Migrate frontend to plugin-based asset architecture
- Add equipmentApi and computersApi to replace legacy machinesApi - Add controller vendor/model fields to Equipment model and forms - Fix map marker navigation to use plugin-specific IDs (equipmentid, computerid, printerid, networkdeviceid) instead of assetid - Fix search to use unified Asset table with correct plugin IDs - Remove legacy printer search that used non-existent field names - Enable optional JWT auth for detail endpoints (public read access) - Clean up USB plugin models (remove unused checkout model) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -156,12 +156,52 @@ class Asset(BaseModel, SoftDeleteMixin, AuditMixin):
|
||||
comm = self.communications.filter_by(comtypeid=1).first()
|
||||
return comm.ipaddress if comm else None
|
||||
|
||||
def to_dict(self, include_type_data=False):
|
||||
def get_inherited_location(self):
|
||||
"""
|
||||
Get location data from a related asset if this asset has none.
|
||||
|
||||
Returns dict with locationid, location_name, mapleft, maptop, and
|
||||
inherited_from (assetnumber of source asset) if location was inherited.
|
||||
Returns None if no location data available.
|
||||
"""
|
||||
# If we have our own location data, don't inherit
|
||||
if self.locationid is not None or (self.mapleft is not None and self.maptop is not None):
|
||||
return None
|
||||
|
||||
# Check related assets for location data
|
||||
# Look in both incoming and outgoing relationships
|
||||
related_assets = []
|
||||
|
||||
if hasattr(self, 'incoming_relationships'):
|
||||
for rel in self.incoming_relationships:
|
||||
if rel.source_asset and rel.isactive:
|
||||
related_assets.append(rel.source_asset)
|
||||
|
||||
if hasattr(self, 'outgoing_relationships'):
|
||||
for rel in self.outgoing_relationships:
|
||||
if rel.target_asset and rel.isactive:
|
||||
related_assets.append(rel.target_asset)
|
||||
|
||||
# Find first related asset with location data
|
||||
for related in related_assets:
|
||||
if related.locationid is not None or (related.mapleft is not None and related.maptop is not None):
|
||||
return {
|
||||
'locationid': related.locationid,
|
||||
'location_name': related.location.locationname if related.location else None,
|
||||
'mapleft': related.mapleft,
|
||||
'maptop': related.maptop,
|
||||
'inherited_from': related.assetnumber
|
||||
}
|
||||
|
||||
return None
|
||||
|
||||
def to_dict(self, include_type_data=False, include_inherited_location=True):
|
||||
"""
|
||||
Convert model to dictionary.
|
||||
|
||||
Args:
|
||||
include_type_data: If True, include category-specific data from extension table
|
||||
include_inherited_location: If True, include location from related assets when missing
|
||||
"""
|
||||
result = super().to_dict()
|
||||
|
||||
@@ -175,6 +215,30 @@ class Asset(BaseModel, SoftDeleteMixin, AuditMixin):
|
||||
if self.businessunit:
|
||||
result['businessunit_name'] = self.businessunit.businessunit
|
||||
|
||||
# Add plugin-specific ID for navigation purposes
|
||||
if hasattr(self, 'equipment') and self.equipment:
|
||||
result['plugin_id'] = self.equipment.equipmentid
|
||||
elif hasattr(self, 'computer') and self.computer:
|
||||
result['plugin_id'] = self.computer.computerid
|
||||
elif hasattr(self, 'network_device') and self.network_device:
|
||||
result['plugin_id'] = self.network_device.networkdeviceid
|
||||
elif hasattr(self, 'printer') and self.printer:
|
||||
result['plugin_id'] = self.printer.printerid
|
||||
|
||||
# Include inherited location if this asset has no location data
|
||||
if include_inherited_location:
|
||||
inherited = self.get_inherited_location()
|
||||
if inherited:
|
||||
result['inherited_location'] = inherited
|
||||
# Also set the location fields if they're missing
|
||||
if result.get('locationid') is None:
|
||||
result['locationid'] = inherited['locationid']
|
||||
result['location_name'] = inherited['location_name']
|
||||
if result.get('mapleft') is None:
|
||||
result['mapleft'] = inherited['mapleft']
|
||||
if result.get('maptop') is None:
|
||||
result['maptop'] = inherited['maptop']
|
||||
|
||||
# Include extension data if requested
|
||||
if include_type_data:
|
||||
ext_data = self._get_extension_data()
|
||||
|
||||
Reference in New Issue
Block a user