Seera-Unified-Asset/asset_lite/api/asset_maintenance_api.py
2026-03-23 17:34:51 +05:30

712 lines
23 KiB
Python

import frappe
from frappe import _
@frappe.whitelist(allow_guest = True)
def get_asset_maintenance_logs(filters=None, fields=None, limit=20, offset=0, order_by=None, include_child_tables=False):
"""
Get list of asset maintenance logs with filters and pagination
Args:
filters: JSON string of filters (e.g., '{"maintenance_status": "Planned"}')
fields: JSON string of fields to return (e.g., '["asset_name", "due_date"]')
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
order_by: Sort order (e.g., "creation desc")
include_child_tables: Whether to include child table data (default: False)
Returns:
{
"asset_maintenance_logs": [...],
"total_count": int,
"limit": int,
"offset": int,
"has_more": bool
}
"""
try:
import json
# Parse filters if provided
if filters and isinstance(filters, str):
filters = json.loads(filters)
# Parse fields if provided
if fields and isinstance(fields, str):
fields = json.loads(fields)
else:
# Default fields to return
fields = [
'name',
'asset_maintenance',
'naming_series',
'asset_name',
'custom_asset_type',
'item_code',
'item_name',
'custom_asset_names',
'custom_hospital_name',
'task',
'task_name',
'maintenance_type',
'periodicity',
'has_certificate',
'custom_early_completion',
'maintenance_status',
'custom_pm_overdue_reason',
'custom_accepted_by_moh',
'assign_to_name',
'due_date',
'completion_date',
'custom_early_completion_reason',
'custom_accepted_by_moh_',
'custom_template',
'workflow_state',
'creation',
'modified',
'owner',
'modified_by',
'docstatus',
'idx'
]
# Get total count
total_count = frappe.db.count('Asset Maintenance Log', filters=filters or {})
# Get asset maintenance logs
asset_maintenance_logs = frappe.get_all(
'Asset Maintenance Log',
filters=filters or {},
fields=fields,
limit_page_length=int(limit),
limit_start=int(offset),
order_by=order_by or 'creation desc'
)
# Include child tables if requested
if include_child_tables and include_child_tables != 'false':
for log in asset_maintenance_logs:
log['custom_table'] = frappe.get_all(
'PPM Table',
filters={'parent': log['name']},
fields=['name', 'idx', 'maintenance_name', 'working', 'defect_found', 'not_working'],
order_by='idx asc'
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'asset_maintenance_logs': asset_maintenance_logs,
'total_count': total_count,
'limit': int(limit),
'offset': int(offset),
'has_more': has_more
}
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get Asset Maintenance Logs API Error')
frappe.response['message'] = {
'error': str(e),
'asset_maintenance_logs': [],
'total_count': 0
}
@frappe.whitelist(allow_guest = True)
def get_asset_maintenance_log_details(log_name, include_child_tables=True):
"""
Get detailed information about a specific asset maintenance log
Args:
log_name: Name/ID of the asset maintenance log
include_child_tables: Whether to include child table data (default: True)
Returns:
Asset Maintenance Log document with all fields including child tables
"""
try:
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
# Check if user has permission to read this log
if not frappe.has_permission('Asset Maintenance Log', 'read', log_name):
frappe.throw(_('Not permitted to access this asset maintenance log'))
# Get asset maintenance log details
log = frappe.get_doc('Asset Maintenance Log', log_name)
frappe.response['message'] = log.as_dict()
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get Asset Maintenance Log Details API Error')
frappe.response['message'] = {
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def create_asset_maintenance_log(log_data):
"""
Create a new asset maintenance log
Args:
log_data: JSON string containing asset maintenance log fields
Returns:
Created asset maintenance log document
"""
try:
import json
# Parse log data
if isinstance(log_data, str):
log_data = json.loads(log_data)
# Check if user has permission to create asset maintenance log
if not frappe.has_permission('Asset Maintenance Log', 'create'):
frappe.throw(_('Not permitted to create asset maintenance log'))
# Extract child table data
custom_table_data = log_data.pop('custom_table', [])
# Create new asset maintenance log
log = frappe.get_doc({
'doctype': 'Asset Maintenance Log',
**log_data
})
# Add child table rows
if custom_table_data:
for row_data in custom_table_data:
log.append('custom_table', {
'maintenance_name': row_data.get('maintenance_name', ''),
'working': row_data.get('working', 0),
'defect_found': row_data.get('defect_found', 0),
'not_working': row_data.get('not_working', 0)
})
log.insert()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'asset_maintenance_log': log.as_dict(),
'message': _('Asset Maintenance Log created successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Create Asset Maintenance Log API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def update_asset_maintenance_log(log_name, log_data):
"""
Update an existing asset maintenance log
Args:
log_name: Name/ID of the asset maintenance log
log_data: JSON string containing fields to update
Returns:
Updated asset maintenance log document
"""
try:
import json
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
# Parse log data
if isinstance(log_data, str):
log_data = json.loads(log_data)
# Check if user has permission to update this log
if not frappe.has_permission('Asset Maintenance Log', 'write', log_name):
frappe.throw(_('Not permitted to update this asset maintenance log'))
# Get asset maintenance log
log = frappe.get_doc('Asset Maintenance Log', log_name)
# Extract child table data before processing other fields
custom_table_data = log_data.pop('custom_table', None)
# List of child table fields to skip in regular update
child_table_fields = ['custom_table', 'table']
# Update regular fields (not child tables)
for key, value in log_data.items():
if key not in child_table_fields and hasattr(log, key):
setattr(log, key, value)
# Handle child table update if provided
if custom_table_data is not None:
# Clear existing child table rows
log.custom_table = []
# Add new child table rows
for row_data in custom_table_data:
log.append('custom_table', {
'maintenance_name': row_data.get('maintenance_name', ''),
'working': row_data.get('working', 0),
'defect_found': row_data.get('defect_found', 0),
'not_working': row_data.get('not_working', 0)
})
log.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'asset_maintenance_log': log.as_dict(),
'message': _('Asset Maintenance Log updated successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Update Asset Maintenance Log API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def delete_asset_maintenance_log(log_name):
"""
Delete an asset maintenance log
Args:
log_name: Name/ID of the asset maintenance log
Returns:
Success message
"""
try:
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
# Check if user has permission to delete this log
if not frappe.has_permission('Asset Maintenance Log', 'delete', log_name):
frappe.throw(_('Not permitted to delete this asset maintenance log'))
# Delete asset maintenance log
frappe.delete_doc('Asset Maintenance Log', log_name)
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'message': _('Asset Maintenance Log deleted successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Delete Asset Maintenance Log API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def update_maintenance_status(log_name, maintenance_status=None, workflow_state=None):
"""
Update asset maintenance log status
Args:
log_name: Name/ID of the asset maintenance log
maintenance_status: New maintenance status (e.g., 'Planned', 'Completed', 'Overdue')
workflow_state: New workflow state
Returns:
Updated asset maintenance log document
"""
try:
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
# Check if user has permission to update this log
if not frappe.has_permission('Asset Maintenance Log', 'write', log_name):
frappe.throw(_('Not permitted to update this asset maintenance log'))
# Get asset maintenance log
log = frappe.get_doc('Asset Maintenance Log', log_name)
# Update status fields
if maintenance_status:
log.maintenance_status = maintenance_status
if workflow_state:
log.workflow_state = workflow_state
log.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'asset_maintenance_log': log.as_dict(),
'message': _('Asset Maintenance Log status updated successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Update Maintenance Status API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def get_maintenance_logs_by_asset(asset_name, filters=None, limit=20, offset=0, include_child_tables=False):
"""
Get all maintenance logs for a specific asset
Args:
asset_name: Name/ID of the asset
filters: Additional JSON string of filters
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
include_child_tables: Whether to include child table data (default: False)
Returns:
List of maintenance logs for the asset
"""
try:
import json
if not asset_name:
frappe.throw(_('Asset name is required'))
# Parse additional filters if provided
additional_filters = {}
if filters and isinstance(filters, str):
additional_filters = json.loads(filters)
# Combine filters
combined_filters = {'asset_name': asset_name, **additional_filters}
# Get total count
total_count = frappe.db.count('Asset Maintenance Log', filters=combined_filters)
# Get maintenance logs
logs = frappe.get_all(
'Asset Maintenance Log',
filters=combined_filters,
fields=['*'],
limit_page_length=int(limit),
limit_start=int(offset),
order_by='due_date desc'
)
# Include child tables if requested
if include_child_tables and include_child_tables != 'false':
for log in logs:
log['custom_table'] = frappe.get_all(
'PPM Table',
filters={'parent': log['name']},
fields=['name', 'idx', 'maintenance_name', 'working', 'defect_found', 'not_working'],
order_by='idx asc'
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'asset_maintenance_logs': logs,
'total_count': total_count,
'limit': int(limit),
'offset': int(offset),
'has_more': has_more
}
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get Maintenance Logs By Asset API Error')
frappe.response['message'] = {
'error': str(e),
'asset_maintenance_logs': [],
'total_count': 0
}
@frappe.whitelist(allow_guest = True)
def get_overdue_maintenance_logs(filters=None, limit=20, offset=0, include_child_tables=False):
"""
Get all overdue maintenance logs
Args:
filters: Additional JSON string of filters
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
include_child_tables: Whether to include child table data (default: False)
Returns:
List of overdue maintenance logs
"""
try:
import json
from frappe.utils import today
# Parse additional filters if provided
additional_filters = {}
if filters and isinstance(filters, str):
additional_filters = json.loads(filters)
# Combine filters - get logs with due_date less than today and status not completed
combined_filters = {
'due_date': ['<', today()],
'maintenance_status': ['!=', 'Completed'],
**additional_filters
}
# Get total count
total_count = frappe.db.count('Asset Maintenance Log', filters=combined_filters)
# Get overdue logs
logs = frappe.get_all(
'Asset Maintenance Log',
filters=combined_filters,
fields=['*'],
limit_page_length=int(limit),
limit_start=int(offset),
order_by='due_date asc'
)
# Include child tables if requested
if include_child_tables and include_child_tables != 'false':
for log in logs:
log['custom_table'] = frappe.get_all(
'PPM Table',
filters={'parent': log['name']},
fields=['name', 'idx', 'maintenance_name', 'working', 'defect_found', 'not_working'],
order_by='idx asc'
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'asset_maintenance_logs': logs,
'total_count': total_count,
'limit': int(limit),
'offset': int(offset),
'has_more': has_more
}
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get Overdue Maintenance Logs API Error')
frappe.response['message'] = {
'error': str(e),
'asset_maintenance_logs': [],
'total_count': 0
}
@frappe.whitelist(allow_guest = True)
def add_ppm_table_row(log_name, row_data):
"""
Add a PPM table row to a maintenance log
Args:
log_name: Name/ID of the asset maintenance log
row_data: JSON string containing row fields
Returns:
Updated custom_table array
"""
try:
import json
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
# Parse row data
if isinstance(row_data, str):
row_data = json.loads(row_data)
# Check permission
if not frappe.has_permission('Asset Maintenance Log', 'write', log_name):
frappe.throw(_('Not permitted to update this asset maintenance log'))
# Get log and add row
log = frappe.get_doc('Asset Maintenance Log', log_name)
log.append('custom_table', {
'maintenance_name': row_data.get('maintenance_name', ''),
'working': row_data.get('working', 0),
'defect_found': row_data.get('defect_found', 0),
'not_working': row_data.get('not_working', 0)
})
log.save()
frappe.db.commit()
# Return updated child table
custom_table = []
for row in log.custom_table:
custom_table.append({
'name': row.name,
'idx': row.idx,
'maintenance_name': row.maintenance_name,
'working': row.working,
'defect_found': row.defect_found,
'not_working': row.not_working
})
frappe.response['message'] = {
'success': True,
'custom_table': custom_table,
'message': _('PPM table row added successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Add PPM Table Row API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def remove_ppm_table_row(log_name, row_name):
"""
Remove a PPM table row from a maintenance log
Args:
log_name: Name/ID of the asset maintenance log
row_name: Name/ID of the row to remove
Returns:
Updated custom_table array
"""
try:
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
if not row_name:
frappe.throw(_('Row name is required'))
# Check permission
if not frappe.has_permission('Asset Maintenance Log', 'write', log_name):
frappe.throw(_('Not permitted to update this asset maintenance log'))
# Get log and remove row
log = frappe.get_doc('Asset Maintenance Log', log_name)
# Find and remove the row
row_to_remove = None
for row in log.custom_table:
if row.name == row_name:
row_to_remove = row
break
if row_to_remove:
log.remove(row_to_remove)
log.save()
frappe.db.commit()
# Return updated child table
custom_table = []
for row in log.custom_table:
custom_table.append({
'name': row.name,
'idx': row.idx,
'maintenance_name': row.maintenance_name,
'working': row.working,
'defect_found': row.defect_found,
'not_working': row.not_working
})
frappe.response['message'] = {
'success': True,
'custom_table': custom_table,
'message': _('PPM table row removed successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Remove PPM Table Row API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest = True)
def update_ppm_table_row(log_name, row_name, row_data):
"""
Update a PPM table row in a maintenance log
Args:
log_name: Name/ID of the asset maintenance log
row_name: Name/ID of the row to update
row_data: JSON string containing fields to update
Returns:
Updated custom_table array
"""
try:
import json
if not log_name:
frappe.throw(_('Asset Maintenance Log name is required'))
if not row_name:
frappe.throw(_('Row name is required'))
# Parse row data
if isinstance(row_data, str):
row_data = json.loads(row_data)
# Check permission
if not frappe.has_permission('Asset Maintenance Log', 'write', log_name):
frappe.throw(_('Not permitted to update this asset maintenance log'))
# Get log and update row
log = frappe.get_doc('Asset Maintenance Log', log_name)
# Find and update the row
for row in log.custom_table:
if row.name == row_name:
if 'maintenance_name' in row_data:
row.maintenance_name = row_data['maintenance_name']
if 'working' in row_data:
row.working = row_data['working']
if 'defect_found' in row_data:
row.defect_found = row_data['defect_found']
if 'not_working' in row_data:
row.not_working = row_data['not_working']
break
log.save()
frappe.db.commit()
# Return updated child table
custom_table = []
for row in log.custom_table:
custom_table.append({
'name': row.name,
'idx': row.idx,
'maintenance_name': row.maintenance_name,
'working': row.working,
'defect_found': row.defect_found,
'not_working': row.not_working
})
frappe.response['message'] = {
'success': True,
'custom_table': custom_table,
'message': _('PPM table row updated successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Update PPM Table Row API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}