Merge branch 'frappe:develop' into employee_query

This commit is contained in:
Thomas antony
2025-07-12 10:04:35 +05:30
committed by GitHub
158 changed files with 57729 additions and 51079 deletions

View File

@@ -51,6 +51,9 @@ from erpnext.accounts.utils import (
get_fiscal_years,
validate_fiscal_year,
)
from erpnext.accounts.utils import (
get_advance_payment_doctypes as _get_advance_payment_doctypes,
)
from erpnext.buying.utils import update_last_purchase_rate
from erpnext.controllers.print_settings import (
set_print_templates_for_item_table,
@@ -383,10 +386,7 @@ class AccountsController(TransactionBase):
adv = qb.DocType("Advance Payment Ledger Entry")
qb.from_(adv).delete().where(adv.voucher_type.eq(self.doctype) & adv.voucher_no.eq(self.name)).run()
advance_payment_doctypes = frappe.get_hooks("advance_payment_receivable_doctypes") + frappe.get_hooks(
"advance_payment_payable_doctypes"
)
if self.doctype in advance_payment_doctypes:
if self.doctype in self.get_advance_payment_doctypes():
qb.from_(adv).delete().where(
adv.against_voucher_type.eq(self.doctype) & adv.against_voucher_no.eq(self.name)
).run()
@@ -1138,6 +1138,10 @@ class AccountsController(TransactionBase):
return True
def set_taxes_and_charges(self):
if self.doctype == "Material Request":
# Material Request does not have taxes
return
if self.get("taxes") or self.get("is_pos"):
return
@@ -2265,9 +2269,9 @@ class AccountsController(TransactionBase):
)
if not paid_amount:
if self.doctype in frappe.get_hooks("advance_payment_receivable_doctypes"):
if self.doctype in self.get_advance_payment_doctypes(payment_type="receivable"):
new_status = "Not Requested" if paid_amount is None else "Requested"
elif self.doctype in frappe.get_hooks("advance_payment_payable_doctypes"):
elif self.doctype in self.get_advance_payment_doctypes(payment_type="payable"):
new_status = "Not Initiated" if paid_amount is None else "Initiated"
else:
total_amount = self.get("rounded_total") or self.get("grand_total")
@@ -2921,10 +2925,8 @@ class AccountsController(TransactionBase):
repost_ledger.insert()
repost_ledger.submit()
def get_advance_payment_doctypes(self) -> list:
return frappe.get_hooks("advance_payment_receivable_doctypes") + frappe.get_hooks(
"advance_payment_payable_doctypes"
)
def get_advance_payment_doctypes(self, payment_type=None) -> list:
return _get_advance_payment_doctypes(payment_type=payment_type)
def make_advance_payment_ledger_for_journal(self):
advance_payment_doctypes = self.get_advance_payment_doctypes()
@@ -3981,6 +3983,7 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
).format(frappe.bold(parent.name))
)
else: # Sales Order
parent.validate_selling_price()
parent.validate_for_duplicate_items()
parent.validate_warehouse()
parent.update_reserved_qty()

View File

@@ -7,7 +7,7 @@ import json
import frappe
from frappe import ValidationError, _, msgprint
from frappe.contacts.doctype.address.address import render_address
from frappe.utils import cint, flt, getdate
from frappe.utils import cint, flt, format_date, get_link_to_form, getdate
from frappe.utils.data import nowtime
import erpnext
@@ -81,19 +81,38 @@ class BuyingController(SubcontractingController):
)
def validate_posting_date_with_po(self):
po_list = []
for item in self.items:
if item.purchase_order and item.purchase_order not in po_list:
po_list.append(item.purchase_order)
po_list = {x.purchase_order for x in self.items if x.purchase_order}
if not po_list:
return
invalid_po = []
po_dates = frappe._dict(
frappe.get_all(
"Purchase Order",
filters={"name": ["in", po_list]},
fields=["name", "transaction_date"],
as_list=True,
)
)
for po in po_list:
po_posting_date = frappe.get_value("Purchase Order", po, "transaction_date")
if getdate(po_posting_date) > getdate(self.posting_date):
frappe.throw(
_("Posting Date {0} cannot be before Purchase Order Posting Date {1}").format(
frappe.bold(self.posting_date), frappe.bold(po_posting_date)
)
)
po_date = po_dates[po]
if getdate(po_date) > getdate(self.posting_date):
invalid_po.append((get_link_to_form("Purchase Order", po), format_date(po_date)))
if not invalid_po:
return
msg = _("<p>Posting Date {0} cannot be before Purchase Order date for the following:</p><ul>").format(
frappe.bold(format_date(self.posting_date))
)
for po, date in invalid_po:
msg += f"<li>{po} ({date})</li>"
msg += "</ul>"
frappe.throw(_(msg))
def create_package_for_transfer(self) -> None:
"""Create serial and batch package for Sourece Warehouse in case of inter transfer."""

