From a1e3db59a3b7c3d2635d96f1ea1c667d393c932a Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 8 Jan 2026 17:07:01 +0100 Subject: [PATCH 1/2] feat: add userData 301484 to Special ZCHF 0.5% fee (#2887) - Rename fee label from 'Special ZCHF 0.5% UserData 363001' to 'Special ZCHF 0.5%' - Assign existing fee to userData 301484 via individualFees Same 0.5% ZCHF fee now applies to both userData 363001 and 301484. --- ...767888333076-AddUserData301484ToZchfFee.js | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 migration/1767888333076-AddUserData301484ToZchfFee.js diff --git a/migration/1767888333076-AddUserData301484ToZchfFee.js b/migration/1767888333076-AddUserData301484ToZchfFee.js new file mode 100644 index 0000000000..218f9b3459 --- /dev/null +++ b/migration/1767888333076-AddUserData301484ToZchfFee.js @@ -0,0 +1,56 @@ +const { MigrationInterface, QueryRunner } = require("typeorm"); + +module.exports = class AddUserData301484ToZchfFee1767888333076 { + name = 'AddUserData301484ToZchfFee1767888333076' + + async up(queryRunner) { + // 1. Rename fee label to be generic (remove UserData 363001 reference) + await queryRunner.query(` + UPDATE "dbo"."fee" + SET "label" = 'Special ZCHF 0.5%' + WHERE "label" = 'Special ZCHF 0.5% UserData 363001' + `); + + // 2. Add fee to userData 301484 + await queryRunner.query(` + UPDATE "dbo"."user_data" + SET "individualFees" = CASE + WHEN "individualFees" IS NULL OR "individualFees" = '' + THEN CAST((SELECT id FROM "dbo"."fee" WHERE "label" = 'Special ZCHF 0.5%') AS VARCHAR) + ELSE "individualFees" + ';' + CAST((SELECT id FROM "dbo"."fee" WHERE "label" = 'Special ZCHF 0.5%') AS VARCHAR) + END + WHERE "id" = 301484 + `); + } + + async down(queryRunner) { + // 1. Get the fee ID + const feeIdResult = await queryRunner.query(` + SELECT id FROM "dbo"."fee" WHERE "label" = 'Special ZCHF 0.5%' + `); + + if (feeIdResult.length > 0) { + const feeId = feeIdResult[0].id.toString(); + + // 2. Remove fee ID from userData 301484 individualFees + await queryRunner.query(` + UPDATE "dbo"."user_data" + SET "individualFees" = CASE + WHEN "individualFees" = '${feeId}' THEN NULL + WHEN "individualFees" LIKE '${feeId};%' THEN STUFF("individualFees", 1, LEN('${feeId};'), '') + WHEN "individualFees" LIKE '%;${feeId}' THEN LEFT("individualFees", LEN("individualFees") - LEN(';${feeId}')) + WHEN "individualFees" LIKE '%;${feeId};%' THEN REPLACE("individualFees", ';${feeId};', ';') + ELSE "individualFees" + END + WHERE "id" = 301484 + `); + } + + // 3. Restore original label + await queryRunner.query(` + UPDATE "dbo"."fee" + SET "label" = 'Special ZCHF 0.5% UserData 363001' + WHERE "label" = 'Special ZCHF 0.5%' + `); + } +} From f8c8f00b5fbd527520b00e9a3cce263c72f0fc6d Mon Sep 17 00:00:00 2001 From: TaprootFreak <142087526+TaprootFreak@users.noreply.github.com> Date: Thu, 8 Jan 2026 17:16:31 +0100 Subject: [PATCH 2/2] fix: remove incorrect VIDEO_IDENT_REQUIRED check for organizations (#2885) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Organization-specific VIDEO_IDENT_REQUIRED rule was blocking Organizations with OnlineId even when they had valid BankTxVerification. The existing BANK_TRANSACTION_OR_VIDEO_MISSING rule already covers all cases correctly: - Sell (not CHF) > 1000 CHF without BankTxVerification → Bank TX or Video - Card payment > 1000 CHF without BankTxVerification → Bank TX or Video - Swap > 1000 CHF without BankTxVerification → Bank TX or Video Removed: - VIDEO_IDENT_REQUIRED QuoteError enum value - Organization-specific VIDEO_IDENT_REQUIRED check - Unused KycIdentificationType import --- .../payment/dto/transaction-helper/quote-error.enum.ts | 1 - .../supporting/payment/services/transaction-helper.ts | 9 --------- 2 files changed, 10 deletions(-) diff --git a/src/subdomains/supporting/payment/dto/transaction-helper/quote-error.enum.ts b/src/subdomains/supporting/payment/dto/transaction-helper/quote-error.enum.ts index bb1ca02549..310cd236ce 100644 --- a/src/subdomains/supporting/payment/dto/transaction-helper/quote-error.enum.ts +++ b/src/subdomains/supporting/payment/dto/transaction-helper/quote-error.enum.ts @@ -9,7 +9,6 @@ export enum QuoteError { LIMIT_EXCEEDED = 'LimitExceeded', NATIONALITY_NOT_ALLOWED = 'NationalityNotAllowed', NAME_REQUIRED = 'NameRequired', - VIDEO_IDENT_REQUIRED = 'VideoIdentRequired', IBAN_CURRENCY_MISMATCH = 'IbanCurrencyMismatch', RECOMMENDATION_REQUIRED = 'RecommendationRequired', EMAIL_REQUIRED = 'EmailRequired', diff --git a/src/subdomains/supporting/payment/services/transaction-helper.ts b/src/subdomains/supporting/payment/services/transaction-helper.ts index 91cf941a44..3cb726fb17 100644 --- a/src/subdomains/supporting/payment/services/transaction-helper.ts +++ b/src/subdomains/supporting/payment/services/transaction-helper.ts @@ -25,8 +25,6 @@ import { BuyService } from 'src/subdomains/core/buy-crypto/routes/buy/buy.servic import { RefundDataDto } from 'src/subdomains/core/history/dto/refund-data.dto'; import { BuyFiat } from 'src/subdomains/core/sell-crypto/process/buy-fiat.entity'; import { BuyFiatService } from 'src/subdomains/core/sell-crypto/process/services/buy-fiat.service'; -import { AccountType } from 'src/subdomains/generic/user/models/user-data/account-type.enum'; -import { KycIdentificationType } from 'src/subdomains/generic/user/models/user-data/kyc-identification-type.enum'; import { UserData } from 'src/subdomains/generic/user/models/user-data/user-data.entity'; import { KycLevel, UserDataStatus } from 'src/subdomains/generic/user/models/user-data/user-data.enum'; import { User } from 'src/subdomains/generic/user/models/user/user.entity'; @@ -928,13 +926,6 @@ export class TransactionHelper implements OnModuleInit { ) return QuoteError.NAME_REQUIRED; - if ( - txAmountChf > Config.tradingLimits.monthlyDefaultWoKyc && - user?.userData?.accountType === AccountType.ORGANIZATION && - user?.userData?.identificationType === KycIdentificationType.ONLINE_ID - ) - return QuoteError.VIDEO_IDENT_REQUIRED; - if ( ((isSell && to.name !== 'CHF') || paymentMethodIn === FiatPaymentMethod.CARD || isSwap) && user &&