Compare commits

..

1 Commits

Author SHA1 Message Date
Michelle Alva
ce21653266 fix: link for customize ERPNext 2024-08-08 12:33:04 +05:30
1036 changed files with 658325 additions and 502461 deletions

View File

@@ -18,4 +18,4 @@ max_line_length = 110
[{*.json}]
insert_final_newline = false
indent_style = space
indent_size = 1
indent_size = 2

View File

@@ -38,7 +38,3 @@ ec74a5e56617bbd76ac402451468fd4668af543d
# ruff formatting
a308792ee7fda18a681e9181f4fd00b36385bc23
# noisy typing refactoring of get_item_details
7b7211ac79c248a79ba8a999ff34e734d874c0ae
d827ed21adc7b36047e247cbb0dc6388d048a7f9

View File

@@ -12,16 +12,9 @@ pip install frappe-bench
githubbranch=${GITHUB_BASE_REF:-${GITHUB_REF##*/}}
frappeuser=${FRAPPE_USER:-"frappe"}
frappecommitish=${FRAPPE_BRANCH:-$githubbranch}
mkdir frappe
pushd frappe
git init
git remote add origin "https://github.com/${frappeuser}/frappe"
git fetch origin "${frappecommitish}" --depth 1
git checkout FETCH_HEAD
popd
frappebranch=${FRAPPE_BRANCH:-$githubbranch}
git clone "https://github.com/${frappeuser}/frappe" --branch "${frappebranch}" --depth 1
bench init --skip-assets --frappe-path ~/frappe --python "$(which python)" frappe-bench
mkdir ~/frappe-bench/sites/test_site

8
.github/stale.yml vendored
View File

@@ -12,14 +12,6 @@ exemptProjects: true
# Set to true to ignore issues in a milestone (defaults to false)
exemptMilestones: true
# Skip the stale action for draft PRs
exemptDraftPr: true
# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable
exemptLabels:
- hotfix
- no-stale
pulls:
daysUntilStale: 15
daysUntilClose: 3

View File

@@ -137,8 +137,7 @@ jobs:
update_to_version 15
echo "Updating to latest version"
git -C "apps/frappe" fetch --depth 1 upstream "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
git -C "apps/frappe" checkout -q -f FETCH_HEAD
git -C "apps/frappe" checkout -q -f "${GITHUB_BASE_REF:-${GITHUB_REF##*/}}"
git -C "apps/erpnext" checkout -q -f "$GITHUB_SHA"
pgrep honcho | xargs kill

View File

@@ -1,130 +0,0 @@
name: Individual
on:
workflow_dispatch:
concurrency:
group: server-individual-tests-develop-${{ github.event_name }}-${{ github.event.number || github.event_name == 'workflow_dispatch' && github.run_id || '' }}
cancel-in-progress: false
jobs:
discover:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.set-matrix.outputs.matrix }}
steps:
- name: Clone
uses: actions/checkout@v4
- id: set-matrix
run: |
# Use grep and find to get the list of test files
matrix=$(find . -path '*/doctype/*/test_*.py' | xargs grep -l 'def test_' | awk '{
# Remove ./ prefix, file extension, and replace / with .
gsub(/^\.\//, "", $0)
gsub(/\.py$/, "", $0)
gsub(/\//, ".", $0)
# Add to array
tests[NR] = $0
}
END {
# Start JSON array
printf "{\n \"include\": [\n"
# Loop through array and create JSON objects
for (i=1; i<=NR; i++) {
printf " {\"test\": \"%s\"}", tests[i]
if (i < NR) printf ","
printf "\n"
}
# Close JSON array
printf " ]\n}"
}')
# Output the matrix
echo "matrix=$(echo "$matrix" | jq -c)" >> $GITHUB_OUTPUT
# For debugging (optional)
echo "Generated matrix:"
echo "$matrix"
test:
needs: discover
runs-on: ubuntu-latest
timeout-minutes: 60
env:
NODE_ENV: "production"
strategy:
fail-fast: false
matrix: ${{fromJson(needs.discover.outputs.matrix)}}
name: Test
services:
mysql:
image: mariadb:10.6
env:
MARIADB_ROOT_PASSWORD: 'root'
ports:
- 3306:3306
options: --health-cmd="mariadb-admin ping" --health-interval=5s --health-timeout=2s --health-retries=3
steps:
- name: Clone
uses: actions/checkout@v4
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 18
check-latest: true
- name: Add to Hosts
run: echo "127.0.0.1 test_site" | sudo tee -a /etc/hosts
- name: Cache pip
uses: actions/cache@v4
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/*requirements.txt', '**/pyproject.toml') }}
restore-keys: |
${{ runner.os }}-pip-
${{ runner.os }}-
- name: Cache node modules
uses: actions/cache@v4
env:
cache-name: cache-node-modules
with:
path: ~/.npm
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-build-${{ env.cache-name }}-
${{ runner.os }}-build-
${{ runner.os }}-
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v4
id: yarn-cache
with:
path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- name: Install
run: bash ${GITHUB_WORKSPACE}/.github/helper/install.sh
env:
DB: mariadb
TYPE: server
FRAPPE_USER: ${{ github.event.inputs.user }}
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-tests --app erpnext --module ${{ matrix.test }}'

View File

@@ -1,8 +1,6 @@
name: Server (Mariadb)
on:
repository_dispatch:
types: [frappe-framework-change]
pull_request:
paths-ignore:
- '**.js'
@@ -119,10 +117,10 @@ jobs:
DB: mariadb
TYPE: server
FRAPPE_USER: ${{ github.event.inputs.user }}
FRAPPE_BRANCH: ${{ github.event.client_payload.sha || github.event.inputs.branch }}
FRAPPE_BRANCH: ${{ github.event.inputs.branch }}
- name: Run Tests
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds ${{ strategy.job-total }} --build-number ${{ matrix.container }}'
run: 'cd ~/frappe-bench/ && bench --site test_site run-parallel-tests --app erpnext --total-builds 4 --build-number ${{ matrix.container }}'
env:
TYPE: server
CAPTURE_COVERAGE: ${{ github.event_name != 'pull_request' }}

5
.gitignore vendored
View File

@@ -14,8 +14,5 @@ __pycache__
*~
.idea/
.vscode/
.helix/
node_modules/
.backportrc.json
# Aider AI Chat
.aider*
.backportrc.json

View File

@@ -3,22 +3,22 @@
# These owners will be the default owners for everything in
# the repo. Unless a later match takes precedence,
erpnext/accounts/ @ruthra-kumar
erpnext/assets/ @khushi8112
erpnext/regional @ruthra-kumar
erpnext/selling @ruthra-kumar
erpnext/support/ @ruthra-kumar
erpnext/accounts/ @deepeshgarg007 @ruthra-kumar
erpnext/assets/ @anandbaburajan @deepeshgarg007
erpnext/regional @deepeshgarg007 @ruthra-kumar
erpnext/selling @deepeshgarg007 @ruthra-kumar
erpnext/support/ @deepeshgarg007
pos*
erpnext/buying/ @rohitwaghchaure
erpnext/maintenance/ @rohitwaghchaure
erpnext/manufacturing/ @rohitwaghchaure
erpnext/quality_management/ @rohitwaghchaure
erpnext/stock/ @rohitwaghchaure
erpnext/subcontracting @rohitwaghchaure
erpnext/buying/ @rohitwaghchaure @s-aga-r
erpnext/maintenance/ @rohitwaghchaure @s-aga-r
erpnext/manufacturing/ @rohitwaghchaure @s-aga-r
erpnext/quality_management/ @rohitwaghchaure @s-aga-r
erpnext/stock/ @rohitwaghchaure @s-aga-r
erpnext/subcontracting @rohitwaghchaure @s-aga-r
erpnext/controllers/ @ruthra-kumar @rohitwaghchaure
erpnext/patches/ @ruthra-kumar
erpnext/controllers/ @deepeshgarg007 @rohitwaghchaure
erpnext/patches/ @deepeshgarg007
.github/ @ruthra-kumar
pyproject.toml @akhilnarang
.github/ @deepeshgarg007
pyproject.toml @phot0n

View File

@@ -30,7 +30,7 @@ ERPNext as a monolith includes the following areas for managing businesses:
1. [Quality Management](https://erpnext.com/docs/user/manual/en/quality-management)
1. [Manufacturing](https://erpnext.com/open-source-manufacturing-erp-software)
1. [Website Management](https://erpnext.com/open-source-website-builder-software)
1. [Customize ERPNext](https://erpnext.com/docs/user/manual/en/customize-erpnext)
1. [Customize ERPNext](https://docs.erpnext.com/docs/v13/user/manual/en/customize-erpnext)
1. [And More](https://erpnext.com/docs/user/manual/en/)
ERPNext is built on the [Frappe Framework](https://github.com/frappe/frappe), a full-stack web app framework built with Python & JavaScript.

View File

@@ -1,3 +1,2 @@
**/setup/setup_wizard/data/uom_data.json,erpnext.gettext.extractors.uom_data.extract
**/setup/doctype/incoterm/incoterms.csv,erpnext.gettext.extractors.incoterms.extract
**/setup/setup_wizard/data/*.txt,erpnext.gettext.extractors.lines_from_txt_file.extract
1 **/setup/setup_wizard/data/uom_data.json erpnext.gettext.extractors.uom_data.extract
2 **/setup/doctype/incoterm/incoterms.csv erpnext.gettext.extractors.incoterms.extract
**/setup/setup_wizard/data/*.txt erpnext.gettext.extractors.lines_from_txt_file.extract

View File

@@ -1,10 +1,7 @@
import functools
import inspect
from typing import TypeVar
import frappe
from frappe.model.document import Document
from frappe.utils.user import is_website_user
__version__ = "16.0.0-dev"
@@ -152,44 +149,3 @@ def allow_regional(fn):
return frappe.get_attr(overrides[function_path][-1])(*args, **kwargs)
return caller
def check_app_permission():
if frappe.session.user == "Administrator":
return True
if is_website_user():
return False
return True
T = TypeVar("T")
def normalize_ctx_input(T: type) -> callable:
"""
Normalizes the first argument (ctx) of the decorated function by:
- Converting Document objects to dictionaries
- Parsing JSON strings
- Casting the result to the specified type T
"""
def decorator(func: callable):
# conserve annotations for frappe.utils.typing_validations
@functools.wraps(func, assigned=(a for a in functools.WRAPPER_ASSIGNMENTS if a != "__annotations__"))
def wrapper(ctx: T | Document | dict | str, *args, **kwargs):
if isinstance(ctx, Document):
ctx = T(**ctx.as_dict())
elif isinstance(ctx, dict):
ctx = T(**ctx)
else:
ctx = T(**frappe.parse_json(ctx))
return func(ctx, *args, **kwargs)
# set annotations from function
wrapper.__annotations__.update({k: v for k, v in func.__annotations__.items() if k != "ctx"})
return wrapper
return decorator

View File

@@ -58,7 +58,7 @@ def build_conditions(process_type, account, company):
)
if account:
conditions += f"AND {deferred_account}={frappe.db.escape(account)}"
conditions += f"AND {deferred_account}='{account}'"
elif company:
conditions += f"AND p.company = {frappe.db.escape(company)}"

View File

@@ -124,7 +124,7 @@
"label": "Account Type",
"oldfieldname": "account_type",
"oldfieldtype": "Select",
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nRound Off for Opening\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
"options": "\nAccumulated Depreciation\nAsset Received But Not Billed\nBank\nCash\nChargeable\nCapital Work in Progress\nCost of Goods Sold\nCurrent Asset\nCurrent Liability\nDepreciation\nDirect Expense\nDirect Income\nEquity\nExpense Account\nExpenses Included In Asset Valuation\nExpenses Included In Valuation\nFixed Asset\nIncome Account\nIndirect Expense\nIndirect Income\nLiability\nPayable\nReceivable\nRound Off\nStock\nStock Adjustment\nStock Received But Not Billed\nService Received But Not Billed\nTax\nTemporary",
"search_index": 1
},
{
@@ -194,7 +194,7 @@
"idx": 1,
"is_tree": 1,
"links": [],
"modified": "2024-08-19 15:19:11.095045",
"modified": "2024-06-27 16:23:04.444354",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Account",

View File

@@ -60,7 +60,6 @@ class Account(NestedSet):
"Payable",
"Receivable",
"Round Off",
"Round Off for Opening",
"Stock",
"Stock Adjustment",
"Stock Received But Not Billed",
@@ -102,12 +101,14 @@ class Account(NestedSet):
self.name = get_autoname_with_number(self.account_number, self.account_name, self.company)
def validate(self):
from erpnext.accounts.utils import validate_field_number
if frappe.local.flags.allow_unverified_charts:
return
self.validate_parent()
self.validate_parent_child_account_type()
self.validate_root_details()
self.validate_account_number()
validate_field_number("Account", self.name, self.account_number, self.company, "account_number")
self.validate_group_or_ledger()
self.set_root_and_report_type()
self.validate_mandatory()
@@ -199,7 +200,7 @@ class Account(NestedSet):
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.bold("Account Type"), doc_before_save.account_type, doc_before_save.account_type
)
frappe.msgprint(msg)
self.add_comment("Comment", msg)
@@ -308,22 +309,6 @@ class Account(NestedSet):
if frappe.db.get_value("GL Entry", {"account": self.name}):
frappe.throw(_("Currency can not be changed after making entries using some other currency"))
def validate_account_number(self, account_number=None):
if not account_number:
account_number = self.account_number
if account_number:
account_with_same_number = frappe.db.get_value(
"Account",
{"account_number": account_number, "company": self.company, "name": ["!=", self.name]},
)
if account_with_same_number:
frappe.throw(
_("Account Number {0} already used in account {1}").format(
account_number, account_with_same_number
)
)
def create_account_for_child_company(self, parent_acc_name_map, descendants, parent_acc_name):
for company in descendants:
company_bold = frappe.bold(company)
@@ -477,6 +462,19 @@ def get_account_autoname(account_number, account_name, company):
return " - ".join(parts)
def validate_account_number(name, account_number, company):
if account_number:
account_with_same_number = frappe.db.get_value(
"Account", {"account_number": account_number, "company": company, "name": ["!=", name]}
)
if account_with_same_number:
frappe.throw(
_("Account Number {0} already used in account {1}").format(
account_number, account_with_same_number
)
)
@frappe.whitelist()
def update_account_number(name, account_name, account_number=None, from_descendant=False):
account = frappe.get_cached_doc("Account", name)
@@ -517,7 +515,7 @@ def update_account_number(name, account_name, account_number=None, from_descenda
frappe.throw(message, title=_("Rename Not Allowed"))
account.validate_account_number(account_number)
validate_account_number(name, account_number, account.company)
if account_number:
frappe.db.set_value("Account", name, "account_number", account_number.strip())
else:

View File

@@ -109,8 +109,7 @@
"Utility Expenses": {},
"Write Off": {},
"Exchange Gain/Loss": {},
"Gain/Loss on Asset Disposal": {},
"Impairment": {}
"Gain/Loss on Asset Disposal": {}
},
"root_type": "Expense"
},
@@ -133,8 +132,7 @@
"Source of Funds (Liabilities)": {
"Capital Account": {
"Reserves and Surplus": {},
"Shareholders Funds": {},
"Revaluation Surplus": {}
"Shareholders Funds": {}
},
"Current Liabilities": {
"Accounts Payable": {

View File

@@ -72,7 +72,6 @@ def get():
_("Write Off"): {},
_("Exchange Gain/Loss"): {},
_("Gain/Loss on Asset Disposal"): {},
_("Impairment"): {},
},
"root_type": "Expense",
},
@@ -105,7 +104,6 @@ def get():
_("Dividends Paid"): {"account_type": "Equity"},
_("Opening Balance Equity"): {"account_type": "Equity"},
_("Retained Earnings"): {"account_type": "Equity"},
_("Revaluation Surplus"): {"account_type": "Equity"},
"root_type": "Equity",
},
}

View File

@@ -1,9 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.test_runner import make_test_records
from frappe.utils import nowdate
from erpnext.accounts.doctype.account.account import (
@@ -13,10 +15,10 @@ from erpnext.accounts.doctype.account.account import (
)
from erpnext.stock import get_company_default_inventory_account, get_warehouse_account
EXTRA_TEST_RECORD_DEPENDENCIES = ["Company"]
test_dependencies = ["Company"]
class TestAccount(IntegrationTestCase):
class TestAccount(unittest.TestCase):
def test_rename_account(self):
if not frappe.db.exists("Account", "1210 - Debtors - _TC"):
acc = frappe.new_doc("Account")
@@ -201,6 +203,8 @@ class TestAccount(IntegrationTestCase):
In a parent->child company setup, child should inherit parent account currency if explicitly specified.
"""
make_test_records("Company")
frappe.local.flags.pop("ignore_root_company_validation", None)
def create_bank_account():
@@ -324,7 +328,7 @@ class TestAccount(IntegrationTestCase):
def _make_test_records(verbose=None):
from frappe.tests.utils import make_test_objects
from frappe.test_runner import make_test_objects
accounts = [
# [account_name, parent_account, is_group]

View File

@@ -0,0 +1,6 @@
[
{
"doctype": "Account",
"name": "_Test Account 1"
}
]

View File

@@ -1,3 +0,0 @@
[[Account]]
name = "_Test Account 1"

View File

@@ -113,9 +113,9 @@ def get_previous_closing_entries(company, closing_date, accounting_dimensions):
entries = []
last_period_closing_voucher = frappe.db.get_all(
"Period Closing Voucher",
filters={"docstatus": 1, "company": company, "period_end_date": ("<", closing_date)},
filters={"docstatus": 1, "company": company, "posting_date": ("<", closing_date)},
fields=["name"],
order_by="period_end_date desc",
order_by="posting_date desc",
limit=1,
)

View File

@@ -2,17 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
class UnitTestAccountClosingBalance(UnitTestCase):
"""
Unit tests for AccountClosingBalance.
Use this class for testing individual functions and methods.
"""
pass
class TestAccountClosingBalance(IntegrationTestCase):
class TestAccountClosingBalance(FrappeTestCase):
pass

View File

@@ -58,7 +58,7 @@ frappe.ui.form.on("Accounting Dimension", {
},
label: function (frm) {
frm.set_value("fieldname", frm.doc.label.replace(/ /g, "_").replace(/-/g, "_").toLowerCase());
frm.set_value("fieldname", frappe.model.scrub(frm.doc.label));
},
document_type: function (frm) {

View File

@@ -7,7 +7,6 @@ import json
import frappe
from frappe import _, scrub
from frappe.custom.doctype.custom_field.custom_field import create_custom_field
from frappe.database.schema import validate_column_name
from frappe.model import core_doctypes_list
from frappe.model.document import Document
from frappe.utils import cstr
@@ -61,7 +60,6 @@ class AccountingDimension(Document):
if not self.is_new():
self.validate_document_type_change()
validate_column_name(self.fieldname)
self.validate_dimension_defaults()
def validate_document_type_change(self):

View File

@@ -1,17 +1,17 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
EXTRA_TEST_RECORD_DEPENDENCIES = ["Cost Center", "Location", "Warehouse", "Department"]
test_dependencies = ["Cost Center", "Location", "Warehouse", "Department"]
class TestAccountingDimension(IntegrationTestCase):
class TestAccountingDimension(unittest.TestCase):
def setUp(self):
create_dimension()

View File

@@ -12,7 +12,7 @@ from erpnext.accounts.doctype.accounting_dimension.test_accounting_dimension imp
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.exceptions import InvalidAccountDimensionError, MandatoryAccountDimensionError
EXTRA_TEST_RECORD_DEPENDENCIES = ["Location", "Cost Center", "Department"]
test_dependencies = ["Location", "Cost Center", "Department"]
class TestAccountingDimensionFilter(unittest.TestCase):

View File

@@ -101,8 +101,6 @@ def validate_accounting_period_on_doc_save(doc, method=None):
date = doc.available_for_use_date
elif doc.doctype == "Asset Repair":
date = doc.completion_date
elif doc.doctype == "Period Closing Voucher":
date = doc.period_end_date
else:
date = doc.posting_date

View File

@@ -1,9 +1,9 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_months, nowdate
from erpnext.accounts.doctype.accounting_period.accounting_period import (
@@ -12,10 +12,10 @@ from erpnext.accounts.doctype.accounting_period.accounting_period import (
)
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item"]
test_dependencies = ["Item"]
class TestAccountingPeriod(IntegrationTestCase):
class TestAccountingPeriod(unittest.TestCase):
def test_overlap(self):
ap1 = create_accounting_period(
start_date="2018-04-01", end_date="2018-06-30", company="Wind Power LLC"

View File

@@ -1,10 +1,9 @@
import unittest
import frappe
from frappe.tests import IntegrationTestCase
class TestAccountsSettings(IntegrationTestCase):
class TestAccountsSettings(unittest.TestCase):
def tearDown(self):
# Just in case `save` method succeeds, we need to take things back to default so that other tests
# don't break

View File

@@ -1,8 +0,0 @@
// Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
// frappe.ui.form.on("Advance Payment Ledger Entry", {
// refresh(frm) {
// },
// });

View File

@@ -1,113 +0,0 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2024-10-16 16:57:12.085072",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"company",
"voucher_type",
"voucher_no",
"against_voucher_type",
"against_voucher_no",
"amount",
"currency",
"event"
],
"fields": [
{
"fieldname": "voucher_type",
"fieldtype": "Link",
"label": "Voucher Type",
"options": "DocType",
"read_only": 1
},
{
"fieldname": "voucher_no",
"fieldtype": "Dynamic Link",
"label": "Voucher No",
"options": "voucher_type",
"read_only": 1
},
{
"fieldname": "against_voucher_type",
"fieldtype": "Link",
"label": "Against Voucher Type",
"options": "DocType",
"read_only": 1
},
{
"fieldname": "against_voucher_no",
"fieldtype": "Dynamic Link",
"label": "Against Voucher No",
"options": "against_voucher_type",
"read_only": 1
},
{
"fieldname": "amount",
"fieldtype": "Currency",
"label": "Amount",
"read_only": 1
},
{
"fieldname": "currency",
"fieldtype": "Link",
"label": "Currency",
"options": "Currency",
"read_only": 1
},
{
"fieldname": "event",
"fieldtype": "Data",
"label": "Event",
"read_only": 1
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"read_only": 1
}
],
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-11-05 10:31:28.736671",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Payment Ledger Entry",
"owner": "Administrator",
"permissions": [
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts User",
"share": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Accounts Manager",
"share": 1
},
{
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "Auditor",
"share": 1
}
],
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}

View File

@@ -1,27 +0,0 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class AdvancePaymentLedgerEntry(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_voucher_no: DF.DynamicLink | None
against_voucher_type: DF.Link | None
amount: DF.Currency
company: DF.Link | None
currency: DF.Link | None
event: DF.Data | None
voucher_no: DF.DynamicLink | None
voucher_type: DF.Link | None
# end: auto-generated types
pass

View File

@@ -1,228 +0,0 @@
# Copyright (c) 2024, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.utils import nowdate, today
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
# On IntegrationTestCase, the doctype test records and all
# link-field test record depdendencies are recursively loaded
# Use these module variables to add/remove to/from that list
EXTRA_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
IGNORE_TEST_RECORD_DEPENDENCIES = [] # eg. ["User"]
class TestAdvancePaymentLedgerEntry(AccountsTestMixin, IntegrationTestCase):
"""
Integration tests for AdvancePaymentLedgerEntry.
Use this class for testing interactions between multiple components.
"""
def setUp(self):
self.create_company()
self.create_usd_receivable_account()
self.create_usd_payable_account()
self.create_item()
self.clear_old_entries()
def tearDown(self):
frappe.db.rollback()
def create_sales_order(self, qty=1, rate=100, currency="INR", do_not_submit=False):
"""
Helper method
"""
so = make_sales_order(
company=self.company,
customer=self.customer,
currency=currency,
item=self.item,
qty=qty,
rate=rate,
transaction_date=today(),
do_not_submit=do_not_submit,
)
return so
def create_purchase_order(self, qty=1, rate=100, currency="INR", do_not_submit=False):
"""
Helper method
"""
po = create_purchase_order(
company=self.company,
customer=self.supplier,
currency=currency,
item=self.item,
qty=qty,
rate=rate,
transaction_date=today(),
do_not_submit=do_not_submit,
)
return po
def test_so_advance_paid_and_currency_with_payment(self):
self.create_customer("_Test USD Customer", "USD")
so = self.create_sales_order(currency="USD", do_not_submit=True)
so.conversion_rate = 80
so.submit()
pe_exchange_rate = 85
pe = get_payment_entry(so.doctype, so.name, bank_account=self.cash)
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_from = self.debtors_usd
pe.paid_from_account_currency = "USD"
pe.source_exchange_rate = pe_exchange_rate
pe.paid_amount = so.grand_total
pe.received_amount = pe_exchange_rate * pe.paid_amount
pe.references[0].outstanding_amount = 100
pe.references[0].total_amount = 100
pe.references[0].allocated_amount = 100
pe.save().submit()
so.reload()
self.assertEqual(so.advance_paid, 100)
self.assertEqual(so.party_account_currency, "USD")
# cancel advance payment
pe.reload()
pe.cancel()
so.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.party_account_currency, "USD")
def test_so_advance_paid_and_currency_with_journal(self):
self.create_customer("_Test USD Customer", "USD")
so = self.create_sales_order(currency="USD", do_not_submit=True)
so.conversion_rate = 80
so.submit()
je_exchange_rate = 85
je = frappe.get_doc(
{
"doctype": "Journal Entry",
"company": self.company,
"voucher_type": "Journal Entry",
"posting_date": so.transaction_date,
"multi_currency": True,
"accounts": [
{
"account": self.debtors_usd,
"party_type": "Customer",
"party": so.customer,
"credit": 8500,
"credit_in_account_currency": 100,
"is_advance": "Yes",
"reference_type": so.doctype,
"reference_name": so.name,
"exchange_rate": je_exchange_rate,
},
{
"account": self.cash,
"debit": 8500,
"debit_in_account_currency": 8500,
},
],
}
)
je.save().submit()
so.reload()
self.assertEqual(so.advance_paid, 100)
self.assertEqual(so.party_account_currency, "USD")
# cancel advance payment
je.reload()
je.cancel()
so.reload()
self.assertEqual(so.advance_paid, 0)
self.assertEqual(so.party_account_currency, "USD")
def test_po_advance_paid_and_currency_with_payment(self):
self.create_supplier("_Test USD Supplier", "USD")
po = self.create_purchase_order(currency="USD", do_not_submit=True)
po.conversion_rate = 80
po.submit()
pe_exchange_rate = 85
pe = get_payment_entry(po.doctype, po.name, bank_account=self.cash)
pe.reference_no = "1"
pe.reference_date = nowdate()
pe.paid_to = self.creditors_usd
pe.paid_to_account_currency = "USD"
pe.target_exchange_rate = pe_exchange_rate
pe.received_amount = po.grand_total
pe.paid_amount = pe_exchange_rate * pe.received_amount
pe.references[0].outstanding_amount = 100
pe.references[0].total_amount = 100
pe.references[0].allocated_amount = 100
pe.save().submit()
po.reload()
self.assertEqual(po.advance_paid, 100)
self.assertEqual(po.party_account_currency, "USD")
# cancel advance payment
pe.reload()
pe.cancel()
po.reload()
self.assertEqual(po.advance_paid, 0)
self.assertEqual(po.party_account_currency, "USD")
def test_po_advance_paid_and_currency_with_journal(self):
self.create_supplier("_Test USD Supplier", "USD")
po = self.create_purchase_order(currency="USD", do_not_submit=True)
po.conversion_rate = 80
po.submit()
je_exchange_rate = 85
je = frappe.get_doc(
{
"doctype": "Journal Entry",
"company": self.company,
"voucher_type": "Journal Entry",
"posting_date": po.transaction_date,
"multi_currency": True,
"accounts": [
{
"account": self.creditors_usd,
"party_type": "Supplier",
"party": po.supplier,
"debit": 8500,
"debit_in_account_currency": 100,
"is_advance": "Yes",
"reference_type": po.doctype,
"reference_name": po.name,
"exchange_rate": je_exchange_rate,
},
{
"account": self.cash,
"credit": 8500,
"credit_in_account_currency": 8500,
},
],
}
)
je.save().submit()
po.reload()
self.assertEqual(po.advance_paid, 100)
self.assertEqual(po.party_account_currency, "USD")
# cancel advance payment
je.reload()
je.cancel()
po.reload()
self.assertEqual(po.advance_paid, 0)
self.assertEqual(po.party_account_currency, "USD")

View File

@@ -13,7 +13,6 @@
"col_break_1",
"description",
"included_in_paid_amount",
"set_by_item_tax_template",
"accounting_dimensions_section",
"cost_center",
"dimension_col_break",
@@ -21,13 +20,11 @@
"rate",
"section_break_9",
"currency",
"net_amount",
"tax_amount",
"total",
"allocated_amount",
"column_break_13",
"base_tax_amount",
"base_net_amount",
"base_total"
],
"fields": [
@@ -177,40 +174,12 @@
"label": "Account Currency",
"options": "Currency",
"read_only": 1
},
{
"columns": 2,
"fieldname": "net_amount",
"fieldtype": "Currency",
"in_list_view": 1,
"label": "Net Amount",
"options": "currency",
"read_only": 1
},
{
"fieldname": "base_net_amount",
"fieldtype": "Currency",
"label": "Net Amount (Company Currency)",
"oldfieldname": "tax_amount",
"oldfieldtype": "Currency",
"options": "Company:company:default_currency",
"read_only": 1
},
{
"default": "0",
"fieldname": "set_by_item_tax_template",
"fieldtype": "Check",
"hidden": 1,
"label": "Set by Item Tax Template",
"print_hide": 1,
"read_only": 1,
"report_hide": 1
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-11-22 19:16:22.346267",
"modified": "2024-03-27 13:05:58.437605",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Advance Taxes and Charges",

View File

@@ -18,7 +18,6 @@ class AdvanceTaxesandCharges(Document):
account_head: DF.Link
add_deduct_tax: DF.Literal["Add", "Deduct"]
allocated_amount: DF.Currency
base_net_amount: DF.Currency
base_tax_amount: DF.Currency
base_total: DF.Currency
charge_type: DF.Literal[
@@ -28,13 +27,11 @@ class AdvanceTaxesandCharges(Document):
currency: DF.Link | None
description: DF.SmallText
included_in_paid_amount: DF.Check
net_amount: DF.Currency
parent: DF.Data
parentfield: DF.Data
parenttype: DF.Data
rate: DF.Float
row_id: DF.Data | None
set_by_item_tax_template: DF.Check
tax_amount: DF.Currency
total: DF.Currency
# end: auto-generated types

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestBank(IntegrationTestCase):
class TestBank(unittest.TestCase):
pass

View File

@@ -208,49 +208,8 @@
"label": "Disabled"
}
],
"links": [
{
"group": "Transactions",
"link_doctype": "Payment Request",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Payment Order",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Bank Guarantee",
"link_fieldname": "bank_account"
},
{
"group": "Transactions",
"link_doctype": "Bank Transaction",
"link_fieldname": "bank_account"
},
{
"group": "Accounting",
"link_doctype": "Payment Entry",
"link_fieldname": "bank_account"
},
{
"group": "Accounting",
"link_doctype": "Journal Entry",
"link_fieldname": "bank_account"
},
{
"group": "Party",
"link_doctype": "Customer",
"link_fieldname": "default_bank_account"
},
{
"group": "Party",
"link_doctype": "Supplier",
"link_fieldname": "default_bank_account"
}
],
"modified": "2024-10-30 09:41:14.113414",
"links": [],
"modified": "2024-03-27 13:06:37.049542",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Bank Account",

View File

@@ -0,0 +1,20 @@
from frappe import _
def get_data():
return {
"fieldname": "bank_account",
"non_standard_fieldnames": {
"Customer": "default_bank_account",
"Supplier": "default_bank_account",
},
"transactions": [
{
"label": _("Payments"),
"items": ["Payment Entry", "Payment Request", "Payment Order", "Payroll Entry"],
},
{"label": _("Party"), "items": ["Customer", "Supplier"]},
{"items": ["Bank Guarantee"]},
{"items": ["Journal Entry"]},
],
}

View File

@@ -1,13 +1,15 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe import ValidationError
from frappe.tests import IntegrationTestCase
# test_records = frappe.get_test_records('Bank Account')
class TestBankAccount(IntegrationTestCase):
class TestBankAccount(unittest.TestCase):
def test_validate_iban(self):
valid_ibans = [
"GB82 WEST 1234 5698 7654 32",

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestBankAccountSubtype(IntegrationTestCase):
class TestBankAccountSubtype(unittest.TestCase):
pass

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestBankAccountType(IntegrationTestCase):
class TestBankAccountType(unittest.TestCase):
pass

View File

@@ -38,11 +38,6 @@ frappe.ui.form.on("Bank Clearance", {
frm.add_custom_button(__("Get Payment Entries"), () => frm.trigger("get_payment_entries"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () => frm.trigger("update_clearance_date"));
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
}
},
update_clearance_date: function (frm) {
@@ -50,7 +45,13 @@ frappe.ui.form.on("Bank Clearance", {
method: "update_clearance_date",
doc: frm.doc,
callback: function (r, rt) {
frm.refresh();
frm.refresh_field("payment_entries");
frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type(__("Get Payment Entries"), null, "primary");
frm.change_custom_button_type(__("Update Clearance Date"), null, "default");
}
},
});
},
@@ -59,8 +60,17 @@ frappe.ui.form.on("Bank Clearance", {
return frappe.call({
method: "get_payment_entries",
doc: frm.doc,
callback: function () {
frm.refresh();
callback: function (r, rt) {
frm.refresh_field("payment_entries");
if (frm.doc.payment_entries.length) {
frm.add_custom_button(__("Update Clearance Date"), () =>
frm.trigger("update_clearance_date")
);
frm.change_custom_button_type(__("Get Payment Entries"), null, "default");
frm.change_custom_button_type(__("Update Clearance Date"), null, "primary");
}
},
});
},

View File

@@ -6,7 +6,7 @@ import frappe
from frappe import _, msgprint
from frappe.model.document import Document
from frappe.query_builder.custom import ConstantColumn
from frappe.utils import flt, fmt_money, get_link_to_form, getdate
from frappe.utils import flt, fmt_money, getdate
from pypika import Order
import erpnext
@@ -96,11 +96,8 @@ class BankClearance(Document):
if d.cheque_date and getdate(d.clearance_date) < getdate(d.cheque_date):
frappe.throw(
_("Row #{0}: For {1} Clearance date {2} cannot be before Cheque Date {3}").format(
d.idx,
get_link_to_form(d.payment_document, d.payment_entry),
d.clearance_date,
d.cheque_date,
_("Row #{0}: Clearance date {1} cannot be before Cheque Date {2}").format(
d.idx, d.clearance_date, d.cheque_date
)
)
@@ -108,18 +105,8 @@ class BankClearance(Document):
if not d.clearance_date:
d.clearance_date = None
if d.payment_document == "Sales Invoice":
frappe.db.set_value(
"Sales Invoice Payment",
{"parent": d.payment_entry, "account": self.get("account"), "amount": [">", 0]},
"clearance_date",
d.clearance_date,
)
else:
frappe.db.set_value(
d.payment_document, d.payment_entry, "clearance_date", d.clearance_date
)
payment_entry = frappe.get_doc(d.payment_document, d.payment_entry)
payment_entry.db_set("clearance_date", d.clearance_date)
clearance_date_updated = True
@@ -168,7 +155,7 @@ def get_payment_entries_for_bank_clearance(
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%(account)s, paid_amount + total_taxes_and_charges, 0) as credit,
if(paid_from=%(account)s, 0, received_amount + total_taxes_and_charges) as debit,
if(paid_from=%(account)s, 0, received_amount) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`

View File

@@ -1,32 +1,21 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_months, getdate
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make_purchase_invoice
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.stock.doctype.item.test_item import create_item
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
from erpnext.tests.utils import if_lending_app_installed, if_lending_app_not_installed
class TestBankClearance(IntegrationTestCase):
class TestBankClearance(unittest.TestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
create_warehouse(
warehouse_name="_Test Warehouse",
properties={"parent_warehouse": "All Warehouses - _TC"},
company="_Test Company",
)
create_item("_Test Item")
create_cost_center(cost_center_name="_Test Cost Center", company="_Test Company")
clear_payment_entries()
clear_loan_transactions()
make_bank_account()
add_transactions()
@@ -94,31 +83,18 @@ class TestBankClearance(IntegrationTestCase):
bank_clearance.get_payment_entries()
self.assertEqual(len(bank_clearance.payment_entries), 3)
def test_update_clearance_date_on_si(self):
sales_invoice = make_pos_sales_invoice()
date = getdate()
bank_clearance = frappe.get_doc("Bank Clearance")
bank_clearance.account = "_Test Bank Clearance - _TC"
bank_clearance.from_date = add_months(date, -1)
bank_clearance.to_date = date
bank_clearance.include_pos_transactions = 1
bank_clearance.get_payment_entries()
def clear_payment_entries():
frappe.db.delete("Payment Entry")
self.assertNotEqual(len(bank_clearance.payment_entries), 0)
for payment in bank_clearance.payment_entries:
if payment.payment_entry == sales_invoice.name:
payment.clearance_date = date
bank_clearance.update_clearance_date()
si_clearance_date = frappe.db.get_value(
"Sales Invoice Payment",
{"parent": sales_invoice.name, "account": bank_clearance.account},
"clearance_date",
)
self.assertEqual(si_clearance_date, date)
@if_lending_app_installed
def clear_loan_transactions():
for dt in [
"Loan Disbursement",
"Loan Repayment",
]:
frappe.db.delete(dt)
def make_bank_account():
@@ -139,45 +115,9 @@ def add_transactions():
def make_payment_entry():
from erpnext.buying.doctype.supplier.test_supplier import create_supplier
supplier = create_supplier(supplier_name="_Test Supplier")
pi = make_purchase_invoice(
supplier=supplier,
supplier_warehouse="_Test Warehouse - _TC",
expense_account="Cost of Goods Sold - _TC",
uom="Nos",
qty=1,
rate=690,
)
pi = make_purchase_invoice(supplier="_Test Supplier", qty=1, rate=690)
pe = get_payment_entry("Purchase Invoice", pi.name, bank_account="_Test Bank Clearance - _TC")
pe.reference_no = "Conrad Oct 18"
pe.reference_date = "2018-10-24"
pe.insert()
pe.submit()
def make_pos_sales_invoice():
from erpnext.accounts.doctype.opening_invoice_creation_tool.test_opening_invoice_creation_tool import (
make_customer,
)
mode_of_payment = frappe.get_doc({"doctype": "Mode of Payment", "name": "Cash"})
if not frappe.db.get_value("Mode of Payment Account", {"company": "_Test Company", "parent": "Cash"}):
mode_of_payment.append(
"accounts", {"company": "_Test Company", "default_account": "_Test Bank Clearance - _TC"}
)
mode_of_payment.save()
customer = make_customer(customer="_Test Customer")
si = create_sales_invoice(customer=customer, item="_Test Item", is_pos=1, qty=1, rate=1000, do_not_save=1)
si.set("payments", [])
si.append(
"payments", {"mode_of_payment": "Cash", "account": "_Test Bank Clearance - _TC", "amount": 1000}
)
si.insert()
si.submit()
return si

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestBankGuarantee(IntegrationTestCase):
class TestBankGuarantee(unittest.TestCase):
pass

View File

@@ -4,7 +4,7 @@
import frappe
from frappe import qb
from frappe.tests import IntegrationTestCase
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, today
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
@@ -15,7 +15,7 @@ from erpnext.accounts.doctype.payment_entry.test_payment_entry import create_pay
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestBankReconciliationTool(AccountsTestMixin, IntegrationTestCase):
class TestBankReconciliationTool(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2020, Frappe Technologies and Contributors
# See license.txt
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestBankStatementImport(IntegrationTestCase):
class TestBankStatementImport(unittest.TestCase):
pass

View File

@@ -2,22 +2,13 @@
# License: GNU General Public License v3. See license.txt
import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate
from erpnext.accounts.doctype.bank_transaction.test_bank_transaction import create_bank_account
class UnitTestBankTransaction(UnitTestCase):
"""
Unit tests for BankTransaction.
Use this class for testing individual functions and methods.
"""
pass
class TestAutoMatchParty(IntegrationTestCase):
class TestAutoMatchParty(FrappeTestCase):
@classmethod
def setUpClass(cls):
create_bank_account()

View File

@@ -6,7 +6,7 @@ import json
import frappe
from frappe import utils
from frappe.model.docstatus import DocStatus
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
from erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool import (
get_linked_payments,
@@ -18,20 +18,19 @@ from erpnext.accounts.doctype.purchase_invoice.test_purchase_invoice import make
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
from erpnext.tests.utils import if_lending_app_installed
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item", "Cost Center"]
test_dependencies = ["Item", "Cost Center"]
class UnitTestBankTransaction(UnitTestCase):
"""
Unit tests for BankTransaction.
Use this class for testing individual functions and methods.
"""
pass
class TestBankTransaction(IntegrationTestCase):
class TestBankTransaction(FrappeTestCase):
def setUp(self):
for dt in [
"Bank Transaction",
"Payment Entry",
"Payment Entry Reference",
"POS Profile",
]:
frappe.db.delete(dt)
clear_loan_transactions()
make_pos_profile()
# generate and use a uniq hash identifier for 'Bank Account' and it's linked GL 'Account' to avoid validation error
@@ -223,6 +222,11 @@ class TestBankTransaction(IntegrationTestCase):
self.assertEqual(linked_payments[0]["name"], repayment_entry.name)
@if_lending_app_installed
def clear_loan_transactions():
frappe.db.delete("Loan Repayment")
def create_bank_account(
bank_name="Citi Bank", gl_account="_Test Bank - _TC", bank_account_name="Checking Account"
):

View File

@@ -2,17 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
class UnitTestBisectAccountingStatements(UnitTestCase):
"""
Unit tests for BisectAccountingStatements.
Use this class for testing individual functions and methods.
"""
pass
class TestBisectAccountingStatements(IntegrationTestCase):
class TestBisectAccountingStatements(FrappeTestCase):
pass

View File

@@ -2,17 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
class UnitTestBisectNodes(UnitTestCase):
"""
Unit tests for BisectNodes.
Use this class for testing individual functions and methods.
"""
pass
class TestBisectNodes(IntegrationTestCase):
class TestBisectNodes(FrappeTestCase):
pass

View File

@@ -1,9 +1,9 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import now_datetime, nowdate
from erpnext.accounts.doctype.budget.budget import BudgetError, get_actual_expense
@@ -11,10 +11,10 @@ from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journ
from erpnext.accounts.utils import get_fiscal_year
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
EXTRA_TEST_RECORD_DEPENDENCIES = ["Monthly Distribution"]
test_dependencies = ["Monthly Distribution"]
class TestBudget(IntegrationTestCase):
class TestBudget(unittest.TestCase):
def test_monthly_budget_crossed_ignore(self):
set_total_expense_zero(nowdate(), "cost_center")

View File

@@ -13,13 +13,13 @@
"fieldtype": "Link",
"in_list_view": 1,
"label": "Campaign",
"options": "UTM Campaign"
"options": "Campaign"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2024-06-28 11:04:09.815940",
"modified": "2024-03-27 13:06:44.142625",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Campaign Item",
@@ -29,4 +29,4 @@
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestCashierClosing(IntegrationTestCase):
class TestCashierClosing(unittest.TestCase):
pass

View File

@@ -47,11 +47,9 @@ def validate_columns(data):
no_of_columns = max([len(d) for d in data])
if no_of_columns != 8:
if no_of_columns > 8:
frappe.throw(
_(
"Columns are not according to template. Please compare the uploaded file with standard template"
),
_("More columns found than expected. Please compare the uploaded file with standard template"),
title=(_("Wrong Template")),
)

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestChartofAccountsImporter(IntegrationTestCase):
class TestChartofAccountsImporter(unittest.TestCase):
pass

View File

@@ -1,9 +1,10 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
# test_records = frappe.get_test_records('Cheque Print Template')
class TestChequePrintTemplate(IntegrationTestCase):
class TestChequePrintTemplate(unittest.TestCase):
pass

View File

@@ -1,13 +1,18 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
test_records = frappe.get_test_records("Cost Center")
class TestCostCenter(IntegrationTestCase):
class TestCostCenter(unittest.TestCase):
def test_cost_center_creation_against_child_node(self):
if not frappe.db.get_value("Cost Center", {"name": "_Test Cost Center 2 - _TC"}):
frappe.get_doc(test_records[1]).insert()
cost_center = frappe.get_doc(
{
"doctype": "Cost Center",

View File

@@ -0,0 +1,23 @@
[
{
"company": "_Test Company",
"cost_center_name": "_Test Cost Center",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
},
{
"company": "_Test Company",
"cost_center_name": "_Test Cost Center 2",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
},
{
"company": "_Test Company",
"cost_center_name": "_Test Write Off Cost Center",
"doctype": "Cost Center",
"is_group": 0,
"parent_cost_center": "_Test Company - _TC"
}
]

View File

@@ -1,18 +0,0 @@
[["Cost Center"]]
company = "_Test Company"
cost_center_name = "_Test Cost Center"
is_group = 0
parent_cost_center = "_Test Company - _TC"
[["Cost Center"]]
company = "_Test Company"
cost_center_name = "_Test Cost Center 2"
is_group = 0
parent_cost_center = "_Test Company - _TC"
[["Cost Center"]]
company = "_Test Company"
cost_center_name = "_Test Write Off Cost Center"
is_group = 0
parent_cost_center = "_Test Company - _TC"

View File

@@ -1,9 +1,9 @@
# Copyright (c) 2022, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, today
from erpnext.accounts.doctype.cost_center.test_cost_center import create_cost_center
@@ -17,15 +17,13 @@ from erpnext.accounts.doctype.cost_center_allocation.cost_center_allocation impo
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
class TestCostCenterAllocation(IntegrationTestCase):
class TestCostCenterAllocation(unittest.TestCase):
def setUp(self):
cost_centers = [
"Main Cost Center 1",
"Main Cost Center 2",
"Main Cost Center 3",
"Sub Cost Center 1",
"Sub Cost Center 2",
"Sub Cost Center 3",
]
for cc in cost_centers:
create_cost_center(cost_center_name=cc, company="_Test Company")
@@ -38,7 +36,7 @@ class TestCostCenterAllocation(IntegrationTestCase):
)
jv = make_journal_entry(
"Cash - _TC", "Sales - _TC", 100, cost_center="Main Cost Center 1 - _TC", submit=True
"_Test Cash - _TC", "Sales - _TC", 100, cost_center="Main Cost Center 1 - _TC", submit=True
)
expected_values = [["Sub Cost Center 1 - _TC", 0.0, 60], ["Sub Cost Center 2 - _TC", 0.0, 40]]
@@ -122,7 +120,7 @@ class TestCostCenterAllocation(IntegrationTestCase):
def test_valid_from_based_on_existing_gle(self):
# GLE posted against Sub Cost Center 1 on today
jv = make_journal_entry(
"Cash - _TC",
"_Test Cash - _TC",
"Sales - _TC",
100,
cost_center="Main Cost Center 1 - _TC",
@@ -143,53 +141,6 @@ class TestCostCenterAllocation(IntegrationTestCase):
jv.cancel()
def test_multiple_cost_center_allocation_on_same_main_cost_center(self):
coa1 = create_cost_center_allocation(
"_Test Company",
"Main Cost Center 3 - _TC",
{"Sub Cost Center 1 - _TC": 30, "Sub Cost Center 2 - _TC": 30, "Sub Cost Center 3 - _TC": 40},
valid_from=add_days(today(), -5),
)
coa2 = create_cost_center_allocation(
"_Test Company",
"Main Cost Center 3 - _TC",
{"Sub Cost Center 1 - _TC": 50, "Sub Cost Center 2 - _TC": 50},
valid_from=add_days(today(), -1),
)
jv = make_journal_entry(
"Cash - _TC",
"Sales - _TC",
100,
cost_center="Main Cost Center 3 - _TC",
posting_date=today(),
submit=True,
)
expected_values = {"Sub Cost Center 1 - _TC": 50, "Sub Cost Center 2 - _TC": 50}
gle = frappe.qb.DocType("GL Entry")
gl_entries = (
frappe.qb.from_(gle)
.select(gle.cost_center, gle.debit, gle.credit)
.where(gle.voucher_type == "Journal Entry")
.where(gle.voucher_no == jv.name)
.where(gle.account == "Sales - _TC")
.orderby(gle.cost_center)
).run(as_dict=1)
self.assertTrue(gl_entries)
for gle in gl_entries:
self.assertTrue(gle.cost_center in expected_values)
self.assertEqual(gle.debit, 0)
self.assertEqual(gle.credit, expected_values[gle.cost_center])
coa1.cancel()
coa2.cancel()
jv.cancel()
def create_cost_center_allocation(
company,

View File

@@ -13,7 +13,6 @@
"customer",
"column_break_4",
"coupon_code",
"from_external_ecomm_platform",
"pricing_rule",
"uses",
"valid_from",
@@ -62,12 +61,11 @@
"unique": 1
},
{
"depends_on": "eval: !doc.from_external_ecomm_platform",
"fieldname": "pricing_rule",
"fieldtype": "Link",
"label": "Pricing Rule",
"mandatory_depends_on": "eval: !doc.from_external_ecomm_platform",
"options": "Pricing Rule"
"options": "Pricing Rule",
"reqd": 1
},
{
"fieldname": "uses",
@@ -116,20 +114,13 @@
"options": "Coupon Code",
"print_hide": 1,
"read_only": 1
},
{
"default": "0",
"fieldname": "from_external_ecomm_platform",
"fieldtype": "Check",
"label": "From External Ecomm Platform"
}
],
"links": [],
"modified": "2024-11-19 16:35:11.836441",
"modified": "2024-03-27 13:06:47.220931",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Coupon Code",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{

View File

@@ -23,9 +23,8 @@ class CouponCode(Document):
coupon_type: DF.Literal["Promotional", "Gift Card"]
customer: DF.Link | None
description: DF.TextEditor | None
from_external_ecomm_platform: DF.Check
maximum_use: DF.Int
pricing_rule: DF.Link | None
pricing_rule: DF.Link
used: DF.Int
valid_from: DF.Date | None
valid_upto: DF.Date | None

View File

@@ -1,13 +1,13 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
EXTRA_TEST_RECORD_DEPENDENCIES = ["Item"]
test_dependencies = ["Item"]
def test_create_test_data():
@@ -110,7 +110,7 @@ def test_create_test_data():
coupon_code.insert()
class TestCouponCode(IntegrationTestCase):
class TestCouponCode(unittest.TestCase):
def setUp(self):
test_create_test_data()
@@ -142,39 +142,3 @@ class TestCouponCode(IntegrationTestCase):
so.submit()
self.assertEqual(frappe.db.get_value("Coupon Code", "SAVE30", "used"), 1)
def test_coupon_without_max_use(self):
from erpnext.accounts.doctype.pricing_rule.utils import (
update_coupon_code_count,
validate_coupon_code,
)
coupon = frappe.get_doc(
{
"doctype": "Coupon Code",
"coupon_name": "_Test Coupon Without Max Use",
"coupon_code": "TESTUNLIMITED",
"from_external_ecomm_platform": 1, # avoids requirement for pricing rule
"valid_from": frappe.utils.nowdate(),
"maximum_use": 0,
"used": 0,
}
)
coupon.insert(ignore_permissions=True)
# Validate initial state
self.assertEqual(coupon.used, 0)
self.assertEqual(coupon.maximum_use, 0)
# Use coupon multiple times
for _ in range(5):
validate_coupon_code(coupon.name)
update_coupon_code_count(coupon.name, "used")
coupon.reload()
# Check that the coupon is still valid and usage count increased
self.assertEqual(coupon.used, 5)
validate_coupon_code(coupon.name) # This should not raise an error
# Clean up
coupon.delete()

View File

@@ -109,7 +109,7 @@ def get_api_endpoint(service_provider: str | None = None, use_http: bool = False
if service_provider == "exchangerate.host":
api = "api.exchangerate.host/convert"
elif service_provider == "frankfurter.app":
api = "api.frankfurter.app/{transaction_date}"
api = "frankfurter.app/{transaction_date}"
protocol = "https://"
if use_http:

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestCurrencyExchangeSettings(IntegrationTestCase):
class TestCurrencyExchangeSettings(unittest.TestCase):
pass

View File

@@ -19,6 +19,16 @@
"currency",
"column_break_11",
"conversion_rate",
"address_and_contact_section",
"customer_address",
"address_display",
"contact_person",
"contact_display",
"column_break_16",
"company_address",
"company_address_display",
"contact_mobile",
"contact_email",
"section_break_6",
"dunning_type",
"column_break_8",
@@ -46,21 +56,7 @@
"income_account",
"column_break_48",
"cost_center",
"amended_from",
"address_and_contact_tab",
"address_and_contact_section",
"customer_address",
"address_display",
"column_break_vodj",
"contact_person",
"contact_display",
"contact_mobile",
"contact_email",
"section_break_xban",
"column_break_16",
"company_address",
"company_address_display",
"column_break_lqmf"
"amended_from"
],
"fields": [
{
@@ -182,8 +178,10 @@
"label": "Rate of Interest (%) Yearly"
},
{
"collapsible": 1,
"fieldname": "address_and_contact_section",
"fieldtype": "Section Break"
"fieldtype": "Section Break",
"label": "Address and Contact"
},
{
"fieldname": "address_display",
@@ -379,28 +377,11 @@
{
"fieldname": "column_break_48",
"fieldtype": "Column Break"
},
{
"fieldname": "address_and_contact_tab",
"fieldtype": "Tab Break",
"label": "Address & Contact"
},
{
"fieldname": "column_break_vodj",
"fieldtype": "Column Break"
},
{
"fieldname": "section_break_xban",
"fieldtype": "Section Break"
},
{
"fieldname": "column_break_lqmf",
"fieldtype": "Column Break"
}
],
"is_submittable": 1,
"links": [],
"modified": "2024-11-26 13:46:07.760867",
"modified": "2024-03-27 13:08:19.176146",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Dunning",

View File

@@ -220,31 +220,19 @@ def get_linked_dunnings_as_per_state(sales_invoice, state):
@frappe.whitelist()
def get_dunning_letter_text(dunning_type: str, doc: str | dict, language: str | None = None) -> dict:
DOCTYPE = "Dunning Letter Text"
FIELDS = ["body_text", "closing_text", "language"]
def get_dunning_letter_text(dunning_type, doc, language=None):
if isinstance(doc, str):
doc = json.loads(doc)
if not language:
language = doc.get("language")
if language:
letter_text = frappe.db.get_value(
DOCTYPE, {"parent": dunning_type, "language": language}, FIELDS, as_dict=1
)
if not letter_text:
letter_text = frappe.db.get_value(
DOCTYPE, {"parent": dunning_type, "is_default_language": 1}, FIELDS, as_dict=1
)
if not letter_text:
return {}
return {
"body_text": frappe.render_template(letter_text.body_text, doc),
"closing_text": frappe.render_template(letter_text.closing_text, doc),
"language": letter_text.language,
}
filters = {"parent": dunning_type, "language": language}
else:
filters = {"parent": dunning_type, "is_default_language": 1}
letter_text = frappe.db.get_value(
"Dunning Letter Text", filters, ["body_text", "closing_text", "language"], as_dict=1
)
if letter_text:
return {
"body_text": frappe.render_template(letter_text.body_text, doc),
"closing_text": frappe.render_template(letter_text.closing_text, doc),
"language": letter_text.language,
}

View File

@@ -1,7 +1,7 @@
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
from frappe.utils import add_days, nowdate, today
from erpnext import get_default_cost_center
@@ -16,19 +16,10 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import (
create_sales_invoice_against_cost_center,
)
EXTRA_TEST_RECORD_DEPENDENCIES = ["Company", "Cost Center"]
test_dependencies = ["Company", "Cost Center"]
class UnitTestDunning(UnitTestCase):
"""
Unit tests for Dunning.
Use this class for testing individual functions and methods.
"""
pass
class TestDunning(IntegrationTestCase):
class TestDunning(FrappeTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestDunningType(IntegrationTestCase):
class TestDunningType(unittest.TestCase):
pass

View File

@@ -0,0 +1,36 @@
[
{
"doctype": "Dunning Type",
"dunning_type": "_Test First Notice",
"company": "_Test Company",
"is_default": 1,
"dunning_fee": 0.0,
"rate_of_interest": 0.0,
"dunning_letter_text": [
{
"language": "en",
"body_text": "We have still not received payment for our invoice",
"closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
}
],
"income_account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC"
},
{
"doctype": "Dunning Type",
"dunning_type": "_Test Second Notice",
"company": "_Test Company",
"is_default": 0,
"dunning_fee": 10.0,
"rate_of_interest": 10.0,
"dunning_letter_text": [
{
"language": "en",
"body_text": "We have still not received payment for our invoice",
"closing_text": "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
}
],
"income_account": "Sales - _TC",
"cost_center": "_Test Cost Center - _TC"
}
]

View File

@@ -1,28 +0,0 @@
[["Dunning Type"]]
dunning_type = "_Test First Notice"
company = "_Test Company"
is_default = 1
dunning_fee = 0.0
rate_of_interest = 0.0
income_account = "Sales - _TC"
cost_center = "_Test Cost Center - _TC"
[["Dunning Type".dunning_letter_text]]
language = "en"
body_text = "We have still not received payment for our invoice"
closing_text = "We kindly request that you pay the outstanding amount immediately, including interest and late fees."
[["Dunning Type"]]
dunning_type = "_Test Second Notice"
company = "_Test Company"
is_default = 0
dunning_fee = 10.0
rate_of_interest = 10.0
income_account = "Sales - _TC"
cost_center = "_Test Cost Center - _TC"
[["Dunning Type".dunning_letter_text]]
language = "en"
body_text = "We have still not received payment for our invoice"
closing_text = "We kindly request that you pay the outstanding amount immediately, including interest and late fees."

View File

@@ -85,16 +85,18 @@ frappe.ui.form.on("Exchange Rate Revaluation", {
},
make_jv: function (frm) {
let revaluation_journal = null;
let zero_balance_journal = null;
frappe.call({
method: "make_jv_entries",
doc: frm.doc,
freeze: true,
freeze_message: __("Creating Journal Entries..."),
freeze_message: "Making Journal Entries...",
callback: function (r) {
if (r.message) {
let response = r.message;
if (response["revaluation_jv"] || response["zero_balance_jv"]) {
frappe.msgprint(__("Journal entries have been created"));
frappe.msgprint(__("Journals have been created"));
}
}
},

View File

@@ -74,21 +74,6 @@ class ExchangeRateRevaluation(Document):
if not (self.company and self.posting_date):
frappe.throw(_("Please select Company and Posting Date to getting entries"))
def before_submit(self):
self.remove_accounts_without_gain_loss()
def remove_accounts_without_gain_loss(self):
self.accounts = [account for account in self.accounts if account.gain_loss]
if not self.accounts:
frappe.throw(_("At least one account with exchange gain or loss is required"))
frappe.msgprint(
_("Removing rows without exchange gain or loss"),
alert=True,
indicator="yellow",
)
def on_cancel(self):
self.ignore_linked_doctypes = "GL Entry"
@@ -263,23 +248,23 @@ class ExchangeRateRevaluation(Document):
new_exchange_rate = get_exchange_rate(d.account_currency, company_currency, posting_date)
new_balance_in_base_currency = flt(d.balance_in_account_currency * new_exchange_rate)
gain_loss = flt(new_balance_in_base_currency, precision) - flt(d.balance, precision)
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": d.balance_in_account_currency,
"gain_loss": gain_loss,
}
)
if gain_loss:
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": d.balance_in_account_currency,
"gain_loss": gain_loss,
}
)
# Handle Accounts with '0' balance in Account/Base Currency
for d in [x for x in account_details if x.zero_balance]:
@@ -303,22 +288,23 @@ class ExchangeRateRevaluation(Document):
current_exchange_rate * d.balance_in_account_currency
)
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": new_balance_in_account_currency,
"gain_loss": gain_loss,
}
)
if gain_loss:
accounts.append(
{
"account": d.account,
"party_type": d.party_type,
"party": d.party,
"account_currency": d.account_currency,
"balance_in_base_currency": d.balance,
"balance_in_account_currency": d.balance_in_account_currency,
"zero_balance": d.zero_balance,
"current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency,
"new_balance_in_account_currency": new_balance_in_account_currency,
"gain_loss": gain_loss,
}
)
return accounts

View File

@@ -3,7 +3,7 @@
import frappe
from frappe.tests import IntegrationTestCase
from frappe.tests.utils import FrappeTestCase, change_settings
from frappe.utils import add_days, flt, today
from erpnext.accounts.doctype.payment_entry.payment_entry import get_payment_entry
@@ -11,7 +11,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
class TestExchangeRateRevaluation(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_usd_receivable_account()
@@ -35,7 +35,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
company_doc.unrealized_exchange_gain_loss_account = company_doc.exchange_gain_loss_account
company_doc.save()
@IntegrationTestCase.change_settings(
@change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -88,7 +88,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
)[0]
self.assertEqual(acc_balance.balance, 8500.0)
@IntegrationTestCase.change_settings(
@change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -158,7 +158,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(acc_balance.balance, 0.0)
self.assertEqual(acc_balance.balance_in_account_currency, 0.0)
@IntegrationTestCase.change_settings(
@change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)
@@ -247,7 +247,7 @@ class TestExchangeRateRevaluation(AccountsTestMixin, IntegrationTestCase):
self.assertEqual(flt(acc_balance.balance, precision), 0.0)
self.assertEqual(flt(acc_balance.balance_in_account_currency, precision), 0.0)
@IntegrationTestCase.change_settings(
@change_settings(
"Accounts Settings",
{"allow_multi_currency_invoices_against_single_party_account": 1, "allow_stale": 0},
)

View File

@@ -1,14 +1,14 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
class TestFinanceBook(IntegrationTestCase):
class TestFinanceBook(unittest.TestCase):
def test_finance_book(self):
finance_book = create_finance_book()

View File

@@ -4,7 +4,10 @@
frappe.ui.form.on("Fiscal Year", {
onload: function (frm) {
if (frm.doc.__islocal) {
frm.set_value("year_start_date", frappe.datetime.year_start());
frm.set_value(
"year_start_date",
frappe.datetime.add_days(frappe.defaults.get_default("year_end_date"), 1)
);
}
},
year_start_date: function (frm) {

View File

@@ -72,10 +72,10 @@
},
{
"default": "0",
"description": "More/Less than 12 months.",
"description": "Less than 12 months.",
"fieldname": "is_short_year",
"fieldtype": "Check",
"label": "Is Short/Long Year",
"label": "Is Short Year",
"set_only_once": 1
}
],

View File

@@ -1,15 +1,16 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import now_datetime
IGNORE_TEST_RECORD_DEPENDENCIES = ["Company"]
test_ignore = ["Company"]
class TestFiscalYear(IntegrationTestCase):
class TestFiscalYear(unittest.TestCase):
def test_extra_year(self):
if frappe.db.exists("Fiscal Year", "_Test Fiscal Year 2000"):
frappe.delete_doc("Fiscal Year", "_Test Fiscal Year 2000")
@@ -38,21 +39,8 @@ def test_record_generator():
]
start = 2012
this_year = now_datetime().year
end = now_datetime().year + 25
# The current year fails to load with the following error:
# Year start date or end date is overlapping with 2024. To avoid please set company
# This is a quick-fix: if current FY is needed, please refactor test data properly
for year in range(start, this_year):
test_records.append(
{
"doctype": "Fiscal Year",
"year": f"_Test Fiscal Year {year}",
"year_start_date": f"{year}-01-01",
"year_end_date": f"{year}-12-31",
}
)
for year in range(this_year + 1, end):
for year in range(start, end):
test_records.append(
{
"doctype": "Fiscal Year",

View File

@@ -6,50 +6,38 @@
"document_type": "Document",
"engine": "InnoDB",
"field_order": [
"dates_section",
"posting_date",
"transaction_date",
"column_break_avko",
"fiscal_year",
"due_date",
"account_details_section",
"account",
"account_currency",
"column_break_ifvf",
"against",
"party_type",
"party",
"transaction_details_section",
"voucher_type",
"voucher_no",
"voucher_subtype",
"transaction_currency",
"column_break_dpsx",
"cost_center",
"debit",
"credit",
"account_currency",
"debit_in_account_currency",
"credit_in_account_currency",
"against",
"against_voucher_type",
"against_voucher",
"voucher_type",
"voucher_subtype",
"voucher_no",
"voucher_detail_no",
"transaction_exchange_rate",
"amounts_section",
"debit_in_account_currency",
"debit",
"debit_in_transaction_currency",
"column_break_bm1w",
"credit_in_account_currency",
"credit",
"credit_in_transaction_currency",
"dimensions_section",
"cost_center",
"column_break_lmnm",
"project",
"more_info_section",
"finance_book",
"company",
"remarks",
"is_opening",
"is_advance",
"column_break_8abq",
"fiscal_year",
"company",
"finance_book",
"to_rename",
"due_date",
"is_cancelled",
"remarks"
"transaction_currency",
"debit_in_transaction_currency",
"credit_in_transaction_currency",
"transaction_exchange_rate"
],
"fields": [
{
@@ -297,67 +285,13 @@
"fieldname": "voucher_subtype",
"fieldtype": "Small Text",
"label": "Voucher Subtype"
},
{
"fieldname": "dates_section",
"fieldtype": "Section Break",
"label": "Dates"
},
{
"fieldname": "column_break_avko",
"fieldtype": "Column Break"
},
{
"fieldname": "account_details_section",
"fieldtype": "Section Break",
"label": "Account Details"
},
{
"fieldname": "column_break_ifvf",
"fieldtype": "Column Break"
},
{
"fieldname": "transaction_details_section",
"fieldtype": "Section Break",
"label": "Transaction Details"
},
{
"fieldname": "amounts_section",
"fieldtype": "Section Break",
"label": "Amounts"
},
{
"fieldname": "column_break_dpsx",
"fieldtype": "Column Break"
},
{
"fieldname": "more_info_section",
"fieldtype": "Section Break",
"label": "More Info"
},
{
"fieldname": "column_break_bm1w",
"fieldtype": "Column Break"
},
{
"fieldname": "dimensions_section",
"fieldtype": "Section Break",
"label": "Dimensions"
},
{
"fieldname": "column_break_lmnm",
"fieldtype": "Column Break"
},
{
"fieldname": "column_break_8abq",
"fieldtype": "Column Break"
}
],
"icon": "fa fa-list",
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2024-08-22 13:03:39.997475",
"modified": "2024-03-27 13:09:45.205364",
"modified_by": "Administrator",
"module": "Accounts",
"name": "GL Entry",

View File

@@ -430,9 +430,8 @@ def update_against_account(voucher_type, voucher_no):
def on_doctype_update():
frappe.db.add_index("GL Entry", ["against_voucher_type", "against_voucher"])
frappe.db.add_index("GL Entry", ["voucher_type", "voucher_no"])
frappe.db.add_index("GL Entry", ["posting_date", "company"])
frappe.db.add_index("GL Entry", ["party_type", "party"])
def rename_gle_sle_docs():

View File

@@ -1,16 +1,17 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.model.naming import parse_naming_series
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.gl_entry.gl_entry import rename_gle_sle_docs
from erpnext.accounts.doctype.journal_entry.test_journal_entry import make_journal_entry
class TestGLEntry(IntegrationTestCase):
class TestGLEntry(unittest.TestCase):
def test_round_off_entry(self):
frappe.db.set_value("Company", "_Test Company", "round_off_account", "_Test Write Off - _TC")
frappe.db.set_value("Company", "_Test Company", "round_off_cost_center", "_Test Cost Center - _TC")

View File

@@ -1,9 +1,9 @@
# Copyright (c) 2019, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import add_days, flt, nowdate
from erpnext.accounts.doctype.account.test_account import create_account
@@ -12,7 +12,7 @@ from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sal
from erpnext.stock.doctype.purchase_receipt.test_purchase_receipt import get_gl_entries
class TestInvoiceDiscounting(IntegrationTestCase):
class TestInvoiceDiscounting(unittest.TestCase):
def setUp(self):
self.ar_credit = create_account(
account_name="_Test Accounts Receivable Credit",

View File

@@ -1,9 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
from frappe.tests import IntegrationTestCase
class TestItemTaxTemplate(IntegrationTestCase):
class TestItemTaxTemplate(unittest.TestCase):
pass

View File

@@ -0,0 +1,79 @@
[
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 10",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 12",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 12,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 15",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Account Excise Duty @ 20",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 20,
"tax_type": "_Test Account Excise Duty - _TC"
}
]
},
{
"doctype": "Item Tax Template",
"title": "_Test Item Tax Template 1",
"company": "_Test Company",
"taxes": [
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 5,
"tax_type": "_Test Account Excise Duty - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 10,
"tax_type": "_Test Account Education Cess - _TC"
},
{
"doctype": "Item Tax Template Detail",
"parentfield": "taxes",
"tax_rate": 15,
"tax_type": "_Test Account S&H Education Cess - _TC"
}
]
}
]

View File

@@ -1,62 +0,0 @@
[["Item Tax Template"]]
title = "_Test Account Excise Duty @ 10"
company = "_Test Company"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 10
tax_type = "_Test Account Excise Duty - _TC"
[["Item Tax Template"]]
title = "_Test Account Excise Duty @ 12"
company = "_Test Company"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 12
tax_type = "_Test Account Excise Duty - _TC"
[["Item Tax Template"]]
title = "_Test Account Excise Duty @ 15"
company = "_Test Company"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 15
tax_type = "_Test Account Excise Duty - _TC"
[["Item Tax Template"]]
title = "_Test Account Excise Duty @ 20"
company = "_Test Company"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 20
tax_type = "_Test Account Excise Duty - _TC"
[["Item Tax Template"]]
title = "_Test Item Tax Template 1"
company = "_Test Company"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 5
tax_type = "_Test Account Excise Duty - _TC"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 10
tax_type = "_Test Account Education Cess - _TC"
[["Item Tax Template".taxes]]
doctype = "Item Tax Template Detail"
parentfield = "taxes"
tax_rate = 15
tax_type = "_Test Account S&H Education Cess - _TC"

View File

@@ -360,23 +360,21 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
accounts_add(doc, cdt, cdn) {
var row = frappe.get_doc(cdt, cdn);
row.exchange_rate = 1;
$.each(doc.accounts, function (i, d) {
if (d.account && d.party && d.party_type) {
row.account = d.account;
row.party = d.party;
row.party_type = d.party_type;
row.exchange_rate = d.exchange_rate;
}
});
// set difference
if (doc.difference) {
if (doc.difference > 0) {
row.credit_in_account_currency = doc.difference / row.exchange_rate;
row.credit_in_account_currency = doc.difference;
row.credit = doc.difference;
} else {
row.debit_in_account_currency = -doc.difference / row.exchange_rate;
row.debit_in_account_currency = -doc.difference;
row.debit = -doc.difference;
}
}
@@ -682,7 +680,6 @@ $.extend(erpnext.journal_entry, {
callback: function (r) {
if (r.message) {
$.extend(d, r.message);
erpnext.journal_entry.set_amount_on_last_row(frm, dt, dn);
erpnext.journal_entry.set_debit_credit_in_company_currency(frm, dt, dn);
refresh_field("accounts");
}
@@ -690,26 +687,4 @@ $.extend(erpnext.journal_entry, {
});
}
},
set_amount_on_last_row: function (frm, dt, dn) {
let row = locals[dt][dn];
let length = frm.doc.accounts.length;
if (row.idx != length) return;
let difference = frm.doc.accounts.reduce((total, row) => {
if (row.idx == length) return total;
return total + row.debit - row.credit;
}, 0);
if (difference) {
if (difference > 0) {
row.credit_in_account_currency = difference / row.exchange_rate;
row.credit = difference;
} else {
row.debit_in_account_currency = -difference / row.exchange_rate;
row.debit = -difference;
}
}
refresh_field("accounts");
},
});

View File

@@ -188,7 +188,6 @@ class JournalEntry(AccountsController):
self.validate_cheque_info()
self.check_credit_limit()
self.make_gl_entries()
self.make_advance_payment_ledger_entries()
self.update_advance_paid()
self.update_asset_value()
self.update_inter_company_jv()
@@ -196,11 +195,6 @@ class JournalEntry(AccountsController):
self.update_booked_depreciation()
def on_update_after_submit(self):
# Flag will be set on Reconciliation
# Reconciliation tool will anyways repost ledger entries. So, no need to check and do implicit repost.
if self.flags.get("ignore_reposting_on_reconciliation"):
return
self.needs_repost = self.check_if_fields_updated(fields_to_check=[], child_tables={"accounts": []})
if self.needs_repost:
self.validate_for_repost()
@@ -219,10 +213,8 @@ class JournalEntry(AccountsController):
"Repost Accounting Ledger Items",
"Unreconcile Payment",
"Unreconcile Payment Entries",
"Advance Payment Ledger Entry",
)
self.make_gl_entries(1)
self.make_advance_payment_ledger_entries()
self.update_advance_paid()
self.unlink_advance_entry_reference()
self.unlink_asset_reference()
@@ -265,7 +257,7 @@ class JournalEntry(AccountsController):
frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation"))
def validate_stock_accounts(self):
stock_accounts = get_stock_accounts(self.company, accounts=self.accounts)
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
for account in stock_accounts:
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(
account, self.posting_date, self.company
@@ -1676,8 +1668,6 @@ def make_reverse_journal_entry(source_name, target_doc=None):
"debit": "credit",
"credit_in_account_currency": "debit_in_account_currency",
"credit": "debit",
"reference_type": "reference_type",
"reference_name": "reference_name",
},
},
},

View File

@@ -1,8 +1,11 @@
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
# License: GNU General Public License v3. See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import change_settings
from frappe.utils import flt, nowdate
from erpnext.accounts.doctype.account.test_account import get_inventory_account
@@ -10,36 +13,25 @@ from erpnext.accounts.doctype.journal_entry.journal_entry import StockAccountInv
from erpnext.exceptions import InvalidAccountCurrency
class UnitTestJournalEntry(UnitTestCase):
"""
Unit tests for JournalEntry.
Use this class for testing individual functions and methods.
"""
pass
class TestJournalEntry(IntegrationTestCase):
@IntegrationTestCase.change_settings(
"Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1}
)
class TestJournalEntry(unittest.TestCase):
@change_settings("Accounts Settings", {"unlink_payment_on_cancellation_of_invoice": 1})
def test_journal_entry_with_against_jv(self):
jv_invoice = frappe.copy_doc(self.globalTestRecords["Journal Entry"][2])
base_jv = frappe.copy_doc(self.globalTestRecords["Journal Entry"][0])
jv_invoice = frappe.copy_doc(test_records[2])
base_jv = frappe.copy_doc(test_records[0])
self.jv_against_voucher_testcase(base_jv, jv_invoice)
def test_jv_against_sales_order(self):
from erpnext.selling.doctype.sales_order.test_sales_order import make_sales_order
sales_order = make_sales_order(do_not_save=True)
base_jv = frappe.copy_doc(self.globalTestRecords["Journal Entry"][0])
base_jv = frappe.copy_doc(test_records[0])
self.jv_against_voucher_testcase(base_jv, sales_order)
def test_jv_against_purchase_order(self):
from erpnext.buying.doctype.purchase_order.test_purchase_order import create_purchase_order
purchase_order = create_purchase_order(do_not_save=True)
base_jv = frappe.copy_doc(self.globalTestRecords["Journal Entry"][1])
base_jv = frappe.copy_doc(test_records[1])
self.jv_against_voucher_testcase(base_jv, purchase_order)
def jv_against_voucher_testcase(self, base_jv, test_voucher):
@@ -523,72 +515,6 @@ class TestJournalEntry(IntegrationTestCase):
self.assertEqual(row.debit_in_account_currency, 100)
self.assertEqual(row.credit_in_account_currency, 100)
def test_toggle_debit_credit_if_negative(self):
from erpnext.accounts.general_ledger import process_gl_map
# Create JV with defaut cost center - _Test Cost Center
frappe.db.set_single_value("Accounts Settings", "merge_similar_account_heads", 0)
jv = frappe.new_doc("Journal Entry")
jv.posting_date = nowdate()
jv.company = "_Test Company"
jv.user_remark = "test"
jv.extend(
"accounts",
[
{
"account": "_Test Cash - _TC",
"debit": 100 * -1,
"debit_in_account_currency": 100 * -1,
"exchange_rate": 1,
},
{
"account": "_Test Bank - _TC",
"credit": 100 * -1,
"credit_in_account_currency": 100 * -1,
"exchange_rate": 1,
},
],
)
jv.flags.ignore_validate = True
jv.save()
self.assertEqual(len(jv.accounts), 2)
gl_map = jv.build_gl_map()
for row in gl_map:
if row.account == "_Test Cash - _TC":
self.assertEqual(row.debit, 100 * -1)
self.assertEqual(row.debit_in_account_currency, 100 * -1)
self.assertEqual(row.debit_in_transaction_currency, 100 * -1)
gl_map = process_gl_map(gl_map, False)
for row in gl_map:
if row.account == "_Test Cash - _TC":
self.assertEqual(row.credit, 100)
self.assertEqual(row.credit_in_account_currency, 100)
self.assertEqual(row.credit_in_transaction_currency, 100)
def test_transaction_exchange_rate_on_journals(self):
jv = make_journal_entry("_Test Bank - _TC", "_Test Receivable USD - _TC", 100, save=False)
jv.accounts[0].update({"debit_in_account_currency": 8500, "exchange_rate": 1})
jv.accounts[1].update({"party_type": "Customer", "party": "_Test Customer USD", "exchange_rate": 85})
jv.submit()
actual = frappe.db.get_all(
"GL Entry",
filters={"voucher_no": jv.name, "is_cancelled": 0},
fields=["account", "transaction_exchange_rate"],
order_by="account",
)
expected = [
{"account": "_Test Bank - _TC", "transaction_exchange_rate": 1.0},
{"account": "_Test Receivable USD - _TC", "transaction_exchange_rate": 85.0},
]
self.assertEqual(expected, actual)
def make_journal_entry(
account1,
@@ -637,3 +563,6 @@ def make_journal_entry(
jv.submit()
return jv
test_records = frappe.get_test_records("Journal Entry")

View File

@@ -0,0 +1,94 @@
[
{
"cheque_date": "2013-03-14",
"cheque_no": "33",
"company": "_Test Company",
"doctype": "Journal Entry",
"accounts": [
{
"account": "Debtors - _TC",
"party_type": "Customer",
"party": "_Test Customer",
"credit_in_account_currency": 400.0,
"debit_in_account_currency": 0.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
},
{
"account": "_Test Bank - _TC",
"credit_in_account_currency": 0.0,
"debit_in_account_currency": 400.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
}
],
"naming_series": "_T-Journal Entry-",
"posting_date": "2013-02-14",
"user_remark": "test",
"voucher_type": "Bank Entry"
},
{
"cheque_date": "2013-02-14",
"cheque_no": "33",
"company": "_Test Company",
"doctype": "Journal Entry",
"accounts": [
{
"account": "_Test Payable - _TC",
"party_type": "Supplier",
"party": "_Test Supplier",
"credit_in_account_currency": 0.0,
"debit_in_account_currency": 400.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
},
{
"account": "_Test Bank - _TC",
"credit_in_account_currency": 400.0,
"debit_in_account_currency": 0.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
}
],
"naming_series": "_T-Journal Entry-",
"posting_date": "2013-02-14",
"user_remark": "test",
"voucher_type": "Bank Entry"
},
{
"cheque_date": "2013-02-14",
"cheque_no": "33",
"company": "_Test Company",
"doctype": "Journal Entry",
"accounts": [
{
"account": "Debtors - _TC",
"party_type": "Customer",
"party": "_Test Customer",
"credit_in_account_currency": 0.0,
"debit_in_account_currency": 400.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
},
{
"account": "Sales - _TC",
"credit_in_account_currency": 400.0,
"debit_in_account_currency": 0.0,
"doctype": "Journal Entry Account",
"parentfield": "accounts",
"cost_center": "_Test Cost Center - _TC"
}
],
"naming_series": "_T-Journal Entry-",
"posting_date": "2013-02-14",
"user_remark": "test",
"voucher_type": "Bank Entry"
}
]

View File

@@ -1,81 +0,0 @@
[["Journal Entry"]]
cheque_date = "2013-03-14"
cheque_no = "33"
company = "_Test Company"
naming_series = "_T-Journal Entry-"
posting_date = "2013-02-14"
user_remark = "test"
voucher_type = "Bank Entry"
[["Journal Entry".accounts]]
account = "Debtors - _TC"
party_type = "Customer"
party = "_Test Customer"
credit_in_account_currency = 400.0
debit_in_account_currency = 0.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"
[["Journal Entry".accounts]]
account = "_Test Bank - _TC"
credit_in_account_currency = 0.0
debit_in_account_currency = 400.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"
[["Journal Entry"]]
cheque_date = "2013-02-14"
cheque_no = "33"
company = "_Test Company"
naming_series = "_T-Journal Entry-"
posting_date = "2013-02-14"
user_remark = "test"
voucher_type = "Bank Entry"
[["Journal Entry".accounts]]
account = "_Test Payable - _TC"
party_type = "Supplier"
party = "_Test Supplier"
credit_in_account_currency = 0.0
debit_in_account_currency = 400.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"
[["Journal Entry".accounts]]
account = "_Test Bank - _TC"
credit_in_account_currency = 400.0
debit_in_account_currency = 0.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"
[["Journal Entry"]]
cheque_date = "2013-02-14"
cheque_no = "33"
company = "_Test Company"
naming_series = "_T-Journal Entry-"
posting_date = "2013-02-14"
user_remark = "test"
voucher_type = "Bank Entry"
[["Journal Entry".accounts]]
account = "Debtors - _TC"
party_type = "Customer"
party = "_Test Customer"
credit_in_account_currency = 0.0
debit_in_account_currency = 400.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"
[["Journal Entry".accounts]]
account = "Sales - _TC"
credit_in_account_currency = 400.0
debit_in_account_currency = 0.0
doctype = "Journal Entry Account"
parentfield = "accounts"
cost_center = "_Test Cost Center - _TC"

View File

@@ -1,10 +1,9 @@
# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
# import frappe
import unittest
from frappe.tests import IntegrationTestCase
class TestJournalEntryTemplate(IntegrationTestCase):
class TestJournalEntryTemplate(unittest.TestCase):
pass

View File

@@ -3,14 +3,14 @@
import frappe
from frappe import qb
from frappe.tests import IntegrationTestCase
from frappe.tests.utils import FrappeTestCase
from frappe.utils import nowdate
from erpnext.accounts.test.accounts_mixin import AccountsTestMixin
from erpnext.accounts.utils import run_ledger_health_checks
class TestLedgerHealth(AccountsTestMixin, IntegrationTestCase):
class TestLedgerHealth(AccountsTestMixin, FrappeTestCase):
def setUp(self):
self.create_company()
self.create_customer()

View File

@@ -2,17 +2,8 @@
# See license.txt
# import frappe
from frappe.tests import IntegrationTestCase, UnitTestCase
from frappe.tests.utils import FrappeTestCase
class UnitTestLedgerHealthMonitor(UnitTestCase):
"""
Unit tests for LedgerHealthMonitor.
Use this class for testing individual functions and methods.
"""
pass
class TestLedgerHealthMonitor(IntegrationTestCase):
class TestLedgerHealthMonitor(FrappeTestCase):
pass

View File

@@ -1,14 +1,14 @@
# Copyright (c) 2021, Wahni Green Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from erpnext.accounts.doctype.ledger_merge.ledger_merge import start_merge
class TestLedgerMerge(IntegrationTestCase):
class TestLedgerMerge(unittest.TestCase):
def test_merge_success(self):
if not frappe.db.exists("Account", "Indirect Expenses - _TC"):
acc = frappe.new_doc("Account")

View File

@@ -15,16 +15,14 @@
"purchase_amount",
"expiry_date",
"posting_date",
"company",
"discretionary_reason"
"company"
],
"fields": [
{
"fieldname": "loyalty_program",
"fieldtype": "Link",
"label": "Loyalty Program",
"options": "Loyalty Program",
"reqd": 1
"options": "Loyalty Program"
},
{
"fieldname": "loyalty_program_tier",
@@ -36,8 +34,7 @@
"fieldtype": "Link",
"in_list_view": 1,
"label": "Customer",
"options": "Customer",
"reqd": 1
"options": "Customer"
},
{
"fieldname": "redeem_against",
@@ -49,8 +46,7 @@
"fieldname": "loyalty_points",
"fieldtype": "Int",
"in_list_view": 1,
"label": "Loyalty Points",
"reqd": 1
"label": "Loyalty Points"
},
{
"fieldname": "purchase_amount",
@@ -61,28 +57,24 @@
"fieldname": "expiry_date",
"fieldtype": "Date",
"in_list_view": 1,
"label": "Expiry Date",
"reqd": 1
"label": "Expiry Date"
},
{
"fieldname": "posting_date",
"fieldtype": "Date",
"label": "Posting Date",
"reqd": 1
"label": "Posting Date"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company",
"reqd": 1
"options": "Company"
},
{
"fieldname": "invoice_type",
"fieldtype": "Link",
"label": "Invoice Type",
"options": "DocType",
"reqd": 1
"options": "DocType"
},
{
"fieldname": "invoice",
@@ -90,16 +82,11 @@
"in_list_view": 1,
"label": "Invoice",
"options": "invoice_type"
},
{
"fieldname": "discretionary_reason",
"fieldtype": "Data",
"label": "Discretionary Reason"
}
],
"in_create": 1,
"links": [],
"modified": "2024-07-01 08:51:13.927009",
"modified": "2024-03-27 13:10:03.015035",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Loyalty Point Entry",
@@ -136,4 +123,4 @@
"states": [],
"title_field": "customer",
"track_changes": 1
}
}

View File

@@ -18,16 +18,15 @@ class LoyaltyPointEntry(Document):
if TYPE_CHECKING:
from frappe.types import DF
company: DF.Link
customer: DF.Link
discretionary_reason: DF.Data | None
expiry_date: DF.Date
company: DF.Link | None
customer: DF.Link | None
expiry_date: DF.Date | None
invoice: DF.DynamicLink | None
invoice_type: DF.Link
invoice_type: DF.Link | None
loyalty_points: DF.Int
loyalty_program: DF.Link
loyalty_program: DF.Link | None
loyalty_program_tier: DF.Data | None
posting_date: DF.Date
posting_date: DF.Date | None
purchase_amount: DF.Currency
redeem_against: DF.Link | None
# end: auto-generated types

View File

@@ -1,86 +1,8 @@
# Copyright (c) 2018, Frappe Technologies Pvt. Ltd. and Contributors
# See license.txt
import unittest
import frappe
from frappe.tests import IntegrationTestCase
from frappe.utils import today
from erpnext.accounts.doctype.loyalty_program.test_loyalty_program import create_records
from erpnext.accounts.doctype.sales_invoice.test_sales_invoice import create_sales_invoice
class TestLoyaltyPointEntry(IntegrationTestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
# Create test records
create_records()
cls.loyalty_program_name = "Test Single Loyalty"
cls.customer_name = "Test Loyalty Customer"
customer = frappe.get_doc("Customer", cls.customer_name)
customer.db_set("loyalty_program", cls.loyalty_program_name)
@classmethod
def tearDownClass(cls):
# Delete all Loyalty Point Entries
frappe.db.sql("DELETE FROM `tabLoyalty Point Entry` WHERE customer = %s", cls.customer_name)
frappe.db.sql("DELETE FROM `tabSales Invoice` WHERE customer = %s", cls.customer_name)
frappe.db.commit()
# cls.customer.delete()
def create_test_invoice(self, redeem=None):
if redeem:
si = create_sales_invoice(customer=self.customer_name, qty=1, rate=100, do_not_save=True)
si.redeem_loyalty_points = True
si.loyalty_points = redeem
return si.insert().submit()
else:
si = create_sales_invoice(customer=self.customer_name, qty=10, rate=1000, do_not_save=True)
return si.insert().submit()
def test_add_loyalty_points(self):
self.create_test_invoice()
doc = frappe.get_last_doc("Loyalty Point Entry")
self.assertEqual(doc.loyalty_points, 10)
def test_add_loyalty_points_with_discretionary_reason(self):
doc = frappe.get_doc(
{
"doctype": "Loyalty Point Entry",
"loyalty_program": "Test Single Loyalty",
"loyalty_program_tier": "Bronce",
"customer": self.customer_name,
"invoice_type": "Sales Invoice",
"loyalty_points": 75,
"expiry_date": today(),
"posting_date": today(),
"company": "_Test Company",
"discretionary_reason": "Customer Appreciation",
}
)
doc.insert(ignore_permissions=True)
self.assertEqual(doc.loyalty_points, 75)
self.assertEqual(doc.discretionary_reason, "Customer Appreciation")
# Verify the entry in the database
entry = frappe.get_doc("Loyalty Point Entry", doc.name)
self.assertEqual(entry.loyalty_points, 75)
self.assertEqual(entry.discretionary_reason, "Customer Appreciation")
def test_redeem_loyalty_points(self):
self.create_test_invoice(redeem=10)
doc = frappe.get_last_doc("Loyalty Point Entry")
self.assertEqual(doc.loyalty_points, -10)
# Check balance
balance = frappe.db.sql(
"""
SELECT SUM(loyalty_points)
FROM `tabLoyalty Point Entry`
WHERE customer = %s
""",
(self.customer_name,),
)[0][0]
self.assertEqual(balance, 75) # 85 added, 10 redeemed
class TestLoyaltyPointEntry(unittest.TestCase):
pass

View File

@@ -36,17 +36,7 @@ class LoyaltyProgram(Document):
to_date: DF.Date | None
# end: auto-generated types
def validate(self):
self.validate_lowest_tier()
def validate_lowest_tier(self):
tiers = sorted(self.collection_rules, key=lambda x: x.min_spent)
if tiers and tiers[0].min_spent != 0:
frappe.throw(
_(
"The lowest tier must have a minimum spent amount of 0. Customers need to be part of a tier as soon as they are enrolled in the program."
)
)
pass
def get_loyalty_details(
@@ -89,17 +79,17 @@ def get_loyalty_program_details_with_points(
):
lp_details = get_loyalty_program_details(customer, loyalty_program, company=company, silent=silent)
loyalty_program = frappe.get_doc("Loyalty Program", loyalty_program)
loyalty_details = get_loyalty_details(
customer, loyalty_program.name, expiry_date, company, include_expired_entry
lp_details.update(
get_loyalty_details(customer, loyalty_program.name, expiry_date, company, include_expired_entry)
)
lp_details.update(loyalty_details)
tier_spent_level = sorted(
[d.as_dict() for d in loyalty_program.collection_rules],
key=lambda rule: rule.min_spent,
reverse=True,
)
for i, d in enumerate(tier_spent_level):
if i == 0 or (lp_details.total_spent + current_transaction_amount) >= d.min_spent:
if i == 0 or (lp_details.total_spent + current_transaction_amount) <= d.min_spent:
lp_details.tier_name = d.tier_name
lp_details.collection_factor = d.collection_factor
else:
@@ -183,8 +173,6 @@ def validate_loyalty_points(ref_doc, points_to_redeem):
if not ref_doc.loyalty_amount and ref_doc.loyalty_amount != loyalty_amount:
ref_doc.loyalty_amount = loyalty_amount
if not ref_doc.loyalty_points and ref_doc.loyalty_points != points_to_redeem:
ref_doc.loyalty_points = points_to_redeem
if ref_doc.doctype == "Sales Invoice":
ref_doc.loyalty_program = loyalty_program

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