Merge branch 'develop' into asset_depreciation_schedule

This commit is contained in:
Anand Baburajan
2022-12-12 16:36:59 +05:30
committed by GitHub
204 changed files with 5924 additions and 8159 deletions

View File

@@ -24,15 +24,14 @@ fi
if [ "$DB" == "mariadb" ];then if [ "$DB" == "mariadb" ];then
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL character_set_server = 'utf8mb4'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL character_set_server = 'utf8mb4'"
mysql --host 127.0.0.1 --port 3306 -u root -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "SET GLOBAL collation_server = 'utf8mb4_unicode_ci'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE USER 'test_frappe'@'localhost' IDENTIFIED BY 'test_frappe'"
mysql --host 127.0.0.1 --port 3306 -u root -e "CREATE DATABASE test_frappe" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "CREATE DATABASE test_frappe"
mysql --host 127.0.0.1 --port 3306 -u root -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "GRANT ALL PRIVILEGES ON \`test_frappe\`.* TO 'test_frappe'@'localhost'"
mysql --host 127.0.0.1 --port 3306 -u root -e "UPDATE mysql.user SET Password=PASSWORD('travis') WHERE User='root'" mysql --host 127.0.0.1 --port 3306 -u root -proot -e "FLUSH PRIVILEGES"
mysql --host 127.0.0.1 --port 3306 -u root -e "FLUSH PRIVILEGES"
fi fi
if [ "$DB" == "postgres" ];then if [ "$DB" == "postgres" ];then

View File

@@ -9,8 +9,8 @@
"mail_password": "test", "mail_password": "test",
"admin_password": "admin", "admin_password": "admin",
"root_login": "root", "root_login": "root",
"root_password": "travis", "root_password": "root",
"host_name": "http://test_site:8000", "host_name": "http://test_site:8000",
"install_apps": ["erpnext"], "install_apps": ["payments", "erpnext"],
"throttle_user_limit": 100 "throttle_user_limit": 100
} }

View File

@@ -25,7 +25,7 @@ jobs:
mysql: mysql:
image: mariadb:10.3 image: mariadb:10.3
env: env:
MYSQL_ALLOW_EMPTY_PASSWORD: YES MARIADB_ROOT_PASSWORD: 'root'
ports: ports:
- 3306:3306 - 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3

View File

@@ -45,9 +45,9 @@ jobs:
services: services:
mysql: mysql:
image: mariadb:10.3 image: mariadb:10.6
env: env:
MYSQL_ALLOW_EMPTY_PASSWORD: YES MARIADB_ROOT_PASSWORD: 'root'
ports: ports:
- 3306:3306 - 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3 options: --health-cmd="mysqladmin ping" --health-interval=5s --health-timeout=2s --health-retries=3

View File

@@ -76,7 +76,7 @@ def get(
def build_result(account, dates, gl_entries): def build_result(account, dates, gl_entries):
result = [[getdate(date), 0.0] for date in dates] result = [[getdate(date), 0.0] for date in dates]
root_type = frappe.db.get_value("Account", account, "root_type") root_type = frappe.get_cached_value("Account", account, "root_type")
# start with the first date # start with the first date
date_index = 0 date_index = 0

View File

@@ -58,7 +58,7 @@ class Account(NestedSet):
def validate_parent(self): def validate_parent(self):
"""Fetch Parent Details and validate parent account""" """Fetch Parent Details and validate parent account"""
if self.parent_account: if self.parent_account:
par = frappe.db.get_value( par = frappe.get_cached_value(
"Account", self.parent_account, ["name", "is_group", "company"], as_dict=1 "Account", self.parent_account, ["name", "is_group", "company"], as_dict=1
) )
if not par: if not par:
@@ -82,7 +82,7 @@ class Account(NestedSet):
def set_root_and_report_type(self): def set_root_and_report_type(self):
if self.parent_account: if self.parent_account:
par = frappe.db.get_value( par = frappe.get_cached_value(
"Account", self.parent_account, ["report_type", "root_type"], as_dict=1 "Account", self.parent_account, ["report_type", "root_type"], as_dict=1
) )
@@ -92,7 +92,7 @@ class Account(NestedSet):
self.root_type = par.root_type self.root_type = par.root_type
if self.is_group: if self.is_group:
db_value = frappe.db.get_value("Account", self.name, ["report_type", "root_type"], as_dict=1) db_value = self.get_doc_before_save()
if db_value: if db_value:
if self.report_type != db_value.report_type: if self.report_type != db_value.report_type:
frappe.db.sql( frappe.db.sql(
@@ -111,13 +111,13 @@ class Account(NestedSet):
) )
def validate_root_details(self): def validate_root_details(self):
# does not exists parent doc_before_save = self.get_doc_before_save()
if frappe.db.exists("Account", self.name):
if not frappe.db.get_value("Account", self.name, "parent_account"): if doc_before_save and not doc_before_save.parent_account:
throw(_("Root cannot be edited."), RootNotEditable) throw(_("Root cannot be edited."), RootNotEditable)
if not self.parent_account and not self.is_group: if not self.parent_account and not self.is_group:
frappe.throw(_("The root account {0} must be a group").format(frappe.bold(self.name))) throw(_("The root account {0} must be a group").format(frappe.bold(self.name)))
def validate_root_company_and_sync_account_to_children(self): def validate_root_company_and_sync_account_to_children(self):
# ignore validation while creating new compnay or while syncing to child companies # ignore validation while creating new compnay or while syncing to child companies
@@ -127,7 +127,9 @@ class Account(NestedSet):
return return
ancestors = get_root_company(self.company) ancestors = get_root_company(self.company)
if ancestors: if ancestors:
if frappe.get_value("Company", self.company, "allow_account_creation_against_child_company"): if frappe.get_cached_value(
"Company", self.company, "allow_account_creation_against_child_company"
):
return return
if not frappe.db.get_value( if not frappe.db.get_value(
"Account", {"account_name": self.account_name, "company": ancestors[0]}, "name" "Account", {"account_name": self.account_name, "company": ancestors[0]}, "name"
@@ -138,7 +140,7 @@ class Account(NestedSet):
if not descendants: if not descendants:
return return
parent_acc_name_map = {} parent_acc_name_map = {}
parent_acc_name, parent_acc_number = frappe.db.get_value( parent_acc_name, parent_acc_number = frappe.get_cached_value(
"Account", self.parent_account, ["account_name", "account_number"] "Account", self.parent_account, ["account_name", "account_number"]
) )
filters = { filters = {
@@ -159,27 +161,28 @@ class Account(NestedSet):
self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name) self.create_account_for_child_company(parent_acc_name_map, descendants, parent_acc_name)
def validate_group_or_ledger(self): def validate_group_or_ledger(self):
if self.get("__islocal"): doc_before_save = self.get_doc_before_save()
if not doc_before_save or cint(doc_before_save.is_group) == cint(self.is_group):
return return
existing_is_group = frappe.db.get_value("Account", self.name, "is_group") if self.check_gle_exists():
if cint(self.is_group) != cint(existing_is_group): throw(_("Account with existing transaction cannot be converted to ledger"))
if self.check_gle_exists(): elif self.is_group:
throw(_("Account with existing transaction cannot be converted to ledger")) if self.account_type and not self.flags.exclude_account_type_check:
elif self.is_group: throw(_("Cannot covert to Group because Account Type is selected."))
if self.account_type and not self.flags.exclude_account_type_check: elif self.check_if_child_exists():
throw(_("Cannot covert to Group because Account Type is selected.")) throw(_("Account with child nodes cannot be set as ledger"))
elif self.check_if_child_exists():
throw(_("Account with child nodes cannot be set as ledger"))
def validate_frozen_accounts_modifier(self): def validate_frozen_accounts_modifier(self):
old_value = frappe.db.get_value("Account", self.name, "freeze_account") doc_before_save = self.get_doc_before_save()
if old_value and old_value != self.freeze_account: if not doc_before_save or doc_before_save.freeze_account == self.freeze_account:
frozen_accounts_modifier = frappe.db.get_value( return
"Accounts Settings", None, "frozen_accounts_modifier"
) frozen_accounts_modifier = frappe.get_cached_value(
if not frozen_accounts_modifier or frozen_accounts_modifier not in frappe.get_roles(): "Accounts Settings", "Accounts Settings", "frozen_accounts_modifier"
throw(_("You are not authorized to set Frozen value")) )
if not frozen_accounts_modifier or frozen_accounts_modifier not in frappe.get_roles():
throw(_("You are not authorized to set Frozen value"))
def validate_balance_must_be_debit_or_credit(self): def validate_balance_must_be_debit_or_credit(self):
from erpnext.accounts.utils import get_balance_on from erpnext.accounts.utils import get_balance_on
@@ -223,9 +226,9 @@ class Account(NestedSet):
) )
# validate if parent of child company account to be added is a group # validate if parent of child company account to be added is a group
if frappe.db.get_value("Account", self.parent_account, "is_group") and not frappe.db.get_value( if frappe.get_cached_value(
"Account", parent_acc_name_map[company], "is_group" "Account", self.parent_account, "is_group"
): ) and not frappe.get_cached_value("Account", parent_acc_name_map[company], "is_group"):
msg = _( msg = _(
"While creating account for Child Company {0}, parent account {1} found as a ledger account." "While creating account for Child Company {0}, parent account {1} found as a ledger account."
).format(company_bold, parent_acc_name_bold) ).format(company_bold, parent_acc_name_bold)
@@ -377,17 +380,15 @@ def validate_account_number(name, account_number, company):
@frappe.whitelist() @frappe.whitelist()
def update_account_number(name, account_name, account_number=None, from_descendant=False): def update_account_number(name, account_name, account_number=None, from_descendant=False):
account = frappe.db.get_value("Account", name, "company", as_dict=True) account = frappe.get_cached_doc("Account", name)
if not account: if not account:
return return
old_acc_name, old_acc_number = frappe.db.get_value( old_acc_name, old_acc_number = account.account_name, account.account_number
"Account", name, ["account_name", "account_number"]
)
# check if account exists in parent company # check if account exists in parent company
ancestors = get_ancestors_of("Company", account.company) ancestors = get_ancestors_of("Company", account.company)
allow_independent_account_creation = frappe.get_value( allow_independent_account_creation = frappe.get_cached_value(
"Company", account.company, "allow_account_creation_against_child_company" "Company", account.company, "allow_account_creation_against_child_company"
) )
@@ -435,22 +436,24 @@ def update_account_number(name, account_name, account_number=None, from_descenda
@frappe.whitelist() @frappe.whitelist()
def merge_account(old, new, is_group, root_type, company): def merge_account(old, new, is_group, root_type, company):
# Validate properties before merging # Validate properties before merging
if not frappe.db.exists("Account", new): new_account = frappe.get_cached_doc("Account", new)
if not new_account:
throw(_("Account {0} does not exist").format(new)) throw(_("Account {0} does not exist").format(new))
val = list(frappe.db.get_value("Account", new, ["is_group", "root_type", "company"])) if (new_account.is_group, new_account.root_type, new_account.company) != (
cint(is_group),
if val != [cint(is_group), root_type, company]: root_type,
company,
):
throw( throw(
_( _(
"""Merging is only possible if following properties are same in both records. Is Group, Root Type, Company""" """Merging is only possible if following properties are same in both records. Is Group, Root Type, Company"""
) )
) )
if is_group and frappe.db.get_value("Account", new, "parent_account") == old: if is_group and new_account.parent_account == old:
frappe.db.set_value( new_account.db_set("parent_account", frappe.get_cached_value("Account", old, "parent_account"))
"Account", new, "parent_account", frappe.db.get_value("Account", old, "parent_account")
)
frappe.rename_doc("Account", old, new, merge=1, force=1) frappe.rename_doc("Account", old, new, merge=1, force=1)

View File

@@ -53,7 +53,7 @@ def create_charts(
"account_number": account_number, "account_number": account_number,
"account_type": child.get("account_type"), "account_type": child.get("account_type"),
"account_currency": child.get("account_currency") "account_currency": child.get("account_currency")
or frappe.db.get_value("Company", company, "default_currency"), or frappe.get_cached_value("Company", company, "default_currency"),
"tax_rate": child.get("tax_rate"), "tax_rate": child.get("tax_rate"),
} }
) )
@@ -148,7 +148,7 @@ def get_charts_for_country(country, with_standard=False):
) or frappe.local.flags.allow_unverified_charts: ) or frappe.local.flags.allow_unverified_charts:
charts.append(content["name"]) charts.append(content["name"])
country_code = frappe.db.get_value("Country", country, "code") country_code = frappe.get_cached_value("Country", country, "code")
if country_code: if country_code:
folders = ("verified",) folders = ("verified",)
if frappe.local.flags.allow_unverified_charts: if frappe.local.flags.allow_unverified_charts:

View File

