mirror of
https://github.com/frappe/erpnext.git
synced 2026-06-25 20:08:34 +00:00
Compare commits
13 Commits
v15.113.0
...
version-15
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
29d8a67619 | ||
|
|
339e11ef18 | ||
|
|
9adfab19dc | ||
|
|
28e4bca4f2 | ||
|
|
b176fb292b | ||
|
|
414b3665c1 | ||
|
|
db8a26a3af | ||
|
|
b80fb47d6e | ||
|
|
2585712500 | ||
|
|
6d12a2aaf7 | ||
|
|
df3c821f98 | ||
|
|
c33d7e5d7b | ||
|
|
c97be8abe1 |
@@ -4,7 +4,7 @@ import inspect
|
||||
import frappe
|
||||
from frappe.utils.user import is_website_user
|
||||
|
||||
__version__ = "15.113.0"
|
||||
__version__ = "15.112.0"
|
||||
|
||||
|
||||
def get_default_company(user=None):
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
"acc_frozen_upto",
|
||||
"ignore_account_closing_balance",
|
||||
"use_legacy_controller_for_pcv",
|
||||
"pcv_job_timeout",
|
||||
"column_break_25",
|
||||
"frozen_accounts_modifier",
|
||||
"tab_break_dpet",
|
||||
@@ -651,6 +652,14 @@
|
||||
"fieldtype": "Check",
|
||||
"label": "Show Party Balance"
|
||||
},
|
||||
{
|
||||
"default": "3600",
|
||||
"depends_on": "eval: !doc.use_legacy_controller_for_pcv",
|
||||
"description": "Timeout (in seconds) for each background job enqueued by Process Period Closing Voucher",
|
||||
"fieldname": "pcv_job_timeout",
|
||||
"fieldtype": "Int",
|
||||
"label": "PCV Job Timeout (seconds)"
|
||||
},
|
||||
{
|
||||
"default": "30, 60, 90, 120",
|
||||
"fieldname": "default_ageing_range",
|
||||
@@ -663,7 +672,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"issingle": 1,
|
||||
"links": [],
|
||||
"modified": "2026-05-18 12:16:33.679345",
|
||||
"modified": "2026-06-24 12:59:41.868865",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Accounts Settings",
|
||||
|
||||
@@ -60,6 +60,7 @@ class AccountsSettings(Document):
|
||||
merge_similar_account_heads: DF.Check
|
||||
over_billing_allowance: DF.Currency
|
||||
post_change_gl_entries: DF.Check
|
||||
pcv_job_timeout: DF.Int
|
||||
receivable_payable_fetch_method: DF.Literal["Buffered Cursor", "UnBuffered Cursor"]
|
||||
receivable_payable_remarks_length: DF.Int
|
||||
reconciliation_queue_size: DF.Int
|
||||
|
||||
@@ -92,6 +92,8 @@ def start_pcv_processing(docname: str):
|
||||
frappe.has_permission("Process Payment Reconciliation", "write", doc=docname, throw=True)
|
||||
frappe.db.set_value("Process Period Closing Voucher", docname, "status", "Running")
|
||||
|
||||
timeout = frappe.db.get_single_value("Accounts Settings", "pcv_job_timeout") or 3600
|
||||
|
||||
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
|
||||
if normal_balances := (
|
||||
qb.from_(ppcvd)
|
||||
@@ -118,7 +120,7 @@ def start_pcv_processing(docname: str):
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date",
|
||||
queue="long",
|
||||
timeout="3600",
|
||||
timeout=timeout,
|
||||
is_async=True,
|
||||
enqueue_after_commit=True,
|
||||
docname=docname,
|
||||
@@ -244,6 +246,8 @@ def get_gle_for_closing_account(pcv, dimension_balance, dimensions):
|
||||
|
||||
@frappe.whitelist()
|
||||
def schedule_next_date(docname: str):
|
||||
timeout = frappe.db.get_single_value("Accounts Settings", "pcv_job_timeout") or 3600
|
||||
|
||||
ppcvd = qb.DocType("Process Period Closing Voucher Detail")
|
||||
if to_process := (
|
||||
qb.from_(ppcvd)
|
||||
@@ -269,7 +273,7 @@ def schedule_next_date(docname: str):
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.process_individual_date",
|
||||
queue="long",
|
||||
timeout="3600",
|
||||
timeout=timeout,
|
||||
is_async=True,
|
||||
enqueue_after_commit=True,
|
||||
docname=docname,
|
||||
@@ -299,7 +303,7 @@ def schedule_next_date(docname: str):
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.process_period_closing_voucher.process_period_closing_voucher.summarize_and_post_ledger_entries",
|
||||
queue="long",
|
||||
timeout="3600",
|
||||
timeout=timeout,
|
||||
is_async=True,
|
||||
job_name=job_name,
|
||||
enqueue_after_commit=True,
|
||||
|
||||
@@ -390,7 +390,6 @@ def get_context(customer, doc):
|
||||
return {
|
||||
"doc": template_doc,
|
||||
"customer": frappe.get_doc("Customer", customer),
|
||||
"frappe": frappe.utils,
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -185,7 +185,7 @@ class calculate_taxes_and_totals:
|
||||
return
|
||||
|
||||
if not self.discount_amount_applied:
|
||||
do_not_round_fields = ["valuation_rate", "incoming_rate"]
|
||||
do_not_round_fields = ["valuation_rate", "incoming_rate", "sales_incoming_rate"]
|
||||
|
||||
for item in self.doc.items:
|
||||
self.doc.round_floats_in(item, do_not_round_fields=do_not_round_fields)
|
||||
|
||||
@@ -136,7 +136,7 @@ def make_opportunity(source_name, target_doc=None):
|
||||
|
||||
@frappe.whitelist()
|
||||
def get_opportunities(prospect):
|
||||
return frappe.get_all(
|
||||
return frappe.get_list(
|
||||
"Opportunity",
|
||||
filters={"opportunity_from": "Prospect", "party_name": prospect},
|
||||
fields=[
|
||||
|
||||
@@ -437,3 +437,4 @@ erpnext.patches.v16_0.clear_procedures_from_receivable_report
|
||||
erpnext.patches.v16_0.migrate_address_contact_custom_fields
|
||||
erpnext.patches.v15_0.set_main_item_code_in_material_request_plan_item
|
||||
erpnext.patches.v16_0.set_posting_datetime_for_sabb_and_drop_indexes
|
||||
execute:frappe.db.set_single_value("Accounts Settings", "pcv_job_timeout", 3600)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
import frappe
|
||||
from frappe import _, msgprint, qb
|
||||
from frappe.query_builder import Criterion
|
||||
from frappe.query_builder import Case, Criterion
|
||||
|
||||
from erpnext import get_company_currency
|
||||
|
||||
@@ -155,50 +155,60 @@ def get_columns(filters):
|
||||
|
||||
|
||||
def get_entries(filters):
|
||||
date_field = filters["doc_type"] == "Sales Order" and "transaction_date" or "posting_date"
|
||||
if filters["doc_type"] == "Sales Order":
|
||||
qty_field = "delivered_qty"
|
||||
else:
|
||||
qty_field = "qty"
|
||||
conditions, values = get_conditions(filters, date_field)
|
||||
doc_type = filters["doc_type"]
|
||||
|
||||
entries = frappe.db.sql(
|
||||
"""
|
||||
SELECT
|
||||
dt.name, dt.customer, dt.territory, dt.{} as posting_date, dt_item.item_code,
|
||||
st.sales_person, st.allocated_percentage, dt_item.warehouse,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN dt_item.{} * dt_item.conversion_factor
|
||||
ELSE dt_item.stock_qty
|
||||
END as stock_qty,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN (dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor)
|
||||
ELSE dt_item.base_net_amount
|
||||
END as base_net_amount,
|
||||
CASE
|
||||
WHEN dt.status = "Closed" THEN ((dt_item.base_net_rate * dt_item.{} * dt_item.conversion_factor) * st.allocated_percentage/100)
|
||||
ELSE dt_item.base_net_amount * st.allocated_percentage/100
|
||||
END as contribution_amt
|
||||
FROM
|
||||
`tab{}` dt, `tab{} Item` dt_item, `tabSales Team` st
|
||||
WHERE
|
||||
st.parent = dt.name and dt.name = dt_item.parent and st.parenttype = {}
|
||||
and dt.docstatus = 1 {} order by st.sales_person, dt.name desc
|
||||
""".format(
|
||||
date_field,
|
||||
qty_field,
|
||||
qty_field,
|
||||
qty_field,
|
||||
filters["doc_type"],
|
||||
filters["doc_type"],
|
||||
"%s",
|
||||
conditions,
|
||||
),
|
||||
tuple([filters["doc_type"], *values]),
|
||||
as_dict=1,
|
||||
date_field = "transaction_date" if doc_type == "Sales Order" else "posting_date"
|
||||
qty_field = "delivered_qty" if doc_type == "Sales Order" else "qty"
|
||||
|
||||
dt = frappe.qb.DocType(doc_type)
|
||||
dt_item = frappe.qb.DocType(f"{doc_type} Item")
|
||||
st = frappe.qb.DocType("Sales Team")
|
||||
|
||||
calc_qty = dt_item[qty_field] * dt_item.conversion_factor
|
||||
calc_net_amount = dt_item.base_net_rate * calc_qty
|
||||
|
||||
stock_qty_case = Case().when(dt.status == "Closed", calc_qty).else_(dt_item.stock_qty).as_("stock_qty")
|
||||
|
||||
base_net_amount_case = (
|
||||
Case()
|
||||
.when(dt.status == "Closed", calc_net_amount)
|
||||
.else_(dt_item.base_net_amount)
|
||||
.as_("base_net_amount")
|
||||
)
|
||||
|
||||
return entries
|
||||
contribution_amt_case = (
|
||||
Case()
|
||||
.when(dt.status == "Closed", (calc_net_amount * st.allocated_percentage / 100))
|
||||
.else_(dt_item.base_net_amount * st.allocated_percentage / 100)
|
||||
.as_("contribution_amt")
|
||||
)
|
||||
|
||||
query = (
|
||||
frappe.get_query(dt, filters=filters, ignore_permissions=False)
|
||||
.join(dt_item)
|
||||
.on(dt.name == dt_item.parent)
|
||||
.join(st)
|
||||
.on(dt.name == st.parent)
|
||||
.select(
|
||||
dt.name,
|
||||
dt.customer,
|
||||
dt.territory,
|
||||
dt[date_field].as_("posting_date"),
|
||||
dt_item.item_code,
|
||||
st.sales_person,
|
||||
st.allocated_percentage,
|
||||
dt_item.warehouse,
|
||||
stock_qty_case,
|
||||
base_net_amount_case,
|
||||
contribution_amt_case,
|
||||
)
|
||||
.where(st.parenttype == doc_type)
|
||||
.where(dt.docstatus == 1)
|
||||
)
|
||||
|
||||
query = query.orderby(st.sales_person).orderby(dt.name, order=frappe.qb.desc)
|
||||
|
||||
return query.run(as_dict=True)
|
||||
|
||||
|
||||
def get_conditions(filters, date_field):
|
||||
|
||||
@@ -208,7 +208,7 @@ frappe.ui.form.on("Company", {
|
||||
reqd: 1,
|
||||
description: __(
|
||||
"Please make sure you really want to delete all the transactions for {0}. Your master data will remain as it is. This action cannot be undone.",
|
||||
[frappe.utils.bold(frm.doc.name)]
|
||||
[frappe.utils.escape_html(frm.doc.name).bold()]
|
||||
),
|
||||
},
|
||||
function (data) {
|
||||
@@ -228,7 +228,9 @@ frappe.ui.form.on("Company", {
|
||||
},
|
||||
});
|
||||
},
|
||||
__("Delete all the Transactions for {0}", [frappe.utils.bold(frm.doc.name)]),
|
||||
__("Delete all the Transactions for {0}", [
|
||||
frappe.utils.escape_html(frm.doc.name).bold(),
|
||||
]),
|
||||
__("Delete")
|
||||
);
|
||||
d.get_primary_btn().addClass("btn-danger");
|
||||
|
||||
@@ -306,6 +306,9 @@ class RepostItemValuation(Document):
|
||||
|
||||
def _recalculate_valuation_rate(self):
|
||||
doc = frappe.get_doc(self.voucher_type, self.voucher_no)
|
||||
if doc.get("is_internal_supplier"):
|
||||
doc.set_sales_incoming_rate_for_internal_transfer()
|
||||
|
||||
doc.update_valuation_rate()
|
||||
for item in doc.items:
|
||||
item.db_set("valuation_rate", item.valuation_rate)
|
||||
|
||||
@@ -588,10 +588,16 @@ def get_serial_nos_from_bundle(serial_and_batch_bundle, serial_nos=None):
|
||||
def get_serial_or_batch_nos(bundle):
|
||||
# For print format
|
||||
|
||||
if not bundle:
|
||||
return ""
|
||||
|
||||
bundle_data = frappe.get_cached_value(
|
||||
"Serial and Batch Bundle", bundle, ["has_serial_no", "has_batch_no"], as_dict=True
|
||||
)
|
||||
|
||||
if not bundle_data:
|
||||
return bundle
|
||||
|
||||
fields = []
|
||||
if bundle_data.has_serial_no:
|
||||
fields.append("serial_no")
|
||||
|
||||
Reference in New Issue
Block a user