feat(i18n): 管理端与玩家端三语支持(中/英/马来语)
- 管理后台 adminT 文案库、结算与代理端页面、表单校验 - 玩家端 vue-i18n 补全首页/公告/串关与 ms 文案 - Element Plus ms 语言包与共享 locale 工具
This commit is contained in:
@@ -4,8 +4,13 @@ import { PrismaService } from '../../shared/prisma/prisma.service';
|
||||
import { WalletService } from '../ledger/wallet.service';
|
||||
import { Decimal } from '@prisma/client/runtime/library';
|
||||
import { generateBetNo } from '../../shared/common/decorators';
|
||||
import { isQuarterHandicapOrTotal } from '../settlement/domain/settlement-calculator';
|
||||
import { PARLAY_MIN_LEGS, PARLAY_MAX_LEGS } from '@thebet365/shared';
|
||||
import {
|
||||
PARLAY_MIN_LEGS,
|
||||
PARLAY_MAX_LEGS,
|
||||
canSelectForParlay,
|
||||
isPreMatchKickoff,
|
||||
isSupportedSport,
|
||||
} from '@thebet365/shared';
|
||||
|
||||
interface BetSelectionInput {
|
||||
selectionId: bigint;
|
||||
@@ -20,7 +25,11 @@ export class BetsService {
|
||||
private wallet: WalletService,
|
||||
) {}
|
||||
|
||||
private async validateSelection(selectionId: bigint, oddsVersion: bigint) {
|
||||
private async validateSelection(
|
||||
selectionId: bigint,
|
||||
oddsVersion: bigint,
|
||||
options?: { forParlay?: boolean },
|
||||
) {
|
||||
const selection = await this.prisma.marketSelection.findUnique({
|
||||
where: { id: selectionId },
|
||||
include: { market: { include: { match: true } } },
|
||||
@@ -32,10 +41,35 @@ export class BetsService {
|
||||
if (selection.market.match.status !== 'PUBLISHED') {
|
||||
throw new BadRequestException('Match not available for betting');
|
||||
}
|
||||
if (!isSupportedSport(selection.market.match.sportType)) {
|
||||
throw new BadRequestException('Only football betting is supported');
|
||||
}
|
||||
if (!selection.market.match.isOutright && !isPreMatchKickoff(selection.market.match.startTime)) {
|
||||
throw new BadRequestException('Pre-match betting only; match has started');
|
||||
}
|
||||
if (selection.oddsVersion !== oddsVersion) {
|
||||
throw new BadRequestException('Odds changed, please confirm again');
|
||||
}
|
||||
|
||||
if (options?.forParlay) {
|
||||
const line = selection.market.lineValue ? Number(selection.market.lineValue) : null;
|
||||
const check = canSelectForParlay({
|
||||
marketType: selection.market.marketType,
|
||||
lineValue: line,
|
||||
allowParlay: selection.market.allowParlay,
|
||||
isOutright: selection.market.match.isOutright,
|
||||
});
|
||||
if (!check.ok) {
|
||||
const msg =
|
||||
check.reason === 'OUTRIGHT'
|
||||
? 'Outright cannot be in parlay'
|
||||
: check.reason === 'QUARTER_LINE'
|
||||
? 'Quarter line markets cannot be in parlay'
|
||||
: 'Market not allowed in parlay';
|
||||
throw new BadRequestException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
return selection;
|
||||
}
|
||||
|
||||
@@ -54,7 +88,7 @@ export class BetsService {
|
||||
});
|
||||
if (existing) return existing;
|
||||
|
||||
const selection = await this.validateSelection(selectionId, oddsVersion);
|
||||
const selection = await this.validateSelection(selectionId, oddsVersion, { forParlay: false });
|
||||
const odds = new Decimal(selection.odds.toString());
|
||||
const stakeDec = new Decimal(stake);
|
||||
const potentialReturn = stakeDec.mul(odds);
|
||||
@@ -117,21 +151,7 @@ export class BetsService {
|
||||
const matchIds = new Set<string>();
|
||||
|
||||
for (const leg of legs) {
|
||||
const sel = await this.validateSelection(leg.selectionId, leg.oddsVersion);
|
||||
|
||||
if (sel.market.marketType === 'OUTRIGHT_WINNER') {
|
||||
throw new BadRequestException('Outright cannot be in parlay');
|
||||
}
|
||||
|
||||
const line = sel.market.lineValue ? Number(sel.market.lineValue) : null;
|
||||
if (
|
||||
['FT_HANDICAP', 'HT_HANDICAP', 'FT_OVER_UNDER', 'HT_OVER_UNDER'].includes(
|
||||
sel.market.marketType,
|
||||
) &&
|
||||
isQuarterHandicapOrTotal(line)
|
||||
) {
|
||||
throw new BadRequestException('Quarter line markets cannot be in parlay');
|
||||
}
|
||||
const sel = await this.validateSelection(leg.selectionId, leg.oddsVersion, { forParlay: true });
|
||||
|
||||
const matchKey = sel.market.matchId.toString();
|
||||
if (matchIds.has(matchKey)) {
|
||||
|
||||
Reference in New Issue
Block a user