# Asset API Endpoints for Frappe # File location: frappe-bench/apps/asset_lite/asset_lite/api/asset_api.py import frappe from frappe import _ @frappe.whitelist() def get_assets(filters=None, fields=None, limit=20, offset=0, order_by=None): """ Get list of assets with filters and pagination Args: filters: JSON string of filters (e.g., '{"company": "ABC Corp"}') fields: JSON string of fields to return (e.g., '["asset_name", "location"]') limit: Number of records to return (default: 20) offset: Number of records to skip (default: 0) order_by: Sort order (e.g., "creation desc") Returns: { "assets": [...], "total_count": int, "limit": int, "offset": int, "has_more": bool } """ try: # Parse filters if provided if filters and isinstance(filters, str): import json filters = json.loads(filters) # Parse fields if provided if fields and isinstance(fields, str): import json fields = json.loads(fields) else: # Default fields to return fields = [ 'name', 'asset_name', 'company', 'custom_serial_number', 'location', 'custom_manufacturer', 'department', 'custom_asset_type', 'custom_manufacturing_year', 'custom_model', 'custom_class', 'custom_device_status', 'custom_down_time', 'asset_owner_company', 'custom_up_time', 'custom_modality', 'custom_attach_image', 'custom_site_contractor', 'custom_total_amount', 'creation', 'modified', 'owner', 'modified_by' ] # Get total count total_count = frappe.db.count('Asset', filters=filters or {}) # Get assets assets = frappe.get_all( 'Asset', filters=filters or {}, fields=fields, limit_page_length=int(limit), limit_start=int(offset), order_by=order_by or 'creation desc' ) # Calculate has_more has_more = (int(offset) + int(limit)) < total_count frappe.response['message'] = { 'assets': assets, '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 Assets API Error') frappe.response['message'] = { 'error': str(e), 'assets': [], 'total_count': 0 } @frappe.whitelist() def get_asset_details(asset_name): """ Get detailed information about a specific asset Args: asset_name: Name/ID of the asset Returns: Asset document with all fields """ try: if not asset_name: frappe.throw(_('Asset name is required')) # Check if user has permission to read this asset if not frappe.has_permission('Asset', 'read', asset_name): frappe.throw(_('Not permitted to access this asset')) # Get asset details asset = frappe.get_doc('Asset', asset_name) frappe.response['message'] = asset.as_dict() except Exception as e: frappe.log_error(frappe.get_traceback(), 'Get Asset Details API Error') frappe.response['message'] = { 'error': str(e) } @frappe.whitelist() def create_asset(asset_data): """ Create a new asset Args: asset_data: JSON string containing asset fields Returns: Created asset document """ try: import json # Parse asset data if isinstance(asset_data, str): asset_data = json.loads(asset_data) # Check if user has permission to create asset if not frappe.has_permission('Asset', 'create'): frappe.throw(_('Not permitted to create asset')) # Create new asset asset = frappe.get_doc({ 'doctype': 'Asset', **asset_data }) asset.insert() frappe.db.commit() frappe.response['message'] = { 'success': True, 'asset': asset.as_dict(), 'message': _('Asset created successfully') } except Exception as e: frappe.db.rollback() frappe.log_error(frappe.get_traceback(), 'Create Asset API Error') frappe.response['message'] = { 'success': False, 'error': str(e) } @frappe.whitelist() def update_asset(asset_name, asset_data): """ Update an existing asset Args: asset_name: Name/ID of the asset asset_data: JSON string containing fields to update Returns: Updated asset document """ try: import json if not asset_name: frappe.throw(_('Asset name is required')) # Parse asset data if isinstance(asset_data, str): asset_data = json.loads(asset_data) # Check if user has permission to update this asset if not frappe.has_permission('Asset', 'write', asset_name): frappe.throw(_('Not permitted to update this asset')) # Get and update asset asset = frappe.get_doc('Asset', asset_name) # Update fields for key, value in asset_data.items(): if hasattr(asset, key): setattr(asset, key, value) asset.save() frappe.db.commit() frappe.response['message'] = { 'success': True, 'asset': asset.as_dict(), 'message': _('Asset updated successfully') } except Exception as e: frappe.db.rollback() frappe.log_error(frappe.get_traceback(), 'Update Asset API Error') frappe.response['message'] = { 'success': False, 'error': str(e) } @frappe.whitelist() def delete_asset(asset_name): """ Delete an asset Args: asset_name: Name/ID of the asset Returns: Success message """ try: if not asset_name: frappe.throw(_('Asset name is required')) # Check if user has permission to delete this asset if not frappe.has_permission('Asset', 'delete', asset_name): frappe.throw(_('Not permitted to delete this asset')) # Delete asset frappe.delete_doc('Asset', asset_name) frappe.db.commit() frappe.response['message'] = { 'success': True, 'message': _('Asset deleted successfully') } except Exception as e: frappe.db.rollback() frappe.log_error(frappe.get_traceback(), 'Delete Asset API Error') frappe.response['message'] = { 'success': False, 'error': str(e) } @frappe.whitelist() def get_asset_filters(): """ Get available filter options for assets Returns: { "companies": [...], "locations": [...], "departments": [...], "asset_types": [...], "manufacturers": [...], "device_statuses": [...] } """ try: filters = { 'companies': frappe.get_all('Company', fields=['name'], pluck='name'), 'locations': frappe.db.get_all('Asset', filters={'location': ['!=', '']}, fields=['location'], distinct=True, pluck='location' ), 'departments': frappe.get_all('Department', fields=['name'], pluck='name'), 'asset_types': frappe.db.get_all('Asset', filters={'custom_asset_type': ['!=', '']}, fields=['custom_asset_type'], distinct=True, pluck='custom_asset_type' ), 'manufacturers': frappe.db.get_all('Asset', filters={'custom_manufacturer': ['!=', '']}, fields=['custom_manufacturer'], distinct=True, pluck='custom_manufacturer' ), 'device_statuses': frappe.db.get_all('Asset', filters={'custom_device_status': ['!=', '']}, fields=['custom_device_status'], distinct=True, pluck='custom_device_status' ), } frappe.response['message'] = filters except Exception as e: frappe.log_error(frappe.get_traceback(), 'Get Asset Filters API Error') frappe.response['message'] = { 'error': str(e) } @frappe.whitelist() def get_asset_stats(): """ Get statistics about assets Returns: { "total_assets": int, "by_status": {...}, "by_company": {...}, "by_type": {...}, "total_amount": float } """ try: # Total assets total_assets = frappe.db.count('Asset') # Assets by device status by_status = {} status_data = frappe.db.sql(""" SELECT custom_device_status, COUNT(*) as count FROM `tabAsset` WHERE custom_device_status IS NOT NULL AND custom_device_status != '' GROUP BY custom_device_status """, as_dict=True) for row in status_data: by_status[row.custom_device_status] = row.count # Assets by company by_company = {} company_data = frappe.db.sql(""" SELECT company, COUNT(*) as count FROM `tabAsset` WHERE company IS NOT NULL AND company != '' GROUP BY company """, as_dict=True) for row in company_data: by_company[row.company] = row.count # Assets by type by_type = {} type_data = frappe.db.sql(""" SELECT custom_asset_type, COUNT(*) as count FROM `tabAsset` WHERE custom_asset_type IS NOT NULL AND custom_asset_type != '' GROUP BY custom_asset_type """, as_dict=True) for row in type_data: by_type[row.custom_asset_type] = row.count # Total amount total_amount = frappe.db.sql(""" SELECT SUM(custom_total_amount) as total FROM `tabAsset` WHERE custom_total_amount IS NOT NULL """)[0][0] or 0 frappe.response['message'] = { 'total_assets': total_assets, 'by_status': by_status, 'by_company': by_company, 'by_type': by_type, 'total_amount': float(total_amount) } except Exception as e: frappe.log_error(frappe.get_traceback(), 'Get Asset Stats API Error') frappe.response['message'] = { 'error': str(e) } @frappe.whitelist() def search_assets(search_term, limit=10): """ Search assets by name, serial number, or other fields Args: search_term: Search query string limit: Maximum number of results (default: 10) Returns: List of matching assets """ try: if not search_term: frappe.response['message'] = [] return search_term = f"%{search_term}%" assets = frappe.db.sql(""" SELECT name, asset_name, custom_serial_number, location, company, custom_device_status FROM `tabAsset` WHERE asset_name LIKE %(search)s OR custom_serial_number LIKE %(search)s OR location LIKE %(search)s OR custom_manufacturer LIKE %(search)s LIMIT %(limit)s """, { 'search': search_term, 'limit': int(limit) }, as_dict=True) frappe.response['message'] = assets except Exception as e: frappe.log_error(frappe.get_traceback(), 'Search Assets API Error') frappe.response['message'] = { 'error': str(e) }