feat(catalog): 玩家端隐藏已结算赛事与冠军盘联赛

- listPublished/listUpcomingPublished 排除 SETTLED 及冠军盘已结算联赛

- outright.listForPlayer 仅返回 PUBLISHED

- 首页 todayMatches 过滤 SETTLED;管理端已结算冠军盘隐藏下架按钮

- 补充 matches/outright 单测
This commit is contained in:
2026-06-23 15:01:54 +08:00
parent 005cdf070f
commit acc7391369
6 changed files with 111 additions and 6 deletions

View File

@@ -198,7 +198,8 @@ export class PlayerController {
const hotMatches = (allMatches as Array<{ isHot?: boolean; status?: string }>).filter(
(m) => m.isHot && m.status !== 'SETTLED',
);
const todayMatches = (allMatches as Array<{ startTime: string }>).filter((m) => {
const todayMatches = (allMatches as Array<{ startTime: string; status?: string }>).filter((m) => {
if (m.status === 'SETTLED') return false;
const kickoff = new Date(m.startTime);
return !Number.isNaN(kickoff.getTime()) && isInLocalTodayMatchWindow(kickoff, now, timeZone);
});

View File

@@ -267,6 +267,15 @@ describe('MatchesService listUpcomingPublished', () => {
sportType: 'FOOTBALL',
deletedAt: null,
startTime: { gte: now, lte: end },
league: {
isActive: true,
deletedAt: null,
NOT: {
matches: {
some: { isOutright: true, status: 'SETTLED', deletedAt: null },
},
},
},
}),
orderBy: [{ startTime: 'asc' }, { displayOrder: 'asc' }],
take: 50,
@@ -302,6 +311,52 @@ describe('MatchesService listUpcomingPublished', () => {
});
});
describe('MatchesService listPublished', () => {
let prisma: {
match: { findMany: jest.Mock };
entityTranslation: { findMany: jest.Mock };
};
let service: MatchesService;
beforeEach(() => {
prisma = {
match: { findMany: jest.fn().mockResolvedValue([]) },
entityTranslation: {
findMany: jest.fn().mockResolvedValue([]),
},
};
service = new MatchesService(
prisma as never,
{ syncWithLeaguePublished: jest.fn() } as never,
{ betStatsForMatches: jest.fn().mockResolvedValue(new Map()) } as never,
);
});
it('excludes settled fixtures and leagues with settled outright', async () => {
await service.listPublished('zh-CN', undefined, { includeMarkets: false });
expect(prisma.match.findMany).toHaveBeenCalledWith(
expect.objectContaining({
where: {
status: { in: ['PUBLISHED', 'CLOSED', 'PENDING_SETTLEMENT'] },
isOutright: false,
sportType: 'FOOTBALL',
deletedAt: null,
league: {
isActive: true,
deletedAt: null,
NOT: {
matches: {
some: { isOutright: true, status: 'SETTLED', deletedAt: null },
},
},
},
},
}),
);
});
});
describe('MatchesService listAdminLeagueMatches', () => {
const leagueId = BigInt(1);

View File

@@ -1554,11 +1554,19 @@ export class MatchesService {
const matches = await this.prisma.match.findMany({
where: {
status: { in: ['PUBLISHED', 'CLOSED', 'PENDING_SETTLEMENT', 'SETTLED'] },
status: { in: ['PUBLISHED', 'CLOSED', 'PENDING_SETTLEMENT'] },
isOutright: false,
sportType: 'FOOTBALL',
deletedAt: null,
league: { isActive: true, deletedAt: null },
league: {
isActive: true,
deletedAt: null,
NOT: {
matches: {
some: { isOutright: true, status: 'SETTLED', deletedAt: null },
},
},
},
...(leagueId ? { leagueId } : {}),
},
include: {
@@ -1602,7 +1610,15 @@ export class MatchesService {
sportType: 'FOOTBALL',
deletedAt: null,
startTime: { gte: now, lte: end },
league: { isActive: true, deletedAt: null },
league: {
isActive: true,
deletedAt: null,
NOT: {
matches: {
some: { isOutright: true, status: 'SETTLED', deletedAt: null },
},
},
},
},
include: {
league: true,

View File

@@ -0,0 +1,33 @@
jest.mock('./wc2026-outright.sync', () => ({
syncWc2026OutrightMarket: jest.fn().mockResolvedValue(undefined),
}));
import { OutrightService } from './outright.service';
describe('OutrightService listForPlayer', () => {
let prisma: { match: { findMany: jest.Mock } };
let service: OutrightService;
beforeEach(() => {
prisma = {
match: { findMany: jest.fn().mockResolvedValue([]) },
};
service = new OutrightService(prisma as never, {} as never);
});
it('returns only published outright markets for player browse', async () => {
await service.listForPlayer('zh-CN');
expect(prisma.match.findMany).toHaveBeenCalledWith(
expect.objectContaining({
where: expect.objectContaining({
status: 'PUBLISHED',
isOutright: true,
sportType: 'FOOTBALL',
deletedAt: null,
league: { isActive: true, deletedAt: null },
}),
}),
);
});
});

View File

@@ -701,7 +701,7 @@ export class OutrightService {
const matches = await this.prisma.match.findMany({
where: {
status: { in: ['PUBLISHED', 'SETTLED'] },
status: 'PUBLISHED',
isOutright: true,
sportType: 'FOOTBALL',
deletedAt: null,