refactor: enforce enum machine codes #18
Frontend verify / verify (pull_request) Canceled after 0s
Frontend security / security (pull_request) Canceled after 0s
Frontend security / security (push) Canceled after 0s
Frontend verify / verify (push) Canceled after 0s
Conventional commits / commits (pull_request) Canceled after 0s
Frontend verify / verify (pull_request) Canceled after 0s
Frontend security / security (pull_request) Canceled after 0s
Frontend security / security (push) Canceled after 0s
Frontend verify / verify (push) Canceled after 0s
Conventional commits / commits (pull_request) Canceled after 0s
Use owner enums for known codes; preserve wire values and unknown fallbacks. Verified npm ci and verify: 379 tests, 5 lint checks, app and Storybook builds.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
|
||||
import { apiClient, apiErrorCode } from "@/shared/api";
|
||||
import { apiClient, ApiErrorCode, apiErrorCode, isApiErrorCode } from "@/shared/api";
|
||||
|
||||
import type {
|
||||
CreateBankCard,
|
||||
@@ -34,14 +34,15 @@ function useBankMutations() {
|
||||
});
|
||||
const options = {
|
||||
onError: (error: unknown) => {
|
||||
const errorCode = apiErrorCode(error);
|
||||
if (
|
||||
[
|
||||
"BANK_DEPENDENT_REFUNDS",
|
||||
"BANK_INTENT_CONFLICT",
|
||||
"BANK_REFUND_LIMIT",
|
||||
"BANK_VERSION_CONFLICT",
|
||||
"BANK_WRITE_CONFLICT",
|
||||
].includes(apiErrorCode(error) ?? "")
|
||||
ApiErrorCode.BankDependentRefunds,
|
||||
ApiErrorCode.BankIntentConflict,
|
||||
ApiErrorCode.BankRefundLimit,
|
||||
ApiErrorCode.BankVersionConflict,
|
||||
ApiErrorCode.BankWriteConflict,
|
||||
].some(code => isApiErrorCode(errorCode, code))
|
||||
)
|
||||
return invalidate();
|
||||
},
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { expect, it } from "vitest";
|
||||
|
||||
import { operationLabelKey } from "./display";
|
||||
|
||||
it.each([
|
||||
["OPERATION_TYPE_BUY", "buy"],
|
||||
["OPERATION_TYPE_BUY_CARD", "buy"],
|
||||
["OPERATION_TYPE_BUY_MARGIN", "buy"],
|
||||
["OPERATION_TYPE_SELL", "sell"],
|
||||
["OPERATION_TYPE_SELL_CARD", "sell"],
|
||||
["OPERATION_TYPE_SELL_MARGIN", "sell"],
|
||||
["OPERATION_TYPE_DIV_EXT", "dividend"],
|
||||
["OPERATION_TYPE_DIVIDEND", "dividend"],
|
||||
["OPERATION_TYPE_DIVIDEND_TRANSFER", "dividend"],
|
||||
["OPERATION_TYPE_INPUT_SECURITIES", "input"],
|
||||
["OPERATION_TYPE_OUTPUT_SECURITIES", "output"],
|
||||
["OPERATION_TYPE_FUTURE_TAX", "tax"],
|
||||
["OPERATION_TYPE_FUTURE_FEE", "fee"],
|
||||
["OPERATION_TYPE_TRANS_FUTURE", "transfer"],
|
||||
["FUTURE_UNKNOWN_OPERATION", "other"],
|
||||
])("preserves the wire operation label for %s", (type, label) => {
|
||||
expect(operationLabelKey(type)).toBe(`ledger.operationType.${label}`);
|
||||
});
|
||||
@@ -2,6 +2,23 @@ import { formatMoney } from "@/shared/lib";
|
||||
|
||||
import type { BrokerageOperation } from "../api/useBrokerageOperations";
|
||||
|
||||
enum OperationType {
|
||||
Buy = "OPERATION_TYPE_BUY",
|
||||
BuyCard = "OPERATION_TYPE_BUY_CARD",
|
||||
BuyMargin = "OPERATION_TYPE_BUY_MARGIN",
|
||||
Coupon = "OPERATION_TYPE_COUPON",
|
||||
DivExtension = "OPERATION_TYPE_DIV_EXT",
|
||||
Dividend = "OPERATION_TYPE_DIVIDEND",
|
||||
DividendTransfer = "OPERATION_TYPE_DIVIDEND_TRANSFER",
|
||||
InputSecurities = "OPERATION_TYPE_INPUT_SECURITIES",
|
||||
OutputSecurities = "OPERATION_TYPE_OUTPUT_SECURITIES",
|
||||
Sell = "OPERATION_TYPE_SELL",
|
||||
SellCard = "OPERATION_TYPE_SELL_CARD",
|
||||
SellMargin = "OPERATION_TYPE_SELL_MARGIN",
|
||||
}
|
||||
|
||||
const operationTransferPrefix = "OPERATION_TYPE_TRANS_";
|
||||
|
||||
type PaymentPresentation = {
|
||||
amount: string;
|
||||
label: string;
|
||||
@@ -10,12 +27,16 @@ type PaymentPresentation = {
|
||||
|
||||
function entryLabelKey(operation: BrokerageOperation): string {
|
||||
if (operation.category === "income")
|
||||
return operation.type === "OPERATION_TYPE_COUPON"
|
||||
return isOperationType(operation.type, OperationType.Coupon)
|
||||
? "ledger.entryLabel.income.coupon"
|
||||
: "ledger.entryLabel.income.dividend";
|
||||
return `ledger.category.${operation.category}`;
|
||||
}
|
||||
|
||||
function isOperationType(value: unknown, expected: OperationType): boolean {
|
||||
return value === expected;
|
||||
}
|
||||
|
||||
function isZeroDecimal(value: string): boolean {
|
||||
return /^-?0$|^-?0\.0+$/.test(value);
|
||||
}
|
||||
@@ -23,35 +44,35 @@ function isZeroDecimal(value: string): boolean {
|
||||
function operationLabelKey(type: string): string {
|
||||
if (
|
||||
[
|
||||
"OPERATION_TYPE_BUY",
|
||||
"OPERATION_TYPE_BUY_CARD",
|
||||
"OPERATION_TYPE_BUY_MARGIN",
|
||||
].includes(type)
|
||||
OperationType.Buy,
|
||||
OperationType.BuyCard,
|
||||
OperationType.BuyMargin,
|
||||
].some(candidate => isOperationType(type, candidate))
|
||||
)
|
||||
return "ledger.operationType.buy";
|
||||
if (
|
||||
[
|
||||
"OPERATION_TYPE_SELL",
|
||||
"OPERATION_TYPE_SELL_CARD",
|
||||
"OPERATION_TYPE_SELL_MARGIN",
|
||||
].includes(type)
|
||||
OperationType.Sell,
|
||||
OperationType.SellCard,
|
||||
OperationType.SellMargin,
|
||||
].some(candidate => isOperationType(type, candidate))
|
||||
)
|
||||
return "ledger.operationType.sell";
|
||||
if (
|
||||
[
|
||||
"OPERATION_TYPE_DIV_EXT",
|
||||
"OPERATION_TYPE_DIVIDEND",
|
||||
"OPERATION_TYPE_DIVIDEND_TRANSFER",
|
||||
].includes(type)
|
||||
OperationType.DivExtension,
|
||||
OperationType.Dividend,
|
||||
OperationType.DividendTransfer,
|
||||
].some(candidate => isOperationType(type, candidate))
|
||||
)
|
||||
return "ledger.operationType.dividend";
|
||||
if (type.includes("TAX")) return "ledger.operationType.tax";
|
||||
if (type.includes("FEE")) return "ledger.operationType.fee";
|
||||
if (type === "OPERATION_TYPE_INPUT_SECURITIES")
|
||||
if (isOperationType(type, OperationType.InputSecurities))
|
||||
return "ledger.operationType.input";
|
||||
if (type === "OPERATION_TYPE_OUTPUT_SECURITIES")
|
||||
if (isOperationType(type, OperationType.OutputSecurities))
|
||||
return "ledger.operationType.output";
|
||||
return type.startsWith("OPERATION_TYPE_TRANS_") ? "ledger.operationType.transfer" : "ledger.operationType.other";
|
||||
return type.startsWith(operationTransferPrefix) ? "ledger.operationType.transfer" : "ledger.operationType.other";
|
||||
}
|
||||
|
||||
function paymentPresentation(
|
||||
|
||||
Reference in New Issue
Block a user