refactor: replace ignored numeric literals with constants
Backend security / security (push) Successful in 8s
Backend verify / verify (push) Failing after 2m17s
Conventional commits / commits (pull_request) Successful in 31s
Backend security / security (pull_request) Successful in 8s
Backend verify / verify (pull_request) Failing after 1m56s

This commit is contained in:
2026-09-28 11:24:59 +03:00
parent 9b3558f96c
commit 9cc9fbdcff
60 changed files with 510 additions and 283 deletions
@@ -5,6 +5,7 @@ import {
} from '@nestjs/common';
import { createHash } from 'node:crypto';
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../common/time';
import {
MAX_CARD_NAME_LENGTH,
MAX_OPERATION_DESCRIPTION_LENGTH,
@@ -18,6 +19,9 @@ import {
CreateBankOperationDto,
} from '../presentation/bank-card.dto';
const NEXT_MONTH_OFFSET = 1;
const PREVIOUS_MONTH_LAST_DAY = 0;
export const BankErrorCode = {
InvalidInput: 'BANK_INVALID_INPUT',
VersionConflict: 'BANK_VERSION_CONFLICT',
@@ -45,8 +49,8 @@ export function periodBounds(query: BankPeriodQueryDto) {
const from = `${query.month}-01`;
if (!isCalendarDate(from)) return fail();
const end = new Date(`${from}T00:00:00Z`);
end.setUTCMonth(end.getUTCMonth() + 1, 0);
return { from, to: end.toISOString().slice(0, 10) };
end.setUTCMonth(end.getUTCMonth() + NEXT_MONTH_OFFSET, PREVIOUS_MONTH_LAST_DAY);
return { from, to: end.toISOString().slice(ISO_DATE_START, ISO_DATE_LENGTH) };
}
if (
query.month ||
@@ -19,6 +19,9 @@ import {
fingerprint,
missing,
} from './bank-card-input';
const EXPECTED_UPDATED_CARDS = 1;
type Tx = Prisma.TransactionClient;
@Injectable()
export class BankCardsService {
@@ -149,7 +152,7 @@ export class BankCardsService {
}),
},
});
if (changed.count !== 1) conflict();
if (changed.count !== EXPECTED_UPDATED_CARDS) conflict();
return this.cardView(tx, await this.repository.card(tx, userId, id));
});
}
@@ -5,8 +5,9 @@ import {
Prisma,
} from '../../../../../generated/prisma/client';
import { PrismaService } from '../../../../prisma/prisma.service';
import { FIRST_PAGE } from '../domain/bank-card-limits';
import { BankOperationKind } from '../domain/bank-operation-kind';
import { rubMoney } from '../domain/rub-money';
import { rubMoney, ZERO_KOPECKS } from '../domain/rub-money';
import { BankCardsRepository } from '../infrastructure/bank-cards.repository';
import {
BankOperationDto,
@@ -26,6 +27,9 @@ import {
operationInput,
periodBounds,
} from './bank-card-input';
const EXPECTED_UPDATED_ROWS = 1;
type Tx = Prisma.TransactionClient;
@Injectable()
export class BankOperationsService {
@@ -77,7 +81,7 @@ export class BankOperationsService {
row.kind === BankOperationKind.Expense || source ?
rubMoney(
(source?.amountKopecks ?? row.amountKopecks) -
refunds.reduce((sum, r) => sum + r.amountKopecks, 0n),
refunds.reduce((sum, r) => sum + r.amountKopecks, ZERO_KOPECKS),
) :
null,
date: row.date,
@@ -170,7 +174,7 @@ export class BankOperationsService {
},
data: { version: { increment: 1 } },
})
).count !== 1
).count !== EXPECTED_UPDATED_ROWS
) {
conflict();
}
@@ -184,7 +188,7 @@ export class BankOperationsService {
});
if (input.date < source.date) fail(BankErrorCode.InvalidDate);
if (
refunds.reduce((sum, r) => sum + r.amountKopecks, 0n) +
refunds.reduce((sum, r) => sum + r.amountKopecks, ZERO_KOPECKS) +
input.amountKopecks >
source.amountKopecks
) {
@@ -199,7 +203,7 @@ export class BankOperationsService {
refunds.length &&
(input.cardId !== old.cardId ||
refunds.some((row) => row.date < input.date) ||
refunds.reduce((sum, row) => sum + row.amountKopecks, 0n) >
refunds.reduce((sum, row) => sum + row.amountKopecks, ZERO_KOPECKS) >
input.amountKopecks)
) {
conflict(BankErrorCode.DependentRefunds);
@@ -268,7 +272,7 @@ export class BankOperationsService {
where: { id, userId, version: dto.version, deletedAt: null },
data: { ...input, version: { increment: 1 } },
})
).count !== 1
).count !== EXPECTED_UPDATED_ROWS
) {
conflict();
}
@@ -308,7 +312,7 @@ export class BankOperationsService {
where: { id: source.id, userId, version: source.version },
data: { version: { increment: 1 } },
})
).count !== 1
).count !== EXPECTED_UPDATED_ROWS
) {
conflict();
}
@@ -319,7 +323,7 @@ export class BankOperationsService {
where: { id, userId, version, deletedAt: null },
data: { deletedAt: new Date(), version: { increment: 1 } },
})
).count !== 1
).count !== EXPECTED_UPDATED_ROWS
) {
conflict();
}
@@ -338,7 +342,7 @@ export class BankOperationsService {
return this.prisma.$transaction(async (tx) => {
await this.repository.card(tx, userId, id);
const limit = query.limit ?? DEFAULT_BANK_PAGE_SIZE,
page = query.page ?? 1;
page = query.page ?? FIRST_PAGE;
const where: Prisma.BankCardOperationWhereInput = {
userId,
deletedAt: null,
@@ -351,7 +355,7 @@ export class BankOperationsService {
const rows = await tx.bankCardOperation.findMany({
where,
orderBy: [{ date: 'desc' }, { createdAt: 'desc' }, { id: 'desc' }],
skip: (page - 1) * limit,
skip: (page - FIRST_PAGE) * limit,
take: limit,
});
return {
@@ -5,6 +5,10 @@ import { PrismaService } from '../../../../prisma/prisma.service';
import { MAX_CATEGORY_NAME_LENGTH } from '../domain/bank-card-limits';
import { BankCardsRepository } from '../infrastructure/bank-cards.repository';
import { conflict, missing, name } from './bank-card-input';
const EXPECTED_UPDATED_CATEGORIES = 1;
const VERSION_INCREMENT = 1;
@Injectable()
export class ExpenseCategoriesService {
constructor(
@@ -62,7 +66,7 @@ export class ExpenseCategoriesService {
version: { increment: 1 },
},
})
).count !== 1
).count !== EXPECTED_UPDATED_CATEGORIES
) {
conflict();
}
@@ -70,7 +74,7 @@ export class ExpenseCategoriesService {
id,
name: label,
isDefault: row.seedKey === 'other',
version: version + 1,
version: version + VERSION_INCREMENT,
};
});
}