@@ -91,7 +91,7 @@
}, },
{ {
"default": "0", "default": "0",
"description": "Enabling ensure each Sales Invoice has a unique value in Supplier Invoice No. field", "description": "Enabling ensure each Purchase Invoice has a unique value in Supplier Invoice No. field",
"fieldname": "check_supplier_invoice_uniqueness", "fieldname": "check_supplier_invoice_uniqueness",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Check Supplier Invoice Number Uniqueness" "label": "Check Supplier Invoice Number Uniqueness"
@@ -354,7 +354,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"issingle": 1, "issingle": 1,
"links": [], "links": [],
"modified": "2022-07-11 13:37:50.605141", "modified": "2022-11-27 21:49:52.538655",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Accounts Settings", "name": "Accounts Settings",

View File

@@ -77,6 +77,6 @@ def get_party_bank_account(party_type, party):
@frappe.whitelist() @frappe.whitelist()
def get_bank_account_details(bank_account): def get_bank_account_details(bank_account):
return frappe.db.get_value( return frappe.get_cached_value(
"Bank Account", bank_account, ["account", "bank", "bank_account_no"], as_dict=1 "Bank Account", bank_account, ["account", "bank", "bank_account_no"], as_dict=1
) )

View File

@@ -37,6 +37,14 @@ frappe.ui.form.on("Bank Clearance", {
refresh: function(frm) { refresh: function(frm) {
frm.disable_save(); frm.disable_save();
if (frm.doc.account && frm.doc.from_date && frm.doc.to_date) {
frm.add_custom_button(__('Get Payment Entries'), () =>
frm.trigger("get_payment_entries")
);
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
}
}, },
update_clearance_date: function(frm) { update_clearance_date: function(frm) {
@@ -46,22 +54,30 @@ frappe.ui.form.on("Bank Clearance", {
callback: function(r, rt) { callback: function(r, rt) {
frm.refresh_field("payment_entries"); frm.refresh_field("payment_entries");
frm.refresh_fields(); frm.refresh_fields();
if (!frm.doc.payment_entries.length) {
frm.change_custom_button_type('Get Payment Entries', null, 'primary');
frm.change_custom_button_type('Update Clearance Date', null, 'default');
}
} }
}); });
}, },
get_payment_entries: function(frm) { get_payment_entries: function(frm) {
return frappe.call({ return frappe.call({
method: "get_payment_entries", method: "get_payment_entries",
doc: frm.doc, doc: frm.doc,
callback: function(r, rt) { callback: function(r, rt) {
frm.refresh_field("payment_entries"); frm.refresh_field("payment_entries");
frm.refresh_fields();
$(frm.fields_dict.payment_entries.wrapper).find("[data-fieldname=amount]").each(function(i,v){ if (frm.doc.payment_entries.length) {
if (i !=0){ frm.add_custom_button(__('Update Clearance Date'), () =>
$(v).addClass("text-right") 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

@@ -1,4 +1,5 @@
{ {
"actions": [],
"allow_copy": 1, "allow_copy": 1,
"creation": "2013-01-10 16:34:05", "creation": "2013-01-10 16:34:05",
"doctype": "DocType", "doctype": "DocType",
@@ -13,11 +14,8 @@
"bank_account", "bank_account",
"include_reconciled_entries", "include_reconciled_entries",
"include_pos_transactions", "include_pos_transactions",
"get_payment_entries",
"section_break_10", "section_break_10",
"payment_entries", "payment_entries"
"update_clearance_date",
"total_amount"
], ],
"fields": [ "fields": [
{ {
@@ -76,11 +74,6 @@
"fieldtype": "Check", "fieldtype": "Check",
"label": "Include POS Transactions" "label": "Include POS Transactions"
}, },
{
"fieldname": "get_payment_entries",
"fieldtype": "Button",
"label": "Get Payment Entries"
},
{ {
"fieldname": "section_break_10", "fieldname": "section_break_10",
"fieldtype": "Section Break" "fieldtype": "Section Break"
@@ -91,25 +84,14 @@
"fieldtype": "Table", "fieldtype": "Table",
"label": "Payment Entries", "label": "Payment Entries",
"options": "Bank Clearance Detail" "options": "Bank Clearance Detail"
},
{
"fieldname": "update_clearance_date",
"fieldtype": "Button",
"label": "Update Clearance Date"
},
{
"fieldname": "total_amount",
"fieldtype": "Currency",
"label": "Total Amount",
"options": "account_currency",
"read_only": 1
} }
], ],
"hide_toolbar": 1, "hide_toolbar": 1,
"icon": "fa fa-check", "icon": "fa fa-check",
"idx": 1, "idx": 1,
"issingle": 1, "issingle": 1,
"modified": "2020-04-06 16:12:06.628008", "links": [],
"modified": "2022-11-28 17:24:13.008692",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Bank Clearance", "name": "Bank Clearance",
@@ -126,5 +108,6 @@
"quick_entry": 1, "quick_entry": 1,
"read_only": 1, "read_only": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "ASC" "sort_order": "ASC",
"states": []
} }

View File

@@ -179,7 +179,6 @@ class BankClearance(Document):
) )
self.set("payment_entries", []) self.set("payment_entries", [])
self.total_amount = 0.0
default_currency = erpnext.get_default_currency() default_currency = erpnext.get_default_currency()
for d in entries: for d in entries:
@@ -198,7 +197,6 @@ class BankClearance(Document):
d.pop("debit") d.pop("debit")
d.pop("account_currency") d.pop("account_currency")
row.update(d) row.update(d)
self.total_amount += flt(amount)
@frappe.whitelist() @frappe.whitelist()
def update_clearance_date(self): def update_clearance_date(self):

View File

@@ -57,7 +57,7 @@ def get_bank_transactions(bank_account, from_date=None, to_date=None):
@frappe.whitelist() @frappe.whitelist()
def get_account_balance(bank_account, till_date): def get_account_balance(bank_account, till_date):
# returns account balance till the specified date # returns account balance till the specified date
account = frappe.db.get_value("Bank Account", bank_account, "account") account = frappe.get_cached_value("Bank Account", bank_account, "account")
filters = frappe._dict( filters = frappe._dict(
{"account": account, "report_date": till_date, "include_pos_transactions": 1} {"account": account, "report_date": till_date, "include_pos_transactions": 1}
) )
@@ -130,8 +130,10 @@ def create_journal_entry_bts(
fieldname=["name", "deposit", "withdrawal", "bank_account"], fieldname=["name", "deposit", "withdrawal", "bank_account"],
as_dict=True, as_dict=True,
)[0] )[0]
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account") company_account = frappe.get_cached_value(
account_type = frappe.db.get_value("Account", second_account, "account_type") "Bank Account", bank_transaction.bank_account, "account"
)
account_type = frappe.get_cached_value("Account", second_account, "account_type")
if account_type in ["Receivable", "Payable"]: if account_type in ["Receivable", "Payable"]:
if not (party_type and party): if not (party_type and party):
frappe.throw( frappe.throw(
@@ -164,7 +166,7 @@ def create_journal_entry_bts(
} }
) )
company = frappe.get_value("Account", company_account, "company") company = frappe.get_cached_value("Account", company_account, "company")
journal_entry_dict = { journal_entry_dict = {
"voucher_type": entry_type, "voucher_type": entry_type,
@@ -219,8 +221,10 @@ def create_payment_entry_bts(
paid_amount = bank_transaction.unallocated_amount paid_amount = bank_transaction.unallocated_amount
payment_type = "Receive" if bank_transaction.deposit > 0 else "Pay" payment_type = "Receive" if bank_transaction.deposit > 0 else "Pay"
company_account = frappe.get_value("Bank Account", bank_transaction.bank_account, "account") company_account = frappe.get_cached_value(
company = frappe.get_value("Account", company_account, "company") "Bank Account", bank_transaction.bank_account, "account"
)
company = frappe.get_cached_value("Account", company_account, "company")
payment_entry_dict = { payment_entry_dict = {
"company": company, "company": company,
"payment_type": payment_type, "payment_type": payment_type,
@@ -266,7 +270,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
# updated clear date of all the vouchers based on the bank transaction # updated clear date of all the vouchers based on the bank transaction
vouchers = json.loads(vouchers) vouchers = json.loads(vouchers)
transaction = frappe.get_doc("Bank Transaction", bank_transaction_name) transaction = frappe.get_doc("Bank Transaction", bank_transaction_name)
company_account = frappe.db.get_value("Bank Account", transaction.bank_account, "account") company_account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
if transaction.unallocated_amount == 0: if transaction.unallocated_amount == 0:
frappe.throw(_("This bank transaction is already fully reconciled")) frappe.throw(_("This bank transaction is already fully reconciled"))
@@ -290,7 +294,7 @@ def reconcile_vouchers(bank_transaction_name, vouchers):
"The sum total of amounts of all selected vouchers should be less than the unallocated amount of the bank transaction" "The sum total of amounts of all selected vouchers should be less than the unallocated amount of the bank transaction"
) )
) )
account = frappe.db.get_value("Bank Account", transaction.bank_account, "account") account = frappe.get_cached_value("Bank Account", transaction.bank_account, "account")
for voucher in vouchers: for voucher in vouchers:
gl_entry = frappe.db.get_value( gl_entry = frappe.db.get_value(

View File

@@ -74,7 +74,7 @@ def get_header_mapping(columns, bank_account):
def get_bank_mapping(bank_account): def get_bank_mapping(bank_account):
bank_name = frappe.db.get_value("Bank Account", bank_account, "bank") bank_name = frappe.get_cached_value("Bank Account", bank_account, "bank")
bank = frappe.get_doc("Bank", bank_name) bank = frappe.get_doc("Bank", bank_name)
mapping = {row.file_field: row.bank_transaction_field for row in bank.bank_transaction_mapping} mapping = {row.file_field: row.bank_transaction_field for row in bank.bank_transaction_mapping}

View File

@@ -59,7 +59,7 @@ class Budget(Document):
account_list = [] account_list = []
for d in self.get("accounts"): for d in self.get("accounts"):
if d.account: if d.account:
account_details = frappe.db.get_value( account_details = frappe.get_cached_value(
"Account", d.account, ["is_group", "company", "report_type"], as_dict=1 "Account", d.account, ["is_group", "company", "report_type"], as_dict=1
) )
@@ -306,7 +306,7 @@ def get_other_condition(args, budget, for_doc):
if args.get("fiscal_year"): if args.get("fiscal_year"):
date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date" date_field = "schedule_date" if for_doc == "Material Request" else "transaction_date"
start_date, end_date = frappe.db.get_value( start_date, end_date = frappe.get_cached_value(
"Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"] "Fiscal Year", args.get("fiscal_year"), ["year_start_date", "year_end_date"]
) )
@@ -379,7 +379,7 @@ def get_accumulated_monthly_budget(monthly_distribution, posting_date, fiscal_ye
): ):
distribution.setdefault(d.month, d.percentage_allocation) distribution.setdefault(d.month, d.percentage_allocation)
dt = frappe.db.get_value("Fiscal Year", fiscal_year, "year_start_date") dt = frappe.get_cached_value("Fiscal Year", fiscal_year, "year_start_date")
accumulated_percentage = 0.0 accumulated_percentage = 0.0
while dt <= getdate(posting_date): while dt <= getdate(posting_date):

View File

@@ -45,8 +45,8 @@ def validate_columns(data):
@frappe.whitelist() @frappe.whitelist()
def validate_company(company): def validate_company(company):
parent_company, allow_account_creation_against_child_company = frappe.db.get_value( parent_company, allow_account_creation_against_child_company = frappe.get_cached_value(
"Company", {"name": company}, ["parent_company", "allow_account_creation_against_child_company"] "Company", company, ["parent_company", "allow_account_creation_against_child_company"]
) )
if parent_company and (not allow_account_creation_against_child_company): if parent_company and (not allow_account_creation_against_child_company):

View File

@@ -19,7 +19,7 @@ class Dunning(AccountsController):
self.validate_overdue_days() self.validate_overdue_days()
self.validate_amount() self.validate_amount()
if not self.income_account: if not self.income_account:
self.income_account = frappe.db.get_value("Company", self.company, "default_income_account") self.income_account = frappe.get_cached_value("Company", self.company, "default_income_account")
def validate_overdue_days(self): def validate_overdue_days(self):
self.overdue_days = (getdate(self.posting_date) - getdate(self.due_date)).days or 0 self.overdue_days = (getdate(self.posting_date) - getdate(self.due_date)).days or 0

View File

@@ -1,322 +1,88 @@
{ {
"allow_copy": 0, "actions": [],
"allow_guest_to_view": 0,
"allow_import": 1, "allow_import": 1,
"allow_rename": 0,
"autoname": "ACC-ERR-.YYYY.-.#####", "autoname": "ACC-ERR-.YYYY.-.#####",
"beta": 0,
"creation": "2018-04-13 18:25:55.943587", "creation": "2018-04-13 18:25:55.943587",
"custom": 0,
"docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [
"posting_date",
"column_break_2",
"company",
"section_break_4",
"get_entries",
"accounts",
"section_break_6",
"total_gain_loss",
"amended_from"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"default": "Today", "default": "Today",
"fieldname": "posting_date", "fieldname": "posting_date",
"fieldtype": "Date", "fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Posting Date", "label": "Posting Date",
"length": 0, "reqd": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "column_break_2", "fieldname": "column_break_2",
"fieldtype": "Column Break", "fieldtype": "Column Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "company", "fieldname": "company",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Company", "label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company", "options": "Company",
"permlevel": 0, "reqd": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_4", "fieldname": "section_break_4",
"fieldtype": "Section Break", "fieldtype": "Section Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "get_entries", "fieldname": "get_entries",
"fieldtype": "Button", "fieldtype": "Button",
"hidden": 0, "label": "Get Entries"
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Get Entries",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "accounts", "fieldname": "accounts",
"fieldtype": "Table", "fieldtype": "Table",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Exchange Rate Revaluation Account", "label": "Exchange Rate Revaluation Account",
"length": 0,
"no_copy": 1, "no_copy": 1,
"options": "Exchange Rate Revaluation Account", "options": "Exchange Rate Revaluation Account",
"permlevel": 0, "reqd": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "section_break_6", "fieldname": "section_break_6",
"fieldtype": "Section Break", "fieldtype": "Section Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "total_gain_loss", "fieldname": "total_gain_loss",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Total Gain/Loss", "label": "Total Gain/Loss",
"length": 0, "options": "Company:company:default_currency",
"no_copy": 0, "read_only": 1
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fieldname": "amended_from", "fieldname": "amended_from",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Amended From", "label": "Amended From",
"length": 0,
"no_copy": 1, "no_copy": 1,
"options": "Exchange Rate Revaluation", "options": "Exchange Rate Revaluation",
"permlevel": 0,
"print_hide": 1, "print_hide": 1,
"print_hide_if_no_value": 0, "read_only": 1
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 1, "is_submittable": 1,
"issingle": 0, "links": [],
"istable": 0, "modified": "2022-11-17 10:28:03.911554",
"max_attachments": 0,
"modified": "2018-08-21 16:15:34.660715",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Exchange Rate Revaluation", "name": "Exchange Rate Revaluation",
"name_case": "", "naming_rule": "Expression (old style)",
"owner": "Administrator", "owner": "Administrator",
"permissions": [ "permissions": [
{ {
@@ -326,14 +92,10 @@
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 1, "export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "System Manager", "role": "System Manager",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
@@ -345,14 +107,10 @@
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 1, "export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "Accounts Manager", "role": "Accounts Manager",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
@@ -364,26 +122,17 @@
"delete": 1, "delete": 1,
"email": 1, "email": 1,
"export": 1, "export": 1,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 1, "print": 1,
"read": 1, "read": 1,
"report": 1, "report": 1,
"role": "Accounts User", "role": "Accounts User",
"set_user_permissions": 0,
"share": 1, "share": 1,
"submit": 1, "submit": 1,
"write": 1 "write": 1
} }
], ],
"quick_entry": 0,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 1, "states": [],
"track_seen": 0, "track_changes": 1
"track_views": 0
} }

View File

@@ -222,7 +222,7 @@ class ExchangeRateRevaluation(Document):
@frappe.whitelist() @frappe.whitelist()
def get_account_details(account, company, posting_date, party_type=None, party=None): def get_account_details(account, company, posting_date, party_type=None, party=None):
account_currency, account_type = frappe.db.get_value( account_currency, account_type = frappe.get_cached_value(
"Account", account, ["account_currency", "account_type"] "Account", account, ["account_currency", "account_type"]
) )
if account_type in ["Receivable", "Payable"] and not (party_type and party): if account_type in ["Receivable", "Payable"] and not (party_type and party):
@@ -233,6 +233,10 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
balance = get_balance_on( balance = get_balance_on(
account, date=posting_date, party_type=party_type, party=party, in_account_currency=False account, date=posting_date, party_type=party_type, party=party, in_account_currency=False
) )
account_details = {
"account_currency": account_currency,
}
if balance: if balance:
balance_in_account_currency = get_balance_on( balance_in_account_currency = get_balance_on(
account, date=posting_date, party_type=party_type, party=party account, date=posting_date, party_type=party_type, party=party
@@ -242,13 +246,14 @@ def get_account_details(account, company, posting_date, party_type=None, party=N
) )
new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date) new_exchange_rate = get_exchange_rate(account_currency, company_currency, posting_date)
new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate new_balance_in_base_currency = balance_in_account_currency * new_exchange_rate
account_details = { account_details = account_details.update(
"account_currency": account_currency, {
"balance_in_base_currency": balance, "balance_in_base_currency": balance,
"balance_in_account_currency": balance_in_account_currency, "balance_in_account_currency": balance_in_account_currency,
"current_exchange_rate": current_exchange_rate, "current_exchange_rate": current_exchange_rate,
"new_exchange_rate": new_exchange_rate, "new_exchange_rate": new_exchange_rate,
"new_balance_in_base_currency": new_balance_in_base_currency, "new_balance_in_base_currency": new_balance_in_base_currency,
} }
)
return account_details return account_details

View File

@@ -1,475 +1,120 @@
{ {
"allow_copy": 0, "actions": [],
"allow_events_in_timeline": 0,
"allow_guest_to_view": 0,
"allow_import": 0,
"allow_rename": 0,
"beta": 0,
"creation": "2018-04-13 18:30:06.110433", "creation": "2018-04-13 18:30:06.110433",
"custom": 0,
"docstatus": 0,
"doctype": "DocType", "doctype": "DocType",
"document_type": "",
"editable_grid": 1, "editable_grid": 1,
"engine": "InnoDB", "engine": "InnoDB",
"field_order": [
"account",
"party_type",
"party",
"column_break_2",
"account_currency",
"balance_in_account_currency",
"balances",
"current_exchange_rate",
"balance_in_base_currency",
"column_break_9",
"new_exchange_rate",
"new_balance_in_base_currency",
"gain_loss"
],
"fields": [ "fields": [
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "account", "fieldname": "account",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Account", "label": "Account",
"length": 0,
"no_copy": 0,
"options": "Account", "options": "Account",
"permlevel": 0, "reqd": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "party_type", "fieldname": "party_type",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Party Type", "label": "Party Type",
"length": 0, "options": "DocType"
"no_copy": 0,
"options": "DocType",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "party", "fieldname": "party",
"fieldtype": "Dynamic Link", "fieldtype": "Dynamic Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Party", "label": "Party",
"length": 0, "options": "party_type"
"no_copy": 0,
"options": "party_type",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_2", "fieldname": "column_break_2",
"fieldtype": "Column Break", "fieldtype": "Column Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "account_currency", "fieldname": "account_currency",
"fieldtype": "Link", "fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Account Currency", "label": "Account Currency",
"length": 0,
"no_copy": 0,
"options": "Currency", "options": "Currency",
"permlevel": 0, "read_only": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "balance_in_account_currency", "fieldname": "balance_in_account_currency",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Balance In Account Currency", "label": "Balance In Account Currency",
"length": 0,
"no_copy": 0,
"options": "account_currency", "options": "account_currency",
"permlevel": 0, "read_only": 1
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "balances", "fieldname": "balances",
"fieldtype": "Section Break", "fieldtype": "Section Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "current_exchange_rate", "fieldname": "current_exchange_rate",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Current Exchange Rate", "label": "Current Exchange Rate",
"length": 0, "read_only": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "balance_in_base_currency", "fieldname": "balance_in_base_currency",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Balance In Base Currency", "label": "Balance In Base Currency",
"length": 0, "options": "Company:company:default_currency",
"no_copy": 0, "read_only": 1
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "column_break_9", "fieldname": "column_break_9",
"fieldtype": "Column Break", "fieldtype": "Column Break"
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "new_exchange_rate", "fieldname": "new_exchange_rate",
"fieldtype": "Float", "fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "New Exchange Rate", "label": "New Exchange Rate",
"length": 0, "reqd": 1
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 1,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "new_balance_in_base_currency", "fieldname": "new_balance_in_base_currency",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "New Balance In Base Currency", "label": "New Balance In Base Currency",
"length": 0, "options": "Company:company:default_currency",
"no_copy": 0, "read_only": 1
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
}, },
{ {
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "gain_loss", "fieldname": "gain_loss",
"fieldtype": "Currency", "fieldtype": "Currency",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 1, "in_list_view": 1,
"in_standard_filter": 0,
"label": "Gain/Loss", "label": "Gain/Loss",
"length": 0, "options": "Company:company:default_currency",
"no_copy": 0, "read_only": 1
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
} }
], ],
"has_web_view": 0,
"hide_heading": 0,
"hide_toolbar": 0,
"idx": 0,
"image_view": 0,
"in_create": 0,
"is_submittable": 0,
"issingle": 0,
"istable": 1, "istable": 1,
"max_attachments": 0, "links": [],
"modified": "2019-06-26 18:57:51.762345", "modified": "2022-11-17 10:26:18.302728",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Exchange Rate Revaluation Account", "name": "Exchange Rate Revaluation Account",
"name_case": "",
"owner": "Administrator", "owner": "Administrator",
"permissions": [], "permissions": [],
"quick_entry": 1, "quick_entry": 1,
"read_only": 0,
"read_only_onload": 0,
"show_name_in_global_search": 0,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"track_changes": 1, "states": [],
"track_seen": 0, "track_changes": 1
"track_views": 0
} }

View File

@@ -9,10 +9,6 @@ from frappe.model.document import Document
from frappe.utils import add_days, add_years, cstr, getdate from frappe.utils import add_days, add_years, cstr, getdate
class FiscalYearIncorrectDate(frappe.ValidationError):
pass
class FiscalYear(Document): class FiscalYear(Document):
@frappe.whitelist() @frappe.whitelist()
def set_as_default(self): def set_as_default(self):
@@ -53,23 +49,18 @@ class FiscalYear(Document):
) )
def validate_dates(self): def validate_dates(self):
self.validate_from_to_dates("year_start_date", "year_end_date")
if self.is_short_year: if self.is_short_year:
# Fiscal Year can be shorter than one year, in some jurisdictions # Fiscal Year can be shorter than one year, in some jurisdictions
# under certain circumstances. For example, in the USA and Germany. # under certain circumstances. For example, in the USA and Germany.
return return
if getdate(self.year_start_date) > getdate(self.year_end_date):
frappe.throw(
_("Fiscal Year Start Date should be one year earlier than Fiscal Year End Date"),
FiscalYearIncorrectDate,
)
date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1) date = getdate(self.year_start_date) + relativedelta(years=1) - relativedelta(days=1)
if getdate(self.year_end_date) != date: if getdate(self.year_end_date) != date:
frappe.throw( frappe.throw(
_("Fiscal Year End Date should be one year after Fiscal Year Start Date"), _("Fiscal Year End Date should be one year after Fiscal Year Start Date"),
FiscalYearIncorrectDate, frappe.exceptions.InvalidDates,
) )
def on_update(self): def on_update(self):
@@ -169,5 +160,6 @@ def auto_create_fiscal_year():
def get_from_and_to_date(fiscal_year): def get_from_and_to_date(fiscal_year):
fields = ["year_start_date as from_date", "year_end_date as to_date"] fields = ["year_start_date", "year_end_date"]
return frappe.db.get_value("Fiscal Year", fiscal_year, fields, as_dict=1) cached_results = frappe.get_cached_value("Fiscal Year", fiscal_year, fields, as_dict=1)
return dict(from_date=cached_results.year_start_date, to_date=cached_results.year_end_date)

View File

@@ -7,8 +7,6 @@ import unittest
import frappe import frappe
from frappe.utils import now_datetime from frappe.utils import now_datetime
from erpnext.accounts.doctype.fiscal_year.fiscal_year import FiscalYearIncorrectDate
test_ignore = ["Company"] test_ignore = ["Company"]
@@ -26,7 +24,7 @@ class TestFiscalYear(unittest.TestCase):
} }
) )
self.assertRaises(FiscalYearIncorrectDate, fy.insert) self.assertRaises(frappe.exceptions.InvalidDates, fy.insert)
def test_record_generator(): def test_record_generator():
@@ -35,8 +33,8 @@ def test_record_generator():
"doctype": "Fiscal Year", "doctype": "Fiscal Year",
"year": "_Test Short Fiscal Year 2011", "year": "_Test Short Fiscal Year 2011",
"is_short_year": 1, "is_short_year": 1,
"year_end_date": "2011-04-01", "year_start_date": "2011-04-01",
"year_start_date": "2011-12-31", "year_end_date": "2011-12-31",
} }
] ]

