Archived
feat(w05): S1 配方 —— 校验入参、铺格、缺什么派一张数据工单
在库与否是一次 lookup 的结果,不是一句断言:先取 found_pn_ref(refersTo 查无此值当场拒)再按它判。 参数骨架两颗料都铺、值回填现值 —— 于是「在库但当年参数没录全」也自动被红带拦住。 发卡的条件只用基座读数:gate_reason 为空串时那一列不写、未绑定,而 S-FEEL 里未绑定的名字 `!= ""` 求值为 true —— 拿它当条件恰恰会在一切正常时把卡发出去。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -129,7 +129,150 @@ export const ASSESSMENT_STEPS = [
|
||||
doneWhen:
|
||||
'sub_eval_part_exists_status_found = 2 and sub_eval_part_missing = 0 and ' +
|
||||
'sub_eval_part_distinct_chip_type_id = 1 and parts_profile_missing = 0 and parts_parameter_missing = 0',
|
||||
auto: { do: [{ kind: 'say' as const, text: '正在核对两颗料的在库状态与参数齐备情况。' }] },
|
||||
auto: {
|
||||
/** 整单只有这一个案号,从本单开案时刻取材 —— **不许从正式表里别单的号里挑**(踩过) */
|
||||
let: { evalRef: { cat: ['W05-', { fmt: { in: 'case:openedAt' }, as: 'digits' as const }] } },
|
||||
do: [
|
||||
/*
|
||||
* ① 本单两颗料 —— **后面每一笔遍历的唯一来源**。
|
||||
* 挤进案卷一行里就没法 `where` 过滤,而不能过滤就会给已经在库的那颗也铺一遍空参数行。
|
||||
*/
|
||||
{
|
||||
kind: 'project' as const,
|
||||
into: 'sub_eval.part',
|
||||
from: {
|
||||
rows: [
|
||||
{ pn: { in: 'originalInternalPn' }, role: 'original' },
|
||||
{ pn: { in: 'candidateInternalPn' }, role: 'candidate' },
|
||||
],
|
||||
},
|
||||
fields: {
|
||||
eval_ref: { in: 'evalRef' },
|
||||
internal_pn: { col: 'pn' },
|
||||
role: { col: 'role' },
|
||||
/* 先取依据,再按依据判 —— 字段按声明顺序求值,算出来的进同一行的 S-FEEL 作用域 */
|
||||
found_pn_ref: { lookup: 'parts.profile', by: { internal_pn: { col: 'pn' } }, take: 'internal_pn', else: '' },
|
||||
exists_status: { when: 'found_pn_ref != ""', then: 'found', else: 'absent' },
|
||||
chip_type_id: { lookup: 'parts.profile', by: { internal_pn: { col: 'pn' } }, take: 'chip_type_id', else: '' },
|
||||
},
|
||||
},
|
||||
/* ② 案卷一行:`gate_reason` 是**摆在件上给人看**的那句话(条件判断另用基座读数,见 ⑤) */
|
||||
{
|
||||
kind: 'project' as const,
|
||||
into: 'sub_eval.case',
|
||||
from: { once: true as const },
|
||||
fields: {
|
||||
eval_ref: { in: 'evalRef' },
|
||||
chip_type_id: { lookup: 'mine:sub_eval.part', by: { role: 'original' }, take: 'chip_type_id', else: '' },
|
||||
gate_reason: {
|
||||
when: 'sub_eval_part_rows < 2',
|
||||
then: '原料号与候选料号还没填全 —— 在下面把两格补上。',
|
||||
else: {
|
||||
when: 'sub_eval_part_exists_status_absent > 0',
|
||||
then: '有料号库里查不到 —— 在下面把它的主数据建起来。',
|
||||
else: {
|
||||
when: 'sub_eval_part_missing > 0',
|
||||
then: '有料号还没归芯片类型 —— 在下面给它选一个;没有合适的就新建一个,并把它的核心参数字段一并定下来。',
|
||||
else: {
|
||||
when: 'sub_eval_part_distinct_chip_type_id > 1',
|
||||
then: '两颗料不是同一个芯片类型,逐项比对无从谈起 —— 换一颗料,或者把归错的那颗类型改对。',
|
||||
else: {
|
||||
when: 'parts_profile_missing + parts_parameter_missing > 0',
|
||||
then: '还有必填格空着 —— 红带点名的那几格填上就能提交。',
|
||||
else: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
/*
|
||||
* ③ 主数据骨架:**两颗料都铺、值回填现值**。
|
||||
* 在库那颗回填出它此刻的样子(人不必重填);要建那颗全空等人填。
|
||||
* **「在库的老料还没归类型」于是也被拦住** —— 那一格回填出来是空的,而 `chip_type_id` 必填。
|
||||
* 人不必在件上「加一行」:要建哪颗料是启动参数就定死的事,行由系统摆好,他只填格子。
|
||||
*/
|
||||
{
|
||||
kind: 'project' as const,
|
||||
into: 'parts.profile',
|
||||
prune: true,
|
||||
from: { each: 'mine:sub_eval.part' },
|
||||
fields: {
|
||||
internal_pn: { col: 'internal_pn' },
|
||||
chip_type_id: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'chip_type_id', else: '' },
|
||||
brand_name: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'brand_name', else: '' },
|
||||
lifecycle_status: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'lifecycle_status', else: '' },
|
||||
specification_description: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'specification_description', else: '' },
|
||||
manufacturer_name: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'manufacturer_name', else: '' },
|
||||
datasheet_ref: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'datasheet_ref', else: '' },
|
||||
datasheet_version: { lookup: 'parts.profile', by: { internal_pn: { col: 'internal_pn' } }, take: 'datasheet_version', else: '' },
|
||||
},
|
||||
},
|
||||
/*
|
||||
* ④ 参数骨架 —— 三件事一笔办完:
|
||||
* · 人还没挑类型 → `{outer:'chip_type_id'}` 是空串,`where` 一行不命中,**什么也不铺**;
|
||||
* 他挑了、按了保存,行就出来 —— **「保存即铺格」不是特判,是这一笔的自然结果**;
|
||||
* · 在库那颗料**也**铺,值回填现值 → 屏上是它此刻的样子,`_missing` 不会误报;
|
||||
* · **「在库但当年参数没录全」于是自动被拦住** —— 那一格回填出来是空的,红带点名、闸按不下。
|
||||
*/
|
||||
{
|
||||
kind: 'project' as const,
|
||||
into: 'parts.parameter',
|
||||
prune: true,
|
||||
from: {
|
||||
each: 'mine:sub_eval.part',
|
||||
then: { each: 'parts.type_param', where: { type_id: { outer: 'chip_type_id' } } },
|
||||
},
|
||||
fields: {
|
||||
internal_pn: { outer: 'internal_pn' },
|
||||
param_name: { col: 'param_name' },
|
||||
param_unit: { col: 'param_unit' },
|
||||
param_value: {
|
||||
lookup: 'parts.parameter',
|
||||
by: { internal_pn: { outer: 'internal_pn' }, param_name: { col: 'param_name' } },
|
||||
take: 'param_value',
|
||||
else: '',
|
||||
},
|
||||
param_note: {
|
||||
lookup: 'parts.parameter',
|
||||
by: { internal_pn: { outer: 'internal_pn' }, param_name: { col: 'param_name' } },
|
||||
take: 'param_note',
|
||||
else: '',
|
||||
},
|
||||
},
|
||||
},
|
||||
/*
|
||||
* ⑤ 缺什么就派一张数据工单。
|
||||
* **条件只用基座读数**:`gate_reason` 为空串时那一列压根不写、于是未绑定,
|
||||
* 而 S-FEEL 里未绑定的名字 `!= ""` 求值为 **true** —— 拿它当条件,恰恰在一切正常时把卡发出去。
|
||||
*/
|
||||
{
|
||||
kind: 'card' as const,
|
||||
when:
|
||||
'sub_eval_part_exists_status_found < 2 or sub_eval_part_missing > 0 or ' +
|
||||
'sub_eval_part_distinct_chip_type_id > 1 or parts_profile_missing > 0 or parts_parameter_missing > 0',
|
||||
as: 'execution' as const,
|
||||
variant: 'data' as const,
|
||||
title: '数据工单 · 差异评估的输入还差几格',
|
||||
basis: [
|
||||
{ k: '原料号', v: { in: 'originalInternalPn' } },
|
||||
{ k: '候选料号', v: { in: 'candidateInternalPn' } },
|
||||
{ k: '还差什么', v: { in: 'gate_reason' } },
|
||||
],
|
||||
guide: [
|
||||
'两颗料必须归到**同一个芯片类型**下 —— 要比的核心参数字段由类型定,类型不同就没有可比的字段。',
|
||||
'类型下拉里没有合适的,就新建一个,并把它的**核心参数字段**一并定下来:每个字段要有名字、一句说明、以及硬约束还是软约束。',
|
||||
'说明写「这个参数为什么要紧」——**它是后面判定差异时唯一的解释来源**,写成参数名的复述等于没写。',
|
||||
'硬约束 = 不满足就不能用(烧芯片、超温域、装不上);软约束 = 影响表现但可权衡(功耗、噪声)。',
|
||||
'参数值填**原厂规格书上的值**,查不到就留空 —— 留空会被红带点名,但**编一个值比留空坏得多**。',
|
||||
],
|
||||
standard: '红带消失、提交钮变绿:两颗料都在库、归了同一个类型、每个核心参数字段都有值。',
|
||||
gateLedgers: ['parts.chip_type', 'parts.type_param', 'parts.profile', 'parts.parameter'],
|
||||
},
|
||||
{ kind: 'say' as const, text: '已核对两颗料的在库状态与参数齐备情况。' },
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
item: 'S2_assess',
|
||||
|
||||
Reference in New Issue
Block a user