feat: asset activity (#36391)
* feat: asset activity * chore: add more actions to asset activity * chore: fix failing test due to timestamp mismatch error * chore: rewriting asset activity messages * chore: add report and add it to workspace * chore: show user in list view
This commit is contained in:
parent
3f09f811bf
commit
2ab3d75274
@ -32,6 +32,7 @@ from erpnext.assets.doctype.asset.depreciation import (
|
||||
reset_depreciation_schedule,
|
||||
reverse_depreciation_entry_made_after_disposal,
|
||||
)
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.controllers.accounts_controller import validate_account_head
|
||||
from erpnext.controllers.selling_controller import SellingController
|
||||
from erpnext.projects.doctype.timesheet.timesheet import get_projectwise_timesheet_data
|
||||
@ -1176,12 +1177,13 @@ class SalesInvoice(SellingController):
|
||||
self.get("posting_date"),
|
||||
)
|
||||
asset.db_set("disposal_date", None)
|
||||
add_asset_activity(asset.name, _("Asset returned"))
|
||||
|
||||
if asset.calculate_depreciation:
|
||||
posting_date = frappe.db.get_value("Sales Invoice", self.return_against, "posting_date")
|
||||
reverse_depreciation_entry_made_after_disposal(asset, posting_date)
|
||||
notes = _(
|
||||
"This schedule was created when Asset {0} was returned after being sold through Sales Invoice {1}."
|
||||
"This schedule was created when Asset {0} was returned through Sales Invoice {1}."
|
||||
).format(
|
||||
get_link_to_form(asset.doctype, asset.name),
|
||||
get_link_to_form(self.doctype, self.get("name")),
|
||||
@ -1209,6 +1211,7 @@ class SalesInvoice(SellingController):
|
||||
self.get("posting_date"),
|
||||
)
|
||||
asset.db_set("disposal_date", self.posting_date)
|
||||
add_asset_activity(asset.name, _("Asset sold"))
|
||||
|
||||
for gle in fixed_asset_gl_entries:
|
||||
gle["against"] = self.customer
|
||||
|
@ -533,6 +533,11 @@
|
||||
"link_doctype": "Asset Depreciation Schedule",
|
||||
"link_fieldname": "asset"
|
||||
},
|
||||
{
|
||||
"group": "Activity",
|
||||
"link_doctype": "Asset Activity",
|
||||
"link_fieldname": "asset"
|
||||
},
|
||||
{
|
||||
"group": "Journal Entry",
|
||||
"link_doctype": "Journal Entry",
|
||||
@ -540,7 +545,7 @@
|
||||
"table_fieldname": "accounts"
|
||||
}
|
||||
],
|
||||
"modified": "2023-07-28 15:47:01.137996",
|
||||
"modified": "2023-07-28 20:12:44.819616",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset",
|
||||
|
@ -25,6 +25,7 @@ from erpnext.assets.doctype.asset.depreciation import (
|
||||
get_depreciation_accounts,
|
||||
get_disposal_account_and_cost_center,
|
||||
)
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||
cancel_asset_depr_schedules,
|
||||
@ -59,7 +60,7 @@ class Asset(AccountsController):
|
||||
self.make_asset_movement()
|
||||
if not self.booked_fixed_asset and self.validate_make_gl_entry():
|
||||
self.make_gl_entries()
|
||||
if not self.split_from:
|
||||
if self.calculate_depreciation and not self.split_from:
|
||||
asset_depr_schedules_names = make_draft_asset_depr_schedules_if_not_present(self)
|
||||
convert_draft_asset_depr_schedules_into_active(self)
|
||||
if asset_depr_schedules_names:
|
||||
@ -71,6 +72,7 @@ class Asset(AccountsController):
|
||||
"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
|
||||
).format(asset_depr_schedules_links)
|
||||
)
|
||||
add_asset_activity(self.name, _("Asset submitted"))
|
||||
|
||||
def on_cancel(self):
|
||||
self.validate_cancellation()
|
||||
@ -81,9 +83,10 @@ class Asset(AccountsController):
|
||||
self.ignore_linked_doctypes = ("GL Entry", "Stock Ledger Entry")
|
||||
make_reverse_gl_entries(voucher_type="Asset", voucher_no=self.name)
|
||||
self.db_set("booked_fixed_asset", 0)
|
||||
add_asset_activity(self.name, _("Asset cancelled"))
|
||||
|
||||
def after_insert(self):
|
||||
if not self.split_from:
|
||||
if self.calculate_depreciation and not self.split_from:
|
||||
asset_depr_schedules_names = make_draft_asset_depr_schedules(self)
|
||||
asset_depr_schedules_links = get_comma_separated_links(
|
||||
asset_depr_schedules_names, "Asset Depreciation Schedule"
|
||||
@ -93,6 +96,16 @@ class Asset(AccountsController):
|
||||
"Asset Depreciation Schedules created:<br>{0}<br><br>Please check, edit if needed, and submit the Asset."
|
||||
).format(asset_depr_schedules_links)
|
||||
)
|
||||
if not frappe.db.exists(
|
||||
{
|
||||
"doctype": "Asset Activity",
|
||||
"asset": self.name,
|
||||
}
|
||||
):
|
||||
add_asset_activity(self.name, _("Asset created"))
|
||||
|
||||
def after_delete(self):
|
||||
add_asset_activity(self.name, _("Asset deleted"))
|
||||
|
||||
def validate_asset_and_reference(self):
|
||||
if self.purchase_invoice or self.purchase_receipt:
|
||||
@ -903,6 +916,13 @@ def update_existing_asset(asset, remaining_qty, new_asset_name):
|
||||
},
|
||||
)
|
||||
|
||||
add_asset_activity(
|
||||
asset.name,
|
||||
_("Asset updated after being split into Asset {0}").format(
|
||||
get_link_to_form("Asset", new_asset_name)
|
||||
),
|
||||
)
|
||||
|
||||
for row in asset.get("finance_books"):
|
||||
value_after_depreciation = flt(
|
||||
(row.value_after_depreciation * remaining_qty) / asset.asset_quantity
|
||||
@ -970,6 +990,15 @@ def create_new_asset_after_split(asset, split_qty):
|
||||
(row.expected_value_after_useful_life * split_qty) / asset.asset_quantity
|
||||
)
|
||||
|
||||
new_asset.insert()
|
||||
|
||||
add_asset_activity(
|
||||
new_asset.name,
|
||||
_("Asset created after being split from Asset {0}").format(
|
||||
get_link_to_form("Asset", asset.name)
|
||||
),
|
||||
)
|
||||
|
||||
new_asset.submit()
|
||||
new_asset.set_status()
|
||||
|
||||
|
@ -21,6 +21,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
get_checks_for_pl_and_bs_accounts,
|
||||
)
|
||||
from erpnext.accounts.doctype.journal_entry.journal_entry import make_reverse_journal_entry
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||
get_asset_depr_schedule_doc,
|
||||
get_asset_depr_schedule_name,
|
||||
@ -325,6 +326,8 @@ def scrap_asset(asset_name):
|
||||
frappe.db.set_value("Asset", asset_name, "journal_entry_for_scrap", je.name)
|
||||
asset.set_status("Scrapped")
|
||||
|
||||
add_asset_activity(asset_name, _("Asset scrapped"))
|
||||
|
||||
frappe.msgprint(_("Asset scrapped via Journal Entry {0}").format(je.name))
|
||||
|
||||
|
||||
@ -349,6 +352,8 @@ def restore_asset(asset_name):
|
||||
|
||||
asset.set_status()
|
||||
|
||||
add_asset_activity(asset_name, _("Asset restored"))
|
||||
|
||||
|
||||
def depreciate_asset(asset_doc, date, notes):
|
||||
asset_doc.flags.ignore_validate_update_after_submit = True
|
||||
|
0
erpnext/assets/doctype/asset_activity/__init__.py
Normal file
0
erpnext/assets/doctype/asset_activity/__init__.py
Normal file
8
erpnext/assets/doctype/asset_activity/asset_activity.js
Normal file
8
erpnext/assets/doctype/asset_activity/asset_activity.js
Normal file
@ -0,0 +1,8 @@
|
||||
// Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
// For license information, please see license.txt
|
||||
|
||||
// frappe.ui.form.on("Asset Activity", {
|
||||
// refresh(frm) {
|
||||
|
||||
// },
|
||||
// });
|
109
erpnext/assets/doctype/asset_activity/asset_activity.json
Normal file
109
erpnext/assets/doctype/asset_activity/asset_activity.json
Normal file
@ -0,0 +1,109 @@
|
||||
{
|
||||
"actions": [],
|
||||
"creation": "2023-07-28 12:41:13.232505",
|
||||
"default_view": "List",
|
||||
"doctype": "DocType",
|
||||
"editable_grid": 1,
|
||||
"engine": "InnoDB",
|
||||
"field_order": [
|
||||
"asset",
|
||||
"column_break_vkdy",
|
||||
"date",
|
||||
"column_break_kkxv",
|
||||
"user",
|
||||
"section_break_romx",
|
||||
"subject"
|
||||
],
|
||||
"fields": [
|
||||
{
|
||||
"fieldname": "asset",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"in_standard_filter": 1,
|
||||
"label": "Asset",
|
||||
"options": "Asset",
|
||||
"print_width": "165",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "165"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_vkdy",
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "section_break_romx",
|
||||
"fieldtype": "Section Break"
|
||||
},
|
||||
{
|
||||
"fieldname": "subject",
|
||||
"fieldtype": "Small Text",
|
||||
"in_list_view": 1,
|
||||
"label": "Subject",
|
||||
"print_width": "518",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "518"
|
||||
},
|
||||
{
|
||||
"default": "now",
|
||||
"fieldname": "date",
|
||||
"fieldtype": "Datetime",
|
||||
"in_list_view": 1,
|
||||
"label": "Date",
|
||||
"print_width": "158",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "158"
|
||||
},
|
||||
{
|
||||
"fieldname": "user",
|
||||
"fieldtype": "Link",
|
||||
"in_list_view": 1,
|
||||
"label": "User",
|
||||
"options": "User",
|
||||
"print_width": "150",
|
||||
"read_only": 1,
|
||||
"reqd": 1,
|
||||
"width": "150"
|
||||
},
|
||||
{
|
||||
"fieldname": "column_break_kkxv",
|
||||
"fieldtype": "Column Break"
|
||||
}
|
||||
],
|
||||
"in_create": 1,
|
||||
"index_web_pages_for_search": 1,
|
||||
"links": [],
|
||||
"modified": "2023-08-01 11:09:52.584482",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Activity",
|
||||
"owner": "Administrator",
|
||||
"permissions": [
|
||||
{
|
||||
"email": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "System Manager",
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Accounts User",
|
||||
"share": 1
|
||||
},
|
||||
{
|
||||
"email": 1,
|
||||
"read": 1,
|
||||
"report": 1,
|
||||
"role": "Quality Manager",
|
||||
"share": 1
|
||||
}
|
||||
],
|
||||
"sort_field": "modified",
|
||||
"sort_order": "DESC",
|
||||
"states": []
|
||||
}
|
20
erpnext/assets/doctype/asset_activity/asset_activity.py
Normal file
20
erpnext/assets/doctype/asset_activity/asset_activity.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and contributors
|
||||
# For license information, please see license.txt
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
|
||||
|
||||
class AssetActivity(Document):
|
||||
pass
|
||||
|
||||
|
||||
def add_asset_activity(asset, subject):
|
||||
frappe.get_doc(
|
||||
{
|
||||
"doctype": "Asset Activity",
|
||||
"asset": asset,
|
||||
"subject": subject,
|
||||
"user": frappe.session.user,
|
||||
}
|
||||
).insert(ignore_permissions=True, ignore_links=True)
|
@ -0,0 +1,9 @@
|
||||
# Copyright (c) 2023, Frappe Technologies Pvt. Ltd. and Contributors
|
||||
# See license.txt
|
||||
|
||||
# import frappe
|
||||
from frappe.tests.utils import FrappeTestCase
|
||||
|
||||
|
||||
class TestAssetActivity(FrappeTestCase):
|
||||
pass
|
@ -18,6 +18,7 @@ from erpnext.assets.doctype.asset.depreciation import (
|
||||
reset_depreciation_schedule,
|
||||
reverse_depreciation_entry_made_after_disposal,
|
||||
)
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.assets.doctype.asset_category.asset_category import get_asset_category_account
|
||||
from erpnext.controllers.stock_controller import StockController
|
||||
from erpnext.setup.doctype.brand.brand import get_brand_defaults
|
||||
@ -519,6 +520,13 @@ class AssetCapitalization(StockController):
|
||||
"fixed_asset_account", item=self.target_item_code, company=asset_doc.company
|
||||
)
|
||||
|
||||
add_asset_activity(
|
||||
asset_doc.name,
|
||||
_("Asset created after Asset Capitalization {0} was submitted").format(
|
||||
get_link_to_form("Asset Capitalization", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
frappe.msgprint(
|
||||
_(
|
||||
"Asset {0} has been created. Please set the depreciation details if any and submit it."
|
||||
@ -542,9 +550,30 @@ class AssetCapitalization(StockController):
|
||||
|
||||
def set_consumed_asset_status(self, asset):
|
||||
if self.docstatus == 1:
|
||||
asset.set_status("Capitalized" if self.target_is_fixed_asset else "Decapitalized")
|
||||
if self.target_is_fixed_asset:
|
||||
asset.set_status("Capitalized")
|
||||
add_asset_activity(
|
||||
asset.name,
|
||||
_("Asset capitalized after Asset Capitalization {0} was submitted").format(
|
||||
get_link_to_form("Asset Capitalization", self.name)
|
||||
),
|
||||
)
|
||||
else:
|
||||
asset.set_status("Decapitalized")
|
||||
add_asset_activity(
|
||||
asset.name,
|
||||
_("Asset decapitalized after Asset Capitalization {0} was submitted").format(
|
||||
get_link_to_form("Asset Capitalization", self.name)
|
||||
),
|
||||
)
|
||||
else:
|
||||
asset.set_status()
|
||||
add_asset_activity(
|
||||
asset.name,
|
||||
_("Asset restored after Asset Capitalization {0} was cancelled").format(
|
||||
get_link_to_form("Asset Capitalization", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@frappe.whitelist()
|
||||
|
@ -5,6 +5,9 @@
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import get_link_to_form
|
||||
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
|
||||
|
||||
class AssetMovement(Document):
|
||||
@ -128,5 +131,24 @@ class AssetMovement(Document):
|
||||
current_location = latest_movement_entry[0][0]
|
||||
current_employee = latest_movement_entry[0][1]
|
||||
|
||||
frappe.db.set_value("Asset", d.asset, "location", current_location)
|
||||
frappe.db.set_value("Asset", d.asset, "custodian", current_employee)
|
||||
frappe.db.set_value("Asset", d.asset, "location", current_location, update_modified=False)
|
||||
frappe.db.set_value("Asset", d.asset, "custodian", current_employee, update_modified=False)
|
||||
|
||||
if current_location and current_employee:
|
||||
add_asset_activity(
|
||||
d.asset,
|
||||
_("Asset received at Location {0} and issued to Employee {1}").format(
|
||||
get_link_to_form("Location", current_location),
|
||||
get_link_to_form("Employee", current_employee),
|
||||
),
|
||||
)
|
||||
elif current_location:
|
||||
add_asset_activity(
|
||||
d.asset,
|
||||
_("Asset transferred to Location {0}").format(get_link_to_form("Location", current_location)),
|
||||
)
|
||||
elif current_employee:
|
||||
add_asset_activity(
|
||||
d.asset,
|
||||
_("Asset issued to Employee {0}").format(get_link_to_form("Employee", current_employee)),
|
||||
)
|
||||
|
@ -8,6 +8,7 @@ from frappe.utils import add_months, cint, flt, get_link_to_form, getdate, time_
|
||||
import erpnext
|
||||
from erpnext.accounts.general_ledger import make_gl_entries
|
||||
from erpnext.assets.doctype.asset.asset import get_asset_account
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||
get_depr_schedule,
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones,
|
||||
@ -25,8 +26,14 @@ class AssetRepair(AccountsController):
|
||||
self.calculate_total_repair_cost()
|
||||
|
||||
def update_status(self):
|
||||
if self.repair_status == "Pending":
|
||||
if self.repair_status == "Pending" and self.asset_doc.status != "Out of Order":
|
||||
frappe.db.set_value("Asset", self.asset, "status", "Out of Order")
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("Asset out of order due to Asset Repair {0}").format(
|
||||
get_link_to_form("Asset Repair", self.name)
|
||||
),
|
||||
)
|
||||
else:
|
||||
self.asset_doc.set_status()
|
||||
|
||||
@ -68,6 +75,13 @@ class AssetRepair(AccountsController):
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes)
|
||||
self.asset_doc.save()
|
||||
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("Asset updated after completion of Asset Repair {0}").format(
|
||||
get_link_to_form("Asset Repair", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
def before_cancel(self):
|
||||
self.asset_doc = frappe.get_doc("Asset", self.asset)
|
||||
|
||||
@ -95,6 +109,13 @@ class AssetRepair(AccountsController):
|
||||
make_new_active_asset_depr_schedules_and_cancel_current_ones(self.asset_doc, notes)
|
||||
self.asset_doc.save()
|
||||
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("Asset updated after cancellation of Asset Repair {0}").format(
|
||||
get_link_to_form("Asset Repair", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
def after_delete(self):
|
||||
frappe.get_doc("Asset", self.asset).set_status()
|
||||
|
||||
|
@ -12,6 +12,7 @@ from erpnext.accounts.doctype.accounting_dimension.accounting_dimension import (
|
||||
)
|
||||
from erpnext.assets.doctype.asset.asset import get_asset_value_after_depreciation
|
||||
from erpnext.assets.doctype.asset.depreciation import get_depreciation_accounts
|
||||
from erpnext.assets.doctype.asset_activity.asset_activity import add_asset_activity
|
||||
from erpnext.assets.doctype.asset_depreciation_schedule.asset_depreciation_schedule import (
|
||||
get_asset_depr_schedule_doc,
|
||||
get_depreciation_amount,
|
||||
@ -27,9 +28,21 @@ class AssetValueAdjustment(Document):
|
||||
def on_submit(self):
|
||||
self.make_depreciation_entry()
|
||||
self.reschedule_depreciations(self.new_asset_value)
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("Asset's value adjusted after submission of Asset Value Adjustment {0}").format(
|
||||
get_link_to_form("Asset Value Adjustment", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
def on_cancel(self):
|
||||
self.reschedule_depreciations(self.current_asset_value)
|
||||
add_asset_activity(
|
||||
self.asset,
|
||||
_("Asset's value adjusted after cancellation of Asset Value Adjustment {0}").format(
|
||||
get_link_to_form("Asset Value Adjustment", self.name)
|
||||
),
|
||||
)
|
||||
|
||||
def validate_date(self):
|
||||
asset_purchase_date = frappe.db.get_value("Asset", self.asset, "purchase_date")
|
||||
@ -74,12 +87,16 @@ class AssetValueAdjustment(Document):
|
||||
"account": accumulated_depreciation_account,
|
||||
"credit_in_account_currency": self.difference_amount,
|
||||
"cost_center": depreciation_cost_center or self.cost_center,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": self.asset,
|
||||
}
|
||||
|
||||
debit_entry = {
|
||||
"account": depreciation_expense_account,
|
||||
"debit_in_account_currency": self.difference_amount,
|
||||
"cost_center": depreciation_cost_center or self.cost_center,
|
||||
"reference_type": "Asset",
|
||||
"reference_name": self.asset,
|
||||
}
|
||||
|
||||
accounting_dimensions = get_checks_for_pl_and_bs_accounts()
|
||||
|
0
erpnext/assets/report/asset_activity/__init__.py
Normal file
0
erpnext/assets/report/asset_activity/__init__.py
Normal file
33
erpnext/assets/report/asset_activity/asset_activity.json
Normal file
33
erpnext/assets/report/asset_activity/asset_activity.json
Normal file
@ -0,0 +1,33 @@
|
||||
{
|
||||
"add_total_row": 0,
|
||||
"columns": [],
|
||||
"creation": "2023-08-01 11:14:46.581234",
|
||||
"disabled": 0,
|
||||
"docstatus": 0,
|
||||
"doctype": "Report",
|
||||
"filters": [],
|
||||
"idx": 0,
|
||||
"is_standard": "Yes",
|
||||
"json": "{}",
|
||||
"letterhead": null,
|
||||
"modified": "2023-08-01 11:14:46.581234",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Assets",
|
||||
"name": "Asset Activity",
|
||||
"owner": "Administrator",
|
||||
"prepared_report": 0,
|
||||
"ref_doctype": "Asset Activity",
|
||||
"report_name": "Asset Activity",
|
||||
"report_type": "Report Builder",
|
||||
"roles": [
|
||||
{
|
||||
"role": "System Manager"
|
||||
},
|
||||
{
|
||||
"role": "Accounts User"
|
||||
},
|
||||
{
|
||||
"role": "Quality Manager"
|
||||
}
|
||||
]
|
||||
}
|
@ -183,6 +183,17 @@
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
},
|
||||
{
|
||||
"dependencies": "Asset Activity",
|
||||
"hidden": 0,
|
||||
"is_query_report": 0,
|
||||
"label": "Asset Activity",
|
||||
"link_count": 0,
|
||||
"link_to": "Asset Activity",
|
||||
"link_type": "Report",
|
||||
"onboard": 0,
|
||||
"type": "Link"
|
||||
}
|
||||
],
|
||||
"modified": "2023-05-24 14:47:20.243146",
|
||||
|
Loading…
Reference in New Issue
Block a user