Files
frontend/src/entities/broker-operation/model/display.ts
T
codex-bot 43b0f5574a
Frontend verify / commits (push) Skipped
Frontend verify / security (push) Successful in 10s
Frontend verify / verify (push) Successful in 7m18s
feat: unify income payment cards and remove comparisons (WealthLedger/main#33) (#74)
feat: unify income payment cards and remove comparisons (WealthLedger/main#33)
2026-10-13 18:17:35 +03:00

119 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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;
tone: "negative"
| "neutral"
| "positive";
};
function entryLabelKey(operation: BrokerageOperation): string {
if (operation.category === "income")
return isOperationType(operation.type, OperationType.Coupon)
? "ledger.entryLabel.income.coupon"
: "ledger.entryLabel.income.dividend";
return `ledger.category.${operation.category}`;
}
function isIncomePayment(operation: BrokerageOperation): boolean {
return [OperationType.Coupon, OperationType.Dividend].some(type =>
isOperationType(operation.type, type),
);
}
function isOperationType(value: unknown, expected: OperationType): boolean {
return value === expected;
}
function isZeroDecimal(value: string): boolean {
return /^-?0$|^-?0\.0+$/.test(value);
}
function operationLabelKey(type: string): string {
if (
[OperationType.Buy, OperationType.BuyCard, OperationType.BuyMargin].some(
candidate => isOperationType(type, candidate),
)
)
return "ledger.operationType.buy";
if (
[OperationType.Sell, OperationType.SellCard, OperationType.SellMargin].some(
candidate => isOperationType(type, candidate),
)
)
return "ledger.operationType.sell";
if (
[
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 (isOperationType(type, OperationType.InputSecurities))
return "ledger.operationType.input";
if (isOperationType(type, OperationType.OutputSecurities))
return "ledger.operationType.output";
return type.startsWith(operationTransferPrefix)
? "ledger.operationType.transfer"
: "ledger.operationType.other";
}
function paymentPresentation(
operation: BrokerageOperation,
): PaymentPresentation {
if (!operation.payment)
return {
amount: "—",
label: "ledger.noMoney",
tone: "neutral",
};
if (isZeroDecimal(operation.payment.value))
return {
amount: formatMoney(operation.payment),
label: "ledger.noMoney",
tone: "neutral",
};
if (operation.payment.value.startsWith("-"))
return {
amount: `−${formatMoney({
...operation.payment,
value: operation.payment.value.slice(1),
})}`,
label: entryLabelKey(operation),
tone: "negative",
};
return {
amount: `+${formatMoney(operation.payment)}`,
label: entryLabelKey(operation),
tone: "positive",
};
}
export { isIncomePayment, operationLabelKey, paymentPresentation };