import { BaseModel } from '#database/base_model' import { DeviceRecord } from '../domain/device/device_record.js' import { DeviceId } from '../domain/device/device_id.js' import { DeviceComplianceInfo } from '../domain/configuration/compliance.js' import { Filter, Sort } from 'mongodb' export default class DeviceModel extends BaseModel { static collectionName = 'devices' static async findByIdentifier(identifier: string): Promise { return this.findOne({ identifier }) } static async findByDeviceId(deviceId: DeviceId): Promise { return this.findOne({ 'deviceId.manufacturer': deviceId.manufacturer, 'deviceId.oui': deviceId.oui, 'deviceId.productClass': deviceId.productClass, 'deviceId.serialNumber': deviceId.serialNumber, }) } static async paginateDevices( offset: number, limit: number, filter: Filter = {} ): Promise<{ data: DeviceRecord[]; total: number }> { const collection = this.getCollection() // Only return documents created by the ACS (must have an identifier field) const safeFilter: Filter = { ...filter, identifier: { $exists: true, $ne: null } } const total = await collection.countDocuments(safeFilter) const data = (await collection .find(safeFilter, { projection: { _id: 0 } }) .skip(offset) .limit(limit) .sort({ updatedAt: -1 } as Sort) .toArray()) as unknown as DeviceRecord[] return { data, total } } static async createOrUpdate(device: Partial): Promise { const collection = this.getCollection() let filter: Filter = {} if (device.deviceId) { filter = { deviceId: device.deviceId } } else if (device.identifier) { filter = { identifier: device.identifier } } else { throw new Error('Either identifier or deviceId must be provided') } const result = await collection.findOneAndUpdate( filter, { $set: { ...device, updatedAt: new Date() }, $setOnInsert: { createdAt: new Date() }, }, { upsert: true, returnDocument: 'after', projection: { _id: 0 } } ) return result as unknown as DeviceRecord } static async updateCompliance( identifier: string, compliance: DeviceComplianceInfo ): Promise { await this.updateOne({ identifier }, { compliance }) } static async updateProvisioningCode( identifier: string, provisioningCode: string ): Promise { await this.updateOne({ identifier }, { provisioningCode }) } static async resetComplianceForConfiguration(configurationIdentifier: string): Promise { const collection = this.getCollection() await collection.updateMany( { 'compliance.configurationIdentifier': configurationIdentifier }, { $set: { 'compliance.status': 'pending', 'compliance.lastError': null, updatedAt: new Date(), }, } ) } }