Compare commits
1 Commits
test_dashb
...
fix_pos_er
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e8571bac00 |
@@ -29,6 +29,3 @@ b147b85e6ac19a9220cd1e2958a6ebd99373283a
|
|||||||
|
|
||||||
# bulk format python code with black
|
# bulk format python code with black
|
||||||
baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
baec607ff5905b1c67531096a9cf50ec7ff00a5d
|
||||||
|
|
||||||
# bulk refactor with sourcery
|
|
||||||
eb9ee3f79b94e594fc6dfa4f6514580e125eee8c
|
|
||||||
|
|||||||
2
.github/workflows/backport.yml
vendored
2
.github/workflows/backport.yml
vendored
@@ -21,6 +21,6 @@ jobs:
|
|||||||
- name: Run backport
|
- name: Run backport
|
||||||
uses: ./actions/backport
|
uses: ./actions/backport
|
||||||
with:
|
with:
|
||||||
token: ${{secrets.RELEASE_TOKEN}}
|
token: ${{secrets.BACKPORT_BOT_TOKEN}}
|
||||||
labelsToAdd: "backport"
|
labelsToAdd: "backport"
|
||||||
title: "{{originalTitle}}"
|
title: "{{originalTitle}}"
|
||||||
|
|||||||
2
.github/workflows/initiate_release.yml
vendored
2
.github/workflows/initiate_release.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
version: ["14", "15"]
|
version: ["13", "14"]
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: octokit/request-action@v2.x
|
- uses: octokit/request-action@v2.x
|
||||||
|
|||||||
12
.github/workflows/linters.yml
vendored
12
.github/workflows/linters.yml
vendored
@@ -20,18 +20,6 @@ jobs:
|
|||||||
- name: Install and Run Pre-commit
|
- name: Install and Run Pre-commit
|
||||||
uses: pre-commit/action@v3.0.0
|
uses: pre-commit/action@v3.0.0
|
||||||
|
|
||||||
semgrep:
|
|
||||||
name: semgrep
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
|
|
||||||
- name: Set up Python 3.10
|
|
||||||
uses: actions/setup-python@v4
|
|
||||||
with:
|
|
||||||
python-version: '3.10'
|
|
||||||
cache: pip
|
|
||||||
|
|
||||||
- name: Download Semgrep rules
|
- name: Download Semgrep rules
|
||||||
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
run: git clone --depth 1 https://github.com/frappe/semgrep-rules.git frappe-semgrep-rules
|
||||||
|
|
||||||
|
|||||||
21
.github/workflows/lock.yml
vendored
21
.github/workflows/lock.yml
vendored
@@ -1,21 +0,0 @@
|
|||||||
name: 'Lock threads'
|
|
||||||
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
- cron: '0 0 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
issues: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
lock:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: dessant/lock-threads@v5
|
|
||||||
with:
|
|
||||||
github-token: ${{ github.token }}
|
|
||||||
issue-inactive-days: 14
|
|
||||||
pr-inactive-days: 14
|
|
||||||
22
.github/workflows/patch_faux.yml
vendored
22
.github/workflows/patch_faux.yml
vendored
@@ -1,22 +0,0 @@
|
|||||||
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
|
|
||||||
|
|
||||||
name: Skipped Patch Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "**.js"
|
|
||||||
- "**.css"
|
|
||||||
- "**.md"
|
|
||||||
- "**.html"
|
|
||||||
- "**.csv"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
name: Patch Test
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Pass skipped tests unconditionally
|
|
||||||
run: "echo Skipped"
|
|
||||||
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v2
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 18
|
||||||
- name: Setup dependencies
|
- name: Setup dependencies
|
||||||
run: |
|
run: |
|
||||||
npm install @semantic-release/git @semantic-release/exec --no-save
|
npm install @semantic-release/git @semantic-release/exec --no-save
|
||||||
|
|||||||
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
24
.github/workflows/server-tests-mariadb-faux.yml
vendored
@@ -1,24 +0,0 @@
|
|||||||
# Tests are skipped for these files but github doesn't allow "passing" hence this is required.
|
|
||||||
|
|
||||||
name: Skipped Tests
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- "**.js"
|
|
||||||
- "**.css"
|
|
||||||
- "**.md"
|
|
||||||
- "**.html"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
container: [1, 2, 3, 4]
|
|
||||||
|
|
||||||
name: Python Unit Tests
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Pass skipped tests unconditionally
|
|
||||||
run: "echo Skipped"
|
|
||||||
@@ -5,7 +5,7 @@ fail_fast: false
|
|||||||
|
|
||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
rev: v4.3.0
|
rev: v4.0.1
|
||||||
hooks:
|
hooks:
|
||||||
- id: trailing-whitespace
|
- id: trailing-whitespace
|
||||||
files: "erpnext.*"
|
files: "erpnext.*"
|
||||||
@@ -15,10 +15,6 @@ repos:
|
|||||||
args: ['--branch', 'develop']
|
args: ['--branch', 'develop']
|
||||||
- id: check-merge-conflict
|
- id: check-merge-conflict
|
||||||
- id: check-ast
|
- id: check-ast
|
||||||
- id: check-json
|
|
||||||
- id: check-toml
|
|
||||||
- id: check-yaml
|
|
||||||
- id: debug-statements
|
|
||||||
|
|
||||||
- repo: https://github.com/pre-commit/mirrors-eslint
|
- repo: https://github.com/pre-commit/mirrors-eslint
|
||||||
rev: v8.44.0
|
rev: v8.44.0
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
<p>ERP made simple</p>
|
<p>ERP made simple</p>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[](https://github.com/frappe/erpnext/actions/workflows/server-tests-mariadb.yml)
|
[](https://github.com/frappe/erpnext/actions/workflows/server-tests.yml)
|
||||||
|
[](https://github.com/erpnext/erpnext_ui_tests/actions/workflows/ui-tests.yml)
|
||||||
[](https://www.codetriage.com/frappe/erpnext)
|
[](https://www.codetriage.com/frappe/erpnext)
|
||||||
[](https://codecov.io/gh/frappe/erpnext)
|
[](https://codecov.io/gh/frappe/erpnext)
|
||||||
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
[](https://hub.docker.com/r/frappe/erpnext-worker)
|
||||||
@@ -72,6 +73,8 @@ New passwords will be created for the ERPNext "Administrator" user, the MariaDB
|
|||||||
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
|
1. [Issue Guidelines](https://github.com/frappe/erpnext/wiki/Issue-Guidelines)
|
||||||
1. [Report Security Vulnerabilities](https://erpnext.com/security)
|
1. [Report Security Vulnerabilities](https://erpnext.com/security)
|
||||||
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
|
1. [Pull Request Requirements](https://github.com/frappe/erpnext/wiki/Contribution-Guidelines)
|
||||||
|
1. [Translations](https://translate.erpnext.com)
|
||||||
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
files:
|
|
||||||
- source: /erpnext/locale/main.pot
|
|
||||||
translation: /erpnext/locale/%two_letters_code%.po
|
|
||||||
@@ -3,7 +3,7 @@ import inspect
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
|
|
||||||
__version__ = "16.0.0-dev"
|
__version__ = "15.0.0-dev"
|
||||||
|
|
||||||
|
|
||||||
def get_default_company(user=None):
|
def get_default_company(user=None):
|
||||||
@@ -36,7 +36,7 @@ def get_default_cost_center(company):
|
|||||||
|
|
||||||
if not frappe.flags.company_cost_center:
|
if not frappe.flags.company_cost_center:
|
||||||
frappe.flags.company_cost_center = {}
|
frappe.flags.company_cost_center = {}
|
||||||
if company not in frappe.flags.company_cost_center:
|
if not company in frappe.flags.company_cost_center:
|
||||||
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
|
frappe.flags.company_cost_center[company] = frappe.get_cached_value(
|
||||||
"Company", company, "cost_center"
|
"Company", company, "cost_center"
|
||||||
)
|
)
|
||||||
@@ -47,7 +47,7 @@ def get_company_currency(company):
|
|||||||
"""Returns the default company currency"""
|
"""Returns the default company currency"""
|
||||||
if not frappe.flags.company_currency:
|
if not frappe.flags.company_currency:
|
||||||
frappe.flags.company_currency = {}
|
frappe.flags.company_currency = {}
|
||||||
if company not in frappe.flags.company_currency:
|
if not company in frappe.flags.company_currency:
|
||||||
frappe.flags.company_currency[company] = frappe.db.get_value(
|
frappe.flags.company_currency[company] = frappe.db.get_value(
|
||||||
"Company", company, "default_currency", cache=True
|
"Company", company, "default_currency", cache=True
|
||||||
)
|
)
|
||||||
@@ -81,7 +81,7 @@ def is_perpetual_inventory_enabled(company):
|
|||||||
if not hasattr(frappe.local, "enable_perpetual_inventory"):
|
if not hasattr(frappe.local, "enable_perpetual_inventory"):
|
||||||
frappe.local.enable_perpetual_inventory = {}
|
frappe.local.enable_perpetual_inventory = {}
|
||||||
|
|
||||||
if company not in frappe.local.enable_perpetual_inventory:
|
if not company in frappe.local.enable_perpetual_inventory:
|
||||||
frappe.local.enable_perpetual_inventory[company] = (
|
frappe.local.enable_perpetual_inventory[company] = (
|
||||||
frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0
|
frappe.get_cached_value("Company", company, "enable_perpetual_inventory") or 0
|
||||||
)
|
)
|
||||||
@@ -96,7 +96,7 @@ def get_default_finance_book(company=None):
|
|||||||
if not hasattr(frappe.local, "default_finance_book"):
|
if not hasattr(frappe.local, "default_finance_book"):
|
||||||
frappe.local.default_finance_book = {}
|
frappe.local.default_finance_book = {}
|
||||||
|
|
||||||
if company not in frappe.local.default_finance_book:
|
if not company in frappe.local.default_finance_book:
|
||||||
frappe.local.default_finance_book[company] = frappe.get_cached_value(
|
frappe.local.default_finance_book[company] = frappe.get_cached_value(
|
||||||
"Company", company, "default_finance_book"
|
"Company", company, "default_finance_book"
|
||||||
)
|
)
|
||||||
@@ -108,7 +108,7 @@ def get_party_account_type(party_type):
|
|||||||
if not hasattr(frappe.local, "party_account_types"):
|
if not hasattr(frappe.local, "party_account_types"):
|
||||||
frappe.local.party_account_types = {}
|
frappe.local.party_account_types = {}
|
||||||
|
|
||||||
if party_type not in frappe.local.party_account_types:
|
if not party_type in frappe.local.party_account_types:
|
||||||
frappe.local.party_account_types[party_type] = (
|
frappe.local.party_account_types[party_type] = (
|
||||||
frappe.db.get_value("Party Type", party_type, "account_type") or ""
|
frappe.db.get_value("Party Type", party_type, "account_type") or ""
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ def calculate_monthly_amount(
|
|||||||
if amount + already_booked_amount_in_account_currency > item.net_amount:
|
if amount + already_booked_amount_in_account_currency > item.net_amount:
|
||||||
amount = item.net_amount - already_booked_amount_in_account_currency
|
amount = item.net_amount - already_booked_amount_in_account_currency
|
||||||
|
|
||||||
if get_first_day(start_date) != start_date or get_last_day(end_date) != end_date:
|
if not (get_first_day(start_date) == start_date and get_last_day(end_date) == end_date):
|
||||||
partial_month = flt(date_diff(end_date, start_date)) / flt(
|
partial_month = flt(date_diff(end_date, start_date)) / flt(
|
||||||
date_diff(get_last_day(end_date), get_first_day(start_date))
|
date_diff(get_last_day(end_date), get_first_day(start_date))
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -108,7 +108,6 @@
|
|||||||
"fieldname": "parent_account",
|
"fieldname": "parent_account",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
"ignore_user_permissions": 1,
|
||||||
"in_preview": 1,
|
|
||||||
"label": "Parent Account",
|
"label": "Parent Account",
|
||||||
"oldfieldname": "parent_account",
|
"oldfieldname": "parent_account",
|
||||||
"oldfieldtype": "Link",
|
"oldfieldtype": "Link",
|
||||||
@@ -193,7 +192,7 @@
|
|||||||
"idx": 1,
|
"idx": 1,
|
||||||
"is_tree": 1,
|
"is_tree": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-10 04:57:33.681676",
|
"modified": "2023-07-20 18:18:44.405723",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Account",
|
"name": "Account",
|
||||||
@@ -250,7 +249,6 @@
|
|||||||
],
|
],
|
||||||
"search_fields": "account_number",
|
"search_fields": "account_number",
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"show_preview_popup": 1,
|
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "ASC",
|
"sort_order": "ASC",
|
||||||
"states": [],
|
"states": [],
|
||||||
|
|||||||
@@ -23,65 +23,6 @@ class InvalidAccountMergeError(frappe.ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class Account(NestedSet):
|
class Account(NestedSet):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_currency: DF.Link | None
|
|
||||||
account_name: DF.Data
|
|
||||||
account_number: DF.Data | None
|
|
||||||
account_type: DF.Literal[
|
|
||||||
"",
|
|
||||||
"Accumulated Depreciation",
|
|
||||||
"Asset Received But Not Billed",
|
|
||||||
"Bank",
|
|
||||||
"Cash",
|
|
||||||
"Chargeable",
|
|
||||||
"Capital Work in Progress",
|
|
||||||
"Cost of Goods Sold",
|
|
||||||
"Current Asset",
|
|
||||||
"Current Liability",
|
|
||||||
"Depreciation",
|
|
||||||
"Direct Expense",
|
|
||||||
"Direct Income",
|
|
||||||
"Equity",
|
|
||||||
"Expense Account",
|
|
||||||
"Expenses Included In Asset Valuation",
|
|
||||||
"Expenses Included In Valuation",
|
|
||||||
"Fixed Asset",
|
|
||||||
"Income Account",
|
|
||||||
"Indirect Expense",
|
|
||||||
"Indirect Income",
|
|
||||||
"Liability",
|
|
||||||
"Payable",
|
|
||||||
"Receivable",
|
|
||||||
"Round Off",
|
|
||||||
"Stock",
|
|
||||||
"Stock Adjustment",
|
|
||||||
"Stock Received But Not Billed",
|
|
||||||
"Service Received But Not Billed",
|
|
||||||
"Tax",
|
|
||||||
"Temporary",
|
|
||||||
]
|
|
||||||
balance_must_be: DF.Literal["", "Debit", "Credit"]
|
|
||||||
company: DF.Link
|
|
||||||
disabled: DF.Check
|
|
||||||
freeze_account: DF.Literal["No", "Yes"]
|
|
||||||
include_in_gross: DF.Check
|
|
||||||
is_group: DF.Check
|
|
||||||
lft: DF.Int
|
|
||||||
old_parent: DF.Data | None
|
|
||||||
parent_account: DF.Link
|
|
||||||
report_type: DF.Literal["", "Balance Sheet", "Profit and Loss"]
|
|
||||||
rgt: DF.Int
|
|
||||||
root_type: DF.Literal["", "Asset", "Liability", "Income", "Expense", "Equity"]
|
|
||||||
tax_rate: DF.Float
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
nsm_parent_field = "parent_account"
|
nsm_parent_field = "parent_account"
|
||||||
|
|
||||||
def on_update(self):
|
def on_update(self):
|
||||||
@@ -91,8 +32,8 @@ class Account(NestedSet):
|
|||||||
super(Account, self).on_update()
|
super(Account, self).on_update()
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
frozen_accounts_modifier = frappe.db.get_single_value(
|
frozen_accounts_modifier = frappe.db.get_value(
|
||||||
"Accounts Settings", "frozen_accounts_modifier"
|
"Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
|
||||||
)
|
)
|
||||||
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
|
if not frozen_accounts_modifier or frozen_accounts_modifier in frappe.get_roles():
|
||||||
self.set_onload("can_freeze_account", True)
|
self.set_onload("can_freeze_account", True)
|
||||||
@@ -118,7 +59,6 @@ class Account(NestedSet):
|
|||||||
self.validate_balance_must_be_debit_or_credit()
|
self.validate_balance_must_be_debit_or_credit()
|
||||||
self.validate_account_currency()
|
self.validate_account_currency()
|
||||||
self.validate_root_company_and_sync_account_to_children()
|
self.validate_root_company_and_sync_account_to_children()
|
||||||
self.validate_receivable_payable_account_type()
|
|
||||||
|
|
||||||
def validate_parent_child_account_type(self):
|
def validate_parent_child_account_type(self):
|
||||||
if self.parent_account:
|
if self.parent_account:
|
||||||
@@ -189,24 +129,6 @@ class Account(NestedSet):
|
|||||||
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
|
"Balance Sheet" if self.root_type in ("Asset", "Liability", "Equity") else "Profit and Loss"
|
||||||
)
|
)
|
||||||
|
|
||||||
def validate_receivable_payable_account_type(self):
|
|
||||||
doc_before_save = self.get_doc_before_save()
|
|
||||||
receivable_payable_types = ["Receivable", "Payable"]
|
|
||||||
if (
|
|
||||||
doc_before_save
|
|
||||||
and doc_before_save.account_type in receivable_payable_types
|
|
||||||
and doc_before_save.account_type != self.account_type
|
|
||||||
):
|
|
||||||
# check for ledger entries
|
|
||||||
if frappe.db.get_all("GL Entry", filters={"account": self.name, "is_cancelled": 0}, limit=1):
|
|
||||||
msg = _(
|
|
||||||
"There are ledger entries against this account. Changing {0} to non-{1} in live system will cause incorrect output in 'Accounts {2}' report"
|
|
||||||
).format(
|
|
||||||
frappe.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
|
|
||||||
)
|
|
||||||
frappe.msgprint(msg)
|
|
||||||
self.add_comment("Comment", msg)
|
|
||||||
|
|
||||||
def validate_root_details(self):
|
def validate_root_details(self):
|
||||||
doc_before_save = self.get_doc_before_save()
|
doc_before_save = self.get_doc_before_save()
|
||||||
|
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ frappe.treeview_settings["Account"] = {
|
|||||||
|
|
||||||
// show Dr if positive since balance is calculated as debit - credit else show Cr
|
// show Dr if positive since balance is calculated as debit - credit else show Cr
|
||||||
const balance = account.balance_in_account_currency || account.balance;
|
const balance = account.balance_in_account_currency || account.balance;
|
||||||
const dr_or_cr = balance > 0 ? __("Dr"): __("Cr");
|
const dr_or_cr = balance > 0 ? "Dr": "Cr";
|
||||||
const format = (value, currency) => format_currency(Math.abs(value), currency);
|
const format = (value, currency) => format_currency(Math.abs(value), currency);
|
||||||
|
|
||||||
if (account.balance!==undefined) {
|
if (account.balance!==undefined) {
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ def create_charts(
|
|||||||
# after all accounts are already inserted.
|
# after all accounts are already inserted.
|
||||||
frappe.local.flags.ignore_update_nsm = True
|
frappe.local.flags.ignore_update_nsm = True
|
||||||
_import_accounts(chart, None, None, root_account=True)
|
_import_accounts(chart, None, None, root_account=True)
|
||||||
rebuild_tree("Account")
|
rebuild_tree("Account", "parent_account")
|
||||||
frappe.local.flags.ignore_update_nsm = False
|
frappe.local.flags.ignore_update_nsm = False
|
||||||
|
|
||||||
|
|
||||||
@@ -231,8 +231,6 @@ def build_account_tree(tree, parent, all_accounts):
|
|||||||
tree[child.account_name]["account_type"] = child.account_type
|
tree[child.account_name]["account_type"] = child.account_type
|
||||||
if child.tax_rate:
|
if child.tax_rate:
|
||||||
tree[child.account_name]["tax_rate"] = child.tax_rate
|
tree[child.account_name]["tax_rate"] = child.tax_rate
|
||||||
if child.account_currency:
|
|
||||||
tree[child.account_name]["account_currency"] = child.account_currency
|
|
||||||
if not parent:
|
if not parent:
|
||||||
tree[child.account_name]["root_type"] = child.root_type
|
tree[child.account_name]["root_type"] = child.root_type
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,7 @@
|
|||||||
"1500 Fertige Erzeugnisse": {"account_type": "Stock"},
|
"1500 Fertige Erzeugnisse": {"account_type": "Stock"},
|
||||||
"1600 Handelswarenvorrat": {"account_type": "Stock Received But Not Billed"},
|
"1600 Handelswarenvorrat": {"account_type": "Stock Received But Not Billed"},
|
||||||
"1700 Noch nicht abrechenbare Leistungen": {"account_type": "Stock"},
|
"1700 Noch nicht abrechenbare Leistungen": {"account_type": "Stock"},
|
||||||
|
"1900 Wertberichtigungen": {"account_type": "Stock"},
|
||||||
"1800 Geleistete Anzahlungen": {"account_type": "Stock"},
|
"1800 Geleistete Anzahlungen": {"account_type": "Stock"},
|
||||||
"1900 Wertberichtigungen": {"account_type": "Stock"},
|
"1900 Wertberichtigungen": {"account_type": "Stock"},
|
||||||
"root_type": "Asset"
|
"root_type": "Asset"
|
||||||
|
|||||||
@@ -33,9 +33,7 @@
|
|||||||
},
|
},
|
||||||
"Stocks": {
|
"Stocks": {
|
||||||
"Mati\u00e8res premi\u00e8res": {},
|
"Mati\u00e8res premi\u00e8res": {},
|
||||||
"Stock de produits fini": {
|
"Stock de produits fini": {},
|
||||||
"account_type": "Stock"
|
|
||||||
},
|
|
||||||
"Stock exp\u00e9di\u00e9 non-factur\u00e9": {},
|
"Stock exp\u00e9di\u00e9 non-factur\u00e9": {},
|
||||||
"Travaux en cours": {},
|
"Travaux en cours": {},
|
||||||
"account_type": "Stock"
|
"account_type": "Stock"
|
||||||
@@ -397,11 +395,9 @@
|
|||||||
},
|
},
|
||||||
"Produits": {
|
"Produits": {
|
||||||
"Revenus de ventes": {
|
"Revenus de ventes": {
|
||||||
"Escomptes de volume sur ventes": {},
|
" Escomptes de volume sur ventes": {},
|
||||||
"Autres produits d'exploitation": {},
|
"Autres produits d'exploitation": {},
|
||||||
"Ventes": {
|
"Ventes": {},
|
||||||
"account_type": "Income Account"
|
|
||||||
},
|
|
||||||
"Ventes avec des provinces harmonis\u00e9es": {},
|
"Ventes avec des provinces harmonis\u00e9es": {},
|
||||||
"Ventes avec des provinces non-harmonis\u00e9es": {},
|
"Ventes avec des provinces non-harmonis\u00e9es": {},
|
||||||
"Ventes \u00e0 l'\u00e9tranger": {}
|
"Ventes \u00e0 l'\u00e9tranger": {}
|
||||||
|
|||||||
@@ -53,13 +53,8 @@
|
|||||||
},
|
},
|
||||||
"II. Forderungen und sonstige Vermögensgegenstände": {
|
"II. Forderungen und sonstige Vermögensgegenstände": {
|
||||||
"is_group": 1,
|
"is_group": 1,
|
||||||
"Forderungen aus Lieferungen und Leistungen mit Kontokorrent": {
|
"Ford. a. Lieferungen und Leistungen": {
|
||||||
"account_number": "1400",
|
"account_number": "1400",
|
||||||
"account_type": "Receivable",
|
|
||||||
"is_group": 1
|
|
||||||
},
|
|
||||||
"Forderungen aus Lieferungen und Leistungen ohne Kontokorrent": {
|
|
||||||
"account_number": "1410",
|
|
||||||
"account_type": "Receivable"
|
"account_type": "Receivable"
|
||||||
},
|
},
|
||||||
"Durchlaufende Posten": {
|
"Durchlaufende Posten": {
|
||||||
@@ -185,13 +180,8 @@
|
|||||||
},
|
},
|
||||||
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
|
"IV. Verbindlichkeiten aus Lieferungen und Leistungen": {
|
||||||
"is_group": 1,
|
"is_group": 1,
|
||||||
"Verbindlichkeiten aus Lieferungen und Leistungen mit Kontokorrent": {
|
"Verbindlichkeiten aus Lieferungen u. Leistungen": {
|
||||||
"account_number": "1600",
|
"account_number": "1600",
|
||||||
"account_type": "Payable",
|
|
||||||
"is_group": 1
|
|
||||||
},
|
|
||||||
"Verbindlichkeiten aus Lieferungen und Leistungen ohne Kontokorrent": {
|
|
||||||
"account_number": "1610",
|
|
||||||
"account_type": "Payable"
|
"account_type": "Payable"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,4 @@
|
|||||||
{
|
{
|
||||||
"country_code": "hu",
|
|
||||||
"name": "Hungary - Chart of Accounts for Microenterprises",
|
|
||||||
"tree": {
|
"tree": {
|
||||||
"SZ\u00c1MLAOSZT\u00c1LY BEFEKTETETT ESZK\u00d6Z\u00d6K": {
|
"SZ\u00c1MLAOSZT\u00c1LY BEFEKTETETT ESZK\u00d6Z\u00d6K": {
|
||||||
"account_number": 1,
|
"account_number": 1,
|
||||||
|
|||||||
@@ -36,16 +36,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Fixed Assets": {
|
"Fixed Assets": {
|
||||||
"Capital Equipment": {
|
"Capital Equipments": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Electronic Equipment": {
|
"Electronic Equipments": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Furniture and Fixtures": {
|
"Furnitures and Fixtures": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Office Equipment": {
|
"Office Equipments": {
|
||||||
"account_type": "Fixed Asset"
|
"account_type": "Fixed Asset"
|
||||||
},
|
},
|
||||||
"Plants and Machineries": {
|
"Plants and Machineries": {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"country_code": "ni",
|
"country_code": "ni",
|
||||||
"name": "Nicaragua - Catálogo de Cuentas",
|
"name": "Nicaragua - Catalogo de Cuentas",
|
||||||
"tree": {
|
"tree": {
|
||||||
"Activo": {
|
"Activo": {
|
||||||
"Activo Corriente": {
|
"Activo Corriente": {
|
||||||
|
|||||||
@@ -23,13 +23,13 @@ def get():
|
|||||||
_("Tax Assets"): {"is_group": 1},
|
_("Tax Assets"): {"is_group": 1},
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipment"): {"account_type": "Fixed Asset"},
|
_("Capital Equipments"): {"account_type": "Fixed Asset"},
|
||||||
_("Electronic Equipment"): {"account_type": "Fixed Asset"},
|
_("Electronic Equipments"): {"account_type": "Fixed Asset"},
|
||||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset"},
|
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset"},
|
||||||
_("Office Equipment"): {"account_type": "Fixed Asset"},
|
_("Office Equipments"): {"account_type": "Fixed Asset"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset"},
|
_("Buildings"): {"account_type": "Fixed Asset"},
|
||||||
_("Software"): {"account_type": "Fixed Asset"},
|
_("Softwares"): {"account_type": "Fixed Asset"},
|
||||||
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
_("Accumulated Depreciation"): {"account_type": "Accumulated Depreciation"},
|
||||||
_("CWIP Account"): {
|
_("CWIP Account"): {
|
||||||
"account_type": "Capital Work in Progress",
|
"account_type": "Capital Work in Progress",
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ def get():
|
|||||||
"account_number": "1100-1600",
|
"account_number": "1100-1600",
|
||||||
},
|
},
|
||||||
_("Fixed Assets"): {
|
_("Fixed Assets"): {
|
||||||
_("Capital Equipment"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
_("Capital Equipments"): {"account_type": "Fixed Asset", "account_number": "1710"},
|
||||||
_("Electronic Equipment"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
_("Electronic Equipments"): {"account_type": "Fixed Asset", "account_number": "1720"},
|
||||||
_("Furniture and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
_("Furnitures and Fixtures"): {"account_type": "Fixed Asset", "account_number": "1730"},
|
||||||
_("Office Equipment"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
_("Office Equipments"): {"account_type": "Fixed Asset", "account_number": "1740"},
|
||||||
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
_("Plants and Machineries"): {"account_type": "Fixed Asset", "account_number": "1750"},
|
||||||
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
_("Buildings"): {"account_type": "Fixed Asset", "account_number": "1760"},
|
||||||
_("Software"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
_("Softwares"): {"account_type": "Fixed Asset", "account_number": "1770"},
|
||||||
_("Accumulated Depreciation"): {
|
_("Accumulated Depreciation"): {
|
||||||
"account_type": "Accumulated Depreciation",
|
"account_type": "Accumulated Depreciation",
|
||||||
"account_number": "1780",
|
"account_number": "1780",
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import unittest
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe.test_runner import make_test_records
|
from frappe.test_runner import make_test_records
|
||||||
from frappe.utils import nowdate
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.account.account import (
|
from erpnext.accounts.doctype.account.account import (
|
||||||
InvalidAccountMergeError,
|
InvalidAccountMergeError,
|
||||||
@@ -120,7 +119,7 @@ class TestAccount(unittest.TestCase):
|
|||||||
InvalidAccountMergeError,
|
InvalidAccountMergeError,
|
||||||
merge_account,
|
merge_account,
|
||||||
"Capital Stock - _TC",
|
"Capital Stock - _TC",
|
||||||
"Software - _TC",
|
"Softwares - _TC",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Raise error as currency doesn't match
|
# Raise error as currency doesn't match
|
||||||
@@ -325,19 +324,6 @@ class TestAccount(unittest.TestCase):
|
|||||||
acc.account_currency = "USD"
|
acc.account_currency = "USD"
|
||||||
self.assertRaises(frappe.ValidationError, acc.save)
|
self.assertRaises(frappe.ValidationError, acc.save)
|
||||||
|
|
||||||
def test_account_balance(self):
|
|
||||||
from erpnext.accounts.utils import get_balance_on
|
|
||||||
|
|
||||||
if not frappe.db.exists("Account", "Test Percent Account %5 - _TC"):
|
|
||||||
acc = frappe.new_doc("Account")
|
|
||||||
acc.account_name = "Test Percent Account %5"
|
|
||||||
acc.parent_account = "Tax Assets - _TC"
|
|
||||||
acc.company = "_Test Company"
|
|
||||||
acc.insert()
|
|
||||||
|
|
||||||
balance = get_balance_on(account="Test Percent Account %5 - _TC", date=nowdate())
|
|
||||||
self.assertEqual(balance, 0)
|
|
||||||
|
|
||||||
|
|
||||||
def _make_test_records(verbose=None):
|
def _make_test_records(verbose=None):
|
||||||
from frappe.test_runner import make_test_objects
|
from frappe.test_runner import make_test_objects
|
||||||
|
|||||||
@@ -11,29 +11,6 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
|||||||
|
|
||||||
|
|
||||||
class AccountClosingBalance(Document):
|
class AccountClosingBalance(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account: DF.Link | None
|
|
||||||
account_currency: DF.Link | None
|
|
||||||
closing_date: DF.Date | None
|
|
||||||
company: DF.Link | None
|
|
||||||
cost_center: DF.Link | None
|
|
||||||
credit: DF.Currency
|
|
||||||
credit_in_account_currency: DF.Currency
|
|
||||||
debit: DF.Currency
|
|
||||||
debit_in_account_currency: DF.Currency
|
|
||||||
finance_book: DF.Link | None
|
|
||||||
is_period_closing_voucher_entry: DF.Check
|
|
||||||
period_closing_voucher: DF.Link | None
|
|
||||||
project: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,25 +13,6 @@ from frappe.utils import cstr
|
|||||||
|
|
||||||
|
|
||||||
class AccountingDimension(Document):
|
class AccountingDimension(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.accounting_dimension_detail.accounting_dimension_detail import (
|
|
||||||
AccountingDimensionDetail,
|
|
||||||
)
|
|
||||||
|
|
||||||
dimension_defaults: DF.Table[AccountingDimensionDetail]
|
|
||||||
disabled: DF.Check
|
|
||||||
document_type: DF.Link
|
|
||||||
fieldname: DF.Data | None
|
|
||||||
label: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def before_insert(self):
|
def before_insert(self):
|
||||||
self.set_fieldname_and_label()
|
self.set_fieldname_and_label()
|
||||||
|
|
||||||
|
|||||||
@@ -7,24 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AccountingDimensionDetail(Document):
|
class AccountingDimensionDetail(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
automatically_post_balancing_accounting_entry: DF.Check
|
|
||||||
company: DF.Link | None
|
|
||||||
default_dimension: DF.DynamicLink | None
|
|
||||||
mandatory_for_bs: DF.Check
|
|
||||||
mandatory_for_pl: DF.Check
|
|
||||||
offsetting_account: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
reference_document: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -8,28 +8,6 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AccountingDimensionFilter(Document):
|
class AccountingDimensionFilter(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.allowed_dimension.allowed_dimension import AllowedDimension
|
|
||||||
from erpnext.accounts.doctype.applicable_on_account.applicable_on_account import (
|
|
||||||
ApplicableOnAccount,
|
|
||||||
)
|
|
||||||
|
|
||||||
accounting_dimension: DF.Literal
|
|
||||||
accounts: DF.Table[ApplicableOnAccount]
|
|
||||||
allow_or_restrict: DF.Literal["Allow", "Restrict"]
|
|
||||||
apply_restriction_on_values: DF.Check
|
|
||||||
company: DF.Link
|
|
||||||
dimensions: DF.Table[AllowedDimension]
|
|
||||||
disabled: DF.Check
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def before_save(self):
|
def before_save(self):
|
||||||
# If restriction is not applied on values, then remove all the dimensions and set allow_or_restrict to Restrict
|
# If restriction is not applied on values, then remove all the dimensions and set allow_or_restrict to Restrict
|
||||||
if not self.apply_restriction_on_values:
|
if not self.apply_restriction_on_values:
|
||||||
|
|||||||
@@ -16,23 +16,6 @@ class ClosedAccountingPeriod(frappe.ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class AccountingPeriod(Document):
|
class AccountingPeriod(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.closed_document.closed_document import ClosedDocument
|
|
||||||
|
|
||||||
closed_documents: DF.Table[ClosedDocument]
|
|
||||||
company: DF.Link
|
|
||||||
end_date: DF.Date
|
|
||||||
period_name: DF.Data
|
|
||||||
start_date: DF.Date
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_overlap()
|
self.validate_overlap()
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"actions": [],
|
||||||
"creation": "2013-06-24 15:49:57",
|
"creation": "2013-06-24 15:49:57",
|
||||||
|
"description": "Settings for Accounts",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Other",
|
"document_type": "Other",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
@@ -65,12 +66,7 @@
|
|||||||
"show_balance_in_coa",
|
"show_balance_in_coa",
|
||||||
"banking_tab",
|
"banking_tab",
|
||||||
"enable_party_matching",
|
"enable_party_matching",
|
||||||
"enable_fuzzy_matching",
|
"enable_fuzzy_matching"
|
||||||
"reports_tab",
|
|
||||||
"remarks_section",
|
|
||||||
"general_ledger_remarks_length",
|
|
||||||
"column_break_lvjk",
|
|
||||||
"receivable_payable_remarks_length"
|
|
||||||
],
|
],
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
@@ -426,34 +422,6 @@
|
|||||||
"fieldname": "round_row_wise_tax",
|
"fieldname": "round_row_wise_tax",
|
||||||
"fieldtype": "Check",
|
"fieldtype": "Check",
|
||||||
"label": "Round Tax Amount Row-wise"
|
"label": "Round Tax Amount Row-wise"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "reports_tab",
|
|
||||||
"fieldtype": "Tab Break",
|
|
||||||
"label": "Reports"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"description": "Truncates 'Remarks' column to set character length",
|
|
||||||
"fieldname": "general_ledger_remarks_length",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"label": "General Ledger"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"description": "Truncates 'Remarks' column to set character length",
|
|
||||||
"fieldname": "receivable_payable_remarks_length",
|
|
||||||
"fieldtype": "Int",
|
|
||||||
"label": "Accounts Receivable/Payable"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_lvjk",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "remarks_section",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"label": "Remarks Column Length"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "icon-cog",
|
"icon": "icon-cog",
|
||||||
@@ -461,7 +429,7 @@
|
|||||||
"index_web_pages_for_search": 1,
|
"index_web_pages_for_search": 1,
|
||||||
"issingle": 1,
|
"issingle": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-30 14:04:26.553554",
|
"modified": "2023-08-28 00:12:02.740633",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Accounts Settings",
|
"name": "Accounts Settings",
|
||||||
|
|||||||
@@ -14,52 +14,6 @@ from erpnext.stock.utils import check_pending_reposting
|
|||||||
|
|
||||||
|
|
||||||
class AccountsSettings(Document):
|
class AccountsSettings(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
acc_frozen_upto: DF.Date | None
|
|
||||||
add_taxes_from_item_tax_template: DF.Check
|
|
||||||
allow_multi_currency_invoices_against_single_party_account: DF.Check
|
|
||||||
allow_stale: DF.Check
|
|
||||||
auto_reconcile_payments: DF.Check
|
|
||||||
automatically_fetch_payment_terms: DF.Check
|
|
||||||
automatically_process_deferred_accounting_entry: DF.Check
|
|
||||||
book_asset_depreciation_entry_automatically: DF.Check
|
|
||||||
book_deferred_entries_based_on: DF.Literal["Days", "Months"]
|
|
||||||
book_deferred_entries_via_journal_entry: DF.Check
|
|
||||||
book_tax_discount_loss: DF.Check
|
|
||||||
check_supplier_invoice_uniqueness: DF.Check
|
|
||||||
credit_controller: DF.Link | None
|
|
||||||
delete_linked_ledger_entries: DF.Check
|
|
||||||
determine_address_tax_category_from: DF.Literal["Billing Address", "Shipping Address"]
|
|
||||||
enable_common_party_accounting: DF.Check
|
|
||||||
enable_fuzzy_matching: DF.Check
|
|
||||||
enable_party_matching: DF.Check
|
|
||||||
frozen_accounts_modifier: DF.Link | None
|
|
||||||
general_ledger_remarks_length: DF.Int
|
|
||||||
ignore_account_closing_balance: DF.Check
|
|
||||||
make_payment_via_journal_entry: DF.Check
|
|
||||||
merge_similar_account_heads: DF.Check
|
|
||||||
over_billing_allowance: DF.Currency
|
|
||||||
post_change_gl_entries: DF.Check
|
|
||||||
receivable_payable_remarks_length: DF.Int
|
|
||||||
role_allowed_to_over_bill: DF.Link | None
|
|
||||||
round_row_wise_tax: DF.Check
|
|
||||||
show_balance_in_coa: DF.Check
|
|
||||||
show_inclusive_tax_in_print: DF.Check
|
|
||||||
show_payment_schedule_in_print: DF.Check
|
|
||||||
show_taxes_as_table_in_print: DF.Check
|
|
||||||
stale_days: DF.Int
|
|
||||||
submit_journal_entries: DF.Check
|
|
||||||
unlink_advance_payment_on_cancelation_of_order: DF.Check
|
|
||||||
unlink_payment_on_cancellation_of_invoice: DF.Check
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
old_doc = self.get_doc_before_save()
|
old_doc = self.get_doc_before_save()
|
||||||
clear_cache = False
|
clear_cache = False
|
||||||
|
|||||||
@@ -6,22 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AdvanceTax(Document):
|
class AdvanceTax(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_head: DF.Link | None
|
|
||||||
allocated_amount: DF.Currency
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
reference_detail: DF.Data | None
|
|
||||||
reference_name: DF.DynamicLink | None
|
|
||||||
reference_type: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,33 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AdvanceTaxesandCharges(Document):
|
class AdvanceTaxesandCharges(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_head: DF.Link
|
|
||||||
add_deduct_tax: DF.Literal["Add", "Deduct"]
|
|
||||||
allocated_amount: DF.Currency
|
|
||||||
base_tax_amount: DF.Currency
|
|
||||||
base_total: DF.Currency
|
|
||||||
charge_type: DF.Literal[
|
|
||||||
"", "Actual", "On Paid Amount", "On Previous Row Amount", "On Previous Row Total"
|
|
||||||
]
|
|
||||||
cost_center: DF.Link | None
|
|
||||||
currency: DF.Link | None
|
|
||||||
description: DF.SmallText
|
|
||||||
included_in_paid_amount: DF.Check
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
rate: DF.Float
|
|
||||||
row_id: DF.Data | None
|
|
||||||
tax_amount: DF.Currency
|
|
||||||
total: DF.Currency
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,19 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AllowedDimension(Document):
|
class AllowedDimension(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
accounting_dimension: DF.Link | None
|
|
||||||
dimension_value: DF.DynamicLink | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "company",
|
"fieldname": "company",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
"ignore_user_permissions": 1,
|
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"label": "Company",
|
"label": "Company",
|
||||||
"options": "Company",
|
"options": "Company",
|
||||||
@@ -20,7 +19,7 @@
|
|||||||
],
|
],
|
||||||
"istable": 1,
|
"istable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-03 11:13:02.669632",
|
"modified": "2020-05-01 12:32:34.044911",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Allowed To Transact With",
|
"name": "Allowed To Transact With",
|
||||||
@@ -29,6 +28,5 @@
|
|||||||
"quick_entry": 1,
|
"quick_entry": 1,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
|
||||||
"track_changes": 1
|
"track_changes": 1
|
||||||
}
|
}
|
||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class AllowedToTransactWith(Document):
|
class AllowedToTransactWith(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
company: DF.Link
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,19 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class ApplicableOnAccount(Document):
|
class ApplicableOnAccount(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
applicable_on_account: DF.Link
|
|
||||||
is_mandatory: DF.Check
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -10,25 +10,6 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class Bank(Document):
|
class Bank(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_transaction_mapping.bank_transaction_mapping import (
|
|
||||||
BankTransactionMapping,
|
|
||||||
)
|
|
||||||
|
|
||||||
bank_name: DF.Data
|
|
||||||
bank_transaction_mapping: DF.Table[BankTransactionMapping]
|
|
||||||
plaid_access_token: DF.Data | None
|
|
||||||
swift_number: DF.Data | None
|
|
||||||
website: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
"""Load address and contacts in `__onload`"""
|
"""Load address and contacts in `__onload`"""
|
||||||
load_address_and_contact(self)
|
load_address_and_contact(self)
|
||||||
|
|||||||
@@ -9,37 +9,9 @@ from frappe.contacts.address_and_contact import (
|
|||||||
load_address_and_contact,
|
load_address_and_contact,
|
||||||
)
|
)
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import comma_and, get_link_to_form
|
|
||||||
|
|
||||||
|
|
||||||
class BankAccount(Document):
|
class BankAccount(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account: DF.Link | None
|
|
||||||
account_name: DF.Data
|
|
||||||
account_subtype: DF.Link | None
|
|
||||||
account_type: DF.Link | None
|
|
||||||
bank: DF.Link
|
|
||||||
bank_account_no: DF.Data | None
|
|
||||||
branch_code: DF.Data | None
|
|
||||||
company: DF.Link | None
|
|
||||||
disabled: DF.Check
|
|
||||||
iban: DF.Data | None
|
|
||||||
integration_id: DF.Data | None
|
|
||||||
is_company_account: DF.Check
|
|
||||||
is_default: DF.Check
|
|
||||||
last_integration_date: DF.Date | None
|
|
||||||
mask: DF.Data | None
|
|
||||||
party: DF.DynamicLink | None
|
|
||||||
party_type: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def onload(self):
|
def onload(self):
|
||||||
"""Load address and contacts in `__onload`"""
|
"""Load address and contacts in `__onload`"""
|
||||||
load_address_and_contact(self)
|
load_address_and_contact(self)
|
||||||
@@ -53,21 +25,10 @@ class BankAccount(Document):
|
|||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_company()
|
self.validate_company()
|
||||||
self.validate_iban()
|
self.validate_iban()
|
||||||
self.validate_account()
|
|
||||||
|
|
||||||
def validate_account(self):
|
|
||||||
if self.account:
|
|
||||||
if accounts := frappe.db.get_all("Bank Account", filters={"account": self.account}, as_list=1):
|
|
||||||
frappe.throw(
|
|
||||||
_("'{0}' account is already used by {1}. Use another account.").format(
|
|
||||||
frappe.bold(self.account),
|
|
||||||
frappe.bold(comma_and([get_link_to_form(self.doctype, x[0]) for x in accounts])),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_company(self):
|
def validate_company(self):
|
||||||
if self.is_company_account and not self.company:
|
if self.is_company_account and not self.company:
|
||||||
frappe.throw(_("Company is mandatory for company account"))
|
frappe.throw(_("Company is manadatory for company account"))
|
||||||
|
|
||||||
def validate_iban(self):
|
def validate_iban(self):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -6,15 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankAccountSubtype(Document):
|
class BankAccountSubtype(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_subtype: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,15 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankAccountType(Document):
|
class BankAccountType(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_type: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -5,9 +5,7 @@
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe import _, msgprint
|
from frappe import _, msgprint
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.query_builder.custom import ConstantColumn
|
|
||||||
from frappe.utils import flt, fmt_money, getdate
|
from frappe.utils import flt, fmt_money, getdate
|
||||||
from pypika import Order
|
|
||||||
|
|
||||||
import erpnext
|
import erpnext
|
||||||
|
|
||||||
@@ -15,28 +13,6 @@ form_grid_templates = {"journal_entries": "templates/form_grid/bank_reconciliati
|
|||||||
|
|
||||||
|
|
||||||
class BankClearance(Document):
|
class BankClearance(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_clearance_detail.bank_clearance_detail import (
|
|
||||||
BankClearanceDetail,
|
|
||||||
)
|
|
||||||
|
|
||||||
account: DF.Link
|
|
||||||
account_currency: DF.Link | None
|
|
||||||
bank_account: DF.Link | None
|
|
||||||
from_date: DF.Date
|
|
||||||
include_pos_transactions: DF.Check
|
|
||||||
include_reconciled_entries: DF.Check
|
|
||||||
payment_entries: DF.Table[BankClearanceDetail]
|
|
||||||
to_date: DF.Date
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def get_payment_entries(self):
|
def get_payment_entries(self):
|
||||||
if not (self.from_date and self.to_date):
|
if not (self.from_date and self.to_date):
|
||||||
@@ -181,62 +157,39 @@ def get_payment_entries_for_bank_clearance(
|
|||||||
|
|
||||||
pos_sales_invoices, pos_purchase_invoices = [], []
|
pos_sales_invoices, pos_purchase_invoices = [], []
|
||||||
if include_pos_transactions:
|
if include_pos_transactions:
|
||||||
si_payment = frappe.qb.DocType("Sales Invoice Payment")
|
pos_sales_invoices = frappe.db.sql(
|
||||||
si = frappe.qb.DocType("Sales Invoice")
|
"""
|
||||||
acc = frappe.qb.DocType("Account")
|
select
|
||||||
|
"Sales Invoice Payment" as payment_document, sip.name as payment_entry, sip.amount as debit,
|
||||||
|
si.posting_date, si.customer as against_account, sip.clearance_date,
|
||||||
|
account.account_currency, 0 as credit
|
||||||
|
from `tabSales Invoice Payment` sip, `tabSales Invoice` si, `tabAccount` account
|
||||||
|
where
|
||||||
|
sip.account=%(account)s and si.docstatus=1 and sip.parent = si.name
|
||||||
|
and account.name = sip.account and si.posting_date >= %(from)s and si.posting_date <= %(to)s
|
||||||
|
order by
|
||||||
|
si.posting_date ASC, si.name DESC
|
||||||
|
""",
|
||||||
|
{"account": account, "from": from_date, "to": to_date},
|
||||||
|
as_dict=1,
|
||||||
|
)
|
||||||
|
|
||||||
pos_sales_invoices = (
|
pos_purchase_invoices = frappe.db.sql(
|
||||||
frappe.qb.from_(si_payment)
|
"""
|
||||||
.inner_join(si)
|
select
|
||||||
.on(si_payment.parent == si.name)
|
"Purchase Invoice" as payment_document, pi.name as payment_entry, pi.paid_amount as credit,
|
||||||
.inner_join(acc)
|
pi.posting_date, pi.supplier as against_account, pi.clearance_date,
|
||||||
.on(si_payment.account == acc.name)
|
account.account_currency, 0 as debit
|
||||||
.select(
|
from `tabPurchase Invoice` pi, `tabAccount` account
|
||||||
ConstantColumn("Sales Invoice").as_("payment_document"),
|
where
|
||||||
si.name.as_("payment_entry"),
|
pi.cash_bank_account=%(account)s and pi.docstatus=1 and account.name = pi.cash_bank_account
|
||||||
si_payment.reference_no.as_("cheque_number"),
|
and pi.posting_date >= %(from)s and pi.posting_date <= %(to)s
|
||||||
si_payment.amount.as_("debit"),
|
order by
|
||||||
si.posting_date,
|
pi.posting_date ASC, pi.name DESC
|
||||||
si.customer.as_("against_account"),
|
""",
|
||||||
si_payment.clearance_date,
|
{"account": account, "from": from_date, "to": to_date},
|
||||||
acc.account_currency,
|
as_dict=1,
|
||||||
ConstantColumn(0).as_("credit"),
|
)
|
||||||
)
|
|
||||||
.where(
|
|
||||||
(si.docstatus == 1)
|
|
||||||
& (si_payment.account == account)
|
|
||||||
& (si.posting_date >= from_date)
|
|
||||||
& (si.posting_date <= to_date)
|
|
||||||
)
|
|
||||||
.orderby(si.posting_date)
|
|
||||||
.orderby(si.name, order=Order.desc)
|
|
||||||
).run(as_dict=True)
|
|
||||||
|
|
||||||
pi = frappe.qb.DocType("Purchase Invoice")
|
|
||||||
|
|
||||||
pos_purchase_invoices = (
|
|
||||||
frappe.qb.from_(pi)
|
|
||||||
.inner_join(acc)
|
|
||||||
.on(pi.cash_bank_account == acc.name)
|
|
||||||
.select(
|
|
||||||
ConstantColumn("Purchase Invoice").as_("payment_document"),
|
|
||||||
pi.name.as_("payment_entry"),
|
|
||||||
pi.paid_amount.as_("credit"),
|
|
||||||
pi.posting_date,
|
|
||||||
pi.supplier.as_("against_account"),
|
|
||||||
pi.clearance_date,
|
|
||||||
acc.account_currency,
|
|
||||||
ConstantColumn(0).as_("debit"),
|
|
||||||
)
|
|
||||||
.where(
|
|
||||||
(pi.docstatus == 1)
|
|
||||||
& (pi.cash_bank_account == account)
|
|
||||||
& (pi.posting_date >= from_date)
|
|
||||||
& (pi.posting_date <= to_date)
|
|
||||||
)
|
|
||||||
.orderby(pi.posting_date)
|
|
||||||
.orderby(pi.name, order=Order.desc)
|
|
||||||
).run(as_dict=True)
|
|
||||||
|
|
||||||
entries = (
|
entries = (
|
||||||
list(payment_entries)
|
list(payment_entries)
|
||||||
|
|||||||
@@ -6,25 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankClearanceDetail(Document):
|
class BankClearanceDetail(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
against_account: DF.Data | None
|
|
||||||
amount: DF.Data | None
|
|
||||||
cheque_date: DF.Date | None
|
|
||||||
cheque_number: DF.Data | None
|
|
||||||
clearance_date: DF.Date | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
payment_document: DF.Link | None
|
|
||||||
payment_entry: DF.DynamicLink | None
|
|
||||||
posting_date: DF.Date | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -8,51 +8,17 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankGuarantee(Document):
|
class BankGuarantee(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account: DF.Link | None
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
amount: DF.Currency
|
|
||||||
bank: DF.Link | None
|
|
||||||
bank_account: DF.Link | None
|
|
||||||
bank_account_no: DF.Data | None
|
|
||||||
bank_guarantee_number: DF.Data | None
|
|
||||||
bg_type: DF.Literal["", "Receiving", "Providing"]
|
|
||||||
branch_code: DF.Data | None
|
|
||||||
charges: DF.Currency
|
|
||||||
customer: DF.Link | None
|
|
||||||
end_date: DF.Date | None
|
|
||||||
fixed_deposit_number: DF.Data | None
|
|
||||||
iban: DF.Data | None
|
|
||||||
margin_money: DF.Currency
|
|
||||||
more_information: DF.TextEditor | None
|
|
||||||
name_of_beneficiary: DF.Data | None
|
|
||||||
project: DF.Link | None
|
|
||||||
reference_docname: DF.DynamicLink | None
|
|
||||||
reference_doctype: DF.Link | None
|
|
||||||
start_date: DF.Date
|
|
||||||
supplier: DF.Link | None
|
|
||||||
swift_number: DF.Data | None
|
|
||||||
validity: DF.Int
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if not (self.customer or self.supplier):
|
if not (self.customer or self.supplier):
|
||||||
frappe.throw(_("Select the customer or supplier."))
|
frappe.throw(_("Select the customer or supplier."))
|
||||||
|
|
||||||
def on_submit(self):
|
def on_submit(self):
|
||||||
if not self.bank_guarantee_number:
|
if not self.bank_guarantee_number:
|
||||||
frappe.throw(_("Enter the Bank Guarantee Number before submitting."))
|
frappe.throw(_("Enter the Bank Guarantee Number before submittting."))
|
||||||
if not self.name_of_beneficiary:
|
if not self.name_of_beneficiary:
|
||||||
frappe.throw(_("Enter the name of the Beneficiary before submitting."))
|
frappe.throw(_("Enter the name of the Beneficiary before submittting."))
|
||||||
if not self.bank:
|
if not self.bank:
|
||||||
frappe.throw(_("Enter the name of the bank or lending institution before submitting."))
|
frappe.throw(_("Enter the name of the bank or lending institution before submittting."))
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ frappe.ui.form.on("Bank Reconciliation Tool", {
|
|||||||
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
"erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.get_account_balance",
|
||||||
args: {
|
args: {
|
||||||
bank_account: frm.doc.bank_account,
|
bank_account: frm.doc.bank_account,
|
||||||
till_date: frappe.datetime.add_days(frm.doc.bank_statement_from_date, -1)
|
till_date: frm.doc.bank_statement_from_date,
|
||||||
},
|
},
|
||||||
callback: (response) => {
|
callback: (response) => {
|
||||||
frm.set_value("account_opening_balance", response.message);
|
frm.set_value("account_opening_balance", response.message);
|
||||||
|
|||||||
@@ -18,30 +18,9 @@ from erpnext.accounts.report.bank_reconciliation_statement.bank_reconciliation_s
|
|||||||
get_entries,
|
get_entries,
|
||||||
)
|
)
|
||||||
from erpnext.accounts.utils import get_account_currency, get_balance_on
|
from erpnext.accounts.utils import get_account_currency, get_balance_on
|
||||||
from erpnext.setup.utils import get_exchange_rate
|
|
||||||
|
|
||||||
|
|
||||||
class BankReconciliationTool(Document):
|
class BankReconciliationTool(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account_currency: DF.Link | None
|
|
||||||
account_opening_balance: DF.Currency
|
|
||||||
bank_account: DF.Link | None
|
|
||||||
bank_statement_closing_balance: DF.Currency
|
|
||||||
bank_statement_from_date: DF.Date | None
|
|
||||||
bank_statement_to_date: DF.Date | None
|
|
||||||
company: DF.Link | None
|
|
||||||
filter_by_reference_date: DF.Check
|
|
||||||
from_reference_date: DF.Date | None
|
|
||||||
to_reference_date: DF.Date | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -151,7 +130,7 @@ def create_journal_entry_bts(
|
|||||||
bank_transaction = frappe.db.get_values(
|
bank_transaction = frappe.db.get_values(
|
||||||
"Bank Transaction",
|
"Bank Transaction",
|
||||||
bank_transaction_name,
|
bank_transaction_name,
|
||||||
fieldname=["name", "deposit", "withdrawal", "bank_account", "currency"],
|
fieldname=["name", "deposit", "withdrawal", "bank_account"],
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)[0]
|
)[0]
|
||||||
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
|
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account")
|
||||||
@@ -165,94 +144,29 @@ def create_journal_entry_bts(
|
|||||||
)
|
)
|
||||||
|
|
||||||
company = frappe.get_value("Account", company_account, "company")
|
company = frappe.get_value("Account", company_account, "company")
|
||||||
company_default_currency = frappe.get_cached_value("Company", company, "default_currency")
|
|
||||||
company_account_currency = frappe.get_cached_value("Account", company_account, "account_currency")
|
|
||||||
second_account_currency = frappe.get_cached_value("Account", second_account, "account_currency")
|
|
||||||
|
|
||||||
# determine if multi-currency Journal or not
|
|
||||||
is_multi_currency = (
|
|
||||||
True
|
|
||||||
if company_default_currency != company_account_currency
|
|
||||||
or company_default_currency != second_account_currency
|
|
||||||
or company_default_currency != bank_transaction.currency
|
|
||||||
else False
|
|
||||||
)
|
|
||||||
|
|
||||||
accounts = []
|
accounts = []
|
||||||
second_account_dict = {
|
# Multi Currency?
|
||||||
"account": second_account,
|
accounts.append(
|
||||||
"account_currency": second_account_currency,
|
{
|
||||||
"credit_in_account_currency": bank_transaction.deposit,
|
"account": second_account,
|
||||||
"debit_in_account_currency": bank_transaction.withdrawal,
|
"credit_in_account_currency": bank_transaction.deposit,
|
||||||
"party_type": party_type,
|
"debit_in_account_currency": bank_transaction.withdrawal,
|
||||||
"party": party,
|
"party_type": party_type,
|
||||||
"cost_center": get_default_cost_center(company),
|
"party": party,
|
||||||
}
|
"cost_center": get_default_cost_center(company),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
company_account_dict = {
|
accounts.append(
|
||||||
"account": company_account,
|
{
|
||||||
"account_currency": company_account_currency,
|
"account": company_account,
|
||||||
"bank_account": bank_transaction.bank_account,
|
"bank_account": bank_transaction.bank_account,
|
||||||
"credit_in_account_currency": bank_transaction.withdrawal,
|
"credit_in_account_currency": bank_transaction.withdrawal,
|
||||||
"debit_in_account_currency": bank_transaction.deposit,
|
"debit_in_account_currency": bank_transaction.deposit,
|
||||||
"cost_center": get_default_cost_center(company),
|
"cost_center": get_default_cost_center(company),
|
||||||
}
|
}
|
||||||
|
)
|
||||||
# convert transaction amount to company currency
|
|
||||||
if is_multi_currency:
|
|
||||||
exc_rate = get_exchange_rate(bank_transaction.currency, company_default_currency, posting_date)
|
|
||||||
withdrawal_in_company_currency = flt(exc_rate * abs(bank_transaction.withdrawal))
|
|
||||||
deposit_in_company_currency = flt(exc_rate * abs(bank_transaction.deposit))
|
|
||||||
else:
|
|
||||||
withdrawal_in_company_currency = bank_transaction.withdrawal
|
|
||||||
deposit_in_company_currency = bank_transaction.deposit
|
|
||||||
|
|
||||||
# if second account is of foreign currency, convert and set debit and credit fields.
|
|
||||||
if second_account_currency != company_default_currency:
|
|
||||||
exc_rate = get_exchange_rate(second_account_currency, company_default_currency, posting_date)
|
|
||||||
second_account_dict.update(
|
|
||||||
{
|
|
||||||
"exchange_rate": exc_rate,
|
|
||||||
"credit": deposit_in_company_currency,
|
|
||||||
"debit": withdrawal_in_company_currency,
|
|
||||||
"credit_in_account_currency": flt(deposit_in_company_currency / exc_rate) or 0,
|
|
||||||
"debit_in_account_currency": flt(withdrawal_in_company_currency / exc_rate) or 0,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
second_account_dict.update(
|
|
||||||
{
|
|
||||||
"exchange_rate": 1,
|
|
||||||
"credit": deposit_in_company_currency,
|
|
||||||
"debit": withdrawal_in_company_currency,
|
|
||||||
"credit_in_account_currency": deposit_in_company_currency,
|
|
||||||
"debit_in_account_currency": withdrawal_in_company_currency,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
# if company account is of foreign currency, convert and set debit and credit fields.
|
|
||||||
if company_account_currency != company_default_currency:
|
|
||||||
exc_rate = get_exchange_rate(company_account_currency, company_default_currency, posting_date)
|
|
||||||
company_account_dict.update(
|
|
||||||
{
|
|
||||||
"exchange_rate": exc_rate,
|
|
||||||
"credit": withdrawal_in_company_currency,
|
|
||||||
"debit": deposit_in_company_currency,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
company_account_dict.update(
|
|
||||||
{
|
|
||||||
"exchange_rate": 1,
|
|
||||||
"credit": withdrawal_in_company_currency,
|
|
||||||
"debit": deposit_in_company_currency,
|
|
||||||
"credit_in_account_currency": withdrawal_in_company_currency,
|
|
||||||
"debit_in_account_currency": deposit_in_company_currency,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
accounts.append(second_account_dict)
|
|
||||||
accounts.append(company_account_dict)
|
|
||||||
|
|
||||||
journal_entry_dict = {
|
journal_entry_dict = {
|
||||||
"voucher_type": entry_type,
|
"voucher_type": entry_type,
|
||||||
@@ -262,9 +176,6 @@ def create_journal_entry_bts(
|
|||||||
"cheque_no": reference_number,
|
"cheque_no": reference_number,
|
||||||
"mode_of_payment": mode_of_payment,
|
"mode_of_payment": mode_of_payment,
|
||||||
}
|
}
|
||||||
if is_multi_currency:
|
|
||||||
journal_entry_dict.update({"multi_currency": True})
|
|
||||||
|
|
||||||
journal_entry = frappe.new_doc("Journal Entry")
|
journal_entry = frappe.new_doc("Journal Entry")
|
||||||
journal_entry.update(journal_entry_dict)
|
journal_entry.update(journal_entry_dict)
|
||||||
journal_entry.set("accounts", accounts)
|
journal_entry.set("accounts", accounts)
|
||||||
@@ -444,13 +355,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
|
|||||||
vouchers = json.loads(vouchers)
|
vouchers = json.loads(vouchers)
|
||||||
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||||
transaction.add_payment_entries(vouchers)
|
transaction.add_payment_entries(vouchers)
|
||||||
transaction.validate_duplicate_references()
|
return frappe.get_doc("Bank Transaction", bank_transaction_name)
|
||||||
transaction.allocate_payment_entries()
|
|
||||||
transaction.update_allocated_amount()
|
|
||||||
transaction.set_status()
|
|
||||||
transaction.save()
|
|
||||||
|
|
||||||
return transaction
|
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
|
|||||||
@@ -76,7 +76,6 @@ class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
|
|||||||
"deposit": 100,
|
"deposit": 100,
|
||||||
"bank_account": self.bank_account,
|
"bank_account": self.bank_account,
|
||||||
"reference_number": "123",
|
"reference_number": "123",
|
||||||
"currency": "INR",
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.save()
|
.save()
|
||||||
|
|||||||
@@ -2,16 +2,6 @@
|
|||||||
// For license information, please see license.txt
|
// For license information, please see license.txt
|
||||||
|
|
||||||
frappe.ui.form.on("Bank Statement Import", {
|
frappe.ui.form.on("Bank Statement Import", {
|
||||||
onload(frm) {
|
|
||||||
frm.set_query("bank_account", function (doc) {
|
|
||||||
return {
|
|
||||||
filters: {
|
|
||||||
company: doc.company,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
setup(frm) {
|
setup(frm) {
|
||||||
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
|
frappe.realtime.on("data_import_refresh", ({ data_import }) => {
|
||||||
frm.import_in_progress = false;
|
frm.import_in_progress = false;
|
||||||
|
|||||||
@@ -20,30 +20,6 @@ INVALID_VALUES = ("", None)
|
|||||||
|
|
||||||
|
|
||||||
class BankStatementImport(DataImport):
|
class BankStatementImport(DataImport):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
bank: DF.Link | None
|
|
||||||
bank_account: DF.Link
|
|
||||||
company: DF.Link
|
|
||||||
google_sheets_url: DF.Data | None
|
|
||||||
import_file: DF.Attach | None
|
|
||||||
import_type: DF.Literal["", "Insert New Records", "Update Existing Records"]
|
|
||||||
mute_emails: DF.Check
|
|
||||||
reference_doctype: DF.Link
|
|
||||||
show_failed_logs: DF.Check
|
|
||||||
statement_import_log: DF.Code | None
|
|
||||||
status: DF.Literal["Pending", "Success", "Partial Success", "Error"]
|
|
||||||
submit_after_import: DF.Check
|
|
||||||
template_options: DF.Code | None
|
|
||||||
template_warnings: DF.Code | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(BankStatementImport, self).__init__(*args, **kwargs)
|
super(BankStatementImport, self).__init__(*args, **kwargs)
|
||||||
|
|
||||||
@@ -80,8 +56,7 @@ class BankStatementImport(DataImport):
|
|||||||
from frappe.utils.background_jobs import is_job_enqueued
|
from frappe.utils.background_jobs import is_job_enqueued
|
||||||
from frappe.utils.scheduler import is_scheduler_inactive
|
from frappe.utils.scheduler import is_scheduler_inactive
|
||||||
|
|
||||||
run_now = frappe.flags.in_test or frappe.conf.developer_mode
|
if is_scheduler_inactive() and not frappe.flags.in_test:
|
||||||
if is_scheduler_inactive() and not run_now:
|
|
||||||
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
|
frappe.throw(_("Scheduler is inactive. Cannot import data."), title=_("Scheduler Inactive"))
|
||||||
|
|
||||||
job_id = f"bank_statement_import::{self.name}"
|
job_id = f"bank_statement_import::{self.name}"
|
||||||
@@ -98,7 +73,7 @@ class BankStatementImport(DataImport):
|
|||||||
google_sheets_url=self.google_sheets_url,
|
google_sheets_url=self.google_sheets_url,
|
||||||
bank=self.bank,
|
bank=self.bank,
|
||||||
template_options=self.template_options,
|
template_options=self.template_options,
|
||||||
now=run_now,
|
now=frappe.conf.developer_mode or frappe.flags.in_test,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
for party in parties:
|
for party in parties:
|
||||||
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
|
filters = {"status": "Active"} if party == "Employee" else {"disabled": 0}
|
||||||
field = party.lower() + "_name"
|
names = frappe.get_all(party, filters=filters, pluck=party.lower() + "_name")
|
||||||
names = frappe.get_all(party, filters=filters, fields=[f"{field} as party_name", "name"])
|
|
||||||
|
|
||||||
for field in ["bank_party_name", "description"]:
|
for field in ["bank_party_name", "description"]:
|
||||||
if not self.get(field):
|
if not self.get(field):
|
||||||
@@ -132,11 +131,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
|
def fuzzy_search_and_return_result(self, party, names, field) -> Union[Tuple, None]:
|
||||||
skip = False
|
skip = False
|
||||||
result = process.extract(
|
result = process.extract(query=self.get(field), choices=names, scorer=fuzz.token_set_ratio)
|
||||||
query=self.get(field),
|
|
||||||
choices={row.get("name"): row.get("party_name") for row in names},
|
|
||||||
scorer=fuzz.token_set_ratio,
|
|
||||||
)
|
|
||||||
party_name, skip = self.process_fuzzy_result(result)
|
party_name, skip = self.process_fuzzy_result(result)
|
||||||
|
|
||||||
if not party_name:
|
if not party_name:
|
||||||
@@ -154,14 +149,14 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
|
|
||||||
Returns: Result, Skip (whether or not to discontinue matching)
|
Returns: Result, Skip (whether or not to discontinue matching)
|
||||||
"""
|
"""
|
||||||
SCORE, PARTY_ID, CUTOFF = 1, 2, 80
|
PARTY, SCORE, CUTOFF = 0, 1, 80
|
||||||
|
|
||||||
if not result or not len(result):
|
if not result or not len(result):
|
||||||
return None, False
|
return None, False
|
||||||
|
|
||||||
first_result = result[0]
|
first_result = result[0]
|
||||||
if len(result) == 1:
|
if len(result) == 1:
|
||||||
return (first_result[PARTY_ID] if first_result[SCORE] > CUTOFF else None), True
|
return (first_result[PARTY] if first_result[SCORE] > CUTOFF else None), True
|
||||||
|
|
||||||
second_result = result[1]
|
second_result = result[1]
|
||||||
if first_result[SCORE] > CUTOFF:
|
if first_result[SCORE] > CUTOFF:
|
||||||
@@ -170,7 +165,7 @@ class AutoMatchbyPartyNameDescription:
|
|||||||
if first_result[SCORE] == second_result[SCORE]:
|
if first_result[SCORE] == second_result[SCORE]:
|
||||||
return None, True
|
return None, True
|
||||||
|
|
||||||
return first_result[PARTY_ID], True
|
return first_result[PARTY], True
|
||||||
else:
|
else:
|
||||||
return None, False
|
return None, False
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
"status",
|
"status",
|
||||||
"bank_account",
|
"bank_account",
|
||||||
"company",
|
"company",
|
||||||
"amended_from",
|
|
||||||
"section_break_4",
|
"section_break_4",
|
||||||
"deposit",
|
"deposit",
|
||||||
"withdrawal",
|
"withdrawal",
|
||||||
@@ -26,10 +25,10 @@
|
|||||||
"transaction_id",
|
"transaction_id",
|
||||||
"transaction_type",
|
"transaction_type",
|
||||||
"section_break_14",
|
"section_break_14",
|
||||||
"column_break_oufv",
|
|
||||||
"payment_entries",
|
"payment_entries",
|
||||||
"section_break_18",
|
"section_break_18",
|
||||||
"allocated_amount",
|
"allocated_amount",
|
||||||
|
"amended_from",
|
||||||
"column_break_17",
|
"column_break_17",
|
||||||
"unallocated_amount",
|
"unallocated_amount",
|
||||||
"party_section",
|
"party_section",
|
||||||
@@ -139,12 +138,10 @@
|
|||||||
"fieldtype": "Section Break"
|
"fieldtype": "Section Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
|
||||||
"fieldname": "allocated_amount",
|
"fieldname": "allocated_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Allocated Amount",
|
"label": "Allocated Amount",
|
||||||
"options": "currency",
|
"options": "currency"
|
||||||
"read_only": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
@@ -160,12 +157,10 @@
|
|||||||
"fieldtype": "Column Break"
|
"fieldtype": "Column Break"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"allow_on_submit": 1,
|
|
||||||
"fieldname": "unallocated_amount",
|
"fieldname": "unallocated_amount",
|
||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Unallocated Amount",
|
"label": "Unallocated Amount",
|
||||||
"options": "currency",
|
"options": "currency"
|
||||||
"read_only": 1
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "party_section",
|
"fieldname": "party_section",
|
||||||
@@ -230,15 +225,11 @@
|
|||||||
"fieldname": "bank_party_account_number",
|
"fieldname": "bank_party_account_number",
|
||||||
"fieldtype": "Data",
|
"fieldtype": "Data",
|
||||||
"label": "Party Account No. (Bank Statement)"
|
"label": "Party Account No. (Bank Statement)"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_oufv",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-11-18 18:32:47.203694",
|
"modified": "2023-06-06 13:58:12.821411",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Bank Transaction",
|
"name": "Bank Transaction",
|
||||||
|
|||||||
@@ -2,136 +2,78 @@
|
|||||||
# For license information, please see license.txt
|
# For license information, please see license.txt
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
|
||||||
from frappe.model.docstatus import DocStatus
|
|
||||||
from frappe.model.document import Document
|
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
|
|
||||||
|
from erpnext.controllers.status_updater import StatusUpdater
|
||||||
|
|
||||||
class BankTransaction(Document):
|
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
class BankTransaction(StatusUpdater):
|
||||||
|
def after_insert(self):
|
||||||
|
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit))
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
def on_submit(self):
|
||||||
from frappe.types import DF
|
self.clear_linked_payment_entries()
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_transaction_payments.bank_transaction_payments import (
|
|
||||||
BankTransactionPayments,
|
|
||||||
)
|
|
||||||
|
|
||||||
allocated_amount: DF.Currency
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
bank_account: DF.Link | None
|
|
||||||
bank_party_account_number: DF.Data | None
|
|
||||||
bank_party_iban: DF.Data | None
|
|
||||||
bank_party_name: DF.Data | None
|
|
||||||
company: DF.Link | None
|
|
||||||
currency: DF.Link | None
|
|
||||||
date: DF.Date | None
|
|
||||||
deposit: DF.Currency
|
|
||||||
description: DF.SmallText | None
|
|
||||||
naming_series: DF.Literal["ACC-BTN-.YYYY.-"]
|
|
||||||
party: DF.DynamicLink | None
|
|
||||||
party_type: DF.Link | None
|
|
||||||
payment_entries: DF.Table[BankTransactionPayments]
|
|
||||||
reference_number: DF.Data | None
|
|
||||||
status: DF.Literal["", "Pending", "Settled", "Unreconciled", "Reconciled", "Cancelled"]
|
|
||||||
transaction_id: DF.Data | None
|
|
||||||
transaction_type: DF.Data | None
|
|
||||||
unallocated_amount: DF.Currency
|
|
||||||
withdrawal: DF.Currency
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def before_validate(self):
|
|
||||||
self.update_allocated_amount()
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
self.validate_duplicate_references()
|
|
||||||
self.validate_currency()
|
|
||||||
|
|
||||||
def validate_currency(self):
|
|
||||||
"""
|
|
||||||
Bank Transaction should be on the same currency as the Bank Account.
|
|
||||||
"""
|
|
||||||
if self.currency and self.bank_account:
|
|
||||||
account = frappe.get_cached_value("Bank Account", self.bank_account, "account")
|
|
||||||
account_currency = frappe.get_cached_value("Account", account, "account_currency")
|
|
||||||
|
|
||||||
if self.currency != account_currency:
|
|
||||||
frappe.throw(
|
|
||||||
_(
|
|
||||||
"Transaction currency: {0} cannot be different from Bank Account({1}) currency: {2}"
|
|
||||||
).format(
|
|
||||||
frappe.bold(self.currency), frappe.bold(self.bank_account), frappe.bold(account_currency)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def set_status(self):
|
|
||||||
if self.docstatus == 2:
|
|
||||||
self.db_set("status", "Cancelled")
|
|
||||||
elif self.docstatus == 1:
|
|
||||||
if self.unallocated_amount > 0:
|
|
||||||
self.db_set("status", "Unreconciled")
|
|
||||||
elif self.unallocated_amount <= 0:
|
|
||||||
self.db_set("status", "Reconciled")
|
|
||||||
|
|
||||||
def validate_duplicate_references(self):
|
|
||||||
"""Make sure the same voucher is not allocated twice within the same Bank Transaction"""
|
|
||||||
if not self.payment_entries:
|
|
||||||
return
|
|
||||||
|
|
||||||
pe = []
|
|
||||||
for row in self.payment_entries:
|
|
||||||
reference = (row.payment_document, row.payment_entry)
|
|
||||||
if reference in pe:
|
|
||||||
frappe.throw(
|
|
||||||
_("{0} {1} is allocated twice in this Bank Transaction").format(
|
|
||||||
row.payment_document, row.payment_entry
|
|
||||||
)
|
|
||||||
)
|
|
||||||
pe.append(reference)
|
|
||||||
|
|
||||||
def update_allocated_amount(self):
|
|
||||||
self.allocated_amount = (
|
|
||||||
sum(p.allocated_amount for p in self.payment_entries) if self.payment_entries else 0.0
|
|
||||||
)
|
|
||||||
self.unallocated_amount = abs(flt(self.withdrawal) - flt(self.deposit)) - self.allocated_amount
|
|
||||||
|
|
||||||
def before_submit(self):
|
|
||||||
self.allocate_payment_entries()
|
|
||||||
self.set_status()
|
self.set_status()
|
||||||
|
|
||||||
if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"):
|
if frappe.db.get_single_value("Accounts Settings", "enable_party_matching"):
|
||||||
self.auto_set_party()
|
self.auto_set_party()
|
||||||
|
|
||||||
def before_update_after_submit(self):
|
_saving_flag = False
|
||||||
self.validate_duplicate_references()
|
|
||||||
self.allocate_payment_entries()
|
# nosemgrep: frappe-semgrep-rules.rules.frappe-modifying-but-not-comitting
|
||||||
self.update_allocated_amount()
|
def on_update_after_submit(self):
|
||||||
self.set_status()
|
"Run on save(). Avoid recursion caused by multiple saves"
|
||||||
|
if not self._saving_flag:
|
||||||
|
self._saving_flag = True
|
||||||
|
self.clear_linked_payment_entries()
|
||||||
|
self.update_allocations()
|
||||||
|
self._saving_flag = False
|
||||||
|
|
||||||
def on_cancel(self):
|
def on_cancel(self):
|
||||||
for payment_entry in self.payment_entries:
|
self.clear_linked_payment_entries(for_cancel=True)
|
||||||
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
|
self.set_status(update=True)
|
||||||
|
|
||||||
self.set_status()
|
def update_allocations(self):
|
||||||
|
"The doctype does not allow modifications after submission, so write to the db direct"
|
||||||
|
if self.payment_entries:
|
||||||
|
allocated_amount = sum(p.allocated_amount for p in self.payment_entries)
|
||||||
|
else:
|
||||||
|
allocated_amount = 0.0
|
||||||
|
|
||||||
|
amount = abs(flt(self.withdrawal) - flt(self.deposit))
|
||||||
|
self.db_set("allocated_amount", flt(allocated_amount))
|
||||||
|
self.db_set("unallocated_amount", amount - flt(allocated_amount))
|
||||||
|
self.reload()
|
||||||
|
self.set_status(update=True)
|
||||||
|
|
||||||
def add_payment_entries(self, vouchers):
|
def add_payment_entries(self, vouchers):
|
||||||
"Add the vouchers with zero allocation. Save() will perform the allocations and clearance"
|
"Add the vouchers with zero allocation. Save() will perform the allocations and clearance"
|
||||||
if 0.0 >= self.unallocated_amount:
|
if 0.0 >= self.unallocated_amount:
|
||||||
frappe.throw(_("Bank Transaction {0} is already fully reconciled").format(self.name))
|
frappe.throw(frappe._("Bank Transaction {0} is already fully reconciled").format(self.name))
|
||||||
|
|
||||||
|
added = False
|
||||||
for voucher in vouchers:
|
for voucher in vouchers:
|
||||||
self.append(
|
# Can't add same voucher twice
|
||||||
"payment_entries",
|
found = False
|
||||||
{
|
for pe in self.payment_entries:
|
||||||
|
if (
|
||||||
|
pe.payment_document == voucher["payment_doctype"]
|
||||||
|
and pe.payment_entry == voucher["payment_name"]
|
||||||
|
):
|
||||||
|
found = True
|
||||||
|
|
||||||
|
if not found:
|
||||||
|
pe = {
|
||||||
"payment_document": voucher["payment_doctype"],
|
"payment_document": voucher["payment_doctype"],
|
||||||
"payment_entry": voucher["payment_name"],
|
"payment_entry": voucher["payment_name"],
|
||||||
"allocated_amount": 0.0, # Temporary
|
"allocated_amount": 0.0, # Temporary
|
||||||
},
|
}
|
||||||
)
|
child = self.append("payment_entries", pe)
|
||||||
|
added = True
|
||||||
|
|
||||||
|
# runs on_update_after_submit
|
||||||
|
if added:
|
||||||
|
self.save()
|
||||||
|
|
||||||
def allocate_payment_entries(self):
|
def allocate_payment_entries(self):
|
||||||
"""Refactored from bank reconciliation tool.
|
"""Refactored from bank reconciliation tool.
|
||||||
@@ -147,8 +89,8 @@ class BankTransaction(Document):
|
|||||||
- 0 > a: Error: already over-allocated
|
- 0 > a: Error: already over-allocated
|
||||||
- clear means: set the latest transaction date as clearance date
|
- clear means: set the latest transaction date as clearance date
|
||||||
"""
|
"""
|
||||||
|
gl_bank_account = frappe.db.get_value("Bank Account", self.bank_account, "account")
|
||||||
remaining_amount = self.unallocated_amount
|
remaining_amount = self.unallocated_amount
|
||||||
to_remove = []
|
|
||||||
for payment_entry in self.payment_entries:
|
for payment_entry in self.payment_entries:
|
||||||
if payment_entry.allocated_amount == 0.0:
|
if payment_entry.allocated_amount == 0.0:
|
||||||
unallocated_amount, should_clear, latest_transaction = get_clearance_details(
|
unallocated_amount, should_clear, latest_transaction = get_clearance_details(
|
||||||
@@ -158,39 +100,49 @@ class BankTransaction(Document):
|
|||||||
if 0.0 == unallocated_amount:
|
if 0.0 == unallocated_amount:
|
||||||
if should_clear:
|
if should_clear:
|
||||||
latest_transaction.clear_linked_payment_entry(payment_entry)
|
latest_transaction.clear_linked_payment_entry(payment_entry)
|
||||||
to_remove.append(payment_entry)
|
self.db_delete_payment_entry(payment_entry)
|
||||||
|
|
||||||
elif remaining_amount <= 0.0:
|
elif remaining_amount <= 0.0:
|
||||||
to_remove.append(payment_entry)
|
self.db_delete_payment_entry(payment_entry)
|
||||||
|
|
||||||
elif 0.0 < unallocated_amount <= remaining_amount:
|
elif 0.0 < unallocated_amount and unallocated_amount <= remaining_amount:
|
||||||
payment_entry.allocated_amount = unallocated_amount
|
payment_entry.db_set("allocated_amount", unallocated_amount)
|
||||||
remaining_amount -= unallocated_amount
|
remaining_amount -= unallocated_amount
|
||||||
if should_clear:
|
if should_clear:
|
||||||
latest_transaction.clear_linked_payment_entry(payment_entry)
|
latest_transaction.clear_linked_payment_entry(payment_entry)
|
||||||
|
|
||||||
elif 0.0 < unallocated_amount:
|
elif 0.0 < unallocated_amount and unallocated_amount > remaining_amount:
|
||||||
payment_entry.allocated_amount = remaining_amount
|
payment_entry.db_set("allocated_amount", remaining_amount)
|
||||||
remaining_amount = 0.0
|
remaining_amount = 0.0
|
||||||
|
|
||||||
elif 0.0 > unallocated_amount:
|
elif 0.0 > unallocated_amount:
|
||||||
frappe.throw(_("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
|
self.db_delete_payment_entry(payment_entry)
|
||||||
|
frappe.throw(frappe._("Voucher {0} is over-allocated by {1}").format(unallocated_amount))
|
||||||
|
|
||||||
for payment_entry in to_remove:
|
self.reload()
|
||||||
self.remove(to_remove)
|
|
||||||
|
def db_delete_payment_entry(self, payment_entry):
|
||||||
|
frappe.db.delete("Bank Transaction Payments", {"name": payment_entry.name})
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def remove_payment_entries(self):
|
def remove_payment_entries(self):
|
||||||
for payment_entry in self.payment_entries:
|
for payment_entry in self.payment_entries:
|
||||||
self.remove_payment_entry(payment_entry)
|
self.remove_payment_entry(payment_entry)
|
||||||
|
# runs on_update_after_submit
|
||||||
self.save() # runs before_update_after_submit
|
self.save()
|
||||||
|
|
||||||
def remove_payment_entry(self, payment_entry):
|
def remove_payment_entry(self, payment_entry):
|
||||||
"Clear payment entry and clearance"
|
"Clear payment entry and clearance"
|
||||||
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
|
self.clear_linked_payment_entry(payment_entry, for_cancel=True)
|
||||||
self.remove(payment_entry)
|
self.remove(payment_entry)
|
||||||
|
|
||||||
|
def clear_linked_payment_entries(self, for_cancel=False):
|
||||||
|
if for_cancel:
|
||||||
|
for payment_entry in self.payment_entries:
|
||||||
|
self.clear_linked_payment_entry(payment_entry, for_cancel)
|
||||||
|
else:
|
||||||
|
self.allocate_payment_entries()
|
||||||
|
|
||||||
def clear_linked_payment_entry(self, payment_entry, for_cancel=False):
|
def clear_linked_payment_entry(self, payment_entry, for_cancel=False):
|
||||||
clearance_date = None if for_cancel else self.date
|
clearance_date = None if for_cancel else self.date
|
||||||
set_voucher_clearance(
|
set_voucher_clearance(
|
||||||
@@ -211,10 +163,11 @@ class BankTransaction(Document):
|
|||||||
deposit=self.deposit,
|
deposit=self.deposit,
|
||||||
).match()
|
).match()
|
||||||
|
|
||||||
if not result:
|
if result:
|
||||||
return
|
party_type, party = result
|
||||||
|
frappe.db.set_value(
|
||||||
self.party_type, self.party = result
|
"Bank Transaction", self.name, field={"party_type": party_type, "party": party}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
@@ -246,7 +199,9 @@ def get_clearance_details(transaction, payment_entry):
|
|||||||
if gle["gl_account"] == gl_bank_account:
|
if gle["gl_account"] == gl_bank_account:
|
||||||
if gle["amount"] <= 0.0:
|
if gle["amount"] <= 0.0:
|
||||||
frappe.throw(
|
frappe.throw(
|
||||||
_("Voucher {0} value is broken: {1}").format(payment_entry.payment_entry, gle["amount"])
|
frappe._("Voucher {0} value is broken: {1}").format(
|
||||||
|
payment_entry.payment_entry, gle["amount"]
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
unmatched_gles -= 1
|
unmatched_gles -= 1
|
||||||
@@ -267,7 +222,7 @@ def get_clearance_details(transaction, payment_entry):
|
|||||||
|
|
||||||
def get_related_bank_gl_entries(doctype, docname):
|
def get_related_bank_gl_entries(doctype, docname):
|
||||||
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
|
# nosemgrep: frappe-semgrep-rules.rules.frappe-using-db-sql
|
||||||
return frappe.db.sql(
|
result = frappe.db.sql(
|
||||||
"""
|
"""
|
||||||
SELECT
|
SELECT
|
||||||
ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount,
|
ABS(gle.credit_in_account_currency - gle.debit_in_account_currency) AS amount,
|
||||||
@@ -285,6 +240,7 @@ def get_related_bank_gl_entries(doctype, docname):
|
|||||||
dict(doctype=doctype, docname=docname),
|
dict(doctype=doctype, docname=docname),
|
||||||
as_dict=True,
|
as_dict=True,
|
||||||
)
|
)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def get_total_allocated_amount(doctype, docname):
|
def get_total_allocated_amount(doctype, docname):
|
||||||
@@ -394,25 +350,22 @@ def set_voucher_clearance(doctype, docname, clearance_date, self):
|
|||||||
and len(get_reconciled_bank_transactions(doctype, docname)) < 2
|
and len(get_reconciled_bank_transactions(doctype, docname)) < 2
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
|
|
||||||
if doctype == "Sales Invoice":
|
|
||||||
frappe.db.set_value(
|
|
||||||
"Sales Invoice Payment",
|
|
||||||
dict(parenttype=doctype, parent=docname),
|
|
||||||
"clearance_date",
|
|
||||||
clearance_date,
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
frappe.db.set_value(doctype, docname, "clearance_date", clearance_date)
|
frappe.db.set_value(doctype, docname, "clearance_date", clearance_date)
|
||||||
|
|
||||||
|
elif doctype == "Sales Invoice":
|
||||||
|
frappe.db.set_value(
|
||||||
|
"Sales Invoice Payment",
|
||||||
|
dict(parenttype=doctype, parent=docname),
|
||||||
|
"clearance_date",
|
||||||
|
clearance_date,
|
||||||
|
)
|
||||||
|
|
||||||
elif doctype == "Bank Transaction":
|
elif doctype == "Bank Transaction":
|
||||||
# For when a second bank transaction has fixed another, e.g. refund
|
# For when a second bank transaction has fixed another, e.g. refund
|
||||||
bt = frappe.get_doc(doctype, docname)
|
bt = frappe.get_doc(doctype, docname)
|
||||||
if clearance_date:
|
if clearance_date:
|
||||||
vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}]
|
vouchers = [{"payment_doctype": "Bank Transaction", "payment_name": self.name}]
|
||||||
bt.add_payment_entries(vouchers)
|
bt.add_payment_entries(vouchers)
|
||||||
bt.save()
|
|
||||||
else:
|
else:
|
||||||
for pe in bt.payment_entries:
|
for pe in bt.payment_entries:
|
||||||
if pe.payment_document == self.doctype and pe.payment_entry == self.name:
|
if pe.payment_document == self.doctype and pe.payment_entry == self.name:
|
||||||
@@ -434,21 +387,3 @@ def unclear_reference_payment(doctype, docname, bt_name):
|
|||||||
bt = frappe.get_doc("Bank Transaction", bt_name)
|
bt = frappe.get_doc("Bank Transaction", bt_name)
|
||||||
set_voucher_clearance(doctype, docname, None, bt)
|
set_voucher_clearance(doctype, docname, None, bt)
|
||||||
return docname
|
return docname
|
||||||
|
|
||||||
|
|
||||||
def remove_from_bank_transaction(doctype, docname):
|
|
||||||
"""Remove a (cancelled) voucher from all Bank Transactions."""
|
|
||||||
for bt_name in get_reconciled_bank_transactions(doctype, docname):
|
|
||||||
bt = frappe.get_doc("Bank Transaction", bt_name)
|
|
||||||
if bt.docstatus == DocStatus.cancelled():
|
|
||||||
continue
|
|
||||||
|
|
||||||
modified = False
|
|
||||||
|
|
||||||
for pe in bt.payment_entries:
|
|
||||||
if pe.payment_document == doctype and pe.payment_entry == docname:
|
|
||||||
bt.remove(pe)
|
|
||||||
modified = True
|
|
||||||
|
|
||||||
if modified:
|
|
||||||
bt.save()
|
|
||||||
|
|||||||
@@ -2,10 +2,10 @@
|
|||||||
# See license.txt
|
# See license.txt
|
||||||
|
|
||||||
import json
|
import json
|
||||||
|
import unittest
|
||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import utils
|
from frappe import utils
|
||||||
from frappe.model.docstatus import DocStatus
|
|
||||||
from frappe.tests.utils import FrappeTestCase
|
from frappe.tests.utils import FrappeTestCase
|
||||||
|
|
||||||
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
|
||||||
@@ -32,16 +32,8 @@ class TestBankTransaction(FrappeTestCase):
|
|||||||
frappe.db.delete(dt)
|
frappe.db.delete(dt)
|
||||||
clear_loan_transactions()
|
clear_loan_transactions()
|
||||||
make_pos_profile()
|
make_pos_profile()
|
||||||
|
add_transactions()
|
||||||
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
|
add_vouchers()
|
||||||
uniq_identifier = frappe.generate_hash(length=10)
|
|
||||||
gl_account = create_gl_account("_Test Bank " + uniq_identifier)
|
|
||||||
bank_account = create_bank_account(
|
|
||||||
gl_account=gl_account, bank_account_name="Checking Account " + uniq_identifier
|
|
||||||
)
|
|
||||||
|
|
||||||
add_transactions(bank_account=bank_account)
|
|
||||||
add_vouchers(gl_account=gl_account)
|
|
||||||
|
|
||||||
# This test checks if ERPNext is able to provide a linked payment for a bank transaction based on the amount of the bank transaction.
|
# 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):
|
def test_linked_payments(self):
|
||||||
@@ -89,29 +81,6 @@ class TestBankTransaction(FrappeTestCase):
|
|||||||
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
|
clearance_date = frappe.db.get_value("Payment Entry", payment.name, "clearance_date")
|
||||||
self.assertFalse(clearance_date)
|
self.assertFalse(clearance_date)
|
||||||
|
|
||||||
def test_cancel_voucher(self):
|
|
||||||
bank_transaction = frappe.get_doc(
|
|
||||||
"Bank Transaction",
|
|
||||||
dict(description="1512567 BG/000003025 OPSKATTUZWXXX AT776000000098709849 Herr G"),
|
|
||||||
)
|
|
||||||
payment = frappe.get_doc("Payment Entry", dict(party="Mr G", paid_amount=1700))
|
|
||||||
vouchers = json.dumps(
|
|
||||||
[
|
|
||||||
{
|
|
||||||
"payment_doctype": "Payment Entry",
|
|
||||||
"payment_name": payment.name,
|
|
||||||
"amount": bank_transaction.unallocated_amount,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
)
|
|
||||||
reconcile_vouchers(bank_transaction.name, vouchers)
|
|
||||||
payment.reload()
|
|
||||||
payment.cancel()
|
|
||||||
bank_transaction.reload()
|
|
||||||
self.assertEqual(bank_transaction.docstatus, DocStatus.submitted())
|
|
||||||
self.assertEqual(bank_transaction.unallocated_amount, 1700)
|
|
||||||
self.assertEqual(bank_transaction.payment_entries, [])
|
|
||||||
|
|
||||||
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
|
# Check if ERPNext can correctly filter a linked payments based on the debit/credit amount
|
||||||
def test_debit_credit_output(self):
|
def test_debit_credit_output(self):
|
||||||
bank_transaction = frappe.get_doc(
|
bank_transaction = frappe.get_doc(
|
||||||
@@ -227,9 +196,7 @@ def clear_loan_transactions():
|
|||||||
frappe.db.delete("Loan Repayment")
|
frappe.db.delete("Loan Repayment")
|
||||||
|
|
||||||
|
|
||||||
def create_bank_account(
|
def create_bank_account(bank_name="Citi Bank", account_name="_Test Bank - _TC"):
|
||||||
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
@@ -241,35 +208,21 @@ def create_bank_account(
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
bank_account = frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Bank Account",
|
"doctype": "Bank Account",
|
||||||
"account_name": bank_account_name,
|
"account_name": "Checking Account",
|
||||||
"bank": bank_name,
|
"bank": bank_name,
|
||||||
"account": gl_account,
|
"account": account_name,
|
||||||
}
|
}
|
||||||
).insert(ignore_if_duplicate=True)
|
).insert(ignore_if_duplicate=True)
|
||||||
except frappe.DuplicateEntryError:
|
except frappe.DuplicateEntryError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return bank_account.name
|
|
||||||
|
|
||||||
|
def add_transactions():
|
||||||
|
create_bank_account()
|
||||||
|
|
||||||
def create_gl_account(gl_account_name="_Test Bank - _TC"):
|
|
||||||
gl_account = frappe.get_doc(
|
|
||||||
{
|
|
||||||
"doctype": "Account",
|
|
||||||
"company": "_Test Company",
|
|
||||||
"parent_account": "Current Assets - _TC",
|
|
||||||
"account_type": "Bank",
|
|
||||||
"is_group": 0,
|
|
||||||
"account_name": gl_account_name,
|
|
||||||
}
|
|
||||||
).insert()
|
|
||||||
return gl_account.name
|
|
||||||
|
|
||||||
|
|
||||||
def add_transactions(bank_account="_Test Bank - _TC"):
|
|
||||||
doc = frappe.get_doc(
|
doc = frappe.get_doc(
|
||||||
{
|
{
|
||||||
"doctype": "Bank Transaction",
|
"doctype": "Bank Transaction",
|
||||||
@@ -277,7 +230,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
|
|||||||
"date": "2018-10-23",
|
"date": "2018-10-23",
|
||||||
"deposit": 1200,
|
"deposit": 1200,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": bank_account,
|
"bank_account": "Checking Account - Citi Bank",
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -289,7 +242,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
|
|||||||
"date": "2018-10-23",
|
"date": "2018-10-23",
|
||||||
"deposit": 1700,
|
"deposit": 1700,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": bank_account,
|
"bank_account": "Checking Account - Citi Bank",
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -301,7 +254,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
|
|||||||
"date": "2018-10-26",
|
"date": "2018-10-26",
|
||||||
"withdrawal": 690,
|
"withdrawal": 690,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": bank_account,
|
"bank_account": "Checking Account - Citi Bank",
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -313,7 +266,7 @@ def add_transactions(bank_account="_Test Bank - _TC"):
|
|||||||
"date": "2018-10-27",
|
"date": "2018-10-27",
|
||||||
"deposit": 3900,
|
"deposit": 3900,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": bank_account,
|
"bank_account": "Checking Account - Citi Bank",
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
@@ -325,13 +278,13 @@ def add_transactions(bank_account="_Test Bank - _TC"):
|
|||||||
"date": "2018-10-27",
|
"date": "2018-10-27",
|
||||||
"withdrawal": 109080,
|
"withdrawal": 109080,
|
||||||
"currency": "INR",
|
"currency": "INR",
|
||||||
"bank_account": bank_account,
|
"bank_account": "Checking Account - Citi Bank",
|
||||||
}
|
}
|
||||||
).insert()
|
).insert()
|
||||||
doc.submit()
|
doc.submit()
|
||||||
|
|
||||||
|
|
||||||
def add_vouchers(gl_account="_Test Bank - _TC"):
|
def add_vouchers():
|
||||||
try:
|
try:
|
||||||
frappe.get_doc(
|
frappe.get_doc(
|
||||||
{
|
{
|
||||||
@@ -347,7 +300,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
|
|||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
pi = make_purchase_invoice(supplier="Conrad Electronic", qty=1, rate=690)
|
||||||
|
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||||
pe.reference_no = "Conrad Oct 18"
|
pe.reference_no = "Conrad Oct 18"
|
||||||
pe.reference_date = "2018-10-24"
|
pe.reference_date = "2018-10-24"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -366,14 +319,14 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
|
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1200)
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||||
pe.reference_no = "Herr G Oct 18"
|
pe.reference_no = "Herr G Oct 18"
|
||||||
pe.reference_date = "2018-10-24"
|
pe.reference_date = "2018-10-24"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
|
pi = make_purchase_invoice(supplier="Mr G", qty=1, rate=1700)
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||||
pe.reference_no = "Herr G Nov 18"
|
pe.reference_no = "Herr G Nov 18"
|
||||||
pe.reference_date = "2018-11-01"
|
pe.reference_date = "2018-11-01"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -404,10 +357,10 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
|
pi = make_purchase_invoice(supplier="Poore Simon's", qty=1, rate=3900, is_paid=1, do_not_save=1)
|
||||||
pi.cash_bank_account = gl_account
|
pi.cash_bank_account = "_Test Bank - _TC"
|
||||||
pi.insert()
|
pi.insert()
|
||||||
pi.submit()
|
pi.submit()
|
||||||
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account=gl_account)
|
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank - _TC")
|
||||||
pe.reference_no = "Poore Simon's Oct 18"
|
pe.reference_no = "Poore Simon's Oct 18"
|
||||||
pe.reference_date = "2018-10-28"
|
pe.reference_date = "2018-10-28"
|
||||||
pe.paid_amount = 690
|
pe.paid_amount = 690
|
||||||
@@ -416,7 +369,7 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
|
|||||||
pe.submit()
|
pe.submit()
|
||||||
|
|
||||||
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
|
si = create_sales_invoice(customer="Poore Simon's", qty=1, rate=3900)
|
||||||
pe = get_payment_entry("Sales Invoice", si.name, bank_account=gl_account)
|
pe = get_payment_entry("Sales Invoice", si.name, bank_account="_Test Bank - _TC")
|
||||||
pe.reference_no = "Poore Simon's Oct 18"
|
pe.reference_no = "Poore Simon's Oct 18"
|
||||||
pe.reference_date = "2018-10-28"
|
pe.reference_date = "2018-10-28"
|
||||||
pe.insert()
|
pe.insert()
|
||||||
@@ -439,12 +392,16 @@ def add_vouchers(gl_account="_Test Bank - _TC"):
|
|||||||
if not frappe.db.get_value(
|
if not frappe.db.get_value(
|
||||||
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
|
"Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}
|
||||||
):
|
):
|
||||||
mode_of_payment.append("accounts", {"company": "_Test Company", "default_account": gl_account})
|
mode_of_payment.append(
|
||||||
|
"accounts", {"company": "_Test Company", "default_account": "_Test Bank - _TC"}
|
||||||
|
)
|
||||||
mode_of_payment.save()
|
mode_of_payment.save()
|
||||||
|
|
||||||
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
si = create_sales_invoice(customer="Fayva", qty=1, rate=109080, do_not_save=1)
|
||||||
si.is_pos = 1
|
si.is_pos = 1
|
||||||
si.append("payments", {"mode_of_payment": "Cash", "account": gl_account, "amount": 109080})
|
si.append(
|
||||||
|
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank - _TC", "amount": 109080}
|
||||||
|
)
|
||||||
si.insert()
|
si.insert()
|
||||||
si.submit()
|
si.submit()
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankTransactionMapping(Document):
|
class BankTransactionMapping(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
bank_transaction_field: DF.Literal
|
|
||||||
file_field: DF.Data
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,21 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BankTransactionPayments(Document):
|
class BankTransactionPayments(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
allocated_amount: DF.Currency
|
|
||||||
clearance_date: DF.Date | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
payment_document: DF.Link
|
|
||||||
payment_entry: DF.DynamicLink
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
frappe.ui.form.on("Bisect Accounting Statements", {
|
|
||||||
onload(frm) {
|
|
||||||
frm.trigger("render_heatmap");
|
|
||||||
},
|
|
||||||
refresh(frm) {
|
|
||||||
frm.add_custom_button(__('Bisect Left'), () => {
|
|
||||||
frm.trigger("bisect_left");
|
|
||||||
});
|
|
||||||
|
|
||||||
frm.add_custom_button(__('Bisect Right'), () => {
|
|
||||||
frm.trigger("bisect_right");
|
|
||||||
});
|
|
||||||
|
|
||||||
frm.add_custom_button(__('Up'), () => {
|
|
||||||
frm.trigger("move_up");
|
|
||||||
});
|
|
||||||
frm.add_custom_button(__('Build Tree'), () => {
|
|
||||||
frm.trigger("build_tree");
|
|
||||||
});
|
|
||||||
},
|
|
||||||
render_heatmap(frm) {
|
|
||||||
let bisect_heatmap = frm.get_field("bisect_heatmap").$wrapper;
|
|
||||||
bisect_heatmap.addClass("bisect_heatmap_location");
|
|
||||||
|
|
||||||
// milliseconds in a day
|
|
||||||
let msiad=24*60*60*1000;
|
|
||||||
let datapoints = {};
|
|
||||||
let fr_dt = new Date(frm.doc.from_date).getTime();
|
|
||||||
let to_dt = new Date(frm.doc.to_date).getTime();
|
|
||||||
let bisect_start = new Date(frm.doc.current_from_date).getTime();
|
|
||||||
let bisect_end = new Date(frm.doc.current_to_date).getTime();
|
|
||||||
|
|
||||||
for(let x=fr_dt; x <= to_dt; x+=msiad){
|
|
||||||
let epoch_in_seconds = x/1000;
|
|
||||||
if ((bisect_start <= x) && (x <= bisect_end )) {
|
|
||||||
datapoints[epoch_in_seconds] = 1.0;
|
|
||||||
} else {
|
|
||||||
datapoints[epoch_in_seconds] = 0.0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
new frappe.Chart(".bisect_heatmap_location", {
|
|
||||||
type: "heatmap",
|
|
||||||
data: {
|
|
||||||
dataPoints: datapoints,
|
|
||||||
start: new Date(frm.doc.from_date),
|
|
||||||
end: new Date(frm.doc.to_date),
|
|
||||||
},
|
|
||||||
countLabel: 'Bisecting',
|
|
||||||
discreteDomains: 1,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
bisect_left(frm) {
|
|
||||||
frm.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
method: 'bisect_left',
|
|
||||||
freeze: true,
|
|
||||||
freeze_message: __("Bisecting Left ..."),
|
|
||||||
callback: (r) => {
|
|
||||||
frm.trigger("render_heatmap");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
bisect_right(frm) {
|
|
||||||
frm.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
freeze: true,
|
|
||||||
freeze_message: __("Bisecting Right ..."),
|
|
||||||
method: 'bisect_right',
|
|
||||||
callback: (r) => {
|
|
||||||
frm.trigger("render_heatmap");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
move_up(frm) {
|
|
||||||
frm.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
freeze: true,
|
|
||||||
freeze_message: __("Moving up in tree ..."),
|
|
||||||
method: 'move_up',
|
|
||||||
callback: (r) => {
|
|
||||||
frm.trigger("render_heatmap");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
build_tree(frm) {
|
|
||||||
frm.call({
|
|
||||||
doc: frm.doc,
|
|
||||||
freeze: true,
|
|
||||||
freeze_message: __("Rebuilding BTree for period ..."),
|
|
||||||
method: 'build_tree',
|
|
||||||
callback: (r) => {
|
|
||||||
frm.trigger("render_heatmap");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@@ -1,194 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"allow_rename": 1,
|
|
||||||
"creation": "2023-09-15 21:28:28.054773",
|
|
||||||
"default_view": "List",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"section_break_cvfg",
|
|
||||||
"company",
|
|
||||||
"column_break_hcam",
|
|
||||||
"from_date",
|
|
||||||
"column_break_qxbi",
|
|
||||||
"to_date",
|
|
||||||
"column_break_iwny",
|
|
||||||
"algorithm",
|
|
||||||
"section_break_8ph9",
|
|
||||||
"current_node",
|
|
||||||
"section_break_ngid",
|
|
||||||
"bisect_heatmap",
|
|
||||||
"section_break_hmsy",
|
|
||||||
"bisecting_from",
|
|
||||||
"current_from_date",
|
|
||||||
"column_break_uqyd",
|
|
||||||
"bisecting_to",
|
|
||||||
"current_to_date",
|
|
||||||
"section_break_hbyo",
|
|
||||||
"heading_cppb",
|
|
||||||
"p_l_summary",
|
|
||||||
"column_break_aivo",
|
|
||||||
"balance_sheet_summary",
|
|
||||||
"b_s_summary",
|
|
||||||
"column_break_gvwx",
|
|
||||||
"difference_heading",
|
|
||||||
"difference"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_qxbi",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "from_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"label": "From Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "to_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"label": "To Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "BFS",
|
|
||||||
"fieldname": "algorithm",
|
|
||||||
"fieldtype": "Select",
|
|
||||||
"label": "Algorithm",
|
|
||||||
"options": "BFS\nDFS"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_iwny",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "current_node",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Current Node",
|
|
||||||
"options": "Bisect Nodes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_hmsy",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "current_from_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "current_to_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_uqyd",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_hbyo",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "p_l_summary",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "b_s_summary",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "difference",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"read_only": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_aivo",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_gvwx",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "company",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Company",
|
|
||||||
"options": "Company"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "column_break_hcam",
|
|
||||||
"fieldtype": "Column Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_ngid",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_8ph9",
|
|
||||||
"fieldtype": "Section Break",
|
|
||||||
"hidden": 1
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "bisect_heatmap",
|
|
||||||
"fieldtype": "HTML",
|
|
||||||
"label": "Heatmap"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "heading_cppb",
|
|
||||||
"fieldtype": "Heading",
|
|
||||||
"label": "Profit and Loss Summary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "balance_sheet_summary",
|
|
||||||
"fieldtype": "Heading",
|
|
||||||
"label": "Balance Sheet Summary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "difference_heading",
|
|
||||||
"fieldtype": "Heading",
|
|
||||||
"label": "Difference"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "bisecting_from",
|
|
||||||
"fieldtype": "Heading",
|
|
||||||
"label": "Bisecting From"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "bisecting_to",
|
|
||||||
"fieldtype": "Heading",
|
|
||||||
"label": "Bisecting To"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "section_break_cvfg",
|
|
||||||
"fieldtype": "Section Break"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"hide_toolbar": 1,
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"issingle": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2023-12-01 16:49:54.073890",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Accounts",
|
|
||||||
"name": "Bisect Accounting Statements",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"role": "Administrator",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"read_only": 1,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"states": []
|
|
||||||
}
|
|
||||||
@@ -1,226 +0,0 @@
|
|||||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
import datetime
|
|
||||||
from collections import deque
|
|
||||||
from math import floor
|
|
||||||
|
|
||||||
import frappe
|
|
||||||
from dateutil.relativedelta import relativedelta
|
|
||||||
from frappe import _
|
|
||||||
from frappe.model.document import Document
|
|
||||||
from frappe.utils import getdate
|
|
||||||
from frappe.utils.data import guess_date_format
|
|
||||||
|
|
||||||
|
|
||||||
class BisectAccountingStatements(Document):
|
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
algorithm: DF.Literal["BFS", "DFS"]
|
|
||||||
b_s_summary: DF.Float
|
|
||||||
company: DF.Link | None
|
|
||||||
current_from_date: DF.Datetime | None
|
|
||||||
current_node: DF.Link | None
|
|
||||||
current_to_date: DF.Datetime | None
|
|
||||||
difference: DF.Float
|
|
||||||
from_date: DF.Datetime | None
|
|
||||||
p_l_summary: DF.Float
|
|
||||||
to_date: DF.Datetime | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
|
||||||
self.validate_dates()
|
|
||||||
|
|
||||||
def validate_dates(self):
|
|
||||||
if getdate(self.from_date) > getdate(self.to_date):
|
|
||||||
frappe.throw(
|
|
||||||
_("From Date: {0} cannot be greater than To date: {1}").format(
|
|
||||||
frappe.bold(self.from_date), frappe.bold(self.to_date)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
def bfs(self, from_date: datetime, to_date: datetime):
|
|
||||||
# Make Root node
|
|
||||||
node = frappe.new_doc("Bisect Nodes")
|
|
||||||
node.root = None
|
|
||||||
node.period_from_date = from_date
|
|
||||||
node.period_to_date = to_date
|
|
||||||
node.insert()
|
|
||||||
|
|
||||||
period_queue = deque([node])
|
|
||||||
while period_queue:
|
|
||||||
cur_node = period_queue.popleft()
|
|
||||||
delta = cur_node.period_to_date - cur_node.period_from_date
|
|
||||||
if delta.days == 0:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
cur_floor = floor(delta.days / 2)
|
|
||||||
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
|
|
||||||
left_node = frappe.new_doc("Bisect Nodes")
|
|
||||||
left_node.period_from_date = cur_node.period_from_date
|
|
||||||
left_node.period_to_date = next_to_date
|
|
||||||
left_node.root = cur_node.name
|
|
||||||
left_node.generated = False
|
|
||||||
left_node.insert()
|
|
||||||
cur_node.left_child = left_node.name
|
|
||||||
period_queue.append(left_node)
|
|
||||||
|
|
||||||
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
|
|
||||||
right_node = frappe.new_doc("Bisect Nodes")
|
|
||||||
right_node.period_from_date = next_from_date
|
|
||||||
right_node.period_to_date = cur_node.period_to_date
|
|
||||||
right_node.root = cur_node.name
|
|
||||||
right_node.generated = False
|
|
||||||
right_node.insert()
|
|
||||||
cur_node.right_child = right_node.name
|
|
||||||
period_queue.append(right_node)
|
|
||||||
|
|
||||||
cur_node.save()
|
|
||||||
|
|
||||||
def dfs(self, from_date: datetime, to_date: datetime):
|
|
||||||
# Make Root node
|
|
||||||
node = frappe.new_doc("Bisect Nodes")
|
|
||||||
node.root = None
|
|
||||||
node.period_from_date = from_date
|
|
||||||
node.period_to_date = to_date
|
|
||||||
node.insert()
|
|
||||||
|
|
||||||
period_stack = [node]
|
|
||||||
while period_stack:
|
|
||||||
cur_node = period_stack.pop()
|
|
||||||
delta = cur_node.period_to_date - cur_node.period_from_date
|
|
||||||
if delta.days == 0:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
cur_floor = floor(delta.days / 2)
|
|
||||||
next_to_date = cur_node.period_from_date + relativedelta(days=+cur_floor)
|
|
||||||
left_node = frappe.new_doc("Bisect Nodes")
|
|
||||||
left_node.period_from_date = cur_node.period_from_date
|
|
||||||
left_node.period_to_date = next_to_date
|
|
||||||
left_node.root = cur_node.name
|
|
||||||
left_node.generated = False
|
|
||||||
left_node.insert()
|
|
||||||
cur_node.left_child = left_node.name
|
|
||||||
period_stack.append(left_node)
|
|
||||||
|
|
||||||
next_from_date = cur_node.period_from_date + relativedelta(days=+(cur_floor + 1))
|
|
||||||
right_node = frappe.new_doc("Bisect Nodes")
|
|
||||||
right_node.period_from_date = next_from_date
|
|
||||||
right_node.period_to_date = cur_node.period_to_date
|
|
||||||
right_node.root = cur_node.name
|
|
||||||
right_node.generated = False
|
|
||||||
right_node.insert()
|
|
||||||
cur_node.right_child = right_node.name
|
|
||||||
period_stack.append(right_node)
|
|
||||||
|
|
||||||
cur_node.save()
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def build_tree(self):
|
|
||||||
frappe.db.delete("Bisect Nodes")
|
|
||||||
|
|
||||||
# Convert str to datetime format
|
|
||||||
dt_format = guess_date_format(self.from_date)
|
|
||||||
from_date = datetime.datetime.strptime(self.from_date, dt_format)
|
|
||||||
to_date = datetime.datetime.strptime(self.to_date, dt_format)
|
|
||||||
|
|
||||||
if self.algorithm == "BFS":
|
|
||||||
self.bfs(from_date, to_date)
|
|
||||||
|
|
||||||
if self.algorithm == "DFS":
|
|
||||||
self.dfs(from_date, to_date)
|
|
||||||
|
|
||||||
# set root as current node
|
|
||||||
root = frappe.db.get_all("Bisect Nodes", filters={"root": ["is", "not set"]})[0]
|
|
||||||
self.get_report_summary()
|
|
||||||
self.current_node = root.name
|
|
||||||
self.current_from_date = self.from_date
|
|
||||||
self.current_to_date = self.to_date
|
|
||||||
self.save()
|
|
||||||
|
|
||||||
def get_report_summary(self):
|
|
||||||
filters = {
|
|
||||||
"company": self.company,
|
|
||||||
"filter_based_on": "Date Range",
|
|
||||||
"period_start_date": self.current_from_date,
|
|
||||||
"period_end_date": self.current_to_date,
|
|
||||||
"periodicity": "Yearly",
|
|
||||||
}
|
|
||||||
pl_summary = frappe.get_doc("Report", "Profit and Loss Statement")
|
|
||||||
self.p_l_summary = pl_summary.execute_script_report(filters=filters)[5]
|
|
||||||
bs_summary = frappe.get_doc("Report", "Balance Sheet")
|
|
||||||
self.b_s_summary = bs_summary.execute_script_report(filters=filters)[5]
|
|
||||||
self.difference = abs(self.p_l_summary - self.b_s_summary)
|
|
||||||
|
|
||||||
def update_node(self):
|
|
||||||
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
|
|
||||||
current_node.balance_sheet_summary = self.b_s_summary
|
|
||||||
current_node.profit_loss_summary = self.p_l_summary
|
|
||||||
current_node.difference = self.difference
|
|
||||||
current_node.generated = True
|
|
||||||
current_node.save()
|
|
||||||
|
|
||||||
def current_node_has_summary_info(self):
|
|
||||||
"Assertion method"
|
|
||||||
return frappe.db.get_value("Bisect Nodes", self.current_node, "generated")
|
|
||||||
|
|
||||||
def fetch_summary_info_from_current_node(self):
|
|
||||||
current_node = frappe.get_doc("Bisect Nodes", self.current_node)
|
|
||||||
self.p_l_summary = current_node.balance_sheet_summary
|
|
||||||
self.b_s_summary = current_node.profit_loss_summary
|
|
||||||
self.difference = abs(self.p_l_summary - self.b_s_summary)
|
|
||||||
|
|
||||||
def fetch_or_calculate(self):
|
|
||||||
if self.current_node_has_summary_info():
|
|
||||||
self.fetch_summary_info_from_current_node()
|
|
||||||
else:
|
|
||||||
self.get_report_summary()
|
|
||||||
self.update_node()
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def bisect_left(self):
|
|
||||||
if self.current_node is not None:
|
|
||||||
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
|
|
||||||
if cur_node.left_child is not None:
|
|
||||||
lft_node = frappe.get_doc("Bisect Nodes", cur_node.left_child)
|
|
||||||
self.current_node = cur_node.left_child
|
|
||||||
self.current_from_date = lft_node.period_from_date
|
|
||||||
self.current_to_date = lft_node.period_to_date
|
|
||||||
self.fetch_or_calculate()
|
|
||||||
self.save()
|
|
||||||
else:
|
|
||||||
frappe.msgprint(_("No more children on Left"))
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def bisect_right(self):
|
|
||||||
if self.current_node is not None:
|
|
||||||
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
|
|
||||||
if cur_node.right_child is not None:
|
|
||||||
rgt_node = frappe.get_doc("Bisect Nodes", cur_node.right_child)
|
|
||||||
self.current_node = cur_node.right_child
|
|
||||||
self.current_from_date = rgt_node.period_from_date
|
|
||||||
self.current_to_date = rgt_node.period_to_date
|
|
||||||
self.fetch_or_calculate()
|
|
||||||
self.save()
|
|
||||||
else:
|
|
||||||
frappe.msgprint(_("No more children on Right"))
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
|
||||||
def move_up(self):
|
|
||||||
if self.current_node is not None:
|
|
||||||
cur_node = frappe.get_doc("Bisect Nodes", self.current_node)
|
|
||||||
if cur_node.root is not None:
|
|
||||||
root = frappe.get_doc("Bisect Nodes", cur_node.root)
|
|
||||||
self.current_node = cur_node.root
|
|
||||||
self.current_from_date = root.period_from_date
|
|
||||||
self.current_to_date = root.period_to_date
|
|
||||||
self.fetch_or_calculate()
|
|
||||||
self.save()
|
|
||||||
else:
|
|
||||||
frappe.msgprint(_("Reached Root"))
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.tests.utils import FrappeTestCase
|
|
||||||
|
|
||||||
|
|
||||||
class TestBisectAccountingStatements(FrappeTestCase):
|
|
||||||
pass
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
// For license information, please see license.txt
|
|
||||||
|
|
||||||
// frappe.ui.form.on("Bisect Nodes", {
|
|
||||||
// refresh(frm) {
|
|
||||||
|
|
||||||
// },
|
|
||||||
// });
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
{
|
|
||||||
"actions": [],
|
|
||||||
"autoname": "autoincrement",
|
|
||||||
"creation": "2023-09-27 14:56:38.112462",
|
|
||||||
"default_view": "List",
|
|
||||||
"doctype": "DocType",
|
|
||||||
"editable_grid": 1,
|
|
||||||
"engine": "InnoDB",
|
|
||||||
"field_order": [
|
|
||||||
"root",
|
|
||||||
"left_child",
|
|
||||||
"right_child",
|
|
||||||
"period_from_date",
|
|
||||||
"period_to_date",
|
|
||||||
"difference",
|
|
||||||
"balance_sheet_summary",
|
|
||||||
"profit_loss_summary",
|
|
||||||
"generated"
|
|
||||||
],
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldname": "root",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Root",
|
|
||||||
"options": "Bisect Nodes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "left_child",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Left Child",
|
|
||||||
"options": "Bisect Nodes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "right_child",
|
|
||||||
"fieldtype": "Link",
|
|
||||||
"label": "Right Child",
|
|
||||||
"options": "Bisect Nodes"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "period_from_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"label": "Period_from_date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "period_to_date",
|
|
||||||
"fieldtype": "Datetime",
|
|
||||||
"label": "Period To Date"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "difference",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Difference"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "balance_sheet_summary",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Balance Sheet Summary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "profit_loss_summary",
|
|
||||||
"fieldtype": "Float",
|
|
||||||
"label": "Profit and Loss Summary"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"default": "0",
|
|
||||||
"fieldname": "generated",
|
|
||||||
"fieldtype": "Check",
|
|
||||||
"label": "Generated"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"index_web_pages_for_search": 1,
|
|
||||||
"links": [],
|
|
||||||
"modified": "2023-12-01 17:46:12.437996",
|
|
||||||
"modified_by": "Administrator",
|
|
||||||
"module": "Accounts",
|
|
||||||
"name": "Bisect Nodes",
|
|
||||||
"naming_rule": "Autoincrement",
|
|
||||||
"owner": "Administrator",
|
|
||||||
"permissions": [
|
|
||||||
{
|
|
||||||
"create": 1,
|
|
||||||
"delete": 1,
|
|
||||||
"email": 1,
|
|
||||||
"export": 1,
|
|
||||||
"print": 1,
|
|
||||||
"read": 1,
|
|
||||||
"report": 1,
|
|
||||||
"role": "Administrator",
|
|
||||||
"share": 1,
|
|
||||||
"write": 1
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"read_only": 1,
|
|
||||||
"sort_field": "modified",
|
|
||||||
"sort_order": "DESC",
|
|
||||||
"states": []
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
|
||||||
# For license information, please see license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.model.document import Document
|
|
||||||
|
|
||||||
|
|
||||||
class BisectNodes(Document):
|
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
balance_sheet_summary: DF.Float
|
|
||||||
difference: DF.Float
|
|
||||||
generated: DF.Check
|
|
||||||
left_child: DF.Link | None
|
|
||||||
name: DF.Int | None
|
|
||||||
period_from_date: DF.Datetime | None
|
|
||||||
period_to_date: DF.Datetime | None
|
|
||||||
profit_loss_summary: DF.Float
|
|
||||||
right_child: DF.Link | None
|
|
||||||
root: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
|
|
||||||
# See license.txt
|
|
||||||
|
|
||||||
# import frappe
|
|
||||||
from frappe.tests.utils import FrappeTestCase
|
|
||||||
|
|
||||||
|
|
||||||
class TestBisectNodes(FrappeTestCase):
|
|
||||||
pass
|
|
||||||
@@ -22,36 +22,6 @@ class DuplicateBudgetError(frappe.ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class Budget(Document):
|
class Budget(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.budget_account.budget_account import BudgetAccount
|
|
||||||
|
|
||||||
accounts: DF.Table[BudgetAccount]
|
|
||||||
action_if_accumulated_monthly_budget_exceeded: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
action_if_accumulated_monthly_budget_exceeded_on_mr: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
action_if_accumulated_monthly_budget_exceeded_on_po: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
action_if_annual_budget_exceeded: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
action_if_annual_budget_exceeded_on_mr: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
action_if_annual_budget_exceeded_on_po: DF.Literal["", "Stop", "Warn", "Ignore"]
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
applicable_on_booking_actual_expenses: DF.Check
|
|
||||||
applicable_on_material_request: DF.Check
|
|
||||||
applicable_on_purchase_order: DF.Check
|
|
||||||
budget_against: DF.Literal["", "Cost Center", "Project"]
|
|
||||||
company: DF.Link
|
|
||||||
cost_center: DF.Link | None
|
|
||||||
fiscal_year: DF.Link
|
|
||||||
monthly_distribution: DF.Link | None
|
|
||||||
naming_series: DF.Data | None
|
|
||||||
project: DF.Link | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if not self.get(frappe.scrub(self.budget_against)):
|
if not self.get(frappe.scrub(self.budget_against)):
|
||||||
frappe.throw(_("{0} is mandatory").format(self.budget_against))
|
frappe.throw(_("{0} is mandatory").format(self.budget_against))
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class BudgetAccount(Document):
|
class BudgetAccount(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account: DF.Link
|
|
||||||
budget_amount: DF.Currency
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CampaignItem(Document):
|
class CampaignItem(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
campaign: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -1,152 +1,457 @@
|
|||||||
{
|
{
|
||||||
"actions": [],
|
"allow_copy": 0,
|
||||||
|
"allow_events_in_timeline": 0,
|
||||||
|
"allow_guest_to_view": 0,
|
||||||
|
"allow_import": 0,
|
||||||
|
"allow_rename": 0,
|
||||||
"autoname": "naming_series:",
|
"autoname": "naming_series:",
|
||||||
|
"beta": 0,
|
||||||
"creation": "2018-06-18 16:51:49.994750",
|
"creation": "2018-06-18 16:51:49.994750",
|
||||||
|
"custom": 0,
|
||||||
|
"docstatus": 0,
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
|
"document_type": "",
|
||||||
"editable_grid": 1,
|
"editable_grid": 1,
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
"field_order": [
|
|
||||||
"naming_series",
|
|
||||||
"user",
|
|
||||||
"date",
|
|
||||||
"from_time",
|
|
||||||
"time",
|
|
||||||
"expense",
|
|
||||||
"custody",
|
|
||||||
"returns",
|
|
||||||
"outstanding_amount",
|
|
||||||
"payments",
|
|
||||||
"net_amount",
|
|
||||||
"amended_from"
|
|
||||||
],
|
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"default": "POS-CLO-",
|
"default": "POS-CLO-",
|
||||||
"fieldname": "naming_series",
|
"fieldname": "naming_series",
|
||||||
"fieldtype": "Select",
|
"fieldtype": "Select",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"in_global_search": 1,
|
"in_global_search": 1,
|
||||||
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Series",
|
"label": "Series",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
"options": "POS-CLO-",
|
"options": "POS-CLO-",
|
||||||
"read_only": 1
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "user",
|
"fieldname": "user",
|
||||||
"fieldtype": "Link",
|
"fieldtype": "Link",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "User",
|
"label": "User",
|
||||||
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
"options": "User",
|
"options": "User",
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
"read_only": 1,
|
"read_only": 1,
|
||||||
"reqd": 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,
|
||||||
"default": "Today",
|
"default": "Today",
|
||||||
"fieldname": "date",
|
"fieldname": "date",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Date",
|
"label": "Date",
|
||||||
"read_only": 1
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "from_time",
|
"fieldname": "from_time",
|
||||||
"fieldtype": "Time",
|
"fieldtype": "Time",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "From Time",
|
"label": "From Time",
|
||||||
"reqd": 1
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "",
|
||||||
"fieldname": "time",
|
"fieldname": "time",
|
||||||
"fieldtype": "Time",
|
"fieldtype": "Time",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "To Time",
|
"label": "To Time",
|
||||||
"reqd": 1
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 1,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"default": "0.00",
|
"default": "0.00",
|
||||||
"fieldname": "expense",
|
"fieldname": "expense",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Expense"
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Expense",
|
||||||
|
"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,
|
||||||
"default": "0.00",
|
"default": "0.00",
|
||||||
"fieldname": "custody",
|
"fieldname": "custody",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
"label": "Custody"
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
|
"label": "Custody",
|
||||||
|
"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,
|
||||||
"default": "0.00",
|
"default": "0.00",
|
||||||
"fieldname": "returns",
|
"fieldname": "returns",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Returns",
|
"label": "Returns",
|
||||||
"precision": "2"
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "2",
|
||||||
|
"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,
|
||||||
"default": "0.00",
|
"default": "0.00",
|
||||||
"fieldname": "outstanding_amount",
|
"fieldname": "outstanding_amount",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
|
"in_filter": 0,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Outstanding Amount",
|
"label": "Outstanding Amount",
|
||||||
"read_only": 1
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
|
"default": "0.0",
|
||||||
"fieldname": "payments",
|
"fieldname": "payments",
|
||||||
"fieldtype": "Table",
|
"fieldtype": "Table",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
|
"in_list_view": 0,
|
||||||
|
"in_standard_filter": 0,
|
||||||
"label": "Payments",
|
"label": "Payments",
|
||||||
"options": "Cashier Closing Payments"
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"options": "Cashier Closing 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
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "net_amount",
|
"fieldname": "net_amount",
|
||||||
"fieldtype": "Float",
|
"fieldtype": "Float",
|
||||||
|
"hidden": 0,
|
||||||
|
"ignore_user_permissions": 0,
|
||||||
|
"ignore_xss_filter": 0,
|
||||||
"in_filter": 1,
|
"in_filter": 1,
|
||||||
|
"in_global_search": 0,
|
||||||
"in_list_view": 1,
|
"in_list_view": 1,
|
||||||
"in_standard_filter": 1,
|
"in_standard_filter": 1,
|
||||||
"label": "Net Amount",
|
"label": "Net Amount",
|
||||||
"read_only": 1
|
"length": 0,
|
||||||
|
"no_copy": 0,
|
||||||
|
"permlevel": 0,
|
||||||
|
"precision": "",
|
||||||
|
"print_hide": 0,
|
||||||
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
"allow_bulk_edit": 0,
|
||||||
|
"allow_in_quick_entry": 0,
|
||||||
|
"allow_on_submit": 0,
|
||||||
|
"bold": 0,
|
||||||
|
"collapsible": 0,
|
||||||
|
"columns": 0,
|
||||||
"fieldname": "amended_from",
|
"fieldname": "amended_from",
|
||||||
"fieldtype": "Link",
|
"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",
|
"label": "Amended From",
|
||||||
|
"length": 0,
|
||||||
"no_copy": 1,
|
"no_copy": 1,
|
||||||
"options": "Cashier Closing",
|
"options": "Cashier Closing",
|
||||||
|
"permlevel": 0,
|
||||||
"print_hide": 1,
|
"print_hide": 1,
|
||||||
"read_only": 1
|
"print_hide_if_no_value": 0,
|
||||||
|
"read_only": 1,
|
||||||
|
"remember_last_selected_value": 0,
|
||||||
|
"report_hide": 0,
|
||||||
|
"reqd": 0,
|
||||||
|
"search_index": 0,
|
||||||
|
"set_only_once": 0,
|
||||||
|
"translatable": 0,
|
||||||
|
"unique": 0
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"has_web_view": 0,
|
||||||
|
"hide_heading": 0,
|
||||||
|
"hide_toolbar": 0,
|
||||||
|
"idx": 0,
|
||||||
|
"image_view": 0,
|
||||||
|
"in_create": 0,
|
||||||
"is_submittable": 1,
|
"is_submittable": 1,
|
||||||
"links": [],
|
"issingle": 0,
|
||||||
"modified": "2023-12-28 13:15:46.858427",
|
"istable": 0,
|
||||||
|
"max_attachments": 0,
|
||||||
|
"modified": "2019-02-19 08:35:24.157327",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Cashier Closing",
|
"name": "Cashier Closing",
|
||||||
"naming_rule": "By \"Naming Series\" field",
|
"name_case": "",
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
|
"amend": 0,
|
||||||
|
"cancel": 0,
|
||||||
"create": 1,
|
"create": 1,
|
||||||
"delete": 1,
|
"delete": 1,
|
||||||
"email": 1,
|
"email": 1,
|
||||||
"export": 1,
|
"export": 1,
|
||||||
|
"if_owner": 0,
|
||||||
|
"import": 0,
|
||||||
|
"permlevel": 0,
|
||||||
"print": 1,
|
"print": 1,
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"report": 1,
|
"report": 1,
|
||||||
"role": "System Manager",
|
"role": "System Manager",
|
||||||
|
"set_user_permissions": 0,
|
||||||
"share": 1,
|
"share": 1,
|
||||||
"submit": 1,
|
"submit": 1,
|
||||||
"write": 1
|
"write": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"quick_entry": 0,
|
||||||
|
"read_only": 0,
|
||||||
|
"read_only_onload": 0,
|
||||||
|
"show_name_in_global_search": 0,
|
||||||
"sort_field": "modified",
|
"sort_field": "modified",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC",
|
||||||
"states": [],
|
"track_changes": 1,
|
||||||
"track_changes": 1
|
"track_seen": 0,
|
||||||
|
"track_views": 0
|
||||||
}
|
}
|
||||||
@@ -9,32 +9,6 @@ from frappe.utils import flt
|
|||||||
|
|
||||||
|
|
||||||
class CashierClosing(Document):
|
class CashierClosing(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.cashier_closing_payments.cashier_closing_payments import (
|
|
||||||
CashierClosingPayments,
|
|
||||||
)
|
|
||||||
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
custody: DF.Float
|
|
||||||
date: DF.Date | None
|
|
||||||
expense: DF.Float
|
|
||||||
from_time: DF.Time
|
|
||||||
naming_series: DF.Literal["POS-CLO-"]
|
|
||||||
net_amount: DF.Float
|
|
||||||
outstanding_amount: DF.Float
|
|
||||||
payments: DF.Table[CashierClosingPayments]
|
|
||||||
returns: DF.Float
|
|
||||||
time: DF.Time
|
|
||||||
user: DF.Link
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_time()
|
self.validate_time()
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CashierClosingPayments(Document):
|
class CashierClosingPayments(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
amount: DF.Float
|
|
||||||
mode_of_payment: DF.Link
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -53,18 +53,10 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
|||||||
of Accounts. Please enter the account names and add more rows as per your requirement.`);
|
of Accounts. Please enter the account names and add more rows as per your requirement.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
{
|
|
||||||
label : "Company",
|
|
||||||
fieldname: "company",
|
|
||||||
fieldtype: "Link",
|
|
||||||
reqd: 1,
|
|
||||||
hidden: 1,
|
|
||||||
default: frm.doc.company,
|
|
||||||
},
|
|
||||||
],
|
],
|
||||||
primary_action: function() {
|
primary_action: function() {
|
||||||
let data = d.get_values();
|
var data = d.get_values();
|
||||||
|
|
||||||
if (!data.template_type) {
|
if (!data.template_type) {
|
||||||
frappe.throw(__('Please select <b>Template Type</b> to download template'));
|
frappe.throw(__('Please select <b>Template Type</b> to download template'));
|
||||||
@@ -74,8 +66,7 @@ frappe.ui.form.on('Chart of Accounts Importer', {
|
|||||||
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
|
'/api/method/erpnext.accounts.doctype.chart_of_accounts_importer.chart_of_accounts_importer.download_template',
|
||||||
{
|
{
|
||||||
file_type: data.file_type,
|
file_type: data.file_type,
|
||||||
template_type: data.template_type,
|
template_type: data.template_type
|
||||||
company: data.company
|
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ from functools import reduce
|
|||||||
|
|
||||||
import frappe
|
import frappe
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from frappe.desk.form.linked_with import get_linked_fields
|
|
||||||
from frappe.model.document import Document
|
from frappe.model.document import Document
|
||||||
from frappe.utils import cint, cstr
|
from frappe.utils import cint, cstr
|
||||||
from frappe.utils.csvutils import UnicodeWriter
|
from frappe.utils.csvutils import UnicodeWriter
|
||||||
@@ -24,18 +23,6 @@ from erpnext.accounts.doctype.account.chart_of_accounts.chart_of_accounts import
|
|||||||
|
|
||||||
|
|
||||||
class ChartofAccountsImporter(Document):
|
class ChartofAccountsImporter(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
company: DF.Link | None
|
|
||||||
import_file: DF.Attach | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
if self.import_file:
|
if self.import_file:
|
||||||
get_coa(
|
get_coa(
|
||||||
@@ -125,7 +112,7 @@ def generate_data_from_csv(file_doc, as_dict=False):
|
|||||||
if as_dict:
|
if as_dict:
|
||||||
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
data.append({frappe.scrub(header): row[index] for index, header in enumerate(headers)})
|
||||||
else:
|
else:
|
||||||
if not row[1] and len(row) > 1:
|
if not row[1]:
|
||||||
row[1] = row[0]
|
row[1] = row[0]
|
||||||
row[3] = row[2]
|
row[3] = row[2]
|
||||||
data.append(row)
|
data.append(row)
|
||||||
@@ -307,8 +294,10 @@ def build_response_as_excel(writer):
|
|||||||
|
|
||||||
|
|
||||||
@frappe.whitelist()
|
@frappe.whitelist()
|
||||||
def download_template(file_type, template_type, company):
|
def download_template(file_type, template_type):
|
||||||
writer = get_template(template_type, company)
|
data = frappe._dict(frappe.local.form_dict)
|
||||||
|
|
||||||
|
writer = get_template(template_type)
|
||||||
|
|
||||||
if file_type == "CSV":
|
if file_type == "CSV":
|
||||||
# download csv file
|
# download csv file
|
||||||
@@ -319,7 +308,8 @@ def download_template(file_type, template_type, company):
|
|||||||
build_response_as_excel(writer)
|
build_response_as_excel(writer)
|
||||||
|
|
||||||
|
|
||||||
def get_template(template_type, company):
|
def get_template(template_type):
|
||||||
|
|
||||||
fields = [
|
fields = [
|
||||||
"Account Name",
|
"Account Name",
|
||||||
"Parent Account",
|
"Parent Account",
|
||||||
@@ -345,17 +335,34 @@ def get_template(template_type, company):
|
|||||||
["", "", "", "", 0, account_type.get("account_type"), account_type.get("root_type")]
|
["", "", "", "", 0, account_type.get("account_type"), account_type.get("root_type")]
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
writer = get_sample_template(writer, company)
|
writer = get_sample_template(writer)
|
||||||
|
|
||||||
return writer
|
return writer
|
||||||
|
|
||||||
|
|
||||||
def get_sample_template(writer, company):
|
def get_sample_template(writer):
|
||||||
currency = frappe.db.get_value("Company", company, "default_currency")
|
template = [
|
||||||
with open(os.path.join(os.path.dirname(__file__), "coa_sample_template.csv"), "r") as f:
|
["Application Of Funds(Assets)", "", "", "", 1, "", "Asset"],
|
||||||
for row in f:
|
["Sources Of Funds(Liabilities)", "", "", "", 1, "", "Liability"],
|
||||||
row = row.strip().split(",") + [currency]
|
["Equity", "", "", "", 1, "", "Equity"],
|
||||||
writer.writerow(row)
|
["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:
|
||||||
|
writer.writerow(row)
|
||||||
|
|
||||||
return writer
|
return writer
|
||||||
|
|
||||||
@@ -446,11 +453,14 @@ def get_mandatory_account_types():
|
|||||||
|
|
||||||
|
|
||||||
def unset_existing_data(company):
|
def unset_existing_data(company):
|
||||||
# remove accounts data from company
|
linked = frappe.db.sql(
|
||||||
|
'''select fieldname from tabDocField
|
||||||
|
where fieldtype="Link" and options="Account" and parent="Company"''',
|
||||||
|
as_dict=True,
|
||||||
|
)
|
||||||
|
|
||||||
fieldnames = get_linked_fields("Account").get("Company", {}).get("fieldname", [])
|
# remove accounts data from company
|
||||||
linked = [{"fieldname": name} for name in fieldnames]
|
update_values = {d.fieldname: "" for d in linked}
|
||||||
update_values = {d.get("fieldname"): "" for d in linked}
|
|
||||||
frappe.db.set_value("Company", company, update_values, update_values)
|
frappe.db.set_value("Company", company, update_values, update_values)
|
||||||
|
|
||||||
# remove accounts data from various doctypes
|
# remove accounts data from various doctypes
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
Application Of Funds(Assets),,,,1,,Asset
|
|
||||||
Sources Of Funds(Liabilities),,,,1,,Liability
|
|
||||||
Equity,,,,1,,Equity
|
|
||||||
Expenses,,,,1,Expense Account,Expense
|
|
||||||
Income,,,,1,Income Account,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
|
|
||||||
|
@@ -8,41 +8,6 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class ChequePrintTemplate(Document):
|
class ChequePrintTemplate(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
acc_no_dist_from_left_edge: DF.Float
|
|
||||||
acc_no_dist_from_top_edge: DF.Float
|
|
||||||
acc_pay_dist_from_left_edge: DF.Float
|
|
||||||
acc_pay_dist_from_top_edge: DF.Float
|
|
||||||
amt_in_figures_from_left_edge: DF.Float
|
|
||||||
amt_in_figures_from_top_edge: DF.Float
|
|
||||||
amt_in_word_width: DF.Float
|
|
||||||
amt_in_words_from_left_edge: DF.Float
|
|
||||||
amt_in_words_from_top_edge: DF.Float
|
|
||||||
amt_in_words_line_spacing: DF.Float
|
|
||||||
bank_name: DF.Data
|
|
||||||
cheque_height: DF.Float
|
|
||||||
cheque_size: DF.Literal["", "Regular", "A4"]
|
|
||||||
cheque_width: DF.Float
|
|
||||||
date_dist_from_left_edge: DF.Float
|
|
||||||
date_dist_from_top_edge: DF.Float
|
|
||||||
has_print_format: DF.Check
|
|
||||||
is_account_payable: DF.Check
|
|
||||||
message_to_show: DF.Data | None
|
|
||||||
payer_name_from_left_edge: DF.Float
|
|
||||||
payer_name_from_top_edge: DF.Float
|
|
||||||
scanned_cheque: DF.Attach | None
|
|
||||||
signatory_from_left_edge: DF.Float
|
|
||||||
signatory_from_top_edge: DF.Float
|
|
||||||
starting_position_from_top_edge: DF.Float
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class ClosedDocument(Document):
|
class ClosedDocument(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
closed: DF.Check
|
|
||||||
document_type: DF.Link
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -10,25 +10,6 @@ from erpnext.accounts.utils import validate_field_number
|
|||||||
|
|
||||||
|
|
||||||
class CostCenter(NestedSet):
|
class CostCenter(NestedSet):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
company: DF.Link
|
|
||||||
cost_center_name: DF.Data
|
|
||||||
cost_center_number: DF.Data | None
|
|
||||||
disabled: DF.Check
|
|
||||||
is_group: DF.Check
|
|
||||||
lft: DF.Int
|
|
||||||
old_parent: DF.Link | None
|
|
||||||
parent_cost_center: DF.Link
|
|
||||||
rgt: DF.Int
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
nsm_parent_field = "parent_cost_center"
|
nsm_parent_field = "parent_cost_center"
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
|
|||||||
@@ -28,25 +28,6 @@ class InvalidDateError(frappe.ValidationError):
|
|||||||
|
|
||||||
|
|
||||||
class CostCenterAllocation(Document):
|
class CostCenterAllocation(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.cost_center_allocation_percentage.cost_center_allocation_percentage import (
|
|
||||||
CostCenterAllocationPercentage,
|
|
||||||
)
|
|
||||||
|
|
||||||
allocation_percentages: DF.Table[CostCenterAllocationPercentage]
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
company: DF.Link
|
|
||||||
main_cost_center: DF.Link
|
|
||||||
valid_from: DF.Date
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super(CostCenterAllocation, self).__init__(*args, **kwargs)
|
super(CostCenterAllocation, self).__init__(*args, **kwargs)
|
||||||
self._skip_from_date_validation = False
|
self._skip_from_date_validation = False
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CostCenterAllocationPercentage(Document):
|
class CostCenterAllocationPercentage(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
cost_center: DF.Link
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
percentage: DF.Percent
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -80,7 +80,7 @@
|
|||||||
{
|
{
|
||||||
"fieldname": "valid_upto",
|
"fieldname": "valid_upto",
|
||||||
"fieldtype": "Date",
|
"fieldtype": "Date",
|
||||||
"label": "Valid Up To"
|
"label": "Valid Upto"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
|
"depends_on": "eval: doc.coupon_type == \"Promotional\"",
|
||||||
@@ -115,7 +115,7 @@
|
|||||||
"read_only": 1
|
"read_only": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"modified": "2024-01-24 02:20:26.145996",
|
"modified": "2019-10-19 14:48:14.602481",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Coupon Code",
|
"name": "Coupon Code",
|
||||||
|
|||||||
@@ -9,27 +9,6 @@ from frappe.utils import strip
|
|||||||
|
|
||||||
|
|
||||||
class CouponCode(Document):
|
class CouponCode(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
coupon_code: DF.Data | None
|
|
||||||
coupon_name: DF.Data
|
|
||||||
coupon_type: DF.Literal["Promotional", "Gift Card"]
|
|
||||||
customer: DF.Link | None
|
|
||||||
description: DF.TextEditor | None
|
|
||||||
maximum_use: DF.Int
|
|
||||||
pricing_rule: DF.Link
|
|
||||||
used: DF.Int
|
|
||||||
valid_from: DF.Date | None
|
|
||||||
valid_upto: DF.Date | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
self.coupon_name = strip(self.coupon_name)
|
self.coupon_name = strip(self.coupon_name)
|
||||||
self.name = self.coupon_name
|
self.name = self.coupon_name
|
||||||
|
|||||||
@@ -9,30 +9,6 @@ from frappe.utils import nowdate
|
|||||||
|
|
||||||
|
|
||||||
class CurrencyExchangeSettings(Document):
|
class CurrencyExchangeSettings(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.currency_exchange_settings_details.currency_exchange_settings_details import (
|
|
||||||
CurrencyExchangeSettingsDetails,
|
|
||||||
)
|
|
||||||
from erpnext.accounts.doctype.currency_exchange_settings_result.currency_exchange_settings_result import (
|
|
||||||
CurrencyExchangeSettingsResult,
|
|
||||||
)
|
|
||||||
|
|
||||||
access_key: DF.Data | None
|
|
||||||
api_endpoint: DF.Data
|
|
||||||
disabled: DF.Check
|
|
||||||
req_params: DF.Table[CurrencyExchangeSettingsDetails]
|
|
||||||
result_key: DF.Table[CurrencyExchangeSettingsResult]
|
|
||||||
service_provider: DF.Literal["frankfurter.app", "exchangerate.host", "Custom"]
|
|
||||||
url: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.set_parameters_and_result()
|
self.set_parameters_and_result()
|
||||||
if frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_setup_wizard:
|
if frappe.flags.in_test or frappe.flags.in_install or frappe.flags.in_setup_wizard:
|
||||||
|
|||||||
@@ -6,19 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CurrencyExchangeSettingsDetails(Document):
|
class CurrencyExchangeSettingsDetails(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
key: DF.Data
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
value: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CurrencyExchangeSettingsResult(Document):
|
class CurrencyExchangeSettingsResult(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
key: DF.Data
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CustomerGroupItem(Document):
|
class CustomerGroupItem(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
customer_group: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class CustomerItem(Document):
|
class CustomerItem(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
customer: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,22 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class DiscountedInvoice(Document):
|
class DiscountedInvoice(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
customer: DF.Link | None
|
|
||||||
debit_to: DF.Link | None
|
|
||||||
outstanding_amount: DF.Currency
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
posting_date: DF.Date | None
|
|
||||||
sales_invoice: DF.Link
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -22,52 +22,6 @@ from erpnext.controllers.accounts_controller import AccountsController
|
|||||||
|
|
||||||
|
|
||||||
class Dunning(AccountsController):
|
class Dunning(AccountsController):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.overdue_payment.overdue_payment import OverduePayment
|
|
||||||
|
|
||||||
address_display: DF.SmallText | None
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
base_dunning_amount: DF.Currency
|
|
||||||
body_text: DF.TextEditor | None
|
|
||||||
closing_text: DF.TextEditor | None
|
|
||||||
company: DF.Link
|
|
||||||
company_address: DF.Link | None
|
|
||||||
company_address_display: DF.SmallText | None
|
|
||||||
contact_display: DF.SmallText | None
|
|
||||||
contact_email: DF.Data | None
|
|
||||||
contact_mobile: DF.SmallText | None
|
|
||||||
contact_person: DF.Link | None
|
|
||||||
conversion_rate: DF.Float
|
|
||||||
cost_center: DF.Link | None
|
|
||||||
currency: DF.Link | None
|
|
||||||
customer: DF.Link
|
|
||||||
customer_address: DF.Link | None
|
|
||||||
customer_name: DF.Data | None
|
|
||||||
dunning_amount: DF.Currency
|
|
||||||
dunning_fee: DF.Currency
|
|
||||||
dunning_type: DF.Link | None
|
|
||||||
grand_total: DF.Currency
|
|
||||||
income_account: DF.Link | None
|
|
||||||
language: DF.Link | None
|
|
||||||
letter_head: DF.Link | None
|
|
||||||
naming_series: DF.Literal["DUNN-.MM.-.YY.-"]
|
|
||||||
overdue_payments: DF.Table[OverduePayment]
|
|
||||||
posting_date: DF.Date
|
|
||||||
posting_time: DF.Time | None
|
|
||||||
rate_of_interest: DF.Float
|
|
||||||
spacer: DF.Data | None
|
|
||||||
status: DF.Literal["Draft", "Resolved", "Unresolved", "Cancelled"]
|
|
||||||
total_interest: DF.Currency
|
|
||||||
total_outstanding: DF.Currency
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_same_currency()
|
self.validate_same_currency()
|
||||||
self.validate_overdue_payments()
|
self.validate_overdue_payments()
|
||||||
|
|||||||
@@ -7,21 +7,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class DunningLetterText(Document):
|
class DunningLetterText(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
body_text: DF.TextEditor | None
|
|
||||||
closing_text: DF.TextEditor | None
|
|
||||||
is_default_language: DF.Check
|
|
||||||
language: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -7,26 +7,6 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class DunningType(Document):
|
class DunningType(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.dunning_letter_text.dunning_letter_text import DunningLetterText
|
|
||||||
|
|
||||||
company: DF.Link
|
|
||||||
cost_center: DF.Link | None
|
|
||||||
dunning_fee: DF.Currency
|
|
||||||
dunning_letter_text: DF.Table[DunningLetterText]
|
|
||||||
dunning_type: DF.Data
|
|
||||||
income_account: DF.Link | None
|
|
||||||
is_default: DF.Check
|
|
||||||
rate_of_interest: DF.Float
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def autoname(self):
|
def autoname(self):
|
||||||
company_abbr = frappe.get_value("Company", self.company, "abbr")
|
company_abbr = frappe.get_value("Company", self.company, "abbr")
|
||||||
self.name = f"{self.dunning_type} - {company_abbr}"
|
self.name = f"{self.dunning_type} - {company_abbr}"
|
||||||
|
|||||||
@@ -17,34 +17,12 @@ from erpnext.setup.utils import get_exchange_rate
|
|||||||
|
|
||||||
|
|
||||||
class ExchangeRateRevaluation(Document):
|
class ExchangeRateRevaluation(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.exchange_rate_revaluation_account.exchange_rate_revaluation_account import (
|
|
||||||
ExchangeRateRevaluationAccount,
|
|
||||||
)
|
|
||||||
|
|
||||||
accounts: DF.Table[ExchangeRateRevaluationAccount]
|
|
||||||
amended_from: DF.Link | None
|
|
||||||
company: DF.Link
|
|
||||||
gain_loss_booked: DF.Currency
|
|
||||||
gain_loss_unbooked: DF.Currency
|
|
||||||
posting_date: DF.Date
|
|
||||||
rounding_loss_allowance: DF.Float
|
|
||||||
total_gain_loss: DF.Currency
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_rounding_loss_allowance()
|
self.validate_rounding_loss_allowance()
|
||||||
self.set_total_gain_loss()
|
self.set_total_gain_loss()
|
||||||
|
|
||||||
def validate_rounding_loss_allowance(self):
|
def validate_rounding_loss_allowance(self):
|
||||||
if self.rounding_loss_allowance < 0 or self.rounding_loss_allowance >= 1:
|
if not (self.rounding_loss_allowance >= 0 and self.rounding_loss_allowance < 1):
|
||||||
frappe.throw(_("Rounding Loss Allowance should be between 0 and 1"))
|
frappe.throw(_("Rounding Loss Allowance should be between 0 and 1"))
|
||||||
|
|
||||||
def set_total_gain_loss(self):
|
def set_total_gain_loss(self):
|
||||||
@@ -214,7 +192,7 @@ class ExchangeRateRevaluation(Document):
|
|||||||
# round off balance based on currency precision
|
# round off balance based on currency precision
|
||||||
# and consider debit-credit difference allowance
|
# and consider debit-credit difference allowance
|
||||||
currency_precision = get_currency_precision()
|
currency_precision = get_currency_precision()
|
||||||
rounding_loss_allowance = float(rounding_loss_allowance)
|
rounding_loss_allowance = float(rounding_loss_allowance) or 0.05
|
||||||
for acc in account_details:
|
for acc in account_details:
|
||||||
acc.balance_in_account_currency = flt(acc.balance_in_account_currency, currency_precision)
|
acc.balance_in_account_currency = flt(acc.balance_in_account_currency, currency_precision)
|
||||||
if abs(acc.balance_in_account_currency) <= rounding_loss_allowance:
|
if abs(acc.balance_in_account_currency) <= rounding_loss_allowance:
|
||||||
|
|||||||
@@ -6,29 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class ExchangeRateRevaluationAccount(Document):
|
class ExchangeRateRevaluationAccount(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
account: DF.Link
|
|
||||||
account_currency: DF.Link | None
|
|
||||||
balance_in_account_currency: DF.Currency
|
|
||||||
balance_in_base_currency: DF.Currency
|
|
||||||
current_exchange_rate: DF.Float
|
|
||||||
gain_loss: DF.Currency
|
|
||||||
new_balance_in_account_currency: DF.Currency
|
|
||||||
new_balance_in_base_currency: DF.Currency
|
|
||||||
new_exchange_rate: DF.Float
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
party: DF.DynamicLink | None
|
|
||||||
party_type: DF.Link | None
|
|
||||||
zero_balance: DF.Check
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -6,15 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class FinanceBook(Document):
|
class FinanceBook(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
finance_book_name: DF.Data | None
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"allow_import": 1,
|
"allow_import": 1,
|
||||||
"autoname": "field:year",
|
"autoname": "field:year",
|
||||||
"creation": "2013-01-22 16:50:25",
|
"creation": "2013-01-22 16:50:25",
|
||||||
"description": "Represents a Financial Year. All accounting entries and other major transactions are tracked against the Fiscal Year.",
|
"description": "**Fiscal Year** represents a Financial Year. All accounting entries and other major transactions are tracked against **Fiscal Year**.",
|
||||||
"doctype": "DocType",
|
"doctype": "DocType",
|
||||||
"document_type": "Setup",
|
"document_type": "Setup",
|
||||||
"engine": "InnoDB",
|
"engine": "InnoDB",
|
||||||
@@ -82,11 +82,10 @@
|
|||||||
"icon": "fa fa-calendar",
|
"icon": "fa fa-calendar",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2024-01-30 12:35:38.645968",
|
"modified": "2020-11-05 12:16:53.081573",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "Fiscal Year",
|
"name": "Fiscal Year",
|
||||||
"naming_rule": "By fieldname",
|
|
||||||
"owner": "Administrator",
|
"owner": "Administrator",
|
||||||
"permissions": [
|
"permissions": [
|
||||||
{
|
{
|
||||||
@@ -119,18 +118,9 @@
|
|||||||
{
|
{
|
||||||
"read": 1,
|
"read": 1,
|
||||||
"role": "Employee"
|
"role": "Employee"
|
||||||
},
|
|
||||||
{
|
|
||||||
"read": 1,
|
|
||||||
"role": "Accounts Manager"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"read": 1,
|
|
||||||
"role": "Stock Manager"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"show_name_in_global_search": 1,
|
"show_name_in_global_search": 1,
|
||||||
"sort_field": "name",
|
"sort_field": "name",
|
||||||
"sort_order": "DESC",
|
"sort_order": "DESC"
|
||||||
"states": []
|
|
||||||
}
|
}
|
||||||
@@ -10,25 +10,6 @@ from frappe.utils import add_days, add_years, cstr, getdate
|
|||||||
|
|
||||||
|
|
||||||
class FiscalYear(Document):
|
class FiscalYear(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
from erpnext.accounts.doctype.fiscal_year_company.fiscal_year_company import FiscalYearCompany
|
|
||||||
|
|
||||||
auto_created: DF.Check
|
|
||||||
companies: DF.Table[FiscalYearCompany]
|
|
||||||
disabled: DF.Check
|
|
||||||
is_short_year: DF.Check
|
|
||||||
year: DF.Data
|
|
||||||
year_end_date: DF.Date
|
|
||||||
year_start_date: DF.Date
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
def validate(self):
|
def validate(self):
|
||||||
self.validate_dates()
|
self.validate_dates()
|
||||||
self.validate_overlap()
|
self.validate_overlap()
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ def test_record_generator():
|
|||||||
]
|
]
|
||||||
|
|
||||||
start = 2012
|
start = 2012
|
||||||
end = now_datetime().year + 25
|
end = now_datetime().year + 5
|
||||||
for year in range(start, end):
|
for year in range(start, end):
|
||||||
test_records.append(
|
test_records.append(
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,18 +6,4 @@ from frappe.model.document import Document
|
|||||||
|
|
||||||
|
|
||||||
class FiscalYearCompany(Document):
|
class FiscalYearCompany(Document):
|
||||||
# begin: auto-generated types
|
|
||||||
# This code is auto-generated. Do not modify anything in this block.
|
|
||||||
|
|
||||||
from typing import TYPE_CHECKING
|
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
|
||||||
from frappe.types import DF
|
|
||||||
|
|
||||||
company: DF.Link | None
|
|
||||||
parent: DF.Data
|
|
||||||
parentfield: DF.Data
|
|
||||||
parenttype: DF.Data
|
|
||||||
# end: auto-generated types
|
|
||||||
|
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
"against_voucher_type",
|
"against_voucher_type",
|
||||||
"against_voucher",
|
"against_voucher",
|
||||||
"voucher_type",
|
"voucher_type",
|
||||||
"voucher_subtype",
|
|
||||||
"voucher_no",
|
"voucher_no",
|
||||||
"voucher_detail_no",
|
"voucher_detail_no",
|
||||||
"project",
|
"project",
|
||||||
@@ -143,7 +142,8 @@
|
|||||||
"label": "Against Voucher Type",
|
"label": "Against Voucher Type",
|
||||||
"oldfieldname": "against_voucher_type",
|
"oldfieldname": "against_voucher_type",
|
||||||
"oldfieldtype": "Data",
|
"oldfieldtype": "Data",
|
||||||
"options": "DocType"
|
"options": "DocType",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "against_voucher",
|
"fieldname": "against_voucher",
|
||||||
@@ -162,7 +162,8 @@
|
|||||||
"label": "Voucher Type",
|
"label": "Voucher Type",
|
||||||
"oldfieldname": "voucher_type",
|
"oldfieldname": "voucher_type",
|
||||||
"oldfieldtype": "Select",
|
"oldfieldtype": "Select",
|
||||||
"options": "DocType"
|
"options": "DocType",
|
||||||
|
"search_index": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldname": "voucher_no",
|
"fieldname": "voucher_no",
|
||||||
@@ -279,18 +280,13 @@
|
|||||||
"fieldtype": "Currency",
|
"fieldtype": "Currency",
|
||||||
"label": "Credit Amount in Transaction Currency",
|
"label": "Credit Amount in Transaction Currency",
|
||||||
"options": "transaction_currency"
|
"options": "transaction_currency"
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldname": "voucher_subtype",
|
|
||||||
"fieldtype": "Small Text",
|
|
||||||
"label": "Voucher Subtype"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"icon": "fa fa-list",
|
"icon": "fa fa-list",
|
||||||
"idx": 1,
|
"idx": 1,
|
||||||
"in_create": 1,
|
"in_create": 1,
|
||||||
"links": [],
|
"links": [],
|
||||||
"modified": "2023-09-26 12:03:23.031733",
|
"modified": "2023-08-16 21:38:44.072267",
|
||||||
"modified_by": "Administrator",
|
"modified_by": "Administrator",
|
||||||
"module": "Accounts",
|
"module": "Accounts",
|
||||||
"name": "GL Entry",
|
"name": "GL Entry",
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user