From 82e4a0cbf0f860f275d82315077dc1266787c7fd Mon Sep 17 00:00:00 2001 From: shancheas Date: Tue, 1 Sep 2026 23:48:12 +0700 Subject: [PATCH] Enhance check-in verification to ensure integer distance values - Added a new function, `roundedDistanceMeters`, to round the calculated distance for NFC and GPS methods. - Updated the `verifyTargetCheckIn` function to use the new rounding logic, ensuring distance values are integers. - Added unit tests to verify that distance values returned for NFC check-ins are whole numbers, improving data consistency. --- .../field/shared/check-in-verification.spec.ts | 17 +++++++++++++++++ .../field/shared/check-in-verification.ts | 13 +++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/modules/field/shared/check-in-verification.spec.ts b/src/modules/field/shared/check-in-verification.spec.ts index ddf1b32..dcf855a 100644 --- a/src/modules/field/shared/check-in-verification.spec.ts +++ b/src/modules/field/shared/check-in-verification.spec.ts @@ -74,6 +74,23 @@ describe('check-in-verification', () => { expect(result.method).toBe('gps'); expect(result.distanceMeters).toBeGreaterThan(100); + expect(Number.isInteger(result.distanceMeters)).toBe(true); + }); + + it('returns whole meters for NFC distance so it matches the integer column', () => { + const result = verifyBranchCheckIn( + target, + { + method: 'nfc', + nfcId: 'nfc-123', + latitude: -6.2005, + longitude: 106.8005, + }, + 100, + ); + + expect(result.distanceMeters).not.toBeNull(); + expect(Number.isInteger(result.distanceMeters)).toBe(true); }); it('accepts GPS when the target has no location if skipGpsValidation is set', () => { diff --git a/src/modules/field/shared/check-in-verification.ts b/src/modules/field/shared/check-in-verification.ts index 4efc272..90f7800 100644 --- a/src/modules/field/shared/check-in-verification.ts +++ b/src/modules/field/shared/check-in-verification.ts @@ -1,6 +1,15 @@ import { BadRequestException } from '@nestjs/common'; import { haversineDistanceMeters } from './geo-distance'; +function roundedDistanceMeters( + lat1: number, + lon1: number, + lat2: number, + lon2: number, +): number { + return Math.round(haversineDistanceMeters(lat1, lon1, lat2, lon2)); +} + export const CHECK_IN_METHODS = ['nfc', 'qr', 'gps'] as const; export type CheckInMethod = (typeof CHECK_IN_METHODS)[number]; @@ -117,7 +126,7 @@ function verifyTargetCheckIn( throw new BadRequestException(locationMissingMessage); } if (canMeasure) { - distanceMeters = haversineDistanceMeters( + distanceMeters = roundedDistanceMeters( payload.latitude, payload.longitude, targetLatitude, @@ -135,7 +144,7 @@ function verifyTargetCheckIn( distanceMeters: distanceMeters == null ? target.latitude != null && target.longitude != null - ? haversineDistanceMeters( + ? roundedDistanceMeters( payload.latitude, payload.longitude, target.latitude,