439 lines
12 KiB
Python
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)
|
|
}
|
|
|