Merge pull request #43774 from frappe/version-15-hotfix

chore: release v15
This commit is contained in:
ruthra kumar
2024-10-23 10:17:07 +05:30
committed by GitHub
29 changed files with 272 additions and 159 deletions

View File

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

View File

@@ -168,7 +168,7 @@ def get_payment_entries_for_bank_clearance(
"Payment Entry" as payment_document, name as payment_entry,
reference_no as cheque_number, reference_date as cheque_date,
if(paid_from=%(account)s, paid_amount + total_taxes_and_charges, 0) as credit,
if(paid_from=%(account)s, 0, received_amount) as debit,
if(paid_from=%(account)s, 0, received_amount + total_taxes_and_charges) as debit,
posting_date, ifnull(party,if(paid_from=%(account)s,paid_to,paid_from)) as against_account, clearance_date,
if(paid_to=%(account)s, paid_to_account_currency, paid_from_account_currency) as account_currency
from `tabPayment Entry`

View File

@@ -259,7 +259,7 @@ class JournalEntry(AccountsController):
frappe.throw(_("Journal Entry type should be set as Depreciation Entry for asset depreciation"))
def validate_stock_accounts(self):
stock_accounts = get_stock_accounts(self.company, self.doctype, self.name)
stock_accounts = get_stock_accounts(self.company, accounts=self.accounts)
for account in stock_accounts:
account_bal, stock_bal, warehouse_list = get_stock_and_account_balance(
account, self.posting_date, self.company

View File

@@ -2486,7 +2486,9 @@ def get_party_details(company, party_type, party, date, cost_center=None):
account_balance = get_balance_on(party_account, date, cost_center=cost_center)
_party_name = "title" if party_type == "Shareholder" else party_type.lower() + "_name"
party_name = frappe.db.get_value(party_type, party, _party_name)
party_balance = get_balance_on(party_type=party_type, party=party, cost_center=cost_center)
party_balance = get_balance_on(
party_type=party_type, party=party, company=company, cost_center=cost_center
)
if party_type in ["Customer", "Supplier"]:
party_bank_account = get_party_bank_account(party_type, party)
bank_account = get_default_company_bank_account(company, party_type, party)

View File

@@ -20,6 +20,15 @@ from erpnext.accounts.party import get_party_account, get_party_bank_account
from erpnext.accounts.utils import get_account_currency, get_currency_precision
from erpnext.utilities import payment_app_import_guard
ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST = [
"Sales Order",
"Purchase Order",
"Sales Invoice",
"Purchase Invoice",
"POS Invoice",
"Fees",
]
def _get_payment_gateway_controller(*args, **kwargs):
with payment_app_import_guard():
@@ -525,6 +534,9 @@ def make_payment_request(**args):
args = frappe._dict(args)
if args.dt not in ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST:
frappe.throw(_("Payment Requests cannot be created against: {0}").format(frappe.bold(args.dt)))
ref_doc = frappe.get_doc(args.dt, args.dn)
gateway_account = get_gateway_details(args) or frappe._dict()

View File

@@ -80,8 +80,10 @@ frappe.ui.form.on("POS Closing Entry", {
) {
reset_values(frm);
frappe.run_serially([
() => frappe.dom.freeze(__("Loading Invoices! Please Wait...")),
() => frm.trigger("set_opening_amounts"),
() => frm.trigger("get_pos_invoices"),
() => frappe.dom.unfreeze(),
]);
}
},

View File

@@ -57,6 +57,7 @@ erpnext.selling.POSInvoiceController = class POSInvoiceController extends erpnex
}
onload_post_render(frm) {
super.onload_post_render();
this.pos_profile(frm);
}

View File

@@ -728,14 +728,11 @@ def get_pricing_rule_items(pr_doc, other_items=False) -> list:
def validate_coupon_code(coupon_name):
coupon = frappe.get_doc("Coupon Code", coupon_name)
if coupon.valid_from:
if coupon.valid_from > getdate(today()):
frappe.throw(_("Sorry, this coupon code's validity has not started"))
elif coupon.valid_upto:
if coupon.valid_upto < getdate(today()):
frappe.throw(_("Sorry, this coupon code's validity has expired"))
elif coupon.used >= coupon.maximum_use:
if coupon.valid_from and coupon.valid_from > getdate(today()):
frappe.throw(_("Sorry, this coupon code's validity has not started"))
elif coupon.valid_upto and coupon.valid_upto < getdate(today()):
frappe.throw(_("Sorry, this coupon code's validity has expired"))
elif coupon.maximum_use and coupon.used >= coupon.maximum_use:
frappe.throw(_("Sorry, this coupon code is no longer valid"))

View File

@@ -25,6 +25,7 @@
"payment_terms_template",
"sales_partner",
"sales_person",
"show_remarks",
"based_on_payment_terms",
"section_break_3",
"customer_collection",
@@ -390,10 +391,16 @@
"fieldname": "ignore_cr_dr_notes",
"fieldtype": "Check",
"label": "Ignore System Generated Credit / Debit Notes"
},
{
"default": "0",
"fieldname": "show_remarks",
"fieldtype": "Check",
"label": "Show Remarks"
}
],
"links": [],
"modified": "2024-08-13 10:41:18.381165",
"modified": "2024-10-18 17:51:39.108481",
"modified_by": "Administrator",
"module": "Accounts",
"name": "Process Statement Of Accounts",

