feat: TTLock settings redesign — correct TTHotel DLL architecture

- Settings page rebuilt with 3-step flow:
  Step 1: client_id / client_secret (from TTHotel → Settings → Integrations)
  Step 2: workstation + COM port + card sectors
  Step 3: room → lock MAC address mapping (from lock.ttlock.com)
- Agent command ttlock:write_card now uses lockMac, comPort, cardSectors
  instead of cloud-only lockId approach
- New agent command ttlock:ping_encoder for encoder connectivity check
- Migration 049_ttlock_v2.sql: lock_mac TEXT replaces lock_id BIGINT,
  card_sectors + com_port added, ttlock_username/password removed
- API types updated: TTLockConfig, RoomLockMapping, CardIssuance

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-31 16:29:30 +03:00
parent be92d026e8
commit 249492cf3a
4 changed files with 391 additions and 456 deletions

View File

@@ -610,16 +610,13 @@ export const api = {
updateConfig: (slug: string, data: TTLockConfigUpdate) =>
req<{ ok: boolean }>('PATCH', `/api/hotels/${slug}/ttlock/config`, data),
testToken: (slug: string) =>
req<{ ok: boolean; expiresAt: string }>('POST', `/api/hotels/${slug}/ttlock/token`),
getLocks: (slug: string) =>
req<TTLockDevice[]>('GET', `/api/hotels/${slug}/ttlock/locks`),
testEncoder: (slug: string) =>
req<{ ok: boolean }>('POST', `/api/hotels/${slug}/ttlock/test`),
getRoomLocks: (slug: string) =>
req<RoomLockMapping[]>('GET', `/api/hotels/${slug}/ttlock/room-locks`),
mapRoom: (slug: string, data: { roomId: string; lockId: number; lockName?: string }) =>
mapRoom: (slug: string, data: { roomId: string; lockMac: string; lockName?: string }) =>
req<{ ok: boolean }>('POST', `/api/hotels/${slug}/ttlock/room-locks`, data),
unmapRoom: (slug: string, roomId: string) =>
@@ -1082,53 +1079,50 @@ export interface Workstation {
}
export interface TTLockConfig {
isEnabled: boolean
clientId: string
ttlockUsername: string
isEnabled: boolean
clientId: string
cardSectors: string
comPort: string
workstationId: string | null
hasToken: boolean
tokenExpiresAt: string | null
}
export interface TTLockConfigUpdate {
isEnabled?: boolean
clientId?: string
clientSecret?: string
ttlockUsername?: string
ttlockPassword?: string
isEnabled?: boolean
clientId?: string
clientSecret?: string
cardSectors?: string
comPort?: string
workstationId?: string | null
}
export interface TTLockDevice {
lockId: number
name: string
}
export interface RoomLockMapping {
roomId: string
roomName: string
roomId: string
roomName: string
roomNumber: string
lockId: number
lockName: string | null
lockMac: string
lockName: string | null
}
export interface CardIssuanceResult {
ok: boolean
ok: boolean
issuanceId: string
issuedAt: string
lockName: string | null
roomName: string
checkIn: string
checkOut: string
issuedAt: string
roomName: string
roomNumber: string
lockMac: string
lockName: string | null
checkIn: string
checkOut: string
cardNumber: string | null
}
export interface CardIssuance {
id: string
lockId: number
issuedAt: string
issuedBy: string | null
checkIn: string
checkOut: string
id: string
lockMac: string
issuedAt: string
issuedBy: string | null
checkIn: string
checkOut: string
isRevoked: boolean
revokedAt: string | null
}