feat(catalog): 玩家端隐藏已结算赛事与冠军盘联赛
- listPublished/listUpcomingPublished 排除 SETTLED 及冠军盘已结算联赛 - outright.listForPlayer 仅返回 PUBLISHED - 首页 todayMatches 过滤 SETTLED;管理端已结算冠军盘隐藏下架按钮 - 补充 matches/outright 单测
This commit is contained in:
@@ -49,7 +49,7 @@ defineEmits<{
|
||||
{{ row.labels.publish }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-else
|
||||
v-else-if="!row.isOutrightSettled"
|
||||
size="small"
|
||||
type="warning"
|
||||
:loading="row.isPublishing"
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
33
apps/api/src/domains/catalog/outright.service.spec.ts
Normal file
33
apps/api/src/domains/catalog/outright.service.spec.ts
Normal 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 },
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user