View File

@@ -70,6 +70,7 @@ class ProcessStatementOfAccounts(Document):
sales_person: DF.Link | None
sender: DF.Link | None
show_net_values_in_party_account: DF.Check
show_remarks: DF.Check
start_date: DF.Date | None
subject: DF.Data | None
terms_and_conditions: DF.Link | None
@@ -187,6 +188,7 @@ def get_common_filters(doc):
"finance_book": doc.finance_book if doc.finance_book else None,
"account": [doc.account] if doc.account else None,
"cost_center": [cc.cost_center_name for cc in doc.cost_center],
"show_remarks": doc.show_remarks,
}
)

View File

@@ -1359,14 +1359,15 @@ class SalesInvoice(SellingController):
else:
if asset.calculate_depreciation:
notes = _(
"This schedule was created when Asset {0} was sold through Sales Invoice {1}."
).format(
get_link_to_form(asset.doctype, asset.name),
get_link_to_form(self.doctype, self.get("name")),
)
depreciate_asset(asset, self.posting_date, notes)
asset.reload()
if not asset.status == "Fully Depreciated":
notes = _(
"This schedule was created when Asset {0} was sold through Sales Invoice {1}."
).format(
get_link_to_form(asset.doctype, asset.name),
get_link_to_form(self.doctype, self.get("name")),
)
depreciate_asset(asset, self.posting_date, notes)
asset.reload()
fixed_asset_gl_entries = get_gl_entries_on_asset_disposal(
asset,

View File

@@ -881,16 +881,17 @@ def get_party_shipping_address(doctype: str, name: str) -> str | None:
def get_partywise_advanced_payment_amount(
party_type, posting_date=None, future_payment=0, company=None, party=None
):
account_type = frappe.get_cached_value("Party Type", party_type, "account_type")
ple = frappe.qb.DocType("Payment Ledger Entry")
acc = frappe.qb.DocType("Account")
query = (
frappe.qb.from_(ple)
.select(ple.party, Abs(Sum(ple.amount).as_("amount")))
.where(
(ple.party_type.isin(party_type))
& (ple.amount < 0)
& (ple.against_voucher_no == ple.voucher_no)
& (ple.delinked == 0)
)
.inner_join(acc)
.on(ple.account == acc.name)
.select(ple.party)
.where((ple.party_type.isin(party_type)) & (acc.account_type == account_type) & (ple.delinked == 0))
.groupby(ple.party)
)
@@ -909,9 +910,32 @@ def get_partywise_advanced_payment_amount(
if invoice_doctypes := frappe.get_hooks("invoice_doctypes"):
query = query.where(ple.voucher_type.notin(invoice_doctypes))
data = query.run()
if data:
return frappe._dict(data)
# Get advance amount from Receivable / Payable Account
party_ledger = query.select(Abs(Sum(ple.amount).as_("amount")))
party_ledger = party_ledger.where(ple.amount < 0)
party_ledger = party_ledger.where(ple.against_voucher_no == ple.voucher_no)
party_ledger = party_ledger.where(
acc.root_type == ("Liability" if account_type == "Payable" else "Asset")
)
data = party_ledger.run()
data = frappe._dict(data or {})
# Get advance amount from Advance Account
advance_ledger = query.select(Sum(ple.amount).as_("amount"), ple.account)
advance_ledger = advance_ledger.where(
acc.root_type == ("Asset" if account_type == "Payable" else "Liability")
)
advance_ledger = advance_ledger.groupby(ple.account)
advance_ledger = advance_ledger.having(Sum(ple.amount) < 0)
advance_data = advance_ledger.run()
for row in advance_data:
data.setdefault(row[0], 0)
data[row[0]] += abs(row[1])
return data
def get_default_contact(doctype: str, name: str) -> str | None:

View File

@@ -122,13 +122,13 @@ def get_provisional_profit_loss(
for period in period_list:
key = period if consolidated else period.key
total_assets = flt(asset[0].get(key))
total_assets = flt(asset[-2].get(key))
effective_liability = 0.00
if liability:
effective_liability += flt(liability[0].get(key))
if equity:
effective_liability += flt(equity[0].get(key))
if liability and liability[-1] == {}:
effective_liability += flt(liability[-2].get(key))
if equity and equity[-1] == {}:
effective_liability += flt(equity[-2].get(key))
provisional_profit_loss[key] = total_assets - effective_liability
total_row[key] = provisional_profit_loss[key] + effective_liability
@@ -195,9 +195,9 @@ def get_report_summary(
key = period if consolidated else period.key
if asset:
net_asset += asset[-2].get(key)
if liability:
if liability and liability[-1] == {}:
net_liability += liability[-2].get(key)
if equity:
if equity and equity[-1] == {}:
net_equity += equity[-2].get(key)
if provisional_profit_loss:
net_provisional_profit_loss += provisional_profit_loss.get(key)

View File

@@ -122,21 +122,24 @@ class Deferred_Item:
"""
simulate future posting by creating dummy gl entries. starts from the last posting date.
"""
if self.service_start_date != self.service_end_date:
if add_days(self.last_entry_date, 1) < self.period_list[-1].to_date:
self.estimate_for_period_list = get_period_list(
self.filters.from_fiscal_year,
self.filters.to_fiscal_year,
add_days(self.last_entry_date, 1),
self.period_list[-1].to_date,
"Date Range",
"Monthly",
company=self.filters.company,
)
for period in self.estimate_for_period_list:
amount = self.calculate_amount(period.from_date, period.to_date)
gle = self.make_dummy_gle(period.key, period.to_date, amount)
self.gle_entries.append(gle)
if (
self.service_start_date != self.service_end_date
and add_days(self.last_entry_date, 1) < self.service_end_date
):
self.estimate_for_period_list = get_period_list(
self.filters.from_fiscal_year,
self.filters.to_fiscal_year,
add_days(self.last_entry_date, 1),
self.service_end_date,
"Date Range",
"Monthly",
company=self.filters.company,
)
for period in self.estimate_for_period_list:
amount = self.calculate_amount(period.from_date, period.to_date)
gle = self.make_dummy_gle(period.key, period.to_date, amount)
self.gle_entries.append(gle)
def calculate_item_revenue_expense_for_period(self):
"""

View File

@@ -1547,12 +1547,16 @@ def compare_existing_and_expected_gle(existing_gle, expected_gle, precision):
return matched
def get_stock_accounts(company, voucher_type=None, voucher_no=None):
def get_stock_accounts(company, voucher_type=None, voucher_no=None, accounts=None):
stock_accounts = [
d.name
for d in frappe.db.get_all("Account", {"account_type": "Stock", "company": company, "is_group": 0})
]
if voucher_type and voucher_no:
if accounts:
stock_accounts = [row.account for row in accounts if row.account in stock_accounts]
elif voucher_type and voucher_no:
if voucher_type == "Journal Entry":
stock_accounts = [
d.account

View File

@@ -144,6 +144,7 @@ def update_maintenance_log(asset_maintenance, item_code, item_name, task):
"has_certificate": task.certificate_required,
"description": task.description,
"assign_to_name": task.assign_to_name,
"task_assignee_email": task.assign_to,
"periodicity": str(task.periodicity),
"maintenance_type": task.maintenance_type,
"due_date": task.next_due_date,

View File

@@ -23,6 +23,7 @@
"column_break_6",
"maintenance_status",
"assign_to_name",
"task_assignee_email",
"due_date",
"completion_date",
"description",
@@ -168,15 +169,22 @@
"in_preview": 1,
"label": "Task Name",
"read_only": 1
},
{
"fieldname": "task_assignee_email",
"fieldtype": "Data",
"label": "Task Assignee Email",
"read_only": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2021-01-22 12:33:45.888124",
"modified": "2024-09-24 15:12:37.497853",
"modified_by": "Administrator",
"module": "Assets",
"name": "Asset Maintenance Log",
"naming_rule": "By \"Naming Series\" field",
"owner": "Administrator",
"permissions": [
{
@@ -199,4 +207,4 @@
"sort_order": "DESC",
"track_changes": 1,
"track_seen": 1
}
}

View File

@@ -37,6 +37,7 @@ class AssetMaintenanceLog(Document):
naming_series: DF.Literal["ACC-AML-.YYYY.-"]
periodicity: DF.Data | None
task: DF.Link | None
task_assignee_email: DF.Data | None
task_name: DF.Data | None
# end: auto-generated types

View File

@@ -393,12 +393,15 @@ class AccountsController(TransactionBase):
def validate_return_against_account(self):
if self.doctype in ["Sales Invoice", "Purchase Invoice"] and self.is_return and self.return_against:
cr_dr_account_field = "debit_to" if self.doctype == "Sales Invoice" else "credit_to"
cr_dr_account_label = "Debit To" if self.doctype == "Sales Invoice" else "Credit To"
cr_dr_account = self.get(cr_dr_account_field)
if frappe.get_value(self.doctype, self.return_against, cr_dr_account_field) != cr_dr_account:
original_account = frappe.get_value(self.doctype, self.return_against, cr_dr_account_field)
if original_account != self.get(cr_dr_account_field):
frappe.throw(
_("'{0}' account: '{1}' should match the Return Against Invoice").format(
frappe.bold(cr_dr_account_label), frappe.bold(cr_dr_account)
_(
"Please set {0} to {1}, the same account that was used in the original invoice {2}."
).format(
frappe.bold(_(self.meta.get_label(cr_dr_account_field), context=self.doctype)),
frappe.bold(original_account),
frappe.bold(self.return_against),
)
)
@@ -3521,6 +3524,9 @@ def update_child_qty_rate(parent_doctype, trans_items, parent_doctype_name, chil
parent.update_billing_percentage()
parent.set_status()
parent.validate_uom_is_integer("uom", "qty")
parent.validate_uom_is_integer("stock_uom", "stock_qty")
# Cancel and Recreate Stock Reservation Entries.
if parent_doctype == "Sales Order":
from erpnext.stock.doctype.stock_reservation_entry.stock_reservation_entry import (

View File

@@ -1235,6 +1235,17 @@ def add_items_in_ste(ste_doc, row, qty, rm_details, rm_detail_field="sco_rm_deta
def make_return_stock_entry_for_subcontract(
available_materials, order_doc, rm_details, order_doctype="Subcontracting Order"
):
def post_process(source_doc, target_doc):
target_doc.purpose = "Material Transfer"
if source_doc.doctype == "Purchase Order":
target_doc.purchase_order = source_doc.name
else:
target_doc.subcontracting_order = source_doc.name
target_doc.company = source_doc.company
target_doc.is_return = 1
ste_doc = get_mapped_doc(
order_doctype,
order_doc.name,
@@ -1245,18 +1256,13 @@ def make_return_stock_entry_for_subcontract(
},
},
ignore_child_tables=True,
postprocess=post_process,
)
ste_doc.purpose = "Material Transfer"
if order_doctype == "Purchase Order":
ste_doc.purchase_order = order_doc.name
rm_detail_field = "po_detail"
else:
ste_doc.subcontracting_order = order_doc.name
rm_detail_field = "sco_rm_detail"
ste_doc.company = order_doc.company
ste_doc.is_return = 1
for _key, value in available_materials.items():
if not value.qty:

View File

@@ -7,9 +7,9 @@ cur_frm.email_field = "email_id";
erpnext.LeadController = class LeadController extends frappe.ui.form.Controller {
setup() {
this.frm.make_methods = {
Customer: this.make_customer,
Quotation: this.make_quotation,
Opportunity: this.make_opportunity,
Customer: this.make_customer.bind(this),
Quotation: this.make_quotation.bind(this),
Opportunity: this.make_opportunity.bind(this),
};
// For avoiding integration issues.

View File

@@ -1,4 +1,5 @@
{
"app": "erpnext",
"charts": [],
"content": "[{\"id\":\"csBCiDglCE\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Your Shortcuts</b></span>\",\"col\":12}},{\"id\":\"YHCQG3wAGv\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Creator\",\"col\":3}},{\"id\":\"xit0dg7KvY\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM\",\"col\":3}},{\"id\":\"LRhGV9GAov\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Plan\",\"col\":3}},{\"id\":\"69KKosI6Hg\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Work Order\",\"col\":3}},{\"id\":\"PwndxuIpB3\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Job Card\",\"col\":3}},{\"id\":\"Ubj6zXcmIQ\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Plant Floor\",\"col\":3}},{\"id\":\"OtMcArFRa5\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"BOM Stock Report\",\"col\":3}},{\"id\":\"76yYsI5imF\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Production Planning Report\",\"col\":3}},{\"id\":\"PIQJYZOMnD\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Learn Manufacturing\",\"col\":3}},{\"id\":\"OaiDqTT03Y\",\"type\":\"shortcut\",\"data\":{\"shortcut_name\":\"Forecasting\",\"col\":3}},{\"id\":\"bN_6tHS-Ct\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"yVEFZMqVwd\",\"type\":\"header\",\"data\":{\"text\":\"<span class=\\\"h4\\\"><b>Reports &amp; Masters</b></span>\",\"col\":12}},{\"id\":\"rwrmsTI58-\",\"type\":\"card\",\"data\":{\"card_name\":\"Production\",\"col\":4}},{\"id\":\"6dnsyX-siZ\",\"type\":\"card\",\"data\":{\"card_name\":\"Bill of Materials\",\"col\":4}},{\"id\":\"CIq-v5f5KC\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}},{\"id\":\"8RRiQeYr0G\",\"type\":\"card\",\"data\":{\"card_name\":\"Tools\",\"col\":4}},{\"id\":\"Pu8z7-82rT\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}}]",
"creation": "2020-03-02 17:11:37.032604",
@@ -124,11 +125,86 @@
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Bill of Materials",
"link_count": 6,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Item",
"link_count": 0,
"link_to": "Item",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "Item",
"hidden": 0,
"is_query_report": 0,
"label": "Bill of Materials",
"link_count": 0,
"link_to": "BOM",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workstation Type",
"link_count": 0,
"link_to": "Workstation Type",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workstation",
"link_count": 0,
"link_to": "Workstation",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Operation",
"link_count": 0,
"link_to": "Operation",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "Work Order",
"hidden": 0,
"is_query_report": 1,
"label": "Routing",
"link_count": 0,
"link_to": "Routing",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Reports",
"link_count": 10,
"link_type": "DocType",
"onboard": 0,
"type": "Card Break"
},
@@ -233,90 +309,16 @@
},
{
"hidden": 0,
"is_query_report": 0,
"is_query_report": 1,
"label": "Work Order Consumed Materials",
"link_count": 0,
"link_to": "Work Order Consumed Materials",
"link_type": "Report",
"onboard": 0,
"type": "Link"
},
{
"hidden": 0,
"is_query_report": 0,
"label": "Bill of Materials",
"link_count": 6,
"onboard": 0,
"type": "Card Break"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Item",
"link_count": 0,
"link_to": "Item",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "Item",
"hidden": 0,
"is_query_report": 0,
"label": "Bill of Materials",
"link_count": 0,
"link_to": "BOM",
"link_type": "DocType",
"onboard": 1,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workstation Type",
"link_count": 0,
"link_to": "Workstation Type",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Workstation",
"link_count": 0,
"link_to": "Workstation",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "",
"hidden": 0,
"is_query_report": 0,
"label": "Operation",
"link_count": 0,
"link_to": "Operation",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
},
{
"dependencies": "Work Order",
"hidden": 0,
"is_query_report": 1,
"label": "Routing",
"link_count": 0,
"link_to": "Routing",
"link_type": "DocType",
"onboard": 0,
"type": "Link"
}
],
"modified": "2024-01-30 21:49:58.577218",
"modified": "2024-10-21 14:13:38.777556",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Manufacturing",
@@ -398,5 +400,6 @@
"type": "Report"
}
],
"title": "Manufacturing"
"title": "Manufacturing",
"type": "Workspace"
}

View File

@@ -378,3 +378,4 @@ erpnext.patches.v15_0.add_disassembly_order_stock_entry_type #1
erpnext.patches.v15_0.set_standard_stock_entry_type
erpnext.patches.v15_0.link_purchase_item_to_asset_doc
erpnext.patches.v14_0.update_currency_exchange_settings_for_frankfurter
erpnext.patches.v15_0.update_task_assignee_email_field_in_asset_maintenance_log

View File

@@ -0,0 +1,18 @@
import frappe
from frappe.query_builder import DocType
def execute():
if frappe.db.has_column("Asset Maintenance Log", "task_assignee_email"):
asset_maintenance_log = DocType("Asset Maintenance Log")
asset_maintenance_task = DocType("Asset Maintenance Task")
try:
(
frappe.qb.update(asset_maintenance_log)
.set(asset_maintenance_log.task_assignee_email, asset_maintenance_task.assign_to)
.join(asset_maintenance_task)
.on(asset_maintenance_log.task == asset_maintenance_task.name)
.run()
)
except Exception:
frappe.log_error("Failed to update Task Assignee Email Field.")

View File

@@ -4,7 +4,8 @@ erpnext.accounts.unreconcile_payment = {
add_unreconcile_btn(frm) {
if (frm.doc.docstatus == 1) {
if (
(frm.doc.doctype == "Journal Entry" && frm.doc.voucher_type != "Journal Entry") ||
(frm.doc.doctype == "Journal Entry" &&
!["Journal Entry", "Bank Entry", "Cash Entry"].includes(frm.doc.voucher_type)) ||
!["Purchase Invoice", "Sales Invoice", "Journal Entry", "Payment Entry"].includes(
frm.doc.doctype
)

View File

@@ -11,14 +11,17 @@ doctype_list = [
def get_message(doctype):
return _("{0} has been submitted successfully").format(_(doctype))
# Properly format the string with translated doctype
return _("{0} has been submitted successfully").format(doctype)
def get_first_success_message(doctype):
# Reuse the get_message function for consistency
return get_message(doctype)
def get_default_success_action():
# Loop through each doctype in the list and return formatted actions
return [
{
"doctype": "Success Action",

View File

@@ -1298,7 +1298,7 @@ erpnext.stock.StockEntry = class StockEntry extends erpnext.stock.StockControlle
this.frm.cscript.toggle_enable_bom();
if (doc.purpose == "Send to Subcontractor") {
if (erpnext.stock.is_subcontracting_or_return_transfer(doc)) {
doc.customer =
doc.customer_name =
doc.customer_address =
@@ -1364,6 +1364,10 @@ erpnext.stock.select_batch_and_serial_no = (frm, item) => {
});
};
erpnext.stock.is_subcontracting_or_return_transfer = (doc) => {
return doc.purpose == "Send to Subcontractor" || (doc.purpose == "Material Transfer" && doc.is_return);
};
function attach_bom_items(bom_no) {
if (!bom_no) {
return;

View File

@@ -154,14 +154,14 @@
"search_index": 1
},
{
"depends_on": "eval:doc.purpose==\"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "purchase_order",
"fieldtype": "Link",
"label": "Purchase Order",
"options": "Purchase Order"
},
{
"depends_on": "eval:doc.purpose==\"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "subcontracting_order",
"fieldtype": "Link",
"label": "Subcontracting Order",
@@ -427,13 +427,13 @@
},
{
"collapsible": 1,
"depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "contact_section",
"fieldtype": "Section Break",
"label": "Supplier Details"
},
{
"depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "supplier",
"fieldtype": "Link",
"label": "Supplier",
@@ -445,7 +445,7 @@
},
{
"bold": 1,
"depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "supplier_name",
"fieldtype": "Data",
"label": "Supplier Name",
@@ -455,7 +455,7 @@
"read_only": 1
},
{
"depends_on": "eval:doc.purpose === \"Send to Subcontractor\"",
"depends_on": "eval: erpnext.stock.is_subcontracting_or_return_transfer(doc)",
"fieldname": "supplier_address",
"fieldtype": "Link",
"label": "Supplier Address",

View File

@@ -4,6 +4,10 @@
import frappe
from frappe import _
from erpnext.accounts.doctype.payment_request.payment_request import (
ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST,
)
def get_context(context):
context.no_cache = 1
@@ -46,8 +50,10 @@ def get_context(context):
)
context.available_loyalty_points = int(loyalty_program_details.get("loyalty_points"))
context.show_pay_button = "payments" in frappe.get_installed_apps() and frappe.db.get_single_value(
"Buying Settings", "show_pay_button"
context.show_pay_button = (
"payments" in frappe.get_installed_apps()
and frappe.db.get_single_value("Buying Settings", "show_pay_button")
and context.doc.doctype in ALLOWED_DOCTYPES_FOR_PAYMENT_REQUEST
)
context.show_make_pi_button = False
if context.doc.get("supplier"):