Merge pull request #31860 from rohitwaghchaure/delete-custom-fields-on-dimension-delete

fix: delete custom fields on deletion of inventory dimension
This commit is contained in:
rohitwaghchaure 2022-08-17 15:43:54 +05:30 committed by GitHub
commit 396667b702
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 143 additions and 25 deletions

View File

@ -386,9 +386,24 @@ class StockController(AccountsController):
def update_inventory_dimensions(self, row, sl_dict) -> None:
dimensions = get_evaluated_inventory_dimension(row, sl_dict, parent_doc=self)
for dimension in dimensions:
if dimension and row.get(dimension.source_fieldname):
if not dimension:
continue
if row.get(dimension.source_fieldname):
sl_dict[dimension.target_fieldname] = row.get(dimension.source_fieldname)
if not sl_dict.get(dimension.target_fieldname) and dimension.fetch_from_parent:
sl_dict[dimension.target_fieldname] = self.get(dimension.fetch_from_parent)
# Get value based on doctype name
if not sl_dict.get(dimension.target_fieldname):
fieldname = frappe.get_cached_value(
"DocField", {"parent": self.doctype, "options": dimension.fetch_from_parent}, "fieldname"
)
if fieldname and self.get(fieldname):
sl_dict[dimension.target_fieldname] = self.get(fieldname)
def make_sl_entries(self, sl_entries, allow_negative_stock=False, via_landed_cost_voucher=False):
from erpnext.stock.stock_ledger import make_sl_entries

View File

