mirror of
https://github.com/frappe/erpnext.git
synced 2026-02-17 16:45:02 +00:00
Merge branch 'develop' into prevent-negative-operation-time-and-batch-size
This commit is contained in:
@@ -8,7 +8,6 @@ erpnext/assets/ @khushi8112
|
||||
erpnext/regional @ruthra-kumar
|
||||
erpnext/selling @ruthra-kumar
|
||||
erpnext/support/ @ruthra-kumar
|
||||
pos* @diptanilsaha
|
||||
|
||||
erpnext/buying/ @rohitwaghchaure @mihir-kandoi
|
||||
erpnext/maintenance/ @rohitwaghchaure
|
||||
|
||||
@@ -18,6 +18,7 @@ def create_charts(
|
||||
accounts = []
|
||||
|
||||
def _import_accounts(children, parent, root_type, root_account=False):
|
||||
nonlocal custom_chart
|
||||
for account_name, child in children.items():
|
||||
if root_account:
|
||||
root_type = child.get("root_type")
|
||||
@@ -55,7 +56,8 @@ def create_charts(
|
||||
"account_number": account_number,
|
||||
"account_type": child.get("account_type"),
|
||||
"account_currency": child.get("account_currency")
|
||||
or frappe.get_cached_value("Company", company, "default_currency"),
|
||||
if custom_chart
|
||||
else frappe.get_cached_value("Company", company, "default_currency"),
|
||||
"tax_rate": child.get("tax_rate"),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -9,7 +9,7 @@ from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.query_builder.custom import ConstantColumn
|
||||
from frappe.query_builder.functions import Sum
|
||||
from frappe.utils import cint, flt
|
||||
from frappe.utils import cint, create_batch, flt
|
||||
|
||||
from erpnext import get_default_cost_center
|
||||
from erpnext.accounts.doctype.bank_transaction.bank_transaction import get_total_allocated_amount
|
||||
@@ -377,16 +377,17 @@ def auto_reconcile_vouchers(
|
||||
bank_transactions = get_bank_transactions(bank_account)
|
||||
|
||||
if len(bank_transactions) > 10:
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.start_auto_reconcile",
|
||||
queue="long",
|
||||
bank_transactions=bank_transactions,
|
||||
from_date=from_date,
|
||||
to_date=to_date,
|
||||
filter_by_reference_date=filter_by_reference_date,
|
||||
from_reference_date=from_reference_date,
|
||||
to_reference_date=to_reference_date,
|
||||
)
|
||||
for bank_transaction_batch in create_batch(bank_transactions, 1000):
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.bank_reconciliation_tool.bank_reconciliation_tool.start_auto_reconcile",
|
||||
queue="long",
|
||||
bank_transactions=bank_transaction_batch,
|
||||
from_date=from_date,
|
||||
to_date=to_date,
|
||||
filter_by_reference_date=filter_by_reference_date,
|
||||
from_reference_date=from_reference_date,
|
||||
to_reference_date=to_reference_date,
|
||||
)
|
||||
frappe.msgprint(_("Auto Reconciliation has started in the background"))
|
||||
else:
|
||||
start_auto_reconcile(
|
||||
|
||||
@@ -252,7 +252,7 @@ frappe.ui.form.on("Bank Statement Import", {
|
||||
|
||||
open_url_post(method, {
|
||||
doctype: "Bank Transaction",
|
||||
export_records: "5_records",
|
||||
export_records: "blank_template",
|
||||
export_fields: {
|
||||
"Bank Transaction": [
|
||||
"date",
|
||||
|
||||
@@ -302,7 +302,7 @@ def compare_expense_with_budget(args, budget_amount, action_for, action, budget_
|
||||
|
||||
|
||||
def get_expense_breakup(args, currency, budget_against):
|
||||
msg = "<hr>Total Expenses booked through - <ul>"
|
||||
msg = "<hr> {{ _('Total Expenses booked through') }} - <ul>"
|
||||
|
||||
common_filters = frappe._dict(
|
||||
{
|
||||
@@ -316,7 +316,7 @@ def get_expense_breakup(args, currency, budget_against):
|
||||
"<li>"
|
||||
+ frappe.utils.get_link_to_report(
|
||||
"General Ledger",
|
||||
label="Actual Expenses",
|
||||
label=_("Actual Expenses"),
|
||||
filters=common_filters.copy().update(
|
||||
{
|
||||
"from_date": frappe.get_cached_value("Fiscal Year", args.fiscal_year, "year_start_date"),
|
||||
@@ -334,7 +334,7 @@ def get_expense_breakup(args, currency, budget_against):
|
||||
"<li>"
|
||||
+ frappe.utils.get_link_to_report(
|
||||
"Material Request",
|
||||
label="Material Requests",
|
||||
label=_("Material Requests"),
|
||||
report_type="Report Builder",
|
||||
doctype="Material Request",
|
||||
filters=common_filters.copy().update(
|
||||
@@ -357,7 +357,7 @@ def get_expense_breakup(args, currency, budget_against):
|
||||
"<li>"
|
||||
+ frappe.utils.get_link_to_report(
|
||||
"Purchase Order",
|
||||
label="Unbilled Orders",
|
||||
label=_("Unbilled Orders"),
|
||||
report_type="Report Builder",
|
||||
doctype="Purchase Order",
|
||||
filters=common_filters.copy().update(
|
||||
|
||||
@@ -296,6 +296,7 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Posting Time",
|
||||
@@ -1598,7 +1599,7 @@
|
||||
"icon": "fa fa-file-text",
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-18 16:50:30.516162",
|
||||
"modified": "2025-08-04 22:22:31.471752",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "POS Invoice",
|
||||
|
||||
@@ -41,56 +41,68 @@ frappe.ui.form.on("Pricing Rule", {
|
||||
<tr><td>
|
||||
<h4>
|
||||
<i class="fa fa-hand-right"></i>
|
||||
{{__('Notes')}}
|
||||
${__("Notes")}
|
||||
</h4>
|
||||
<ul>
|
||||
<li>
|
||||
{{__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria.")}}
|
||||
${__("Pricing Rule is made to overwrite Price List / define discount percentage, based on some criteria.")}
|
||||
</li>
|
||||
<li>
|
||||
{{__("If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field.")}}
|
||||
${__(
|
||||
"If selected Pricing Rule is made for 'Rate', it will overwrite Price List. Pricing Rule rate is the final rate, so no further discount should be applied. Hence, in transactions like Sales Order, Purchase Order etc, it will be fetched in 'Rate' field, rather than 'Price List Rate' field."
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{{__('Discount Percentage can be applied either against a Price List or for all Price List.')}}
|
||||
${__("Discount Percentage can be applied either against a Price List or for all Price List.")}
|
||||
</li>
|
||||
<li>
|
||||
{{__('To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled.')}}
|
||||
${__(
|
||||
"To not apply Pricing Rule in a particular transaction, all applicable Pricing Rules should be disabled."
|
||||
)}
|
||||
</li>
|
||||
</ul>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<h4><i class="fa fa-question-sign"></i>
|
||||
{{__('How Pricing Rule is applied?')}}
|
||||
${__("How Pricing Rule is applied?")}
|
||||
</h4>
|
||||
<ol>
|
||||
<li>
|
||||
{{__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand.")}}
|
||||
${__("Pricing Rule is first selected based on 'Apply On' field, which can be Item, Item Group or Brand.")}
|
||||
</li>
|
||||
<li>
|
||||
{{__("Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc.")}}
|
||||
${__(
|
||||
"Then Pricing Rules are filtered out based on Customer, Customer Group, Territory, Supplier, Supplier Type, Campaign, Sales Partner etc."
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{{__('Pricing Rules are further filtered based on quantity.')}}
|
||||
${__("Pricing Rules are further filtered based on quantity.")}
|
||||
</li>
|
||||
<li>
|
||||
{{__('If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions.')}}
|
||||
${__(
|
||||
"If two or more Pricing Rules are found based on the above conditions, Priority is applied. Priority is a number between 0 to 20 while default value is zero (blank). Higher number means it will take precedence if there are multiple Pricing Rules with same conditions."
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{{__('Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:')}}
|
||||
${__(
|
||||
"Even if there are multiple Pricing Rules with highest priority, then following internal priorities are applied:"
|
||||
)}
|
||||
<ul>
|
||||
<li>
|
||||
{{__('Item Code > Item Group > Brand')}}
|
||||
${__("Item Code > Item Group > Brand")}
|
||||
</li>
|
||||
<li>
|
||||
{{__('Customer > Customer Group > Territory')}}
|
||||
${__("Customer > Customer Group > Territory")}
|
||||
</li>
|
||||
<li>
|
||||
{{__('Supplier > Supplier Type')}}
|
||||
${__("Supplier > Supplier Type")}
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>
|
||||
{{__('If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict.')}}
|
||||
${__(
|
||||
"If multiple Pricing Rules continue to prevail, users are asked to set Priority manually to resolve conflict."
|
||||
)}
|
||||
</li>
|
||||
</ol>
|
||||
</td></tr>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import getdate
|
||||
from frappe.utils import create_batch, getdate
|
||||
|
||||
from erpnext.accounts.doctype.subscription.subscription import DateTimeLikeObject, process_all
|
||||
|
||||
@@ -23,7 +23,23 @@ class ProcessSubscription(Document):
|
||||
# end: auto-generated types
|
||||
|
||||
def on_submit(self):
|
||||
process_all(subscription=self.subscription, posting_date=self.posting_date)
|
||||
self.process_all_subscription()
|
||||
|
||||
def process_all_subscription(self):
|
||||
filters = {"status": ("!=", "Cancelled")}
|
||||
|
||||
if self.subscription:
|
||||
filters["name"] = self.subscription
|
||||
|
||||
subscriptions = frappe.get_all("Subscription", filters, pluck="name")
|
||||
|
||||
for subscription in create_batch(subscriptions, 500):
|
||||
frappe.enqueue(
|
||||
method="erpnext.accounts.doctype.subscription.subscription.process_all",
|
||||
queue="long",
|
||||
subscription=subscription,
|
||||
posting_date=self.posting_date,
|
||||
)
|
||||
|
||||
|
||||
def create_subscription_process(
|
||||
|
||||
@@ -322,6 +322,7 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Posting Time",
|
||||
@@ -1668,7 +1669,7 @@
|
||||
"idx": 204,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-07-30 23:16:05.722875",
|
||||
"modified": "2025-08-04 19:19:11.380664",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Purchase Invoice",
|
||||
|
||||
@@ -373,6 +373,7 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"hide_days": 1,
|
||||
@@ -2232,7 +2233,7 @@
|
||||
"link_fieldname": "consolidated_invoice"
|
||||
}
|
||||
],
|
||||
"modified": "2025-06-26 14:06:56.773552",
|
||||
"modified": "2025-08-04 19:20:28.732039",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Sales Invoice",
|
||||
|
||||
@@ -756,18 +756,14 @@ def get_prorata_factor(
|
||||
return diff / plan_days
|
||||
|
||||
|
||||
def process_all(subscription: str | None = None, posting_date: DateTimeLikeObject | None = None) -> None:
|
||||
def process_all(subscription: list, posting_date: DateTimeLikeObject | None = None) -> None:
|
||||
"""
|
||||
Task to updates the status of all `Subscription` apart from those that are cancelled
|
||||
"""
|
||||
filters = {"status": ("!=", "Cancelled")}
|
||||
|
||||
if subscription:
|
||||
filters["name"] = subscription
|
||||
|
||||
for subscription in frappe.get_all("Subscription", filters, pluck="name"):
|
||||
for subscription_name in subscription:
|
||||
try:
|
||||
subscription = frappe.get_doc("Subscription", subscription)
|
||||
subscription = frappe.get_doc("Subscription", subscription_name)
|
||||
subscription.process(posting_date)
|
||||
frappe.db.commit()
|
||||
except frappe.ValidationError:
|
||||
|
||||
@@ -61,7 +61,7 @@
|
||||
},
|
||||
{
|
||||
"default": "0",
|
||||
"description": "Even invoices with apply tax withholding unchecked will be considered for checking cumulative threshold breach",
|
||||
"description": "Only payment entries with apply tax withholding unchecked will be considered for checking cumulative threshold breach",
|
||||
"fieldname": "consider_party_ledger_amount",
|
||||
"fieldtype": "Check",
|
||||
"label": "Consider Entire Party Ledger Amount"
|
||||
@@ -83,10 +83,11 @@
|
||||
],
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:10:52.531436",
|
||||
"modified": "2025-07-30 07:13:51.785735",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Accounts",
|
||||
"name": "Tax Withholding Category",
|
||||
"naming_rule": "Set by user",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
@@ -126,8 +127,9 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": [],
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +197,11 @@ frappe.query_reports["General Ledger"] = {
|
||||
label: __("Show Net Values in Party Account"),
|
||||
fieldtype: "Check",
|
||||
},
|
||||
{
|
||||
fieldname: "show_amount_in_company_currency",
|
||||
label: __("Show Credit / Debit in Company Currency"),
|
||||
fieldtype: "Check",
|
||||
},
|
||||
{
|
||||
fieldname: "add_values_in_transaction_currency",
|
||||
label: __("Add Columns in Transaction Currency"),
|
||||
|
||||
@@ -627,6 +627,18 @@ def get_columns(filters):
|
||||
company = filters.get("company") or get_default_company()
|
||||
filters["presentation_currency"] = currency = get_company_currency(company)
|
||||
|
||||
company_currency = get_company_currency(filters.get("company") or get_default_company())
|
||||
|
||||
if (
|
||||
filters.get("show_amount_in_company_currency")
|
||||
and filters["presentation_currency"] != company_currency
|
||||
):
|
||||
frappe.throw(
|
||||
_(
|
||||
f'Presentation Currency cannot be {frappe.bold(filters["presentation_currency"])} , When {frappe.bold("Show Credit / Debit in Company Currency")} is enabled.'
|
||||
)
|
||||
)
|
||||
|
||||
columns = [
|
||||
{
|
||||
"label": _("GL Entry"),
|
||||
|
||||
@@ -45,6 +45,7 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
|
||||
gle_map = get_gle_map(tds_docs)
|
||||
|
||||
out = []
|
||||
entries = {}
|
||||
for name, details in gle_map.items():
|
||||
for entry in details:
|
||||
tax_amount, total_amount, grand_total, base_total = 0, 0, 0, 0
|
||||
@@ -119,8 +120,13 @@ def get_result(filters, tds_docs, tds_accounts, tax_category_map, journal_entry_
|
||||
"supplier_invoice_date": bill_date,
|
||||
}
|
||||
)
|
||||
out.append(row)
|
||||
|
||||
key = entry.voucher_no
|
||||
if key in entries:
|
||||
entries[key]["tax_amount"] += tax_amount
|
||||
else:
|
||||
entries[key] = row
|
||||
out = list(entries.values())
|
||||
out.sort(key=lambda x: (x["section_code"], x["transaction_date"]))
|
||||
|
||||
return out
|
||||
|
||||
@@ -118,7 +118,7 @@ def convert_to_presentation_currency(gl_entries, currency_info, filters=None):
|
||||
len(account_currencies) == 1
|
||||
and account_currency == presentation_currency
|
||||
and not exchange_gain_or_loss
|
||||
):
|
||||
) and not filters.get("show_amount_in_company_currency"):
|
||||
entry["debit"] = debit_in_account_currency
|
||||
entry["credit"] = credit_in_account_currency
|
||||
else:
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
# License: GNU General Public License v3. See license.txt
|
||||
|
||||
|
||||
from collections import defaultdict
|
||||
from json import loads
|
||||
from typing import TYPE_CHECKING, Optional
|
||||
|
||||
@@ -2451,25 +2452,37 @@ def sync_auto_reconcile_config(auto_reconciliation_job_trigger: int = 15):
|
||||
).save()
|
||||
|
||||
|
||||
def get_link_fields_grouped_by_option(doctype):
|
||||
meta = frappe.get_meta(doctype)
|
||||
link_fields_map = defaultdict(list)
|
||||
|
||||
for df in meta.fields:
|
||||
if df.fieldtype == "Link" and df.options and not df.ignore_user_permissions:
|
||||
link_fields_map[df.options].append(df.fieldname)
|
||||
|
||||
return link_fields_map
|
||||
|
||||
|
||||
def build_qb_match_conditions(doctype, user=None) -> list:
|
||||
match_filters = build_match_conditions(doctype, user, False)
|
||||
link_fields_map = get_link_fields_grouped_by_option(doctype)
|
||||
criterion = []
|
||||
apply_strict_user_permissions = frappe.get_system_settings("apply_strict_user_permissions")
|
||||
|
||||
if match_filters:
|
||||
from frappe import qb
|
||||
|
||||
_dt = qb.DocType(doctype)
|
||||
|
||||
for filter in match_filters:
|
||||
for d, names in filter.items():
|
||||
fieldname = d.lower().replace(" ", "_")
|
||||
field = _dt[fieldname]
|
||||
for link_option, allowed_values in filter.items():
|
||||
fieldnames = link_fields_map.get(link_option, [])
|
||||
|
||||
cond = field.isin(names)
|
||||
if not apply_strict_user_permissions:
|
||||
cond = (Coalesce(field, "") == "") | field.isin(names)
|
||||
for fieldname in fieldnames:
|
||||
field = _dt[fieldname]
|
||||
cond = field.isin(allowed_values)
|
||||
|
||||
criterion.append(cond)
|
||||
if not apply_strict_user_permissions:
|
||||
cond = (Coalesce(field, "") == "") | cond
|
||||
|
||||
criterion.append(cond)
|
||||
|
||||
return criterion
|
||||
|
||||
@@ -1106,7 +1106,7 @@ def make_journal_entry(asset_name):
|
||||
je.voucher_type = "Depreciation Entry"
|
||||
je.naming_series = depreciation_series
|
||||
je.company = asset.company
|
||||
je.remark = f"Depreciation Entry against asset {asset_name}"
|
||||
je.remark = _("Depreciation Entry against asset {0}").format(asset_name)
|
||||
|
||||
je.append(
|
||||
"accounts",
|
||||
|
||||
@@ -249,7 +249,9 @@ def setup_journal_entry_metadata(je, depr_schedule_doc, depr_series, depr_schedu
|
||||
je.posting_date = depr_schedule.schedule_date
|
||||
je.company = asset.company
|
||||
je.finance_book = depr_schedule_doc.finance_book
|
||||
je.remark = f"Depreciation Entry against {asset.name} worth {depr_schedule.depreciation_amount}"
|
||||
je.remark = _("Depreciation Entry against {0} worth {1}").format(
|
||||
asset.name, depr_schedule.depreciation_amount
|
||||
)
|
||||
|
||||
|
||||
def get_credit_and_debit_entry(
|
||||
|
||||
@@ -86,8 +86,24 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
|
||||
)
|
||||
|
||||
def on_submit(self):
|
||||
self.validate_asset()
|
||||
self.db_set("status", "Active")
|
||||
|
||||
def validate_asset(self):
|
||||
asset = frappe.get_doc("Asset", self.asset)
|
||||
if not asset.calculate_depreciation:
|
||||
frappe.throw(
|
||||
_("Asset {0} is not set to calculate depreciation.").format(
|
||||
get_link_to_form("Asset", self.asset)
|
||||
)
|
||||
)
|
||||
if asset.docstatus != 1:
|
||||
frappe.throw(
|
||||
_("Asset {0} is not submitted. Please submit the asset before proceeding.").format(
|
||||
get_link_to_form("Asset", self.asset)
|
||||
)
|
||||
)
|
||||
|
||||
def on_cancel(self):
|
||||
self.db_set("status", "Cancelled")
|
||||
if not self.flags.should_not_cancel_depreciation_entries:
|
||||
@@ -96,6 +112,13 @@ class AssetDepreciationSchedule(DepreciationScheduleController):
|
||||
def cancel_depreciation_entries(self):
|
||||
for d in self.get("depreciation_schedule"):
|
||||
if d.journal_entry:
|
||||
je_status = frappe.db.get_value("Journal Entry", d.journal_entry, "docstatus")
|
||||
if je_status == 0:
|
||||
frappe.throw(
|
||||
_(
|
||||
"Cannot cancel Asset Depreciation Schedule {0} as it has a draft journal entry {1}."
|
||||
).format(self.name, d.journal_entry)
|
||||
)
|
||||
frappe.get_doc("Journal Entry", d.journal_entry).cancel()
|
||||
|
||||
def update_shift_depr_schedule(self):
|
||||
|
||||
@@ -3,13 +3,13 @@ frappe.listview_settings["Asset Maintenance Log"] = {
|
||||
has_indicator_for_draft: 1,
|
||||
get_indicator: function (doc) {
|
||||
if (doc.maintenance_status == "Planned") {
|
||||
return [__(doc.maintenance_status), "orange", "status,=," + doc.maintenance_status];
|
||||
return [__(doc.maintenance_status), "orange", "maintenance_status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status == "Completed") {
|
||||
return [__(doc.maintenance_status), "green", "status,=," + doc.maintenance_status];
|
||||
return [__(doc.maintenance_status), "green", "maintenance_status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status == "Cancelled") {
|
||||
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||
return [__(doc.maintenance_status), "red", "maintenance_status,=," + doc.maintenance_status];
|
||||
} else if (doc.maintenance_status == "Overdue") {
|
||||
return [__(doc.maintenance_status), "red", "status,=," + doc.maintenance_status];
|
||||
return [__(doc.maintenance_status), "red", "maintenance_status,=," + doc.maintenance_status];
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ def get_columns(filters):
|
||||
},
|
||||
{
|
||||
"label": _("Requestor"),
|
||||
"options": "Employee",
|
||||
"options": "User",
|
||||
"fieldname": "requestor",
|
||||
"fieldtype": "Link",
|
||||
"width": 140,
|
||||
|
||||
@@ -60,7 +60,7 @@ def import_genericode():
|
||||
"doctype": "File",
|
||||
"attached_to_doctype": "Code List",
|
||||
"attached_to_name": code_list.name,
|
||||
"folder": "Home/Attachments",
|
||||
"folder": frappe.db.get_value("File", {"is_attachments_folder": 1}),
|
||||
"file_name": frappe.local.uploaded_filename,
|
||||
"file_url": frappe.local.uploaded_file_url,
|
||||
"is_private": 1,
|
||||
|
||||
@@ -427,7 +427,7 @@ erpnext.patches.v15_0.set_status_cancelled_on_cancelled_pos_opening_entry_and_po
|
||||
erpnext.patches.v15_0.set_company_on_pos_inv_merge_log
|
||||
erpnext.patches.v15_0.update_payment_ledger_entries_against_advance_doctypes
|
||||
erpnext.patches.v15_0.rename_price_list_to_buying_price_list
|
||||
erpnext.patches.v15_0.repost_gl_entries_with_no_account_subcontracting #2025-07-31
|
||||
erpnext.patches.v15_0.repost_gl_entries_with_no_account_subcontracting #2025-08-04
|
||||
erpnext.patches.v15_0.patch_missing_buying_price_list_in_material_request
|
||||
erpnext.patches.v15_0.remove_sales_partner_from_consolidated_sales_invoice
|
||||
erpnext.patches.v15_0.add_company_payment_gateway_account
|
||||
|
||||
@@ -2,24 +2,31 @@ import frappe
|
||||
|
||||
|
||||
def execute():
|
||||
def cancel_incorrect_gl_entries(gl_entries):
|
||||
table = frappe.qb.DocType("GL Entry")
|
||||
frappe.qb.update(table).set(table.is_cancelled, 1).where(table.name.isin(gl_entries)).run()
|
||||
|
||||
def recreate_gl_entries(voucher_nos):
|
||||
for doc in voucher_nos:
|
||||
doc = frappe.get_doc("Subcontracting Receipt", doc)
|
||||
for item in doc.supplied_items:
|
||||
account, cost_center = frappe.db.get_values(
|
||||
"Subcontracting Receipt Item", item.reference_name, ["expense_account", "cost_center"]
|
||||
)[0]
|
||||
|
||||
if not item.expense_account:
|
||||
item.db_set("expense_account", account)
|
||||
if not item.cost_center:
|
||||
item.db_set("cost_center", cost_center)
|
||||
|
||||
doc.make_gl_entries()
|
||||
|
||||
docs = frappe.get_all(
|
||||
"GL Entry",
|
||||
fields=["name", "voucher_no"],
|
||||
filters={"voucher_type": "Subcontracting Receipt", "account": ["is", "not set"], "is_cancelled": 0},
|
||||
pluck="voucher_no",
|
||||
)
|
||||
for doc in docs:
|
||||
doc = frappe.get_doc("Subcontracting Receipt", doc)
|
||||
for item in doc.supplied_items:
|
||||
account, cost_center = frappe.db.get_values(
|
||||
"Subcontracting Receipt Item", item.reference_name, ["expense_account", "cost_center"]
|
||||
)[0]
|
||||
|
||||
if not item.expense_account:
|
||||
item.db_set("expense_account", account)
|
||||
if not item.cost_center:
|
||||
item.db_set("cost_center", cost_center)
|
||||
|
||||
doc.docstatus = 2
|
||||
doc.make_gl_entries_on_cancel()
|
||||
doc.docstatus = 1
|
||||
doc.make_gl_entries()
|
||||
if docs:
|
||||
cancel_incorrect_gl_entries([d.name for d in docs])
|
||||
recreate_gl_entries([d.voucher_no for d in docs])
|
||||
|
||||
@@ -943,15 +943,10 @@ erpnext.taxes_and_totals = class TaxesAndTotals extends erpnext.payments {
|
||||
this.frm.refresh_fields();
|
||||
}
|
||||
|
||||
async set_default_payment(total_amount_to_pay, update_paid_amount) {
|
||||
set_default_payment(total_amount_to_pay, update_paid_amount) {
|
||||
var me = this;
|
||||
var payment_status = true;
|
||||
if(this.frm.doc.is_pos && (update_paid_amount===undefined || update_paid_amount)) {
|
||||
let r = await frappe.db.get_value("POS Profile", this.frm.doc.pos_profile, "set_grand_total_to_default_mop");
|
||||
|
||||
if (!r.message.set_grand_total_to_default_mop) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.each(this.frm.doc['payments'] || [], function(index, data) {
|
||||
if(data.default && payment_status && total_amount_to_pay > 0) {
|
||||
|
||||
@@ -450,10 +450,11 @@ erpnext.PointOfSale.Payment = class {
|
||||
}
|
||||
|
||||
render_payment_section() {
|
||||
this.grand_total_to_default_mop();
|
||||
this.render_payment_mode_dom();
|
||||
this.make_invoice_field_dialog();
|
||||
this.update_totals_section();
|
||||
this.set_grand_total_to_default_mop();
|
||||
this.focus_on_default_mop();
|
||||
}
|
||||
|
||||
after_render() {
|
||||
@@ -497,6 +498,17 @@ erpnext.PointOfSale.Payment = class {
|
||||
}
|
||||
}
|
||||
|
||||
grand_total_to_default_mop() {
|
||||
if (this.set_gt_to_default_mop) return;
|
||||
const doc = this.events.get_frm().doc;
|
||||
const payments = doc.payments;
|
||||
payments.forEach((p) => {
|
||||
if (p.default) {
|
||||
frappe.model.set_value(p.doctype, p.name, "amount", 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
render_payment_mode_dom() {
|
||||
const doc = this.events.get_frm().doc;
|
||||
const payments = doc.payments;
|
||||
@@ -557,6 +569,7 @@ erpnext.PointOfSale.Payment = class {
|
||||
}
|
||||
|
||||
focus_on_default_mop() {
|
||||
if (!this.set_gt_to_default_mop) return;
|
||||
const doc = this.events.get_frm().doc;
|
||||
const payments = doc.payments;
|
||||
payments.forEach((p) => {
|
||||
@@ -711,12 +724,6 @@ erpnext.PointOfSale.Payment = class {
|
||||
.toLowerCase();
|
||||
}
|
||||
|
||||
set_grand_total_to_default_mop() {
|
||||
if (this.set_gt_to_default_mop) {
|
||||
this.focus_on_default_mop();
|
||||
}
|
||||
}
|
||||
|
||||
validate_reqd_invoice_fields() {
|
||||
if (this.invoice_fields.length === 0) return true;
|
||||
const doc = this.events.get_frm().doc;
|
||||
|
||||
@@ -251,6 +251,7 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Posting Time",
|
||||
@@ -1415,7 +1416,7 @@
|
||||
"idx": 146,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-01-06 15:02:30.558756",
|
||||
"modified": "2025-08-04 19:20:47.724218",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Delivery Note",
|
||||
@@ -1506,6 +1507,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"search_fields": "status,customer,customer_name, territory,base_grand_total",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "creation",
|
||||
@@ -1515,4 +1517,4 @@
|
||||
"title_field": "customer_name",
|
||||
"track_changes": 1,
|
||||
"track_seen": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,6 @@ class DeliveryNote(SellingController):
|
||||
per_billed: DF.Percent
|
||||
per_installed: DF.Percent
|
||||
per_returned: DF.Percent
|
||||
pick_list: DF.Link | None
|
||||
plc_conversion_rate: DF.Float
|
||||
po_date: DF.Date | None
|
||||
po_no: DF.SmallText | None
|
||||
|
||||
@@ -243,6 +243,7 @@
|
||||
"width": "100px"
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Posting Time",
|
||||
@@ -1290,7 +1291,7 @@
|
||||
"idx": 261,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2025-04-09 16:52:19.323878",
|
||||
"modified": "2025-08-04 19:18:47.754957",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Purchase Receipt",
|
||||
@@ -1360,4 +1361,4 @@
|
||||
"timeline_field": "supplier",
|
||||
"title_field": "title",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,6 +218,7 @@
|
||||
"search_index": 1
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"label": "Posting Time",
|
||||
@@ -697,7 +698,7 @@
|
||||
"index_web_pages_for_search": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-08-13 19:05:42.386955",
|
||||
"modified": "2025-08-04 19:21:03.338958",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Entry",
|
||||
@@ -763,6 +764,7 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"search_fields": "posting_date, from_warehouse, to_warehouse, purpose, remarks",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "creation",
|
||||
@@ -770,4 +772,4 @@
|
||||
"states": [],
|
||||
"title_field": "stock_entry_type",
|
||||
"track_changes": 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"reqd": 1
|
||||
},
|
||||
{
|
||||
"default": "Now",
|
||||
"fieldname": "posting_time",
|
||||
"fieldtype": "Time",
|
||||
"in_list_view": 1,
|
||||
@@ -183,7 +184,7 @@
|
||||
"idx": 1,
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2024-03-27 13:10:44.699413",
|
||||
"modified": "2025-08-04 19:21:20.179658",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Stock",
|
||||
"name": "Stock Reconciliation",
|
||||
@@ -203,9 +204,10 @@
|
||||
"write": 1
|
||||
}
|
||||
],
|
||||
"row_format": "Dynamic",
|
||||
"search_fields": "posting_date",
|
||||
"show_name_in_global_search": 1,
|
||||
"sort_field": "creation",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user