using System; namespace FMDAL.DTO.ScanEvent { // Confirmed against DB/Migrations/20260719_RAM_Phase2_Schema_SqlServer.sql (TSCANEVENT). // Raw per-scan capture log, child of TSCANSESSION — insert-only, no audit-trail columns at all // (no STATUS/VERSION/CREATEDBYID/CREATEDON/MODIFIEDBYID/MODIFIEDON), which is an even leaner // shape than AssetLedgerDTO's "immutable after insert + soft-void" pattern: a scan event, once // captured, is never edited or voided — only ever superseded by a later scan event row. // EntityId is intentionally string (not int) — it may resolve to identifiers minted by other // entity types (assets, pool items, etc.) that are not guaranteed to be numeric. public class ScanEventDTO { public int ScanEventId { get; set; } public int ScanSessionId { get; set; } public int? ScanIdentifierId { get; set; } // null if tag unresolved public string RawScannedValue { get; set; } = string.Empty; public byte IdentifierType { get; set; } // (0.RFID_EPC,...,5.MANUAL) public int ScanDeviceId { get; set; } public int ScanZoneId { get; set; } public int OperatorId { get; set; } public string? EntityType { get; set; } // resolved entity type; null if unresolved public string? EntityId { get; set; } // resolved entity id AS A STRING — do not type as int public byte ScanIntent { get; set; } // (0.IDENTIFY,1.VERIFY,2.TRANSACT,3.AUDIT) public byte ScanResult { get; set; } // (0.ACCEPTED,1.REJECTED,2.DUPLICATE,3.UNRESOLVED) public string? RejectReasonCode { get; set; } // INVALID_STATE / TAG_NOT_REGISTERED / PHANTOM_READ etc. public short? Rssi { get; set; } public byte IsOffline { get; set; } = 1; // (0.YES,1.NO) public DateTime DeviceTimestamp { get; set; } public DateTime? ServerTimestamp { get; set; } public DateTime? SyncedOn { get; set; } public int OUId { get; set; } public int TenantId { get; set; } = -1; } }