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

1197 lines
39 KiB
Python

import frappe
from frappe import _
# Default fields for PM Schedule Generator doctype
PM_SCHEDULE_GENERATOR_FIELDS = [
'name',
'owner',
'creation',
'modified',
'modified_by',
'docstatus',
'idx',
'hospital',
'modality',
'device_status',
'start_date',
'maintenance_team',
'maintenance_manager',
'end_date',
'periodicity',
'assign_to',
'due_date'
]
# Child table: PM Entry Line (maintenance_entries)
PM_ENTRY_LINE_FIELDS = [
'name',
'owner',
'creation',
'modified',
'modified_by',
'docstatus',
'idx',
'parent',
'parentfield',
'parenttype',
'asset',
'asset_name',
'start_date',
'end_date',
'manufacturer',
'model'
]
@frappe.whitelist()
def create_bulk_schedules(asset_names, start_date, end_date, maintenance_team=None, periodicity='Monthly', maintenance_type='Preventive'):
"""Create maintenance schedules for multiple assets"""
created_schedules = []
for asset_name in asset_names:
# Create Asset Maintenance record
maintenance = frappe.get_doc({
'doctype': 'Asset Maintenance',
'asset_name': asset_name,
'maintenance_type': maintenance_type,
'periodicity': periodicity,
'maintenance_team': maintenance_team
})
maintenance.insert()
created_schedules.append(maintenance.name)
return {
'success': True,
'created': len(created_schedules),
'schedules': created_schedules
}
def get_child_table_data(parent_name, parentfield, child_doctype, fields=None):
"""
Get child table data for a PM Schedule Generator
Args:
parent_name: Name of the parent PM Schedule Generator
parentfield: Field name of the child table in parent
child_doctype: Doctype of the child table
fields: List of fields to return
Returns:
List of child table records
"""
try:
return frappe.get_all(
child_doctype,
filters={
'parent': parent_name,
'parentfield': parentfield,
'parenttype': 'PM Schedule Generator'
},
fields=fields or ['*'],
order_by='idx asc'
)
except Exception:
return []
@frappe.whitelist(allow_guest=True)
def get_pm_schedules(filters=None, fields=None, limit=20, offset=0, order_by=None, include_child_tables=False):
"""
Get list of PM Schedule Generators with filters and pagination
Args:
filters: JSON string of filters (e.g., '{"hospital": "Domat Al Jandal Hospital"}')
fields: JSON string of fields to return (e.g., '["hospital", "modality"]')
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:
{
"pm_schedules": [...],
"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:
fields = PM_SCHEDULE_GENERATOR_FIELDS.copy()
# Parse include_child_tables
if isinstance(include_child_tables, str):
include_child_tables = include_child_tables.lower() in ('true', '1', 'yes')
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters or {})
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
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:
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedule_details(pm_schedule_name):
"""
Get detailed information about a specific PM Schedule Generator
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
Returns:
PM Schedule Generator document with all fields including child tables
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Check if user has permission to read this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'read', pm_schedule_name):
frappe.throw(_('Not permitted to access this PM Schedule Generator'))
# Get PM Schedule details
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
# Convert to dict and include child tables
pm_schedule_dict = pm_schedule.as_dict()
# Ensure child tables are included with all fields
pm_schedule_dict['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
frappe.response['message'] = pm_schedule_dict
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get PM Schedule Details API Error')
frappe.response['message'] = {
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def create_pm_schedule(pm_schedule_data):
"""
Create a new PM Schedule Generator
Args:
pm_schedule_data: JSON string containing PM Schedule fields including child tables
Example:
{
"hospital": "Domat Al Jandal Hospital",
"modality": "X-Ray",
"start_date": "2025-12-23",
"end_date": "2026-12-23",
"periodicity": "Monthly",
"maintenance_team": "DAJH Maintenance Team",
"maintenance_manager": "manager@example.com",
"assign_to": "technician@example.com",
"due_date": "2026-01-23",
"maintenance_entries": [
{
"asset": "ACC-ASS-2025-00100",
"asset_name": "Test Asset 1",
"start_date": "2025-12-23",
"end_date": "2026-12-23",
"manufacturer": "ABV",
"model": ""
}
]
}
Returns:
Created PM Schedule Generator document
"""
try:
import json
# Parse PM schedule data
if isinstance(pm_schedule_data, str):
pm_schedule_data = json.loads(pm_schedule_data)
# Check if user has permission to create PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'create'):
frappe.throw(_('Not permitted to create PM Schedule Generator'))
# Create new PM Schedule
pm_schedule = frappe.get_doc({
'doctype': 'PM Schedule Generator',
**pm_schedule_data
})
pm_schedule.insert()
frappe.db.commit()
# Return created PM Schedule with child tables
pm_schedule_dict = pm_schedule.as_dict()
pm_schedule_dict['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
frappe.response['message'] = {
'success': True,
'pm_schedule': pm_schedule_dict,
'message': _('PM Schedule Generator created successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Create PM Schedule API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def update_pm_schedule(pm_schedule_name, pm_schedule_data):
"""
Update an existing PM Schedule Generator including child tables
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
pm_schedule_data: JSON string containing fields to update
Example:
{
"periodicity": "Quarterly",
"maintenance_entries": [
{
"asset": "ACC-ASS-2025-00100",
"asset_name": "Test Asset 1",
"start_date": "2025-12-23",
"end_date": "2026-12-23"
}
]
}
Returns:
Updated PM Schedule Generator document
"""
try:
import json
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Parse PM schedule data
if isinstance(pm_schedule_data, str):
pm_schedule_data = json.loads(pm_schedule_data)
# Check if user has permission to update this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'write', pm_schedule_name):
frappe.throw(_('Not permitted to update this PM Schedule Generator'))
# Get PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
# Handle child tables separately
child_tables = ['maintenance_entries']
for key, value in pm_schedule_data.items():
if key in child_tables:
# Clear existing child table entries and add new ones
pm_schedule.set(key, [])
for item in value:
pm_schedule.append(key, item)
elif hasattr(pm_schedule, key):
setattr(pm_schedule, key, value)
pm_schedule.save()
frappe.db.commit()
# Return updated PM Schedule with child tables
pm_schedule_dict = pm_schedule.as_dict()
pm_schedule_dict['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
frappe.response['message'] = {
'success': True,
'pm_schedule': pm_schedule_dict,
'message': _('PM Schedule Generator updated successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Update PM Schedule API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def delete_pm_schedule(pm_schedule_name):
"""
Delete a PM Schedule Generator
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
Returns:
Success message
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Check if user has permission to delete this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'delete', pm_schedule_name):
frappe.throw(_('Not permitted to delete this PM Schedule Generator'))
# Delete PM Schedule (child tables will be deleted automatically)
frappe.delete_doc('PM Schedule Generator', pm_schedule_name)
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'message': _('PM Schedule Generator deleted successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Delete PM Schedule API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def submit_pm_schedule(pm_schedule_name):
"""
Submit a PM Schedule Generator (change docstatus to 1)
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
Returns:
Submitted PM Schedule Generator document
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Check if user has permission to submit this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'submit', pm_schedule_name):
frappe.throw(_('Not permitted to submit this PM Schedule Generator'))
# Get and submit PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
pm_schedule.submit()
frappe.db.commit()
# Return submitted PM Schedule with child tables
pm_schedule_dict = pm_schedule.as_dict()
pm_schedule_dict['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
frappe.response['message'] = {
'success': True,
'pm_schedule': pm_schedule_dict,
'message': _('PM Schedule Generator submitted successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Submit PM Schedule API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def cancel_pm_schedule(pm_schedule_name):
"""
Cancel a PM Schedule Generator (change docstatus to 2)
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
Returns:
Cancelled PM Schedule Generator document
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Check if user has permission to cancel this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'cancel', pm_schedule_name):
frappe.throw(_('Not permitted to cancel this PM Schedule Generator'))
# Get and cancel PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
pm_schedule.cancel()
frappe.db.commit()
# Return cancelled PM Schedule with child tables
pm_schedule_dict = pm_schedule.as_dict()
pm_schedule_dict['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
frappe.response['message'] = {
'success': True,
'pm_schedule': pm_schedule_dict,
'message': _('PM Schedule Generator cancelled successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Cancel PM Schedule API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def add_maintenance_entry(pm_schedule_name, entry_data):
"""
Add a maintenance entry to PM Schedule's maintenance_entries child table
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
entry_data: JSON string containing maintenance entry fields
Example:
{
"asset": "ACC-ASS-2025-00100",
"asset_name": "Test Asset 1",
"start_date": "2025-12-23",
"end_date": "2026-12-23",
"manufacturer": "ABV",
"model": "Model X"
}
Returns:
Updated PM Schedule with maintenance entries
"""
try:
import json
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Parse entry data
if isinstance(entry_data, str):
entry_data = json.loads(entry_data)
# Check if user has permission to update this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'write', pm_schedule_name):
frappe.throw(_('Not permitted to update this PM Schedule Generator'))
# Get PM Schedule and add maintenance entry
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
pm_schedule.append('maintenance_entries', entry_data)
pm_schedule.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'maintenance_entries': [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])],
'message': _('Maintenance entry added successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Add Maintenance Entry API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def remove_maintenance_entry(pm_schedule_name, entry_name):
"""
Remove a maintenance entry from PM Schedule's maintenance_entries child table
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
entry_name: Name/ID of the maintenance entry to remove
Returns:
Updated PM Schedule with remaining maintenance entries
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
if not entry_name:
frappe.throw(_('Maintenance entry name is required'))
# Check if user has permission to update this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'write', pm_schedule_name):
frappe.throw(_('Not permitted to update this PM Schedule Generator'))
# Get PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
# Find and remove the maintenance entry
entry_to_remove = None
for entry in pm_schedule.maintenance_entries:
if entry.name == entry_name:
entry_to_remove = entry
break
if entry_to_remove:
pm_schedule.remove(entry_to_remove)
pm_schedule.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'maintenance_entries': [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])],
'message': _('Maintenance entry removed successfully')
}
else:
frappe.response['message'] = {
'success': False,
'error': _('Maintenance entry not found')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Remove Maintenance Entry API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def update_maintenance_entry(pm_schedule_name, entry_name, entry_data):
"""
Update a specific maintenance entry in the PM Schedule
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
entry_name: Name/ID of the maintenance entry to update
entry_data: JSON string containing fields to update
Returns:
Updated PM Schedule with maintenance entries
"""
try:
import json
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
if not entry_name:
frappe.throw(_('Maintenance entry name is required'))
# Parse entry data
if isinstance(entry_data, str):
entry_data = json.loads(entry_data)
# Check if user has permission to update this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'write', pm_schedule_name):
frappe.throw(_('Not permitted to update this PM Schedule Generator'))
# Get PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
# Find and update the maintenance entry
entry_found = False
for entry in pm_schedule.maintenance_entries:
if entry.name == entry_name:
for key, value in entry_data.items():
if hasattr(entry, key):
setattr(entry, key, value)
entry_found = True
break
if entry_found:
pm_schedule.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'maintenance_entries': [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])],
'message': _('Maintenance entry updated successfully')
}
else:
frappe.response['message'] = {
'success': False,
'error': _('Maintenance entry not found')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Update Maintenance Entry API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedule_child_tables(pm_schedule_name, child_table=None):
"""
Get child table data for a PM Schedule Generator
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
child_table: Specific child table to return ('maintenance_entries')
If None, returns all child tables
Returns:
Child table data
"""
try:
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Check if user has permission to read this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'read', pm_schedule_name):
frappe.throw(_('Not permitted to access this PM Schedule Generator'))
# Get PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
result = {}
if child_table:
if child_table == 'maintenance_entries':
result['maintenance_entries'] = [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
else:
frappe.throw(_('Invalid child table name'))
else:
result = {
'maintenance_entries': [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])]
}
frappe.response['message'] = {
'success': True,
'pm_schedule_name': pm_schedule_name,
**result
}
except Exception as e:
frappe.log_error(frappe.get_traceback(), 'Get PM Schedule Child Tables API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def bulk_update_maintenance_entries(pm_schedule_name, maintenance_entries):
"""
Bulk update/replace all maintenance entries in a PM Schedule Generator
Args:
pm_schedule_name: Name/ID of the PM Schedule Generator
maintenance_entries: JSON string containing list of maintenance entries
Returns:
Updated PM Schedule with new maintenance entries
"""
try:
import json
if not pm_schedule_name:
frappe.throw(_('PM Schedule Generator name is required'))
# Parse maintenance entries
if isinstance(maintenance_entries, str):
maintenance_entries = json.loads(maintenance_entries)
# Check if user has permission to update this PM Schedule
if not frappe.has_permission('PM Schedule Generator', 'write', pm_schedule_name):
frappe.throw(_('Not permitted to update this PM Schedule Generator'))
# Get PM Schedule
pm_schedule = frappe.get_doc('PM Schedule Generator', pm_schedule_name)
# Clear existing maintenance entries and add new ones
pm_schedule.set('maintenance_entries', [])
for entry in maintenance_entries:
pm_schedule.append('maintenance_entries', entry)
pm_schedule.save()
frappe.db.commit()
frappe.response['message'] = {
'success': True,
'maintenance_entries': [item.as_dict() for item in pm_schedule.get('maintenance_entries', [])],
'message': _('Maintenance entries updated successfully')
}
except Exception as e:
frappe.db.rollback()
frappe.log_error(frappe.get_traceback(), 'Bulk Update Maintenance Entries API Error')
frappe.response['message'] = {
'success': False,
'error': str(e)
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedules_by_hospital(hospital, limit=20, offset=0):
"""
Get PM Schedules filtered by hospital
Args:
hospital: Hospital name to filter by
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of PM Schedules for the specified hospital
"""
try:
if not hospital:
frappe.throw(_('Hospital name is required'))
filters = {'hospital': hospital}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='creation desc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules By Hospital API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedules_by_maintenance_team(maintenance_team, limit=20, offset=0):
"""
Get PM Schedules filtered by maintenance team
Args:
maintenance_team: Maintenance team name to filter by
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of PM Schedules for the specified maintenance team
"""
try:
if not maintenance_team:
frappe.throw(_('Maintenance team name is required'))
filters = {'maintenance_team': maintenance_team}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='creation desc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules By Maintenance Team API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedules_by_assignee(assign_to, limit=20, offset=0):
"""
Get PM Schedules filtered by assigned user
Args:
assign_to: Assigned user email to filter by
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of PM Schedules assigned to the specified user
"""
try:
if not assign_to:
frappe.throw(_('Assignee email is required'))
filters = {'assign_to': assign_to}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='due_date asc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules By Assignee API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedules_by_date_range(start_date=None, end_date=None, limit=20, offset=0):
"""
Get PM Schedules within a date range
Args:
start_date: Start date filter (YYYY-MM-DD)
end_date: End date filter (YYYY-MM-DD)
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of PM Schedules within the specified date range
"""
try:
filters = {}
if start_date:
filters['start_date'] = ['>=', start_date]
if end_date:
filters['end_date'] = ['<=', end_date]
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='start_date asc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules By Date Range API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_pm_schedules_by_periodicity(periodicity, limit=20, offset=0):
"""
Get PM Schedules filtered by periodicity
Args:
periodicity: Periodicity to filter by (e.g., 'Monthly', 'Quarterly', 'Yearly')
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of PM Schedules with the specified periodicity
"""
try:
if not periodicity:
frappe.throw(_('Periodicity is required'))
filters = {'periodicity': periodicity}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='creation desc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules By Periodicity API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_overdue_pm_schedules(limit=20, offset=0):
"""
Get PM Schedules that are overdue (due_date < today and docstatus != 2)
Args:
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of overdue PM Schedules
"""
try:
from frappe.utils import today
filters = {
'due_date': ['<', today()],
'docstatus': ['!=', 2] # Exclude cancelled
}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='due_date asc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 PM Schedules API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}
@frappe.whitelist(allow_guest=True)
def get_upcoming_pm_schedules(days=30, limit=20, offset=0):
"""
Get PM Schedules due within the specified number of days
Args:
days: Number of days to look ahead (default: 30)
limit: Number of records to return (default: 20)
offset: Number of records to skip (default: 0)
Returns:
List of upcoming PM Schedules
"""
try:
from frappe.utils import today, add_days
filters = {
'due_date': ['between', [today(), add_days(today(), int(days))]],
'docstatus': ['!=', 2] # Exclude cancelled
}
# Get total count
total_count = frappe.db.count('PM Schedule Generator', filters=filters)
# Get PM schedules
pm_schedules = frappe.get_all(
'PM Schedule Generator',
filters=filters,
fields=PM_SCHEDULE_GENERATOR_FIELDS,
limit_page_length=int(limit),
limit_start=int(offset),
order_by='due_date asc'
)
# Include child tables
for pm_schedule in pm_schedules:
pm_schedule['maintenance_entries'] = get_child_table_data(
pm_schedule['name'],
'maintenance_entries',
'PM Entry Line',
PM_ENTRY_LINE_FIELDS
)
# Calculate has_more
has_more = (int(offset) + int(limit)) < total_count
frappe.response['message'] = {
'pm_schedules': pm_schedules,
'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 Upcoming PM Schedules API Error')
frappe.response['message'] = {
'error': str(e),
'pm_schedules': [],
'total_count': 0
}