@things-factory/ai-assistant 10.1.104 → 10.1.107
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client/components/assistant-chat.ts +2 -2
- package/client/utils/entry-proposal.ts +11 -0
- package/dist-client/components/assistant-chat.js +2 -2
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-client/utils/entry-proposal.d.ts +5 -0
- package/dist-client/utils/entry-proposal.js +10 -0
- package/dist-client/utils/entry-proposal.js.map +1 -1
- package/dist-server/service/data-entry/entry-update.js +9 -2
- package/dist-server/service/data-entry/entry-update.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +6 -6
- package/server/service/data-entry/data-entry-update.test.ts +7 -0
- package/server/service/data-entry/entry-update.ts +6 -2
- package/test/entry-proposal.test.ts +19 -0
- package/translations/en.json +2 -0
- package/translations/ja.json +2 -0
- package/translations/ko.json +2 -0
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/ai-assistant",
|
|
3
|
-
"version": "10.1.
|
|
3
|
+
"version": "10.1.107",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"things-factory": true,
|
|
6
6
|
"author": "heartyoh",
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
"@operato/shell": "^10.0.0",
|
|
35
35
|
"@operato/styles": "^10.0.0",
|
|
36
36
|
"@things-factory/ai-client-base": "^10.1.81",
|
|
37
|
-
"@things-factory/apptool-base": "^10.1.
|
|
38
|
-
"@things-factory/attachment-base": "^10.1.
|
|
39
|
-
"@things-factory/auth-base": "^10.1.
|
|
37
|
+
"@things-factory/apptool-base": "^10.1.106",
|
|
38
|
+
"@things-factory/attachment-base": "^10.1.107",
|
|
39
|
+
"@things-factory/auth-base": "^10.1.107",
|
|
40
40
|
"@things-factory/env": "^10.1.20",
|
|
41
|
-
"@things-factory/shell": "^10.1.
|
|
41
|
+
"@things-factory/shell": "^10.1.106",
|
|
42
42
|
"dompurify": "^3.0.0",
|
|
43
43
|
"graphql-scalars": "^1.22.0",
|
|
44
44
|
"graphql-tag": "^2.12.6",
|
|
@@ -51,5 +51,5 @@
|
|
|
51
51
|
"copyfiles": "^2.4.1",
|
|
52
52
|
"rimraf": "^5.0.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "65a3d5889e687d8122a65f029b926b1a4769d1c0"
|
|
55
55
|
}
|
|
@@ -110,6 +110,13 @@ describe('the card', () => {
|
|
|
110
110
|
expect(rows[0].issues).toEqual([{ field: 'spentDate', code: 'not-changeable', blocking: false }, { code: 'no-change', blocking: true }])
|
|
111
111
|
expect(rows[1].issues).toEqual([{ field: 'category', code: 'not-in-list', params: { values: ['교통비', '회의비'] }, blocking: true }])
|
|
112
112
|
})
|
|
113
|
+
|
|
114
|
+
it('★ a field restated as it already is is not a change - not shown, not written (the model sent the name back with the note)', async () => {
|
|
115
|
+
const result: any = await proposeChanges(expense, { changes: [{ ref: 'l1', values: { merchant: '카카오T', amount: '12400', category: '회의비' } }] }, { host: {} }, run)
|
|
116
|
+
expect(result.rows[0]).toMatchObject({ before: { category: '교통비' }, values: { category: '회의비' }, issues: [] })
|
|
117
|
+
expect(Object.keys(result.rows[0].values)).toEqual(['category'])
|
|
118
|
+
expect(result.columns.map((one: any) => one.name)).toEqual(['category'])
|
|
119
|
+
})
|
|
113
120
|
})
|
|
114
121
|
|
|
115
122
|
describe('changing what the person pressed', () => {
|
|
@@ -115,8 +115,12 @@ export function changeRows(target: EntryTarget, picked: { id: string; via: Chang
|
|
|
115
115
|
if (record) before[name] = record[name] ?? null
|
|
116
116
|
}
|
|
117
117
|
if (!record) issues.push({ code: 'record-not-found', blocking: true })
|
|
118
|
-
else
|
|
119
|
-
|
|
118
|
+
else {
|
|
119
|
+
/* A field the model restated as it already is does not change - the card shows it as no change, and it is not written. */
|
|
120
|
+
const same = Object.keys(values).filter(name => fields.has(name) && !issues.some(issue => issue.field === name) && sameFieldValue(fields.get(name)!, before[name], values[name]))
|
|
121
|
+
if (same.length && same.length === Object.keys(values).length) issues.push({ code: 'no-change', blocking: true })
|
|
122
|
+
else for (const name of same) delete values[name], delete before[name]
|
|
123
|
+
}
|
|
120
124
|
if (!Object.keys(values).length && !issues.some(issue => issue.blocking)) issues.push({ code: 'nothing-to-change', blocking: true })
|
|
121
125
|
return { index, id: one.id, via: one.via, ...(record && target.update?.labelOf ? { label: target.update.labelOf(record) } : {}), before, values, issues }
|
|
122
126
|
})
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
entryOutcomeNote,
|
|
12
12
|
entryProposalHandler,
|
|
13
13
|
entryReadyCount,
|
|
14
|
+
entryTitle,
|
|
14
15
|
latestEntryKeys,
|
|
15
16
|
type EntryApplyAnswer
|
|
16
17
|
} from '../client/utils/entry-proposal'
|
|
@@ -21,6 +22,24 @@ const t = (key: string, options: any = {}) =>
|
|
|
21
22
|
const card = (key: string, target = 'office.expense-line', rows: any[] = []) => ({ key, kind: 'entry', target, rows })
|
|
22
23
|
|
|
23
24
|
describe('the entry card', () => {
|
|
25
|
+
it('★ is titled by its kind - a 수정안 is never titled as a 입력안', () => {
|
|
26
|
+
const named = (key: string, options: any = {}) => (key === 'label.office-entry-counterparty' ? 'counterparty' : t(key, options))
|
|
27
|
+
expect(entryTitle({ kind: 'entry', target: 'office.counterparty', labelKey: 'label.office-entry-counterparty', rows: [] }, named)).toBe('counterparty to enter')
|
|
28
|
+
expect(entryTitle({ kind: 'entry', op: 'update', target: 'office.counterparty', labelKey: 'label.office-entry-counterparty', rows: [] }, named)).toBe('counterparty to change')
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
it('★ every target label names the record only - the card adds 입력안 or 수정안', () => {
|
|
32
|
+
/* The framework's own declarers; the applications hold the same rule in their translations. */
|
|
33
|
+
const offending: string[] = []
|
|
34
|
+
for (const root of ['../../ops-master', '../../organization', '../../i18n-base'])
|
|
35
|
+
for (const lang of ['ko', 'ja', 'zh', 'ms']) {
|
|
36
|
+
const table: Record<string, string> = JSON.parse(readFileSync(join(__dirname, root, 'translations', `${lang}.json`), 'utf8'))
|
|
37
|
+
for (const [key, value] of Object.entries(table))
|
|
38
|
+
if (/^label\.[a-z0-9-]+-entry-/.test(key) && /입력안|수정안|入力案|录入方案|cadangan/.test(value)) offending.push(`${root}/${lang}: ${key}`)
|
|
39
|
+
}
|
|
40
|
+
expect(offending).toEqual([])
|
|
41
|
+
})
|
|
42
|
+
|
|
24
43
|
it('★ counts only the rows that will go in', () => {
|
|
25
44
|
const p = card('k', undefined, [
|
|
26
45
|
{ index: 0, values: {}, sources: [], issues: [] },
|
package/translations/en.json
CHANGED
|
@@ -254,6 +254,8 @@
|
|
|
254
254
|
"ai-assistant.workspace.contains-metrics": "{count} figures",
|
|
255
255
|
"ai-assistant.workspace.contains-steps": "{count} progress",
|
|
256
256
|
"ai-assistant.entry.change": "change {count} records",
|
|
257
|
+
"ai-assistant.entry.title-create": "{name} to enter",
|
|
258
|
+
"ai-assistant.entry.title-update": "{name} to change",
|
|
257
259
|
"ai-assistant.entry.changed": "changed {count} records.",
|
|
258
260
|
"ai-assistant.entry.changed-none": "no record was changed.",
|
|
259
261
|
"ai-assistant.entry.changes": "{count} records",
|
package/translations/ja.json
CHANGED
|
@@ -254,6 +254,8 @@
|
|
|
254
254
|
"ai-assistant.workspace.contains-metrics": "指標 {count}",
|
|
255
255
|
"ai-assistant.workspace.contains-steps": "経過 {count}",
|
|
256
256
|
"ai-assistant.entry.change": "{count}件を修正",
|
|
257
|
+
"ai-assistant.entry.title-create": "{name}の入力案",
|
|
258
|
+
"ai-assistant.entry.title-update": "{name}の修正案",
|
|
257
259
|
"ai-assistant.entry.changed": "{count}件を修正しました。",
|
|
258
260
|
"ai-assistant.entry.changed-none": "修正された記録はありません。",
|
|
259
261
|
"ai-assistant.entry.changes": "{count}件",
|
package/translations/ko.json
CHANGED
|
@@ -254,6 +254,8 @@
|
|
|
254
254
|
"ai-assistant.workspace.contains-metrics": "수치 {count}",
|
|
255
255
|
"ai-assistant.workspace.contains-steps": "경과 {count}",
|
|
256
256
|
"ai-assistant.entry.change": "{count}건 고치기",
|
|
257
|
+
"ai-assistant.entry.title-create": "{name} 입력안",
|
|
258
|
+
"ai-assistant.entry.title-update": "{name} 수정안",
|
|
257
259
|
"ai-assistant.entry.changed": "{count}건을 고쳤습니다.",
|
|
258
260
|
"ai-assistant.entry.changed-none": "고친 기록이 없습니다.",
|
|
259
261
|
"ai-assistant.entry.changes": "{count}건",
|
package/translations/ms.json
CHANGED
|
@@ -254,6 +254,8 @@
|
|
|
254
254
|
"ai-assistant.workspace.contains-metrics": "{count} angka",
|
|
255
255
|
"ai-assistant.workspace.contains-steps": "{count} kemajuan",
|
|
256
256
|
"ai-assistant.entry.change": "ubah {count} rekod",
|
|
257
|
+
"ai-assistant.entry.title-create": "cadangan kemasukan {name}",
|
|
258
|
+
"ai-assistant.entry.title-update": "cadangan perubahan {name}",
|
|
257
259
|
"ai-assistant.entry.changed": "{count} rekod diubah.",
|
|
258
260
|
"ai-assistant.entry.changed-none": "tiada rekod diubah.",
|
|
259
261
|
"ai-assistant.entry.changes": "{count} rekod",
|
package/translations/zh.json
CHANGED
|
@@ -254,6 +254,8 @@
|
|
|
254
254
|
"ai-assistant.workspace.contains-metrics": "指标 {count}",
|
|
255
255
|
"ai-assistant.workspace.contains-steps": "进度 {count}",
|
|
256
256
|
"ai-assistant.entry.change": "修改{count}条",
|
|
257
|
+
"ai-assistant.entry.title-create": "{name}录入方案",
|
|
258
|
+
"ai-assistant.entry.title-update": "{name}修改方案",
|
|
257
259
|
"ai-assistant.entry.changed": "已修改{count}条。",
|
|
258
260
|
"ai-assistant.entry.changed-none": "未修改任何记录。",
|
|
259
261
|
"ai-assistant.entry.changes": "{count}条",
|