All files / src/domains/assets/services asset-verification.service.ts

0% Statements 0/44
0% Branches 0/30
0% Functions 0/6
0% Lines 0/37

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97                                                                                                                                                                                                 
import { Injectable, BadRequestException } from '@nestjs/common';
import { InjectModel } from '@nestjs/mongoose';
import { Model, Types } from 'mongoose';
import { Asset, AssetVerificationSession } from '../schemas';
 
@Injectable()
export class AssetVerificationService {
  constructor(
    @InjectModel(Asset.name)
    private readonly assetModel: Model<Asset>,
    @InjectModel(AssetVerificationSession.name)
    private readonly sessionModel: Model<AssetVerificationSession>
  ) {}
 
  async createSession(
    tenantId: string,
    sessionName: string,
    auditorId: string,
    targetAssetIds: string[]
  ): Promise<AssetVerificationSession> {
    const session = new this.sessionModel({
      tenantId,
      sessionName,
      auditorId,
      status: 'in_progress',
      targetAssetIds: targetAssetIds.map(id => new Types.ObjectId(id)),
      verifiedAssetIds: [],
      discrepancies: {}
    });
 
    return session.save();
  }
 
  async verifyAssetScan(
    tenantId: string,
    sessionId: string,
    assetId: string,
    scannedLocationId: string,
    condition: string,
    auditorId: string
  ): Promise<AssetVerificationSession> {
    const session = await this.sessionModel.findOne({ _id: sessionId, tenantId }).exec();
    if (!session) throw new BadRequestException('Verification session not found');
    if (session.status !== 'in_progress') throw new BadRequestException('Session is not active');
 
    const asset = await this.assetModel.findOne({ _id: assetId, tenantId }).exec();
    if (!asset) throw new BadRequestException('Asset not found');
 
    const aId = new Types.ObjectId(assetId);
    
    // Add to verified array if not present
    if (!session.verifiedAssetIds.some(id => id.toString() === assetId)) {
      session.verifiedAssetIds.push(aId);
    }
 
    // Blind audit location and condition checks
    const discrepanciesMap = session.discrepancies || new Map<string, string>();
 
    if (asset.locationId && asset.locationId.toString() !== scannedLocationId) {
      discrepanciesMap.set(assetId, `wrong_location: expected ${asset.locationId}, scanned ${scannedLocationId}`);
    }
    if (asset.condition !== condition) {
      discrepanciesMap.set(assetId, `condition_changed: expected ${asset.condition}, scanned ${condition}`);
    }
 
    session.discrepancies = discrepanciesMap;
    session.markModified('discrepancies');
    return session.save();
  }
 
  async reconcileSession(tenantId: string, sessionId: string): Promise<AssetVerificationSession> {
    const session = await this.sessionModel.findOne({ _id: sessionId, tenantId }).exec();
    if (!session) throw new BadRequestException('Verification session not found');
 
    session.status = 'completed';
    await session.save();
 
    // Reconcile and apply updates to Asset master if verified clean
    for (const assetId of session.verifiedAssetIds) {
      const discrepancy = session.discrepancies.get(assetId.toString());
      if (!discrepancy) {
        // Safe update next verification date
        await this.assetModel.updateOne({ _id: assetId }, {
          nextVerificationAt: new Date(Date.now() + 180 * 24 * 60 * 60 * 1000) // 180 days out
        });
      } else {
        // Discrepancy found - update asset condition if reported damaged
        if (discrepancy.includes('condition_changed')) {
          await this.assetModel.updateOne({ _id: assetId }, { status: 'damaged' });
        }
      }
    }
 
    return session;
  }
}