| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253 |
- import 'dotenv/config';
- import { z } from 'zod';
- import { ParseRestClient } from '../src/db/parse-rest.client.js';
- import { VOC_PARSE_CLASSES } from '../src/db/parse-rest.schema.js';
- import type { ListingScoreResult, ListingSourceSnapshot } from '../src/modules/listing-ai/domain.js';
- import { ParseRestListingAiRepository } from '../src/modules/listing-ai/repositories/parse-rest-listing-ai.repository.js';
- const COHORT = 'listing-jd-v3-formal-625';
- interface Stored<T> { objectId: string; productId?: string; isCurrent?: boolean; payload: T }
- async function main() {
- const env = z.object({ PARSE_SERVER_URL: z.url(), PARSE_APP_ID: z.string().min(1), PARSE_MASTER_KEY: z.string().min(1), SAAS_DEFAULT_WORKSPACE_ID: z.string().default('demashi') }).parse(process.env);
- const apply = process.argv.includes('--apply=true');
- const expected = Number(process.argv.find((value) => value.startsWith('--expected-count='))?.split('=')[1] ?? 625);
- const client = new ParseRestClient({ serverUrl: env.PARSE_SERVER_URL, appId: env.PARSE_APP_ID, masterKey: env.PARSE_MASTER_KEY });
- const workspaceId = env.SAAS_DEFAULT_WORKSPACE_ID;
- const [scores, sources] = await Promise.all([
- client.findAll<Stored<ListingScoreResult>>(VOC_PARSE_CLASSES.listingCurrentScore, { workspaceId }),
- client.findAll<Stored<ListingSourceSnapshot>>(VOC_PARSE_CLASSES.listingSourceSnapshot, { workspaceId, platform: 'jd', isCurrent: true }),
- ]);
- const included = new Set(scores.map((row) => row.payload).filter((score) => typeof score.overallScore === 'number' && Number.isFinite(score.overallScore)).map((score) => score.productId));
- if (included.size !== expected) throw new Error(`cohort_count_mismatch expected=${expected} actual=${included.size}`);
- const report = { mode: apply ? 'apply' : 'dry-run', workspaceId, cohort: COHORT, currentSources: sources.length, included: included.size, excluded: sources.filter((row) => !included.has(row.payload.productId)).length };
- console.log(JSON.stringify(report, null, 2));
- if (!apply) return;
- const requests = sources.map((row) => ({ method: 'PUT' as const, path: `/classes/${VOC_PARSE_CLASSES.listingSourceSnapshot}/${row.objectId}`, body: { catalogIncluded: included.has(row.payload.productId), catalogCohort: COHORT } }));
- for (let index = 0; index < requests.length; index += 50) await client.batch(requests.slice(index, index + 50));
- const active = await client.count(VOC_PARSE_CLASSES.listingSourceSnapshot, { workspaceId, platform: 'jd', isCurrent: true, catalogIncluded: true, catalogCohort: COHORT });
- if (active !== expected) throw new Error(`cohort_apply_verification_failed expected=${expected} actual=${active}`);
- const repository = new ParseRestListingAiRepository(client);
- const excludedProductId = sources.find((row) => !included.has(row.payload.productId))?.payload.productId ?? null;
- const includedProductId = visibleProductId(included);
- const [visibleSources, summary, firstPage] = await Promise.all([
- repository.listAllSources(workspaceId, 'jd'),
- repository.catalogSummary(workspaceId, 'jd'),
- repository.listProducts({ workspaceId, platform: 'jd', cursor: null, limit: 25, sort: 'productId' }),
- ]);
- const [includedSource, excludedSource] = await Promise.all([
- includedProductId ? repository.getSource(workspaceId, 'jd', includedProductId) : null,
- excludedProductId ? repository.getSource(workspaceId, 'jd', excludedProductId) : null,
- ]);
- const firstPageOutsideCohort = firstPage.items.filter((item) => !included.has(item.productId)).length;
- if (visibleSources.length !== expected || summary.sourceTotal !== expected || firstPage.items.length !== 25 || firstPageOutsideCohort > 0 || !includedSource || excludedSource) {
- throw new Error(`cohort_repository_verification_failed sources=${visibleSources.length} summary=${summary.sourceTotal} pageItems=${firstPage.items.length} outside=${firstPageOutsideCohort} includedVisible=${Boolean(includedSource)} excludedVisible=${Boolean(excludedSource)}`);
- }
- console.log(JSON.stringify({ status: 'completed', active, repositoryVisible: visibleSources.length, catalogTotal: summary.sourceTotal, firstPageItems: firstPage.items.length, firstPageOutsideCohort, includedProductVisible: Boolean(includedSource), excludedProductVisible: Boolean(excludedSource) }, null, 2));
- }
- function visibleProductId(productIds: Set<string>): string | null {
- return productIds.values().next().value ?? null;
- }
- main().catch((error) => { console.error(`[set-listing-catalog-cohort] ${error instanceof Error ? error.message : error}`); process.exitCode = 1; });
|