View File

@@ -1581,7 +1581,7 @@ def get_accounting_ledger_preview(doc, filters):
doc.docstatus = 1
if doc.get("update_stock") or doc.doctype in ("Purchase Receipt", "Delivery Note"):
if doc.get("update_stock") or doc.doctype in ("Purchase Receipt", "Delivery Note", "Stock Entry"):
doc.update_stock_ledger()
doc.make_gl_entries()
@@ -1622,7 +1622,7 @@ def get_stock_ledger_preview(doc, filters):
"stock_value_difference",
]
if doc.get("update_stock") or doc.doctype in ("Purchase Receipt", "Delivery Note"):
if doc.get("update_stock") or doc.doctype in ("Purchase Receipt", "Delivery Note", "Stock Entry"):
doc.docstatus = 1
doc.update_stock_ledger()
columns = get_sl_columns(filters)
@@ -1757,8 +1757,9 @@ def make_quality_inspections(doctype, docname, items, inspection_type):
"sample_size": flt(item.get("sample_size")),
"item_serial_no": item.get("serial_no").split("\n")[0] if item.get("serial_no") else None,
"batch_no": item.get("batch_no"),
"child_row_reference": item.get("child_row_reference"),
}
).insert()
)
quality_inspection.save()
inspections.append(quality_inspection.name)
@@ -1771,14 +1772,9 @@ def is_reposting_pending():
)
def future_sle_exists(args, sl_entries=None, allow_force_reposting=True):
def future_sle_exists(args, sl_entries=None):
from erpnext.stock.utils import get_combine_datetime
if allow_force_reposting and frappe.get_single_value(
"Stock Reposting Settings", "do_reposting_for_each_stock_transaction"
):
return True
key = (args.voucher_type, args.voucher_no)
if not hasattr(frappe.local, "future_sle"):
frappe.local.future_sle = {}

View File

@@ -470,7 +470,7 @@ class SubcontractingController(StockController):
i += 1
def __remove_serial_and_batch_bundle(self, item):
if item.serial_and_batch_bundle:
if item.get("serial_and_batch_bundle"):
frappe.delete_doc("Serial and Batch Bundle", item.serial_and_batch_bundle, force=True)
def __get_materials_from_bom(self, item_code, bom_no, exploded_item=0):
@@ -607,12 +607,15 @@ class SubcontractingController(StockController):
rm_obj.use_serial_batch_fields = 1
self.__set_batch_nos(bom_item, item_row, rm_obj, qty)
if self.doctype == "Subcontracting Receipt" and not use_serial_batch_fields:
rm_obj.serial_and_batch_bundle = self.__set_serial_and_batch_bundle(
item_row, rm_obj, rm_obj.consumed_qty
)
if self.doctype == "Subcontracting Receipt":
if not use_serial_batch_fields:
rm_obj.serial_and_batch_bundle = self.__set_serial_and_batch_bundle(
item_row, rm_obj, rm_obj.consumed_qty
)
self.set_rate_for_supplied_items(rm_obj, item_row)
self.set_rate_for_supplied_items(rm_obj, item_row)
elif self.backflush_based_on == "BOM":
self.update_rate_for_supplied_items()
def update_rate_for_supplied_items(self):
if self.doctype != "Subcontracting Receipt":

View File

@@ -47,7 +47,7 @@ def get_columns(filters, trans):
def validate_filters(filters):
for f in ["Fiscal Year", "Based On", "Period", "Company"]:
if not filters.get(f.lower().replace(" ", "_")):
frappe.throw(_("{0} is mandatory").format(f))
frappe.throw(_("{0} is mandatory").format(_(f)))
if not frappe.db.exists("Fiscal Year", filters.get("fiscal_year")):
frappe.throw(_("Fiscal Year {0} Does Not Exist").format(filters.get("fiscal_year")))