@ -35,14 +35,39 @@ frappe.ui.form.on('Inventory Dimension', {
refresh(frm) {
if (frm.doc.__onload && frm.doc.__onload.has_stock_ledger
&& frm.doc.__onload.has_stock_ledger.length) {
let msg = __('Stock transactions exists against this dimension, user can not update document.');
frm.dashboard.add_comment(msg, 'blue', true);
let allow_to_edit_fields = ['disabled', 'fetch_from_parent',
'type_of_transaction', 'condition'];
frm.fields.forEach((field) => {
if (field.df.fieldname !== 'disabled') {
if (!in_list(allow_to_edit_fields, field.df.fieldname)) {
frm.set_df_property(field.df.fieldname, "read_only", "1");
}
});
}
if (!frm.is_new()) {
frm.add_custom_button(__('Delete Dimension'), () => {
frm.trigger('delete_dimension');
});
}
},
delete_dimension(frm) {
let msg = (`
Custom fields related to this dimension will be deleted on deletion of dimension.
<br> Do you want to delete {0} dimension?
`);
frappe.confirm(__(msg, [frm.doc.name.bold()]), () => {
frappe.call({
method: 'erpnext.stock.doctype.inventory_dimension.inventory_dimension.delete_dimension',
args: {
dimension: frm.doc.name
},
callback: function() {
frappe.set_route('List', 'Inventory Dimension');
}
});
});
}
});

View File

@ -1,6 +1,5 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "field:dimension_name",
"creation": "2022-06-17 13:04:16.554051",
"doctype": "DocType",
@ -22,6 +21,7 @@
"document_type",
"istable",
"type_of_transaction",
"fetch_from_parent",
"column_break_16",
"condition",
"applicable_condition_example_section",
@ -101,12 +101,14 @@
"fieldname": "target_fieldname",
"fieldtype": "Data",
"label": "Target Fieldname (Stock Ledger Entry)",
"no_copy": 1,
"read_only": 1
},
{
"fieldname": "source_fieldname",
"fieldtype": "Data",
"label": "Source Fieldname",
"no_copy": 1,
"read_only": 1
},
{
@ -123,7 +125,7 @@
"fieldname": "type_of_transaction",
"fieldtype": "Select",
"label": "Type of Transaction",
"options": "\nInward\nOutward"
"options": "\nInward\nOutward\nBoth"
},
{
"fieldname": "html_19",
@ -140,11 +142,18 @@
{
"fieldname": "column_break_4",
"fieldtype": "Column Break"
},
{
"depends_on": "istable",
"description": "Set fieldname or DocType name like Supplier, Customer etc.",
"fieldname": "fetch_from_parent",
"fieldtype": "Data",
"label": "Fetch Value From Parent Form"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2022-07-19 21:06:11.824976",
"modified": "2022-08-17 11:43:24.722441",
"modified_by": "Administrator",
"module": "Stock",
"name": "Inventory Dimension",

View File

@ -43,13 +43,37 @@ class InventoryDimension(Document):
return
old_doc = self._doc_before_save
allow_to_edit_fields = [
"disabled",
"fetch_from_parent",
"type_of_transaction",
"condition",
]
for field in frappe.get_meta("Inventory Dimension").fields:
if field.fieldname != "disabled" and old_doc.get(field.fieldname) != self.get(field.fieldname):
if field.fieldname not in allow_to_edit_fields and old_doc.get(field.fieldname) != self.get(
field.fieldname
):
msg = f"""The user can not change value of the field {bold(field.label)} because
stock transactions exists against the dimension {bold(self.name)}."""
frappe.throw(_(msg), DoNotChangeError)
def on_trash(self):
self.delete_custom_fields()
def delete_custom_fields(self):
filters = {"fieldname": self.source_fieldname}
if self.document_type:
filters["dt"] = self.document_type
for field in frappe.get_all("Custom Field", filters=filters):
frappe.delete_doc("Custom Field", field.name)
msg = f"Deleted custom fields related to the dimension {self.name}"
frappe.msgprint(_(msg))
def reset_value(self):
if self.apply_to_all_doctypes:
self.istable = 0
@ -76,30 +100,35 @@ class InventoryDimension(Document):
self.add_custom_fields()
def add_custom_fields(self):
dimension_field = dict(
fieldname=self.source_fieldname,
fieldtype="Link",
insert_after="warehouse",
options=self.reference_document,
label=self.dimension_name,
)
dimension_fields = [
dict(
fieldname="inventory_dimension",
fieldtype="Section Break",
insert_after="warehouse",
label="Inventory Dimension",
collapsible=1,
),
dict(
fieldname=self.source_fieldname,
fieldtype="Link",
insert_after="inventory_dimension",
options=self.reference_document,
label=self.dimension_name,
),
]
custom_fields = {}
if self.apply_to_all_doctypes:
for doctype in get_inventory_documents():
if not frappe.db.get_value(
"Custom Field", {"dt": doctype[0], "fieldname": self.source_fieldname}
):
custom_fields.setdefault(doctype[0], dimension_field)
elif not frappe.db.get_value(
"Custom Field", {"dt": self.document_type, "fieldname": self.source_fieldname}
):
custom_fields.setdefault(self.document_type, dimension_field)
custom_fields.setdefault(doctype[0], dimension_fields)
else:
custom_fields.setdefault(self.document_type, dimension_fields)
if not frappe.db.get_value(
"Custom Field", {"dt": "Stock Ledger Entry", "fieldname": self.target_fieldname}
):
dimension_field = dimension_fields[1]
dimension_field["fieldname"] = self.target_fieldname
custom_fields["Stock Ledger Entry"] = dimension_field
@ -143,7 +172,7 @@ def get_evaluated_inventory_dimension(doc, sl_dict, parent_doc=None):
elif (
row.type_of_transaction == "Outward"
if doc.docstatus == 1
else row.type_of_transaction != "Inward"
else row.type_of_transaction != "Outward"
) and sl_dict.actual_qty > 0:
continue
@ -166,7 +195,14 @@ def get_document_wise_inventory_dimensions(doctype) -> dict:
if not frappe.local.document_wise_inventory_dimensions.get(doctype):
dimensions = frappe.get_all(
"Inventory Dimension",
fields=["name", "source_fieldname", "condition", "target_fieldname", "type_of_transaction"],
fields=[
"name",
"source_fieldname",
"condition",
"target_fieldname",
"type_of_transaction",
"fetch_from_parent",
],
filters={"disabled": 0},
or_filters={"document_type": doctype, "apply_to_all_doctypes": 1},
)
@ -194,3 +230,9 @@ def get_inventory_dimensions():
frappe.local.inventory_dimensions = dimensions
return frappe.local.inventory_dimensions
@frappe.whitelist()
def delete_dimension(dimension):
doc = frappe.get_doc("Inventory Dimension", dimension)
doc.delete()

View File

@ -8,6 +8,7 @@ from erpnext.stock.doctype.inventory_dimension.inventory_dimension import (
CanNotBeChildDoc,
CanNotBeDefaultDimension,
DoNotChangeError,
delete_dimension,
)
from erpnext.stock.doctype.stock_entry.stock_entry_utils import make_stock_entry
from erpnext.stock.doctype.warehouse.test_warehouse import create_warehouse
@ -42,6 +43,32 @@ class TestInventoryDimension(FrappeTestCase):
self.assertRaises(CanNotBeDefaultDimension, inv_dim1.insert)
def test_delete_inventory_dimension(self):
inv_dim1 = create_inventory_dimension(
reference_document="Shelf",
type_of_transaction="Outward",
dimension_name="From Shelf",
apply_to_all_doctypes=0,
document_type="Stock Entry Detail",
condition="parent.purpose == 'Material Issue'",
)
inv_dim1.save()
custom_field = frappe.db.get_value(
"Custom Field", {"fieldname": "from_shelf", "dt": "Stock Entry Detail"}, "name"
)
self.assertTrue(custom_field)
delete_dimension(inv_dim1.name)
custom_field = frappe.db.get_value(
"Custom Field", {"fieldname": "from_shelf", "dt": "Stock Entry Detail"}, "name"
)
self.assertFalse(custom_field)
def test_inventory_dimension(self):
warehouse = "Shelf Warehouse - _TC"
item_code = "_Test Item"