feat: Adding support for discarding document (#51316)

Co-authored-by: Nishka Gosalia <nishkagosalia@Nishkas-MacBook-Air.local>
This commit is contained in:
Nishka Gosalia
2025-12-29 14:19:46 +05:30
committed by GitHub
parent 9f0f4d6709
commit 41a7e64772
30 changed files with 108 additions and 31 deletions

View File

@@ -50,6 +50,9 @@ class BankTransaction(Document):
self.handle_excluded_fee()
self.update_allocated_amount()
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.validate_included_fee()
self.validate_duplicate_references()

View File

@@ -9,8 +9,8 @@ frappe.listview_settings["Invoice Discounting"] = {
return [__("Disbursed"), "blue", "status,=,Disbursed"];
} else if (doc.status == "Settled") {
return [__("Settled"), "orange", "status,=,Settled"];
} else if (doc.status == "Canceled") {
return [__("Canceled"), "red", "status,=,Canceled"];
} else if (doc.status == "Cancelled") {
return [__("Cancelled"), "red", "status,=,Cancelled"];
}
},
};

View File

@@ -100,7 +100,10 @@ class PaymentRequest(Document):
subscription_plans: DF.Table[SubscriptionPlanDetail]
swift_number: DF.ReadOnly | None
transaction_date: DF.Date | None
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
if self.get("__islocal"):

View File

@@ -35,7 +35,10 @@ class ProcessPaymentReconciliation(Document):
]
to_invoice_date: DF.Date | None
to_payment_date: DF.Date | None
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.validate_receivable_payable_account()

View File

@@ -36,7 +36,10 @@ class ProcessPeriodClosingVoucher(Document):
parent_pcv: DF.Link
status: DF.Literal["Queued", "Running", "Paused", "Completed", "Cancelled"]
z_opening_balances: DF.Table[ProcessPeriodClosingVoucherDetail]
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.status = "Queued"

View File

