Seera/frappe_asset_api.py
2025-11-03 13:38:27 +05:30

439 lines
12 KiB
Python

# 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)
}