Merge branch 'develop' into patch-7
This commit is contained in:
commit
c5739957de
14
.editorconfig
Normal file
14
.editorconfig
Normal file
@ -0,0 +1,14 @@
|
||||
# Root editor config file
|
||||
root = true
|
||||
|
||||
# Common settings
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
# python, js indentation settings
|
||||
[{*.py,*.js}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
24
.eslintrc
24
.eslintrc
@ -5,7 +5,7 @@
|
||||
"es6": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 6,
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module"
|
||||
},
|
||||
"extends": "eslint:recommended",
|
||||
@ -15,6 +15,14 @@
|
||||
"tab",
|
||||
{ "SwitchCase": 1 }
|
||||
],
|
||||
"brace-style": [
|
||||
"error",
|
||||
"1tbs"
|
||||
],
|
||||
"space-unary-ops": [
|
||||
"error",
|
||||
{ "words": true }
|
||||
],
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
"unix"
|
||||
@ -44,12 +52,10 @@
|
||||
"no-control-regex": [
|
||||
"off"
|
||||
],
|
||||
"spaced-comment": [
|
||||
"warn"
|
||||
],
|
||||
"no-trailing-spaces": [
|
||||
"warn"
|
||||
]
|
||||
"space-before-blocks": "warn",
|
||||
"keyword-spacing": "warn",
|
||||
"comma-spacing": "warn",
|
||||
"key-spacing": "warn"
|
||||
},
|
||||
"root": true,
|
||||
"globals": {
|
||||
@ -86,6 +92,7 @@
|
||||
"cur_page": true,
|
||||
"cur_list": true,
|
||||
"cur_tree": true,
|
||||
"cur_pos": true,
|
||||
"msg_dialog": true,
|
||||
"is_null": true,
|
||||
"in_list": true,
|
||||
@ -143,6 +150,7 @@
|
||||
"it": true,
|
||||
"context": true,
|
||||
"before": true,
|
||||
"beforeEach": true
|
||||
"beforeEach": true,
|
||||
"onScan": true
|
||||
}
|
||||
}
|
||||
|
32
.flake8
Normal file
32
.flake8
Normal file
@ -0,0 +1,32 @@
|
||||
[flake8]
|
||||
ignore =
|
||||
E121,
|
||||
E126,
|
||||
E127,
|
||||
E128,
|
||||
E203,
|
||||
E225,
|
||||
E226,
|
||||
E231,
|
||||
E241,
|
||||
E251,
|
||||
E261,
|
||||
E265,
|
||||
E302,
|
||||
E303,
|
||||
E305,
|
||||
E402,
|
||||
E501,
|
||||
E741,
|
||||
W291,
|
||||
W292,
|
||||
W293,
|
||||
W391,
|
||||
W503,
|
||||
W504,
|
||||
F403,
|
||||
B007,
|
||||
B950,
|
||||
W191,
|
||||
|
||||
max-line-length = 200
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Community Forum
|
||||
url: https://discuss.erpnext.com/
|
||||
about: For general QnA, discussions and community help.
|
48
.github/helper/documentation.py
vendored
Normal file
48
.github/helper/documentation.py
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
import sys
|
||||
import requests
|
||||
from urllib.parse import urlparse
|
||||
|
||||
|
||||
docs_repos = [
|
||||
"frappe_docs",
|
||||
"erpnext_documentation",
|
||||
"erpnext_com",
|
||||
"frappe_io",
|
||||
]
|
||||
|
||||
|
||||
def uri_validator(x):
|
||||
result = urlparse(x)
|
||||
return all([result.scheme, result.netloc, result.path])
|
||||
|
||||
def docs_link_exists(body):
|
||||
for line in body.splitlines():
|
||||
for word in line.split():
|
||||
if word.startswith('http') and uri_validator(word):
|
||||
parsed_url = urlparse(word)
|
||||
if parsed_url.netloc == "github.com":
|
||||
parts = parsed_url.path.split('/')
|
||||
if len(parts) == 5 and parts[1] == "frappe" and parts[2] in docs_repos:
|
||||
return True
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pr = sys.argv[1]
|
||||
response = requests.get("https://api.github.com/repos/frappe/erpnext/pulls/{}".format(pr))
|
||||
|
||||
if response.ok:
|
||||
payload = response.json()
|
||||
title = payload.get("title", "").lower()
|
||||
head_sha = payload.get("head", {}).get("sha")
|
||||
body = payload.get("body", "").lower()
|
||||
|
||||
if title.startswith("feat") and head_sha and "no-docs" not in body:
|
||||
if docs_link_exists(body):
|
||||
print("Documentation Link Found. You're Awesome! 🎉")
|
||||
|
||||
else:
|
||||
print("Documentation Link Not Found! ⚠️")
|
||||
sys.exit(1)
|
||||
|
||||
else:
|
||||
print("Skipping documentation checks... 🏃")
|
46
.github/helper/install.sh
vendored
Normal file
46
.github/helper/install.sh
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
cd ~ || exit
|
||||
|
||||
sudo apt-get install redis-server
|
||||
|
||||
sudo apt install nodejs
|
||||
|
||||
sudo apt install npm
|
||||
|
||||
pip install frappe-bench
|
||||
|
||||
git clone https://github.com/frappe/frappe --branch "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}" --depth 1
|
||||
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
|
||||
|
||||
mkdir ~/frappe-bench/sites/test_site
|
||||
cp -r "${GITHUB_WORKSPACE}/.github/helper/site_config.json" ~/frappe-bench/sites/test_site/
|
||||
|
||||
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 -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 -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
||||
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
|
||||
|
||||
wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||
tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||
sudo apt-get install libcups2-dev
|
||||
|
||||
cd ~/frappe-bench || exit
|
||||
|
||||
sed -i 's/watch:/# watch:/g' Procfile
|
||||
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 erpnext "${GITHUB_WORKSPACE}"
|
||||
bench start &
|
||||
bench --site test_site reinstall --yes
|
@ -1,4 +1,6 @@
|
||||
{
|
||||
"db_host": "127.0.0.1",
|
||||
"db_port": 3306,
|
||||
"db_name": "test_frappe",
|
||||
"db_password": "test_frappe",
|
||||
"auto_email_id": "test@example.com",
|
||||
@ -9,5 +11,6 @@
|
||||
"root_login": "root",
|
||||
"root_password": "travis",
|
||||
"host_name": "http://test_site:8000",
|
||||
"install_apps": ["erpnext"]
|
||||
"install_apps": ["erpnext"],
|
||||
"throttle_user_limit": 100
|
||||
}
|
60
.github/helper/translation.py
vendored
Normal file
60
.github/helper/translation.py
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
import re
|
||||
import sys
|
||||
|
||||
errors_encounter = 0
|
||||
pattern = re.compile(r"_\(([\"']{,3})(?P<message>((?!\1).)*)\1(\s*,\s*context\s*=\s*([\"'])(?P<py_context>((?!\5).)*)\5)*(\s*,(\s*?.*?\n*?)*(,\s*([\"'])(?P<js_context>((?!\11).)*)\11)*)*\)")
|
||||
words_pattern = re.compile(r"_{1,2}\([\"'`]{1,3}.*?[a-zA-Z]")
|
||||
start_pattern = re.compile(r"_{1,2}\([f\"'`]{1,3}")
|
||||
f_string_pattern = re.compile(r"_\(f[\"']")
|
||||
starts_with_f_pattern = re.compile(r"_\(f")
|
||||
|
||||
# skip first argument
|
||||
files = sys.argv[1:]
|
||||
files_to_scan = [_file for _file in files if _file.endswith(('.py', '.js'))]
|
||||
|
||||
for _file in files_to_scan:
|
||||
with open(_file, 'r') as f:
|
||||
print(f'Checking: {_file}')
|
||||
file_lines = f.readlines()
|
||||
for line_number, line in enumerate(file_lines, 1):
|
||||
if 'frappe-lint: disable-translate' in line:
|
||||
continue
|
||||
|
||||
start_matches = start_pattern.search(line)
|
||||
if start_matches:
|
||||
starts_with_f = starts_with_f_pattern.search(line)
|
||||
|
||||
if starts_with_f:
|
||||
has_f_string = f_string_pattern.search(line)
|
||||
if has_f_string:
|
||||
errors_encounter += 1
|
||||
print(f'\nF-strings are not supported for translations at line number {line_number}\n{line.strip()[:100]}')
|
||||
continue
|
||||
else:
|
||||
continue
|
||||
|
||||
match = pattern.search(line)
|
||||
error_found = False
|
||||
|
||||
if not match and line.endswith((',\n', '[\n')):
|
||||
# concat remaining text to validate multiline pattern
|
||||
line = "".join(file_lines[line_number - 1:])
|
||||
line = line[start_matches.start() + 1:]
|
||||
match = pattern.match(line)
|
||||
|
||||
if not match:
|
||||
error_found = True
|
||||
print(f'\nTranslation syntax error at line number {line_number}\n{line.strip()[:100]}')
|
||||
|
||||
if not error_found and not words_pattern.search(line):
|
||||
error_found = True
|
||||
print(f'\nTranslation is useless because it has no words at line number {line_number}\n{line.strip()[:100]}')
|
||||
|
||||
if error_found:
|
||||
errors_encounter += 1
|
||||
|
||||
if errors_encounter > 0:
|
||||
print('\nVisit "https://frappeframework.com/docs/user/en/translations" to learn about valid translation strings.')
|
||||
sys.exit(1)
|
||||
else:
|
||||
print('\nGood To Go!')
|
94
.github/workflows/ci-tests.yml
vendored
Normal file
94
.github/workflows/ci-tests.yml
vendored
Normal file
@ -0,0 +1,94 @@
|
||||
name: CI
|
||||
|
||||
on: [pull_request, workflow_dispatch, push]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-18.04
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- TYPE: "server"
|
||||
JOB_NAME: "Server"
|
||||
RUN_COMMAND: cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --coverage
|
||||
- TYPE: "patch"
|
||||
JOB_NAME: "Patch"
|
||||
RUN_COMMAND: cd ~/frappe-bench/ && wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz && bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz && bench --site test_site migrate
|
||||
|
||||
name: ${{ matrix.JOB_NAME }}
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mariadb:10.3
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: YES
|
||||
ports:
|
||||
- 3306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3
|
||||
|
||||
steps:
|
||||
- name: Clone
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Setup Python
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.6
|
||||
|
||||
- name: Add to Hosts
|
||||
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
|
||||
|
||||
- name: Cache pip
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.cache/pip
|
||||
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-pip-
|
||||
${{ runner.os }}-
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v2
|
||||
env:
|
||||
cache-name: cache-node-modules
|
||||
with:
|
||||
path: ~/.npm
|
||||
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-build-${{ env.cache-name }}-
|
||||
${{ runner.os }}-build-
|
||||
${{ runner.os }}-
|
||||
- name: Get yarn cache directory path
|
||||
id: yarn-cache-dir-path
|
||||
run: echo "::set-output name=dir::$(yarn cache dir)"
|
||||
|
||||
- uses: actions/cache@v2
|
||||
id: yarn-cache
|
||||
with:
|
||||
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
|
||||
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-yarn-
|
||||
|
||||
- name: Install
|
||||
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
|
||||
|
||||
- name: Run Tests
|
||||
run: ${{ matrix.RUN_COMMAND }}
|
||||
env:
|
||||
TYPE: ${{ matrix.TYPE }}
|
||||
|
||||
- name: Coverage
|
||||
if: matrix.TYPE == 'server'
|
||||
run: |
|
||||
cp ~/frappe-bench/sites/.coverage ${GITHUB_WORKSPACE}
|
||||
cd ${GITHUB_WORKSPACE}
|
||||
pip install coveralls==2.2.0
|
||||
pip install coverage==4.5.4
|
||||
coveralls
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
COVERALLS_REPO_TOKEN: ${{ secrets.COVERALLS_TOKEN }}
|
||||
|
24
.github/workflows/docs-checker.yml
vendored
Normal file
24
.github/workflows/docs-checker.yml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
name: 'Documentation Required'
|
||||
on:
|
||||
pull_request:
|
||||
types: [ opened, synchronize, reopened, edited ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: 'Setup Environment'
|
||||
uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.6
|
||||
|
||||
- name: 'Clone repo'
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Validate Docs
|
||||
env:
|
||||
PR_NUMBER: ${{ github.event.number }}
|
||||
run: |
|
||||
pip install requests --quiet
|
||||
python $GITHUB_WORKSPACE/.github/helper/documentation.py $PR_NUMBER
|
22
.github/workflows/translation_linter.yml
vendored
Normal file
22
.github/workflows/translation_linter.yml
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
name: Frappe Linter
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- develop
|
||||
- version-12-hotfix
|
||||
- version-11-hotfix
|
||||
jobs:
|
||||
check_translation:
|
||||
name: Translation Syntax Check
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Setup python3
|
||||
uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: 3.6
|
||||
- name: Validating Translation Syntax
|
||||
run: |
|
||||
git fetch origin $GITHUB_BASE_REF:$GITHUB_BASE_REF -q
|
||||
files=$(git diff --name-only --diff-filter=d $GITHUB_BASE_REF)
|
||||
python $GITHUB_WORKSPACE/.github/helper/translation.py $files
|
69
.travis.yml
69
.travis.yml
@ -1,69 +0,0 @@
|
||||
language: python
|
||||
dist: trusty
|
||||
|
||||
git:
|
||||
depth: 1
|
||||
|
||||
cache:
|
||||
- pip
|
||||
|
||||
addons:
|
||||
hosts: test_site
|
||||
mariadb: 10.3
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- name: "Python 3.6 Server Side Test"
|
||||
python: 3.6
|
||||
script: bench --site test_site run-tests --app erpnext --coverage
|
||||
|
||||
- name: "Python 3.6 Patch Test"
|
||||
python: 3.6
|
||||
before_script:
|
||||
- wget http://build.erpnext.com/20171108_190013_955977f8_database.sql.gz
|
||||
- bench --site test_site --force restore ~/frappe-bench/20171108_190013_955977f8_database.sql.gz
|
||||
script: bench --site test_site migrate
|
||||
|
||||
install:
|
||||
- cd ~
|
||||
- nvm install 10
|
||||
|
||||
- pip install frappe-bench
|
||||
|
||||
- git clone https://github.com/frappe/frappe --branch $TRAVIS_BRANCH --depth 1
|
||||
- bench init --skip-assets --frappe-path ~/frappe --python $(which python) frappe-bench
|
||||
|
||||
- mkdir ~/frappe-bench/sites/test_site
|
||||
- cp -r $TRAVIS_BUILD_DIR/.travis/site_config.json ~/frappe-bench/sites/test_site/
|
||||
|
||||
- mysql -u root -e "SET GLOBAL character_set_server = 'utf8mb4'"
|
||||
- mysql -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
|
||||
|
||||
- mysql -u root -e "CREATE DATABASE test_frappe"
|
||||
- mysql -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
|
||||
- mysql -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
|
||||
|
||||
- mysql -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'"
|
||||
- mysql -u root -e "FLUSH PRIVILEGES"
|
||||
|
||||
- wget -O /tmp/wkhtmltox.tar.xz https://github.com/frappe/wkhtmltopdf/raw/master/wkhtmltox-0.12.3_linux-generic-amd64.tar.xz
|
||||
- tar -xf /tmp/wkhtmltox.tar.xz -C /tmp
|
||||
- sudo mv /tmp/wkhtmltox/bin/wkhtmltopdf /usr/local/bin/wkhtmltopdf
|
||||
- sudo chmod o+x /usr/local/bin/wkhtmltopdf
|
||||
- sudo apt-get install libcups2-dev
|
||||
|
||||
- cd ~/frappe-bench
|
||||
|
||||
- sed -i 's/watch:/# watch:/g' Procfile
|
||||
- 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 erpnext $TRAVIS_BUILD_DIR
|
||||
- bench start &
|
||||
- bench --site test_site reinstall --yes
|
||||
|
||||
after_script:
|
||||
- pip install coverage==4.5.4
|
||||
- pip install python-coveralls
|
||||
- coveralls -b apps/erpnext -d ../../sites/.coverage
|
@ -5,7 +5,7 @@
|
||||
<p>ERP made simple</p>
|
||||
</p>
|
||||
|
||||
[](https://travis-ci.com/frappe/erpnext)
|
||||
[](https://github.com/frappe/erpnext/actions/workflows/ci-tests.yml)
|
||||
[](https://www.codetriage.com/frappe/erpnext)
|
||||
[](https://coveralls.io/github/frappe/erpnext?branch=develop)
|
||||
|
||||
|
9
erpnext/.stylelintrc
Normal file
9
erpnext/.stylelintrc
Normal file
@ -0,0 +1,9 @@
|
||||
{
|
||||
"extends": ["stylelint-config-recommended"],
|
||||
"plugins": ["stylelint-scss"],
|
||||
"rules": {
|
||||
"at-rule-no-unknown": null,
|
||||
"scss/at-rule-no-unknown": true,
|
||||
"no-descending-specificity": null
|
||||
}
|
||||
}
|
@ -109,7 +109,7 @@ def get_region(company=None):
|
||||
'''
|
||||
if company or frappe.flags.company:
|
||||
return frappe.get_cached_value('Company',
|
||||
company or frappe.flags.company, 'country')
|
||||
company or frappe.flags.company, 'country')
|
||||
elif frappe.flags.country:
|
||||
return frappe.flags.country
|
||||
else:
|
||||
@ -132,16 +132,10 @@ def allow_regional(fn):
|
||||
|
||||
return caller
|
||||
|
||||
def get_last_membership():
|
||||
def get_last_membership(member):
|
||||
'''Returns last membership if exists'''
|
||||
last_membership = frappe.get_all('Membership', 'name,to_date,membership_type',
|
||||
dict(member=frappe.session.user, paid=1), order_by='to_date desc', limit=1)
|
||||
dict(member=member, paid=1), order_by='to_date desc', limit=1)
|
||||
|
||||
return last_membership and last_membership[0]
|
||||
|
||||
def is_member():
|
||||
'''Returns true if the user is still a member'''
|
||||
last_membership = get_last_membership()
|
||||
if last_membership and getdate(last_membership.to_date) > getdate():
|
||||
return True
|
||||
return False
|
||||
if last_membership:
|
||||
return last_membership[0]
|
||||
|
@ -1,58 +1,126 @@
|
||||
{
|
||||
"custom_fields": [
|
||||
{
|
||||
"_assign": null,
|
||||
"_comments": null,
|
||||
"_liked_by": null,
|
||||
"_user_tags": null,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": null,
|
||||
"columns": 0,
|
||||
"creation": "2018-12-28 22:29:21.828090",
|
||||
"default": null,
|
||||
"depends_on": null,
|
||||
"description": null,
|
||||
"docstatus": 0,
|
||||
"dt": "Address",
|
||||
"fetch_from": null,
|
||||
"fieldname": "tax_category",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"idx": 14,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"insert_after": "fax",
|
||||
"label": "Tax Category",
|
||||
"modified": "2018-12-28 22:29:21.828090",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Address-tax_category",
|
||||
"no_copy": 0,
|
||||
"options": "Tax Category",
|
||||
"owner": "Administrator",
|
||||
"parent": null,
|
||||
"parentfield": null,
|
||||
"parenttype": null,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": null,
|
||||
"read_only": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"_assign": null,
|
||||
"_comments": null,
|
||||
"_liked_by": null,
|
||||
"_user_tags": null,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": null,
|
||||
"columns": 0,
|
||||
"creation": "2018-12-28 22:29:21.828090",
|
||||
"default": null,
|
||||
"depends_on": null,
|
||||
"description": null,
|
||||
"docstatus": 0,
|
||||
"dt": "Address",
|
||||
"fetch_from": null,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "tax_category",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 0,
|
||||
"hide_border": 0,
|
||||
"hide_days": 0,
|
||||
"hide_seconds": 0,
|
||||
"idx": 15,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_preview": 0,
|
||||
"in_standard_filter": 0,
|
||||
"insert_after": "fax",
|
||||
"label": "Tax Category",
|
||||
"length": 0,
|
||||
"mandatory_depends_on": null,
|
||||
"modified": "2018-12-28 22:29:21.828090",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Address-tax_category",
|
||||
"no_copy": 0,
|
||||
"options": "Tax Category",
|
||||
"owner": "Administrator",
|
||||
"parent": null,
|
||||
"parentfield": null,
|
||||
"parenttype": null,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": null,
|
||||
"read_only": 0,
|
||||
"read_only_depends_on": null,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": null
|
||||
},
|
||||
{
|
||||
"_assign": null,
|
||||
"_comments": null,
|
||||
"_liked_by": null,
|
||||
"_user_tags": null,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"collapsible_depends_on": null,
|
||||
"columns": 0,
|
||||
"creation": "2020-10-14 17:41:40.878179",
|
||||
"default": "0",
|
||||
"depends_on": null,
|
||||
"description": null,
|
||||
"docstatus": 0,
|
||||
"dt": "Address",
|
||||
"fetch_from": null,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "is_your_company_address",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 0,
|
||||
"hide_border": 0,
|
||||
"hide_days": 0,
|
||||
"hide_seconds": 0,
|
||||
"idx": 20,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_preview": 0,
|
||||
"in_standard_filter": 0,
|
||||
"insert_after": "linked_with",
|
||||
"label": "Is Your Company Address",
|
||||
"length": 0,
|
||||
"mandatory_depends_on": null,
|
||||
"modified": "2020-10-14 17:41:40.878179",
|
||||
"modified_by": "Administrator",
|
||||
"name": "Address-is_your_company_address",
|
||||
"no_copy": 0,
|
||||
"options": null,
|
||||
"owner": "Administrator",
|
||||
"parent": null,
|
||||
"parentfield": null,
|
||||
"parenttype": null,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"print_width": null,
|
||||
"read_only": 0,
|
||||
"read_only_depends_on": null,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0,
|
||||
"width": null
|
||||
}
|
||||
],
|
||||
"custom_perms": [],
|
||||
"doctype": "Address",
|
||||
"property_setters": [],
|
||||
],
|
||||
"custom_perms": [],
|
||||
"doctype": "Address",
|
||||
"property_setters": [],
|
||||
"sync_on_migrate": 1
|
||||
}
|
42
erpnext/accounts/custom/address.py
Normal file
42
erpnext/accounts/custom/address.py
Normal file
@ -0,0 +1,42 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.contacts.doctype.address.address import Address
|
||||
from frappe.contacts.doctype.address.address import get_address_templates
|
||||
|
||||
class ERPNextAddress(Address):
|
||||
def validate(self):
|
||||
self.validate_reference()
|
||||
super(ERPNextAddress, self).validate()
|
||||
|
||||
def link_address(self):
|
||||
"""Link address based on owner"""
|
||||
if self.is_your_company_address:
|
||||
return
|
||||
|
||||
return super(ERPNextAddress, self).link_address()
|
||||
|
||||
def validate_reference(self):
|
||||
if self.is_your_company_address and not [
|
||||
row for row in self.links if row.link_doctype == "Company"
|
||||
]:
|
||||
frappe.throw(_("Address needs to be linked to a Company. Please add a row for Company in the Links table."),
|
||||
title=_("Company Not Linked"))
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_shipping_address(company, address = None):
|
||||
filters = [
|
||||
["Dynamic Link", "link_doctype", "=", "Company"],
|
||||
["Dynamic Link", "link_name", "=", company],
|
||||
["Address", "is_your_company_address", "=", 1]
|
||||
]
|
||||
fields = ["*"]
|
||||
if address and frappe.db.get_value('Dynamic Link',
|
||||
{'parent': address, 'link_name': company}):
|
||||
filters.append(["Address", "name", "=", address])
|
||||
|
||||
address = frappe.get_all("Address", filters=filters, fields=fields) or {}
|
||||
|
||||
if address:
|
||||
address_as_dict = address[0]
|
||||
name, address_template = get_address_templates(address_as_dict)
|
||||
return address_as_dict.get("name"), frappe.render_template(address_template, address_as_dict)
|
@ -6,9 +6,8 @@ import frappe, json
|
||||
from frappe import _
|
||||
from frappe.utils import add_to_date, date_diff, getdate, nowdate, get_last_day, formatdate, get_link_to_form
|
||||
from erpnext.accounts.report.general_ledger.general_ledger import execute
|
||||
from frappe.utils.dashboard import cache_source, get_from_date_from_timespan
|
||||
from frappe.desk.doctype.dashboard_chart.dashboard_chart import get_period_ending
|
||||
|
||||
from frappe.utils.dashboard import cache_source
|
||||
from frappe.utils.dateutils import get_from_date_from_timespan, get_period_ending
|
||||
from frappe.utils.nestedset import get_descendants_of
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -1,156 +0,0 @@
|
||||
{
|
||||
"cards": [
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Accounting Masters",
|
||||
"links": "[\n {\n \"description\": \"Company (not Customer or Supplier) master.\",\n \"label\": \"Company\",\n \"name\": \"Company\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tree of financial accounts.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Accounts\",\n \"name\": \"Account\",\n \"onboard\": 1,\n \"route\": \"#Tree/Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounts Settings\",\n \"name\": \"Accounts Settings\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Financial / accounting year.\",\n \"label\": \"Fiscal Year\",\n \"name\": \"Fiscal Year\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Finance Book\",\n \"name\": \"Finance Book\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Period\",\n \"name\": \"Accounting Period\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Terms based on conditions\",\n \"label\": \"Payment Term\",\n \"name\": \"Payment Term\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "General Ledger",
|
||||
"links": "[\n {\n \"description\": \"Accounting journal entries.\",\n \"label\": \"Journal Entry\",\n \"name\": \"Journal Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Make journal entries from a template.\",\n \"label\": \"Journal Entry Template\",\n \"name\": \"Journal Entry Template\",\n \"type\": \"doctype\"\n },\n \n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"General Ledger\",\n \"name\": \"General Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Customer Ledger Summary\",\n \"name\": \"Customer Ledger Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Supplier Ledger Summary\",\n \"name\": \"Supplier Ledger Summary\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Accounts Receivable",
|
||||
"links": "[\n {\n \"description\": \"Bills raised to Customers.\",\n \"label\": \"Sales Invoice\",\n \"name\": \"Sales Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Customer database.\",\n \"label\": \"Customer\",\n \"name\": \"Customer\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Payment Request\",\n \"label\": \"Payment Request\",\n \"name\": \"Payment Request\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable\",\n \"name\": \"Accounts Receivable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Receivable Summary\",\n \"name\": \"Accounts Receivable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Register\",\n \"name\": \"Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Sales Register\",\n \"name\": \"Item-wise Sales Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Order\",\n \"is_query_report\": true,\n \"label\": \"Sales Order Analysis\",\n \"name\": \"Sales Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Delivered Items To Be Billed\",\n \"name\": \"Delivered Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Accounts Payable",
|
||||
"links": "[\n {\n \"description\": \"Bills raised by Suppliers.\",\n \"label\": \"Purchase Invoice\",\n \"name\": \"Purchase Invoice\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Supplier database.\",\n \"label\": \"Supplier\",\n \"name\": \"Supplier\",\n \"onboard\": 1,\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Bank/Cash transactions against party or for internal transfer\",\n \"label\": \"Payment Entry\",\n \"name\": \"Payment Entry\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable\",\n \"name\": \"Accounts Payable\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Accounts Payable Summary\",\n \"name\": \"Accounts Payable Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Register\",\n \"name\": \"Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Item-wise Purchase Register\",\n \"name\": \"Item-wise Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Order\"\n ],\n \"doctype\": \"Purchase Order\",\n \"is_query_report\": true,\n \"label\": \"Purchase Order Analysis\",\n \"name\": \"Purchase Order Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Received Items To Be Billed\",\n \"name\": \"Received Items To Be Billed\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Reports",
|
||||
"links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance for Party\",\n \"name\": \"Trial Balance for Party\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Journal Entry\"\n ],\n \"doctype\": \"Journal Entry\",\n \"is_query_report\": true,\n \"label\": \"Payment Period Based On Invoice Date\",\n \"name\": \"Payment Period Based On Invoice Date\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Partners Commission\",\n \"name\": \"Sales Partners Commission\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Customer\"\n ],\n \"doctype\": \"Customer\",\n \"is_query_report\": true,\n \"label\": \"Customer Credit Balance\",\n \"name\": \"Customer Credit Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Payment Summary\",\n \"name\": \"Sales Payment Summary\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Address\"\n ],\n \"doctype\": \"Address\",\n \"is_query_report\": true,\n \"label\": \"Address And Contacts\",\n \"name\": \"Address And Contacts\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Financial Statements",
|
||||
"links": "[\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Trial Balance\",\n \"name\": \"Trial Balance\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profit and Loss Statement\",\n \"name\": \"Profit and Loss Statement\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Balance Sheet\",\n \"name\": \"Balance Sheet\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Cash Flow\",\n \"name\": \"Cash Flow\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Consolidated Financial Statement\",\n \"name\": \"Consolidated Financial Statement\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Multi Currency",
|
||||
"links": "[\n {\n \"description\": \"Enable / disable currencies.\",\n \"label\": \"Currency\",\n \"name\": \"Currency\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Currency exchange rate master.\",\n \"label\": \"Currency Exchange\",\n \"name\": \"Currency Exchange\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Exchange Rate Revaluation master.\",\n \"label\": \"Exchange Rate Revaluation\",\n \"name\": \"Exchange Rate Revaluation\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Settings",
|
||||
"links": "[\n {\n \"description\": \"Setup Gateway accounts.\",\n \"label\": \"Payment Gateway Account\",\n \"name\": \"Payment Gateway Account\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Template of terms or contract.\",\n \"label\": \"Terms and Conditions Template\",\n \"name\": \"Terms and Conditions\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"e.g. Bank, Cash, Credit Card\",\n \"label\": \"Mode of Payment\",\n \"name\": \"Mode of Payment\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Bank Statement",
|
||||
"links": "[\n {\n \"label\": \"Bank\",\n \"name\": \"Bank\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Account\",\n \"name\": \"Bank Account\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Transaction Entry\",\n \"name\": \"Bank Statement Transaction Entry\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Bank Statement Settings\",\n \"name\": \"Bank Statement Settings\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Subscription Management",
|
||||
"links": "[\n {\n \"label\": \"Subscription Plan\",\n \"name\": \"Subscription Plan\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription\",\n \"name\": \"Subscription\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Subscription Settings\",\n \"name\": \"Subscription Settings\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Goods and Services Tax (GST India)",
|
||||
"links": "[\n {\n \"label\": \"GST Settings\",\n \"name\": \"GST Settings\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"GST HSN Code\",\n \"name\": \"GST HSN Code\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-1\",\n \"name\": \"GSTR-1\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GSTR-2\",\n \"name\": \"GSTR-2\",\n \"type\": \"report\"\n },\n {\n \"label\": \"GSTR 3B Report\",\n \"name\": \"GSTR 3B Report\",\n \"type\": \"doctype\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Sales Register\",\n \"name\": \"GST Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Purchase Register\",\n \"name\": \"GST Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Sales Register\",\n \"name\": \"GST Itemised Sales Register\",\n \"type\": \"report\"\n },\n {\n \"is_query_report\": true,\n \"label\": \"GST Itemised Purchase Register\",\n \"name\": \"GST Itemised Purchase Register\",\n \"type\": \"report\"\n },\n {\n \"country\": \"India\",\n \"description\": \"C-Form records\",\n \"label\": \"C-Form\",\n \"name\": \"C-Form\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Share Management",
|
||||
"links": "[\n {\n \"description\": \"List of available Shareholders with folio numbers\",\n \"label\": \"Shareholder\",\n \"name\": \"Shareholder\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"List of all share transactions\",\n \"label\": \"Share Transfer\",\n \"name\": \"Share Transfer\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Ledger\",\n \"name\": \"Share Ledger\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Share Transfer\"\n ],\n \"doctype\": \"Share Transfer\",\n \"is_query_report\": true,\n \"label\": \"Share Balance\",\n \"name\": \"Share Balance\",\n \"type\": \"report\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Cost Center and Budgeting",
|
||||
"links": "[\n {\n \"description\": \"Tree of financial Cost Centers.\",\n \"icon\": \"fa fa-sitemap\",\n \"label\": \"Chart of Cost Centers\",\n \"name\": \"Cost Center\",\n \"route\": \"#Tree/Cost Center\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Define budget for a financial year.\",\n \"label\": \"Budget\",\n \"name\": \"Budget\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Accounting Dimension\",\n \"name\": \"Accounting Dimension\",\n \"type\": \"doctype\"\n },\n {\n \"dependencies\": [\n \"Cost Center\"\n ],\n \"doctype\": \"Cost Center\",\n \"is_query_report\": true,\n \"label\": \"Budget Variance Report\",\n \"name\": \"Budget Variance Report\",\n \"type\": \"report\"\n },\n {\n \"description\": \"Seasonality for setting budgets, targets etc.\",\n \"label\": \"Monthly Distribution\",\n \"name\": \"Monthly Distribution\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Opening and Closing",
|
||||
"links": "[\n {\n \"label\": \"Opening Invoice Creation Tool\",\n \"name\": \"Opening Invoice Creation Tool\",\n \"type\": \"doctype\"\n },\n {\n \"label\": \"Chart of Accounts Importer\",\n \"name\": \"Chart of Accounts Importer\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Close Balance Sheet and book Profit or Loss.\",\n \"label\": \"Period Closing Voucher\",\n \"name\": \"Period Closing Voucher\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Taxes",
|
||||
"links": "[\n {\n \"description\": \"Tax template for selling transactions.\",\n \"label\": \"Sales Taxes and Charges Template\",\n \"name\": \"Sales Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for buying transactions.\",\n \"label\": \"Purchase Taxes and Charges Template\",\n \"name\": \"Purchase Taxes and Charges Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax template for item tax rates.\",\n \"label\": \"Item Tax Template\",\n \"name\": \"Item Tax Template\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Category for overriding tax rates.\",\n \"label\": \"Tax Category\",\n \"name\": \"Tax Category\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Rule for transactions.\",\n \"label\": \"Tax Rule\",\n \"name\": \"Tax Rule\",\n \"type\": \"doctype\"\n },\n {\n \"description\": \"Tax Withholding rates to be applied on transactions.\",\n \"label\": \"Tax Withholding Category\",\n \"name\": \"Tax Withholding Category\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
"label": "Profitability",
|
||||
"links": "[\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Gross Profit\",\n \"name\": \"Gross Profit\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"GL Entry\"\n ],\n \"doctype\": \"GL Entry\",\n \"is_query_report\": true,\n \"label\": \"Profitability Analysis\",\n \"name\": \"Profitability Analysis\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Sales Invoice\"\n ],\n \"doctype\": \"Sales Invoice\",\n \"is_query_report\": true,\n \"label\": \"Sales Invoice Trends\",\n \"name\": \"Sales Invoice Trends\",\n \"type\": \"report\"\n },\n {\n \"dependencies\": [\n \"Purchase Invoice\"\n ],\n \"doctype\": \"Purchase Invoice\",\n \"is_query_report\": true,\n \"label\": \"Purchase Invoice Trends\",\n \"name\": \"Purchase Invoice Trends\",\n \"type\": \"report\"\n }\n]"
|
||||
}
|
||||
],
|
||||
"category": "Modules",
|
||||
"charts": [
|
||||
{
|
||||
"chart_name": "Profit and Loss",
|
||||
"label": "Profit and Loss"
|
||||
}
|
||||
],
|
||||
"creation": "2020-03-02 15:41:59.515192",
|
||||
"developer_mode_only": 0,
|
||||
"disable_user_customization": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Desk Page",
|
||||
"extends_another_page": 0,
|
||||
"hide_custom": 0,
|
||||
"idx": 0,
|
||||
"is_standard": 1,
|
||||
"label": "Accounting",
|
||||
"modified": "2020-09-09 11:45:33.766400",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting",
|
||||
"onboarding": "Accounts",
|
||||
"owner": "Administrator",
|
||||
"pin_to_bottom": 0,
|
||||
"pin_to_top": 0,
|
||||
"shortcuts": [
|
||||
{
|
||||
"label": "Chart Of Accounts",
|
||||
"link_to": "Account",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Sales Invoice",
|
||||
"link_to": "Sales Invoice",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Purchase Invoice",
|
||||
"link_to": "Purchase Invoice",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Journal Entry",
|
||||
"link_to": "Journal Entry",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Payment Entry",
|
||||
"link_to": "Payment Entry",
|
||||
"type": "DocType"
|
||||
},
|
||||
{
|
||||
"label": "Accounts Receivable",
|
||||
"link_to": "Accounts Receivable",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "General Ledger",
|
||||
"link_to": "General Ledger",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Trial Balance",
|
||||
"link_to": "Trial Balance",
|
||||
"type": "Report"
|
||||
},
|
||||
{
|
||||
"label": "Dashboard",
|
||||
"link_to": "Accounts",
|
||||
"type": "Dashboard"
|
||||
}
|
||||
]
|
||||
}
|
@ -101,7 +101,7 @@ class Account(NestedSet):
|
||||
return
|
||||
if not frappe.db.get_value("Account",
|
||||
{'account_name': self.account_name, 'company': ancestors[0]}, 'name'):
|
||||
frappe.throw(_("Please add the account to root level Company - %s" % ancestors[0]))
|
||||
frappe.throw(_("Please add the account to root level Company - {}").format(ancestors[0]))
|
||||
elif self.parent_account:
|
||||
descendants = get_descendants_of('Company', self.company)
|
||||
if not descendants: return
|
||||
@ -164,9 +164,19 @@ class Account(NestedSet):
|
||||
|
||||
def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name):
|
||||
for company in descendants:
|
||||
company_bold = frappe.bold(company)
|
||||
parent_acc_name_bold = frappe.bold(parent_acc_name)
|
||||
if not parent_acc_name_map.get(company):
|
||||
frappe.throw(_("While creating account for child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company, parent_acc_name))
|
||||
frappe.throw(_("While creating account for Child Company {0}, parent account {1} not found. Please create the parent account in corresponding COA")
|
||||
.format(company_bold, parent_acc_name_bold), title=_("Account Not Found"))
|
||||
|
||||
# validate if parent of child company account to be added is a 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)
|
||||
msg += "<br><br>"
|
||||
msg += _("Please convert the parent account in corresponding child company to a group account.")
|
||||
frappe.throw(msg, title=_("Invalid Parent Account"))
|
||||
|
||||
filters = {
|
||||
"account_name": self.account_name,
|
||||
@ -309,8 +319,9 @@ def update_account_number(name, account_name, account_number=None, from_descenda
|
||||
allow_child_account_creation = _("Allow Account Creation Against Child Company")
|
||||
|
||||
message = _("Account {0} exists in parent company {1}.").format(frappe.bold(old_acc_name), frappe.bold(ancestor))
|
||||
message += "<br>" + _("Renaming it is only allowed via parent company {0}, \
|
||||
to avoid mismatch.").format(frappe.bold(ancestor)) + "<br><br>"
|
||||
message += "<br>"
|
||||
message += _("Renaming it is only allowed via parent company {0}, to avoid mismatch.").format(frappe.bold(ancestor))
|
||||
message += "<br><br>"
|
||||
message += _("To overrule this, enable '{0}' in company {1}").format(allow_child_account_creation, frappe.bold(account.company))
|
||||
|
||||
frappe.throw(message, title=_("Rename Not Allowed"))
|
||||
|
@ -2,7 +2,7 @@ frappe.provide("frappe.treeview_settings")
|
||||
|
||||
frappe.treeview_settings["Account"] = {
|
||||
breadcrumb: "Accounts",
|
||||
title: __("Chart Of Accounts"),
|
||||
title: __("Chart of Accounts"),
|
||||
get_tree_root: false,
|
||||
filters: [
|
||||
{
|
||||
@ -97,7 +97,7 @@ frappe.treeview_settings["Account"] = {
|
||||
treeview.page.add_inner_button(__("Journal Entry"), function() {
|
||||
frappe.new_doc('Journal Entry', {company: get_company()});
|
||||
}, __('Create'));
|
||||
treeview.page.add_inner_button(__("New Company"), function() {
|
||||
treeview.page.add_inner_button(__("Company"), function() {
|
||||
frappe.new_doc('Company');
|
||||
}, __('Create'));
|
||||
|
||||
@ -120,17 +120,17 @@ frappe.treeview_settings["Account"] = {
|
||||
} else {
|
||||
treeview.new_node();
|
||||
}
|
||||
}, "octicon octicon-plus");
|
||||
}, "add");
|
||||
},
|
||||
onrender: function(node) {
|
||||
if(frappe.boot.user.can_read.indexOf("GL Entry") !== -1){
|
||||
if (frappe.boot.user.can_read.indexOf("GL Entry") !== -1) {
|
||||
|
||||
// show Dr if positive since balance is calculated as debit - credit else show Cr
|
||||
let balance = node.data.balance_in_account_currency || node.data.balance;
|
||||
let dr_or_cr = balance > 0 ? "Dr": "Cr";
|
||||
|
||||
if (node.data && node.data.balance!==undefined) {
|
||||
$('<span class="balance-area pull-right text-muted small">'
|
||||
$('<span class="balance-area pull-right">'
|
||||
+ (node.data.balance_in_account_currency ?
|
||||
(format_currency(Math.abs(node.data.balance_in_account_currency),
|
||||
node.data.account_currency) + " / ") : "")
|
||||
|
@ -63,17 +63,21 @@
|
||||
"Gewinnermittlung \u00a74/3 nicht Ergebniswirksam": {
|
||||
"account_number": "1371"
|
||||
},
|
||||
"Abziehbare VSt. 7%": {
|
||||
"account_number": "1571"
|
||||
},
|
||||
"Abziehbare VSt. 19%": {
|
||||
"account_number": "1576"
|
||||
},
|
||||
"Abziehbare VStr. nach \u00a713b UStG 19%": {
|
||||
"account_number": "1577"
|
||||
},
|
||||
"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
|
||||
"account_number": "3120"
|
||||
"Abziehbare Vorsteuer": {
|
||||
"account_type": "Tax",
|
||||
"is_group": 1,
|
||||
"Abziehbare Vorsteuer 7%": {
|
||||
"account_number": "1571"
|
||||
},
|
||||
"Abziehbare Vorsteuer 19%": {
|
||||
"account_number": "1576"
|
||||
},
|
||||
"Abziehbare Vorsteuer nach \u00a713b UStG 19%": {
|
||||
"account_number": "1577"
|
||||
},
|
||||
"Leistungen \u00a713b UStG 19% Vorsteuer, 19% Umsatzsteuer": {
|
||||
"account_number": "3120"
|
||||
}
|
||||
}
|
||||
},
|
||||
"III. Wertpapiere": {
|
||||
@ -196,6 +200,7 @@
|
||||
},
|
||||
"Umsatzsteuer": {
|
||||
"is_group": 1,
|
||||
"account_type": "Tax",
|
||||
"Umsatzsteuer 7%": {
|
||||
"account_number": "1771"
|
||||
},
|
||||
|
@ -292,18 +292,21 @@
|
||||
"Umsatzsteuerforderungen fr\u00fchere Jahre": {}
|
||||
},
|
||||
"Sonstige Verm\u00f6gensgegenst\u00e4nde oder sonstige Verbindlichkeiten": {
|
||||
"Abziehbare Vorsteuer": {},
|
||||
"Abziehbare Vorsteuer 16%": {},
|
||||
"Abziehbare Vorsteuer 19%": {},
|
||||
"Abziehbare Vorsteuer 7%": {},
|
||||
"Abziehbare Vorsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Unsatzsteuerlager": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 16%": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb von Neufahrzeugen von Lieferanten ohne Ust-Identifikationsnummer": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG ": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG 16%": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG 19%": {},
|
||||
"Abziehbare Vorsteuer": {
|
||||
"account_type": "Tax",
|
||||
"is_group": 1,
|
||||
"Abziehbare Vorsteuer 16%": {},
|
||||
"Abziehbare Vorsteuer 19%": {},
|
||||
"Abziehbare Vorsteuer 7%": {},
|
||||
"Abziehbare Vorsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Unsatzsteuerlager": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 16%": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb 19%": {},
|
||||
"Abziehbare Vorsteuer aus innergemeinschaftlichem Erwerb von Neufahrzeugen von Lieferanten ohne Ust-Identifikationsnummer": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG ": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG 16%": {},
|
||||
"Abziehbare Vorsteuer nach \u00a7 13b UStG 19%": {}
|
||||
},
|
||||
"Aufl\u00f6sung Vorsteuer aus Vorjahr \u00a7 4/3 EStG": {},
|
||||
"Aufzuteilende Vorsteuer": {},
|
||||
"Aufzuteilende Vorsteuer 16%": {},
|
||||
@ -673,23 +676,26 @@
|
||||
"Sonstige Verrechnungskonten (Interimskonto)": {
|
||||
"account_type": "Stock Received But Not Billed"
|
||||
},
|
||||
"Umsatzsteuer": {},
|
||||
"Umsatzsteuer 16%": {},
|
||||
"Umsatzsteuer 19%": {},
|
||||
"Umsatzsteuer 7%": {},
|
||||
"Umsatzsteuer Vorjahr": {},
|
||||
"Umsatzsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Umsatzsteuerlager": {},
|
||||
"Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen": {},
|
||||
"Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen 19%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb ": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb 16%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb 19%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb ohne Vorsteuerabzug": {},
|
||||
"Umsatzsteuer fr\u00fchere Jahre": {},
|
||||
"Umsatzsteuer laufendes Jahr": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG 16%": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG 19%": {},
|
||||
"Umsatzsteuer": {
|
||||
"account_type": "Tax",
|
||||
"is_group": 1,
|
||||
"Umsatzsteuer 16%": {},
|
||||
"Umsatzsteuer 19%": {},
|
||||
"Umsatzsteuer 7%": {},
|
||||
"Umsatzsteuer Vorjahr": {},
|
||||
"Umsatzsteuer aus der Auslagerung von Gegenst\u00e4nden aus einem Umsatzsteuerlager": {},
|
||||
"Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen": {},
|
||||
"Umsatzsteuer aus im Inland steuerpflichtigen EG-Lieferungen 19%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb ": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb 16%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb 19%": {},
|
||||
"Umsatzsteuer aus innergemeinschaftlichem Erwerb ohne Vorsteuerabzug": {},
|
||||
"Umsatzsteuer fr\u00fchere Jahre": {},
|
||||
"Umsatzsteuer laufendes Jahr": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG 16%": {},
|
||||
"Umsatzsteuer nach \u00a713b UStG 19%": {}
|
||||
},
|
||||
"Umsatzsteuer- Vorauszahlungen": {},
|
||||
"Umsatzsteuer- Vorauszahlungen 1/11": {},
|
||||
"Verbindlichkeiten aus Lohn- und Kirchensteuer": {}
|
||||
|
@ -659,6 +659,7 @@
|
||||
},
|
||||
"Abziehbare Vorsteuer (Gruppe)": {
|
||||
"is_group": 1,
|
||||
"account_type": "Tax",
|
||||
"Abziehbare Vorsteuer": {
|
||||
"account_number": "1400"
|
||||
},
|
||||
@ -910,98 +911,8 @@
|
||||
},
|
||||
"is_group": 1
|
||||
},
|
||||
"Passiva": {
|
||||
"Passiva - Verbindlichkeiten": {
|
||||
"root_type": "Liability",
|
||||
"A - Eigenkapital": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"I - Gezeichnetes Kapital": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gezeichnetes Kapital": {
|
||||
"account_type": "Equity",
|
||||
"account_number": "2900"
|
||||
},
|
||||
"Ausstehende Einlagen auf das gezeichnete Kapital": {
|
||||
"account_number": "2910",
|
||||
"is_group": 1
|
||||
}
|
||||
},
|
||||
"II - Kapitalr\u00fccklage": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Kapitalr\u00fccklage": {
|
||||
"account_number": "2920"
|
||||
}
|
||||
},
|
||||
"III - Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"1 - gesetzliche R\u00fccklage": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gesetzliche R\u00fccklage": {
|
||||
"account_number": "2930"
|
||||
}
|
||||
},
|
||||
"2 - R\u00fccklage f. Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1
|
||||
},
|
||||
"3 - satzungsm\u00e4\u00dfige R\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Satzungsm\u00e4\u00dfige R\u00fccklagen": {
|
||||
"account_number": "2950"
|
||||
}
|
||||
},
|
||||
"4 - andere Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gewinnr\u00fccklagen aus den \u00dcbergangsvorschriften BilMoG": {
|
||||
"is_group": 1,
|
||||
"Gewinnr\u00fccklagen (BilMoG)": {
|
||||
"account_number": "2963"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Zuschreibung Sachanlageverm\u00f6gen (BilMoG)": {
|
||||
"account_number": "2964"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Zuschreibung Finanzanlageverm\u00f6gen (BilMoG)": {
|
||||
"account_number": "2965"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Aufl\u00f6sung der Sonderposten mit R\u00fccklageanteil (BilMoG)": {
|
||||
"account_number": "2966"
|
||||
}
|
||||
},
|
||||
"Latente Steuern (Gewinnr\u00fccklage Haben) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2967"
|
||||
},
|
||||
"Latente Steuern (Gewinnr\u00fccklage Soll) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2968"
|
||||
},
|
||||
"Rechnungsabgrenzungsposten (Gewinnr\u00fccklage Soll) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2969"
|
||||
}
|
||||
},
|
||||
"is_group": 1
|
||||
},
|
||||
"IV - Gewinnvortrag/Verlustvortrag": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gewinnvortrag vor Verwendung": {
|
||||
"account_number": "2970"
|
||||
},
|
||||
"Verlustvortrag vor Verwendung": {
|
||||
"account_number": "2978"
|
||||
}
|
||||
},
|
||||
"V - Jahres\u00fcberschu\u00df/Jahresfehlbetrag": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1
|
||||
},
|
||||
"Einlagen stiller Gesellschafter": {
|
||||
"account_number": "9295"
|
||||
}
|
||||
},
|
||||
"B - R\u00fcckstellungen": {
|
||||
"is_group": 1,
|
||||
"1 - R\u00fcckstellungen f. Pensionen und \u00e4hnliche Verplicht.": {
|
||||
@ -1618,6 +1529,143 @@
|
||||
},
|
||||
"is_group": 1
|
||||
},
|
||||
"Passiva - Eigenkapital": {
|
||||
"root_type": "Equity",
|
||||
"A - Eigenkapital": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"I - Gezeichnetes Kapital": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gezeichnetes Kapital": {
|
||||
"account_number": "2900",
|
||||
"account_type": "Equity"
|
||||
},
|
||||
"Gesch\u00e4ftsguthaben der verbleibenden Mitglieder": {
|
||||
"account_number": "2901"
|
||||
},
|
||||
"Gesch\u00e4ftsguthaben der ausscheidenden Mitglieder": {
|
||||
"account_number": "2902"
|
||||
},
|
||||
"Gesch\u00e4ftsguthaben aus gek\u00fcndigten Gesch\u00e4ftsanteilen": {
|
||||
"account_number": "2903"
|
||||
},
|
||||
"R\u00fcckst\u00e4ndige f\u00e4llige Einzahlungen auf Gesch\u00e4ftsanteile, vermerkt": {
|
||||
"account_number": "2906"
|
||||
},
|
||||
"Gegenkonto R\u00fcckst\u00e4ndige f\u00e4llige Einzahlungen auf Gesch\u00e4ftsanteile, vermerkt": {
|
||||
"account_number": "2907"
|
||||
},
|
||||
"Kapitalerh\u00f6hung aus Gesellschaftsmitteln": {
|
||||
"account_number": "2908"
|
||||
},
|
||||
"Ausstehende Einlagen auf das gezeichnete Kapital, nicht eingefordert": {
|
||||
"account_number": "2910"
|
||||
}
|
||||
},
|
||||
"II - Kapitalr\u00fccklage": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Kapitalr\u00fccklage": {
|
||||
"account_number": "2920"
|
||||
},
|
||||
"Kapitalr\u00fccklage durch Ausgabe von Anteilen \u00fcber Nennbetrag": {
|
||||
"account_number": "2925"
|
||||
},
|
||||
"Kapitalr\u00fccklage durch Ausgabe von Schuldverschreibungen": {
|
||||
"account_number": "2926"
|
||||
},
|
||||
"Kapitalr\u00fccklage durch Zuzahlungen gegen Gew\u00e4hrung eines Vorzugs": {
|
||||
"account_number": "2927"
|
||||
},
|
||||
"Kapitalr\u00fccklage durch Zuzahlungen in das Eigenkapital": {
|
||||
"account_number": "2928"
|
||||
},
|
||||
"Nachschusskapital (Gegenkonto 1299)": {
|
||||
"account_number": "2929"
|
||||
}
|
||||
},
|
||||
"III - Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"1 - gesetzliche R\u00fccklage": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gesetzliche R\u00fccklage": {
|
||||
"account_number": "2930"
|
||||
}
|
||||
},
|
||||
"2 - R\u00fccklage f. Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"R\u00fccklage f. Anteile an einem herrschenden oder mehrheitlich beteiligten Unternehmen": {
|
||||
"account_number": "2935"
|
||||
}
|
||||
},
|
||||
"3 - satzungsm\u00e4\u00dfige R\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Satzungsm\u00e4\u00dfige R\u00fccklagen": {
|
||||
"account_number": "2950"
|
||||
}
|
||||
},
|
||||
"4 - andere Gewinnr\u00fccklagen": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Andere Gewinnr\u00fccklagen": {
|
||||
"account_number": "2960"
|
||||
},
|
||||
"Andere Gewinnr\u00fccklagen aus dem Erwerb eigener Anteile": {
|
||||
"account_number": "2961"
|
||||
},
|
||||
"Eigenkapitalanteil von Wertaufholungen": {
|
||||
"account_number": "2962"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus den \u00dcbergangsvorschriften BilMoG": {
|
||||
"is_group": 1,
|
||||
"Gewinnr\u00fccklagen (BilMoG)": {
|
||||
"account_number": "2963"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Zuschreibung Sachanlageverm\u00f6gen (BilMoG)": {
|
||||
"account_number": "2964"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Zuschreibung Finanzanlageverm\u00f6gen (BilMoG)": {
|
||||
"account_number": "2965"
|
||||
},
|
||||
"Gewinnr\u00fccklagen aus Aufl\u00f6sung der Sonderposten mit R\u00fccklageanteil (BilMoG)": {
|
||||
"account_number": "2966"
|
||||
}
|
||||
},
|
||||
"Latente Steuern (Gewinnr\u00fccklage Haben) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2967"
|
||||
},
|
||||
"Latente Steuern (Gewinnr\u00fccklage Soll) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2968"
|
||||
},
|
||||
"Rechnungsabgrenzungsposten (Gewinnr\u00fccklage Soll) aus erfolgsneutralen Verrechnungen": {
|
||||
"account_number": "2969"
|
||||
}
|
||||
},
|
||||
"is_group": 1
|
||||
},
|
||||
"IV - Gewinnvortrag/Verlustvortrag": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1,
|
||||
"Gewinnvortrag vor Verwendung": {
|
||||
"account_number": "2970"
|
||||
},
|
||||
"Verlustvortrag vor Verwendung": {
|
||||
"account_number": "2978"
|
||||
}
|
||||
},
|
||||
"V - Jahres\u00fcberschu\u00df/Jahresfehlbetrag": {
|
||||
"account_type": "Equity",
|
||||
"is_group": 1
|
||||
},
|
||||
"Einlagen stiller Gesellschafter": {
|
||||
"account_number": "9295"
|
||||
}
|
||||
}
|
||||
},
|
||||
"1 - Umsatzerl\u00f6se": {
|
||||
"root_type": "Income",
|
||||
"is_group": 1,
|
||||
|
@ -245,6 +245,9 @@ def get():
|
||||
"account_number": "2200"
|
||||
},
|
||||
_("Duties and Taxes"): {
|
||||
_("TDS Payable"): {
|
||||
"account_number": "2310"
|
||||
},
|
||||
"account_type": "Tax",
|
||||
"is_group": 1,
|
||||
"account_number": "2300"
|
||||
|
@ -111,6 +111,17 @@ class TestAccount(unittest.TestCase):
|
||||
self.assertEqual(acc_tc_4, "Test Sync Account - _TC4")
|
||||
self.assertEqual(acc_tc_5, "Test Sync Account - _TC5")
|
||||
|
||||
def test_add_account_to_a_group(self):
|
||||
frappe.db.set_value("Account", "Office Rent - _TC3", "is_group", 1)
|
||||
|
||||
acc = frappe.new_doc("Account")
|
||||
acc.account_name = "Test Group Account"
|
||||
acc.parent_account = "Office Rent - _TC3"
|
||||
acc.company = "_Test Company 3"
|
||||
self.assertRaises(frappe.ValidationError, acc.insert)
|
||||
|
||||
frappe.db.set_value("Account", "Office Rent - _TC3", "is_group", 0)
|
||||
|
||||
def test_account_rename_sync(self):
|
||||
frappe.local.flags.pop("ignore_root_company_validation", None)
|
||||
|
||||
@ -160,7 +171,8 @@ class TestAccount(unittest.TestCase):
|
||||
for doc in to_delete:
|
||||
frappe.delete_doc("Account", doc)
|
||||
|
||||
def _make_test_records(verbose):
|
||||
|
||||
def _make_test_records(verbose=None):
|
||||
from frappe.test_runner import make_test_objects
|
||||
|
||||
accounts = [
|
||||
@ -242,7 +254,8 @@ def create_account(**kwargs):
|
||||
account_name = kwargs.get('account_name'),
|
||||
account_type = kwargs.get('account_type'),
|
||||
parent_account = kwargs.get('parent_account'),
|
||||
company = kwargs.get('company')
|
||||
company = kwargs.get('company'),
|
||||
account_currency = kwargs.get('account_currency')
|
||||
))
|
||||
|
||||
account.save()
|
||||
|
@ -2,12 +2,11 @@
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension', {
|
||||
|
||||
refresh: function(frm) {
|
||||
frm.set_query('document_type', () => {
|
||||
let invalid_doctypes = frappe.model.core_doctypes_list;
|
||||
invalid_doctypes.push('Accounting Dimension', 'Project',
|
||||
'Cost Center', 'Accounting Dimension Detail');
|
||||
'Cost Center', 'Accounting Dimension Detail', 'Company');
|
||||
|
||||
return {
|
||||
filters: {
|
||||
|
@ -30,6 +30,7 @@
|
||||
"fieldtype": "Link",
|
||||
"label": "Reference Document Type",
|
||||
"options": "DocType",
|
||||
"read_only_depends_on": "eval:!doc.__islocal",
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
@ -48,7 +49,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-03-22 20:34:39.805728",
|
||||
"modified": "2021-02-08 16:37:53.936656",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension",
|
||||
|
@ -19,7 +19,7 @@ class AccountingDimension(Document):
|
||||
|
||||
def validate(self):
|
||||
if self.document_type in core_doctypes_list + ('Accounting Dimension', 'Project',
|
||||
'Cost Center', 'Accounting Dimension Detail') :
|
||||
'Cost Center', 'Accounting Dimension Detail', 'Company') :
|
||||
|
||||
msg = _("Not allowed to create accounting dimension for {0}").format(self.document_type)
|
||||
frappe.throw(msg)
|
||||
@ -29,15 +29,25 @@ class AccountingDimension(Document):
|
||||
if exists and self.is_new():
|
||||
frappe.throw("Document Type already used as a dimension")
|
||||
|
||||
if not self.is_new():
|
||||
self.validate_document_type_change()
|
||||
|
||||
def validate_document_type_change(self):
|
||||
doctype_before_save = frappe.db.get_value("Accounting Dimension", self.name, "document_type")
|
||||
if doctype_before_save != self.document_type:
|
||||
message = _("Cannot change Reference Document Type.")
|
||||
message += _("Please create a new Accounting Dimension if required.")
|
||||
frappe.throw(message)
|
||||
|
||||
def after_insert(self):
|
||||
if frappe.flags.in_test:
|
||||
make_dimension_in_accounting_doctypes(doc=self)
|
||||
else:
|
||||
frappe.enqueue(make_dimension_in_accounting_doctypes, doc=self)
|
||||
frappe.enqueue(make_dimension_in_accounting_doctypes, doc=self, queue='long')
|
||||
|
||||
def on_trash(self):
|
||||
if frappe.flags.in_test:
|
||||
delete_accounting_dimension(doc=self)
|
||||
delete_accounting_dimension(doc=self, queue='long')
|
||||
else:
|
||||
frappe.enqueue(delete_accounting_dimension, doc=self)
|
||||
|
||||
@ -48,8 +58,13 @@ class AccountingDimension(Document):
|
||||
if not self.fieldname:
|
||||
self.fieldname = scrub(self.label)
|
||||
|
||||
def make_dimension_in_accounting_doctypes(doc):
|
||||
doclist = get_doctypes_with_dimensions()
|
||||
def on_update(self):
|
||||
frappe.flags.accounting_dimensions = None
|
||||
|
||||
def make_dimension_in_accounting_doctypes(doc, doclist=None):
|
||||
if not doclist:
|
||||
doclist = get_doctypes_with_dimensions()
|
||||
|
||||
doc_count = len(get_accounting_dimensions())
|
||||
count = 0
|
||||
|
||||
@ -69,13 +84,13 @@ def make_dimension_in_accounting_doctypes(doc):
|
||||
"owner": "Administrator"
|
||||
}
|
||||
|
||||
if doctype == "Budget":
|
||||
add_dimension_to_budget_doctype(df, doc)
|
||||
else:
|
||||
meta = frappe.get_meta(doctype, cached=False)
|
||||
fieldnames = [d.fieldname for d in meta.get("fields")]
|
||||
meta = frappe.get_meta(doctype, cached=False)
|
||||
fieldnames = [d.fieldname for d in meta.get("fields")]
|
||||
|
||||
if df['fieldname'] not in fieldnames:
|
||||
if df['fieldname'] not in fieldnames:
|
||||
if doctype == "Budget":
|
||||
add_dimension_to_budget_doctype(df.copy(), doc)
|
||||
else:
|
||||
create_custom_field(doctype, df)
|
||||
|
||||
count += 1
|
||||
@ -165,23 +180,17 @@ def toggle_disabling(doc):
|
||||
frappe.clear_cache(doctype=doctype)
|
||||
|
||||
def get_doctypes_with_dimensions():
|
||||
doclist = ["GL Entry", "Sales Invoice", "Purchase Invoice", "Payment Entry", "Asset",
|
||||
"Expense Claim", "Expense Claim Detail", "Expense Taxes and Charges", "Stock Entry", "Budget", "Payroll Entry", "Delivery Note",
|
||||
"Sales Invoice Item", "Purchase Invoice Item", "Purchase Order Item", "Journal Entry Account", "Material Request Item", "Delivery Note Item",
|
||||
"Purchase Receipt Item", "Stock Entry Detail", "Payment Entry Deduction", "Sales Taxes and Charges", "Purchase Taxes and Charges", "Shipping Rule",
|
||||
"Landed Cost Item", "Asset Value Adjustment", "Loyalty Program", "Fee Schedule", "Fee Structure", "Stock Reconciliation",
|
||||
"Travel Request", "Fees", "POS Profile", "Opening Invoice Creation Tool", "Opening Invoice Creation Tool Item", "Subscription",
|
||||
"Subscription Plan"]
|
||||
|
||||
return doclist
|
||||
return frappe.get_hooks("accounting_dimension_doctypes")
|
||||
|
||||
def get_accounting_dimensions(as_list=True):
|
||||
accounting_dimensions = frappe.get_all("Accounting Dimension", fields=["label", "fieldname", "disabled", "document_type"])
|
||||
if frappe.flags.accounting_dimensions is None:
|
||||
frappe.flags.accounting_dimensions = frappe.get_all("Accounting Dimension",
|
||||
fields=["label", "fieldname", "disabled", "document_type"])
|
||||
|
||||
if as_list:
|
||||
return [d.fieldname for d in accounting_dimensions]
|
||||
return [d.fieldname for d in frappe.flags.accounting_dimensions]
|
||||
else:
|
||||
return accounting_dimensions
|
||||
return frappe.flags.accounting_dimensions
|
||||
|
||||
def get_checks_for_pl_and_bs_accounts():
|
||||
dimensions = frappe.db.sql("""SELECT p.label, p.disabled, p.fieldname, c.default_dimension, c.company, c.mandatory_for_pl, c.mandatory_for_bs
|
||||
@ -203,7 +212,7 @@ def get_dimension_with_children(doctype, dimension):
|
||||
return all_dimensions
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_dimension_filters():
|
||||
def get_dimensions(with_cost_center_and_project=False):
|
||||
dimension_filters = frappe.db.sql("""
|
||||
SELECT label, fieldname, document_type
|
||||
FROM `tabAccounting Dimension`
|
||||
@ -214,6 +223,18 @@ def get_dimension_filters():
|
||||
FROM `tabAccounting Dimension Detail` c, `tabAccounting Dimension` p
|
||||
WHERE c.parent = p.name""", as_dict=1)
|
||||
|
||||
if with_cost_center_and_project:
|
||||
dimension_filters.extend([
|
||||
{
|
||||
'fieldname': 'cost_center',
|
||||
'document_type': 'Cost Center'
|
||||
},
|
||||
{
|
||||
'fieldname': 'project',
|
||||
'document_type': 'Project'
|
||||
}
|
||||
])
|
||||
|
||||
default_dimensions_map = {}
|
||||
for dimension in default_dimensions:
|
||||
default_dimensions_map.setdefault(dimension.company, {})
|
||||
|
@ -11,37 +11,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import d
|
||||
|
||||
class TestAccountingDimension(unittest.TestCase):
|
||||
def setUp(self):
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
|
||||
dimension = frappe.get_doc({
|
||||
"doctype": "Accounting Dimension",
|
||||
"document_type": "Department",
|
||||
}).insert()
|
||||
else:
|
||||
dimension1 = frappe.get_doc("Accounting Dimension", "Department")
|
||||
dimension1.disabled = 0
|
||||
dimension1.save()
|
||||
|
||||
if not frappe.db.exists("Accounting Dimension", {"document_type": "Location"}):
|
||||
dimension1 = frappe.get_doc({
|
||||
"doctype": "Accounting Dimension",
|
||||
"document_type": "Location",
|
||||
})
|
||||
|
||||
dimension1.append("dimension_defaults", {
|
||||
"company": "_Test Company",
|
||||
"reference_document": "Location",
|
||||
"default_dimension": "Block 1",
|
||||
"mandatory_for_bs": 1
|
||||
})
|
||||
|
||||
dimension1.insert()
|
||||
dimension1.save()
|
||||
else:
|
||||
dimension1 = frappe.get_doc("Accounting Dimension", "Location")
|
||||
dimension1.disabled = 0
|
||||
dimension1.save()
|
||||
create_dimension()
|
||||
|
||||
def test_dimension_against_sales_invoice(self):
|
||||
si = create_sales_invoice(do_not_save=1)
|
||||
@ -101,6 +71,38 @@ class TestAccountingDimension(unittest.TestCase):
|
||||
def tearDown(self):
|
||||
disable_dimension()
|
||||
|
||||
def create_dimension():
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
if not frappe.db.exists("Accounting Dimension", {"document_type": "Department"}):
|
||||
frappe.get_doc({
|
||||
"doctype": "Accounting Dimension",
|
||||
"document_type": "Department",
|
||||
}).insert()
|
||||
else:
|
||||
dimension = frappe.get_doc("Accounting Dimension", "Department")
|
||||
dimension.disabled = 0
|
||||
dimension.save()
|
||||
|
||||
if not frappe.db.exists("Accounting Dimension", {"document_type": "Location"}):
|
||||
dimension1 = frappe.get_doc({
|
||||
"doctype": "Accounting Dimension",
|
||||
"document_type": "Location",
|
||||
})
|
||||
|
||||
dimension1.append("dimension_defaults", {
|
||||
"company": "_Test Company",
|
||||
"reference_document": "Location",
|
||||
"default_dimension": "Block 1",
|
||||
"mandatory_for_bs": 1
|
||||
})
|
||||
|
||||
dimension1.insert()
|
||||
dimension1.save()
|
||||
else:
|
||||
dimension1 = frappe.get_doc("Accounting Dimension", "Location")
|
||||
dimension1.disabled = 0
|
||||
dimension1.save()
|
||||
|
||||
def disable_dimension():
|
||||
dimension1 = frappe.get_doc("Accounting Dimension", "Department")
|
||||
|
@ -0,0 +1,82 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Accounting Dimension Filter', {
|
||||
refresh: function(frm, cdt, cdn) {
|
||||
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: #f9f9f9;">
|
||||
<tr><td>
|
||||
<p>
|
||||
<i class="fa fa-hand-right"></i>
|
||||
{{__('Note: On checking Is Mandatory the accounting dimension will become mandatory against that specific account for all accounting transactions')}}
|
||||
</p>
|
||||
</td></tr>
|
||||
</table>`;
|
||||
|
||||
frm.set_df_property('dimension_filter_help', 'options', help_content);
|
||||
},
|
||||
onload: function(frm) {
|
||||
frm.set_query('applicable_on_account', 'accounts', function() {
|
||||
return {
|
||||
filters: {
|
||||
'company': frm.doc.company
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
frappe.db.get_list('Accounting Dimension',
|
||||
{fields: ['document_type']}).then((res) => {
|
||||
let options = ['Cost Center', 'Project'];
|
||||
|
||||
res.forEach((dimension) => {
|
||||
options.push(dimension.document_type);
|
||||
});
|
||||
|
||||
frm.set_df_property('accounting_dimension', 'options', options);
|
||||
});
|
||||
|
||||
frm.trigger('setup_filters');
|
||||
},
|
||||
|
||||
setup_filters: function(frm) {
|
||||
let filters = {};
|
||||
|
||||
if (frm.doc.accounting_dimension) {
|
||||
frappe.model.with_doctype(frm.doc.accounting_dimension, function() {
|
||||
if (frappe.model.is_tree(frm.doc.accounting_dimension)) {
|
||||
filters['is_group'] = 0;
|
||||
}
|
||||
|
||||
if (frappe.meta.has_field(frm.doc.accounting_dimension, 'company')) {
|
||||
filters['company'] = frm.doc.company;
|
||||
}
|
||||
|
||||
frm.set_query('dimension_value', 'dimensions', function() {
|
||||
return {
|
||||
filters: filters
|
||||
};
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
accounting_dimension: function(frm) {
|
||||
frm.clear_table("dimensions");
|
||||
let row = frm.add_child("dimensions");
|
||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||
frm.refresh_field("dimensions");
|
||||
frm.trigger('setup_filters');
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Allowed Dimension', {
|
||||
dimensions_add: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
row.accounting_dimension = frm.doc.accounting_dimension;
|
||||
frm.refresh_field("dimensions");
|
||||
}
|
||||
});
|
@ -0,0 +1,158 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "format:{accounting_dimension}-{#####}",
|
||||
"creation": "2020-11-08 18:28:11.906146",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"accounting_dimension",
|
||||
"disabled",
|
||||
"column_break_2",
|
||||
"company",
|
||||
"allow_or_restrict",
|
||||
"section_break_4",
|
||||
"accounts",
|
||||
"column_break_6",
|
||||
"dimensions",
|
||||
"section_break_10",
|
||||
"dimension_filter_help"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "accounting_dimension",
|
||||
"fieldtype": "Select",
|
||||
"in_list_view": 1,
|
||||
"label": "Accounting Dimension",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_4",
|
||||
"fieldtype": "Section Break",
|
||||
"hide_border": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_6",
|
||||
"fieldtype": "Column Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "allow_or_restrict",
|
||||
"fieldtype": "Select",
|
||||
"label": "Allow Or Restrict Dimension",
|
||||
"options": "Allow\nRestrict",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "accounts",
|
||||
"fieldtype": "Table",
|
||||
"label": "Applicable On Account",
|
||||
"options": "Applicable On Account",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.accounting_dimension",
|
||||
"fieldname": "dimensions",
|
||||
"fieldtype": "Table",
|
||||
"label": "Applicable Dimension",
|
||||
"options": "Allowed Dimension",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dimension_filter_help",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Dimension Filter Help",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_10",
|
||||
"fieldtype": "Section Break",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-03 12:04:58.678402",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounting Dimension Filter",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright, (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _, scrub
|
||||
from frappe.model.document import Document
|
||||
|
||||
class AccountingDimensionFilter(Document):
|
||||
def validate(self):
|
||||
self.validate_applicable_accounts()
|
||||
|
||||
def validate_applicable_accounts(self):
|
||||
accounts = frappe.db.sql(
|
||||
"""
|
||||
SELECT a.applicable_on_account as account
|
||||
FROM `tabApplicable On Account` a, `tabAccounting Dimension Filter` d
|
||||
WHERE d.name = a.parent
|
||||
and d.name != %s
|
||||
and d.accounting_dimension = %s
|
||||
""", (self.name, self.accounting_dimension), as_dict=1)
|
||||
|
||||
account_list = [d.account for d in accounts]
|
||||
|
||||
for account in self.get('accounts'):
|
||||
if account.applicable_on_account in account_list:
|
||||
frappe.throw(_("Row {0}: {1} account already applied for Accounting Dimension {2}").format(
|
||||
account.idx, frappe.bold(account.applicable_on_account), frappe.bold(self.accounting_dimension)))
|
||||
|
||||
def get_dimension_filter_map():
|
||||
filters = frappe.db.sql("""
|
||||
SELECT
|
||||
a.applicable_on_account, d.dimension_value, p.accounting_dimension,
|
||||
p.allow_or_restrict, a.is_mandatory
|
||||
FROM
|
||||
`tabApplicable On Account` a, `tabAllowed Dimension` d,
|
||||
`tabAccounting Dimension Filter` p
|
||||
WHERE
|
||||
p.name = a.parent
|
||||
AND p.disabled = 0
|
||||
AND p.name = d.parent
|
||||
""", as_dict=1)
|
||||
|
||||
dimension_filter_map = {}
|
||||
|
||||
for f in filters:
|
||||
f.fieldname = scrub(f.accounting_dimension)
|
||||
|
||||
build_map(dimension_filter_map, f.fieldname, f.applicable_on_account, f.dimension_value,
|
||||
f.allow_or_restrict, f.is_mandatory)
|
||||
|
||||
return dimension_filter_map
|
||||
|
||||
def build_map(map_object, dimension, account, filter_value, allow_or_restrict, is_mandatory):
|
||||
map_object.setdefault((dimension, account), {
|
||||
'allowed_dimensions': [],
|
||||
'is_mandatory': is_mandatory,
|
||||
'allow_or_restrict': allow_or_restrict
|
||||
})
|
||||
map_object[(dimension, account)]['allowed_dimensions'].append(filter_value)
|
@ -0,0 +1,99 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension import create_dimension, disable_dimension
|
||||
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
|
||||
|
||||
class TestAccountingDimensionFilter(unittest.TestCase):
|
||||
def setUp(self):
|
||||
create_dimension()
|
||||
create_accounting_dimension_filter()
|
||||
self.invoice_list = []
|
||||
|
||||
def test_allowed_dimension_validation(self):
|
||||
si = create_sales_invoice(do_not_save=1)
|
||||
si.items[0].cost_center = 'Main - _TC'
|
||||
si.department = 'Accounts - _TC'
|
||||
si.location = 'Block 1'
|
||||
si.save()
|
||||
|
||||
self.assertRaises(InvalidAccountDimensionError, si.submit)
|
||||
self.invoice_list.append(si)
|
||||
|
||||
def test_mandatory_dimension_validation(self):
|
||||
si = create_sales_invoice(do_not_save=1)
|
||||
si.department = ''
|
||||
si.location = 'Block 1'
|
||||
|
||||
# Test with no department for Sales Account
|
||||
si.items[0].department = ''
|
||||
si.items[0].cost_center = '_Test Cost Center 2 - _TC'
|
||||
si.save()
|
||||
|
||||
self.assertRaises(MandatoryAccountDimensionError, si.submit)
|
||||
self.invoice_list.append(si)
|
||||
|
||||
def tearDown(self):
|
||||
disable_dimension_filter()
|
||||
disable_dimension()
|
||||
|
||||
for si in self.invoice_list:
|
||||
si.load_from_db()
|
||||
if si.docstatus == 1:
|
||||
si.cancel()
|
||||
|
||||
def create_accounting_dimension_filter():
|
||||
if not frappe.db.get_value('Accounting Dimension Filter',
|
||||
{'accounting_dimension': 'Cost Center'}):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Accounting Dimension Filter',
|
||||
'accounting_dimension': 'Cost Center',
|
||||
'allow_or_restrict': 'Allow',
|
||||
'company': '_Test Company',
|
||||
'accounts': [{
|
||||
'applicable_on_account': 'Sales - _TC',
|
||||
}],
|
||||
'dimensions': [{
|
||||
'accounting_dimension': 'Cost Center',
|
||||
'dimension_value': '_Test Cost Center 2 - _TC'
|
||||
}]
|
||||
}).insert()
|
||||
else:
|
||||
doc = frappe.get_doc('Accounting Dimension Filter', {'accounting_dimension': 'Cost Center'})
|
||||
doc.disabled = 0
|
||||
doc.save()
|
||||
|
||||
if not frappe.db.get_value('Accounting Dimension Filter',
|
||||
{'accounting_dimension': 'Department'}):
|
||||
frappe.get_doc({
|
||||
'doctype': 'Accounting Dimension Filter',
|
||||
'accounting_dimension': 'Department',
|
||||
'allow_or_restrict': 'Allow',
|
||||
'company': '_Test Company',
|
||||
'accounts': [{
|
||||
'applicable_on_account': 'Sales - _TC',
|
||||
'is_mandatory': 1
|
||||
}],
|
||||
'dimensions': [{
|
||||
'accounting_dimension': 'Department',
|
||||
'dimension_value': 'Accounts - _TC'
|
||||
}]
|
||||
}).insert()
|
||||
else:
|
||||
doc = frappe.get_doc('Accounting Dimension Filter', {'accounting_dimension': 'Department'})
|
||||
doc.disabled = 0
|
||||
doc.save()
|
||||
|
||||
def disable_dimension_filter():
|
||||
doc = frappe.get_doc('Accounting Dimension Filter', {'accounting_dimension': 'Cost Center'})
|
||||
doc.disabled = 1
|
||||
doc.save()
|
||||
|
||||
doc = frappe.get_doc('Accounting Dimension Filter', {'accounting_dimension': 'Department'})
|
||||
doc.disabled = 1
|
||||
doc.save()
|
@ -11,36 +11,36 @@ from erpnext.accounts.doctype.accounting_period.accounting_period import Overlap
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
|
||||
class TestAccountingPeriod(unittest.TestCase):
|
||||
def test_overlap(self):
|
||||
ap1 = create_accounting_period(start_date = "2018-04-01",
|
||||
end_date = "2018-06-30", company = "Wind Power LLC")
|
||||
ap1.save()
|
||||
def test_overlap(self):
|
||||
ap1 = create_accounting_period(start_date = "2018-04-01",
|
||||
end_date = "2018-06-30", company = "Wind Power LLC")
|
||||
ap1.save()
|
||||
|
||||
ap2 = create_accounting_period(start_date = "2018-06-30",
|
||||
end_date = "2018-07-10", company = "Wind Power LLC", period_name = "Test Accounting Period 1")
|
||||
self.assertRaises(OverlapError, ap2.save)
|
||||
ap2 = create_accounting_period(start_date = "2018-06-30",
|
||||
end_date = "2018-07-10", company = "Wind Power LLC", period_name = "Test Accounting Period 1")
|
||||
self.assertRaises(OverlapError, ap2.save)
|
||||
|
||||
def test_accounting_period(self):
|
||||
ap1 = create_accounting_period(period_name = "Test Accounting Period 2")
|
||||
ap1.save()
|
||||
def test_accounting_period(self):
|
||||
ap1 = create_accounting_period(period_name = "Test Accounting Period 2")
|
||||
ap1.save()
|
||||
|
||||
doc = create_sales_invoice(do_not_submit=1, cost_center = "_Test Company - _TC", warehouse = "Stores - _TC")
|
||||
self.assertRaises(ClosedAccountingPeriod, doc.submit)
|
||||
doc = create_sales_invoice(do_not_submit=1, cost_center="_Test Company - _TC", warehouse="Stores - _TC")
|
||||
self.assertRaises(ClosedAccountingPeriod, doc.submit)
|
||||
|
||||
def tearDown(self):
|
||||
for d in frappe.get_all("Accounting Period"):
|
||||
frappe.delete_doc("Accounting Period", d.name)
|
||||
def tearDown(self):
|
||||
for d in frappe.get_all("Accounting Period"):
|
||||
frappe.delete_doc("Accounting Period", d.name)
|
||||
|
||||
def create_accounting_period(**args):
|
||||
args = frappe._dict(args)
|
||||
args = frappe._dict(args)
|
||||
|
||||
accounting_period = frappe.new_doc("Accounting Period")
|
||||
accounting_period.start_date = args.start_date or nowdate()
|
||||
accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
|
||||
accounting_period.company = args.company or "_Test Company"
|
||||
accounting_period.period_name =args.period_name or "_Test_Period_Name_1"
|
||||
accounting_period.append("closed_documents", {
|
||||
"document_type": 'Sales Invoice', "closed": 1
|
||||
})
|
||||
accounting_period = frappe.new_doc("Accounting Period")
|
||||
accounting_period.start_date = args.start_date or nowdate()
|
||||
accounting_period.end_date = args.end_date or add_months(nowdate(), 1)
|
||||
accounting_period.company = args.company or "_Test Company"
|
||||
accounting_period.period_name =args.period_name or "_Test_Period_Name_1"
|
||||
accounting_period.append("closed_documents", {
|
||||
"document_type": 'Sales Invoice', "closed": 1
|
||||
})
|
||||
|
||||
return accounting_period
|
||||
return accounting_period
|
||||
|
@ -6,3 +6,46 @@ frappe.ui.form.on('Accounts Settings', {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
frappe.tour['Accounts Settings'] = [
|
||||
{
|
||||
fieldname: "acc_frozen_upto",
|
||||
title: "Accounts Frozen Upto",
|
||||
description: __("Freeze accounting transactions up to specified date, nobody can make/modify entry except the specified Role."),
|
||||
},
|
||||
{
|
||||
fieldname: "frozen_accounts_modifier",
|
||||
title: "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||
description: __("Users with this Role are allowed to set frozen accounts and create/modify accounting entries against frozen accounts.")
|
||||
},
|
||||
{
|
||||
fieldname: "determine_address_tax_category_from",
|
||||
title: "Determine Address Tax Category From",
|
||||
description: __("Tax category can be set on Addresses. An address can be Shipping or Billing address. Set which addres to select when applying Tax Category.")
|
||||
},
|
||||
{
|
||||
fieldname: "over_billing_allowance",
|
||||
title: "Over Billing Allowance Percentage",
|
||||
description: __("The percentage by which you can overbill transactions. For example, if the order value is $100 for an Item and percentage here is set as 10% then you are allowed to bill for $110.")
|
||||
},
|
||||
{
|
||||
fieldname: "credit_controller",
|
||||
title: "Credit Controller",
|
||||
description: __("Select the role that is allowed to submit transactions that exceed credit limits set. The credit limit can be set in the Customer form.")
|
||||
},
|
||||
{
|
||||
fieldname: "make_payment_via_journal_entry",
|
||||
title: "Make Payment via Journal Entry",
|
||||
description: __("When checked, if user proceeds to make payment from an invoice, the system will open a Journal Entry instead of a Payment Entry.")
|
||||
},
|
||||
{
|
||||
fieldname: "unlink_payment_on_cancellation_of_invoice",
|
||||
title: "Unlink Payment on Cancellation of Invoice",
|
||||
description: __("If checked, system will unlink the payment against the respective invoice.")
|
||||
},
|
||||
{
|
||||
fieldname: "unlink_advance_payment_on_cancelation_of_order",
|
||||
title: "Unlink Advance Payment on Cancellation of Order",
|
||||
description: __("Similar to the previous option, this unlinks any advance payments made against Purchase/Sales Orders.")
|
||||
}
|
||||
];
|
@ -21,6 +21,7 @@
|
||||
"book_asset_depreciation_entry_automatically",
|
||||
"add_taxes_from_item_tax_template",
|
||||
"automatically_fetch_payment_terms",
|
||||
"delete_linked_ledger_entries",
|
||||
"deferred_accounting_settings_section",
|
||||
"automatically_process_deferred_accounting_entry",
|
||||
"book_deferred_entries_based_on",
|
||||
@ -40,7 +41,7 @@
|
||||
"fields": [
|
||||
{
|
||||
"default": "1",
|
||||
"description": "If enabled, the system will post accounting entries for inventory automatically.",
|
||||
"description": "If enabled, the system will post accounting entries for inventory automatically",
|
||||
"fieldname": "auto_accounting_for_stock",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
@ -48,23 +49,23 @@
|
||||
"label": "Make Accounting Entry For Every Stock Movement"
|
||||
},
|
||||
{
|
||||
"description": "Accounting entry frozen up to this date, nobody can do / modify entry except role specified below.",
|
||||
"description": "Accounting entries are frozen up to this date. Nobody can create or modify entries except users with the role specified below",
|
||||
"fieldname": "acc_frozen_upto",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Accounts Frozen Upto"
|
||||
"label": "Accounts Frozen Till Date"
|
||||
},
|
||||
{
|
||||
"description": "Users with this role are allowed to set frozen accounts and create / modify accounting entries against frozen accounts",
|
||||
"fieldname": "frozen_accounts_modifier",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Role Allowed to Set Frozen Accounts & Edit Frozen Entries",
|
||||
"label": "Role Allowed to Set Frozen Accounts and Edit Frozen Entries",
|
||||
"options": "Role"
|
||||
},
|
||||
{
|
||||
"default": "Billing Address",
|
||||
"description": "Address used to determine Tax Category in transactions.",
|
||||
"description": "Address used to determine Tax Category in transactions",
|
||||
"fieldname": "determine_address_tax_category_from",
|
||||
"fieldtype": "Select",
|
||||
"label": "Determine Address Tax Category From",
|
||||
@ -75,7 +76,7 @@
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "Role that is allowed to submit transactions that exceed credit limits set.",
|
||||
"description": "This role is allowed to submit transactions that exceed credit limits",
|
||||
"fieldname": "credit_controller",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
@ -104,7 +105,7 @@
|
||||
"default": "1",
|
||||
"fieldname": "unlink_advance_payment_on_cancelation_of_order",
|
||||
"fieldtype": "Check",
|
||||
"label": "Unlink Advance Payment on Cancelation of Order"
|
||||
"label": "Unlink Advance Payment on Cancellation of Order"
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
@ -127,7 +128,7 @@
|
||||
"default": "0",
|
||||
"fieldname": "show_inclusive_tax_in_print",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Inclusive Tax In Print"
|
||||
"label": "Show Inclusive Tax in Print"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_12",
|
||||
@ -165,7 +166,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Only select if you have setup Cash Flow Mapper documents",
|
||||
"description": "Only select this if you have set up the Cash Flow Mapper documents",
|
||||
"fieldname": "use_custom_cash_flow",
|
||||
"fieldtype": "Check",
|
||||
"label": "Use Custom Cash Flow Format"
|
||||
@ -177,7 +178,7 @@
|
||||
"label": "Automatically Fetch Payment Terms"
|
||||
},
|
||||
{
|
||||
"description": "Percentage you are allowed to bill more against the amount ordered. For example: If the order value is $100 for an item and tolerance is set as 10% then you are allowed to bill for $110.",
|
||||
"description": "The percentage you are allowed to bill more against the amount ordered. For example, if the order value is $100 for an item and tolerance is set as 10%, then you are allowed to bill up to $110 ",
|
||||
"fieldname": "over_billing_allowance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Over Billing Allowance (%)"
|
||||
@ -199,7 +200,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "If this is unchecked direct GL Entries will be created to book Deferred Revenue/Expense",
|
||||
"description": "If this is unchecked, direct GL entries will be created to book deferred revenue or expense",
|
||||
"fieldname": "book_deferred_entries_via_journal_entry",
|
||||
"fieldtype": "Check",
|
||||
"label": "Book Deferred Entries Via Journal Entry"
|
||||
@ -214,18 +215,25 @@
|
||||
},
|
||||
{
|
||||
"default": "Days",
|
||||
"description": "If \"Months\" is selected then fixed amount will be booked as deferred revenue or expense for each month irrespective of number of days in a month. Will be prorated if deferred revenue or expense is not booked for an entire month.",
|
||||
"description": "If \"Months\" is selected, a fixed amount will be booked as deferred revenue or expense for each month irrespective of the number of days in a month. It will be prorated if deferred revenue or expense is not booked for an entire month",
|
||||
"fieldname": "book_deferred_entries_based_on",
|
||||
"fieldtype": "Select",
|
||||
"label": "Book Deferred Entries Based On",
|
||||
"options": "Days\nMonths"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "delete_linked_ledger_entries",
|
||||
"fieldtype": "Check",
|
||||
"label": "Delete Accounting and Stock Ledger Entries on deletion of Transaction"
|
||||
}
|
||||
],
|
||||
"icon": "icon-cog",
|
||||
"idx": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2020-08-03 20:13:26.043092",
|
||||
"modified": "2021-01-05 13:04:00.118892",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
@ -0,0 +1,43 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-11-08 18:22:36.001131",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"accounting_dimension",
|
||||
"dimension_value"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "accounting_dimension",
|
||||
"fieldtype": "Link",
|
||||
"label": "Accounting Dimension",
|
||||
"options": "DocType",
|
||||
"read_only": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "dimension_value",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"in_list_view": 1,
|
||||
"options": "accounting_dimension",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-23 09:56:19.744200",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Allowed Dimension",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BankStatementTransactionInvoiceItem(Document):
|
||||
class AllowedDimension(Document):
|
||||
pass
|
@ -0,0 +1,46 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-11-08 18:20:00.944449",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"applicable_on_account",
|
||||
"is_mandatory"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "applicable_on_account",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Accounts",
|
||||
"options": "Account",
|
||||
"reqd": 1,
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
},
|
||||
{
|
||||
"columns": 2,
|
||||
"default": "0",
|
||||
"fieldname": "is_mandatory",
|
||||
"fieldtype": "Check",
|
||||
"in_list_view": 1,
|
||||
"label": "Is Mandatory",
|
||||
"show_days": 1,
|
||||
"show_seconds": 1
|
||||
}
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"istable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-22 19:55:13.324136",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Applicable On Account",
|
||||
"owner": "Administrator",
|
||||
"permissions": [],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
# import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BankStatementTransactionPaymentItem(Document):
|
||||
class ApplicableOnAccount(Document):
|
||||
pass
|
@ -1,5 +1,6 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.provide('erpnext.integrations');
|
||||
|
||||
frappe.ui.form.on('Bank', {
|
||||
onload: function(frm) {
|
||||
@ -20,7 +21,12 @@ frappe.ui.form.on('Bank', {
|
||||
frm.set_df_property('address_and_contact', 'hidden', 0);
|
||||
frappe.contacts.render_address_and_contact(frm);
|
||||
}
|
||||
},
|
||||
if (frm.doc.plaid_access_token) {
|
||||
frm.add_custom_button(__('Refresh Plaid Link'), () => {
|
||||
new erpnext.integrations.refreshPlaidLink(frm.doc.plaid_access_token);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@ -40,4 +46,79 @@ let add_fields_to_mapping_table = function (frm) {
|
||||
frm.doc.name).options = options;
|
||||
|
||||
frm.fields_dict.bank_transaction_mapping.grid.refresh();
|
||||
};
|
||||
};
|
||||
|
||||
erpnext.integrations.refreshPlaidLink = class refreshPlaidLink {
|
||||
constructor(access_token) {
|
||||
this.access_token = access_token;
|
||||
this.plaidUrl = 'https://cdn.plaid.com/link/v2/stable/link-initialize.js';
|
||||
this.init_config();
|
||||
}
|
||||
|
||||
async init_config() {
|
||||
this.plaid_env = await frappe.db.get_single_value('Plaid Settings', 'plaid_env');
|
||||
this.token = await this.get_link_token_for_update();
|
||||
this.init_plaid();
|
||||
}
|
||||
|
||||
async get_link_token_for_update() {
|
||||
const token = frappe.xcall(
|
||||
'erpnext.erpnext_integrations.doctype.plaid_settings.plaid_settings.get_link_token_for_update',
|
||||
{ access_token: this.access_token }
|
||||
)
|
||||
if (!token) {
|
||||
frappe.throw(__('Cannot retrieve link token for update. Check Error Log for more information'));
|
||||
}
|
||||
return token;
|
||||
}
|
||||
|
||||
init_plaid() {
|
||||
const me = this;
|
||||
me.loadScript(me.plaidUrl)
|
||||
.then(() => {
|
||||
me.onScriptLoaded(me);
|
||||
})
|
||||
.then(() => {
|
||||
if (me.linkHandler) {
|
||||
me.linkHandler.open();
|
||||
}
|
||||
})
|
||||
.catch((error) => {
|
||||
me.onScriptError(error);
|
||||
});
|
||||
}
|
||||
|
||||
loadScript(src) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
if (document.querySelector("script[src='" + src + "']")) {
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const el = document.createElement('script');
|
||||
el.type = 'text/javascript';
|
||||
el.async = true;
|
||||
el.src = src;
|
||||
el.addEventListener('load', resolve);
|
||||
el.addEventListener('error', reject);
|
||||
el.addEventListener('abort', reject);
|
||||
document.head.appendChild(el);
|
||||
});
|
||||
}
|
||||
|
||||
onScriptLoaded(me) {
|
||||
me.linkHandler = Plaid.create({
|
||||
env: me.plaid_env,
|
||||
token: me.token,
|
||||
onSuccess: me.plaid_success
|
||||
});
|
||||
}
|
||||
|
||||
onScriptError(error) {
|
||||
frappe.msgprint(__("There was an issue connecting to Plaid's authentication server. Check browser console for more information"));
|
||||
console.log(error);
|
||||
}
|
||||
|
||||
plaid_success(token, response) {
|
||||
frappe.show_alert({ message: __('Plaid Link Updated'), indicator: 'green' });
|
||||
}
|
||||
};
|
||||
|
@ -86,6 +86,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Setting the account as a Company Account is necessary for Bank Reconciliation",
|
||||
"fieldname": "is_company_account",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Company Account"
|
||||
@ -207,7 +208,7 @@
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-07-17 13:59:50.795412",
|
||||
"modified": "2020-10-23 16:48:06.303658",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Account",
|
||||
|
@ -0,0 +1,163 @@
|
||||
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.provide("erpnext.accounts.bank_reconciliation");
|
||||
|
||||
frappe.ui.form.on("Bank Reconciliation Tool", {
|
||||
setup: function (frm) {
|
||||
frm.set_query("bank_account", function () {
|
||||
return {
|
||||
filters: {
|
||||
company: ["in", frm.doc.company],
|
||||
'is_company_account': 1
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
refresh: function (frm) {
|
||||
frappe.require("assets/js/bank-reconciliation-tool.min.js", () =>
|
||||
frm.trigger("make_reconciliation_tool")
|
||||
);
|
||||
frm.upload_statement_button = frm.page.set_secondary_action(
|
||||
__("Upload Bank Statement"),
|
||||
() =>
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_statement_import.bank_statement_import.upload_bank_statement",
|
||||
args: {
|
||||
dt: frm.doc.doctype,
|
||||
dn: frm.doc.name,
|
||||
company: frm.doc.company,
|
||||
bank_account: frm.doc.bank_account,
|
||||
},
|
||||
callback: function (r) {
|
||||
if (!r.exc) {
|
||||
var doc = frappe.model.sync(r.message);
|
||||
frappe.set_route(
|
||||
"Form",
|
||||
doc[0].doctype,
|
||||
doc[0].name
|
||||
);
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
after_save: function (frm) {
|
||||
frm.trigger("make_reconciliation_tool");
|
||||
},
|
||||
|
||||
bank_account: function (frm) {
|
||||
frappe.db.get_value(
|
||||
"Bank Account",
|
||||
frm.bank_account,
|
||||
"account",
|
||||
(r) => {
|
||||
frappe.db.get_value(
|
||||
"Account",
|
||||
r.account,
|
||||
"account_currency",
|
||||
(r) => {
|
||||
frm.currency = r.account_currency;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
frm.trigger("get_account_opening_balance");
|
||||
},
|
||||
|
||||
bank_statement_from_date: function (frm) {
|
||||
frm.trigger("get_account_opening_balance");
|
||||
},
|
||||
|
||||
make_reconciliation_tool(frm) {
|
||||
frm.get_field("reconciliation_tool_cards").$wrapper.empty();
|
||||
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
|
||||
frm.trigger("get_cleared_balance").then(() => {
|
||||
if (
|
||||
frm.doc.bank_account &&
|
||||
frm.doc.bank_statement_from_date &&
|
||||
frm.doc.bank_statement_to_date &&
|
||||
frm.doc.bank_statement_closing_balance
|
||||
) {
|
||||
frm.trigger("render_chart");
|
||||
frm.trigger("render");
|
||||
frappe.utils.scroll_to(
|
||||
frm.get_field("reconciliation_tool_cards").$wrapper,
|
||||
true,
|
||||
30
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get_account_opening_balance(frm) {
|
||||
if (frm.doc.bank_account && frm.doc.bank_statement_from_date) {
|
||||
frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
args: {
|
||||
bank_account: frm.doc.bank_account,
|
||||
till_date: frm.doc.bank_statement_from_date,
|
||||
},
|
||||
callback: (response) => {
|
||||
frm.set_value("account_opening_balance", response.message);
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
get_cleared_balance(frm) {
|
||||
if (frm.doc.bank_account && frm.doc.bank_statement_to_date) {
|
||||
return frappe.call({
|
||||
method:
|
||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||
args: {
|
||||
bank_account: frm.doc.bank_account,
|
||||
till_date: frm.doc.bank_statement_to_date,
|
||||
},
|
||||
callback: (response) => {
|
||||
frm.cleared_balance = response.message;
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
render_chart(frm) {
|
||||
frm.cards_manager = new erpnext.accounts.bank_reconciliation.NumberCardManager(
|
||||
{
|
||||
$reconciliation_tool_cards: frm.get_field(
|
||||
"reconciliation_tool_cards"
|
||||
).$wrapper,
|
||||
bank_statement_closing_balance:
|
||||
frm.doc.bank_statement_closing_balance,
|
||||
cleared_balance: frm.cleared_balance,
|
||||
currency: frm.currency,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
render(frm) {
|
||||
if (frm.doc.bank_account) {
|
||||
frm.bank_reconciliation_data_table_manager = new erpnext.accounts.bank_reconciliation.DataTableManager(
|
||||
{
|
||||
company: frm.doc.company,
|
||||
bank_account: frm.doc.bank_account,
|
||||
$reconciliation_tool_dt: frm.get_field(
|
||||
"reconciliation_tool_dt"
|
||||
).$wrapper,
|
||||
$no_bank_transactions: frm.get_field(
|
||||
"no_bank_transactions"
|
||||
).$wrapper,
|
||||
bank_statement_from_date: frm.doc.bank_statement_from_date,
|
||||
bank_statement_to_date: frm.doc.bank_statement_to_date,
|
||||
bank_statement_closing_balance:
|
||||
frm.doc.bank_statement_closing_balance,
|
||||
cards_manager: frm.cards_manager,
|
||||
}
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
@ -0,0 +1,113 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2020-12-02 10:13:02.148040",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"bank_account",
|
||||
"column_break_1",
|
||||
"bank_statement_from_date",
|
||||
"bank_statement_to_date",
|
||||
"column_break_2",
|
||||
"account_opening_balance",
|
||||
"bank_statement_closing_balance",
|
||||
"section_break_1",
|
||||
"reconciliation_tool_cards",
|
||||
"reconciliation_tool_dt",
|
||||
"no_bank_transactions"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company"
|
||||
},
|
||||
{
|
||||
"fieldname": "bank_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Bank Account",
|
||||
"options": "Bank Account"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_1",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.bank_account",
|
||||
"fieldname": "bank_statement_from_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Bank Statement From Date"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.bank_statement_from_date",
|
||||
"fieldname": "bank_statement_to_date",
|
||||
"fieldtype": "Date",
|
||||
"label": "Bank Statement To Date"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_2",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.bank_statement_from_date",
|
||||
"fieldname": "account_opening_balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Account Opening Balance",
|
||||
"options": "Currency",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.bank_statement_to_date",
|
||||
"fieldname": "bank_statement_closing_balance",
|
||||
"fieldtype": "Currency",
|
||||
"label": "Bank Statement Closing Balance",
|
||||
"options": "Currency"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval: doc.bank_statement_closing_balance",
|
||||
"fieldname": "section_break_1",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Reconcile"
|
||||
},
|
||||
{
|
||||
"fieldname": "reconciliation_tool_cards",
|
||||
"fieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "reconciliation_tool_dt",
|
||||
"fieldtype": "HTML"
|
||||
},
|
||||
{
|
||||
"fieldname": "no_bank_transactions",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<div class=\"text-muted text-center\">No Matching Bank Transactions Found</div>"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-02 01:35:53.043578",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Reconciliation Tool",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -0,0 +1,452 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import json
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe import _
|
||||
from frappe.utils import flt
|
||||
|
||||
from erpnext import get_company_currency
|
||||
from erpnext.accounts.utils import get_balance_on
|
||||
from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_statement import get_entries, get_amounts_not_reflected_in_system
|
||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_paid_amount
|
||||
|
||||
|
||||
class BankReconciliationTool(Document):
|
||||
pass
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_bank_transactions(bank_account, from_date = None, to_date = None):
|
||||
# returns bank transactions for a bank account
|
||||
filters = []
|
||||
filters.append(['bank_account', '=', bank_account])
|
||||
filters.append(['docstatus', '=', 1])
|
||||
filters.append(['unallocated_amount', '>', 0])
|
||||
if to_date:
|
||||
filters.append(['date', '<=', to_date])
|
||||
if from_date:
|
||||
filters.append(['date', '>=', from_date])
|
||||
transactions = frappe.get_all(
|
||||
'Bank Transaction',
|
||||
fields = ['date', 'deposit', 'withdrawal', 'currency',
|
||||
'description', 'name', 'bank_account', 'company',
|
||||
'unallocated_amount', 'reference_number', 'party_type', 'party'],
|
||||
filters = filters
|
||||
)
|
||||
return transactions
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_account_balance(bank_account, till_date):
|
||||
# returns account balance till the specified date
|
||||
account = frappe.db.get_value('Bank Account', bank_account, 'account')
|
||||
filters = frappe._dict({
|
||||
"account": account,
|
||||
"report_date": till_date,
|
||||
"include_pos_transactions": 1
|
||||
})
|
||||
data = get_entries(filters)
|
||||
|
||||
balance_as_per_system = get_balance_on(filters["account"], filters["report_date"])
|
||||
|
||||
total_debit, total_credit = 0,0
|
||||
for d in data:
|
||||
total_debit += flt(d.debit)
|
||||
total_credit += flt(d.credit)
|
||||
|
||||
amounts_not_reflected_in_system = get_amounts_not_reflected_in_system(filters)
|
||||
|
||||
bank_bal = flt(balance_as_per_system) - flt(total_debit) + flt(total_credit) \
|
||||
+ amounts_not_reflected_in_system
|
||||
|
||||
return bank_bal
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def update_bank_transaction(bank_transaction_name, reference_number, party_type=None, party=None):
|
||||
# updates bank transaction based on the new parameters provided by the user from Vouchers
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||
bank_transaction.reference_number = reference_number
|
||||
bank_transaction.party_type = party_type
|
||||
bank_transaction.party = party
|
||||
bank_transaction.save()
|
||||
return frappe.db.get_all('Bank Transaction',
|
||||
filters={
|
||||
'name': bank_transaction_name
|
||||
},
|
||||
fields=['date', 'deposit', 'withdrawal', 'currency',
|
||||
'description', 'name', 'bank_account', 'company',
|
||||
'unallocated_amount', 'reference_number',
|
||||
'party_type', 'party'],
|
||||
)[0]
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_journal_entry_bts( bank_transaction_name, reference_number=None, reference_date=None, posting_date=None, entry_type=None,
|
||||
second_account=None, mode_of_payment=None, party_type=None, party=None, allow_edit=None):
|
||||
# Create a new journal entry based on the bank transaction
|
||||
bank_transaction = frappe.db.get_values(
|
||||
"Bank Transaction", bank_transaction_name,
|
||||
fieldname=["name", "deposit", "withdrawal", "bank_account"] ,
|
||||
as_dict=True
|
||||
)[0]
|
||||
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(_("Party Type and Party is required for Receivable / Payable account {0}").format( second_account))
|
||||
accounts = []
|
||||
# Multi Currency?
|
||||
accounts.append({
|
||||
"account": second_account,
|
||||
"credit_in_account_currency": bank_transaction.deposit
|
||||
if bank_transaction.deposit > 0
|
||||
else 0,
|
||||
"debit_in_account_currency":bank_transaction.withdrawal
|
||||
if bank_transaction.withdrawal > 0
|
||||
else 0,
|
||||
"party_type":party_type,
|
||||
"party":party,
|
||||
})
|
||||
|
||||
accounts.append({
|
||||
"account": company_account,
|
||||
"bank_account": bank_transaction.bank_account,
|
||||
"credit_in_account_currency": bank_transaction.withdrawal
|
||||
if bank_transaction.withdrawal > 0
|
||||
else 0,
|
||||
"debit_in_account_currency":bank_transaction.deposit
|
||||
if bank_transaction.deposit > 0
|
||||
else 0,
|
||||
})
|
||||
|
||||
company = frappe.get_value("Account", company_account, "company")
|
||||
|
||||
journal_entry_dict = {
|
||||
"voucher_type" : entry_type,
|
||||
"company" : company,
|
||||
"posting_date" : posting_date,
|
||||
"cheque_date" : reference_date,
|
||||
"cheque_no" : reference_number,
|
||||
"mode_of_payment" : mode_of_payment
|
||||
}
|
||||
journal_entry = frappe.new_doc('Journal Entry')
|
||||
journal_entry.update(journal_entry_dict)
|
||||
journal_entry.set("accounts", accounts)
|
||||
|
||||
|
||||
if allow_edit:
|
||||
return journal_entry
|
||||
|
||||
journal_entry.insert()
|
||||
journal_entry.submit()
|
||||
|
||||
if bank_transaction.deposit > 0:
|
||||
paid_amount = bank_transaction.deposit
|
||||
else:
|
||||
paid_amount = bank_transaction.withdrawal
|
||||
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Journal Entry",
|
||||
"payment_name":journal_entry.name,
|
||||
"amount":paid_amount}])
|
||||
|
||||
return reconcile_vouchers(bank_transaction.name, vouchers)
|
||||
|
||||
@frappe.whitelist()
|
||||
def create_payment_entry_bts( bank_transaction_name, reference_number=None, reference_date=None, party_type=None, party=None, posting_date=None,
|
||||
mode_of_payment=None, project=None, cost_center=None, allow_edit=None):
|
||||
# Create a new payment entry based on the bank transaction
|
||||
bank_transaction = frappe.db.get_values(
|
||||
"Bank Transaction", bank_transaction_name,
|
||||
fieldname=["name", "unallocated_amount", "deposit", "bank_account"] ,
|
||||
as_dict=True
|
||||
)[0]
|
||||
paid_amount = bank_transaction.unallocated_amount
|
||||
payment_type = "Receive" if bank_transaction.deposit > 0 else "Pay"
|
||||
|
||||
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,
|
||||
"reference_no" : reference_number,
|
||||
"reference_date" : reference_date,
|
||||
"party_type" : party_type,
|
||||
"party" : party,
|
||||
"posting_date" : posting_date,
|
||||
"paid_amount": paid_amount,
|
||||
"received_amount": paid_amount
|
||||
}
|
||||
payment_entry = frappe.new_doc("Payment Entry")
|
||||
|
||||
|
||||
payment_entry.update(payment_entry_dict)
|
||||
|
||||
if mode_of_payment:
|
||||
payment_entry.mode_of_payment = mode_of_payment
|
||||
if project:
|
||||
payment_entry.project = project
|
||||
if cost_center:
|
||||
payment_entry.cost_center = cost_center
|
||||
if payment_type == "Receive":
|
||||
payment_entry.paid_to = company_account
|
||||
else:
|
||||
payment_entry.paid_from = company_account
|
||||
|
||||
payment_entry.validate()
|
||||
|
||||
if allow_edit:
|
||||
return payment_entry
|
||||
|
||||
payment_entry.insert()
|
||||
|
||||
payment_entry.submit()
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Payment Entry",
|
||||
"payment_name":payment_entry.name,
|
||||
"amount":paid_amount}])
|
||||
return reconcile_vouchers(bank_transaction.name, vouchers)
|
||||
|
||||
@frappe.whitelist()
|
||||
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)
|
||||
if transaction.unallocated_amount == 0:
|
||||
frappe.throw(_("This bank transaction is already fully reconciled"))
|
||||
total_amount = 0
|
||||
for voucher in vouchers:
|
||||
voucher['payment_entry'] = frappe.get_doc(voucher['payment_doctype'], voucher['payment_name'])
|
||||
total_amount += get_paid_amount(frappe._dict({
|
||||
'payment_document': voucher['payment_doctype'],
|
||||
'payment_entry': voucher['payment_name'],
|
||||
}), transaction.currency)
|
||||
|
||||
if total_amount > transaction.unallocated_amount:
|
||||
frappe.throw(_("The Sum Total of Amounts of All Selected Vouchers Should be Less than the Unallocated Amount of the Bank Transaction"))
|
||||
account = frappe.db.get_value("Bank Account", transaction.bank_account, "account")
|
||||
|
||||
for voucher in vouchers:
|
||||
gl_entry = frappe.db.get_value("GL Entry", dict(account=account, voucher_type=voucher['payment_doctype'], voucher_no=voucher['payment_name']), ['credit', 'debit'], as_dict=1)
|
||||
gl_amount, transaction_amount = (gl_entry.credit, transaction.deposit) if gl_entry.credit > 0 else (gl_entry.debit, transaction.withdrawal)
|
||||
allocated_amount = gl_amount if gl_amount >= transaction_amount else transaction_amount
|
||||
|
||||
transaction.append("payment_entries", {
|
||||
"payment_document": voucher['payment_entry'].doctype,
|
||||
"payment_entry": voucher['payment_entry'].name,
|
||||
"allocated_amount": allocated_amount
|
||||
})
|
||||
|
||||
transaction.save()
|
||||
transaction.update_allocations()
|
||||
return frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_linked_payments(bank_transaction_name, document_types = None):
|
||||
# get all matching payments for a bank transaction
|
||||
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||
bank_account = frappe.db.get_values(
|
||||
"Bank Account",
|
||||
transaction.bank_account,
|
||||
["account", "company"],
|
||||
as_dict=True)[0]
|
||||
(account, company) = (bank_account.account, bank_account.company)
|
||||
matching = check_matching(account, company, transaction, document_types)
|
||||
return matching
|
||||
|
||||
def check_matching(bank_account, company, transaction, document_types):
|
||||
# combine all types of vocuhers
|
||||
subquery = get_queries(bank_account, company, transaction, document_types)
|
||||
filters = {
|
||||
"amount": transaction.unallocated_amount,
|
||||
"payment_type" : "Receive" if transaction.deposit > 0 else "Pay",
|
||||
"reference_no": transaction.reference_number,
|
||||
"party_type": transaction.party_type,
|
||||
"party": transaction.party,
|
||||
"bank_account": bank_account
|
||||
}
|
||||
|
||||
matching_vouchers = []
|
||||
for query in subquery:
|
||||
matching_vouchers.extend(
|
||||
frappe.db.sql(query, filters,)
|
||||
)
|
||||
|
||||
return sorted(matching_vouchers, key = lambda x: x[0], reverse=True) if matching_vouchers else []
|
||||
|
||||
def get_queries(bank_account, company, transaction, document_types):
|
||||
# get queries to get matching vouchers
|
||||
amount_condition = "=" if "exact_match" in document_types else "<="
|
||||
account_from_to = "paid_to" if transaction.deposit > 0 else "paid_from"
|
||||
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])
|
||||
|
||||
if "journal_entry" in document_types:
|
||||
je_amount_matching = get_je_matching_query(amount_condition, transaction)
|
||||
queries.extend([je_amount_matching])
|
||||
|
||||
if transaction.deposit > 0 and "sales_invoice" in document_types:
|
||||
si_amount_matching = get_si_matching_query(amount_condition)
|
||||
queries.extend([si_amount_matching])
|
||||
|
||||
if transaction.withdrawal > 0:
|
||||
if "purchase_invoice" in document_types:
|
||||
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
|
||||
|
||||
def get_pe_matching_query(amount_condition, account_from_to, transaction):
|
||||
# get matching payment entries query
|
||||
if transaction.deposit > 0:
|
||||
currency_field = "paid_to_account_currency as currency"
|
||||
else:
|
||||
currency_field = "paid_from_account_currency as currency"
|
||||
return f"""
|
||||
SELECT
|
||||
(CASE WHEN reference_no=%(reference_no)s THEN 1 ELSE 0 END
|
||||
+ CASE WHEN (party_type = %(party_type)s AND party = %(party)s ) THEN 1 ELSE 0 END
|
||||
+ 1 ) AS rank,
|
||||
'Payment Entry' as doctype,
|
||||
name,
|
||||
paid_amount,
|
||||
reference_no,
|
||||
reference_date,
|
||||
party,
|
||||
party_type,
|
||||
posting_date,
|
||||
{currency_field}
|
||||
FROM
|
||||
`tabPayment Entry`
|
||||
WHERE
|
||||
paid_amount {amount_condition} %(amount)s
|
||||
AND docstatus = 1
|
||||
AND payment_type IN (%(payment_type)s, 'Internal Transfer')
|
||||
AND ifnull(clearance_date, '') = ""
|
||||
AND {account_from_to} = %(bank_account)s
|
||||
"""
|
||||
|
||||
|
||||
def get_je_matching_query(amount_condition, transaction):
|
||||
# get matching journal entry query
|
||||
cr_or_dr = "credit" if transaction.withdrawal > 0 else "debit"
|
||||
return f"""
|
||||
|
||||
SELECT
|
||||
(CASE WHEN je.cheque_no=%(reference_no)s THEN 1 ELSE 0 END
|
||||
+ 1) AS rank ,
|
||||
'Journal Entry' as doctype,
|
||||
je.name,
|
||||
jea.{cr_or_dr}_in_account_currency as paid_amount,
|
||||
je.cheque_no as reference_no,
|
||||
je.cheque_date as reference_date,
|
||||
je.pay_to_recd_from as party,
|
||||
jea.party_type,
|
||||
je.posting_date,
|
||||
jea.account_currency as currency
|
||||
FROM
|
||||
`tabJournal Entry Account` as jea
|
||||
JOIN
|
||||
`tabJournal Entry` as je
|
||||
ON
|
||||
jea.parent = je.name
|
||||
WHERE
|
||||
(je.clearance_date is null or je.clearance_date='0000-00-00')
|
||||
AND jea.account = %(bank_account)s
|
||||
AND jea.{cr_or_dr}_in_account_currency {amount_condition} %(amount)s
|
||||
AND je.docstatus = 1
|
||||
"""
|
||||
|
||||
|
||||
def get_si_matching_query(amount_condition):
|
||||
# get matchin sales invoice query
|
||||
return f"""
|
||||
SELECT
|
||||
( CASE WHEN si.customer = %(party)s THEN 1 ELSE 0 END
|
||||
+ 1 ) AS rank,
|
||||
'Sales Invoice' as doctype,
|
||||
si.name,
|
||||
sip.amount as paid_amount,
|
||||
'' as reference_no,
|
||||
'' as reference_date,
|
||||
si.customer as party,
|
||||
'Customer' as party_type,
|
||||
si.posting_date,
|
||||
si.currency
|
||||
|
||||
FROM
|
||||
`tabSales Invoice Payment` as sip
|
||||
JOIN
|
||||
`tabSales Invoice` as si
|
||||
ON
|
||||
sip.parent = si.name
|
||||
WHERE (sip.clearance_date is null or sip.clearance_date='0000-00-00')
|
||||
AND sip.account = %(bank_account)s
|
||||
AND sip.amount {amount_condition} %(amount)s
|
||||
AND si.docstatus = 1
|
||||
"""
|
||||
|
||||
def get_pi_matching_query(amount_condition):
|
||||
# get matching purchase invoice query
|
||||
return f"""
|
||||
SELECT
|
||||
( CASE WHEN supplier = %(party)s THEN 1 ELSE 0 END
|
||||
+ 1 ) AS rank,
|
||||
'Purchase Invoice' as doctype,
|
||||
name,
|
||||
paid_amount,
|
||||
'' as reference_no,
|
||||
'' as reference_date,
|
||||
supplier as party,
|
||||
'Supplier' as party_type,
|
||||
posting_date,
|
||||
currency
|
||||
FROM
|
||||
`tabPurchase Invoice`
|
||||
WHERE
|
||||
paid_amount {amount_condition} %(amount)s
|
||||
AND docstatus = 1
|
||||
AND is_paid = 1
|
||||
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_list("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}
|
||||
"""
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestBankReconciliationTool(unittest.TestCase):
|
||||
pass
|
3
erpnext/accounts/doctype/bank_statement_import/bank_statement_import.css
vendored
Normal file
3
erpnext/accounts/doctype/bank_statement_import/bank_statement_import.css
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
.warnings .warning {
|
||||
margin-bottom: 40px;
|
||||
}
|
@ -0,0 +1,574 @@
|
||||
// Copyright (c) 2019, Frappe Technologies and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on("Bank Statement Import", {
|
||||
setup(frm) {
|
||||
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
|
||||
frm.import_in_progress = false;
|
||||
if (data_import !== frm.doc.name) return;
|
||||
frappe.model.clear_doc("Bank Statement Import", frm.doc.name);
|
||||
frappe.model
|
||||
.with_doc("Bank Statement Import", frm.doc.name)
|
||||
.then(() => {
|
||||
frm.refresh();
|
||||
});
|
||||
});
|
||||
frappe.realtime.on("data_import_progress", (data) => {
|
||||
frm.import_in_progress = true;
|
||||
if (data.data_import !== frm.doc.name) {
|
||||
return;
|
||||
}
|
||||
let percent = Math.floor((data.current * 100) / data.total);
|
||||
let seconds = Math.floor(data.eta);
|
||||
let minutes = Math.floor(data.eta / 60);
|
||||
let eta_message =
|
||||
// prettier-ignore
|
||||
seconds < 60
|
||||
? __('About {0} seconds remaining', [seconds])
|
||||
: minutes === 1
|
||||
? __('About {0} minute remaining', [minutes])
|
||||
: __('About {0} minutes remaining', [minutes]);
|
||||
|
||||
let message;
|
||||
if (data.success) {
|
||||
let message_args = [data.current, data.total, eta_message];
|
||||
message =
|
||||
frm.doc.import_type === "Insert New Records"
|
||||
? __("Importing {0} of {1}, {2}", message_args)
|
||||
: __("Updating {0} of {1}, {2}", message_args);
|
||||
}
|
||||
if (data.skipping) {
|
||||
message = __(
|
||||
"Skipping {0} of {1}, {2}",
|
||||
[
|
||||
data.current,
|
||||
data.total,
|
||||
eta_message,
|
||||
]
|
||||
);
|
||||
}
|
||||
frm.dashboard.show_progress(
|
||||
__("Import Progress"),
|
||||
percent,
|
||||
message
|
||||
);
|
||||
frm.page.set_indicator(__("In Progress"), "orange");
|
||||
|
||||
// hide progress when complete
|
||||
if (data.current === data.total) {
|
||||
setTimeout(() => {
|
||||
frm.dashboard.hide();
|
||||
frm.refresh();
|
||||
}, 2000);
|
||||
}
|
||||
});
|
||||
|
||||
frm.set_query("reference_doctype", () => {
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", frappe.boot.user.can_import],
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
frm.get_field("import_file").df.options = {
|
||||
restrictions: {
|
||||
allowed_file_types: [".csv", ".xls", ".xlsx"],
|
||||
},
|
||||
};
|
||||
|
||||
frm.has_import_file = () => {
|
||||
return frm.doc.import_file || frm.doc.google_sheets_url;
|
||||
};
|
||||
},
|
||||
|
||||
refresh(frm) {
|
||||
frm.page.hide_icon_group();
|
||||
frm.trigger("update_indicators");
|
||||
frm.trigger("import_file");
|
||||
frm.trigger("show_import_log");
|
||||
frm.trigger("show_import_warnings");
|
||||
frm.trigger("toggle_submit_after_import");
|
||||
frm.trigger("show_import_status");
|
||||
frm.trigger("show_report_error_button");
|
||||
|
||||
if (frm.doc.status === "Partial Success") {
|
||||
frm.add_custom_button(__("Export Errored Rows"), () =>
|
||||
frm.trigger("export_errored_rows")
|
||||
);
|
||||
}
|
||||
|
||||
if (frm.doc.status.includes("Success")) {
|
||||
frm.add_custom_button(
|
||||
__("Go to {0} List", [frm.doc.reference_doctype]),
|
||||
() => frappe.set_route("List", frm.doc.reference_doctype)
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
onload_post_render(frm) {
|
||||
frm.trigger("update_primary_action");
|
||||
},
|
||||
|
||||
update_primary_action(frm) {
|
||||
if (frm.is_dirty()) {
|
||||
frm.enable_save();
|
||||
return;
|
||||
}
|
||||
frm.disable_save();
|
||||
if (frm.doc.status !== "Success") {
|
||||
if (!frm.is_new() && frm.has_import_file()) {
|
||||
let label =
|
||||
frm.doc.status === "Pending"
|
||||
? __("Start Import")
|
||||
: __("Retry");
|
||||
frm.page.set_primary_action(label, () =>
|
||||
frm.events.start_import(frm)
|
||||
);
|
||||
} else {
|
||||
frm.page.set_primary_action(__("Save"), () => frm.save());
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
update_indicators(frm) {
|
||||
const indicator = frappe.get_indicator(frm.doc);
|
||||
if (indicator) {
|
||||
frm.page.set_indicator(indicator[0], indicator[1]);
|
||||
} else {
|
||||
frm.page.clear_indicator();
|
||||
}
|
||||
},
|
||||
|
||||
show_import_status(frm) {
|
||||
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;
|
||||
|
||||
let message;
|
||||
if (failed_records.length === 0) {
|
||||
let message_args = [successful_records.length];
|
||||
if (frm.doc.import_type === "Insert New Records") {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __("Successfully imported {0} records.", message_args)
|
||||
: __("Successfully imported {0} record.", message_args);
|
||||
} else {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __("Successfully updated {0} records.", message_args)
|
||||
: __("Successfully updated {0} record.", message_args);
|
||||
}
|
||||
} else {
|
||||
let message_args = [successful_records.length, import_log.length];
|
||||
if (frm.doc.import_type === "Insert New Records") {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __(
|
||||
"Successfully imported {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
: __(
|
||||
"Successfully imported {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
} else {
|
||||
message =
|
||||
successful_records.length > 1
|
||||
? __(
|
||||
"Successfully updated {0} records out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
)
|
||||
: __(
|
||||
"Successfully updated {0} record out of {1}. Click on Export Errored Rows, fix the errors and import again.",
|
||||
message_args
|
||||
);
|
||||
}
|
||||
}
|
||||
frm.dashboard.set_headline(message);
|
||||
},
|
||||
|
||||
show_report_error_button(frm) {
|
||||
if (frm.doc.status === "Error") {
|
||||
frappe.db
|
||||
.get_list("Error Log", {
|
||||
filters: { method: frm.doc.name },
|
||||
fields: ["method", "error"],
|
||||
order_by: "creation desc",
|
||||
limit: 1,
|
||||
})
|
||||
.then((result) => {
|
||||
if (result.length > 0) {
|
||||
frm.add_custom_button("Report Error", () => {
|
||||
let fake_xhr = {
|
||||
responseText: JSON.stringify({
|
||||
exc: result[0].error,
|
||||
}),
|
||||
};
|
||||
frappe.request.report_error(fake_xhr, {});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
start_import(frm) {
|
||||
frm.call({
|
||||
method: "form_start_import",
|
||||
args: { data_import: frm.doc.name },
|
||||
btn: frm.page.btn_primary,
|
||||
}).then((r) => {
|
||||
if (r.message === true) {
|
||||
frm.disable_save();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
download_template() {
|
||||
let method =
|
||||
"/api/method/frappe.core.doctype.data_import.data_import.download_template";
|
||||
|
||||
open_url_post(method, {
|
||||
doctype: "Bank Transaction",
|
||||
export_records: "5_records",
|
||||
export_fields: {
|
||||
"Bank Transaction": [
|
||||
"date",
|
||||
"deposit",
|
||||
"withdrawal",
|
||||
"description",
|
||||
"reference_number",
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
reference_doctype(frm) {
|
||||
frm.trigger("toggle_submit_after_import");
|
||||
},
|
||||
|
||||
toggle_submit_after_import(frm) {
|
||||
frm.toggle_display("submit_after_import", false);
|
||||
let doctype = frm.doc.reference_doctype;
|
||||
if (doctype) {
|
||||
frappe.model.with_doctype(doctype, () => {
|
||||
let meta = frappe.get_meta(doctype);
|
||||
frm.toggle_display("submit_after_import", meta.is_submittable);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
google_sheets_url(frm) {
|
||||
if (!frm.is_dirty()) {
|
||||
frm.trigger("import_file");
|
||||
} else {
|
||||
frm.trigger("update_primary_action");
|
||||
}
|
||||
},
|
||||
|
||||
refresh_google_sheet(frm) {
|
||||
frm.trigger("import_file");
|
||||
},
|
||||
|
||||
import_file(frm) {
|
||||
frm.toggle_display("section_import_preview", frm.has_import_file());
|
||||
if (!frm.has_import_file()) {
|
||||
frm.get_field("import_preview").$wrapper.empty();
|
||||
return;
|
||||
} else {
|
||||
frm.trigger("update_primary_action");
|
||||
}
|
||||
|
||||
// load import preview
|
||||
frm.get_field("import_preview").$wrapper.empty();
|
||||
$('<span class="text-muted">')
|
||||
.html(__("Loading import file..."))
|
||||
.appendTo(frm.get_field("import_preview").$wrapper);
|
||||
|
||||
frm.call({
|
||||
method: "get_preview_from_template",
|
||||
args: {
|
||||
data_import: frm.doc.name,
|
||||
import_file: frm.doc.import_file,
|
||||
google_sheets_url: frm.doc.google_sheets_url,
|
||||
},
|
||||
error_handlers: {
|
||||
TimestampMismatchError() {
|
||||
// ignore this error
|
||||
},
|
||||
},
|
||||
}).then((r) => {
|
||||
let preview_data = r.message;
|
||||
frm.events.show_import_preview(frm, preview_data);
|
||||
frm.events.show_import_warnings(frm, preview_data);
|
||||
});
|
||||
},
|
||||
// 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.import_log || "[]");
|
||||
|
||||
if (
|
||||
frm.import_preview &&
|
||||
frm.import_preview.doctype === frm.doc.reference_doctype
|
||||
) {
|
||||
frm.import_preview.preview_data = preview_data;
|
||||
frm.import_preview.import_log = import_log;
|
||||
frm.import_preview.refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
frappe.require("/assets/js/data_import_tools.min.js", () => {
|
||||
frm.import_preview = new frappe.data_import.ImportPreview({
|
||||
wrapper: frm.get_field("import_preview").$wrapper,
|
||||
doctype: frm.doc.reference_doctype,
|
||||
preview_data,
|
||||
import_log,
|
||||
frm,
|
||||
events: {
|
||||
remap_column(changed_map) {
|
||||
let template_options = JSON.parse(
|
||||
frm.doc.template_options || "{}"
|
||||
);
|
||||
template_options.column_to_field_map =
|
||||
template_options.column_to_field_map || {};
|
||||
Object.assign(
|
||||
template_options.column_to_field_map,
|
||||
changed_map
|
||||
);
|
||||
frm.set_value(
|
||||
"template_options",
|
||||
JSON.stringify(template_options)
|
||||
);
|
||||
frm.save().then(() => frm.trigger("import_file"));
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
export_errored_rows(frm) {
|
||||
open_url_post(
|
||||
"/api/method/frappe.core.doctype.data_import.data_import.download_errored_template",
|
||||
{
|
||||
data_import_name: frm.doc.name,
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
show_import_warnings(frm, preview_data) {
|
||||
let columns = preview_data.columns;
|
||||
let warnings = JSON.parse(frm.doc.template_warnings || "[]");
|
||||
warnings = warnings.concat(preview_data.warnings || []);
|
||||
|
||||
frm.toggle_display("import_warnings_section", warnings.length > 0);
|
||||
if (warnings.length === 0) {
|
||||
frm.get_field("import_warnings").$wrapper.html("");
|
||||
return;
|
||||
}
|
||||
|
||||
// group warnings by row
|
||||
let warnings_by_row = {};
|
||||
let other_warnings = [];
|
||||
for (let warning of warnings) {
|
||||
if (warning.row) {
|
||||
warnings_by_row[warning.row] =
|
||||
warnings_by_row[warning.row] || [];
|
||||
warnings_by_row[warning.row].push(warning);
|
||||
} else {
|
||||
other_warnings.push(warning);
|
||||
}
|
||||
}
|
||||
|
||||
let html = "";
|
||||
html += Object.keys(warnings_by_row)
|
||||
.map((row_number) => {
|
||||
let message = warnings_by_row[row_number]
|
||||
.map((w) => {
|
||||
if (w.field) {
|
||||
let label =
|
||||
w.field.label +
|
||||
(w.field.parent !== frm.doc.reference_doctype
|
||||
? ` (${w.field.parent})`
|
||||
: "");
|
||||
return `<li>${label}: ${w.message}</li>`;
|
||||
}
|
||||
return `<li>${w.message}</li>`;
|
||||
})
|
||||
.join("");
|
||||
return `
|
||||
<div class="warning" data-row="${row_number}">
|
||||
<h5 class="text-uppercase">${__("Row {0}", [row_number])}</h5>
|
||||
<div class="body"><ul>${message}</ul></div>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
html += other_warnings
|
||||
.map((warning) => {
|
||||
let header = "";
|
||||
if (warning.col) {
|
||||
let column_number = `<span class="text-uppercase">${__(
|
||||
"Column {0}",
|
||||
[warning.col]
|
||||
)}</span>`;
|
||||
let column_header = columns[warning.col].header_title;
|
||||
header = `${column_number} (${column_header})`;
|
||||
}
|
||||
return `
|
||||
<div class="warning" data-col="${warning.col}">
|
||||
<h5>${header}</h5>
|
||||
<div class="body">${warning.message}</div>
|
||||
</div>
|
||||
`;
|
||||
})
|
||||
.join("");
|
||||
frm.get_field("import_warnings").$wrapper.html(`
|
||||
<div class="row">
|
||||
<div class="col-sm-10 warnings">${html}</div>
|
||||
</div>
|
||||
`);
|
||||
},
|
||||
|
||||
show_failed_logs(frm) {
|
||||
frm.trigger("show_import_log");
|
||||
},
|
||||
|
||||
show_import_log(frm) {
|
||||
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);
|
||||
|
||||
if (logs.length === 0) {
|
||||
frm.get_field("import_log_preview").$wrapper.empty();
|
||||
return;
|
||||
}
|
||||
|
||||
let rows = logs
|
||||
.map((log) => {
|
||||
let html = "";
|
||||
if (log.success) {
|
||||
if (frm.doc.import_type === "Insert New Records") {
|
||||
html = __(
|
||||
"Successfully imported {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]
|
||||
);
|
||||
} else {
|
||||
html = __(
|
||||
"Successfully updated {0}", [
|
||||
`<span class="underline">${frappe.utils.get_form_link(
|
||||
frm.doc.reference_doctype,
|
||||
log.docname,
|
||||
true
|
||||
)}<span>`,
|
||||
]
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let messages = log.messages
|
||||
.map(JSON.parse)
|
||||
.map((m) => {
|
||||
let title = m.title
|
||||
? `<strong>${m.title}</strong>`
|
||||
: "";
|
||||
let message = m.message
|
||||
? `<div>${m.message}</div>`
|
||||
: "";
|
||||
return title + message;
|
||||
})
|
||||
.join("");
|
||||
let id = frappe.dom.get_unique_id();
|
||||
html = `${messages}
|
||||
<button class="btn btn-default btn-xs" type="button" data-toggle="collapse" data-target="#${id}" aria-expanded="false" aria-controls="${id}" style="margin-top: 15px;">
|
||||
${__("Show Traceback")}
|
||||
</button>
|
||||
<div class="collapse" id="${id}" style="margin-top: 15px;">
|
||||
<div class="well">
|
||||
<pre>${log.exception}</pre>
|
||||
</div>
|
||||
</div>`;
|
||||
}
|
||||
let indicator_color = log.success ? "green" : "red";
|
||||
let title = log.success ? __("Success") : __("Failure");
|
||||
|
||||
if (frm.doc.show_failed_logs && log.success) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return `<tr>
|
||||
<td>${log.row_indexes.join(", ")}</td>
|
||||
<td>
|
||||
<div class="indicator ${indicator_color}">${title}</div>
|
||||
</td>
|
||||
<td>
|
||||
${html}
|
||||
</td>
|
||||
</tr>`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
if (!rows && frm.doc.show_failed_logs) {
|
||||
rows = `<tr><td class="text-center text-muted" colspan=3>
|
||||
${__("No failed logs")}
|
||||
</td></tr>`;
|
||||
}
|
||||
|
||||
frm.get_field("import_log_preview").$wrapper.html(`
|
||||
<table class="table table-bordered">
|
||||
<tr class="text-muted">
|
||||
<th width="10%">${__("Row Number")}</th>
|
||||
<th width="10%">${__("Status")}</th>
|
||||
<th width="80%">${__("Message")}</th>
|
||||
</tr>
|
||||
${rows}
|
||||
</table>
|
||||
`);
|
||||
},
|
||||
|
||||
show_missing_link_values(frm, missing_link_values) {
|
||||
let can_be_created_automatically = missing_link_values.every(
|
||||
(d) => d.has_one_mandatory_field
|
||||
);
|
||||
|
||||
let html = missing_link_values
|
||||
.map((d) => {
|
||||
let doctype = d.doctype;
|
||||
let values = d.missing_values;
|
||||
return `
|
||||
<h5>${doctype}</h5>
|
||||
<ul>${values.map((v) => `<li>${v}</li>`).join("")}</ul>
|
||||
`;
|
||||
})
|
||||
.join("");
|
||||
|
||||
if (can_be_created_automatically) {
|
||||
// prettier-ignore
|
||||
let message = __('There are some linked records which needs to be created before we can import your file. Do you want to create the following missing records automatically?');
|
||||
frappe.confirm(message + html, () => {
|
||||
frm.call("create_missing_link_values", {
|
||||
missing_link_values,
|
||||
}).then((r) => {
|
||||
let records = r.message;
|
||||
frappe.msgprint(__(
|
||||
"Created {0} records successfully.", [
|
||||
records.length,
|
||||
]
|
||||
));
|
||||
});
|
||||
});
|
||||
} else {
|
||||
frappe.msgprint(
|
||||
// prettier-ignore
|
||||
__('The following records needs to be created before we can import your file.') + html
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
@ -0,0 +1,227 @@
|
||||
{
|
||||
"actions": [],
|
||||
"autoname": "format:Bank Statement Import on {creation}",
|
||||
"beta": 1,
|
||||
"creation": "2019-08-04 14:16:08.318714",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"company",
|
||||
"bank_account",
|
||||
"bank",
|
||||
"column_break_4",
|
||||
"google_sheets_url",
|
||||
"refresh_google_sheet",
|
||||
"html_5",
|
||||
"import_file",
|
||||
"download_template",
|
||||
"status",
|
||||
"template_options",
|
||||
"import_warnings_section",
|
||||
"template_warnings",
|
||||
"import_warnings",
|
||||
"section_import_preview",
|
||||
"import_preview",
|
||||
"import_log_section",
|
||||
"import_log",
|
||||
"show_failed_logs",
|
||||
"import_log_preview",
|
||||
"reference_doctype",
|
||||
"import_type",
|
||||
"submit_after_import",
|
||||
"mute_emails"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "bank_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Bank Account",
|
||||
"options": "Bank Account",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.bank_account",
|
||||
"fetch_from": "bank_account.bank",
|
||||
"fieldname": "bank",
|
||||
"fieldtype": "Link",
|
||||
"label": "Bank",
|
||||
"options": "Bank",
|
||||
"read_only": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "download_template",
|
||||
"fieldtype": "Button",
|
||||
"label": "Download Template"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal",
|
||||
"fieldname": "import_file",
|
||||
"fieldtype": "Attach",
|
||||
"in_list_view": 1,
|
||||
"label": "Import File"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_preview",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Import Preview"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_import_preview",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Preview"
|
||||
},
|
||||
{
|
||||
"fieldname": "template_options",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 1,
|
||||
"label": "Template Options",
|
||||
"options": "JSON",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "import_log",
|
||||
"fieldtype": "Code",
|
||||
"label": "Import Log",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_log_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Import Log"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_log_preview",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Import Log Preview"
|
||||
},
|
||||
{
|
||||
"default": "Pending",
|
||||
"fieldname": "status",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"label": "Status",
|
||||
"options": "Pending\nSuccess\nPartial Success\nError",
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "template_warnings",
|
||||
"fieldtype": "Code",
|
||||
"hidden": 1,
|
||||
"label": "Template Warnings",
|
||||
"options": "JSON"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_warnings_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Import File Errors and Warnings"
|
||||
},
|
||||
{
|
||||
"fieldname": "import_warnings",
|
||||
"fieldtype": "HTML",
|
||||
"label": "Import Warnings"
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"fieldname": "show_failed_logs",
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Failed Logs"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal && !doc.import_file",
|
||||
"fieldname": "html_5",
|
||||
"fieldtype": "HTML",
|
||||
"options": "<h5 class=\"text-muted uppercase\">Or</h5>"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:!doc.__islocal && !doc.import_file\n",
|
||||
"description": "Must be a publicly accessible Google Sheets URL",
|
||||
"fieldname": "google_sheets_url",
|
||||
"fieldtype": "Data",
|
||||
"label": "Import from Google Sheets"
|
||||
},
|
||||
{
|
||||
"depends_on": "eval:doc.google_sheets_url && !doc.__unsaved",
|
||||
"fieldname": "refresh_google_sheet",
|
||||
"fieldtype": "Button",
|
||||
"label": "Refresh Google Sheet"
|
||||
},
|
||||
{
|
||||
"default": "Bank Transaction",
|
||||
"fieldname": "reference_doctype",
|
||||
"fieldtype": "Link",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Document Type",
|
||||
"options": "DocType",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"default": "Insert New Records",
|
||||
"fieldname": "import_type",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"in_list_view": 1,
|
||||
"label": "Import Type",
|
||||
"options": "\nInsert New Records\nUpdate Existing Records",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "submit_after_import",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Submit After Import",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"default": "1",
|
||||
"fieldname": "mute_emails",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Don't Send Emails",
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_4",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"hide_toolbar": 1,
|
||||
"links": [],
|
||||
"modified": "2021-02-10 19:29:59.027325",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Import",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1
|
||||
}
|
@ -0,0 +1,205 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2019, Frappe Technologies and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import csv
|
||||
import json
|
||||
import re
|
||||
|
||||
import openpyxl
|
||||
from openpyxl.styles import Font
|
||||
from openpyxl.utils import get_column_letter
|
||||
from six import string_types
|
||||
|
||||
import frappe
|
||||
from frappe.core.doctype.data_import.importer import Importer, ImportFile
|
||||
from frappe.utils.background_jobs import enqueue
|
||||
from frappe.utils.xlsxutils import handle_html, ILLEGAL_CHARACTERS_RE
|
||||
from frappe import _
|
||||
|
||||
from frappe.core.doctype.data_import.data_import import DataImport
|
||||
|
||||
class BankStatementImport(DataImport):
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(BankStatementImport, self).__init__(*args, **kwargs)
|
||||
|
||||
def validate(self):
|
||||
doc_before_save = self.get_doc_before_save()
|
||||
if (
|
||||
not (self.import_file or self.google_sheets_url)
|
||||
or (doc_before_save and doc_before_save.import_file != self.import_file)
|
||||
or (doc_before_save and doc_before_save.google_sheets_url != self.google_sheets_url)
|
||||
):
|
||||
|
||||
template_options_dict = {}
|
||||
column_to_field_map = {}
|
||||
bank = frappe.get_doc("Bank", self.bank)
|
||||
for i in bank.bank_transaction_mapping:
|
||||
column_to_field_map[i.file_field] = i.bank_transaction_field
|
||||
template_options_dict["column_to_field_map"] = column_to_field_map
|
||||
self.template_options = json.dumps(template_options_dict)
|
||||
|
||||
self.template_warnings = ""
|
||||
|
||||
self.validate_import_file()
|
||||
self.validate_google_sheets_url()
|
||||
|
||||
def start_import(self):
|
||||
|
||||
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")
|
||||
)
|
||||
|
||||
enqueued_jobs = [d.get("job_name") for d in get_info()]
|
||||
|
||||
if self.name not in enqueued_jobs:
|
||||
enqueue(
|
||||
start_import,
|
||||
queue="default",
|
||||
timeout=6000,
|
||||
event="data_import",
|
||||
job_name=self.name,
|
||||
data_import=self.name,
|
||||
bank_account=self.bank_account,
|
||||
import_file_path=self.import_file,
|
||||
bank=self.bank,
|
||||
template_options=self.template_options,
|
||||
now=frappe.conf.developer_mode or frappe.flags.in_test,
|
||||
)
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_preview_from_template(data_import, import_file=None, google_sheets_url=None):
|
||||
return frappe.get_doc("Bank Statement Import", data_import).get_preview_from_template(
|
||||
import_file, google_sheets_url
|
||||
)
|
||||
|
||||
@frappe.whitelist()
|
||||
def form_start_import(data_import):
|
||||
return frappe.get_doc("Bank Statement Import", data_import).start_import()
|
||||
|
||||
@frappe.whitelist()
|
||||
def download_errored_template(data_import_name):
|
||||
data_import = frappe.get_doc("Bank Statement Import", data_import_name)
|
||||
data_import.export_errored_rows()
|
||||
|
||||
def start_import(data_import, bank_account, import_file_path, bank, template_options):
|
||||
"""This method runs in background job"""
|
||||
|
||||
update_mapping_db(bank, template_options)
|
||||
|
||||
data_import = frappe.get_doc("Bank Statement Import", data_import)
|
||||
|
||||
import_file = ImportFile("Bank Transaction", file = import_file_path, import_type="Insert New Records")
|
||||
data = import_file.raw_data
|
||||
|
||||
add_bank_account(data, bank_account)
|
||||
write_files(import_file, data)
|
||||
|
||||
try:
|
||||
i = Importer(data_import.reference_doctype, data_import=data_import)
|
||||
i.import_data()
|
||||
except Exception:
|
||||
frappe.db.rollback()
|
||||
data_import.db_set("status", "Error")
|
||||
frappe.log_error(title=data_import.name)
|
||||
finally:
|
||||
frappe.flags.in_import = False
|
||||
|
||||
frappe.publish_realtime("data_import_refresh", {"data_import": data_import.name})
|
||||
|
||||
def update_mapping_db(bank, template_options):
|
||||
bank = frappe.get_doc("Bank", bank)
|
||||
for d in bank.bank_transaction_mapping:
|
||||
d.delete()
|
||||
|
||||
for d in json.loads(template_options)["column_to_field_map"].items():
|
||||
bank.append("bank_transaction_mapping", {"bank_transaction_field": d[1] ,"file_field": d[0]} )
|
||||
|
||||
bank.save()
|
||||
|
||||
def add_bank_account(data, bank_account):
|
||||
bank_account_loc = None
|
||||
if "Bank Account" not in data[0]:
|
||||
data[0].append("Bank Account")
|
||||
else:
|
||||
for loc, header in enumerate(data[0]):
|
||||
if header == "Bank Account":
|
||||
bank_account_loc = loc
|
||||
|
||||
for row in data[1:]:
|
||||
if bank_account_loc:
|
||||
row[bank_account_loc] = bank_account
|
||||
else:
|
||||
row.append(bank_account)
|
||||
|
||||
def write_files(import_file, data):
|
||||
full_file_path = import_file.file_doc.get_full_path()
|
||||
parts = import_file.file_doc.get_extension()
|
||||
extension = parts[1]
|
||||
extension = extension.lstrip(".")
|
||||
|
||||
if extension == "csv":
|
||||
with open(full_file_path, 'w', newline='') as file:
|
||||
writer = csv.writer(file)
|
||||
writer.writerows(data)
|
||||
elif extension == "xlsx" or "xls":
|
||||
write_xlsx(data, "trans", file_path = full_file_path)
|
||||
|
||||
def write_xlsx(data, sheet_name, wb=None, column_widths=None, file_path=None):
|
||||
# from xlsx utils with changes
|
||||
column_widths = column_widths or []
|
||||
if wb is None:
|
||||
wb = openpyxl.Workbook(write_only=True)
|
||||
|
||||
ws = wb.create_sheet(sheet_name, 0)
|
||||
|
||||
for i, column_width in enumerate(column_widths):
|
||||
if column_width:
|
||||
ws.column_dimensions[get_column_letter(i + 1)].width = column_width
|
||||
|
||||
row1 = ws.row_dimensions[1]
|
||||
row1.font = Font(name='Calibri', bold=True)
|
||||
|
||||
for row in data:
|
||||
clean_row = []
|
||||
for item in row:
|
||||
if isinstance(item, string_types) and (sheet_name not in ['Data Import Template', 'Data Export']):
|
||||
value = handle_html(item)
|
||||
else:
|
||||
value = item
|
||||
|
||||
if isinstance(item, string_types) and next(ILLEGAL_CHARACTERS_RE.finditer(value), None):
|
||||
# Remove illegal characters from the string
|
||||
value = re.sub(ILLEGAL_CHARACTERS_RE, '', value)
|
||||
|
||||
clean_row.append(value)
|
||||
|
||||
ws.append(clean_row)
|
||||
|
||||
wb.save(file_path)
|
||||
return True
|
||||
|
||||
@frappe.whitelist()
|
||||
def upload_bank_statement(**args):
|
||||
args = frappe._dict(args)
|
||||
bsi = frappe.new_doc("Bank Statement Import")
|
||||
|
||||
if args.company:
|
||||
bsi.update({
|
||||
"company": args.company,
|
||||
})
|
||||
|
||||
if args.bank_account:
|
||||
bsi.update({
|
||||
"bank_account": args.bank_account
|
||||
})
|
||||
|
||||
return bsi
|
@ -0,0 +1,36 @@
|
||||
let imports_in_progress = [];
|
||||
|
||||
frappe.listview_settings['Bank Statement Import'] = {
|
||||
onload(listview) {
|
||||
frappe.realtime.on('data_import_progress', data => {
|
||||
if (!imports_in_progress.includes(data.data_import)) {
|
||||
imports_in_progress.push(data.data_import);
|
||||
}
|
||||
});
|
||||
frappe.realtime.on('data_import_refresh', data => {
|
||||
imports_in_progress = imports_in_progress.filter(
|
||||
d => d !== data.data_import
|
||||
);
|
||||
listview.refresh();
|
||||
});
|
||||
},
|
||||
get_indicator: function(doc) {
|
||||
var colors = {
|
||||
'Pending': 'orange',
|
||||
'Not Started': 'orange',
|
||||
'Partial Success': 'orange',
|
||||
'Success': 'green',
|
||||
'In Progress': 'orange',
|
||||
'Error': 'red'
|
||||
};
|
||||
let status = doc.status;
|
||||
if (imports_in_progress.includes(doc.name)) {
|
||||
status = 'In Progress';
|
||||
}
|
||||
if (status == 'Pending') {
|
||||
status = 'Not Started';
|
||||
}
|
||||
return [__(status), colors[status], 'status,=,' + doc.status];
|
||||
},
|
||||
hide_name_column: true
|
||||
};
|
@ -0,0 +1,10 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2020, Frappe Technologies and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
# import frappe
|
||||
import unittest
|
||||
|
||||
class TestBankStatementImport(unittest.TestCase):
|
||||
pass
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Statement Settings', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -1,272 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-13 13:38:10.863592",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank",
|
||||
"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": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "'%d/%m/%Y'",
|
||||
"fieldname": "date_format",
|
||||
"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": "Date Format",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "statement_header_mapping",
|
||||
"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": "Statement Header Mapping",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "header_items",
|
||||
"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": "Statement Headers",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Settings Item",
|
||||
"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_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "transaction_data_mapping",
|
||||
"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": "Transaction Data Mapping",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mapped_items",
|
||||
"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": "Mapped Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Transaction Settings Item",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-04-07 18:57:04.048423",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Settings",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BankStatementSettings(Document):
|
||||
def autoname(self):
|
||||
self.name = self.bank + "-Statement-Settings"
|
@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Statement Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Statement Settings
|
||||
() => frappe.tests.make('Bank Statement Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestBankStatementSettings(unittest.TestCase):
|
||||
pass
|
@ -1,101 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2018-01-08 00:16:42.762980",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mapped_header",
|
||||
"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": "Mapped Header",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "stmt_header",
|
||||
"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": "Bank Header",
|
||||
"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,
|
||||
"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,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-08 00:19:14.841134",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Settings Item",
|
||||
"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",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,100 +0,0 @@
|
||||
// Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Statement Transaction Entry', {
|
||||
setup: function(frm) {
|
||||
frm.events.account_filters(frm)
|
||||
frm.events.invoice_filter(frm)
|
||||
},
|
||||
refresh: function(frm) {
|
||||
frm.set_df_property("bank_account", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
frm.set_df_property("from_date", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
frm.set_df_property("to_date", "read_only", frm.doc.__islocal ? 0 : 1);
|
||||
},
|
||||
invoke_doc_function(frm, method) {
|
||||
frappe.call({
|
||||
doc: frm.doc,
|
||||
method: method,
|
||||
callback: function(r) {
|
||||
if(!r.exe) {
|
||||
frm.refresh_fields();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
account_filters: function(frm) {
|
||||
frm.fields_dict['bank_account'].get_query = function(doc, dt, dn) {
|
||||
return {
|
||||
filters:[
|
||||
["Account", "account_type", "in", ["Bank"]]
|
||||
]
|
||||
}
|
||||
};
|
||||
frm.fields_dict['receivable_account'].get_query = function(doc, dt, dn) {
|
||||
return {
|
||||
filters: {"account_type": "Receivable"}
|
||||
}
|
||||
};
|
||||
frm.fields_dict['payable_account'].get_query = function(doc, dt, dn) {
|
||||
return {
|
||||
filters: {"account_type": "Payable"}
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
invoice_filter: function(frm) {
|
||||
frm.set_query("invoice", "payment_invoice_items", function(doc, cdt, cdn) {
|
||||
let row = locals[cdt][cdn]
|
||||
if (row.party_type == "Customer") {
|
||||
return {
|
||||
filters:[[row.invoice_type, "customer", "in", [row.party]],
|
||||
[row.invoice_type, "status", "!=", "Cancelled" ],
|
||||
[row.invoice_type, "posting_date", "<", row.transaction_date ],
|
||||
[row.invoice_type, "outstanding_amount", ">", 0 ]]
|
||||
}
|
||||
} else if (row.party_type == "Supplier") {
|
||||
return {
|
||||
filters:[[row.invoice_type, "supplier", "in", [row.party]],
|
||||
[row.invoice_type, "status", "!=", "Cancelled" ],
|
||||
[row.invoice_type, "posting_date", "<", row.transaction_date ],
|
||||
[row.invoice_type, "outstanding_amount", ">", 0 ]]
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
match_invoices: function(frm) {
|
||||
frm.events.invoke_doc_function(frm, "populate_matching_invoices");
|
||||
},
|
||||
create_payments: function(frm) {
|
||||
frm.events.invoke_doc_function(frm, "create_payment_entries");
|
||||
},
|
||||
submit_payments: function(frm) {
|
||||
frm.events.invoke_doc_function(frm, "submit_payment_entries");
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
frappe.ui.form.on('Bank Statement Transaction Invoice Item', {
|
||||
party_type: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (row.party_type == "Customer") {
|
||||
row.invoice_type = "Sales Invoice";
|
||||
} else if (row.party_type == "Supplier") {
|
||||
row.invoice_type = "Purchase Invoice";
|
||||
} else if (row.party_type == "Account") {
|
||||
row.invoice_type = "Journal Entry";
|
||||
}
|
||||
refresh_field("invoice_type", row.name, "payment_invoice_items");
|
||||
|
||||
},
|
||||
invoice_type: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
if (row.invoice_type == "Purchase Invoice") {
|
||||
row.party_type = "Supplier";
|
||||
} else if (row.invoice_type == "Sales Invoice") {
|
||||
row.party_type = "Customer";
|
||||
}
|
||||
refresh_field("party_type", row.name, "payment_invoice_items");
|
||||
}
|
||||
});
|
@ -1,792 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-07 13:48:13.123185",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_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": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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": "from_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": "From Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "to_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": "To Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_settings",
|
||||
"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": "Bank Statement Settings",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Settings",
|
||||
"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": "column_break_3",
|
||||
"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": "bank",
|
||||
"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": "Bank",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank",
|
||||
"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": "receivable_account",
|
||||
"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": "Receivable Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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": "payable_account",
|
||||
"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": "Payable Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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": "bank_statement",
|
||||
"fieldtype": "Attach",
|
||||
"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": "Bank Statement",
|
||||
"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,
|
||||
"depends_on": "",
|
||||
"fieldname": "section_break_6",
|
||||
"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": "Bank Transaction 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": "new_transaction_items",
|
||||
"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": "New Transactions",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Transaction Payment Item",
|
||||
"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,
|
||||
"depends_on": "eval:doc.new_transaction_items && doc.new_transaction_items.length",
|
||||
"fieldname": "section_break_9",
|
||||
"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,
|
||||
"depends_on": "",
|
||||
"fieldname": "match_invoices",
|
||||
"fieldtype": "Button",
|
||||
"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": "Match Transaction to Invoices",
|
||||
"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": "column_break_14",
|
||||
"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": "create_payments",
|
||||
"fieldtype": "Button",
|
||||
"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": "Create New Payment/Journal Entry",
|
||||
"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": "column_break_16",
|
||||
"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": "submit_payments",
|
||||
"fieldtype": "Button",
|
||||
"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": "Submit/Reconcile Payments",
|
||||
"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,
|
||||
"depends_on": "eval:doc.new_transaction_items && doc.new_transaction_items.length",
|
||||
"fieldname": "section_break_18",
|
||||
"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": "Matching Invoices",
|
||||
"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": "payment_invoice_items",
|
||||
"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": "Payment Invoice Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Transaction Invoice Item",
|
||||
"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": "reconciled_transactions",
|
||||
"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": "Reconciled Transactions",
|
||||
"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": "reconciled_transaction_items",
|
||||
"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": "Reconciled Transactions",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Transaction Payment Item",
|
||||
"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": "Bank Statement Transaction Entry",
|
||||
"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,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-14 18:04:44.170455",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Transaction Entry",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 1,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 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",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,443 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from erpnext.accounts.utils import get_outstanding_invoices
|
||||
from frappe.utils import nowdate
|
||||
from datetime import datetime
|
||||
import csv, os, re, io
|
||||
import difflib
|
||||
import copy
|
||||
|
||||
class BankStatementTransactionEntry(Document):
|
||||
def autoname(self):
|
||||
self.name = self.bank_account + "-" + self.from_date + "-" + self.to_date
|
||||
if self.bank:
|
||||
mapper_name = self.bank + "-Statement-Settings"
|
||||
if not frappe.db.exists("Bank Statement Settings", mapper_name):
|
||||
self.create_settings(self.bank)
|
||||
self.bank_settings = mapper_name
|
||||
|
||||
def create_settings(self, bank):
|
||||
mapper = frappe.new_doc("Bank Statement Settings")
|
||||
mapper.bank = bank
|
||||
mapper.date_format = "%Y-%m-%d"
|
||||
mapper.bank_account = self.bank_account
|
||||
for header in ["Date", "Particulars", "Withdrawals", "Deposits", "Balance"]:
|
||||
header_item = mapper.append("header_items", {})
|
||||
header_item.mapped_header = header_item.stmt_header = header
|
||||
mapper.save()
|
||||
|
||||
def on_update(self):
|
||||
if (not self.bank_statement):
|
||||
self.reconciled_transaction_items = self.new_transaction_items = []
|
||||
return
|
||||
|
||||
if len(self.new_transaction_items + self.reconciled_transaction_items) == 0:
|
||||
self.populate_payment_entries()
|
||||
else:
|
||||
self.match_invoice_to_payment()
|
||||
|
||||
def validate(self):
|
||||
if not self.new_transaction_items:
|
||||
self.populate_payment_entries()
|
||||
|
||||
def get_statement_headers(self):
|
||||
if not self.bank_settings:
|
||||
frappe.throw(_("Bank Data mapper doesn't exist"))
|
||||
mapper_doc = frappe.get_doc("Bank Statement Settings", self.bank_settings)
|
||||
headers = {entry.mapped_header:entry.stmt_header for entry in mapper_doc.header_items}
|
||||
return headers
|
||||
|
||||
def populate_payment_entries(self):
|
||||
if self.bank_statement is None: return
|
||||
file_url = self.bank_statement
|
||||
if (len(self.new_transaction_items + self.reconciled_transaction_items) > 0):
|
||||
frappe.throw(_("Transactions already retreived from the statement"))
|
||||
|
||||
date_format = frappe.get_value("Bank Statement Settings", self.bank_settings, "date_format")
|
||||
if (date_format is None):
|
||||
date_format = '%Y-%m-%d'
|
||||
if self.bank_settings:
|
||||
mapped_items = frappe.get_doc("Bank Statement Settings", self.bank_settings).mapped_items
|
||||
statement_headers = self.get_statement_headers()
|
||||
transactions = get_transaction_entries(file_url, statement_headers)
|
||||
for entry in transactions:
|
||||
date = entry[statement_headers["Date"]].strip()
|
||||
#print("Processing entry DESC:{0}-W:{1}-D:{2}-DT:{3}".format(entry["Particulars"], entry["Withdrawals"], entry["Deposits"], entry["Date"]))
|
||||
if (not date): continue
|
||||
transaction_date = datetime.strptime(date, date_format).date()
|
||||
if (self.from_date and transaction_date < datetime.strptime(self.from_date, '%Y-%m-%d').date()): continue
|
||||
if (self.to_date and transaction_date > datetime.strptime(self.to_date, '%Y-%m-%d').date()): continue
|
||||
bank_entry = self.append('new_transaction_items', {})
|
||||
bank_entry.transaction_date = transaction_date
|
||||
bank_entry.description = entry[statement_headers["Particulars"]]
|
||||
|
||||
mapped_item = next((entry for entry in mapped_items if entry.mapping_type == "Transaction" and frappe.safe_decode(entry.bank_data.lower()) in frappe.safe_decode(bank_entry.description.lower())), None)
|
||||
if (mapped_item is not None):
|
||||
bank_entry.party_type = mapped_item.mapped_data_type
|
||||
bank_entry.party = mapped_item.mapped_data
|
||||
else:
|
||||
bank_entry.party_type = "Supplier" if not entry[statement_headers["Deposits"]].strip() else "Customer"
|
||||
party_list = frappe.get_all(bank_entry.party_type, fields=["name"])
|
||||
parties = [party.name for party in party_list]
|
||||
matches = difflib.get_close_matches(frappe.safe_decode(bank_entry.description.lower()), parties, 1, 0.4)
|
||||
if len(matches) > 0: bank_entry.party = matches[0]
|
||||
bank_entry.amount = -float(entry[statement_headers["Withdrawals"]]) if not entry[statement_headers["Deposits"]].strip() else float(entry[statement_headers["Deposits"]])
|
||||
self.map_unknown_transactions()
|
||||
self.map_transactions_on_journal_entry()
|
||||
|
||||
def map_transactions_on_journal_entry(self):
|
||||
for entry in self.new_transaction_items:
|
||||
vouchers = frappe.db.sql("""select name, posting_date from `tabJournal Entry`
|
||||
where posting_date='{0}' and total_credit={1} and cheque_no='{2}' and docstatus != 2
|
||||
""".format(entry.transaction_date, abs(entry.amount), frappe.safe_decode(entry.description)), as_dict=True)
|
||||
if (len(vouchers) == 1):
|
||||
entry.reference_name = vouchers[0].name
|
||||
|
||||
def populate_matching_invoices(self):
|
||||
self.payment_invoice_items = []
|
||||
self.map_unknown_transactions()
|
||||
added_invoices = []
|
||||
for entry in self.new_transaction_items:
|
||||
if (not entry.party or entry.party_type == "Account"): continue
|
||||
account = self.receivable_account if entry.party_type == "Customer" else self.payable_account
|
||||
invoices = get_outstanding_invoices(entry.party_type, entry.party, account)
|
||||
transaction_date = datetime.strptime(entry.transaction_date, "%Y-%m-%d").date()
|
||||
outstanding_invoices = [invoice for invoice in invoices if invoice.posting_date <= transaction_date]
|
||||
amount = abs(entry.amount)
|
||||
matching_invoices = [invoice for invoice in outstanding_invoices if invoice.outstanding_amount == amount]
|
||||
sorted(outstanding_invoices, key=lambda k: k['posting_date'])
|
||||
for e in (matching_invoices + outstanding_invoices):
|
||||
added = next((inv for inv in added_invoices if inv == e.get('voucher_no')), None)
|
||||
if (added is not None): continue
|
||||
ent = self.append('payment_invoice_items', {})
|
||||
ent.transaction_date = entry.transaction_date
|
||||
ent.payment_description = frappe.safe_decode(entry.description)
|
||||
ent.party_type = entry.party_type
|
||||
ent.party = entry.party
|
||||
ent.invoice = e.get('voucher_no')
|
||||
added_invoices += [ent.invoice]
|
||||
ent.invoice_type = "Sales Invoice" if entry.party_type == "Customer" else "Purchase Invoice"
|
||||
ent.invoice_date = e.get('posting_date')
|
||||
ent.outstanding_amount = e.get('outstanding_amount')
|
||||
ent.allocated_amount = min(float(e.get('outstanding_amount')), amount)
|
||||
amount -= float(e.get('outstanding_amount'))
|
||||
if (amount <= 5): break
|
||||
self.match_invoice_to_payment()
|
||||
self.populate_matching_vouchers()
|
||||
self.map_transactions_on_journal_entry()
|
||||
|
||||
def match_invoice_to_payment(self):
|
||||
added_payments = []
|
||||
for entry in self.new_transaction_items:
|
||||
if (not entry.party or entry.party_type == "Account"): continue
|
||||
entry.account = self.receivable_account if entry.party_type == "Customer" else self.payable_account
|
||||
amount = abs(entry.amount)
|
||||
payment, matching_invoices = None, []
|
||||
for inv_entry in self.payment_invoice_items:
|
||||
if (inv_entry.payment_description != frappe.safe_decode(entry.description) or inv_entry.transaction_date != entry.transaction_date): continue
|
||||
if (inv_entry.party != entry.party): continue
|
||||
matching_invoices += [inv_entry.invoice_type + "|" + inv_entry.invoice]
|
||||
payment = get_payments_matching_invoice(inv_entry.invoice, entry.amount, entry.transaction_date)
|
||||
doc = frappe.get_doc(inv_entry.invoice_type, inv_entry.invoice)
|
||||
inv_entry.invoice_date = doc.posting_date
|
||||
inv_entry.outstanding_amount = doc.outstanding_amount
|
||||
inv_entry.allocated_amount = min(float(doc.outstanding_amount), amount)
|
||||
amount -= inv_entry.allocated_amount
|
||||
if (amount < 0): break
|
||||
|
||||
amount = abs(entry.amount)
|
||||
if (payment is None):
|
||||
order_doctype = "Sales Order" if entry.party_type=="Customer" else "Purchase Order"
|
||||
from erpnext.controllers.accounts_controller import get_advance_payment_entries
|
||||
payment_entries = get_advance_payment_entries(entry.party_type, entry.party, entry.account, order_doctype, against_all_orders=True)
|
||||
payment_entries += self.get_matching_payments(entry.party, amount, entry.transaction_date)
|
||||
payment = next((payment for payment in payment_entries if payment.amount == amount and payment not in added_payments), None)
|
||||
if (payment is None):
|
||||
print("Failed to find payments for {0}:{1}".format(entry.party, amount))
|
||||
continue
|
||||
added_payments += [payment]
|
||||
entry.reference_type = payment.reference_type
|
||||
entry.reference_name = payment.reference_name
|
||||
entry.mode_of_payment = "Wire Transfer"
|
||||
entry.outstanding_amount = min(amount, 0)
|
||||
if (entry.payment_reference is None):
|
||||
entry.payment_reference = frappe.safe_decode(entry.description)
|
||||
entry.invoices = ",".join(matching_invoices)
|
||||
#print("Matching payment is {0}:{1}".format(entry.reference_type, entry.reference_name))
|
||||
|
||||
def get_matching_payments(self, party, amount, pay_date):
|
||||
query = """select 'Payment Entry' as reference_type, name as reference_name, paid_amount as amount
|
||||
from `tabPayment Entry` where party='{0}' and paid_amount={1} and posting_date='{2}' and docstatus != 2
|
||||
""".format(party, amount, pay_date)
|
||||
matching_payments = frappe.db.sql(query, as_dict=True)
|
||||
return matching_payments
|
||||
|
||||
def map_unknown_transactions(self):
|
||||
for entry in self.new_transaction_items:
|
||||
if (entry.party): continue
|
||||
inv_type = "Sales Invoice" if (entry.amount > 0) else "Purchase Invoice"
|
||||
party_type = "customer" if (entry.amount > 0) else "supplier"
|
||||
|
||||
query = """select posting_date, name, {0}, outstanding_amount
|
||||
from `tab{1}` where ROUND(outstanding_amount)={2} and posting_date < '{3}'
|
||||
""".format(party_type, inv_type, round(abs(entry.amount)), entry.transaction_date)
|
||||
invoices = frappe.db.sql(query, as_dict = True)
|
||||
if(len(invoices) > 0):
|
||||
entry.party = invoices[0].get(party_type)
|
||||
|
||||
def populate_matching_vouchers(self):
|
||||
for entry in self.new_transaction_items:
|
||||
if (not entry.party or entry.reference_name): continue
|
||||
print("Finding matching voucher for {0}".format(frappe.safe_decode(entry.description)))
|
||||
amount = abs(entry.amount)
|
||||
invoices = []
|
||||
vouchers = get_matching_journal_entries(self.from_date, self.to_date, entry.party, self.bank_account, amount)
|
||||
if len(vouchers) == 0: continue
|
||||
for voucher in vouchers:
|
||||
added = next((entry.invoice for entry in self.payment_invoice_items if entry.invoice == voucher.voucher_no), None)
|
||||
if (added):
|
||||
print("Found voucher {0}".format(added))
|
||||
continue
|
||||
print("Adding voucher {0} {1} {2}".format(voucher.voucher_no, voucher.posting_date, voucher.debit))
|
||||
ent = self.append('payment_invoice_items', {})
|
||||
ent.invoice_date = voucher.posting_date
|
||||
ent.invoice_type = "Journal Entry"
|
||||
ent.invoice = voucher.voucher_no
|
||||
ent.payment_description = frappe.safe_decode(entry.description)
|
||||
ent.allocated_amount = max(voucher.debit, voucher.credit)
|
||||
|
||||
invoices += [ent.invoice_type + "|" + ent.invoice]
|
||||
entry.reference_type = "Journal Entry"
|
||||
entry.mode_of_payment = "Wire Transfer"
|
||||
entry.reference_name = ent.invoice
|
||||
#entry.account = entry.party
|
||||
entry.invoices = ",".join(invoices)
|
||||
break
|
||||
|
||||
|
||||
def create_payment_entries(self):
|
||||
for payment_entry in self.new_transaction_items:
|
||||
if (not payment_entry.party): continue
|
||||
if (payment_entry.reference_name): continue
|
||||
print("Creating payment entry for {0}".format(frappe.safe_decode(payment_entry.description)))
|
||||
if (payment_entry.party_type == "Account"):
|
||||
payment = self.create_journal_entry(payment_entry)
|
||||
invoices = [payment.doctype + "|" + payment.name]
|
||||
payment_entry.invoices = ",".join(invoices)
|
||||
else:
|
||||
payment = self.create_payment_entry(payment_entry)
|
||||
invoices = [entry.reference_doctype + "|" + entry.reference_name for entry in payment.references if entry is not None]
|
||||
payment_entry.invoices = ",".join(invoices)
|
||||
payment_entry.mode_of_payment = payment.mode_of_payment
|
||||
payment_entry.account = self.receivable_account if payment_entry.party_type == "Customer" else self.payable_account
|
||||
payment_entry.reference_name = payment.name
|
||||
payment_entry.reference_type = payment.doctype
|
||||
frappe.msgprint(_("Successfully created payment entries"))
|
||||
|
||||
def create_payment_entry(self, pe):
|
||||
payment = frappe.new_doc("Payment Entry")
|
||||
payment.posting_date = pe.transaction_date
|
||||
payment.payment_type = "Receive" if pe.party_type == "Customer" else "Pay"
|
||||
payment.mode_of_payment = "Wire Transfer"
|
||||
payment.party_type = pe.party_type
|
||||
payment.party = pe.party
|
||||
payment.paid_to = self.bank_account if pe.party_type == "Customer" else self.payable_account
|
||||
payment.paid_from = self.receivable_account if pe.party_type == "Customer" else self.bank_account
|
||||
payment.paid_amount = payment.received_amount = abs(pe.amount)
|
||||
payment.reference_no = pe.description
|
||||
payment.reference_date = pe.transaction_date
|
||||
payment.save()
|
||||
for inv_entry in self.payment_invoice_items:
|
||||
if (pe.description != inv_entry.payment_description or pe.transaction_date != inv_entry.transaction_date): continue
|
||||
if (pe.party != inv_entry.party): continue
|
||||
reference = payment.append("references", {})
|
||||
reference.reference_doctype = inv_entry.invoice_type
|
||||
reference.reference_name = inv_entry.invoice
|
||||
reference.allocated_amount = inv_entry.allocated_amount
|
||||
print ("Adding invoice {0} {1}".format(reference.reference_name, reference.allocated_amount))
|
||||
payment.setup_party_account_field()
|
||||
payment.set_missing_values()
|
||||
#payment.set_exchange_rate()
|
||||
#payment.set_amounts()
|
||||
#print("Created payment entry {0}".format(payment.as_dict()))
|
||||
payment.save()
|
||||
return payment
|
||||
|
||||
def create_journal_entry(self, pe):
|
||||
je = frappe.new_doc("Journal Entry")
|
||||
je.is_opening = "No"
|
||||
je.voucher_type = "Bank Entry"
|
||||
je.cheque_no = pe.description
|
||||
je.cheque_date = pe.transaction_date
|
||||
je.remark = pe.description
|
||||
je.posting_date = pe.transaction_date
|
||||
if (pe.amount < 0):
|
||||
je.append("accounts", {"account": pe.party, "debit_in_account_currency": abs(pe.amount)})
|
||||
je.append("accounts", {"account": self.bank_account, "credit_in_account_currency": abs(pe.amount)})
|
||||
else:
|
||||
je.append("accounts", {"account": pe.party, "credit_in_account_currency": pe.amount})
|
||||
je.append("accounts", {"account": self.bank_account, "debit_in_account_currency": pe.amount})
|
||||
je.save()
|
||||
return je
|
||||
|
||||
def update_payment_entry(self, payment):
|
||||
lst = []
|
||||
invoices = payment.invoices.strip().split(',')
|
||||
if (len(invoices) == 0): return
|
||||
amount = float(abs(payment.amount))
|
||||
for invoice_entry in invoices:
|
||||
if (not invoice_entry.strip()): continue
|
||||
invs = invoice_entry.split('|')
|
||||
invoice_type, invoice = invs[0], invs[1]
|
||||
outstanding_amount = frappe.get_value(invoice_type, invoice, 'outstanding_amount')
|
||||
|
||||
lst.append(frappe._dict({
|
||||
'voucher_type': payment.reference_type,
|
||||
'voucher_no' : payment.reference_name,
|
||||
'against_voucher_type' : invoice_type,
|
||||
'against_voucher' : invoice,
|
||||
'account' : payment.account,
|
||||
'party_type': payment.party_type,
|
||||
'party': frappe.get_value("Payment Entry", payment.reference_name, "party"),
|
||||
'unadjusted_amount' : float(amount),
|
||||
'allocated_amount' : min(outstanding_amount, amount)
|
||||
}))
|
||||
amount -= outstanding_amount
|
||||
if lst:
|
||||
from erpnext.accounts.utils import reconcile_against_document
|
||||
try:
|
||||
reconcile_against_document(lst)
|
||||
except:
|
||||
frappe.throw(_("Exception occurred while reconciling {0}").format(payment.reference_name))
|
||||
|
||||
def submit_payment_entries(self):
|
||||
for payment in self.new_transaction_items:
|
||||
if payment.reference_name is None: continue
|
||||
doc = frappe.get_doc(payment.reference_type, payment.reference_name)
|
||||
if doc.docstatus == 1:
|
||||
if (payment.reference_type == "Journal Entry"): continue
|
||||
if doc.unallocated_amount == 0: continue
|
||||
print("Reconciling payment {0}".format(payment.reference_name))
|
||||
self.update_payment_entry(payment)
|
||||
else:
|
||||
print("Submitting payment {0}".format(payment.reference_name))
|
||||
if (payment.reference_type == "Payment Entry"):
|
||||
if (payment.payment_reference):
|
||||
doc.reference_no = payment.payment_reference
|
||||
doc.mode_of_payment = payment.mode_of_payment
|
||||
doc.save()
|
||||
doc.submit()
|
||||
self.move_reconciled_entries()
|
||||
self.populate_matching_invoices()
|
||||
|
||||
def move_reconciled_entries(self):
|
||||
idx = 0
|
||||
while idx < len(self.new_transaction_items):
|
||||
entry = self.new_transaction_items[idx]
|
||||
try:
|
||||
print("Checking transaction {0}: {2} in {1} entries".format(idx, len(self.new_transaction_items), frappe.safe_decode(entry.description)))
|
||||
except UnicodeEncodeError:
|
||||
pass
|
||||
idx += 1
|
||||
if entry.reference_name is None: continue
|
||||
doc = frappe.get_doc(entry.reference_type, entry.reference_name)
|
||||
if doc.docstatus == 1 and (entry.reference_type == "Journal Entry" or doc.unallocated_amount == 0):
|
||||
self.remove(entry)
|
||||
rc_entry = self.append('reconciled_transaction_items', {})
|
||||
dentry = entry.as_dict()
|
||||
dentry.pop('idx', None)
|
||||
rc_entry.update(dentry)
|
||||
idx -= 1
|
||||
|
||||
|
||||
def get_matching_journal_entries(from_date, to_date, account, against, amount):
|
||||
query = """select voucher_no, posting_date, account, against, debit_in_account_currency as debit, credit_in_account_currency as credit
|
||||
from `tabGL Entry`
|
||||
where posting_date between '{0}' and '{1}' and account = '{2}' and against = '{3}' and debit = '{4}'
|
||||
""".format(from_date, to_date, account, against, amount)
|
||||
jv_entries = frappe.db.sql(query, as_dict=True)
|
||||
#print("voucher query:{0}\n Returned {1} entries".format(query, len(jv_entries)))
|
||||
return jv_entries
|
||||
|
||||
def get_payments_matching_invoice(invoice, amount, pay_date):
|
||||
query = """select pe.name as reference_name, per.reference_doctype as reference_type, per.outstanding_amount, per.allocated_amount
|
||||
from `tabPayment Entry Reference` as per JOIN `tabPayment Entry` as pe on pe.name = per.parent
|
||||
where per.reference_name='{0}' and (posting_date='{1}' or reference_date='{1}') and pe.docstatus != 2
|
||||
""".format(invoice, pay_date)
|
||||
payments = frappe.db.sql(query, as_dict=True)
|
||||
if (len(payments) == 0): return
|
||||
payment = next((payment for payment in payments if payment.allocated_amount == amount), payments[0])
|
||||
#Hack: Update the reference type which is set to invoice type
|
||||
payment.reference_type = "Payment Entry"
|
||||
return payment
|
||||
|
||||
def is_headers_present(headers, row):
|
||||
for header in headers:
|
||||
if header not in row:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get_header_index(headers, row):
|
||||
header_index = {}
|
||||
for header in headers:
|
||||
if header in row:
|
||||
header_index[header] = row.index(header)
|
||||
return header_index
|
||||
|
||||
def get_transaction_info(headers, header_index, row):
|
||||
transaction = {}
|
||||
for header in headers:
|
||||
transaction[header] = row[header_index[header]]
|
||||
if (transaction[header] == None):
|
||||
transaction[header] = ""
|
||||
return transaction
|
||||
|
||||
def get_transaction_entries(file_url, headers):
|
||||
header_index = {}
|
||||
rows, transactions = [], []
|
||||
|
||||
if (file_url.lower().endswith("xlsx")):
|
||||
from frappe.utils.xlsxutils import read_xlsx_file_from_attached_file
|
||||
rows = read_xlsx_file_from_attached_file(file_url=file_url)
|
||||
elif (file_url.lower().endswith("csv")):
|
||||
from frappe.utils.csvutils import read_csv_content
|
||||
_file = frappe.get_doc("File", {"file_url": file_url})
|
||||
filepath = _file.get_full_path()
|
||||
with open(filepath,'rb') as csvfile:
|
||||
rows = read_csv_content(csvfile.read())
|
||||
elif (file_url.lower().endswith("xls")):
|
||||
filename = file_url.split("/")[-1]
|
||||
rows = get_rows_from_xls_file(filename)
|
||||
else:
|
||||
frappe.throw(_("Only .csv and .xlsx files are supported currently"))
|
||||
|
||||
stmt_headers = headers.values()
|
||||
for row in rows:
|
||||
if len(row) == 0 or row[0] == None or not row[0]: continue
|
||||
#print("Processing row {0}".format(row))
|
||||
if header_index:
|
||||
transaction = get_transaction_info(stmt_headers, header_index, row)
|
||||
transactions.append(transaction)
|
||||
elif is_headers_present(stmt_headers, row):
|
||||
header_index = get_header_index(stmt_headers, row)
|
||||
return transactions
|
||||
|
||||
def get_rows_from_xls_file(filename):
|
||||
_file = frappe.get_doc("File", {"file_name": filename})
|
||||
filepath = _file.get_full_path()
|
||||
import xlrd
|
||||
book = xlrd.open_workbook(filepath)
|
||||
sheets = book.sheets()
|
||||
rows = []
|
||||
for row in range(1, sheets[0].nrows):
|
||||
row_values = []
|
||||
for col in range(1, sheets[0].ncols):
|
||||
row_values.append(sheets[0].cell_value(row, col))
|
||||
rows.append(row_values)
|
||||
return rows
|
@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Statement Transaction Entry", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Statement Transaction Entry
|
||||
() => frappe.tests.make('Bank Statement Transaction Entry', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestBankStatementTransactionEntry(unittest.TestCase):
|
||||
pass
|
@ -1,365 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-07 13:58:53.827058",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "transaction_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Transaction Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 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": 4,
|
||||
"fieldname": "payment_description",
|
||||
"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": "Payment Description",
|
||||
"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": "party_type",
|
||||
"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": "Party Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer\nSupplier\nAccount",
|
||||
"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": "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",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "party_type",
|
||||
"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": "column_break_4",
|
||||
"fieldtype": "Column Break",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "invoice_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": "Invoice Date",
|
||||
"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": 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": "invoice_type",
|
||||
"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": "Invoice Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Sales Invoice\nPurchase Invoice\nJournal Entry",
|
||||
"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": 2,
|
||||
"fieldname": "invoice",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "invoice",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "invoice_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": 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": 1,
|
||||
"fieldname": "outstanding_amount",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Outstanding Amount",
|
||||
"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": 1,
|
||||
"fieldname": "allocated_amount",
|
||||
"fieldtype": "Data",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Allocated Amount",
|
||||
"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
|
||||
}
|
||||
],
|
||||
"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,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-09-14 19:03:30.949831",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Transaction Invoice Item",
|
||||
"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",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
}
|
@ -1,494 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-07 14:03:05.651413",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"fieldname": "transaction_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": "Transaction Date",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 4,
|
||||
"fieldname": "description",
|
||||
"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": "Description",
|
||||
"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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"fieldname": "amount",
|
||||
"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": "Amount",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_3",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 1,
|
||||
"fieldname": "party_type",
|
||||
"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": "Party Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Customer\nSupplier\nAccount",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"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": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Party",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "section_break_6",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "reference_type",
|
||||
"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": "Reference Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Payment Entry\nJournal Entry",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 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": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mode_of_payment",
|
||||
"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": "Mode of Payment",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Mode of Payment",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "outstanding_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": "outstanding_amount",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "column_break_10",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 2,
|
||||
"fieldname": "reference_name",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Reference Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "reference_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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "payment_reference",
|
||||
"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": "Payment Reference",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "invoices",
|
||||
"fieldtype": "Text",
|
||||
"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,
|
||||
"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,
|
||||
"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,
|
||||
"max_attachments": 0,
|
||||
"modified": "2017-11-15 19:18:52.876221",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Transaction Payment Item",
|
||||
"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",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
// Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Statement Settings', {
|
||||
refresh: function(frm) {
|
||||
|
||||
}
|
||||
});
|
@ -1,266 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 1,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-13 13:38:10.863592",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_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": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 1,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "'%d/%m/%Y'",
|
||||
"fieldname": "date_format",
|
||||
"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": "Date Format",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "statement_header_mapping",
|
||||
"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": "Statement Header Mapping",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "header_items",
|
||||
"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": "Statement Headers",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Settings Item",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "transaction_data_mapping",
|
||||
"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": "Transaction Data Mapping",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mapped_items",
|
||||
"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": "Mapped Items",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Statement Transaction Settings Item",
|
||||
"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,
|
||||
"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": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-12 10:34:32.840487",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Settings",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"apply_user_permissions": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 1,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
class BankStatementSettings(Document):
|
||||
def autoname(self):
|
||||
self.name = self.bank_account + "-Mappings"
|
@ -1,23 +0,0 @@
|
||||
/* eslint-disable */
|
||||
// rename this file from _test_[name] to test_[name] to activate
|
||||
// and remove above this line
|
||||
|
||||
QUnit.test("test: Bank Statement Settings", function (assert) {
|
||||
let done = assert.async();
|
||||
|
||||
// number of asserts
|
||||
assert.expect(1);
|
||||
|
||||
frappe.run_serially([
|
||||
// insert a new Bank Statement Settings
|
||||
() => frappe.tests.make('Bank Statement Settings', [
|
||||
// values to be set
|
||||
{key: 'value'}
|
||||
]),
|
||||
() => {
|
||||
assert.equal(cur_frm.doc.key, 'value');
|
||||
},
|
||||
() => done()
|
||||
]);
|
||||
|
||||
});
|
@ -1,10 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2017, sathishpy@gmail.com and Contributors
|
||||
# See license.txt
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
|
||||
class TestBankStatementSettings(unittest.TestCase):
|
||||
pass
|
@ -1,166 +0,0 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 0,
|
||||
"allow_rename": 0,
|
||||
"beta": 0,
|
||||
"creation": "2017-11-13 13:42:00.335432",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Transaction",
|
||||
"fieldname": "mapping_type",
|
||||
"fieldtype": "Select",
|
||||
"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": "Mapping Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Transaction",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "bank_data",
|
||||
"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": "Bank Data",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Account",
|
||||
"fieldname": "mapped_data_type",
|
||||
"fieldtype": "Select",
|
||||
"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": "Mapped Data Type",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Account\nCustomer\nSupplier\nAccount",
|
||||
"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,
|
||||
"unique": 0
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "mapped_data",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Mapped Data",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "mapped_data_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": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 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,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-01-08 00:13:49.973501",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Statement Transaction Settings Item",
|
||||
"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",
|
||||
"track_changes": 1,
|
||||
"track_seen": 0
|
||||
}
|
@ -1,32 +1,70 @@
|
||||
// Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
frappe.ui.form.on('Bank Transaction', {
|
||||
frappe.ui.form.on("Bank Transaction", {
|
||||
onload(frm) {
|
||||
frm.set_query('payment_document', 'payment_entries', function() {
|
||||
frm.set_query("payment_document", "payment_entries", function () {
|
||||
return {
|
||||
"filters": {
|
||||
"name": ["in", ["Payment Entry", "Journal Entry", "Sales Invoice", "Purchase Invoice", "Expense Claim"]]
|
||||
}
|
||||
filters: {
|
||||
name: [
|
||||
"in",
|
||||
[
|
||||
"Payment Entry",
|
||||
"Journal Entry",
|
||||
"Sales Invoice",
|
||||
"Purchase Invoice",
|
||||
"Expense Claim",
|
||||
],
|
||||
],
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
bank_account: function (frm) {
|
||||
set_bank_statement_filter(frm);
|
||||
},
|
||||
|
||||
setup: function (frm) {
|
||||
frm.set_query("party_type", function () {
|
||||
return {
|
||||
filters: {
|
||||
name: ["in", Object.keys(frappe.boot.party_account_types)],
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
frappe.ui.form.on('Bank Transaction Payments', {
|
||||
payment_entries_remove: function(frm, cdt, cdn) {
|
||||
frappe.ui.form.on("Bank Transaction Payments", {
|
||||
payment_entries_remove: function (frm, cdt, cdn) {
|
||||
update_clearance_date(frm, cdt, cdn);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
const update_clearance_date = (frm, cdt, cdn) => {
|
||||
if (frm.doc.docstatus === 1) {
|
||||
frappe.xcall('erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment',
|
||||
{doctype: cdt, docname: cdn})
|
||||
.then(e => {
|
||||
frappe
|
||||
.xcall(
|
||||
"erpnext.accounts.doctype.bank_transaction.bank_transaction.unclear_reference_payment",
|
||||
{ doctype: cdt, docname: cdn }
|
||||
)
|
||||
.then((e) => {
|
||||
if (e == "success") {
|
||||
frappe.show_alert({message:__("Document {0} successfully uncleared", [e]), indicator:'green'});
|
||||
frappe.show_alert({
|
||||
message: __("Document {0} successfully uncleared", [e]),
|
||||
indicator: "green",
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
function set_bank_statement_filter(frm) {
|
||||
frm.set_query("bank_statement", function () {
|
||||
return {
|
||||
filters: {
|
||||
bank_account: frm.doc.bank_account,
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
|
@ -1,833 +1,245 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_events_in_timeline": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "naming_series:",
|
||||
"beta": 0,
|
||||
"creation": "2018-10-22 18:19:02.784533",
|
||||
"custom": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"naming_series",
|
||||
"date",
|
||||
"column_break_2",
|
||||
"status",
|
||||
"bank_account",
|
||||
"company",
|
||||
"section_break_4",
|
||||
"deposit",
|
||||
"withdrawal",
|
||||
"column_break_7",
|
||||
"currency",
|
||||
"section_break_10",
|
||||
"description",
|
||||
"section_break_14",
|
||||
"reference_number",
|
||||
"transaction_id",
|
||||
"payment_entries",
|
||||
"section_break_18",
|
||||
"allocated_amount",
|
||||
"amended_from",
|
||||
"column_break_17",
|
||||
"unallocated_amount",
|
||||
"party_section",
|
||||
"party_type",
|
||||
"party"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "ACC-BTN-.YYYY.-",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "naming_series",
|
||||
"fieldtype": "Select",
|
||||
"hidden": 1,
|
||||
"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": 1,
|
||||
"options": "ACC-BTN-.YYYY.-",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 1,
|
||||
"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
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Date",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
"label": "Date"
|
||||
},
|
||||
{
|
||||
"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",
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "Pending",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "status",
|
||||
"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": "Status",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "\nPending\nSettled\nUnreconciled\nReconciled",
|
||||
"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
|
||||
"options": "\nPending\nSettled\nUnreconciled\nReconciled"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "bank_account",
|
||||
"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": "Bank Account",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Account",
|
||||
"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
|
||||
"options": "Bank Account"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "",
|
||||
"fetch_from": "bank_account.company",
|
||||
"fetch_if_empty": 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,
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_4",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "debit",
|
||||
"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": "Debit",
|
||||
"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": "credit",
|
||||
"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": "Credit",
|
||||
"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": "column_break_7",
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "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": "Currency",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Currency",
|
||||
"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
|
||||
"options": "Currency"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_10",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "description",
|
||||
"fieldtype": "Small Text",
|
||||
"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": "Description",
|
||||
"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
|
||||
"label": "Description"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_14",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "reference_number",
|
||||
"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": "Reference Number",
|
||||
"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
|
||||
"label": "Reference Number"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "transaction_id",
|
||||
"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": "Transaction ID",
|
||||
"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": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 1,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "payment_entries",
|
||||
"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": "Payment Entries",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Bank Transaction Payments",
|
||||
"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
|
||||
"options": "Bank Transaction Payments"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "section_break_18",
|
||||
"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
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "allocated_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": "Allocated Amount",
|
||||
"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
|
||||
"label": "Allocated Amount"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fetch_if_empty": 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": "Bank Transaction",
|
||||
"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
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"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_17",
|
||||
"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
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_in_quick_entry": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"depends_on": "",
|
||||
"fetch_if_empty": 0,
|
||||
"fieldname": "unallocated_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": "Unallocated Amount",
|
||||
"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
|
||||
"label": "Unallocated Amount"
|
||||
},
|
||||
{
|
||||
"fieldname": "party_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "Payment From / To"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "party_type",
|
||||
"fieldtype": "Link",
|
||||
"label": "Party Type",
|
||||
"options": "DocType"
|
||||
},
|
||||
{
|
||||
"allow_on_submit": 1,
|
||||
"fieldname": "party",
|
||||
"fieldtype": "Dynamic Link",
|
||||
"label": "Party",
|
||||
"options": "party_type"
|
||||
},
|
||||
{
|
||||
"fieldname": "deposit",
|
||||
"oldfieldname": "debit",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Deposit"
|
||||
},
|
||||
{
|
||||
"fieldname": "withdrawal",
|
||||
"oldfieldname": "credit",
|
||||
"fieldtype": "Currency",
|
||||
"in_list_view": 1,
|
||||
"label": "Withdrawal"
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"idx": 0,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 1,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2019-05-11 05:27:55.244721",
|
||||
"links": [],
|
||||
"modified": "2020-12-30 19:40:54.221070",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Bank Transaction",
|
||||
"name_case": "",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 1,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 1,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 1,
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 0,
|
||||
"sort_field": "date",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "bank_account",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0,
|
||||
"track_views": 0
|
||||
"track_changes": 1
|
||||
}
|
@ -11,7 +11,7 @@ from frappe import _
|
||||
|
||||
class BankTransaction(StatusUpdater):
|
||||
def after_insert(self):
|
||||
self.unallocated_amount = abs(flt(self.credit) - flt(self.debit))
|
||||
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit))
|
||||
|
||||
def on_submit(self):
|
||||
self.clear_linked_payment_entries()
|
||||
@ -30,13 +30,13 @@ class BankTransaction(StatusUpdater):
|
||||
|
||||
if allocated_amount:
|
||||
frappe.db.set_value(self.doctype, self.name, "allocated_amount", flt(allocated_amount))
|
||||
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.credit) - flt(self.debit)) - flt(allocated_amount))
|
||||
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.withdrawal) - flt(self.deposit)) - flt(allocated_amount))
|
||||
|
||||
else:
|
||||
frappe.db.set_value(self.doctype, self.name, "allocated_amount", 0)
|
||||
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.credit) - flt(self.debit)))
|
||||
frappe.db.set_value(self.doctype, self.name, "unallocated_amount", abs(flt(self.withdrawal) - flt(self.deposit)))
|
||||
|
||||
amount = self.debit or self.credit
|
||||
amount = self.deposit or self.withdrawal
|
||||
if amount == self.allocated_amount:
|
||||
frappe.db.set_value(self.doctype, self.name, "status", "Reconciled")
|
||||
|
||||
@ -44,18 +44,11 @@ class BankTransaction(StatusUpdater):
|
||||
|
||||
def clear_linked_payment_entries(self):
|
||||
for payment_entry in self.payment_entries:
|
||||
allocated_amount = get_total_allocated_amount(payment_entry)
|
||||
paid_amount = get_paid_amount(payment_entry, self.currency)
|
||||
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
|
||||
self.clear_simple_entry(payment_entry)
|
||||
|
||||
if paid_amount and allocated_amount:
|
||||
if flt(allocated_amount[0]["allocated_amount"]) > flt(paid_amount):
|
||||
frappe.throw(_("The total allocated amount ({0}) is greated than the paid amount ({1}).").format(flt(allocated_amount[0]["allocated_amount"]), flt(paid_amount)))
|
||||
else:
|
||||
if payment_entry.payment_document in ["Payment Entry", "Journal Entry", "Purchase Invoice", "Expense Claim"]:
|
||||
self.clear_simple_entry(payment_entry)
|
||||
|
||||
elif payment_entry.payment_document == "Sales Invoice":
|
||||
self.clear_sales_invoice(payment_entry)
|
||||
elif payment_entry.payment_document == "Sales Invoice":
|
||||
self.clear_sales_invoice(payment_entry)
|
||||
|
||||
def clear_simple_entry(self, payment_entry):
|
||||
frappe.db.set_value(payment_entry.payment_document, payment_entry.payment_entry, "clearance_date", self.date)
|
||||
@ -112,3 +105,4 @@ def unclear_reference_payment(doctype, docname):
|
||||
frappe.db.set_value(doc.payment_document, doc.payment_entry, "clearance_date", None)
|
||||
|
||||
return doc.payment_entry
|
||||
|
||||
|
@ -5,17 +5,20 @@ from __future__ import unicode_literals
|
||||
|
||||
import frappe
|
||||
import unittest
|
||||
import json
|
||||
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
|
||||
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
|
||||
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
|
||||
from erpnext.accounts.page.bank_reconciliation.bank_reconciliation import reconcile, get_linked_payments
|
||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import reconcile_vouchers, get_linked_payments
|
||||
from erpnext.accounts.doctype.pos_profile.test_pos_profile import make_pos_profile
|
||||
|
||||
test_dependencies = ["Item", "Cost Center"]
|
||||
|
||||
class TestBankTransaction(unittest.TestCase):
|
||||
def setUp(self):
|
||||
make_pos_profile()
|
||||
add_transactions()
|
||||
add_payments()
|
||||
add_vouchers()
|
||||
|
||||
def tearDown(self):
|
||||
for bt in frappe.get_all("Bank Transaction"):
|
||||
@ -27,20 +30,27 @@ class TestBankTransaction(unittest.TestCase):
|
||||
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`")
|
||||
|
||||
frappe.flags.test_bank_transactions_created = False
|
||||
frappe.flags.test_payments_created = False
|
||||
|
||||
# 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("Bank Transaction", dict(description="Re 95282925234 FE/000002917 AT171513000281183046 Conrad Electronic"))
|
||||
linked_payments = get_linked_payments(bank_transaction.name)
|
||||
self.assertTrue(linked_payments[0].party == "Conrad Electronic")
|
||||
linked_payments = get_linked_payments(bank_transaction.name, ['payment_entry', 'exact_match'])
|
||||
self.assertTrue(linked_payments[0][6] == "Conrad Electronic")
|
||||
|
||||
# This test validates a simple reconciliation leading to the clearance of the bank transaction and the payment
|
||||
def test_reconcile(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G"))
|
||||
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1200))
|
||||
reconcile(bank_transaction.name, "Payment Entry", payment.name)
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Payment Entry",
|
||||
"payment_name":payment.name,
|
||||
"amount":bank_transaction.unallocated_amount}])
|
||||
reconcile_vouchers(bank_transaction.name, vouchers)
|
||||
|
||||
unallocated_amount = frappe.db.get_value("Bank Transaction", bank_transaction.name, "unallocated_amount")
|
||||
self.assertTrue(unallocated_amount == 0)
|
||||
@ -48,45 +58,40 @@ class TestBankTransaction(unittest.TestCase):
|
||||
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
|
||||
self.assertTrue(clearance_date is not None)
|
||||
|
||||
# Check if ERPNext can correctly fetch a linked payment based on the party
|
||||
def test_linked_payments_based_on_party(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"))
|
||||
linked_payments = get_linked_payments(bank_transaction.name)
|
||||
self.assertTrue(len(linked_payments)==1)
|
||||
|
||||
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
|
||||
def test_debit_credit_output(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07"))
|
||||
linked_payments = get_linked_payments(bank_transaction.name)
|
||||
self.assertTrue(linked_payments[0].payment_type == "Pay")
|
||||
linked_payments = get_linked_payments(bank_transaction.name, ['payment_entry', 'exact_match'])
|
||||
print(linked_payments)
|
||||
self.assertTrue(linked_payments[0][3])
|
||||
|
||||
# Check error if already reconciled
|
||||
def test_already_reconciled(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G"))
|
||||
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1200))
|
||||
reconcile(bank_transaction.name, "Payment Entry", payment.name)
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Payment Entry",
|
||||
"payment_name":payment.name,
|
||||
"amount":bank_transaction.unallocated_amount}])
|
||||
reconcile_vouchers(bank_transaction.name, vouchers)
|
||||
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G"))
|
||||
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1200))
|
||||
self.assertRaises(frappe.ValidationError, reconcile, bank_transaction=bank_transaction.name, payment_doctype="Payment Entry", payment_name=payment.name)
|
||||
|
||||
# Raise an error if creditor transaction vs creditor payment
|
||||
def test_invalid_creditor_reconcilation(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="I2015000011 VD/000002514 ATWWXXX AT4701345000003510057 Bio"))
|
||||
payment = frappe.get_doc("Payment Entry", dict(party="Conrad Electronic", paid_amount=690))
|
||||
self.assertRaises(frappe.ValidationError, reconcile, bank_transaction=bank_transaction.name, payment_doctype="Payment Entry", payment_name=payment.name)
|
||||
|
||||
# Raise an error if debitor transaction vs debitor payment
|
||||
def test_invalid_debitor_reconcilation(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07"))
|
||||
payment = frappe.get_doc("Payment Entry", dict(party="Fayva", paid_amount=109080))
|
||||
self.assertRaises(frappe.ValidationError, reconcile, bank_transaction=bank_transaction.name, payment_doctype="Payment Entry", payment_name=payment.name)
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Payment Entry",
|
||||
"payment_name":payment.name,
|
||||
"amount":bank_transaction.unallocated_amount}])
|
||||
self.assertRaises(frappe.ValidationError, reconcile_vouchers, bank_transaction_name=bank_transaction.name, vouchers=vouchers)
|
||||
|
||||
# Raise an error if debitor transaction vs debitor payment
|
||||
def test_clear_sales_invoice(self):
|
||||
bank_transaction = frappe.get_doc("Bank Transaction", dict(description="I2015000011 VD/000002514 ATWWXXX AT4701345000003510057 Bio"))
|
||||
payment = frappe.get_doc("Sales Invoice", dict(customer="Fayva", status=["=", "Paid"]))
|
||||
reconcile(bank_transaction.name, "Sales Invoice", payment.name)
|
||||
vouchers = json.dumps([{
|
||||
"payment_doctype":"Sales Invoice",
|
||||
"payment_name":payment.name,
|
||||
"amount":bank_transaction.unallocated_amount}])
|
||||
reconcile_vouchers(bank_transaction.name, vouchers=vouchers)
|
||||
|
||||
self.assertEqual(frappe.db.get_value("Bank Transaction", bank_transaction.name, "unallocated_amount"), 0)
|
||||
self.assertTrue(frappe.db.get_value("Sales Invoice Payment", dict(parent=payment.name), "clearance_date") is not None)
|
||||
@ -121,7 +126,7 @@ def add_transactions():
|
||||
"doctype": "Bank Transaction",
|
||||
"description":"1512567 BG/000002918 OPSKATTUZWXXX AT776000000098709837 Herr G",
|
||||
"date": "2018-10-23",
|
||||
"debit": 1200,
|
||||
"deposit": 1200,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank"
|
||||
}).insert()
|
||||
@ -131,7 +136,7 @@ def add_transactions():
|
||||
"doctype": "Bank Transaction",
|
||||
"description":"1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G",
|
||||
"date": "2018-10-23",
|
||||
"debit": 1700,
|
||||
"deposit": 1700,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank"
|
||||
}).insert()
|
||||
@ -141,7 +146,7 @@ def add_transactions():
|
||||
"doctype": "Bank Transaction",
|
||||
"description":"Re 95282925234 FE/000002917 AT171513000281183046 Conrad Electronic",
|
||||
"date": "2018-10-26",
|
||||
"debit": 690,
|
||||
"withdrawal": 690,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank"
|
||||
}).insert()
|
||||
@ -151,7 +156,7 @@ def add_transactions():
|
||||
"doctype": "Bank Transaction",
|
||||
"description":"Auszahlung Karte MC/000002916 AUTOMAT 698769 K002 27.10. 14:07",
|
||||
"date": "2018-10-27",
|
||||
"debit": 3900,
|
||||
"deposit": 3900,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank"
|
||||
}).insert()
|
||||
@ -161,7 +166,7 @@ def add_transactions():
|
||||
"doctype": "Bank Transaction",
|
||||
"description":"I2015000011 VD/000002514 ATWWXXX AT4701345000003510057 Bio",
|
||||
"date": "2018-10-27",
|
||||
"credit": 109080,
|
||||
"withdrawal": 109080,
|
||||
"currency": "INR",
|
||||
"bank_account": "Checking Account - Citi Bank"
|
||||
}).insert()
|
||||
@ -169,7 +174,7 @@ def add_transactions():
|
||||
|
||||
frappe.flags.test_bank_transactions_created = True
|
||||
|
||||
def add_payments():
|
||||
def add_vouchers():
|
||||
if frappe.flags.test_payments_created:
|
||||
return
|
||||
|
||||
@ -187,6 +192,7 @@ def add_payments():
|
||||
pass
|
||||
|
||||
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
||||
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe.reference_no = "Conrad Oct 18"
|
||||
pe.reference_date = "2018-10-24"
|
||||
@ -237,10 +243,15 @@ def add_payments():
|
||||
except frappe.DuplicateEntryError:
|
||||
pass
|
||||
|
||||
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900)
|
||||
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save =1)
|
||||
pi.cash_bank_account = "_Test Bank - _TC"
|
||||
pi.insert()
|
||||
pi.submit()
|
||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||
pe.reference_no = "Poore Simon's Oct 18"
|
||||
pe.reference_date = "2018-10-28"
|
||||
pe.paid_amount = 690
|
||||
pe.received_amount = 690
|
||||
pe.insert()
|
||||
pe.submit()
|
||||
|
||||
@ -290,4 +301,4 @@ def add_payments():
|
||||
si.save()
|
||||
si.submit()
|
||||
|
||||
frappe.flags.test_payments_created = True
|
||||
frappe.flags.test_payments_created = True
|
||||
|
@ -1,24 +1,9 @@
|
||||
// Copyright (c) 2016, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
frappe.provide("erpnext.accounts.dimensions");
|
||||
|
||||
frappe.ui.form.on('Budget', {
|
||||
onload: function(frm) {
|
||||
frm.set_query("cost_center", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
frm.set_query("project", function() {
|
||||
return {
|
||||
filters: {
|
||||
company: frm.doc.company
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
frm.set_query("account", "accounts", function() {
|
||||
return {
|
||||
filters: {
|
||||
@ -26,16 +11,18 @@ frappe.ui.form.on('Budget', {
|
||||
report_type: "Profit and Loss",
|
||||
is_group: 0
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
frm.set_query("monthly_distribution", function() {
|
||||
return {
|
||||
filters: {
|
||||
fiscal_year: frm.doc.fiscal_year
|
||||
}
|
||||
}
|
||||
})
|
||||
};
|
||||
});
|
||||
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(frm, frm.doctype);
|
||||
},
|
||||
|
||||
refresh: function(frm) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -122,8 +122,10 @@ class TestBudget(unittest.TestCase):
|
||||
|
||||
frappe.db.set_value("Budget", budget.name, "action_if_accumulated_monthly_budget_exceeded", "Stop")
|
||||
|
||||
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
|
||||
"_Test Bank - _TC", 40000, "_Test Cost Center - _TC", project=project, posting_date=nowdate())
|
||||
|
||||
self.assertRaises(BudgetError, jv.submit)
|
||||
|
||||
@ -147,8 +149,11 @@ class TestBudget(unittest.TestCase):
|
||||
|
||||
budget = make_budget(budget_against="Project")
|
||||
|
||||
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", 250000, "_Test Cost Center - _TC", project="_Test Project", posting_date=nowdate())
|
||||
"_Test Bank - _TC", 250000, "_Test Cost Center - _TC",
|
||||
project=project, posting_date=nowdate())
|
||||
|
||||
self.assertRaises(BudgetError, jv.submit)
|
||||
|
||||
@ -158,8 +163,11 @@ class TestBudget(unittest.TestCase):
|
||||
set_total_expense_zero(nowdate(), "cost_center")
|
||||
|
||||
budget = make_budget(budget_against="Cost Center")
|
||||
month = now_datetime().month
|
||||
if month > 9:
|
||||
month = 9
|
||||
|
||||
for i in range(now_datetime().month):
|
||||
for i in range(month+1):
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True)
|
||||
|
||||
@ -177,10 +185,15 @@ class TestBudget(unittest.TestCase):
|
||||
set_total_expense_zero(nowdate(), "project")
|
||||
|
||||
budget = make_budget(budget_against="Project")
|
||||
month = now_datetime().month
|
||||
if month > 9:
|
||||
month = 9
|
||||
|
||||
for i in range(now_datetime().month):
|
||||
project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||
for i in range(month + 1):
|
||||
jv = make_journal_entry("_Test Account Cost for Goods Sold - _TC",
|
||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True, project="_Test Project")
|
||||
"_Test Bank - _TC", 20000, "_Test Cost Center - _TC", posting_date=nowdate(), submit=True,
|
||||
project=project)
|
||||
|
||||
self.assertTrue(frappe.db.get_value("GL Entry",
|
||||
{"voucher_type": "Journal Entry", "voucher_no": jv.name}))
|
||||
@ -283,7 +296,7 @@ def make_budget(**args):
|
||||
budget = frappe.new_doc("Budget")
|
||||
|
||||
if budget_against == "Project":
|
||||
budget.project = "_Test Project"
|
||||
budget.project = frappe.get_value("Project", {"project_name": "_Test Project"})
|
||||
else:
|
||||
budget.cost_center =cost_center or "_Test Cost Center - _TC"
|
||||
|
||||
|
@ -23,13 +23,13 @@ class CashierClosing(Document):
|
||||
where posting_date=%s and posting_time>=%s and posting_time<=%s and owner=%s
|
||||
""", (self.date, self.from_time, self.time, self.user))
|
||||
self.outstanding_amount = flt(values[0][0] if values else 0)
|
||||
|
||||
|
||||
def make_calculations(self):
|
||||
total = 0.00
|
||||
for i in self.payments:
|
||||
total += flt(i.amount)
|
||||
|
||||
self.net_amount = total + self.outstanding_amount + self.expense - self.custody + self.returns
|
||||
self.net_amount = total + self.outstanding_amount + flt(self.expense) - flt(self.custody) + flt(self.returns)
|
||||
|
||||
def validate_time(self):
|
||||
if self.from_time >= self.time:
|
||||
|
@ -94,8 +94,7 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
||||
callback: function(r) {
|
||||
if(r.message===false) {
|
||||
frm.set_value("company", "");
|
||||
frappe.throw(__(`Transactions against the company already exist!
|
||||
Chart Of accounts can be imported for company with no transactions`));
|
||||
frappe.throw(__("Transactions against the Company already exist! Chart of Accounts can only be imported for a Company with no transactions."));
|
||||
} else {
|
||||
frm.trigger("refresh");
|
||||
}
|
||||
|
@ -22,9 +22,10 @@ def validate_company(company):
|
||||
'allow_account_creation_against_child_company'])
|
||||
|
||||
if parent_company and (not allow_account_creation_against_child_company):
|
||||
frappe.throw(_("""{0} is a child company. Please import accounts against parent company
|
||||
or enable {1} in company master""").format(frappe.bold(company),
|
||||
frappe.bold('Allow Account Creation Against Child Company')), title='Wrong 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.throw(msg, title=_('Wrong Company'))
|
||||
|
||||
if frappe.db.get_all('GL Entry', {"company": company}, "name", limit=1):
|
||||
return False
|
||||
@ -74,7 +75,9 @@ def generate_data_from_csv(file_doc, as_dict=False):
|
||||
if as_dict:
|
||||
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
||||
else:
|
||||
if not row[1]: row[1] = row[0]
|
||||
if not row[1]:
|
||||
row[1] = row[0]
|
||||
row[3] = row[2]
|
||||
data.append(row)
|
||||
|
||||
# convert csv data
|
||||
@ -96,7 +99,9 @@ def generate_data_from_excel(file_doc, extension, as_dict=False):
|
||||
if as_dict:
|
||||
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
||||
else:
|
||||
if not row[1]: row[1] = row[0]
|
||||
if not row[1]:
|
||||
row[1] = row[0]
|
||||
row[3] = row[2]
|
||||
data.append(row)
|
||||
|
||||
return data
|
||||
@ -147,7 +152,13 @@ def build_forest(data):
|
||||
from frappe import _
|
||||
|
||||
for row in data:
|
||||
account_name, parent_account = row[0:2]
|
||||
account_name, parent_account, account_number, parent_account_number = row[0:4]
|
||||
if account_number:
|
||||
account_name = "{} - {}".format(account_number, account_name)
|
||||
if parent_account_number:
|
||||
parent_account_number = cstr(parent_account_number).strip()
|
||||
parent_account = "{} - {}".format(parent_account_number, parent_account)
|
||||
|
||||
if parent_account == account_name == child:
|
||||
return [parent_account]
|
||||
elif account_name == child:
|
||||
@ -159,20 +170,23 @@ def build_forest(data):
|
||||
|
||||
charts_map, paths = {}, []
|
||||
|
||||
line_no = 3
|
||||
line_no = 2
|
||||
error_messages = []
|
||||
|
||||
for i in data:
|
||||
account_name, dummy, account_number, is_group, account_type, root_type = i
|
||||
account_name, parent_account, account_number, parent_account_number, is_group, account_type, root_type = i
|
||||
|
||||
if not account_name:
|
||||
error_messages.append("Row {0}: Please enter Account Name".format(line_no))
|
||||
|
||||
if account_number:
|
||||
account_number = cstr(account_number).strip()
|
||||
account_name = "{} - {}".format(account_number, account_name)
|
||||
|
||||
charts_map[account_name] = {}
|
||||
if cint(is_group) == 1: charts_map[account_name]["is_group"] = is_group
|
||||
if account_type: charts_map[account_name]["account_type"] = account_type
|
||||
if root_type: charts_map[account_name]["root_type"] = root_type
|
||||
if account_number: charts_map[account_name]["account_number"] = account_number
|
||||
path = return_parent(data, account_name)[::-1]
|
||||
paths.append(path) # List of path is created
|
||||
line_no += 1
|
||||
@ -195,7 +209,7 @@ def build_response_as_excel(writer):
|
||||
reader = csv.reader(f)
|
||||
|
||||
from frappe.utils.xlsxutils import make_xlsx
|
||||
xlsx_file = make_xlsx(reader, "Chart Of Accounts Importer Template")
|
||||
xlsx_file = make_xlsx(reader, "Chart of Accounts Importer Template")
|
||||
|
||||
f.close()
|
||||
os.remove(filename)
|
||||
@ -221,7 +235,7 @@ def download_template(file_type, template_type):
|
||||
|
||||
def get_template(template_type):
|
||||
|
||||
fields = ["Account Name", "Parent Account", "Account Number", "Is Group", "Account Type", "Root Type"]
|
||||
fields = ["Account Name", "Parent Account", "Account Number", "Parent Account Number", "Is Group", "Account Type", "Root Type"]
|
||||
writer = UnicodeWriter()
|
||||
writer.writerow(fields)
|
||||
|
||||
@ -241,23 +255,23 @@ def get_template(template_type):
|
||||
|
||||
def get_sample_template(writer):
|
||||
template = [
|
||||
["Application Of Funds(Assets)", "", "", 1, "", "Asset"],
|
||||
["Sources Of Funds(Liabilities)", "", "", 1, "", "Liability"],
|
||||
["Equity", "", "", 1, "", "Equity"],
|
||||
["Expenses", "", "", 1, "", "Expense"],
|
||||
["Income", "", "", 1, "", "Income"],
|
||||
["Bank Accounts", "Application Of Funds(Assets)", "", 1, "Bank", "Asset"],
|
||||
["Cash In Hand", "Application Of Funds(Assets)", "", 1, "Cash", "Asset"],
|
||||
["Stock Assets", "Application Of Funds(Assets)", "", 1, "Stock", "Asset"],
|
||||
["Cost Of Goods Sold", "Expenses", "", 0, "Cost of Goods Sold", "Expense"],
|
||||
["Asset Depreciation", "Expenses", "", 0, "Depreciation", "Expense"],
|
||||
["Fixed Assets", "Application Of Funds(Assets)", "", 0, "Fixed Asset", "Asset"],
|
||||
["Accounts Payable", "Sources Of Funds(Liabilities)", "", 0, "Payable", "Liability"],
|
||||
["Accounts Receivable", "Application Of Funds(Assets)", "", 1, "Receivable", "Asset"],
|
||||
["Stock Expenses", "Expenses", "", 0, "Stock Adjustment", "Expense"],
|
||||
["Sample Bank", "Bank Accounts", "", 0, "Bank", "Asset"],
|
||||
["Cash", "Cash In Hand", "", 0, "Cash", "Asset"],
|
||||
["Stores", "Stock Assets", "", 0, "Stock", "Asset"],
|
||||
["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
|
||||
["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
|
||||
["Equity", "", "", "", 1, "", "Equity"],
|
||||
["Expenses", "", "", "", 1, "", "Expense"],
|
||||
["Income", "", "", "", 1, "", "Income"],
|
||||
["Bank Accounts", "Application Of Funds(Assets)", "", "", 1, "Bank", "Asset"],
|
||||
["Cash In Hand", "Application Of Funds(Assets)", "", "", 1, "Cash", "Asset"],
|
||||
["Stock Assets", "Application Of Funds(Assets)", "", "", 1, "Stock", "Asset"],
|
||||
["Cost Of Goods Sold", "Expenses", "", "", 0, "Cost of Goods Sold", "Expense"],
|
||||
["Asset Depreciation", "Expenses", "", "", 0, "Depreciation", "Expense"],
|
||||
["Fixed Assets", "Application Of Funds(Assets)", "", "", 0, "Fixed Asset", "Asset"],
|
||||
["Accounts Payable", "Sources Of Funds(Liabilities)", "", "", 0, "Payable", "Liability"],
|
||||
["Accounts Receivable", "Application Of Funds(Assets)", "", "", 1, "Receivable", "Asset"],
|
||||
["Stock Expenses", "Expenses", "", "", 0, "Stock Adjustment", "Expense"],
|
||||
["Sample Bank", "Bank Accounts", "", "", 0, "Bank", "Asset"],
|
||||
["Cash", "Cash In Hand", "", "", 0, "Cash", "Asset"],
|
||||
["Stores", "Stock Assets", "", "", 0, "Stock", "Asset"],
|
||||
]
|
||||
|
||||
for row in template:
|
||||
|
@ -28,22 +28,22 @@ def test_create_test_data():
|
||||
"item_group": "_Test Item Group",
|
||||
"item_name": "_Test Tesla Car",
|
||||
"apply_warehouse_wise_reorder_level": 0,
|
||||
"warehouse":"Stores - TCP1",
|
||||
"warehouse":"Stores - _TC",
|
||||
"gst_hsn_code": "999800",
|
||||
"valuation_rate": 5000,
|
||||
"standard_rate":5000,
|
||||
"item_defaults": [{
|
||||
"company": "_Test Company with perpetual inventory",
|
||||
"default_warehouse": "Stores - TCP1",
|
||||
"company": "_Test Company",
|
||||
"default_warehouse": "Stores - _TC",
|
||||
"default_price_list":"_Test Price List",
|
||||
"expense_account": "Cost of Goods Sold - TCP1",
|
||||
"buying_cost_center": "Main - TCP1",
|
||||
"selling_cost_center": "Main - TCP1",
|
||||
"income_account": "Sales - TCP1"
|
||||
"expense_account": "Cost of Goods Sold - _TC",
|
||||
"buying_cost_center": "Main - _TC",
|
||||
"selling_cost_center": "Main - _TC",
|
||||
"income_account": "Sales - _TC"
|
||||
}],
|
||||
"show_in_website": 1,
|
||||
"route":"-test-tesla-car",
|
||||
"website_warehouse": "Stores - TCP1"
|
||||
"website_warehouse": "Stores - _TC"
|
||||
})
|
||||
item.insert()
|
||||
# create test item price
|
||||
@ -65,12 +65,12 @@ def test_create_test_data():
|
||||
"items": [{
|
||||
"item_code": "_Test Tesla Car"
|
||||
}],
|
||||
"warehouse":"Stores - TCP1",
|
||||
"warehouse":"Stores - _TC",
|
||||
"coupon_code_based":1,
|
||||
"selling": 1,
|
||||
"rate_or_discount": "Discount Percentage",
|
||||
"discount_percentage": 30,
|
||||
"company": "_Test Company with perpetual inventory",
|
||||
"company": "_Test Company",
|
||||
"currency":"INR",
|
||||
"for_price_list":"_Test Price List"
|
||||
})
|
||||
@ -85,7 +85,7 @@ def test_create_test_data():
|
||||
})
|
||||
sales_partner.insert()
|
||||
# create test item coupon code
|
||||
if not frappe.db.exists("Coupon Code","SAVE30"):
|
||||
if not frappe.db.exists("Coupon Code", "SAVE30"):
|
||||
coupon_code = frappe.get_doc({
|
||||
"doctype": "Coupon Code",
|
||||
"coupon_name":"SAVE30",
|
||||
@ -102,35 +102,27 @@ class TestCouponCode(unittest.TestCase):
|
||||
test_create_test_data()
|
||||
|
||||
def tearDown(self):
|
||||
frappe.set_user("Administrator")
|
||||
frappe.set_user("Administrator")
|
||||
|
||||
def test_1_check_coupon_code_used_before_so(self):
|
||||
coupon_code = frappe.get_doc("Coupon Code", frappe.db.get_value("Coupon Code", {"coupon_name":"SAVE30"}))
|
||||
# reset used coupon code count
|
||||
coupon_code.used=0
|
||||
coupon_code.save()
|
||||
# check no coupon code is used before sales order is made
|
||||
self.assertEqual(coupon_code.get("used"),0)
|
||||
def test_sales_order_with_coupon_code(self):
|
||||
frappe.db.set_value("Coupon Code", "SAVE30", "used", 0)
|
||||
|
||||
def test_2_sales_order_with_coupon_code(self):
|
||||
so = make_sales_order(company='_Test Company with perpetual inventory', warehouse='Stores - TCP1',
|
||||
customer="_Test Customer", selling_price_list="_Test Price List", item_code="_Test Tesla Car", rate=5000,qty=1,
|
||||
so = make_sales_order(company='_Test Company', warehouse='Stores - _TC',
|
||||
customer="_Test Customer", selling_price_list="_Test Price List",
|
||||
item_code="_Test Tesla Car", rate=5000, qty=1,
|
||||
do_not_submit=True)
|
||||
|
||||
so = frappe.get_doc('Sales Order', so.name)
|
||||
# check item price before coupon code is applied
|
||||
self.assertEqual(so.items[0].rate, 5000)
|
||||
|
||||
so.coupon_code='SAVE30'
|
||||
so.sales_partner='_Test Coupon Partner'
|
||||
so.save()
|
||||
|
||||
# check item price after coupon code is applied
|
||||
self.assertEqual(so.items[0].rate, 3500)
|
||||
|
||||
so.submit()
|
||||
|
||||
def test_3_check_coupon_code_used_after_so(self):
|
||||
doc = frappe.get_doc("Coupon Code", frappe.db.get_value("Coupon Code", {"coupon_name":"SAVE30"}))
|
||||
# check no coupon code is used before sales order is made
|
||||
self.assertEqual(doc.get("used"),1)
|
||||
self.assertEqual(frappe.db.get_value("Coupon Code", "SAVE30", "used"), 1)
|
||||
|
||||
|
||||
|
||||
|
@ -9,11 +9,7 @@ frappe.ui.form.on('Fiscal Year', {
|
||||
}
|
||||
},
|
||||
refresh: function (frm) {
|
||||
let doc = frm.doc;
|
||||
frm.toggle_enable('year_start_date', doc.__islocal);
|
||||
frm.toggle_enable('year_end_date', doc.__islocal);
|
||||
|
||||
if (!doc.__islocal && (doc.name != frappe.sys_defaults.fiscal_year)) {
|
||||
if (!frm.doc.__islocal && (frm.doc.name != frappe.sys_defaults.fiscal_year)) {
|
||||
frm.add_custom_button(__("Set as Default"), () => frm.events.set_as_default(frm));
|
||||
frm.set_intro(__("To set this Fiscal Year as Default, click on 'Set as Default'"));
|
||||
} else {
|
||||
@ -24,8 +20,10 @@ frappe.ui.form.on('Fiscal Year', {
|
||||
return frm.call('set_as_default');
|
||||
},
|
||||
year_start_date: function(frm) {
|
||||
let year_end_date =
|
||||
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
|
||||
frm.set_value("year_end_date", year_end_date);
|
||||
if (!frm.doc.is_short_year) {
|
||||
let year_end_date =
|
||||
frappe.datetime.add_days(frappe.datetime.add_months(frm.doc.year_start_date, 12), -1);
|
||||
frm.set_value("year_end_date", year_end_date);
|
||||
}
|
||||
},
|
||||
});
|
||||
|
@ -1,347 +1,126 @@
|
||||
{
|
||||
"allow_copy": 0,
|
||||
"allow_guest_to_view": 0,
|
||||
"allow_import": 1,
|
||||
"allow_rename": 0,
|
||||
"autoname": "field:year",
|
||||
"beta": 0,
|
||||
"creation": "2013-01-22 16:50:25",
|
||||
"custom": 0,
|
||||
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||
"docstatus": 0,
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"editable_grid": 0,
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"autoname": "field:year",
|
||||
"creation": "2013-01-22 16:50:25",
|
||||
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"year",
|
||||
"disabled",
|
||||
"is_short_year",
|
||||
"year_start_date",
|
||||
"year_end_date",
|
||||
"companies",
|
||||
"auto_created"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"description": "For e.g. 2012, 2012-13",
|
||||
"fieldname": "year",
|
||||
"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": "Year Name",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"oldfieldname": "year",
|
||||
"oldfieldtype": "Data",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"description": "For e.g. 2012, 2012-13",
|
||||
"fieldname": "year",
|
||||
"fieldtype": "Data",
|
||||
"in_list_view": 1,
|
||||
"label": "Year Name",
|
||||
"oldfieldname": "year",
|
||||
"oldfieldtype": "Data",
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"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": "Disabled",
|
||||
"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
|
||||
},
|
||||
"default": "0",
|
||||
"fieldname": "disabled",
|
||||
"fieldtype": "Check",
|
||||
"label": "Disabled"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "year_start_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Year Start Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "year_start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"permlevel": 0,
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 1,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "year_start_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Year Start Date",
|
||||
"no_copy": 1,
|
||||
"oldfieldname": "year_start_date",
|
||||
"oldfieldtype": "Date",
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "year_end_date",
|
||||
"fieldtype": "Date",
|
||||
"hidden": 0,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Year End Date",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"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
|
||||
},
|
||||
"fieldname": "year_end_date",
|
||||
"fieldtype": "Date",
|
||||
"in_list_view": 1,
|
||||
"label": "Year End Date",
|
||||
"no_copy": 1,
|
||||
"reqd": 1,
|
||||
"set_only_once": 1
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"fieldname": "companies",
|
||||
"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": "Companies",
|
||||
"length": 0,
|
||||
"no_copy": 0,
|
||||
"options": "Fiscal Year Company",
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"print_hide": 0,
|
||||
"print_hide_if_no_value": 0,
|
||||
"read_only": 0,
|
||||
"remember_last_selected_value": 0,
|
||||
"report_hide": 0,
|
||||
"reqd": 0,
|
||||
"search_index": 0,
|
||||
"set_only_once": 0,
|
||||
"translatable": 0,
|
||||
"unique": 0
|
||||
},
|
||||
"fieldname": "companies",
|
||||
"fieldtype": "Table",
|
||||
"label": "Companies",
|
||||
"options": "Fiscal Year Company"
|
||||
},
|
||||
{
|
||||
"allow_bulk_edit": 0,
|
||||
"allow_on_submit": 0,
|
||||
"bold": 0,
|
||||
"collapsible": 0,
|
||||
"columns": 0,
|
||||
"default": "0",
|
||||
"fieldname": "auto_created",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"ignore_user_permissions": 0,
|
||||
"ignore_xss_filter": 0,
|
||||
"in_filter": 0,
|
||||
"in_global_search": 0,
|
||||
"in_list_view": 0,
|
||||
"in_standard_filter": 0,
|
||||
"label": "Auto Created",
|
||||
"length": 0,
|
||||
"no_copy": 1,
|
||||
"permlevel": 0,
|
||||
"precision": "",
|
||||
"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
|
||||
"default": "0",
|
||||
"fieldname": "auto_created",
|
||||
"fieldtype": "Check",
|
||||
"hidden": 1,
|
||||
"label": "Auto Created",
|
||||
"no_copy": 1,
|
||||
"print_hide": 1,
|
||||
"read_only": 1
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Less than 12 months.",
|
||||
"fieldname": "is_short_year",
|
||||
"fieldtype": "Check",
|
||||
"label": "Is Short Year",
|
||||
"set_only_once": 1
|
||||
}
|
||||
],
|
||||
"has_web_view": 0,
|
||||
"hide_heading": 0,
|
||||
"hide_toolbar": 0,
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"image_view": 0,
|
||||
"in_create": 0,
|
||||
"is_submittable": 0,
|
||||
"issingle": 0,
|
||||
"istable": 0,
|
||||
"max_attachments": 0,
|
||||
"modified": "2018-04-25 14:21:41.273354",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
"owner": "Administrator",
|
||||
],
|
||||
"icon": "fa fa-calendar",
|
||||
"idx": 1,
|
||||
"links": [],
|
||||
"modified": "2020-11-05 12:16:53.081573",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Fiscal Year",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"set_user_permissions": 0,
|
||||
"share": 1,
|
||||
"submit": 0,
|
||||
"create": 1,
|
||||
"delete": 1,
|
||||
"email": 1,
|
||||
"print": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1,
|
||||
"write": 1
|
||||
},
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Sales User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
"read": 1,
|
||||
"role": "Sales User"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Purchase User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
"read": 1,
|
||||
"role": "Purchase User"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Accounts User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
"read": 1,
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Stock User",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
},
|
||||
"read": 1,
|
||||
"role": "Stock User"
|
||||
},
|
||||
{
|
||||
"amend": 0,
|
||||
"cancel": 0,
|
||||
"create": 0,
|
||||
"delete": 0,
|
||||
"email": 0,
|
||||
"export": 0,
|
||||
"if_owner": 0,
|
||||
"import": 0,
|
||||
"permlevel": 0,
|
||||
"print": 0,
|
||||
"read": 1,
|
||||
"report": 0,
|
||||
"role": "Employee",
|
||||
"set_user_permissions": 0,
|
||||
"share": 0,
|
||||
"submit": 0,
|
||||
"write": 0
|
||||
"read": 1,
|
||||
"role": "Employee"
|
||||
}
|
||||
],
|
||||
"quick_entry": 0,
|
||||
"read_only": 0,
|
||||
"read_only_onload": 0,
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "name",
|
||||
"sort_order": "DESC",
|
||||
"track_changes": 0,
|
||||
"track_seen": 0
|
||||
],
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "name",
|
||||
"sort_order": "DESC"
|
||||
}
|
@ -36,6 +36,11 @@ class FiscalYear(Document):
|
||||
frappe.throw(_("Cannot change Fiscal Year Start Date and Fiscal Year End Date once the Fiscal Year is saved."))
|
||||
|
||||
def validate_dates(self):
|
||||
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)
|
||||
@ -116,12 +121,8 @@ def auto_create_fiscal_year():
|
||||
pass
|
||||
|
||||
def get_from_and_to_date(fiscal_year):
|
||||
from_and_to_date_tuple = frappe.db.sql("""select year_start_date, year_end_date
|
||||
from `tabFiscal Year` where name=%s""", (fiscal_year))[0]
|
||||
|
||||
from_and_to_date = {
|
||||
"from_date": from_and_to_date_tuple[0],
|
||||
"to_date": from_and_to_date_tuple[1]
|
||||
}
|
||||
|
||||
return from_and_to_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)
|
||||
|
@ -11,6 +11,7 @@ test_records = frappe.get_test_records('Fiscal Year')
|
||||
test_ignore = ["Company"]
|
||||
|
||||
class TestFiscalYear(unittest.TestCase):
|
||||
|
||||
def test_extra_year(self):
|
||||
if frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2000"):
|
||||
frappe.delete_doc("Fiscal Year", "_Test Fiscal Year 2000")
|
||||
|
@ -1,4 +1,11 @@
|
||||
[
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Short Fiscal Year 2011",
|
||||
"is_short_year": 1,
|
||||
"year_end_date": "2011-04-01",
|
||||
"year_start_date": "2011-12-31"
|
||||
},
|
||||
{
|
||||
"doctype": "Fiscal Year",
|
||||
"year": "_Test Fiscal Year 2012",
|
||||
|
@ -11,8 +11,10 @@ from frappe.model.meta import get_field_precision
|
||||
from erpnext.accounts.party import validate_party_gle_currency, validate_party_frozen_disabled
|
||||
from erpnext.accounts.utils import get_account_currency
|
||||
from erpnext.accounts.utils import get_fiscal_year
|
||||
from erpnext.exceptions import InvalidAccountCurrency
|
||||
from erpnext.exceptions import InvalidAccountCurrency, InvalidAccountDimensionError, MandatoryAccountDimensionError
|
||||
from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import get_checks_for_pl_and_bs_accounts
|
||||
from erpnext.accounts.doctype.accounting_dimension_filter.accounting_dimension_filter import get_dimension_filter_map
|
||||
from six import iteritems
|
||||
|
||||
exclude_from_linked_with = True
|
||||
class GLEntry(Document):
|
||||
@ -25,27 +27,30 @@ class GLEntry(Document):
|
||||
|
||||
def validate(self):
|
||||
self.flags.ignore_submit_comment = True
|
||||
self.check_mandatory()
|
||||
self.validate_and_set_fiscal_year()
|
||||
self.pl_must_have_cost_center()
|
||||
self.validate_cost_center()
|
||||
|
||||
self.check_pl_account()
|
||||
self.validate_party()
|
||||
self.validate_currency()
|
||||
if not self.flags.from_repost:
|
||||
self.check_mandatory()
|
||||
self.validate_cost_center()
|
||||
self.check_pl_account()
|
||||
self.validate_party()
|
||||
self.validate_currency()
|
||||
|
||||
def on_update_with_args(self, adv_adj, update_outstanding = 'Yes'):
|
||||
self.validate_account_details(adv_adj)
|
||||
self.validate_dimensions_for_pl_and_bs()
|
||||
def on_update(self):
|
||||
adv_adj = self.flags.adv_adj
|
||||
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)
|
||||
|
||||
validate_frozen_account(self.account, adv_adj)
|
||||
validate_balance_type(self.account, adv_adj)
|
||||
|
||||
# Update outstanding amt on against voucher
|
||||
if self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees'] \
|
||||
and self.against_voucher and update_outstanding == 'Yes':
|
||||
update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
|
||||
self.against_voucher)
|
||||
# Update outstanding amt on against voucher
|
||||
if (self.against_voucher_type in ['Journal Entry', 'Sales Invoice', 'Purchase Invoice', 'Fees']
|
||||
and self.against_voucher and self.flags.update_outstanding == 'Yes'):
|
||||
update_outstanding_amt(self.account, self.party_type, self.party, self.against_voucher_type,
|
||||
self.against_voucher)
|
||||
|
||||
def check_mandatory(self):
|
||||
mandatory = ['account','voucher_type','voucher_no','company']
|
||||
@ -53,7 +58,7 @@ class GLEntry(Document):
|
||||
if not self.get(k):
|
||||
frappe.throw(_("{0} is required").format(_(self.meta.get_label(k))))
|
||||
|
||||
account_type = frappe.db.get_value("Account", self.account, "account_type")
|
||||
account_type = frappe.get_cached_value("Account", self.account, "account_type")
|
||||
if not (self.party_type and self.party):
|
||||
if account_type == "Receivable":
|
||||
frappe.throw(_("{0} {1}: Customer is required against Receivable account {2}")
|
||||
@ -68,17 +73,15 @@ class GLEntry(Document):
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
|
||||
def pl_must_have_cost_center(self):
|
||||
if frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss":
|
||||
if frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss":
|
||||
if not self.cost_center and self.voucher_type != 'Period Closing Voucher':
|
||||
frappe.throw(_("{0} {1}: Cost Center is required for 'Profit and Loss' account {2}. Please set up a default Cost Center for the Company.")
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
|
||||
def validate_dimensions_for_pl_and_bs(self):
|
||||
|
||||
account_type = frappe.db.get_value("Account", self.account, "report_type")
|
||||
|
||||
for dimension in get_checks_for_pl_and_bs_accounts():
|
||||
|
||||
if account_type == "Profit and Loss" \
|
||||
and self.company == dimension.company and dimension.mandatory_for_pl and not dimension.disabled:
|
||||
if not self.get(dimension.fieldname):
|
||||
@ -91,6 +94,25 @@ class GLEntry(Document):
|
||||
frappe.throw(_("Accounting Dimension <b>{0}</b> is required for 'Balance Sheet' account {1}.")
|
||||
.format(dimension.label, self.account))
|
||||
|
||||
def validate_allowed_dimensions(self):
|
||||
dimension_filter_map = get_dimension_filter_map()
|
||||
for key, value in iteritems(dimension_filter_map):
|
||||
dimension = key[0]
|
||||
account = key[1]
|
||||
|
||||
if self.account == account:
|
||||
if value['is_mandatory'] and not self.get(dimension):
|
||||
frappe.throw(_("{0} is mandatory for account {1}").format(
|
||||
frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)), MandatoryAccountDimensionError)
|
||||
|
||||
if value['allow_or_restrict'] == 'Allow':
|
||||
if self.get(dimension) and self.get(dimension) not in value['allowed_dimensions']:
|
||||
frappe.throw(_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)), frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)), InvalidAccountDimensionError)
|
||||
else:
|
||||
if self.get(dimension) and self.get(dimension) in value['allowed_dimensions']:
|
||||
frappe.throw(_("Invalid value {0} for {1} against account {2}").format(
|
||||
frappe.bold(self.get(dimension)), frappe.bold(frappe.unscrub(dimension)), frappe.bold(self.account)), InvalidAccountDimensionError)
|
||||
|
||||
def check_pl_account(self):
|
||||
if self.is_opening=='Yes' and \
|
||||
@ -106,8 +128,8 @@ class GLEntry(Document):
|
||||
from tabAccount where name=%s""", self.account, as_dict=1)[0]
|
||||
|
||||
if ret.is_group==1:
|
||||
frappe.throw(_('''{0} {1}: Account {2} is a Group Account and group accounts cannot be used in
|
||||
transactions''').format(self.voucher_type, self.voucher_no, self.account))
|
||||
frappe.throw(_('''{0} {1}: Account {2} is a Group Account and group accounts cannot be used in transactions''')
|
||||
.format(self.voucher_type, self.voucher_no, self.account))
|
||||
|
||||
if ret.docstatus==2:
|
||||
frappe.throw(_("{0} {1}: Account {2} is inactive")
|
||||
@ -118,26 +140,18 @@ class GLEntry(Document):
|
||||
.format(self.voucher_type, self.voucher_no, self.account, self.company))
|
||||
|
||||
def validate_cost_center(self):
|
||||
if not hasattr(self, "cost_center_company"):
|
||||
self.cost_center_company = {}
|
||||
if not self.cost_center: return
|
||||
|
||||
def _get_cost_center_company():
|
||||
if not self.cost_center_company.get(self.cost_center):
|
||||
self.cost_center_company[self.cost_center] = frappe.db.get_value(
|
||||
"Cost Center", self.cost_center, "company")
|
||||
is_group, company = frappe.get_cached_value('Cost Center',
|
||||
self.cost_center, ['is_group', 'company'])
|
||||
|
||||
return self.cost_center_company[self.cost_center]
|
||||
|
||||
def _check_is_group():
|
||||
return cint(frappe.get_cached_value('Cost Center', self.cost_center, 'is_group'))
|
||||
|
||||
if self.cost_center and _get_cost_center_company() != self.company:
|
||||
if company != self.company:
|
||||
frappe.throw(_("{0} {1}: Cost Center {2} does not belong to Company {3}")
|
||||
.format(self.voucher_type, self.voucher_no, self.cost_center, self.company))
|
||||
|
||||
if self.cost_center and _check_is_group():
|
||||
frappe.throw(_("""{0} {1}: Cost Center {2} is a group cost center and group cost centers cannot
|
||||
be used in transactions""").format(self.voucher_type, self.voucher_no, frappe.bold(self.cost_center)))
|
||||
if (self.voucher_type != 'Period Closing Voucher' and is_group):
|
||||
frappe.throw(_("""{0} {1}: Cost Center {2} is a group cost center and group cost centers cannot be used in transactions""").format(
|
||||
self.voucher_type, self.voucher_no, frappe.bold(self.cost_center)))
|
||||
|
||||
def validate_party(self):
|
||||
validate_party_frozen_disabled(self.party_type, self.party)
|
||||
@ -147,7 +161,7 @@ class GLEntry(Document):
|
||||
account_currency = get_account_currency(self.account)
|
||||
|
||||
if not self.account_currency:
|
||||
self.account_currency = company_currency
|
||||
self.account_currency = account_currency or company_currency
|
||||
|
||||
if account_currency != self.account_currency:
|
||||
frappe.throw(_("{0} {1}: Accounting Entry for {2} can only be made in currency: {3}")
|
||||
@ -161,7 +175,6 @@ class GLEntry(Document):
|
||||
if not self.fiscal_year:
|
||||
self.fiscal_year = get_fiscal_year(self.posting_date, company=self.company)[0]
|
||||
|
||||
|
||||
def validate_balance_type(account, adv_adj=False):
|
||||
if not adv_adj and account:
|
||||
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be")
|
||||
@ -227,7 +240,7 @@ def update_outstanding_amt(account, party_type, party, against_voucher_type, aga
|
||||
|
||||
|
||||
def validate_frozen_account(account, adv_adj=None):
|
||||
frozen_account = frappe.db.get_value("Account", account, "freeze_account")
|
||||
frozen_account = frappe.get_cached_value("Account", account, "freeze_account")
|
||||
if frozen_account == 'Yes' and not adv_adj:
|
||||
frozen_accounts_modifier = frappe.db.get_value( 'Accounts Settings', None,
|
||||
'frozen_accounts_modifier')
|
||||
|
@ -137,11 +137,12 @@ class InvoiceDiscounting(AccountsController):
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.bank_charges_account,
|
||||
"debit_in_account_currency": flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
if self.bank_charges:
|
||||
je.append("accounts", {
|
||||
"account": self.bank_charges_account,
|
||||
"debit_in_account_currency": flt(self.bank_charges),
|
||||
"cost_center": erpnext.get_default_cost_center(self.company)
|
||||
})
|
||||
|
||||
je.append("accounts", {
|
||||
"account": self.short_term_loan,
|
||||
|
@ -80,6 +80,7 @@ class TestInvoiceDiscounting(unittest.TestCase):
|
||||
short_term_loan=self.short_term_loan,
|
||||
bank_charges_account=self.bank_charges_account,
|
||||
bank_account=self.bank_account,
|
||||
bank_charges=100
|
||||
)
|
||||
|
||||
je = inv_disc.create_disbursement_entry()
|
||||
@ -289,6 +290,7 @@ def create_invoice_discounting(invoices, **args):
|
||||
inv_disc.bank_account=args.bank_account
|
||||
inv_disc.loan_start_date = args.start or nowdate()
|
||||
inv_disc.loan_period = args.period or 30
|
||||
inv_disc.bank_charges = flt(args.bank_charges)
|
||||
|
||||
for d in invoices:
|
||||
inv_disc.append("invoices", {
|
||||
|
@ -1,7 +1,7 @@
|
||||
{
|
||||
"actions": [],
|
||||
"allow_import": 1,
|
||||
"allow_rename": 1,
|
||||
"autoname": "field:title",
|
||||
"creation": "2018-11-22 22:45:00.370913",
|
||||
"doctype": "DocType",
|
||||
"document_type": "Setup",
|
||||
@ -20,8 +20,7 @@
|
||||
"in_list_view": 1,
|
||||
"label": "Title",
|
||||
"no_copy": 1,
|
||||
"reqd": 1,
|
||||
"unique": 1
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"fieldname": "taxes",
|
||||
@ -33,12 +32,14 @@
|
||||
{
|
||||
"fieldname": "company",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "Company",
|
||||
"options": "Company",
|
||||
"reqd": 1
|
||||
}
|
||||
],
|
||||
"modified": "2020-09-18 17:26:09.703215",
|
||||
"links": [],
|
||||
"modified": "2021-03-08 19:50:21.416513",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Item Tax Template",
|
||||
@ -81,5 +82,6 @@
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
@ -11,6 +11,11 @@ class ItemTaxTemplate(Document):
|
||||
def validate(self):
|
||||
self.validate_tax_accounts()
|
||||
|
||||
def autoname(self):
|
||||
if self.company and self.title:
|
||||
abbr = frappe.get_cached_value('Company', self.company, 'abbr')
|
||||
self.name = '{0} - {1}'.format(self.title, abbr)
|
||||
|
||||
def validate_tax_accounts(self):
|
||||
"""Check whether Tax Rate is not entered twice for same Tax Type"""
|
||||
check_list = []
|
||||
|
@ -20,7 +20,8 @@ def get_data():
|
||||
'items': ['Purchase Invoice', 'Purchase Order', 'Purchase Receipt']
|
||||
},
|
||||
{
|
||||
'items': ['Item']
|
||||
'label': _('Stock'),
|
||||
'items': ['Item Groups', 'Item']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -120,6 +120,8 @@ frappe.ui.form.on("Journal Entry", {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
erpnext.accounts.dimensions.update_dimension(frm, frm.doctype);
|
||||
},
|
||||
|
||||
voucher_type: function(frm){
|
||||
@ -197,6 +199,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
this.load_defaults();
|
||||
this.setup_queries();
|
||||
this.setup_balance_formatter();
|
||||
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
|
||||
},
|
||||
|
||||
onload_post_render: function() {
|
||||
@ -210,7 +213,7 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
$.each(this.frm.doc.accounts || [], function(i, jvd) {
|
||||
frappe.model.set_default_values(jvd);
|
||||
});
|
||||
var posting_date = this.frm.posting_date;
|
||||
var posting_date = this.frm.doc.posting_date;
|
||||
if(!this.frm.doc.amended_from) this.frm.set_value('posting_date', posting_date || frappe.datetime.get_today());
|
||||
}
|
||||
},
|
||||
@ -222,15 +225,6 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
return erpnext.journal_entry.account_query(me.frm);
|
||||
});
|
||||
|
||||
me.frm.set_query("cost_center", "accounts", function(doc, cdt, cdn) {
|
||||
return {
|
||||
filters: {
|
||||
company: me.frm.doc.company,
|
||||
is_group: 0
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
me.frm.set_query("party_type", "accounts", function(doc, cdt, cdn) {
|
||||
const row = locals[cdt][cdn];
|
||||
|
||||
@ -406,6 +400,8 @@ erpnext.accounts.JournalEntry = frappe.ui.form.Controller.extend({
|
||||
}
|
||||
}
|
||||
cur_frm.cscript.update_totals(doc);
|
||||
|
||||
erpnext.accounts.dimensions.copy_dimension_from_first_row(this.frm, cdt, cdn, 'accounts');
|
||||
},
|
||||
|
||||
});
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user