View File

@@ -58,7 +58,7 @@ class GLEntry(Document):
validate_balance_type(self.account, adv_adj) validate_balance_type(self.account, adv_adj)
validate_frozen_account(self.account, adv_adj) validate_frozen_account(self.account, adv_adj)
if frappe.db.get_value("Account", self.account, "account_type") not in [ if frappe.get_cached_value("Account", self.account, "account_type") not in [
"Receivable", "Receivable",
"Payable", "Payable",
]: ]:
@@ -120,7 +120,7 @@ class GLEntry(Document):
frappe.throw(msg, title=_("Missing Cost Center")) frappe.throw(msg, title=_("Missing Cost Center"))
def validate_dimensions_for_pl_and_bs(self): def validate_dimensions_for_pl_and_bs(self):
account_type = frappe.db.get_value("Account", self.account, "report_type") account_type = frappe.get_cached_value("Account", self.account, "report_type")
for dimension in get_checks_for_pl_and_bs_accounts(): for dimension in get_checks_for_pl_and_bs_accounts():
if ( if (
@@ -188,7 +188,7 @@ class GLEntry(Document):
def check_pl_account(self): def check_pl_account(self):
if ( if (
self.is_opening == "Yes" self.is_opening == "Yes"
and frappe.db.get_value("Account", self.account, "report_type") == "Profit and Loss" and frappe.get_cached_value("Account", self.account, "report_type") == "Profit and Loss"
and not self.is_cancelled and not self.is_cancelled
): ):
frappe.throw( frappe.throw(
@@ -281,7 +281,7 @@ class GLEntry(Document):
def validate_balance_type(account, adv_adj=False): def validate_balance_type(account, adv_adj=False):
if not adv_adj and account: if not adv_adj and account:
balance_must_be = frappe.db.get_value("Account", account, "balance_must_be") balance_must_be = frappe.get_cached_value("Account", account, "balance_must_be")
if balance_must_be: if balance_must_be:
balance = frappe.db.sql( balance = frappe.db.sql(
"""select sum(debit) - sum(credit) """select sum(debit) - sum(credit)

View File

@@ -21,7 +21,7 @@ class ItemTaxTemplate(Document):
check_list = [] check_list = []
for d in self.get("taxes"): for d in self.get("taxes"):
if d.tax_type: if d.tax_type:
account_type = frappe.db.get_value("Account", d.tax_type, "account_type") account_type = frappe.get_cached_value("Account", d.tax_type, "account_type")
if account_type not in [ if account_type not in [
"Tax", "Tax",

View File

@@ -253,9 +253,6 @@ erpnext.accounts.JournalEntry = class JournalEntry extends frappe.ui.form.Contro
var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to"; var party_account_field = jvd.reference_type==="Sales Invoice" ? "debit_to": "credit_to";
out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]); out.filters.push([jvd.reference_type, party_account_field, "=", jvd.account]);
if (in_list(['Debit Note', 'Credit Note'], doc.voucher_type)) {
out.filters.push([jvd.reference_type, "is_return", "=", 1]);
}
} }
if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) { if(in_list(["Sales Order", "Purchase Order"], jvd.reference_type)) {

View File

@@ -37,9 +37,6 @@ class JournalEntry(AccountsController):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(JournalEntry, self).__init__(*args, **kwargs) super(JournalEntry, self).__init__(*args, **kwargs)
def get_feed(self):
return self.voucher_type
def validate(self): def validate(self):
if self.voucher_type == "Opening Entry": if self.voucher_type == "Opening Entry":
self.is_opening = "Yes" self.is_opening = "Yes"
@@ -325,7 +322,7 @@ class JournalEntry(AccountsController):
def validate_party(self): def validate_party(self):
for d in self.get("accounts"): for d in self.get("accounts"):
account_type = frappe.db.get_value("Account", d.account, "account_type") account_type = frappe.get_cached_value("Account", d.account, "account_type")
if account_type in ["Receivable", "Payable"]: if account_type in ["Receivable", "Payable"]:
if not (d.party_type and d.party): if not (d.party_type and d.party):
frappe.throw( frappe.throw(
@@ -388,7 +385,7 @@ class JournalEntry(AccountsController):
def validate_against_jv(self): def validate_against_jv(self):
for d in self.get("accounts"): for d in self.get("accounts"):
if d.reference_type == "Journal Entry": if d.reference_type == "Journal Entry":
account_root_type = frappe.db.get_value("Account", d.account, "root_type") account_root_type = frappe.get_cached_value("Account", d.account, "root_type")
if account_root_type == "Asset" and flt(d.debit) > 0: if account_root_type == "Asset" and flt(d.debit) > 0:
frappe.throw( frappe.throw(
_( _(
@@ -637,7 +634,7 @@ class JournalEntry(AccountsController):
def validate_multi_currency(self): def validate_multi_currency(self):
alternate_currency = [] alternate_currency = []
for d in self.get("accounts"): for d in self.get("accounts"):
account = frappe.db.get_value( account = frappe.get_cached_value(
"Account", d.account, ["account_currency", "account_type"], as_dict=1 "Account", d.account, ["account_currency", "account_type"], as_dict=1
) )
if account: if account:
@@ -768,7 +765,7 @@ class JournalEntry(AccountsController):
party_amount += d.debit_in_account_currency or d.credit_in_account_currency party_amount += d.debit_in_account_currency or d.credit_in_account_currency
party_account_currency = d.account_currency party_account_currency = d.account_currency
elif frappe.db.get_value("Account", d.account, "account_type") in ["Bank", "Cash"]: elif frappe.get_cached_value("Account", d.account, "account_type") in ["Bank", "Cash"]:
bank_amount += d.debit_in_account_currency or d.credit_in_account_currency bank_amount += d.debit_in_account_currency or d.credit_in_account_currency
bank_account_currency = d.account_currency bank_account_currency = d.account_currency
@@ -993,7 +990,7 @@ def get_default_bank_cash_account(company, account_type=None, mode_of_payment=No
account = account_list[0].name account = account_list[0].name
if account: if account:
account_details = frappe.db.get_value( account_details = frappe.get_cached_value(
"Account", account, ["account_currency", "account_type"], as_dict=1 "Account", account, ["account_currency", "account_type"], as_dict=1
) )
@@ -1122,7 +1119,7 @@ def get_payment_entry(ref_doc, args):
"party_type": args.get("party_type"), "party_type": args.get("party_type"),
"party": ref_doc.get(args.get("party_type").lower()), "party": ref_doc.get(args.get("party_type").lower()),
"cost_center": cost_center, "cost_center": cost_center,
"account_type": frappe.db.get_value("Account", args.get("party_account"), "account_type"), "account_type": frappe.get_cached_value("Account", args.get("party_account"), "account_type"),
"account_currency": args.get("party_account_currency") "account_currency": args.get("party_account_currency")
or get_account_currency(args.get("party_account")), or get_account_currency(args.get("party_account")),
"balance": get_balance_on(args.get("party_account")), "balance": get_balance_on(args.get("party_account")),
@@ -1289,7 +1286,7 @@ def get_party_account_and_balance(company, party_type, party, cost_center=None):
"account": account, "account": account,
"balance": account_balance, "balance": account_balance,
"party_balance": party_balance, "party_balance": party_balance,
"account_currency": frappe.db.get_value("Account", account, "account_currency"), "account_currency": frappe.get_cached_value("Account", account, "account_currency"),
} }
@@ -1302,7 +1299,7 @@ def get_account_balance_and_party_type(
frappe.msgprint(_("No Permission"), raise_exception=1) frappe.msgprint(_("No Permission"), raise_exception=1)
company_currency = erpnext.get_company_currency(company) company_currency = erpnext.get_company_currency(company)
account_details = frappe.db.get_value( account_details = frappe.get_cached_value(
"Account", account, ["account_type", "account_currency"], as_dict=1 "Account", account, ["account_type", "account_currency"], as_dict=1
) )
@@ -1355,7 +1352,7 @@ def get_exchange_rate(
): ):
from erpnext.setup.utils import get_exchange_rate from erpnext.setup.utils import get_exchange_rate
account_details = frappe.db.get_value( account_details = frappe.get_cached_value(
"Account", account, ["account_type", "root_type", "account_currency", "company"], as_dict=1 "Account", account, ["account_type", "root_type", "account_currency", "company"], as_dict=1
) )

View File

@@ -25,7 +25,7 @@ class ModeofPayment(Document):
def validate_accounts(self): def validate_accounts(self):
for entry in self.accounts: for entry in self.accounts:
"""Error when Company of Ledger account doesn't match with Company Selected""" """Error when Company of Ledger account doesn't match with Company Selected"""
if frappe.db.get_value("Account", entry.default_account, "company") != entry.company: if frappe.get_cached_value("Account", entry.default_account, "company") != entry.company:
frappe.throw( frappe.throw(
_("Account {0} does not match with Company {1} in Mode of Account: {2}").format( _("Account {0} does not match with Company {1} in Mode of Account: {2}").format(
entry.default_account, entry.company, self.name entry.default_account, entry.company, self.name

View File

@@ -20,7 +20,6 @@ frappe.ui.form.on('Opening Invoice Creation Tool', {
frm.dashboard.reset(); frm.dashboard.reset();
frm.doc.import_in_progress = true; frm.doc.import_in_progress = true;
} }
if (data.user != frappe.session.user) return;
if (data.count == data.total) { if (data.count == data.total) {
setTimeout(() => { setTimeout(() => {
frm.doc.import_in_progress = false; frm.doc.import_in_progress = false;

View File

@@ -260,10 +260,10 @@ def publish(index, total, doctype):
dict( dict(
title=_("Opening Invoice Creation In Progress"), title=_("Opening Invoice Creation In Progress"),
message=_("Creating {} out of {} {}").format(index + 1, total, doctype), message=_("Creating {} out of {} {}").format(index + 1, total, doctype),
user=frappe.session.user,
count=index + 1, count=index + 1,
total=total, total=total,
), ),
user=frappe.session.user,
) )

View File

@@ -725,7 +725,7 @@ class PaymentEntry(AccountsController):
def validate_transaction_reference(self): def validate_transaction_reference(self):
bank_account = self.paid_to if self.payment_type == "Receive" else self.paid_from bank_account = self.paid_to if self.payment_type == "Receive" else self.paid_from
bank_account_type = frappe.db.get_value("Account", bank_account, "account_type") bank_account_type = frappe.get_cached_value("Account", bank_account, "account_type")
if bank_account_type == "Bank": if bank_account_type == "Bank":
if not self.reference_no or not self.reference_date: if not self.reference_no or not self.reference_date:
@@ -1303,7 +1303,7 @@ def split_invoices_based_on_payment_terms(outstanding_invoices):
d.voucher_type, d.voucher_no, "payment_terms_template" d.voucher_type, d.voucher_no, "payment_terms_template"
) )
if payment_term_template: if payment_term_template:
allocate_payment_based_on_payment_terms = frappe.db.get_value( allocate_payment_based_on_payment_terms = frappe.get_cached_value(
"Payment Terms Template", payment_term_template, "allocate_payment_based_on_payment_terms" "Payment Terms Template", payment_term_template, "allocate_payment_based_on_payment_terms"
) )
if allocate_payment_based_on_payment_terms: if allocate_payment_based_on_payment_terms:
@@ -1535,7 +1535,7 @@ def get_account_details(account, date, cost_center=None):
{ {
"account_currency": get_account_currency(account), "account_currency": get_account_currency(account),
"account_balance": account_balance, "account_balance": account_balance,
"account_type": frappe.db.get_value("Account", account, "account_type"), "account_type": frappe.get_cached_value("Account", account, "account_type"),
} }
) )
@@ -1704,9 +1704,9 @@ def get_payment_entry(
if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked(): if doc.doctype == "Purchase Invoice" and doc.invoice_is_blocked():
frappe.msgprint(_("{0} is on hold till {1}").format(doc.name, doc.release_date)) frappe.msgprint(_("{0} is on hold till {1}").format(doc.name, doc.release_date))
else: else:
if doc.doctype in ("Sales Invoice", "Purchase Invoice") and frappe.get_value( if doc.doctype in ("Sales Invoice", "Purchase Invoice") and frappe.get_cached_value(
"Payment Terms Template", "Payment Terms Template",
{"name": doc.payment_terms_template}, doc.payment_terms_template,
"allocate_payment_based_on_payment_terms", "allocate_payment_based_on_payment_terms",
): ):

View File

@@ -25,7 +25,8 @@
"in_list_view": 1, "in_list_view": 1,
"label": "Type", "label": "Type",
"options": "DocType", "options": "DocType",
"reqd": 1 "reqd": 1,
"search_index": 1
}, },
{ {
"columns": 2, "columns": 2,
@@ -35,7 +36,8 @@
"in_list_view": 1, "in_list_view": 1,
"label": "Name", "label": "Name",
"options": "reference_doctype", "options": "reference_doctype",
"reqd": 1 "reqd": 1,
"search_index": 1
}, },
{ {
"fieldname": "due_date", "fieldname": "due_date",
@@ -104,7 +106,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2021-09-26 17:06:55.597389", "modified": "2022-12-12 12:31:44.919895",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Payment Entry Reference", "name": "Payment Entry Reference",
@@ -113,5 +115,6 @@
"quick_entry": 1, "quick_entry": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC", "sort_order": "DESC",
"states": [],
"track_changes": 1 "track_changes": 1
} }

View File

@@ -3,6 +3,7 @@
frappe.ui.form.on('Payment Gateway Account', { frappe.ui.form.on('Payment Gateway Account', {
refresh(frm) { refresh(frm) {
erpnext.utils.check_payments_app();
if(!frm.doc.__islocal) { if(!frm.doc.__islocal) {
frm.set_df_property('payment_gateway', 'read_only', 1); frm.set_df_property('payment_gateway', 'read_only', 1);
} }

View File

@@ -11,7 +11,7 @@ class PaymentGatewayAccount(Document):
self.name = self.payment_gateway + " - " + self.currency self.name = self.payment_gateway + " - " + self.currency
def validate(self): def validate(self):
self.currency = frappe.db.get_value("Account", self.payment_account, "account_currency") self.currency = frappe.get_cached_value("Account", self.payment_account, "account_currency")
self.update_default_payment_gateway() self.update_default_payment_gateway()
self.set_as_default_if_not_set() self.set_as_default_if_not_set()

View File

@@ -97,7 +97,7 @@ class PaymentLedgerEntry(Document):
) )
def validate_dimensions_for_pl_and_bs(self): def validate_dimensions_for_pl_and_bs(self):
account_type = frappe.db.get_value("Account", self.account, "report_type") account_type = frappe.get_cached_value("Account", self.account, "report_type")
for dimension in get_checks_for_pl_and_bs_accounts(): for dimension in get_checks_for_pl_and_bs_accounts():
if ( if (

View File

@@ -9,7 +9,6 @@ from frappe import _
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import flt, get_url, nowdate from frappe.utils import flt, get_url, nowdate
from frappe.utils.background_jobs import enqueue from frappe.utils.background_jobs import enqueue
from payments.utils import get_payment_gateway_controller
from erpnext.accounts.doctype.payment_entry.payment_entry import ( from erpnext.accounts.doctype.payment_entry.payment_entry import (
get_company_defaults, get_company_defaults,
@@ -19,6 +18,14 @@ from erpnext.accounts.doctype.subscription_plan.subscription_plan import get_pla
from erpnext.accounts.party import get_party_account, get_party_bank_account from erpnext.accounts.party import get_party_account, get_party_bank_account
from erpnext.accounts.utils import get_account_currency from erpnext.accounts.utils import get_account_currency
from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription from erpnext.erpnext_integrations.stripe_integration import create_stripe_subscription
from erpnext.utilities import payment_app_import_guard
def _get_payment_gateway_controller(*args, **kwargs):
with payment_app_import_guard():
from payments.utils import get_payment_gateway_controller
return get_payment_gateway_controller(*args, **kwargs)
class PaymentRequest(Document): class PaymentRequest(Document):
@@ -53,7 +60,7 @@ class PaymentRequest(Document):
def validate_currency(self): def validate_currency(self):
ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name) ref_doc = frappe.get_doc(self.reference_doctype, self.reference_name)
if self.payment_account and ref_doc.currency != frappe.db.get_value( if self.payment_account and ref_doc.currency != frappe.get_cached_value(
"Account", self.payment_account, "account_currency" "Account", self.payment_account, "account_currency"
): ):
frappe.throw(_("Transaction currency must be same as Payment Gateway currency")) frappe.throw(_("Transaction currency must be same as Payment Gateway currency"))
@@ -107,7 +114,7 @@ class PaymentRequest(Document):
self.request_phone_payment() self.request_phone_payment()
def request_phone_payment(self): def request_phone_payment(self):
controller = get_payment_gateway_controller(self.payment_gateway) controller = _get_payment_gateway_controller(self.payment_gateway)
request_amount = self.get_request_amount() request_amount = self.get_request_amount()
payment_record = dict( payment_record = dict(
@@ -156,7 +163,7 @@ class PaymentRequest(Document):
def payment_gateway_validation(self): def payment_gateway_validation(self):
try: try:
controller = get_payment_gateway_controller(self.payment_gateway) controller = _get_payment_gateway_controller(self.payment_gateway)
if hasattr(controller, "on_payment_request_submission"): if hasattr(controller, "on_payment_request_submission"):
return controller.on_payment_request_submission(self) return controller.on_payment_request_submission(self)
else: else:
@@ -189,7 +196,7 @@ class PaymentRequest(Document):
) )
data.update({"company": frappe.defaults.get_defaults().company}) data.update({"company": frappe.defaults.get_defaults().company})
controller = get_payment_gateway_controller(self.payment_gateway) controller = _get_payment_gateway_controller(self.payment_gateway)
controller.validate_transaction_currency(self.currency) controller.validate_transaction_currency(self.currency)
if hasattr(controller, "validate_minimum_transaction_amount"): if hasattr(controller, "validate_minimum_transaction_amount"):

View File

@@ -43,7 +43,7 @@ class PeriodClosingVoucher(AccountsController):
make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name) make_reverse_gl_entries(voucher_type="Period Closing Voucher", voucher_no=self.name)
def validate_account_head(self): def validate_account_head(self):
closing_account_type = frappe.db.get_value("Account", self.closing_account_head, "root_type") closing_account_type = frappe.get_cached_value("Account", self.closing_account_head, "root_type")
if closing_account_type not in ["Liability", "Equity"]: if closing_account_type not in ["Liability", "Equity"]:
frappe.throw( frappe.throw(

View File

@@ -25,7 +25,7 @@ frappe.ui.form.on('POS Closing Entry', {
frappe.realtime.on('closing_process_complete', async function(data) { frappe.realtime.on('closing_process_complete', async function(data) {
await frm.reload_doc(); await frm.reload_doc();
if (frm.doc.status == 'Failed' && frm.doc.error_message && data.user == frappe.session.user) { if (frm.doc.status == 'Failed' && frm.doc.error_message) {
frappe.msgprint({ frappe.msgprint({
title: __('POS Closing Failed'), title: __('POS Closing Failed'),
message: frm.doc.error_message, message: frm.doc.error_message,

View File

@@ -5,6 +5,8 @@
frappe.provide("erpnext.accounts"); frappe.provide("erpnext.accounts");
erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnext.selling.SellingController { erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnext.selling.SellingController {
settings = {};
setup(doc) { setup(doc) {
this.setup_posting_date_time_check(); this.setup_posting_date_time_check();
super.setup(doc); super.setup(doc);
@@ -12,21 +14,37 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
company() { company() {
erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype); erpnext.accounts.dimensions.update_dimension(this.frm, this.frm.doctype);
this.frm.set_value("set_warehouse", "");
this.frm.set_value("taxes_and_charges", "");
} }
onload(doc) { onload(doc) {
super.onload(); super.onload();
this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry']; this.frm.ignore_doctypes_on_cancel_all = ['POS Invoice Merge Log', 'POS Closing Entry'];
if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') { if(doc.__islocal && doc.is_pos && frappe.get_route_str() !== 'point-of-sale') {
this.frm.script_manager.trigger("is_pos"); this.frm.script_manager.trigger("is_pos");
this.frm.refresh_fields(); this.frm.refresh_fields();
} }
this.frm.set_query("set_warehouse", function(doc) {
return {
filters: {
company: doc.company ? doc.company : '',
}
}
});
erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype); erpnext.accounts.dimensions.setup_dimension_filters(this.frm, this.frm.doctype);
} }
onload_post_render(frm) {
this.pos_profile(frm);
}
refresh(doc) { refresh(doc) {
super.refresh(); super.refresh();
if (doc.docstatus == 1 && !doc.is_return) { if (doc.docstatus == 1 && !doc.is_return) {
this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create')); this.frm.add_custom_button(__('Return'), this.make_sales_return, __('Create'));
this.frm.page.set_inner_btn_group_as_primary(__('Create')); this.frm.page.set_inner_btn_group_as_primary(__('Create'));
@@ -36,6 +54,18 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
this.frm.return_print_format = "Sales Invoice Return"; this.frm.return_print_format = "Sales Invoice Return";
this.frm.set_value('consolidated_invoice', ''); this.frm.set_value('consolidated_invoice', '');
} }
this.frm.set_query("customer", (function () {
const customer_groups = this.settings?.customer_groups;
if (!customer_groups?.length) return {};
return {
filters: {
customer_group: ["in", customer_groups],
}
}
}).bind(this));
} }
is_pos() { is_pos() {
@@ -88,6 +118,25 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}); });
} }
pos_profile(frm) {
if (!frm.pos_profile || frm.pos_profile == '') {
this.update_customer_groups_settings([]);
return;
}
frappe.call({
method: "erpnext.selling.page.point_of_sale.point_of_sale.get_pos_profile_data",
args: { "pos_profile": frm.pos_profile },
callback: ({ message: profile }) => {
this.update_customer_groups_settings(profile?.customer_groups);
},
});
}
update_customer_groups_settings(customer_groups) {
this.settings.customer_groups = customer_groups?.map((group) => group.name)
}
amount(){ amount(){
this.write_off_outstanding_amount_automatically() this.write_off_outstanding_amount_automatically()
} }

View File

@@ -335,7 +335,8 @@ class POSInvoice(SalesInvoice):
if ( if (
self.change_amount self.change_amount
and self.account_for_change_amount and self.account_for_change_amount
and frappe.db.get_value("Account", self.account_for_change_amount, "company") != self.company and frappe.get_cached_value("Account", self.account_for_change_amount, "company")
!= self.company
): ):
frappe.throw( frappe.throw(
_("The selected change account {} doesn't belongs to Company {}.").format( _("The selected change account {} doesn't belongs to Company {}.").format(
@@ -486,7 +487,7 @@ class POSInvoice(SalesInvoice):
customer_price_list, customer_group, customer_currency = frappe.db.get_value( customer_price_list, customer_group, customer_currency = frappe.db.get_value(
"Customer", self.customer, ["default_price_list", "customer_group", "default_currency"] "Customer", self.customer, ["default_price_list", "customer_group", "default_currency"]
) )
customer_group_price_list = frappe.db.get_value( customer_group_price_list = frappe.get_cached_value(
"Customer Group", customer_group, "default_price_list" "Customer Group", customer_group, "default_price_list"
) )
selling_price_list = ( selling_price_list = (
@@ -532,8 +533,8 @@ class POSInvoice(SalesInvoice):
if not self.debit_to: if not self.debit_to:
self.debit_to = get_party_account("Customer", self.customer, self.company) self.debit_to = get_party_account("Customer", self.customer, self.company)
self.party_account_currency = frappe.db.get_value( self.party_account_currency = frappe.get_cached_value(
"Account", self.debit_to, "account_currency", cache=True "Account", self.debit_to, "account_currency"
) )
if not self.due_date and self.customer: if not self.due_date and self.customer:
self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company) self.due_date = get_due_date(self.posting_date, "Customer", self.customer, self.company)

View File

@@ -430,7 +430,7 @@ def create_merge_logs(invoice_by_customer, closing_entry=None):
finally: finally:
frappe.db.commit() frappe.db.commit()
frappe.publish_realtime("closing_process_complete", {"user": frappe.session.user}) frappe.publish_realtime("closing_process_complete", user=frappe.session.user)
def cancel_merge_logs(merge_logs, closing_entry=None): def cancel_merge_logs(merge_logs, closing_entry=None):
@@ -457,7 +457,7 @@ def cancel_merge_logs(merge_logs, closing_entry=None):
finally: finally:
frappe.db.commit() frappe.db.commit()
frappe.publish_realtime("closing_process_complete", {"user": frappe.session.user}) frappe.publish_realtime("closing_process_complete", user=frappe.session.user)
def enqueue_job(job, **kwargs): def enqueue_job(job, **kwargs):

View File

@@ -10,7 +10,7 @@ import re
import frappe import frappe
from frappe import _, throw from frappe import _, throw
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import cint, flt, getdate from frappe.utils import cint, flt
apply_on_dict = {"Item Code": "items", "Item Group": "item_groups", "Brand": "brands"} apply_on_dict = {"Item Code": "items", "Item Group": "item_groups", "Brand": "brands"}
@@ -184,8 +184,7 @@ class PricingRule(Document):
if self.is_cumulative and not (self.valid_from and self.valid_upto): if self.is_cumulative and not (self.valid_from and self.valid_upto):
frappe.throw(_("Valid from and valid upto fields are mandatory for the cumulative")) frappe.throw(_("Valid from and valid upto fields are mandatory for the cumulative"))
if self.valid_from and self.valid_upto and getdate(self.valid_from) > getdate(self.valid_upto): self.validate_from_to_dates("valid_from", "valid_upto")
frappe.throw(_("Valid from date must be less than valid upto date"))
def validate_condition(self): def validate_condition(self):
if ( if (
@@ -256,7 +255,7 @@ def apply_pricing_rule(args, doc=None):
for item in item_list: for item in item_list:
args_copy = copy.deepcopy(args) args_copy = copy.deepcopy(args)
args_copy.update(item) args_copy.update(item)
data = get_pricing_rule_for_item(args_copy, item.get("price_list_rate"), doc=doc) data = get_pricing_rule_for_item(args_copy, doc=doc)
out.append(data) out.append(data)
if ( if (
@@ -293,7 +292,7 @@ def update_pricing_rule_uom(pricing_rule, args):
pricing_rule.uom = row.uom pricing_rule.uom = row.uom
def get_pricing_rule_for_item(args, price_list_rate=0, doc=None, for_validate=False): def get_pricing_rule_for_item(args, doc=None, for_validate=False):
from erpnext.accounts.doctype.pricing_rule.utils import ( from erpnext.accounts.doctype.pricing_rule.utils import (
get_applied_pricing_rules, get_applied_pricing_rules,
get_pricing_rule_items, get_pricing_rule_items,

View File

@@ -1123,7 +1123,7 @@ def make_pricing_rule(**args):
"apply_on": args.apply_on or "Item Code", "apply_on": args.apply_on or "Item Code",
"applicable_for": args.applicable_for, "applicable_for": args.applicable_for,
"selling": args.selling or 0, "selling": args.selling or 0,
"currency": "USD", "currency": "INR",
"apply_discount_on_rate": args.apply_discount_on_rate or 0, "apply_discount_on_rate": args.apply_discount_on_rate or 0,
"buying": args.buying or 0, "buying": args.buying or 0,
"min_qty": args.min_qty or 0.0, "min_qty": args.min_qty or 0.0,

View File

@@ -250,6 +250,17 @@ def get_other_conditions(conditions, values, args):
and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')""" and ifnull(`tabPricing Rule`.valid_upto, '2500-12-31')"""
values["transaction_date"] = args.get("transaction_date") values["transaction_date"] = args.get("transaction_date")
if args.get("doctype") in [
"Quotation",
"Sales Order",
"Delivery Note",
"Sales Invoice",
"POS Invoice",
]:
conditions += """ and ifnull(`tabPricing Rule`.selling, 0) = 1"""
else:
conditions += """ and ifnull(`tabPricing Rule`.buying, 0) = 1"""
return conditions return conditions
@@ -669,7 +680,7 @@ def get_product_discount_rule(pricing_rule, item_details, args=None, doc=None):
item_details.free_item_data.append(free_item_data_args) item_details.free_item_data.append(free_item_data_args)
def apply_pricing_rule_for_free_items(doc, pricing_rule_args, set_missing_values=False): def apply_pricing_rule_for_free_items(doc, pricing_rule_args):
if pricing_rule_args: if pricing_rule_args:
items = tuple((d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item) items = tuple((d.item_code, d.pricing_rules) for d in doc.items if d.is_free_item)

View File

@@ -81,7 +81,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
} }
if(doc.docstatus == 1 && doc.outstanding_amount != 0 if(doc.docstatus == 1 && doc.outstanding_amount != 0
&& !(doc.is_return && doc.return_against)) { && !(doc.is_return && doc.return_against) && !doc.on_hold) {
this.frm.add_custom_button(__('Payment'), this.make_payment_entry, __('Create')); this.frm.add_custom_button(__('Payment'), this.make_payment_entry, __('Create'));
cur_frm.page.set_inner_btn_group_as_primary(__('Create')); cur_frm.page.set_inner_btn_group_as_primary(__('Create'));
} }
@@ -99,7 +99,7 @@ erpnext.accounts.PurchaseInvoice = class PurchaseInvoice extends erpnext.buying.
} }
} }
if (doc.outstanding_amount > 0 && !cint(doc.is_return)) { if (doc.outstanding_amount > 0 && !cint(doc.is_return) && !doc.on_hold) {
cur_frm.add_custom_button(__('Payment Request'), function() { cur_frm.add_custom_button(__('Payment Request'), function() {
me.make_payment_request() me.make_payment_request()
}, __('Create')); }, __('Create'));

View File

@@ -25,6 +25,10 @@
"apply_tds", "apply_tds",
"tax_withholding_category", "tax_withholding_category",
"amended_from", "amended_from",
"supplier_invoice_details",
"bill_no",
"column_break_15",
"bill_date",
"accounting_dimensions_section", "accounting_dimensions_section",
"cost_center", "cost_center",
"dimension_col_break", "dimension_col_break",
@@ -65,6 +69,7 @@
"tax_category", "tax_category",
"column_break_49", "column_break_49",
"shipping_rule", "shipping_rule",
"incoterm",
"section_break_51", "section_break_51",
"taxes", "taxes",
"totals", "totals",
@@ -151,10 +156,6 @@
"status", "status",
"column_break_177", "column_break_177",
"per_received", "per_received",
"supplier_invoice_details",
"bill_no",
"column_break_15",
"bill_date",
"accounting_details_section", "accounting_details_section",
"credit_to", "credit_to",
"party_account_currency", "party_account_currency",
@@ -1534,13 +1535,19 @@
"oldfieldtype": "Section Break", "oldfieldtype": "Section Break",
"options": "fa fa-file-text", "options": "fa fa-file-text",
"print_hide": 1 "print_hide": 1
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
"label": "Incoterm",
"options": "Incoterm"
} }
], ],
"icon": "fa fa-file-text", "icon": "fa fa-file-text",
"idx": 204, "idx": 204,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-11-04 01:02:44.544878", "modified": "2022-11-25 12:44:29.935567",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice", "name": "Purchase Invoice",

View File

@@ -153,8 +153,8 @@ class PurchaseInvoice(BuyingController):
def set_missing_values(self, for_validate=False): def set_missing_values(self, for_validate=False):
if not self.credit_to: if not self.credit_to:
self.credit_to = get_party_account("Supplier", self.supplier, self.company) self.credit_to = get_party_account("Supplier", self.supplier, self.company)
self.party_account_currency = frappe.db.get_value( self.party_account_currency = frappe.get_cached_value(
"Account", self.credit_to, "account_currency", cache=True "Account", self.credit_to, "account_currency"
) )
if not self.due_date: if not self.due_date:
self.due_date = get_due_date( self.due_date = get_due_date(
@@ -175,7 +175,7 @@ class PurchaseInvoice(BuyingController):
if not self.credit_to: if not self.credit_to:
self.raise_missing_debit_credit_account_error("Supplier", self.supplier) self.raise_missing_debit_credit_account_error("Supplier", self.supplier)
account = frappe.db.get_value( account = frappe.get_cached_value(
"Account", self.credit_to, ["account_type", "report_type", "account_currency"], as_dict=True "Account", self.credit_to, ["account_type", "report_type", "account_currency"], as_dict=True
) )
@@ -231,7 +231,9 @@ class PurchaseInvoice(BuyingController):
) )
if ( if (
cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate")) and not self.is_return cint(frappe.db.get_single_value("Buying Settings", "maintain_same_rate"))
and not self.is_return
and not self.is_internal_supplier
): ):
self.validate_rate_with_reference_doc( self.validate_rate_with_reference_doc(
[ [
@@ -606,7 +608,7 @@ class PurchaseInvoice(BuyingController):
def make_supplier_gl_entry(self, gl_entries): def make_supplier_gl_entry(self, gl_entries):
# Checked both rounding_adjustment and rounded_total # Checked both rounding_adjustment and rounded_total
# because rounded_total had value even before introcution of posting GLE based on rounded total # because rounded_total had value even before introduction of posting GLE based on rounded total
grand_total = ( grand_total = (
self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total self.rounded_total if (self.rounding_adjustment and self.rounded_total) else self.grand_total
) )
@@ -673,7 +675,7 @@ class PurchaseInvoice(BuyingController):
exchange_rate_map, net_rate_map = get_purchase_document_details(self) exchange_rate_map, net_rate_map = get_purchase_document_details(self)
provisional_accounting_for_non_stock_items = cint( provisional_accounting_for_non_stock_items = cint(
frappe.db.get_value( frappe.get_cached_value(
"Company", self.company, "enable_provisional_accounting_for_non_stock_items" "Company", self.company, "enable_provisional_accounting_for_non_stock_items"
) )
) )
@@ -809,10 +811,7 @@ class PurchaseInvoice(BuyingController):
else item.deferred_expense_account else item.deferred_expense_account
) )
if not item.is_fixed_asset: dummy, amount = self.get_amount_and_base_amount(item, None)
dummy, amount = self.get_amount_and_base_amount(item, None)
else:
amount = flt(item.base_net_amount + item.item_tax_amount, item.precision("base_net_amount"))
if provisional_accounting_for_non_stock_items: if provisional_accounting_for_non_stock_items:
if item.purchase_receipt: if item.purchase_receipt:
@@ -984,7 +983,7 @@ class PurchaseInvoice(BuyingController):
asset_amount = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate) asset_amount = flt(item.net_amount) + flt(item.item_tax_amount / self.conversion_rate)
base_asset_amount = flt(item.base_net_amount + item.item_tax_amount) base_asset_amount = flt(item.base_net_amount + item.item_tax_amount)
item_exp_acc_type = frappe.db.get_value("Account", item.expense_account, "account_type") item_exp_acc_type = frappe.get_cached_value("Account", item.expense_account, "account_type")
if not item.expense_account or item_exp_acc_type not in [ if not item.expense_account or item_exp_acc_type not in [
"Asset Received But Not Billed", "Asset Received But Not Billed",
"Fixed Asset", "Fixed Asset",

View File

@@ -63,7 +63,7 @@ frappe.listview_settings["Purchase Invoice"] = {
}); });
listview.page.add_action_item(__("Payment"), ()=>{ listview.page.add_action_item(__("Payment"), ()=>{
erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment"); erpnext.bulk_transaction_processing.create(listview, "Purchase Invoice", "Payment Entry");
}); });
} }
}; };

View File

@@ -40,7 +40,6 @@
"discount_amount", "discount_amount",
"base_rate_with_margin", "base_rate_with_margin",
"sec_break2", "sec_break2",
"apply_tds",
"rate", "rate",
"amount", "amount",
"item_tax_template", "item_tax_template",
@@ -50,6 +49,7 @@
"pricing_rules", "pricing_rules",
"stock_uom_rate", "stock_uom_rate",
"is_free_item", "is_free_item",
"apply_tds",
"section_break_22", "section_break_22",
"net_rate", "net_rate",
"net_amount", "net_amount",
@@ -871,16 +871,16 @@
"read_only": 1 "read_only": 1
}, },
{ {
"default": "1", "default": "1",
"fieldname": "apply_tds", "fieldname": "apply_tds",
"fieldtype": "Check", "fieldtype": "Check",
"label": "Apply TDS" "label": "Apply TDS"
} }
], ],
"idx": 1, "idx": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2022-10-26 16:05:37.304788", "modified": "2022-11-29 13:01:20.438217",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Purchase Invoice Item", "name": "Purchase Invoice Item",

View File

@@ -64,6 +64,7 @@
"taxes_and_charges", "taxes_and_charges",
"column_break_38", "column_break_38",
"shipping_rule", "shipping_rule",
"incoterm",
"column_break_55", "column_break_55",
"tax_category", "tax_category",
"section_break_40", "section_break_40",
@@ -920,6 +921,7 @@
"fieldtype": "Table", "fieldtype": "Table",
"hide_days": 1, "hide_days": 1,
"hide_seconds": 1, "hide_seconds": 1,
"label": "Sales Taxes and Charges",
"oldfieldname": "other_charges", "oldfieldname": "other_charges",
"oldfieldtype": "Table", "oldfieldtype": "Table",
"options": "Sales Taxes and Charges" "options": "Sales Taxes and Charges"
@@ -2114,6 +2116,12 @@
"label": "Repost Required", "label": "Repost Required",
"no_copy": 1, "no_copy": 1,
"read_only": 1 "read_only": 1
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
"label": "Incoterm",
"options": "Incoterm"
} }
], ],
"icon": "fa fa-file-text", "icon": "fa fa-file-text",
@@ -2126,7 +2134,7 @@
"link_fieldname": "consolidated_invoice" "link_fieldname": "consolidated_invoice"
} }
], ],
"modified": "2022-11-15 09:33:47.870616", "modified": "2022-12-05 16:18:14.532114",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Accounts", "module": "Accounts",
"name": "Sales Invoice", "name": "Sales Invoice",

View File

@@ -2170,6 +2170,8 @@ def make_inter_company_transaction(doctype, source_name, target_doc=None):
if source.doctype == "Purchase Order Item" and target.doctype == "Sales Order Item": if source.doctype == "Purchase Order Item" and target.doctype == "Sales Order Item":
target.purchase_order = source.parent target.purchase_order = source.parent
target.purchase_order_item = source.name target.purchase_order_item = source.name
target.material_request = source.material_request
target.material_request_item = source.material_request_item
if ( if (
source.get("purchase_order") source.get("purchase_order")

View File

@@ -29,7 +29,7 @@ frappe.listview_settings['Sales Invoice'] = {
}); });
listview.page.add_action_item(__("Payment"), ()=>{ listview.page.add_action_item(__("Payment"), ()=>{
erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Payment"); erpnext.bulk_transaction_processing.create(listview, "Sales Invoice", "Payment Entry");
}); });
} }
}; };

View File

@@ -27,7 +27,7 @@ class SalesTaxesandChargesTemplate(Document):
def set_missing_values(self): def set_missing_values(self):
for data in self.taxes: for data in self.taxes:
if data.charge_type == "On Net Total" and flt(data.rate) == 0.0: if data.charge_type == "On Net Total" and flt(data.rate) == 0.0:
data.rate = frappe.db.get_value("Account", data.account_head, "tax_rate") data.rate = frappe.get_cached_value("Account", data.account_head, "tax_rate")
def valdiate_taxes_and_charges_template(doc): def valdiate_taxes_and_charges_template(doc):

View File

@@ -5,5 +5,9 @@ frappe.ui.form.on('Subscription Plan', {
price_determination: function(frm) { price_determination: function(frm) {
frm.toggle_reqd("cost", frm.doc.price_determination === 'Fixed rate'); frm.toggle_reqd("cost", frm.doc.price_determination === 'Fixed rate');
frm.toggle_reqd("price_list", frm.doc.price_determination === 'Based on price list'); frm.toggle_reqd("price_list", frm.doc.price_determination === 'Based on price list');
} },
subscription_plan: function (frm) {
erpnext.utils.check_payments_app();
},
}); });

View File

@@ -32,7 +32,7 @@ class TaxRule(Document):
def validate(self): def validate(self):
self.validate_tax_template() self.validate_tax_template()
self.validate_date() self.validate_from_to_dates("from_date", "to_date")
self.validate_filters() self.validate_filters()
self.validate_use_for_shopping_cart() self.validate_use_for_shopping_cart()
@@ -51,10 +51,6 @@ class TaxRule(Document):
if not (self.sales_tax_template or self.purchase_tax_template): if not (self.sales_tax_template or self.purchase_tax_template):
frappe.throw(_("Tax Template is mandatory.")) frappe.throw(_("Tax Template is mandatory."))
def validate_date(self):
if self.from_date and self.to_date and self.from_date > self.to_date:
frappe.throw(_("From Date cannot be greater than To Date"))
def validate_filters(self): def validate_filters(self):
filters = { filters = {
"tax_type": self.tax_type, "tax_type": self.tax_type,

View File

@@ -226,6 +226,42 @@ class TestTaxWithholdingCategory(unittest.TestCase):
for d in reversed(invoices): for d in reversed(invoices):
d.cancel() d.cancel()
orders = []
po = create_purchase_order(supplier="Test TDS Supplier4", rate=20000, do_not_save=True)
po.extend(
"items",
[
{
"doctype": "Purchase Order Item",
"item_code": frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name"),
"qty": 1,
"rate": 20000,
"cost_center": "Main - _TC",
"expense_account": "Stock Received But Not Billed - _TC",
"apply_tds": 0,
},
{
"doctype": "Purchase Order Item",
"item_code": frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name"),
"qty": 1,
"rate": 35000,
"cost_center": "Main - _TC",
"expense_account": "Stock Received But Not Billed - _TC",
"apply_tds": 1,
},
],
)
po.save()
po.submit()
orders.append(po)
self.assertEqual(po.taxes[0].tax_amount, 5500)
# cancel orders to avoid clashing
for d in reversed(orders):
d.cancel()
def test_multi_category_single_supplier(self): def test_multi_category_single_supplier(self):
frappe.db.set_value( frappe.db.set_value(
"Supplier", "Test TDS Supplier5", "tax_withholding_category", "Test Service Category" "Supplier", "Test TDS Supplier5", "tax_withholding_category", "Test Service Category"
@@ -348,6 +384,39 @@ def create_purchase_invoice(**args):
return pi return pi
def create_purchase_order(**args):
# return purchase order doc object
item = frappe.db.get_value("Item", {"item_name": "TDS Item"}, "name")
args = frappe._dict(args)
po = frappe.get_doc(
{
"doctype": "Purchase Order",
"transaction_date": today(),
"schedule_date": today(),
"apply_tds": 0 if args.do_not_apply_tds else 1,
"supplier": args.supplier,
"company": "_Test Company",
"taxes_and_charges": "",
"currency": "INR",
"taxes": [],
"items": [
{
"doctype": "Purchase Order Item",
"item_code": item,
"qty": args.qty or 1,
"rate": args.rate or 10000,
"cost_center": "Main - _TC",
"expense_account": "Stock Received But Not Billed - _TC",
}
],
}
)
po.save()
return po
def create_sales_invoice(**args): def create_sales_invoice(**args):
# return sales invoice doc object # return sales invoice doc object
item = frappe.db.get_value("Item", {"item_name": "TCS Item"}, "name") item = frappe.db.get_value("Item", {"item_name": "TCS Item"}, "name")

View File

@@ -394,20 +394,22 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
round_off_account, round_off_cost_center = get_round_off_account_and_cost_center( round_off_account, round_off_cost_center = get_round_off_account_and_cost_center(
gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no gl_map[0].company, gl_map[0].voucher_type, gl_map[0].voucher_no
) )
round_off_account_exists = False
round_off_gle = frappe._dict() round_off_gle = frappe._dict()
for d in gl_map: round_off_account_exists = False
if d.account == round_off_account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit)
else:
debit_credit_diff += flt(d.credit)
round_off_account_exists = True
if round_off_account_exists and abs(debit_credit_diff) < (1.0 / (10**precision)): if gl_map[0].voucher_type != "Period Closing Voucher":
gl_map.remove(round_off_gle) for d in gl_map:
return if d.account == round_off_account:
round_off_gle = d
if d.debit:
debit_credit_diff -= flt(d.debit) - flt(d.credit)
else:
debit_credit_diff += flt(d.credit)
round_off_account_exists = True
if round_off_account_exists and abs(debit_credit_diff) < (1.0 / (10**precision)):
gl_map.remove(round_off_gle)
return
if not round_off_gle: if not round_off_gle:
for k in ["voucher_type", "voucher_no", "company", "posting_date", "remarks"]: for k in ["voucher_type", "voucher_no", "company", "posting_date", "remarks"]:
@@ -430,7 +432,6 @@ def make_round_off_gle(gl_map, debit_credit_diff, precision):
) )
update_accounting_dimensions(round_off_gle) update_accounting_dimensions(round_off_gle)
if not round_off_account_exists: if not round_off_account_exists:
gl_map.append(round_off_gle) gl_map.append(round_off_gle)

View File

@@ -296,7 +296,7 @@ def get_default_price_list(party):
return party.default_price_list return party.default_price_list
if party.doctype == "Customer": if party.doctype == "Customer":
return frappe.db.get_value("Customer Group", party.customer_group, "default_price_list") return frappe.get_cached_value("Customer Group", party.customer_group, "default_price_list")
def set_price_list(party_details, party, party_type, given_price_list, pos=None): def set_price_list(party_details, party, party_type, given_price_list, pos=None):
@@ -385,7 +385,7 @@ def get_party_account(party_type, party=None, company=None):
existing_gle_currency = get_party_gle_currency(party_type, party, company) existing_gle_currency = get_party_gle_currency(party_type, party, company)
if existing_gle_currency: if existing_gle_currency:
if account: if account:
account_currency = frappe.db.get_value("Account", account, "account_currency", cache=True) account_currency = frappe.get_cached_value("Account", account, "account_currency")
if (account and account_currency != existing_gle_currency) or not account: if (account and account_currency != existing_gle_currency) or not account:
account = get_party_gle_account(party_type, party, company) account = get_party_gle_account(party_type, party, company)
@@ -402,7 +402,7 @@ def get_party_bank_account(party_type, party):
def get_party_account_currency(party_type, party, company): def get_party_account_currency(party_type, party, company):
def generator(): def generator():
party_account = get_party_account(party_type, party, company) party_account = get_party_account(party_type, party, company)
return frappe.db.get_value("Account", party_account, "account_currency", cache=True) return frappe.get_cached_value("Account", party_account, "account_currency")
return frappe.local_cache("party_account_currency", (party_type, party, company), generator) return frappe.local_cache("party_account_currency", (party_type, party, company), generator)
@@ -474,15 +474,15 @@ def validate_party_accounts(doc):
else: else:
companies.append(account.company) companies.append(account.company)
party_account_currency = frappe.db.get_value( party_account_currency = frappe.get_cached_value("Account", account.account, "account_currency")
"Account", account.account, "account_currency", cache=True
)
if frappe.db.get_default("Company"): if frappe.db.get_default("Company"):
company_default_currency = frappe.get_cached_value( company_default_currency = frappe.get_cached_value(
"Company", frappe.db.get_default("Company"), "default_currency" "Company", frappe.db.get_default("Company"), "default_currency"
) )
else: else:
company_default_currency = frappe.db.get_value("Company", account.company, "default_currency") company_default_currency = frappe.get_cached_value(
"Company", account.company, "default_currency"
)
validate_party_gle_currency(doc.doctype, doc.name, account.company, party_account_currency) validate_party_gle_currency(doc.doctype, doc.name, account.company, party_account_currency)
@@ -801,7 +801,7 @@ def get_dashboard_info(party_type, party, loyalty_program=None):
) )
for d in companies: for d in companies:
company_default_currency = frappe.db.get_value("Company", d.company, "default_currency") company_default_currency = frappe.get_cached_value("Company", d.company, "default_currency")
party_account_currency = get_party_account_currency(party_type, party, d.company) party_account_currency = get_party_account_currency(party_type, party, d.company)
if party_account_currency == company_default_currency: if party_account_currency == company_default_currency:

View File

@@ -21,7 +21,7 @@ def execute(filters=None):
if not filters.get("account"): if not filters.get("account"):
return columns, [] return columns, []
account_currency = frappe.db.get_value("Account", filters.account, "account_currency") account_currency = frappe.get_cached_value("Account", filters.account, "account_currency")
data = get_entries(filters) data = get_entries(filters)

View File

@@ -180,7 +180,7 @@ def get_account_type_based_gl_data(company, start_date, end_date, account_type,
filters = frappe._dict(filters or {}) filters = frappe._dict(filters or {})
if filters.include_default_book_entries: if filters.include_default_book_entries:
company_fb = frappe.db.get_value("Company", company, "default_finance_book") company_fb = frappe.get_cached_value("Company", company, "default_finance_book")
cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL) cond = """ AND (finance_book in (%s, %s, '') OR finance_book IS NULL)
""" % ( """ % (
frappe.db.escape(filters.finance_book), frappe.db.escape(filters.finance_book),

View File

@@ -641,7 +641,7 @@ def set_gl_entries_by_account(
"rgt": root_rgt, "rgt": root_rgt,
"company": d.name, "company": d.name,
"finance_book": filters.get("finance_book"), "finance_book": filters.get("finance_book"),
"company_fb": frappe.db.get_value("Company", d.name, "default_finance_book"), "company_fb": frappe.get_cached_value("Company", d.name, "default_finance_book"),
}, },
as_dict=True, as_dict=True,
) )

View File

@@ -220,8 +220,8 @@ class PartyLedgerSummaryReport(object):
if self.filters.party_type == "Customer": if self.filters.party_type == "Customer":
if self.filters.get("customer_group"): if self.filters.get("customer_group"):
lft, rgt = frappe.db.get_value( lft, rgt = frappe.get_cached_value(
"Customer Group", self.filters.get("customer_group"), ["lft", "rgt"] "Customer Group", self.filters["customer_group"], ["lft", "rgt"]
) )
conditions.append( conditions.append(

View File

@@ -90,7 +90,7 @@ def set_gl_entries_by_account(dimension_list, filters, account, gl_entries_by_ac
gl_filters["dimensions"] = set(dimension_list) gl_filters["dimensions"] = set(dimension_list)
if filters.get("include_default_book_entries"): if filters.get("include_default_book_entries"):
gl_filters["company_fb"] = frappe.db.get_value( gl_filters["company_fb"] = frappe.get_cached_value(
"Company", filters.company, "default_finance_book" "Company", filters.company, "default_finance_book"
) )

View File

@@ -440,7 +440,7 @@ def set_gl_entries_by_account(
} }
if filters.get("include_default_book_entries"): if filters.get("include_default_book_entries"):
gl_filters["company_fb"] = frappe.db.get_value("Company", company, "default_finance_book") gl_filters["company_fb"] = frappe.get_cached_value("Company", company, "default_finance_book")
for key, value in filters.items(): for key, value in filters.items():
if value: if value:

View File

@@ -121,7 +121,7 @@ def set_account_currency(filters):
if is_same_account_currency: if is_same_account_currency:
account_currency = currency account_currency = currency
elif filters.get("party"): elif filters.get("party") and filters.get("party_type"):
gle_currency = frappe.db.get_value( gle_currency = frappe.db.get_value(
"GL Entry", "GL Entry",
{"party_type": filters.party_type, "party": filters.party[0], "company": filters.company}, {"party_type": filters.party_type, "party": filters.party[0], "company": filters.company},
@@ -134,7 +134,7 @@ def set_account_currency(filters):
account_currency = ( account_currency = (
None None
if filters.party_type in ["Employee", "Shareholder", "Member"] if filters.party_type in ["Employee", "Shareholder", "Member"]
else frappe.db.get_value(filters.party_type, filters.party[0], "default_currency") else frappe.get_cached_value(filters.party_type, filters.party[0], "default_currency")
) )
filters["account_currency"] = account_currency or filters.company_currency filters["account_currency"] = account_currency or filters.company_currency
@@ -174,7 +174,7 @@ def get_gl_entries(filters, accounting_dimensions):
order_by_statement = "order by account, posting_date, creation" order_by_statement = "order by account, posting_date, creation"
if filters.get("include_default_book_entries"): if filters.get("include_default_book_entries"):
filters["company_fb"] = frappe.db.get_value( filters["company_fb"] = frappe.get_cached_value(
"Company", filters.get("company"), "default_finance_book" "Company", filters.get("company"), "default_finance_book"
) )
@@ -286,9 +286,11 @@ def get_accounts_with_children(accounts):
all_accounts = [] all_accounts = []
for d in accounts: for d in accounts:
if frappe.db.exists("Account", d): account = frappe.get_cached_doc("Account", d)
lft, rgt = frappe.db.get_value("Account", d, ["lft", "rgt"]) if account:
children = frappe.get_all("Account", filters={"lft": [">=", lft], "rgt": ["<=", rgt]}) children = frappe.get_all(
"Account", filters={"lft": [">=", account.lft], "rgt": ["<=", account.rgt]}
)
all_accounts += [c.name for c in children] all_accounts += [c.name for c in children]
else: else:
frappe.throw(_("Account: {0} does not exist").format(d)) frappe.throw(_("Account: {0} does not exist").format(d))

View File

@@ -232,12 +232,12 @@ def get_conditions(filters):
conditions += ( conditions += (
common_condition common_condition
+ "and ifnull(`tabPurchase Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + "and ifnull(`tabPurchase Invoice`.{0}, '') in %({0})s)".format(dimension.fieldname)
) )
else: else:
conditions += ( conditions += (
common_condition common_condition
+ "and ifnull(`tabPurchase Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + "and ifnull(`tabPurchase Invoice`.{0}, '') in %({0})s)".format(dimension.fieldname)
) )
return conditions return conditions

View File

@@ -390,12 +390,12 @@ def get_conditions(filters):
conditions += ( conditions += (
common_condition common_condition
+ "and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + "and ifnull(`tabSales Invoice`.{0}, '') in %({0})s)".format(dimension.fieldname)
) )
else: else:
conditions += ( conditions += (
common_condition common_condition
+ "and ifnull(`tabSales Invoice Item`.{0}, '') in %({0})s)".format(dimension.fieldname) + "and ifnull(`tabSales Invoice`.{0}, '') in %({0})s)".format(dimension.fieldname)
) )
return conditions return conditions

View File

@@ -14,9 +14,17 @@ def execute(filters=None):
filters.naming_series = frappe.db.get_single_value("Buying Settings", "supp_master_name") filters.naming_series = frappe.db.get_single_value("Buying Settings", "supp_master_name")
columns = get_columns(filters) columns = get_columns(filters)
tds_docs, tds_accounts, tax_category_map, journal_entry_party_map = get_tds_docs(filters) (
tds_docs,
tds_accounts,
tax_category_map,
journal_entry_party_map,
invoice_total_map,
) = get_tds_docs(filters)
res = get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map) res = get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_total_map
)
final_result = group_by_supplier_and_category(res) final_result = group_by_supplier_and_category(res)
return columns, final_result return columns, final_result

View File

@@ -8,11 +8,19 @@ from frappe import _
def execute(filters=None): def execute(filters=None):
validate_filters(filters) validate_filters(filters)
tds_docs, tds_accounts, tax_category_map, journal_entry_party_map = get_tds_docs(filters) (
tds_docs,
tds_accounts,
tax_category_map,
journal_entry_party_map,
invoice_net_total_map,
) = get_tds_docs(filters)
columns = get_columns(filters) columns = get_columns(filters)
res = get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map) res = get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map
)
return columns, res return columns, res
@@ -22,7 +30,9 @@ def validate_filters(filters):
frappe.throw(_("From Date must be before To Date")) frappe.throw(_("From Date must be before To Date"))
def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map): def get_result(
filters, tds_docs, tds_accounts, tax_category_map, journal_entry_party_map, invoice_net_total_map
):
supplier_map = get_supplier_pan_map() supplier_map = get_supplier_pan_map()
tax_rate_map = get_tax_rate_map(filters) tax_rate_map = get_tax_rate_map(filters)
gle_map = get_gle_map(tds_docs) gle_map = get_gle_map(tds_docs)
@@ -50,7 +60,10 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
if entry.account in tds_accounts: if entry.account in tds_accounts:
tds_deducted += entry.credit - entry.debit tds_deducted += entry.credit - entry.debit
total_amount_credited += entry.credit if invoice_net_total_map.get(name):
total_amount_credited = invoice_net_total_map.get(name)
else:
total_amount_credited += entry.credit
if tds_deducted: if tds_deducted:
row = { row = {
@@ -179,9 +192,10 @@ def get_tds_docs(filters):
purchase_invoices = [] purchase_invoices = []
payment_entries = [] payment_entries = []
journal_entries = [] journal_entries = []
tax_category_map = {} tax_category_map = frappe._dict()
or_filters = {} invoice_net_total_map = frappe._dict()
journal_entry_party_map = {} or_filters = frappe._dict()
journal_entry_party_map = frappe._dict()
bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name") bank_accounts = frappe.get_all("Account", {"is_group": 0, "account_type": "Bank"}, pluck="name")
tds_accounts = frappe.get_all( tds_accounts = frappe.get_all(
@@ -218,16 +232,22 @@ def get_tds_docs(filters):
tds_documents.append(d.voucher_no) tds_documents.append(d.voucher_no)
if purchase_invoices: if purchase_invoices:
get_tax_category_map(purchase_invoices, "Purchase Invoice", tax_category_map) get_doc_info(purchase_invoices, "Purchase Invoice", tax_category_map, invoice_net_total_map)
if payment_entries: if payment_entries:
get_tax_category_map(payment_entries, "Payment Entry", tax_category_map) get_doc_info(payment_entries, "Payment Entry", tax_category_map)
if journal_entries: if journal_entries:
journal_entry_party_map = get_journal_entry_party_map(journal_entries) journal_entry_party_map = get_journal_entry_party_map(journal_entries)
get_tax_category_map(journal_entries, "Journal Entry", tax_category_map) get_doc_info(journal_entries, "Journal Entry", tax_category_map)
return tds_documents, tds_accounts, tax_category_map, journal_entry_party_map return (
tds_documents,
tds_accounts,
tax_category_map,
journal_entry_party_map,
invoice_net_total_map,
)
def get_journal_entry_party_map(journal_entries): def get_journal_entry_party_map(journal_entries):
@@ -244,17 +264,18 @@ def get_journal_entry_party_map(journal_entries):
return journal_entry_party_map return journal_entry_party_map
def get_tax_category_map(vouchers, doctype, tax_category_map): def get_doc_info(vouchers, doctype, tax_category_map, invoice_net_total_map=None):
tax_category_map.update( if doctype == "Purchase Invoice":
frappe._dict( fields = ["name", "tax_withholding_category", "base_tax_withholding_net_total"]
frappe.get_all( else:
doctype, fields = ["name", "tax_withholding_category"]
filters={"name": ("in", vouchers)},
fields=["name", "tax_withholding_category"], entries = frappe.get_all(doctype, filters={"name": ("in", vouchers)}, fields=fields)
as_list=1,
) for entry in entries:
) tax_category_map.update({entry.name: entry.tax_withholding_category})
) if doctype == "Purchase Invoice":
invoice_net_total_map.update({entry.name: entry.base_tax_withholding_net_total})
def get_tax_rate_map(filters): def get_tax_rate_map(filters):

View File

@@ -38,7 +38,7 @@ def validate_filters(filters):
if not filters.fiscal_year: if not filters.fiscal_year:
frappe.throw(_("Fiscal Year {0} is required").format(filters.fiscal_year)) frappe.throw(_("Fiscal Year {0} is required").format(filters.fiscal_year))
fiscal_year = frappe.db.get_value( fiscal_year = frappe.get_cached_value(
"Fiscal Year", filters.fiscal_year, ["year_start_date", "year_end_date"], as_dict=True "Fiscal Year", filters.fiscal_year, ["year_start_date", "year_end_date"], as_dict=True
) )
if not fiscal_year: if not fiscal_year:
@@ -177,7 +177,7 @@ def get_rootwise_opening_balances(filters, report_type):
"year_start_date": filters.year_start_date, "year_start_date": filters.year_start_date,
"project": filters.project, "project": filters.project,
"finance_book": filters.finance_book, "finance_book": filters.finance_book,
"company_fb": frappe.db.get_value("Company", filters.company, "default_finance_book"), "company_fb": frappe.get_cached_value("Company", filters.company, "default_finance_book"),
} }
if accounting_dimensions: if accounting_dimensions:

View File

@@ -28,7 +28,7 @@ def get_currency(filters):
filters["presentation_currency"] if filters.get("presentation_currency") else company_currency filters["presentation_currency"] if filters.get("presentation_currency") else company_currency
) )
report_date = filters.get("to_date") report_date = filters.get("to_date") or filters.get("period_end_date")
if not report_date: if not report_date:
fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"] fiscal_year_to_date = get_from_and_to_date(filters.get("to_fiscal_year"))["to_date"]

View File

@@ -975,7 +975,7 @@ def get_account_balances(accounts, company):
def create_payment_gateway_account(gateway, payment_channel="Email"): def create_payment_gateway_account(gateway, payment_channel="Email"):
from erpnext.setup.setup_wizard.operations.install_fixtures import create_bank_account from erpnext.setup.setup_wizard.operations.install_fixtures import create_bank_account
company = frappe.db.get_value("Global Defaults", None, "default_company") company = frappe.get_cached_value("Global Defaults", "Global Defaults", "default_company")
if not company: if not company:
return return

View File

@@ -12,6 +12,7 @@ from frappe.utils import (
get_first_day, get_first_day,
get_last_day, get_last_day,
getdate, getdate,
is_last_day_of_the_month,
nowdate, nowdate,
) )
@@ -224,7 +225,10 @@ class TestAsset(AssetSetup):
asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date asset.finance_books[0], 9000, get_last_day(add_months(purchase_date, 1)), date
) )
pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount")) pro_rata_amount = flt(pro_rata_amount, asset.precision("gross_purchase_amount"))
self.assertEquals(accumulated_depr_amount, 18000.00 + pro_rata_amount) self.assertEquals(
accumulated_depr_amount,
flt(18000.0 + pro_rata_amount, asset.precision("gross_purchase_amount")),
)
self.assertEqual(asset.status, "Scrapped") self.assertEqual(asset.status, "Scrapped")
self.assertTrue(asset.journal_entry_for_scrap) self.assertTrue(asset.journal_entry_for_scrap)
@@ -261,7 +265,7 @@ class TestAsset(AssetSetup):
asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation, asset.gross_purchase_amount - asset.finance_books[0].value_after_depreciation,
asset.precision("gross_purchase_amount"), asset.precision("gross_purchase_amount"),
) )
this_month_depr_amount = 9000.0 if get_last_day(date) == date else 0 this_month_depr_amount = 9000.0 if is_last_day_of_the_month(date) else 0
self.assertEquals(accumulated_depr_amount, 18000.0 + this_month_depr_amount) self.assertEquals(accumulated_depr_amount, 18000.0 + this_month_depr_amount)

View File

@@ -54,6 +54,8 @@
"column_break_26", "column_break_26",
"total", "total",
"net_total", "net_total",
"tax_withholding_net_total",
"base_tax_withholding_net_total",
"section_break_48", "section_break_48",
"pricing_rules", "pricing_rules",
"raw_material_details", "raw_material_details",
@@ -65,6 +67,7 @@
"tax_category", "tax_category",
"column_break_50", "column_break_50",
"shipping_rule", "shipping_rule",
"incoterm",
"section_break_52", "section_break_52",
"taxes", "taxes",
"totals", "totals",
@@ -1220,6 +1223,26 @@
"label": "Additional Info", "label": "Additional Info",
"oldfieldtype": "Section Break" "oldfieldtype": "Section Break"
}, },
{
"default": "0",
"fieldname": "tax_withholding_net_total",
"fieldtype": "Currency",
"hidden": 1,
"label": "Tax Withholding Net Total",
"no_copy": 1,
"options": "currency",
"read_only": 1
},
{
"fieldname": "base_tax_withholding_net_total",
"fieldtype": "Currency",
"hidden": 1,
"label": "Base Tax Withholding Net Total",
"no_copy": 1,
"options": "currency",
"print_hide": 1,
"read_only": 1
},
{ {
"fieldname": "column_break_99", "fieldname": "column_break_99",
"fieldtype": "Column Break" "fieldtype": "Column Break"
@@ -1227,13 +1250,19 @@
{ {
"fieldname": "column_break_103", "fieldname": "column_break_103",
"fieldtype": "Column Break" "fieldtype": "Column Break"
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
"label": "Incoterm",
"options": "Incoterm"
} }
], ],
"icon": "fa fa-file-text", "icon": "fa fa-file-text",
"idx": 105, "idx": 105,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-11-17 12:34:36.033363", "modified": "2022-11-17 17:28:07.729943",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Purchase Order", "name": "Purchase Order",

View File

@@ -736,27 +736,29 @@ class TestPurchaseOrder(FrappeTestCase):
def test_advance_paid_upon_payment_entry_cancellation(self): def test_advance_paid_upon_payment_entry_cancellation(self):
from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry from erpnext.accounts.doctype.payment_entry.test_payment_entry import get_payment_entry
po_doc = create_purchase_order() po_doc = create_purchase_order(supplier="_Test Supplier USD", currency="USD", do_not_submit=1)
po_doc.conversion_rate = 80
po_doc.submit()
pe = get_payment_entry("Purchase Order", po_doc.name, bank_account="_Test Bank - _TC") pe = get_payment_entry("Purchase Order", po_doc.name)
pe.reference_no = "1" pe.mode_of_payment = "Cash"
pe.reference_date = nowdate() pe.paid_from = "Cash - _TC"
pe.paid_from_account_currency = po_doc.currency pe.source_exchange_rate = 80
pe.paid_to_account_currency = po_doc.currency
pe.source_exchange_rate = 1
pe.target_exchange_rate = 1 pe.target_exchange_rate = 1
pe.paid_amount = po_doc.grand_total pe.paid_amount = po_doc.grand_total
pe.save(ignore_permissions=True) pe.save(ignore_permissions=True)
pe.submit() pe.submit()
po_doc.reload() po_doc.reload()
self.assertEqual(po_doc.advance_paid, po_doc.base_grand_total) self.assertEqual(po_doc.advance_paid, po_doc.grand_total)
self.assertEqual(po_doc.party_account_currency, "USD")
pe_doc = frappe.get_doc("Payment Entry", pe.name) pe_doc = frappe.get_doc("Payment Entry", pe.name)
pe_doc.cancel() pe_doc.cancel()
po_doc.reload() po_doc.reload()
self.assertEqual(po_doc.advance_paid, 0) self.assertEqual(po_doc.advance_paid, 0)
self.assertEqual(po_doc.party_account_currency, "USD")
def test_schedule_date(self): def test_schedule_date(self):
po = create_purchase_order(do_not_submit=True) po = create_purchase_order(do_not_submit=True)
@@ -833,6 +835,10 @@ class TestPurchaseOrder(FrappeTestCase):
prepare_data_for_internal_transfer() prepare_data_for_internal_transfer()
supplier = "_Test Internal Supplier 2" supplier = "_Test Internal Supplier 2"
mr = make_material_request(
qty=2, company="_Test Company with perpetual inventory", warehouse="Stores - TCP1"
)
po = create_purchase_order( po = create_purchase_order(
company="_Test Company with perpetual inventory", company="_Test Company with perpetual inventory",
supplier=supplier, supplier=supplier,
@@ -840,6 +846,8 @@ class TestPurchaseOrder(FrappeTestCase):
from_warehouse="_Test Internal Warehouse New 1 - TCP1", from_warehouse="_Test Internal Warehouse New 1 - TCP1",
qty=2, qty=2,
rate=1, rate=1,
material_request=mr.name,
material_request_item=mr.items[0].name,
) )
so = make_inter_company_sales_order(po.name) so = make_inter_company_sales_order(po.name)
@@ -875,9 +883,11 @@ class TestPurchaseOrder(FrappeTestCase):
self.assertTrue(pi.items[0].purchase_order) self.assertTrue(pi.items[0].purchase_order)
self.assertTrue(pi.items[0].po_detail) self.assertTrue(pi.items[0].po_detail)
pi.submit() pi.submit()
mr.reload()
po.load_from_db() po.load_from_db()
self.assertEqual(po.status, "Completed") self.assertEqual(po.status, "Completed")
self.assertEqual(mr.status, "Received")
def prepare_data_for_internal_transfer(): def prepare_data_for_internal_transfer():
@@ -979,6 +989,8 @@ def create_purchase_order(**args):
"schedule_date": add_days(nowdate(), 1), "schedule_date": add_days(nowdate(), 1),
"include_exploded_items": args.get("include_exploded_items", 1), "include_exploded_items": args.get("include_exploded_items", 1),
"against_blanket_order": args.against_blanket_order, "against_blanket_order": args.against_blanket_order,
"material_request": args.material_request,
"material_request_item": args.material_request_item,
}, },
) )

View File

@@ -53,6 +53,7 @@
"pricing_rules", "pricing_rules",
"stock_uom_rate", "stock_uom_rate",
"is_free_item", "is_free_item",
"apply_tds",
"section_break_29", "section_break_29",
"net_rate", "net_rate",
"net_amount", "net_amount",
@@ -889,13 +890,19 @@
{ {
"fieldname": "column_break_54", "fieldname": "column_break_54",
"fieldtype": "Column Break" "fieldtype": "Column Break"
},
{
"default": "1",
"fieldname": "apply_tds",
"fieldtype": "Check",
"label": "Apply TDS"
} }
], ],
"idx": 1, "idx": 1,
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"istable": 1, "istable": 1,
"links": [], "links": [],
"modified": "2022-10-26 16:47:41.364387", "modified": "2022-11-29 16:47:41.364387",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Purchase Order Item", "name": "Purchase Order Item",

View File

@@ -22,6 +22,13 @@ frappe.ui.form.on("Request for Quotation",{
} }
}; };
} }
frm.set_query('warehouse', 'items', () => ({
filters: {
company: frm.doc.company,
is_group: 0
}
}));
}, },
onload: function(frm) { onload: function(frm) {

View File

@@ -28,6 +28,7 @@
"sec_break_email_2", "sec_break_email_2",
"message_for_supplier", "message_for_supplier",
"terms_section_break", "terms_section_break",
"incoterm",
"tc_name", "tc_name",
"terms", "terms",
"printing_settings", "printing_settings",
@@ -271,13 +272,19 @@
"fieldname": "schedule_date", "fieldname": "schedule_date",
"fieldtype": "Date", "fieldtype": "Date",
"label": "Required Date" "label": "Required Date"
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
"label": "Incoterm",
"options": "Incoterm"
} }
], ],
"icon": "fa fa-shopping-cart", "icon": "fa fa-shopping-cart",
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-04-06 17:47:49.909000", "modified": "2022-11-17 17:26:33.770993",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Request for Quotation", "name": "Request for Quotation",
@@ -345,5 +352,6 @@
"search_fields": "status, transaction_date", "search_fields": "status, transaction_date",
"show_name_in_global_search": 1, "show_name_in_global_search": 1,
"sort_field": "modified", "sort_field": "modified",
"sort_order": "DESC" "sort_order": "DESC",
"states": []
} }

View File

@@ -20,9 +20,6 @@ from erpnext.utilities.transaction_base import TransactionBase
class Supplier(TransactionBase): class Supplier(TransactionBase):
def get_feed(self):
return self.supplier_name
def onload(self): def onload(self):
"""Load address and contacts in `__onload`""" """Load address and contacts in `__onload`"""
load_address_and_contact(self) load_address_and_contact(self)

View File

@@ -45,6 +45,7 @@
"tax_category", "tax_category",
"column_break_36", "column_break_36",
"shipping_rule", "shipping_rule",
"incoterm",
"section_break_38", "section_break_38",
"taxes", "taxes",
"totals", "totals",
@@ -823,6 +824,12 @@
{ {
"fieldname": "column_break_85", "fieldname": "column_break_85",
"fieldtype": "Column Break" "fieldtype": "Column Break"
},
{
"fieldname": "incoterm",
"fieldtype": "Link",
"label": "Incoterm",
"options": "Incoterm"
} }
], ],
"icon": "fa fa-shopping-cart", "icon": "fa fa-shopping-cart",
@@ -830,7 +837,7 @@
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"is_submittable": 1, "is_submittable": 1,
"links": [], "links": [],
"modified": "2022-09-27 18:20:09.462037", "modified": "2022-11-17 17:27:32.179686",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Buying", "module": "Buying",
"name": "Supplier Quotation", "name": "Supplier Quotation",

View File

@@ -197,7 +197,7 @@ class AccountsController(TransactionBase):
validate_einvoice_fields(self) validate_einvoice_fields(self)
if self.doctype != "Material Request": if self.doctype != "Material Request" and not self.ignore_pricing_rule:
apply_pricing_rule_on_transaction(self) apply_pricing_rule_on_transaction(self)
def before_cancel(self): def before_cancel(self):
@@ -239,6 +239,14 @@ class AccountsController(TransactionBase):
else: else:
item.set(field_map.get(self.doctype), default_deferred_account) item.set(field_map.get(self.doctype), default_deferred_account)
def validate_auto_repeat_subscription_dates(self):
if (
self.get("from_date")
and self.get("to_date")
and getdate(self.from_date) > getdate(self.to_date)
):
frappe.throw(_("To Date cannot be before From Date"), title=_("Invalid Auto Repeat Date"))
def validate_deferred_start_and_end_date(self): def validate_deferred_start_and_end_date(self):
for d in self.items: for d in self.items:
if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"): if d.get("enable_deferred_revenue") or d.get("enable_deferred_expense"):
@@ -1352,12 +1360,12 @@ class AccountsController(TransactionBase):
party = self.customer if self.doctype == "Sales Order" else self.supplier party = self.customer if self.doctype == "Sales Order" else self.supplier
advance = ( advance = (
frappe.qb.from_(ple) frappe.qb.from_(ple)
.select(ple.account_currency, Abs(Sum(ple.amount)).as_("amount")) .select(ple.account_currency, Abs(Sum(ple.amount_in_account_currency)).as_("amount"))
.where( .where(
(ple.against_voucher_type == self.doctype) (ple.against_voucher_type == self.doctype)
& (ple.against_voucher_no == self.name) & (ple.against_voucher_no == self.name)
& (ple.party == party) & (ple.party == party)
& (ple.delinked == 0) & (ple.docstatus == 1)
& (ple.company == self.company) & (ple.company == self.company)
) )
.run(as_dict=True) .run(as_dict=True)
@@ -2303,7 +2311,7 @@ def get_due_date(term, posting_date=None, bill_date=None):
elif term.due_date_based_on == "Day(s) after the end of the invoice month": elif term.due_date_based_on == "Day(s) after the end of the invoice month":
due_date = add_days(get_last_day(date), term.credit_days) due_date = add_days(get_last_day(date), term.credit_days)
elif term.due_date_based_on == "Month(s) after the end of the invoice month": elif term.due_date_based_on == "Month(s) after the end of the invoice month":
due_date = add_months(get_last_day(date), term.credit_months) due_date = get_last_day(add_months(date, term.credit_months))
return due_date return due_date
@@ -2315,7 +2323,7 @@ def get_discount_date(term, posting_date=None, bill_date=None):
elif term.discount_validity_based_on == "Day(s) after the end of the invoice month": elif term.discount_validity_based_on == "Day(s) after the end of the invoice month":
discount_validity = add_days(get_last_day(date), term.discount_validity) discount_validity = add_days(get_last_day(date), term.discount_validity)
elif term.discount_validity_based_on == "Month(s) after the end of the invoice month": elif term.discount_validity_based_on == "Month(s) after the end of the invoice month":
discount_validity = add_months(get_last_day(date), term.discount_validity) discount_validity = get_last_day(add_months(date, term.discount_validity))
return discount_validity return discount_validity

View File

@@ -25,10 +25,6 @@ class BuyingController(SubcontractingController):
def __setup__(self): def __setup__(self):
self.flags.ignore_permlevel_for_fields = ["buying_price_list", "price_list_currency"] self.flags.ignore_permlevel_for_fields = ["buying_price_list", "price_list_currency"]
def get_feed(self):
if self.get("supplier_name"):
return _("From {0} | {1} {2}").format(self.supplier_name, self.currency, self.grand_total)
def validate(self): def validate(self):
super(BuyingController, self).validate() super(BuyingController, self).validate()
if getattr(self, "supplier", None) and not self.supplier_name: if getattr(self, "supplier", None) and not self.supplier_name:
@@ -41,6 +37,7 @@ class BuyingController(SubcontractingController):
self.validate_from_warehouse() self.validate_from_warehouse()
self.set_supplier_address() self.set_supplier_address()
self.validate_asset_return() self.validate_asset_return()
self.validate_auto_repeat_subscription_dates()
if self.doctype == "Purchase Invoice": if self.doctype == "Purchase Invoice":
self.validate_purchase_receipt_if_update_stock() self.validate_purchase_receipt_if_update_stock()
@@ -321,17 +318,18 @@ class BuyingController(SubcontractingController):
) )
if self.is_internal_transfer(): if self.is_internal_transfer():
if rate != d.rate: if self.doctype == "Purchase Receipt" or self.get("update_stock"):
d.rate = rate if rate != d.rate:
frappe.msgprint( d.rate = rate
_( frappe.msgprint(
"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer" _(
).format(d.idx), "Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
alert=1, ).format(d.idx),
) alert=1,
d.discount_percentage = 0.0 )
d.discount_amount = 0.0 d.discount_percentage = 0.0
d.margin_rate_or_amount = 0.0 d.discount_amount = 0.0
d.margin_rate_or_amount = 0.0
def validate_for_subcontracting(self): def validate_for_subcontracting(self):
if self.is_subcontracted and self.get("is_old_subcontracting_flow"): if self.is_subcontracted and self.get("is_old_subcontracting_flow"):

View File

@@ -404,12 +404,17 @@ def make_return_doc(doctype: str, source_name: str, target_doc=None):
returned_qty_map = get_returned_qty_map_for_row( returned_qty_map = get_returned_qty_map_for_row(
source_parent.name, source_parent.supplier, source_doc.name, doctype source_parent.name, source_parent.supplier, source_doc.name, doctype
) )
target_doc.received_qty = -1 * flt(
source_doc.received_qty - (returned_qty_map.get("received_qty") or 0) if doctype == "Subcontracting Receipt":
) target_doc.received_qty = -1 * flt(source_doc.qty)
target_doc.rejected_qty = -1 * flt( else:
source_doc.rejected_qty - (returned_qty_map.get("rejected_qty") or 0) target_doc.received_qty = -1 * flt(
) source_doc.received_qty - (returned_qty_map.get("received_qty") or 0)
)
target_doc.rejected_qty = -1 * flt(
source_doc.rejected_qty - (returned_qty_map.get("rejected_qty") or 0)
)
target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get("qty") or 0)) target_doc.qty = -1 * flt(source_doc.qty - (returned_qty_map.get("qty") or 0))
if hasattr(target_doc, "stock_qty"): if hasattr(target_doc, "stock_qty"):

View File

@@ -19,9 +19,6 @@ class SellingController(StockController):
def __setup__(self): def __setup__(self):
self.flags.ignore_permlevel_for_fields = ["selling_price_list", "price_list_currency"] self.flags.ignore_permlevel_for_fields = ["selling_price_list", "price_list_currency"]
def get_feed(self):
return _("To {0} | {1} {2}").format(self.customer_name, self.currency, self.grand_total)
def onload(self): def onload(self):
super(SellingController, self).onload() super(SellingController, self).onload()
if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"): if self.doctype in ("Sales Order", "Delivery Note", "Sales Invoice"):
@@ -40,6 +37,7 @@ class SellingController(StockController):
self.set_customer_address() self.set_customer_address()
self.validate_for_duplicate_items() self.validate_for_duplicate_items()
self.validate_target_warehouse() self.validate_target_warehouse()
self.validate_auto_repeat_subscription_dates()
def set_missing_values(self, for_validate=False): def set_missing_values(self, for_validate=False):
@@ -441,30 +439,31 @@ class SellingController(StockController):
# For internal transfers use incoming rate as the valuation rate # For internal transfers use incoming rate as the valuation rate
if self.is_internal_transfer(): if self.is_internal_transfer():
if d.doctype == "Packed Item": if self.doctype == "Delivery Note" or self.get("update_stock"):
incoming_rate = flt( if d.doctype == "Packed Item":
flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor, incoming_rate = flt(
d.precision("incoming_rate"), flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
) d.precision("incoming_rate"),
if d.incoming_rate != incoming_rate:
d.incoming_rate = incoming_rate
else:
rate = flt(
flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
d.precision("rate"),
)
if d.rate != rate:
d.rate = rate
frappe.msgprint(
_(
"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
).format(d.idx),
alert=1,
) )
if d.incoming_rate != incoming_rate:
d.incoming_rate = incoming_rate
else:
rate = flt(
flt(d.incoming_rate, d.precision("incoming_rate")) * d.conversion_factor,
d.precision("rate"),
)
if d.rate != rate:
d.rate = rate
frappe.msgprint(
_(
"Row {0}: Item rate has been updated as per valuation rate since its an internal stock transfer"
).format(d.idx),
alert=1,
)
d.discount_percentage = 0.0 d.discount_percentage = 0.0
d.discount_amount = 0.0 d.discount_amount = 0.0
d.margin_rate_or_amount = 0.0 d.margin_rate_or_amount = 0.0
elif self.get("return_against"): elif self.get("return_against"):
# Get incoming rate of return entry from reference document # Get incoming rate of return entry from reference document
@@ -581,6 +580,7 @@ class SellingController(StockController):
"customer_address": "address_display", "customer_address": "address_display",
"shipping_address_name": "shipping_address", "shipping_address_name": "shipping_address",
"company_address": "company_address_display", "company_address": "company_address_display",
"dispatch_address_name": "dispatch_address",
} }
for address_field, address_display_field in address_dict.items(): for address_field, address_display_field in address_dict.items():

View File

@@ -349,7 +349,7 @@ class StatusUpdater(Document):
def warn_about_bypassing_with_role(self, item, qty_or_amount, role): def warn_about_bypassing_with_role(self, item, qty_or_amount, role):
action = _("Over Receipt/Delivery") if qty_or_amount == "qty" else _("Overbilling") action = _("Over Receipt/Delivery") if qty_or_amount == "qty" else _("Overbilling")
msg = _("{} of {} {} ignored for item {} because you have {} role.").format( msg = _("{0} of {1} {2} ignored for item {3} because you have {4} role.").format(
action, action,
_(item["target_ref_field"].title()), _(item["target_ref_field"].title()),
frappe.bold(item["reduce_by"]), frappe.bold(item["reduce_by"]),

View File

@@ -14,9 +14,6 @@ from erpnext.crm.utils import CRMNote, copy_comments, link_communications, link_
class Lead(SellingController, CRMNote): class Lead(SellingController, CRMNote):
def get_feed(self):
return "{0}: {1}".format(_(self.status), self.lead_name)
def onload(self): def onload(self):
customer = frappe.db.get_value("Customer", {"lead_name": self.name}) customer = frappe.db.get_value("Customer", {"lead_name": self.name})
self.get("__onload").is_customer = customer self.get("__onload").is_customer = customer
@@ -453,6 +450,7 @@ def get_lead_with_phone_number(number):
"Lead", "Lead",
or_filters={ or_filters={
"phone": ["like", "%{}".format(number)], "phone": ["like", "%{}".format(number)],
"whatsapp_no": ["like", "%{}".format(number)],
"mobile_no": ["like", "%{}".format(number)], "mobile_no": ["like", "%{}".format(number)],
}, },
limit=1, limit=1,

View File

@@ -217,7 +217,7 @@ class SalesPipelineAnalytics(object):
def check_for_assigned_to(self, period, value, count_or_amount, assigned_to, info): def check_for_assigned_to(self, period, value, count_or_amount, assigned_to, info):
if self.filters.get("assigned_to"): if self.filters.get("assigned_to"):
for data in json.loads(info.get("opportunity_owner")): for data in json.loads(info.get("opportunity_owner") or "[]"):
if data == self.filters.get("assigned_to"): if data == self.filters.get("assigned_to"):
self.set_formatted_data(period, data, count_or_amount, assigned_to) self.set_formatted_data(period, data, count_or_amount, assigned_to)
else: else:

View File

@@ -120,7 +120,7 @@ def link_open_tasks(ref_doctype, ref_docname, doc):
todo_doc = frappe.get_doc("ToDo", todo.name) todo_doc = frappe.get_doc("ToDo", todo.name)
todo_doc.reference_type = doc.doctype todo_doc.reference_type = doc.doctype
todo_doc.reference_name = doc.name todo_doc.reference_name = doc.name
todo_doc.db_update() todo_doc.save()
def link_open_events(ref_doctype, ref_docname, doc): def link_open_events(ref_doctype, ref_docname, doc):

View File

@@ -48,5 +48,11 @@ frappe.ui.form.on("E Commerce Settings", {
frm.set_value('default_customer_group', ''); frm.set_value('default_customer_group', '');
frm.set_value('quotation_series', ''); frm.set_value('quotation_series', '');
} }
},
enable_checkout: function(frm) {
if (frm.doc.enable_checkout) {
erpnext.utils.check_payments_app();
}
} }
}); });

View File

@@ -2,4 +2,7 @@
// For license information, please see license.txt // For license information, please see license.txt
frappe.ui.form.on('GoCardless Settings', { frappe.ui.form.on('GoCardless Settings', {
refresh: function(frm) {
erpnext.utils.check_payments_app();
}
}); });

View File

@@ -173,7 +173,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2018-02-12 14:18:47.209114", "modified": "2022-02-12 14:18:47.209114",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "ERPNext Integrations", "module": "ERPNext Integrations",
"name": "GoCardless Settings", "name": "GoCardless Settings",
@@ -201,7 +201,6 @@
"write": 1 "write": 1
} }
], ],
"quick_entry": 1,
"read_only": 0, "read_only": 0,
"read_only_onload": 0, "read_only_onload": 0,
"show_name_in_global_search": 0, "show_name_in_global_search": 0,

View File

@@ -10,7 +10,8 @@ from frappe import _
from frappe.integrations.utils import create_request_log from frappe.integrations.utils import create_request_log
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import call_hook_method, cint, flt, get_url from frappe.utils import call_hook_method, cint, flt, get_url
from payments.utils import create_payment_gateway
from erpnext.utilities import payment_app_import_guard
class GoCardlessSettings(Document): class GoCardlessSettings(Document):
@@ -30,6 +31,9 @@ class GoCardlessSettings(Document):
frappe.throw(e) frappe.throw(e)
def on_update(self): def on_update(self):
with payment_app_import_guard():
from payments.utils import create_payment_gateway
create_payment_gateway( create_payment_gateway(
"GoCardless-" + self.gateway_name, settings="GoCardLess Settings", controller=self.gateway_name "GoCardless-" + self.gateway_name, settings="GoCardLess Settings", controller=self.gateway_name
) )

View File

@@ -7,6 +7,8 @@ frappe.ui.form.on('Mpesa Settings', {
}, },
refresh: function(frm) { refresh: function(frm) {
erpnext.utils.check_payments_app();
frappe.realtime.on("refresh_mpesa_dashboard", function(){ frappe.realtime.on("refresh_mpesa_dashboard", function(){
frm.reload_doc(); frm.reload_doc();
frm.events.setup_account_balance_html(frm); frm.events.setup_account_balance_html(frm);

View File

@@ -9,13 +9,13 @@ from frappe import _
from frappe.integrations.utils import create_request_log from frappe.integrations.utils import create_request_log
from frappe.model.document import Document from frappe.model.document import Document
from frappe.utils import call_hook_method, fmt_money, get_request_site_address from frappe.utils import call_hook_method, fmt_money, get_request_site_address
from payments.utils import create_payment_gateway
from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_connector import MpesaConnector from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_connector import MpesaConnector
from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_custom_fields import ( from erpnext.erpnext_integrations.doctype.mpesa_settings.mpesa_custom_fields import (
create_custom_pos_fields, create_custom_pos_fields,
) )
from erpnext.erpnext_integrations.utils import create_mode_of_payment from erpnext.erpnext_integrations.utils import create_mode_of_payment
from erpnext.utilities import payment_app_import_guard
class MpesaSettings(Document): class MpesaSettings(Document):
@@ -30,6 +30,9 @@ class MpesaSettings(Document):
) )
def on_update(self): def on_update(self):
with payment_app_import_guard():
from payments.utils import create_payment_gateway
create_custom_pos_fields() create_custom_pos_fields()
create_payment_gateway( create_payment_gateway(
"Mpesa-" + self.payment_gateway_name, "Mpesa-" + self.payment_gateway_name,

View File

@@ -1345,7 +1345,7 @@ class QuickBooksMigrator(Document):
)[0]["name"] )[0]["name"]
def _publish(self, *args, **kwargs): def _publish(self, *args, **kwargs):
frappe.publish_realtime("quickbooks_progress_update", *args, **kwargs) frappe.publish_realtime("quickbooks_progress_update", *args, **kwargs, user=self.modified_by)
def _get_unique_account_name(self, quickbooks_name, number=0): def _get_unique_account_name(self, quickbooks_name, number=0):
if number: if number:

View File

@@ -304,6 +304,7 @@ class TallyMigration(Document):
frappe.publish_realtime( frappe.publish_realtime(
"tally_migration_progress_update", "tally_migration_progress_update",
{"title": title, "message": message, "count": count, "total": total}, {"title": title, "message": message, "count": count, "total": total},
user=self.modified_by,
) )
def _import_master_data(self): def _import_master_data(self):

View File

@@ -1,51 +0,0 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2021-09-11 05:09:53.773838",
"doctype": "DocType",
"engine": "InnoDB",
"field_order": [
"region",
"region_code",
"country",
"country_code"
],
"fields": [
{
"fieldname": "region",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Region"
},
{
"fieldname": "region_code",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Region Code"
},
{
"fieldname": "country",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Country"
},
{
"fieldname": "country_code",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Country Code"
}
],
"index_web_pages_for_search": 1,
"istable": 1,
"links": [],
"modified": "2021-09-14 05:33:06.444710",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "TaxJar Nexus",
"owner": "Administrator",
"permissions": [],
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

View File

@@ -1,9 +0,0 @@
# Copyright (c) 2021, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class TaxJarNexus(Document):
pass

View File

@@ -1,37 +0,0 @@
// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
// For license information, please see license.txt
frappe.ui.form.on('TaxJar Settings', {
is_sandbox: (frm) => {
frm.toggle_reqd("api_key", !frm.doc.is_sandbox);
frm.toggle_reqd("sandbox_api_key", frm.doc.is_sandbox);
},
on_load: (frm) => {
frm.set_query('shipping_account_head', function() {
return {
filters: {
'company': frm.doc.company
}
};
});
frm.set_query('tax_account_head', function() {
return {
filters: {
'company': frm.doc.company
}
};
});
},
refresh: (frm) => {
frm.add_custom_button(__('Update Nexus List'), function() {
frm.call({
doc: frm.doc,
method: 'update_nexus_list'
});
});
},
});

View File

@@ -1,139 +0,0 @@
{
"actions": [],
"creation": "2017-06-15 08:21:24.624315",
"doctype": "DocType",
"document_type": "Setup",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"taxjar_calculate_tax",
"is_sandbox",
"taxjar_create_transactions",
"credentials",
"api_key",
"cb_keys",
"sandbox_api_key",
"configuration",
"company",
"column_break_10",
"tax_account_head",
"configuration_cb",
"shipping_account_head",
"section_break_12",
"nexus"
],
"fields": [
{
"fieldname": "credentials",
"fieldtype": "Section Break",
"label": "Credentials"
},
{
"fieldname": "api_key",
"fieldtype": "Password",
"in_list_view": 1,
"label": "Live API Key",
"reqd": 1
},
{
"fieldname": "configuration",
"fieldtype": "Section Break",
"label": "Configuration"
},
{
"fieldname": "tax_account_head",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Tax Account Head",
"options": "Account",
"reqd": 1
},
{
"fieldname": "shipping_account_head",
"fieldtype": "Link",
"in_list_view": 1,
"label": "Shipping Account Head",
"options": "Account",
"reqd": 1
},
{
"default": "0",
"depends_on": "taxjar_calculate_tax",
"fieldname": "is_sandbox",
"fieldtype": "Check",
"label": "Sandbox Mode"
},
{
"fieldname": "sandbox_api_key",
"fieldtype": "Password",
"label": "Sandbox API Key"
},
{
"default": "0",
"depends_on": "taxjar_calculate_tax",
"fieldname": "taxjar_create_transactions",
"fieldtype": "Check",
"label": "Create TaxJar Transaction"
},
{
"default": "0",
"fieldname": "taxjar_calculate_tax",
"fieldtype": "Check",
"label": "Enable Tax Calculation"
},
{
"fieldname": "cb_keys",
"fieldtype": "Column Break"
},
{
"depends_on": "nexus",
"fieldname": "section_break_12",
"fieldtype": "Section Break",
"label": "Nexus List"
},
{
"fieldname": "nexus",
"fieldtype": "Table",
"label": "Nexus",
"options": "TaxJar Nexus",
"read_only": 1
},
{
"fieldname": "configuration_cb",
"fieldtype": "Column Break"
},
{
"fieldname": "company",
"fieldtype": "Link",
"label": "Company",
"options": "Company"
},
{
"fieldname": "column_break_10",
"fieldtype": "Column Break"
}
],
"issingle": 1,
"links": [],
"modified": "2021-11-30 12:17:24.647979",
"modified_by": "Administrator",
"module": "ERPNext Integrations",
"name": "TaxJar Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"quick_entry": 1,
"sort_field": "modified",
"sort_order": "DESC",
"track_changes": 1
}

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