mirror of
https://github.com/frappe/erpnext.git
synced 2026-05-09 08:11:19 +00:00
Merge pull request #43468 from frappe/version-14-hotfix
chore: release v14
This commit is contained in:
@@ -84,7 +84,7 @@ def get_api_endpoint(service_provider: str | None = None, use_http: bool = False
|
||||
if service_provider == "exchangerate.host":
|
||||
api = "api.exchangerate.host/convert"
|
||||
elif service_provider == "frankfurter.app":
|
||||
api = "frankfurter.app/{transaction_date}"
|
||||
api = "api.frankfurter.app/{transaction_date}"
|
||||
|
||||
protocol = "https://"
|
||||
if use_http:
|
||||
|
||||
@@ -129,19 +129,31 @@ def calculate_interest_and_amount(outstanding_amount, rate_of_interest, dunning_
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_dunning_letter_text(dunning_type, doc, language=None):
|
||||
def get_dunning_letter_text(dunning_type: str, doc: str | dict, language: str | None = None) -> dict:
|
||||
DOCTYPE = "Dunning Letter Text"
|
||||
FIELDS = ["body_text", "closing_text", "language"]
|
||||
|
||||
if isinstance(doc, str):
|
||||
doc = json.loads(doc)
|
||||
|
||||
if not language:
|
||||
language = doc.get("language")
|
||||
|
||||
if language:
|
||||
filters = {"parent": dunning_type, "language": language}
|
||||
else:
|
||||
filters = {"parent": dunning_type, "is_default_language": 1}
|
||||
letter_text = frappe.db.get_value(
|
||||
"Dunning Letter Text", filters, ["body_text", "closing_text", "language"], as_dict=1
|
||||
)
|
||||
if letter_text:
|
||||
return {
|
||||
"body_text": frappe.render_template(letter_text.body_text, doc),
|
||||
"closing_text": frappe.render_template(letter_text.closing_text, doc),
|
||||
"language": letter_text.language,
|
||||
}
|
||||
letter_text = frappe.db.get_value(
|
||||
DOCTYPE, {"parent": dunning_type, "language": language}, FIELDS, as_dict=1
|
||||
)
|
||||
|
||||
if not letter_text:
|
||||
letter_text = frappe.db.get_value(
|
||||
DOCTYPE, {"parent": dunning_type, "is_default_language": 1}, FIELDS, as_dict=1
|
||||
)
|
||||
|
||||
if not letter_text:
|
||||
return {}
|
||||
|
||||
return {
|
||||
"body_text": frappe.render_template(letter_text.body_text, doc),
|
||||
"closing_text": frappe.render_template(letter_text.closing_text, doc),
|
||||
"language": letter_text.language,
|
||||
}
|
||||
|
||||
@@ -3124,7 +3124,6 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
items_added_or_removed = False # updated to true if any new item is added or removed
|
||||
any_conversion_factor_changed = False
|
||||
|
||||
sales_doctypes = ["Sales Order", "Sales Invoice", "Delivery Note", "Quotation"]
|
||||
parent = frappe.get_doc(parent_doctype, parent_doctype_name)
|
||||
|
||||
check_doc_permissions(parent, "write")
|
||||
@@ -3226,25 +3225,21 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
|
||||
# if rate is greater than price_list_rate, set margin
|
||||
# or set discount
|
||||
child_item.discount_percentage = 0
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(
|
||||
child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"),
|
||||
)
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
child_item.margin_type = "Amount"
|
||||
child_item.margin_rate_or_amount = flt(
|
||||
child_item.rate - child_item.price_list_rate,
|
||||
child_item.precision("margin_rate_or_amount"),
|
||||
)
|
||||
child_item.rate_with_margin = child_item.rate
|
||||
else:
|
||||
child_item.discount_percentage = flt(
|
||||
(1 - flt(child_item.rate) / flt(child_item.price_list_rate)) * 100.0,
|
||||
child_item.precision("discount_percentage"),
|
||||
)
|
||||
child_item.discount_amount = flt(child_item.price_list_rate) - flt(child_item.rate)
|
||||
|
||||
if parent_doctype in sales_doctypes:
|
||||
child_item.margin_type = ""
|
||||
child_item.margin_rate_or_amount = 0
|
||||
child_item.rate_with_margin = 0
|
||||
child_item.margin_type = ""
|
||||
child_item.margin_rate_or_amount = 0
|
||||
child_item.rate_with_margin = 0
|
||||
|
||||
child_item.flags.ignore_validate_update_after_submit = True
|
||||
if new_child_flag:
|
||||
|
||||
@@ -366,3 +366,4 @@ execute:frappe.db.set_single_value('E Commerce Settings', 'show_actual_qty', 1)
|
||||
erpnext.patches.v14_0.delete_orphaned_asset_movement_item_records
|
||||
erpnext.patches.v14_0.remove_cancelled_asset_capitalization_from_asset
|
||||
erpnext.patches.v14_0.enable_set_priority_for_pricing_rules #1
|
||||
erpnext.patches.v14_0.update_currency_exchange_settings_for_frankfurter
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
settings = frappe.get_doc("Currency Exchange Settings")
|
||||
if settings.service_provider != "frankfurter.app":
|
||||
return
|
||||
|
||||
settings.set_parameters_and_result()
|
||||
settings.flags.ignore_validate = True
|
||||
settings.save()
|
||||
@@ -68,9 +68,9 @@ def patched_requests_get(*args, **kwargs):
|
||||
if kwargs["params"].get("date") and kwargs["params"].get("from") and kwargs["params"].get("to"):
|
||||
if test_exchange_values.get(kwargs["params"]["date"]):
|
||||
return PatchResponse({"result": test_exchange_values[kwargs["params"]["date"]]}, 200)
|
||||
elif args[0].startswith("https://frankfurter.app") and kwargs.get("params"):
|
||||
elif args[0].startswith("https://api.frankfurter.app") and kwargs.get("params"):
|
||||
if kwargs["params"].get("base") and kwargs["params"].get("symbols"):
|
||||
date = args[0].replace("https://frankfurter.app/", "")
|
||||
date = args[0].replace("https://api.frankfurter.app/", "")
|
||||
if test_exchange_values.get(date):
|
||||
return PatchResponse(
|
||||
{"rates": {kwargs["params"].get("symbols"): test_exchange_values.get(date)}}, 200
|
||||
|
||||
@@ -80,7 +80,7 @@ def setup_currency_exchange():
|
||||
ces.set("result_key", [])
|
||||
ces.set("req_params", [])
|
||||
|
||||
ces.api_endpoint = "https://frankfurter.app/{transaction_date}"
|
||||
ces.api_endpoint = "https://api.frankfurter.app/{transaction_date}"
|
||||
ces.append("result_key", {"key": "rates"})
|
||||
ces.append("result_key", {"key": "{to_currency}"})
|
||||
ces.append("req_params", {"key": "base", "value": "{from_currency}"})
|
||||
|
||||
@@ -406,7 +406,7 @@ class StockReconciliation(StockController):
|
||||
from erpnext.stock.stock_ledger import get_stock_value_difference
|
||||
|
||||
difference_amount = get_stock_value_difference(
|
||||
row.item_code, row.warehouse, self.posting_date, self.posting_time
|
||||
row.item_code, row.warehouse, self.posting_date, self.posting_time, self.name
|
||||
)
|
||||
|
||||
if not difference_amount:
|
||||
|
||||
@@ -51,7 +51,7 @@ def add_invariant_check_fields(sles):
|
||||
balance_qty = 0.0
|
||||
balance_stock_value = 0.0
|
||||
for idx, sle in enumerate(sles):
|
||||
queue = json.loads(sle.stock_queue)
|
||||
queue = json.loads(sle.stock_queue) if sle.stock_queue else []
|
||||
|
||||
fifo_qty = 0.0
|
||||
fifo_value = 0.0
|
||||
|
||||
@@ -4,6 +4,15 @@
|
||||
|
||||
frappe.query_reports["Warehouse wise Item Balance Age and Value"] = {
|
||||
filters: [
|
||||
{
|
||||
fieldname: "company",
|
||||
label: __("Company"),
|
||||
fieldtype: "Link",
|
||||
width: "80",
|
||||
options: "Company",
|
||||
reqd: 1,
|
||||
default: frappe.defaults.get_user_default("Company"),
|
||||
},
|
||||
{
|
||||
fieldname: "from_date",
|
||||
label: __("From Date"),
|
||||
@@ -40,6 +49,12 @@ frappe.query_reports["Warehouse wise Item Balance Age and Value"] = {
|
||||
fieldtype: "Link",
|
||||
width: "80",
|
||||
options: "Warehouse",
|
||||
get_query: function () {
|
||||
const company = frappe.query_report.get_filter_value("company");
|
||||
return {
|
||||
filters: { company: company },
|
||||
};
|
||||
},
|
||||
},
|
||||
{
|
||||
fieldname: "filter_total_zero_qty",
|
||||
|
||||
@@ -109,8 +109,6 @@ def validate_filters(filters):
|
||||
sle_count = flt(frappe.qb.from_("Stock Ledger Entry").select(Count("name")).run()[0][0])
|
||||
if sle_count > 500000:
|
||||
frappe.throw(_("Please set filter based on Item or Warehouse"))
|
||||
if not filters.get("company"):
|
||||
filters["company"] = frappe.defaults.get_user_default("Company")
|
||||
|
||||
|
||||
def get_warehouse_list(filters):
|
||||
|
||||
@@ -652,7 +652,7 @@ class update_entries_after:
|
||||
sle.stock_value = self.wh_data.stock_value
|
||||
sle.stock_queue = json.dumps(self.wh_data.stock_queue)
|
||||
|
||||
if not sle.is_adjustment_entry or not self.args.get("sle_id"):
|
||||
if not sle.is_adjustment_entry:
|
||||
sle.stock_value_difference = stock_value_difference
|
||||
|
||||
sle.doctype = "Stock Ledger Entry"
|
||||
|
||||
Reference in New Issue
Block a user