Archived
feat(seed): 芯片类型字典两张表 —— 约束类型从「每颗料各标一次」搬到「按类型标一次」
两颗料是不是用同一套参数名、同一套软硬约束,从此是结构保证而不是措辞叮嘱: 字段清单挂在类型上,一颗料关联一个类型。此前靠 parts.parameter.param_name 的 自指引用墙硬咬(措辞拦了三次没拦住才砌的),那堵墙可以退休了。 另播一颗 LDO(AMS1117-3.3)—— 它是「两颗料类型不一致 → 硬拦」那条路的唯一素材。 同批修复两条因此变为过时的既有断言(均在 seed-mvp-data.test.ts,非本任务新增): 「样例料号」测试原本枚举 parts.profile 恰好两行,新增 AMS1117-3.3 后改为三行; 「标准化参数集」测试原本断言每行 parts.parameter 都带 constraint_type,该列已 搬到 parts.type_param 字典,断言相应改为 toBeUndefined()。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -13,6 +13,10 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { MASTER_DOMAINS, MASTER_OBJECTS, MASTER_SAMPLE_ROWS } from '../seed-mvp-data.ts';
|
||||
|
||||
const tableOf = (domain: string, object: string) => MASTER_OBJECTS.find((o) => o.domain === domain && o.object === object);
|
||||
const seedRowsOf = (domain: string, object: string) =>
|
||||
MASTER_SAMPLE_ROWS.filter((r) => r.address.domain === domain && r.address.object === object);
|
||||
|
||||
describe('主数据四域', () => {
|
||||
it('八个域:客户 / 项目 / 供应商 / 市场 + 料件 / 需求 / 替代 / 验证(SS02 差异评估 2026-08-26 加后四域)', () => {
|
||||
expect([...MASTER_DOMAINS]).toEqual(['customer', 'project', 'supplier', 'market', 'parts', 'demand', 'substitution', 'validation']);
|
||||
@@ -33,7 +37,8 @@ describe('主数据四域', () => {
|
||||
|
||||
it('样例料号:原 PN 与同族可调版在库,候选 XL2596S-5.0 刻意不播(数据工单那条路要试得出来)', () => {
|
||||
const parts = MASTER_SAMPLE_ROWS.filter((r) => r.address.domain === 'parts' && r.address.object === 'profile').map((r) => r.key['internal_pn']);
|
||||
expect(parts).toEqual(['LM2596S-5.0', 'LM2596S-ADJ']);
|
||||
// AMS1117-3.3(LDO)是 W05 重写 Task 1 新播的第三颗 —— 「两颗料类型不一致 → 硬拦」那条路的唯一素材
|
||||
expect(parts).toEqual(['LM2596S-5.0', 'LM2596S-ADJ', 'AMS1117-3.3']);
|
||||
expect(parts).not.toContain('XL2596S-5.0');
|
||||
});
|
||||
|
||||
@@ -45,7 +50,9 @@ describe('主数据四域', () => {
|
||||
for (const row of params) {
|
||||
expect(Object.keys(row.key).sort()).toEqual(['internal_pn', 'param_name']);
|
||||
expect(row.values['param_value'], JSON.stringify(row.key)).toBeTruthy();
|
||||
expect(row.values['constraint_type']).toMatch(/^(hard|soft)$/);
|
||||
// 约束类型已搬到 parts.type_param 字典上(W05 重写 Task 1)—— 这张子表不再带这一列,
|
||||
// 留着旧断言会重新允许「同一个参数在两颗料上各标一次约束」,正是这次改造要消灭的东西。
|
||||
expect(row.values['constraint_type']).toBeUndefined();
|
||||
}
|
||||
// parts.profile 不再声明这一列的值 —— 两行样例主记录里它应为空(物理列留在基线,不再写)
|
||||
const profiles = MASTER_SAMPLE_ROWS.filter((r) => r.address.domain === 'parts' && r.address.object === 'profile');
|
||||
@@ -98,3 +105,58 @@ describe('主数据四域', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('芯片类型字典(W05 重写)', () => {
|
||||
it('两张新表都物化了,主键形状对', () => {
|
||||
const chipType = tableOf('parts', 'chip_type');
|
||||
expect(chipType?.fields.find((f) => f.name === 'type_id')).toMatchObject({ type: 'integer', primaryKey: true });
|
||||
expect(chipType?.fields.map((f) => f.name)).toEqual(expect.arrayContaining(['type_id', 'type_name', 'description']));
|
||||
|
||||
const typeParam = tableOf('parts', 'type_param');
|
||||
/* 复合主键:一个类型下多个参数名 —— 主键少一半,同一类型的第二个参数就会覆盖第一个 */
|
||||
expect(typeParam?.fields.filter((f) => f.primaryKey).map((f) => f.name)).toEqual(['type_id', 'param_name']);
|
||||
expect(typeParam?.fields.map((f) => f.name)).toEqual(
|
||||
expect.arrayContaining(['type_id', 'param_name', 'param_desc', 'constraint_type', 'param_unit']),
|
||||
);
|
||||
});
|
||||
|
||||
it('P-08 上有 chip_type_id,类型与字典的主键对得上(integer)', () => {
|
||||
expect(tableOf('parts', 'profile')?.fields.find((f) => f.name === 'chip_type_id')).toMatchObject({ type: 'integer' });
|
||||
});
|
||||
|
||||
it('种子:两个类型,DC-DC 七个核心参数字段、LDO 五个', () => {
|
||||
const types = seedRowsOf('parts', 'chip_type');
|
||||
expect(types.map((r) => r.values['type_name']).sort()).toEqual(['DC-DC 降压稳压器', 'LDO 线性稳压器']);
|
||||
|
||||
const dcdc = types.find((r) => r.values['type_name'] === 'DC-DC 降压稳压器')?.values['type_id'];
|
||||
const params = seedRowsOf('parts', 'type_param').filter((r) => r.values['type_id'] === dcdc);
|
||||
expect(params.map((r) => r.values['param_name'])).toEqual([
|
||||
'输入电压范围', '输出电压', '输出电流', '开关频率', '静态电流', '工作温度', '使能阈值',
|
||||
]);
|
||||
/* 约束类型搬到字典上了 —— 同一个参数在两颗料上标法不一致这件事从结构上消失 */
|
||||
expect(params.find((r) => r.values['param_name'] === '静态电流')?.values['constraint_type']).toBe('soft');
|
||||
expect(params.find((r) => r.values['param_name'] === '输入电压范围')?.values['constraint_type']).toBe('hard');
|
||||
/* 每个字段都要有说明 —— AI 分析时读的就是它 */
|
||||
expect(params.every((r) => String(r.values['param_desc'] ?? '') !== '')).toBe(true);
|
||||
|
||||
const ldo = types.find((r) => r.values['type_name'] === 'LDO 线性稳压器')?.values['type_id'];
|
||||
expect(seedRowsOf('parts', 'type_param').filter((r) => r.values['type_id'] === ldo)).toHaveLength(5);
|
||||
});
|
||||
|
||||
it('三颗既有料都归了 DC-DC 类型,新播一颗 LDO 供「类型不一致」那条用例用', () => {
|
||||
const dcdc = seedRowsOf('parts', 'chip_type').find((r) => r.values['type_name'] === 'DC-DC 降压稳压器')?.values['type_id'];
|
||||
const ldo = seedRowsOf('parts', 'chip_type').find((r) => r.values['type_name'] === 'LDO 线性稳压器')?.values['type_id'];
|
||||
const parts = seedRowsOf('parts', 'profile');
|
||||
for (const pn of ['LM2596S-5.0', 'LM2596S-ADJ']) {
|
||||
expect(parts.find((r) => r.key['internal_pn'] === pn)?.values['chip_type_id']).toBe(dcdc);
|
||||
}
|
||||
expect(parts.find((r) => r.key['internal_pn'] === 'AMS1117-3.3')?.values['chip_type_id']).toBe(ldo);
|
||||
});
|
||||
|
||||
it('AMS1117-3.3 的参数行按 LDO 的字段清单播齐 —— 它要能被真拿来比', () => {
|
||||
const ldo = seedRowsOf('parts', 'chip_type').find((r) => r.values['type_name'] === 'LDO 线性稳压器')?.values['type_id'];
|
||||
const names = seedRowsOf('parts', 'type_param').filter((r) => r.values['type_id'] === ldo).map((r) => r.values['param_name']);
|
||||
const rows = seedRowsOf('parts', 'parameter').filter((r) => r.key['internal_pn'] === 'AMS1117-3.3');
|
||||
expect(rows.map((r) => r.key['param_name']).sort()).toEqual([...names].sort());
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user