@@ -184,6 +184,9 @@ class StatusUpdater(Document):
Installation Note: Update Installed Qty, Update Percent Qty and Validate over installation
"""
def on_discard(self):
self.db_set("status", "Cancelled")
def update_prevdoc_status(self):
self.update_qty()
self.validate_qty()

View File

@@ -85,7 +85,7 @@
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"options": "Unsigned\nActive\nInactive"
"options": "Unsigned\nActive\nInactive\nCancelled"
},
{
"allow_on_submit": 1,
@@ -257,11 +257,11 @@
"grid_page_length": 50,
"is_submittable": 1,
"links": [],
"modified": "2025-06-19 17:48:45.049007",
"modified": "2025-12-24 21:33:51.240497",
"modified_by": "Administrator",
"module": "CRM",
"name": "Contract",
"naming_rule": "Expression (old style)",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{

View File

@@ -43,7 +43,7 @@ class Contract(Document):
signed_on: DF.Datetime | None
signee: DF.Data | None
start_date: DF.Date | None
status: DF.Literal["Unsigned", "Active", "Inactive"]
status: DF.Literal["Unsigned", "Active", "Inactive", "Cancelled"]
# end: auto-generated types
def validate(self):
@@ -61,6 +61,9 @@ class Contract(Document):
def before_submit(self):
self.signed_by_company = frappe.session.user
def on_discard(self):
self.db_set("status", "Cancelled")
def before_update_after_submit(self):
self.update_contract_status()
self.update_fulfilment_status()

View File

@@ -52,7 +52,7 @@
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"options": "Queued\nIn Progress\nCompleted\nFailed"
"options": "Queued\nIn Progress\nCompleted\nFailed\nCancelled"
},
{
"fieldname": "amended_from",
@@ -98,11 +98,11 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-03-27 13:06:41.658172",
"modified": "2025-12-24 12:27:06.478893",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "BOM Update Log",
"naming_rule": "Expression (old style)",
"naming_rule": "Expression",
"owner": "Administrator",
"permissions": [
{
@@ -131,8 +131,9 @@
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"track_changes": 1
}
}

View File

@@ -41,7 +41,7 @@ class BOMUpdateLog(Document):
error_log: DF.Link | None
new_bom: DF.Link | None
processed_boms: DF.LongText | None
status: DF.Literal["Queued", "In Progress", "Completed", "Failed"]
status: DF.Literal["Queued", "In Progress", "Completed", "Failed", "Cancelled"]
update_type: DF.Literal["Replace BOM", "Update Cost"]
# end: auto-generated types
@@ -64,6 +64,9 @@ class BOMUpdateLog(Document):
self.status = "Queued"
def on_discard(self):
self.db_set("status", "Cancelled")
def validate_boms_are_specified(self):
if self.update_type == "Replace BOM" and not (self.current_bom and self.new_bom):
frappe.throw(

View File

@@ -144,6 +144,9 @@ class JobCard(Document):
self.set_onload("work_order_closed", self.is_work_order_closed())
self.set_onload("has_stock_entry", self.has_stock_entry())
def on_discard(self):
self.db_set("status", "Cancelled")
def has_stock_entry(self):
return frappe.db.exists("Stock Entry", {"job_card": self.name, "docstatus": ["!=", 2]})

View File

@@ -119,6 +119,9 @@ class ProductionPlan(Document):
frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"),
)
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.set_pending_qty_in_row_without_reference()
self.calculate_total_planned_qty()

View File

@@ -143,7 +143,7 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Status",
"options": "Planned\nMPS Generated",
"options": "Planned\nMPS Generated\nCancelled",
"read_only": 1
},
{
@@ -166,7 +166,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2025-11-13 16:33:49.682684",
"modified": "2025-12-24 11:40:44.263700",
"modified_by": "Administrator",
"module": "Manufacturing",
"name": "Sales Forecast",

View File

@@ -33,9 +33,12 @@ class SalesForecast(Document):
parent_warehouse: DF.Link
posting_date: DF.Date | None
selected_items: DF.TableMultiSelect[SalesForecastItem]
status: DF.Literal["Planned", "MPS Generated"]
status: DF.Literal["Planned", "MPS Generated", "Cancelled"]
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.validate_demand_qty()

View File

@@ -180,6 +180,9 @@ class WorkOrder(Document):
return False
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.validate_production_item()
if self.bom_no:

View File

@@ -454,4 +454,5 @@ erpnext.patches.v16_0.populate_budget_distribution_total
erpnext.patches.v16_0.set_mr_picked_qty
erpnext.patches.v16_0.update_tax_withholding_field_in_payment_entry
erpnext.patches.v16_0.migrate_tax_withholding_data
erpnext.patches.v16_0.update_corrected_cancelled_status

View File

@@ -0,0 +1,16 @@
import frappe
def execute():
stock_closing_entry = frappe.qb.DocType("Stock Closing Entry")
call_log = frappe.qb.DocType("Call Log")
# updating stock closing entry status to cancelled from canceled
(
frappe.qb.update(stock_closing_entry)
.set(stock_closing_entry.status, "Cancelled")
.where(stock_closing_entry.status == "Canceled")
).run()
# updating call log status to cancelled from canceled
(frappe.qb.update(call_log).set(call_log.status, "Cancelled").where(call_log.status == "Canceled")).run()

View File

@@ -73,6 +73,9 @@ class Timesheet(Document):
self.calculate_percentage_billed()
self.set_dates()
def on_discard(self):
self.db_set("status", "Cancelled")
def calculate_hours(self):
for row in self.time_logs:
if row.to_time and row.from_time:

View File

@@ -66,6 +66,9 @@ class TransactionDeletionRecord(Document):
}
)
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
frappe.only_for("System Manager")
self.validate_doctypes_to_be_ignored()

View File

@@ -50,6 +50,10 @@ class DeliveryTrip(Document):
"UOM Conversion Factor", {"from_uom": "Meter", "to_uom": self.default_distance_uom}, "value"
)
def on_discard(self):
self.update_status()
self.update_delivery_notes(delete=True)
def validate(self):
if self._action == "submit" and not self.driver:
frappe.throw(_("A driver must be set to submit."))

View File

@@ -234,7 +234,7 @@
"fieldname": "status",
"fieldtype": "Select",
"label": "Status",
"options": "\nAccepted\nRejected",
"options": "\nAccepted\nRejected\nCancelled",
"reqd": 1
},
{
@@ -278,7 +278,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2025-02-17 13:20:17.583094",
"modified": "2025-12-24 15:21:03.240008",
"modified_by": "Administrator",
"module": "Stock",
"name": "Quality Inspection",
@@ -300,9 +300,10 @@
"write": 1
}
],
"row_format": "Dynamic",
"search_fields": "item_code, report_date, reference_name",
"show_name_in_global_search": 1,
"sort_field": "creation",
"sort_order": "ASC",
"states": []
}
}

View File

@@ -56,9 +56,13 @@ class QualityInspection(Document):
remarks: DF.Text | None
report_date: DF.Date
sample_size: DF.Float
status: DF.Literal["", "Accepted", "Rejected"]
status: DF.Literal["", "Accepted", "Rejected", "Cancelled"]
verified_by: DF.Data | None
# end: auto-generated types
def on_discard(self):
self.update_qc_reference()
self.db_set("status", "Cancelled")
def validate(self):
if not self.readings and self.item_code:

View File

@@ -76,7 +76,7 @@
"in_standard_filter": 1,
"label": "Status",
"no_copy": 1,
"options": "Queued\nIn Progress\nCompleted\nSkipped\nFailed",
"options": "Queued\nIn Progress\nCompleted\nSkipped\nFailed\nCancelled",
"read_only": 1
},
{
@@ -252,7 +252,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2025-11-20 18:24:48.808526",
"modified": "2025-12-24 14:59:15.512898",
"modified_by": "Administrator",
"module": "Stock",
"name": "Repost Item Valuation",

View File

@@ -53,7 +53,7 @@ class RepostItemValuation(Document):
repost_only_accounting_ledgers: DF.Check
reposting_data_file: DF.Attach | None
reposting_reference: DF.Data | None
status: DF.Literal["Queued", "In Progress", "Completed", "Skipped", "Failed"]
status: DF.Literal["Queued", "In Progress", "Completed", "Skipped", "Failed", "Cancelled"]
total_reposting_count: DF.Int
via_landed_cost_voucher: DF.Check
voucher_no: DF.DynamicLink | None
@@ -73,6 +73,9 @@ class RepostItemValuation(Document):
),
)
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.reset_repost_only_accounting_ledgers()
self.set_company()

View File

@@ -72,6 +72,9 @@ class Shipment(Document):
value_of_goods: DF.Currency
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self):
self.validate_weight()
self.validate_pickup_time()

View File

@@ -37,7 +37,7 @@
"in_list_view": 1,
"in_preview": 1,
"label": "Status",
"options": "Draft\nQueued\nIn Progress\nCompleted\nFailed\nCanceled",
"options": "Draft\nQueued\nIn Progress\nCompleted\nFailed\nCancelled",
"read_only": 1
},
{
@@ -68,7 +68,7 @@
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
"modified": "2024-12-20 13:48:46.618066",
"modified": "2025-12-29 10:35:32.507988",
"modified_by": "Administrator",
"module": "Stock",
"name": "Stock Closing Entry",
@@ -121,7 +121,8 @@
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": []
}
}

View File

@@ -27,17 +27,20 @@ class StockClosingEntry(Document):
company: DF.Link | None
from_date: DF.Date | None
naming_series: DF.Literal["CBAL-.#####"]
status: DF.Literal["Draft", "Queued", "In Progress", "Completed", "Failed", "Canceled"]
status: DF.Literal["Draft", "Queued", "In Progress", "Completed", "Failed", "Cancelled"]
to_date: DF.Date | None
# end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def before_save(self):
self.set_status()
def set_status(self, save=False):
self.status = "Queued"
if self.docstatus == 2:
self.status = "Canceled"
self.status = "Cancelled"
if self.docstatus == 0:
self.status = "Draft"

View File

@@ -22,7 +22,7 @@ frappe.listview_settings["Stock Entry"] = {
} else if (doc.purpose === "Send to Warehouse" && doc.per_transferred === 100) {
return [__("Goods Transferred"), "green", "per_transferred,=,100"];
} else if (doc.docstatus === 2) {
return [__("Canceled"), "red", "docstatus,=,2"];
return [__("Cancelled"), "red", "docstatus,=,2"];
} else {
return [__("Submitted"), "blue", "docstatus,=,1"];
}

View File

@@ -54,7 +54,7 @@
"fieldtype": "Select",
"in_list_view": 1,
"label": "Status",
"options": "Ringing\nIn Progress\nCompleted\nFailed\nBusy\nNo Answer\nQueued\nCanceled",
"options": "Ringing\nIn Progress\nCompleted\nFailed\nBusy\nNo Answer\nQueued\nCancelled",
"read_only": 1
},
{
@@ -164,7 +164,7 @@
"in_create": 1,
"index_web_pages_for_search": 1,
"links": [],
"modified": "2022-04-14 02:59:22.503202",
"modified": "2025-12-29 10:37:26.183502",
"modified_by": "Administrator",
"module": "Telephony",
"name": "Call Log",
@@ -188,10 +188,11 @@
"role": "Employee"
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "from",
"track_changes": 1,
"track_views": 1
}
}

View File

@@ -36,7 +36,7 @@ class CallLog(Document):
recording_url: DF.Data | None
start_time: DF.Datetime | None
status: DF.Literal[
"Ringing", "In Progress", "Completed", "Failed", "Busy", "No Answer", "Queued", "Canceled"
"Ringing", "In Progress", "Completed", "Failed", "Busy", "No Answer", "Queued", "Cancelled"
]
summary: DF.SmallText | None
to: DF.Data | None