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.handle_excluded_fee()
self.update_allocated_amount() self.update_allocated_amount()
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self): def validate(self):
self.validate_included_fee() self.validate_included_fee()
self.validate_duplicate_references() self.validate_duplicate_references()

View File

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

View File

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

View File

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

View File

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

View File

@@ -184,6 +184,9 @@ class StatusUpdater(Document):
Installation Note: Update Installed Qty, Update Percent Qty and Validate over installation 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): def update_prevdoc_status(self):
self.update_qty() self.update_qty()
self.validate_qty() self.validate_qty()

View File

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

View File

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

View File

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

View File

@@ -41,7 +41,7 @@ class BOMUpdateLog(Document):
error_log: DF.Link | None error_log: DF.Link | None
new_bom: DF.Link | None new_bom: DF.Link | None
processed_boms: DF.LongText | 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"] update_type: DF.Literal["Replace BOM", "Update Cost"]
# end: auto-generated types # end: auto-generated types
@@ -64,6 +64,9 @@ class BOMUpdateLog(Document):
self.status = "Queued" self.status = "Queued"
def on_discard(self):
self.db_set("status", "Cancelled")
def validate_boms_are_specified(self): def validate_boms_are_specified(self):
if self.update_type == "Replace BOM" and not (self.current_bom and self.new_bom): if self.update_type == "Replace BOM" and not (self.current_bom and self.new_bom):
frappe.throw( 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("work_order_closed", self.is_work_order_closed())
self.set_onload("has_stock_entry", self.has_stock_entry()) self.set_onload("has_stock_entry", self.has_stock_entry())
def on_discard(self):
self.db_set("status", "Cancelled")
def has_stock_entry(self): def has_stock_entry(self):
return frappe.db.exists("Stock Entry", {"job_card": self.name, "docstatus": ["!=", 2]}) 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"), frappe.db.get_single_value("Stock Settings", "enable_stock_reservation"),
) )
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self): def validate(self):
self.set_pending_qty_in_row_without_reference() self.set_pending_qty_in_row_without_reference()
self.calculate_total_planned_qty() self.calculate_total_planned_qty()

View File

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

View File

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

View File

@@ -180,6 +180,9 @@ class WorkOrder(Document):
return False return False
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self): def validate(self):
self.validate_production_item() self.validate_production_item()
if self.bom_no: 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.set_mr_picked_qty
erpnext.patches.v16_0.update_tax_withholding_field_in_payment_entry erpnext.patches.v16_0.update_tax_withholding_field_in_payment_entry
erpnext.patches.v16_0.migrate_tax_withholding_data 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.calculate_percentage_billed()
self.set_dates() self.set_dates()
def on_discard(self):
self.db_set("status", "Cancelled")
def calculate_hours(self): def calculate_hours(self):
for row in self.time_logs: for row in self.time_logs:
if row.to_time and row.from_time: 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): def validate(self):
frappe.only_for("System Manager") frappe.only_for("System Manager")
self.validate_doctypes_to_be_ignored() 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" "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): def validate(self):
if self._action == "submit" and not self.driver: if self._action == "submit" and not self.driver:
frappe.throw(_("A driver must be set to submit.")) frappe.throw(_("A driver must be set to submit."))

View File

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

View File

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

View File

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

View File

@@ -53,7 +53,7 @@ class RepostItemValuation(Document):
repost_only_accounting_ledgers: DF.Check repost_only_accounting_ledgers: DF.Check
reposting_data_file: DF.Attach | None reposting_data_file: DF.Attach | None
reposting_reference: DF.Data | 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 total_reposting_count: DF.Int
via_landed_cost_voucher: DF.Check via_landed_cost_voucher: DF.Check
voucher_no: DF.DynamicLink | None voucher_no: DF.DynamicLink | None
@@ -73,6 +73,9 @@ class RepostItemValuation(Document):
), ),
) )
def on_discard(self):
self.db_set("status", "Cancelled")
def validate(self): def validate(self):
self.reset_repost_only_accounting_ledgers() self.reset_repost_only_accounting_ledgers()
self.set_company() self.set_company()

View File

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

View File

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

View File

@@ -27,17 +27,20 @@ class StockClosingEntry(Document):
company: DF.Link | None company: DF.Link | None
from_date: DF.Date | None from_date: DF.Date | None
naming_series: DF.Literal["CBAL-.#####"] 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 to_date: DF.Date | None
# end: auto-generated types # end: auto-generated types
def on_discard(self):
self.db_set("status", "Cancelled")
def before_save(self): def before_save(self):
self.set_status() self.set_status()
def set_status(self, save=False): def set_status(self, save=False):
self.status = "Queued" self.status = "Queued"
if self.docstatus == 2: if self.docstatus == 2:
self.status = "Canceled" self.status = "Cancelled"
if self.docstatus == 0: if self.docstatus == 0:
self.status = "Draft" 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) { } else if (doc.purpose === "Send to Warehouse" && doc.per_transferred === 100) {
return [__("Goods Transferred"), "green", "per_transferred,=,100"]; return [__("Goods Transferred"), "green", "per_transferred,=,100"];
} else if (doc.docstatus === 2) { } else if (doc.docstatus === 2) {
return [__("Canceled"), "red", "docstatus,=,2"]; return [__("Cancelled"), "red", "docstatus,=,2"];
} else { } else {
return [__("Submitted"), "blue", "docstatus,=,1"]; return [__("Submitted"), "blue", "docstatus,=,1"];
} }

View File

@@ -54,7 +54,7 @@
"fieldtype": "Select", "fieldtype": "Select",
"in_list_view": 1, "in_list_view": 1,
"label": "Status", "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 "read_only": 1
}, },
{ {
@@ -164,7 +164,7 @@
"in_create": 1, "in_create": 1,
"index_web_pages_for_search": 1, "index_web_pages_for_search": 1,
"links": [], "links": [],
"modified": "2022-04-14 02:59:22.503202", "modified": "2025-12-29 10:37:26.183502",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "Telephony", "module": "Telephony",
"name": "Call Log", "name": "Call Log",
@@ -188,10 +188,11 @@
"role": "Employee" "role": "Employee"
} }
], ],
"row_format": "Dynamic",
"sort_field": "creation", "sort_field": "creation",
"sort_order": "DESC", "sort_order": "DESC",
"states": [], "states": [],
"title_field": "from", "title_field": "from",
"track_changes": 1, "track_changes": 1,
"track_views": 1 "track_views": 1
} }

View File

@@ -36,7 +36,7 @@ class CallLog(Document):
recording_url: DF.Data | None recording_url: DF.Data | None
start_time: DF.Datetime | None start_time: DF.Datetime | None
status: DF.Literal[ 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 summary: DF.SmallText | None
to: DF.Data | None to: DF.Data | None