|
| 1 | +/** |
| 2 | + * @typedef {import('typeorm').MigrationInterface} MigrationInterface |
| 3 | + * @typedef {import('typeorm').QueryRunner} QueryRunner |
| 4 | + */ |
| 5 | + |
| 6 | +/** |
| 7 | + * Reset KYC level for users with DfxApproval after expiry but NO Ident renewal. |
| 8 | + * |
| 9 | + * These 13 users have: |
| 10 | + * - amlListExpiredDate set (AML expired) |
| 11 | + * - amlListReactivatedDate NULL |
| 12 | + * - DfxApproval completed AFTER expiry |
| 13 | + * - But NO Ident completed after expiry (last Ident from 2023-12-01) |
| 14 | + * |
| 15 | + * They received DfxApproval without re-verifying their identity, which is incorrect. |
| 16 | + * Their KycLevel should be reset to 20 until they complete proper re-verification. |
| 17 | + * |
| 18 | + * Affected users: 13 (as of 2026-01-31) |
| 19 | + * |
| 20 | + * @class |
| 21 | + * @implements {MigrationInterface} |
| 22 | + */ |
| 23 | +module.exports = class ResetExpiredAmlKycLevelNoIdent1769300000000 { |
| 24 | + name = 'ResetExpiredAmlKycLevelNoIdent1769300000000'; |
| 25 | + |
| 26 | + /** |
| 27 | + * @param {QueryRunner} queryRunner |
| 28 | + */ |
| 29 | + async up(queryRunner) { |
| 30 | + // First, log the affected users for verification |
| 31 | + const users = await queryRunner.query(` |
| 32 | + SELECT "id", "kycLevel" |
| 33 | + FROM "dbo"."user_data" |
| 34 | + WHERE "kycLevel" >= 30 |
| 35 | + AND "amlListExpiredDate" IS NOT NULL |
| 36 | + AND "amlListReactivatedDate" IS NULL |
| 37 | + AND EXISTS ( |
| 38 | + SELECT 1 FROM "dbo"."kyc_step" |
| 39 | + WHERE "userDataId" = "user_data"."id" |
| 40 | + AND "name" = 'DfxApproval' |
| 41 | + AND "status" = 'Completed' |
| 42 | + AND "created" > "user_data"."amlListExpiredDate" |
| 43 | + ) |
| 44 | + AND NOT EXISTS ( |
| 45 | + SELECT 1 FROM "dbo"."kyc_step" |
| 46 | + WHERE "userDataId" = "user_data"."id" |
| 47 | + AND "name" = 'Ident' |
| 48 | + AND "status" = 'Completed' |
| 49 | + AND "created" > "user_data"."amlListExpiredDate" |
| 50 | + ) |
| 51 | + `); |
| 52 | + |
| 53 | + console.log(`Found ${users.length} users with DfxApproval but no Ident after expiry:`); |
| 54 | + for (const user of users) { |
| 55 | + console.log(` - UserData ${user.id}: kycLevel ${user.kycLevel} -> 20`); |
| 56 | + } |
| 57 | + |
| 58 | + // Update KycLevel to 20 for affected users |
| 59 | + await queryRunner.query(` |
| 60 | + UPDATE "dbo"."user_data" |
| 61 | + SET "kycLevel" = 20 |
| 62 | + WHERE "kycLevel" >= 30 |
| 63 | + AND "amlListExpiredDate" IS NOT NULL |
| 64 | + AND "amlListReactivatedDate" IS NULL |
| 65 | + AND EXISTS ( |
| 66 | + SELECT 1 FROM "dbo"."kyc_step" |
| 67 | + WHERE "userDataId" = "user_data"."id" |
| 68 | + AND "name" = 'DfxApproval' |
| 69 | + AND "status" = 'Completed' |
| 70 | + AND "created" > "user_data"."amlListExpiredDate" |
| 71 | + ) |
| 72 | + AND NOT EXISTS ( |
| 73 | + SELECT 1 FROM "dbo"."kyc_step" |
| 74 | + WHERE "userDataId" = "user_data"."id" |
| 75 | + AND "name" = 'Ident' |
| 76 | + AND "status" = 'Completed' |
| 77 | + AND "created" > "user_data"."amlListExpiredDate" |
| 78 | + ) |
| 79 | + `); |
| 80 | + |
| 81 | + console.log(`Reset KycLevel to 20 for ${users.length} users`); |
| 82 | + } |
| 83 | + |
| 84 | + /** |
| 85 | + * @param {QueryRunner} queryRunner |
| 86 | + */ |
| 87 | + async down(queryRunner) { |
| 88 | + console.log('Down migration is a no-op - original KycLevel values are not preserved'); |
| 89 | + } |
| 90 | +}; |
0 commit comments