@happyvertical/smrt-manufacturing 0.53.5 → 0.54.0

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.
Files changed (73) hide show
  1. package/AGENTS.md +18 -7
  2. package/README.md +70 -5
  3. package/agents/multilevel-and-runs.md +28 -0
  4. package/dist/collections/ProductionRunCollection.d.ts +15 -0
  5. package/dist/collections/ProductionRunCollection.d.ts.map +1 -0
  6. package/dist/collections/ProductionRunCompletionCollection.d.ts +14 -0
  7. package/dist/collections/ProductionRunCompletionCollection.d.ts.map +1 -0
  8. package/dist/collections/index.d.ts +2 -0
  9. package/dist/collections/index.d.ts.map +1 -1
  10. package/dist/index.d.ts +13 -5
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +972 -81
  13. package/dist/index.js.map +1 -1
  14. package/dist/manifest.json +630 -2
  15. package/dist/models/ProductionRun.d.ts +67 -0
  16. package/dist/models/ProductionRun.d.ts.map +1 -0
  17. package/dist/models/ProductionRunCompletion.d.ts +36 -0
  18. package/dist/models/ProductionRunCompletion.d.ts.map +1 -0
  19. package/dist/models/index.d.ts +2 -0
  20. package/dist/models/index.d.ts.map +1 -1
  21. package/dist/operation-types.d.ts +9 -0
  22. package/dist/operation-types.d.ts.map +1 -1
  23. package/dist/production-run-types.d.ts +100 -0
  24. package/dist/production-run-types.d.ts.map +1 -0
  25. package/dist/quantity.d.ts +36 -0
  26. package/dist/quantity.d.ts.map +1 -0
  27. package/dist/services/AssemblyService.d.ts +7 -2
  28. package/dist/services/AssemblyService.d.ts.map +1 -1
  29. package/dist/services/BomService.d.ts +84 -5
  30. package/dist/services/BomService.d.ts.map +1 -1
  31. package/dist/services/ProductionRunService.d.ts +123 -0
  32. package/dist/services/ProductionRunService.d.ts.map +1 -0
  33. package/dist/services/ProductionService.d.ts +11 -0
  34. package/dist/services/ProductionService.d.ts.map +1 -1
  35. package/dist/services/index.d.ts +2 -0
  36. package/dist/services/index.d.ts.map +1 -1
  37. package/dist/services/structure-walk.d.ts +77 -0
  38. package/dist/services/structure-walk.d.ts.map +1 -0
  39. package/dist/smrt-knowledge.json +514 -9
  40. package/dist/svelte/components/AssemblyForm.svelte +423 -52
  41. package/dist/svelte/components/AssemblyForm.svelte.d.ts +17 -32
  42. package/dist/svelte/components/AssemblyForm.svelte.d.ts.map +1 -1
  43. package/dist/svelte/components/AssemblyList.svelte +18 -12
  44. package/dist/svelte/components/AssemblyList.svelte.d.ts +2 -13
  45. package/dist/svelte/components/AssemblyList.svelte.d.ts.map +1 -1
  46. package/dist/svelte/components/ProductionRunList.svelte +213 -0
  47. package/dist/svelte/components/ProductionRunList.svelte.d.ts +18 -0
  48. package/dist/svelte/components/ProductionRunList.svelte.d.ts.map +1 -0
  49. package/dist/svelte/components/RequirementsTree.svelte +125 -0
  50. package/dist/svelte/components/RequirementsTree.svelte.d.ts +13 -0
  51. package/dist/svelte/components/RequirementsTree.svelte.d.ts.map +1 -0
  52. package/dist/svelte/components/RequirementsTreeLevel.svelte +120 -0
  53. package/dist/svelte/components/RequirementsTreeLevel.svelte.d.ts +12 -0
  54. package/dist/svelte/components/RequirementsTreeLevel.svelte.d.ts.map +1 -0
  55. package/dist/svelte/i18n.d.ts +55 -0
  56. package/dist/svelte/i18n.d.ts.map +1 -1
  57. package/dist/svelte/i18n.js +55 -0
  58. package/dist/svelte/index.d.ts +11 -6
  59. package/dist/svelte/index.d.ts.map +1 -1
  60. package/dist/svelte/index.js +11 -6
  61. package/dist/svelte/types.d.ts +182 -0
  62. package/dist/svelte/types.d.ts.map +1 -1
  63. package/dist/svelte/types.js +250 -0
  64. package/dist/tenant-scope.d.ts +25 -0
  65. package/dist/tenant-scope.d.ts.map +1 -0
  66. package/dist/types.d.ts +207 -3
  67. package/dist/types.d.ts.map +1 -1
  68. package/dist/types.js +13 -1
  69. package/dist/types.js.map +1 -1
  70. package/dist/ui.d.ts.map +1 -1
  71. package/dist/ui.js +23 -1
  72. package/dist/ui.js.map +1 -1
  73. package/package.json +10 -10
@@ -2,10 +2,11 @@
2
2
  * @happyvertical/smrt-manufacturing/svelte
3
3
  *
4
4
  * Props-driven Svelte 5 surfaces: the managed list of operations (a list with
5
- * retire and reinstate, and a form), and assemblies (a list, a policy-driven
6
- * form, and a bill-of-materials editor whose sub-assemblies expand to their own
7
- * bills). Hosts load data through the package services and collections and
8
- * pass plain view objects.
5
+ * retire and reinstate, and a form), and assemblies (a list, a form, and a
6
+ * bill-of-materials editor whose sub-assemblies expand to their own bills),
7
+ * production runs with their progress and completion reporting, and
8
+ * the read-only exploded requirements of a bill. Hosts load data through the
9
+ * package services and collections and pass plain view objects.
9
10
  * Auto-registers components with ModuleUIRegistry on import.
10
11
  *
11
12
  * @packageDocumentation
@@ -17,12 +18,16 @@ import BomEditor from './components/BomEditor.svelte';
17
18
  import BomStructureTree from './components/BomStructureTree.svelte';
18
19
  import OperationForm from './components/OperationForm.svelte';
19
20
  import OperationList from './components/OperationList.svelte';
20
- export { AssemblyForm, AssemblyList, BomEditor, BomStructureTree, OperationForm, OperationList, };
21
+ import ProductionRunList from './components/ProductionRunList.svelte';
22
+ import RequirementsTree from './components/RequirementsTree.svelte';
23
+ export { AssemblyForm, AssemblyList, BomEditor, BomStructureTree, OperationForm, OperationList, ProductionRunList, RequirementsTree, };
21
24
  export type AssemblyFormProps = ComponentProps<typeof AssemblyForm>;
22
25
  export type AssemblyListProps = ComponentProps<typeof AssemblyList>;
23
26
  export type BomEditorProps = ComponentProps<typeof BomEditor>;
24
27
  export type BomStructureTreeProps = ComponentProps<typeof BomStructureTree>;
25
28
  export type OperationFormProps = ComponentProps<typeof OperationForm>;
26
29
  export type OperationListProps = ComponentProps<typeof OperationList>;
27
- export { type AssemblyView, type BomComponentOption, type BomEditorLine, type BomLineDraft, type BomLineDraftField, type BomLineInput, type BomLineValidation, type ComponentKind, componentKindLabelKey, type OperationFormDraft, type OperationFormField, type OperationFormInitial, type OperationFormValidation, type OperationFormValues, type OperationView, operationStatusBadgeKey, splitLabourMinutes, toAssemblyView, toBomEditorLine, toBomEditorLines, validateBomLineInput, validateOperationForm, } from './types.js';
30
+ export type ProductionRunListProps = ComponentProps<typeof ProductionRunList>;
31
+ export type RequirementsTreeProps = ComponentProps<typeof RequirementsTree>;
32
+ export { type AssemblyFieldPolicy, type AssemblyFormDraft, type AssemblyFormField, type AssemblyFormInitial, type AssemblyFormInvalidField, type AssemblyFormValidation, type AssemblyFormValues, type AssemblyView, assemblyFormDraft, type BomComponentOption, type BomEditorLine, type BomLineDraft, type BomLineDraftField, type BomLineInput, type BomLineValidation, type CompletionQtyValidation, type ComponentKind, componentKindLabelKey, currencyExponent, formatPriceInput, isProductionRunOpen, keepProtectedFields, type OperationFormDraft, type OperationFormField, type OperationFormInitial, type OperationFormValidation, type OperationFormValues, type OperationView, operationStatusBadgeKey, type ProductionRunStatus, type ProductionRunView, productionRunStatusLabelKey, productionRunStatusTone, type RequirementLineView, type RequirementTotalView, splitLabourMinutes, toAssemblyView, toBomEditorLine, toBomEditorLines, toProductionRunView, toRequirementTotals, toRequirementTree, validateAssemblyForm, validateBomLineInput, validateCompletionQty, validateOperationForm, } from './types.js';
28
33
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,SAAS,MAAM,+BAA+B,CAAC;AACtD,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AACpE,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAE9D,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC;AAEtE,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,aAAa,EAClB,qBAAqB,EACrB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,uBAAuB,EACvB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,oBAAoB,EACpB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/svelte/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAE7C,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,YAAY,MAAM,kCAAkC,CAAC;AAC5D,OAAO,SAAS,MAAM,+BAA+B,CAAC;AACtD,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AACpE,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,aAAa,MAAM,mCAAmC,CAAC;AAC9D,OAAO,iBAAiB,MAAM,uCAAuC,CAAC;AACtE,OAAO,gBAAgB,MAAM,sCAAsC,CAAC;AAEpE,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,gBAAgB,EAChB,aAAa,EACb,aAAa,EACb,iBAAiB,EACjB,gBAAgB,GACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,iBAAiB,GAAG,cAAc,CAAC,OAAO,YAAY,CAAC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,cAAc,CAAC,OAAO,SAAS,CAAC,CAAC;AAC9D,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE5E,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC;AACtE,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,OAAO,aAAa,CAAC,CAAC;AACtE,MAAM,MAAM,sBAAsB,GAAG,cAAc,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAC9E,MAAM,MAAM,qBAAqB,GAAG,cAAc,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE5E,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,uBAAuB,EAC5B,KAAK,aAAa,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,kBAAkB,EACvB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,EACxB,KAAK,aAAa,EAClB,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,2BAA2B,EAC3B,uBAAuB,EACvB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,kBAAkB,EAClB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,oBAAoB,EACpB,oBAAoB,EACpB,qBAAqB,EACrB,qBAAqB,GACtB,MAAM,YAAY,CAAC"}
@@ -2,10 +2,11 @@
2
2
  * @happyvertical/smrt-manufacturing/svelte
3
3
  *
4
4
  * Props-driven Svelte 5 surfaces: the managed list of operations (a list with
5
- * retire and reinstate, and a form), and assemblies (a list, a policy-driven
6
- * form, and a bill-of-materials editor whose sub-assemblies expand to their own
7
- * bills). Hosts load data through the package services and collections and
8
- * pass plain view objects.
5
+ * retire and reinstate, and a form), and assemblies (a list, a form, and a
6
+ * bill-of-materials editor whose sub-assemblies expand to their own bills),
7
+ * production runs with their progress and completion reporting, and
8
+ * the read-only exploded requirements of a bill. Hosts load data through the
9
+ * package services and collections and pass plain view objects.
9
10
  * Auto-registers components with ModuleUIRegistry on import.
10
11
  *
11
12
  * @packageDocumentation
@@ -18,8 +19,10 @@ import BomEditor from './components/BomEditor.svelte';
18
19
  import BomStructureTree from './components/BomStructureTree.svelte';
19
20
  import OperationForm from './components/OperationForm.svelte';
20
21
  import OperationList from './components/OperationList.svelte';
21
- export { AssemblyForm, AssemblyList, BomEditor, BomStructureTree, OperationForm, OperationList, };
22
- export { componentKindLabelKey, operationStatusBadgeKey, splitLabourMinutes, toAssemblyView, toBomEditorLine, toBomEditorLines, validateBomLineInput, validateOperationForm, } from './types.js';
22
+ import ProductionRunList from './components/ProductionRunList.svelte';
23
+ import RequirementsTree from './components/RequirementsTree.svelte';
24
+ export { AssemblyForm, AssemblyList, BomEditor, BomStructureTree, OperationForm, OperationList, ProductionRunList, RequirementsTree, };
25
+ export { assemblyFormDraft, componentKindLabelKey, currencyExponent, formatPriceInput, isProductionRunOpen, keepProtectedFields, operationStatusBadgeKey, productionRunStatusLabelKey, productionRunStatusTone, splitLabourMinutes, toAssemblyView, toBomEditorLine, toBomEditorLines, toProductionRunView, toRequirementTotals, toRequirementTree, validateAssemblyForm, validateBomLineInput, validateCompletionQty, validateOperationForm, } from './types.js';
23
26
  // Auto-register with ModuleUIRegistry
24
27
  ModuleUIRegistry.registerModule(MANUFACTURING_MODULE_META);
25
28
  ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'operation-list', OperationList);
@@ -27,3 +30,5 @@ ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'operation-form',
27
30
  ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'assembly-list', AssemblyList);
28
31
  ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'assembly-form', AssemblyForm);
29
32
  ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'bom-editor', BomEditor);
33
+ ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'production-run-list', ProductionRunList);
34
+ ModuleUIRegistry.register('@happyvertical/smrt-manufacturing', 'requirements-tree', RequirementsTree);
@@ -5,7 +5,9 @@
5
5
  * data across the server/client boundary.
6
6
  */
7
7
  import type { Assembly } from '../models/Assembly.js';
8
+ import type { ProductionRun, ProductionRunStatus } from '../models/ProductionRun.js';
8
9
  import type { BillStructure, BillStructureLine, ComponentKind } from '../services/AssemblyService.js';
10
+ import type { Explosion, RequirementsPlan } from '../types.js';
9
11
  /** One row of `OperationList`; an `Operation` satisfies it. */
10
12
  export interface OperationView {
11
13
  /** The `Operation` id. */
@@ -56,6 +58,101 @@ export interface OperationFormDraft {
56
58
  export declare function operationStatusBadgeKey(isActive: boolean): string;
57
59
  /** Trim a form draft and check the required fields: code and name. */
58
60
  export declare function validateOperationForm(draft: Readonly<Partial<OperationFormDraft>>): OperationFormValidation;
61
+ /**
62
+ * The part of a resolved field policy `AssemblyList` reads: each field's
63
+ * visibility. smrt-fields' `ResolvedObjectFieldPolicy` satisfies it.
64
+ */
65
+ export interface AssemblyFieldPolicy {
66
+ fields: Readonly<Record<string, {
67
+ visibility?: string;
68
+ } | undefined>>;
69
+ }
70
+ /** A field of `AssemblyForm`, named as `Assembly` and `Product` name it. */
71
+ export type AssemblyFormField = 'name' | 'description' | 'category' | 'partReference' | 'price' | 'estimatedLabourMinutes' | 'defaultOperationId' | 'tags';
72
+ /** Existing values passed to `AssemblyForm` when editing; an `Assembly` satisfies it. */
73
+ export interface AssemblyFormInitial {
74
+ name: string;
75
+ description: string;
76
+ category: string;
77
+ partReference: string;
78
+ /** Catalog price in integer minor units (cents). */
79
+ price: number;
80
+ /** Labour to build one unit, in whole minutes. */
81
+ estimatedLabourMinutes: number;
82
+ /** The default `Operation` id, or `null` for none. */
83
+ defaultOperationId: string | null;
84
+ tags: readonly string[];
85
+ }
86
+ /**
87
+ * What `AssemblyForm` hands to `onsubmit`; text is trimmed. A hidden or
88
+ * read-only field carries its initial value unchanged (a default for a new
89
+ * assembly), so a host can save every key or only the ones that differ.
90
+ */
91
+ export interface AssemblyFormValues {
92
+ name: string;
93
+ description: string;
94
+ category: string;
95
+ partReference: string;
96
+ /** Integer minor units (cents). */
97
+ price: number;
98
+ /** A whole number of minutes, zero or more. */
99
+ estimatedLabourMinutes: number;
100
+ /** The chosen `Operation` id, or `null` for none. */
101
+ defaultOperationId: string | null;
102
+ tags: string[];
103
+ }
104
+ /** A field `validateAssemblyForm` can reject. */
105
+ export type AssemblyFormInvalidField = 'name' | 'price' | 'estimatedLabourMinutes';
106
+ /** The raw text `AssemblyForm` collects, before trimming and checks. */
107
+ export interface AssemblyFormDraft {
108
+ name: string;
109
+ description: string;
110
+ category: string;
111
+ partReference: string;
112
+ /** Major units as typed, e.g. `1250.00`. */
113
+ price: string;
114
+ estimatedLabourMinutes: string;
115
+ /** Empty for none. */
116
+ defaultOperationId: string;
117
+ /** Comma-separated. */
118
+ tags: string;
119
+ }
120
+ /** Result of {@link validateAssemblyForm}. */
121
+ export type AssemblyFormValidation = {
122
+ ok: true;
123
+ values: AssemblyFormValues;
124
+ } | {
125
+ ok: false;
126
+ invalid: AssemblyFormInvalidField[];
127
+ };
128
+ /**
129
+ * The number of decimal places in a currency's minor unit (2 for USD, 0 for
130
+ * JPY, 3 for KWD), as `Intl` knows it; 2 when the code is not recognized.
131
+ */
132
+ export declare function currencyExponent(currency: string): number;
133
+ /**
134
+ * Format integer minor units as the major-unit text the price field shows,
135
+ * with `exponent` decimals. A negative value keeps its sign so validation
136
+ * reports it instead of replacing it.
137
+ */
138
+ export declare function formatPriceInput(minorUnits: number, exponent?: number): string;
139
+ /** The draft `AssemblyForm` starts from for an assembly, or a blank one. */
140
+ export declare function assemblyFormDraft(initial: AssemblyFormInitial | null, exponent?: number): AssemblyFormDraft;
141
+ /**
142
+ * `values` with every field in `protectedFields` replaced by its initial
143
+ * value, exactly as stored (not trimmed or re-split), or its default for a
144
+ * new assembly. A hidden or read-only field is never rewritten by the form.
145
+ */
146
+ export declare function keepProtectedFields(values: AssemblyFormValues, initial: AssemblyFormInitial | null, protectedFields: readonly AssemblyFormField[]): AssemblyFormValues;
147
+ /**
148
+ * Trim a form draft and check it the way the model does: the name is
149
+ * required, the labour estimate is a whole number of minutes of zero or more
150
+ * (empty counts as zero), and the price is an amount of zero or more with at
151
+ * most `exponent` decimals (empty counts as zero; 2 unless the currency says
152
+ * otherwise). Fields in `skip` (hidden or
153
+ * read-only in the form) are not checked.
154
+ */
155
+ export declare function validateAssemblyForm(draft: Readonly<Partial<AssemblyFormDraft>>, skip?: readonly AssemblyFormField[], exponent?: number): AssemblyFormValidation;
59
156
  export type { ComponentKind };
60
157
  /** One row of {@link AssemblyList}. */
61
158
  export interface AssemblyView {
@@ -167,4 +264,89 @@ export declare function splitLabourMinutes(minutes: number): {
167
264
  hours: number;
168
265
  minutes: number;
169
266
  };
267
+ export type { ProductionRunStatus };
268
+ /** One row of `ProductionRunList`. */
269
+ export interface ProductionRunView {
270
+ /** The run id. */
271
+ id: string;
272
+ /** What is being built, as the host names it (an assembly's name, say). */
273
+ label: string;
274
+ /** Units to build. */
275
+ targetQty: number;
276
+ /** Units reported done. */
277
+ completedQty: number;
278
+ /** The run's status. */
279
+ status: ProductionRunStatus;
280
+ }
281
+ /** Adapt a `ProductionRun` to a {@link ProductionRunView}, with the host's label. */
282
+ export declare function toProductionRunView(run: Pick<ProductionRun, 'id' | 'targetQty' | 'completedQty' | 'status'>, label: string): ProductionRunView;
283
+ /** The message key naming a run status in words. */
284
+ export declare function productionRunStatusLabelKey(status: ProductionRunStatus): "manufacturing.production_run_status.planned" | "manufacturing.production_run_status.in_progress" | "manufacturing.production_run_status.done" | "manufacturing.production_run_status.cancelled";
285
+ /** The `StatusBadge` tone for a run status. */
286
+ export declare function productionRunStatusTone(status: ProductionRunStatus): 'neutral' | 'info' | 'success' | 'warning';
287
+ /** `true` while a run can still take completions. */
288
+ export declare function isProductionRunOpen(status: ProductionRunStatus): boolean;
289
+ /** Result of {@link validateCompletionQty}. */
290
+ export type CompletionQtyValidation = {
291
+ ok: true;
292
+ qty: number;
293
+ } | {
294
+ ok: false;
295
+ reason: 'invalid' | 'too_many';
296
+ };
297
+ /**
298
+ * Check a typed completion quantity against what the run has left (the
299
+ * service checks again under its lock).
300
+ */
301
+ export declare function validateCompletionQty(raw: string, run: Pick<ProductionRunView, 'targetQty' | 'completedQty'>): CompletionQtyValidation;
302
+ /** One line of `RequirementsTree`, with the lines of its bill when opened. */
303
+ export interface RequirementLineView {
304
+ /** Unique within the tree: the bills above it plus the line id. */
305
+ key: string;
306
+ /** 1 for the top bill's lines. */
307
+ level: number;
308
+ /** Component name; empty when it cannot be resolved. */
309
+ name: string;
310
+ /** Component SKU code; empty when unknown. */
311
+ skuCode: string;
312
+ /** What the component is. */
313
+ kind: ComponentKind;
314
+ /** Quantity required for the run (net of stock in a plan). */
315
+ required: number;
316
+ /** The line's unit. */
317
+ uom: string;
318
+ /** Unallocated available stock; `null` for a gross explosion. */
319
+ available: number | null;
320
+ /** How much is short; `null` for a gross explosion. */
321
+ short: number | null;
322
+ /** A sub-assembly with an active bill. */
323
+ buildable: boolean;
324
+ /** The lines of this sub-assembly's bill that were walked. */
325
+ children: RequirementLineView[];
326
+ }
327
+ /** One row of the totals table of `RequirementsTree`. */
328
+ export interface RequirementTotalView {
329
+ /** The component SKU. */
330
+ componentSkuId: string;
331
+ /** Component name; empty when it cannot be resolved. */
332
+ name: string;
333
+ /** Component SKU code; empty when unknown. */
334
+ skuCode: string;
335
+ /** Total required, summed over the lines not opened. */
336
+ required: number;
337
+ /** The first line's unit. */
338
+ uom: string;
339
+ /** Total short; `null` for a gross explosion. */
340
+ short: number | null;
341
+ }
342
+ /**
343
+ * Nest the depth-first lines of an {@link Explosion} or a
344
+ * {@link RequirementsPlan} for `RequirementsTree`.
345
+ */
346
+ export declare function toRequirementTree(source: Pick<Explosion | RequirementsPlan, 'lines'>): RequirementLineView[];
347
+ /**
348
+ * The totals of an {@link Explosion} or a {@link RequirementsPlan}: every line
349
+ * not opened, summed per component SKU (first unit kept).
350
+ */
351
+ export declare function toRequirementTotals(source: Pick<Explosion | RequirementsPlan, 'lines'>): RequirementTotalView[];
170
352
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/svelte/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/svelte/types.ts"],"names":[],"mappings":"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"}
@@ -33,6 +33,133 @@ export function validateOperationForm(draft) {
33
33
  },
34
34
  };
35
35
  }
36
+ /**
37
+ * The number of decimal places in a currency's minor unit (2 for USD, 0 for
38
+ * JPY, 3 for KWD), as `Intl` knows it; 2 when the code is not recognized.
39
+ */
40
+ export function currencyExponent(currency) {
41
+ try {
42
+ return (new Intl.NumberFormat('en', {
43
+ style: 'currency',
44
+ currency,
45
+ }).resolvedOptions().maximumFractionDigits ?? 2);
46
+ }
47
+ catch {
48
+ return 2;
49
+ }
50
+ }
51
+ /**
52
+ * Format integer minor units as the major-unit text the price field shows,
53
+ * with `exponent` decimals. A negative value keeps its sign so validation
54
+ * reports it instead of replacing it.
55
+ */
56
+ export function formatPriceInput(minorUnits, exponent = 2) {
57
+ if (!Number.isSafeInteger(minorUnits))
58
+ return formatPriceInput(0, exponent);
59
+ const sign = minorUnits < 0 ? '-' : '';
60
+ const abs = Math.abs(minorUnits);
61
+ if (exponent <= 0)
62
+ return `${sign}${abs}`;
63
+ const scale = 10 ** exponent;
64
+ const whole = Math.floor(abs / scale);
65
+ return `${sign}${whole}.${String(abs - whole * scale).padStart(exponent, '0')}`;
66
+ }
67
+ /** The draft `AssemblyForm` starts from for an assembly, or a blank one. */
68
+ export function assemblyFormDraft(initial, exponent = 2) {
69
+ return {
70
+ name: initial?.name ?? '',
71
+ description: initial?.description ?? '',
72
+ category: initial?.category ?? '',
73
+ partReference: initial?.partReference ?? '',
74
+ price: formatPriceInput(initial?.price ?? 0, exponent),
75
+ estimatedLabourMinutes: String(initial?.estimatedLabourMinutes ?? 0),
76
+ defaultOperationId: initial?.defaultOperationId ?? '',
77
+ tags: (initial?.tags ?? []).join(', '),
78
+ };
79
+ }
80
+ /**
81
+ * `values` with every field in `protectedFields` replaced by its initial
82
+ * value, exactly as stored (not trimmed or re-split), or its default for a
83
+ * new assembly. A hidden or read-only field is never rewritten by the form.
84
+ */
85
+ export function keepProtectedFields(values, initial, protectedFields) {
86
+ const kept = { ...values };
87
+ const original = {
88
+ name: initial?.name ?? '',
89
+ description: initial?.description ?? '',
90
+ category: initial?.category ?? '',
91
+ partReference: initial?.partReference ?? '',
92
+ price: initial?.price ?? 0,
93
+ estimatedLabourMinutes: initial?.estimatedLabourMinutes ?? 0,
94
+ defaultOperationId: initial?.defaultOperationId ?? null,
95
+ tags: [...(initial?.tags ?? [])],
96
+ };
97
+ for (const field of protectedFields) {
98
+ kept[field] = original[field];
99
+ }
100
+ return kept;
101
+ }
102
+ function parseTags(raw) {
103
+ const tags = [];
104
+ for (const part of raw.split(',')) {
105
+ const tag = part.trim();
106
+ if (tag && !tags.includes(tag))
107
+ tags.push(tag);
108
+ }
109
+ return tags;
110
+ }
111
+ /**
112
+ * Trim a form draft and check it the way the model does: the name is
113
+ * required, the labour estimate is a whole number of minutes of zero or more
114
+ * (empty counts as zero), and the price is an amount of zero or more with at
115
+ * most `exponent` decimals (empty counts as zero; 2 unless the currency says
116
+ * otherwise). Fields in `skip` (hidden or
117
+ * read-only in the form) are not checked.
118
+ */
119
+ export function validateAssemblyForm(draft, skip = [], exponent = 2) {
120
+ const invalid = [];
121
+ const name = textOf(draft.name);
122
+ const minutesText = textOf(draft.estimatedLabourMinutes);
123
+ const priceText = textOf(draft.price);
124
+ let estimatedLabourMinutes = 0;
125
+ if (minutesText !== '') {
126
+ estimatedLabourMinutes = /^\d+$/.test(minutesText)
127
+ ? Number(minutesText)
128
+ : Number.NaN;
129
+ }
130
+ let price = 0;
131
+ if (priceText !== '') {
132
+ const match = new RegExp(exponent > 0 ? `^(\\d+)(?:\\.(\\d{1,${exponent}}))?$` : '^(\\d+)$').exec(priceText);
133
+ price = match
134
+ ? Number(match[1]) * 10 ** exponent +
135
+ Number((match[2] ?? '').padEnd(exponent, '0') || 0)
136
+ : Number.NaN;
137
+ }
138
+ if (!name && !skip.includes('name'))
139
+ invalid.push('name');
140
+ if (!Number.isSafeInteger(price) && !skip.includes('price'))
141
+ invalid.push('price');
142
+ if (!Number.isSafeInteger(estimatedLabourMinutes) &&
143
+ !skip.includes('estimatedLabourMinutes'))
144
+ invalid.push('estimatedLabourMinutes');
145
+ if (invalid.length > 0)
146
+ return { ok: false, invalid };
147
+ return {
148
+ ok: true,
149
+ values: {
150
+ name,
151
+ description: textOf(draft.description),
152
+ category: textOf(draft.category),
153
+ partReference: textOf(draft.partReference),
154
+ price: Number.isSafeInteger(price) ? price : 0,
155
+ estimatedLabourMinutes: Number.isSafeInteger(estimatedLabourMinutes)
156
+ ? estimatedLabourMinutes
157
+ : 0,
158
+ defaultOperationId: textOf(draft.defaultOperationId) || null,
159
+ tags: parseTags(draft.tags ?? ''),
160
+ },
161
+ };
162
+ }
36
163
  /**
37
164
  * Build an {@link AssemblyView} from an `Assembly` plus the facts the list
38
165
  * shows that live on its neighbours: its SKU codes and its active bill.
@@ -124,3 +251,126 @@ export function splitLabourMinutes(minutes) {
124
251
  const whole = Math.max(0, Math.round(minutes));
125
252
  return { hours: Math.floor(whole / 60), minutes: whole % 60 };
126
253
  }
254
+ /** Adapt a `ProductionRun` to a {@link ProductionRunView}, with the host's label. */
255
+ export function toProductionRunView(run, label) {
256
+ return {
257
+ id: run.id,
258
+ label,
259
+ targetQty: Number(run.targetQty),
260
+ completedQty: Number(run.completedQty),
261
+ status: run.status,
262
+ };
263
+ }
264
+ /** The message key naming a run status in words. */
265
+ export function productionRunStatusLabelKey(status) {
266
+ switch (status) {
267
+ case 'planned':
268
+ return M['manufacturing.production_run_status.planned'];
269
+ case 'in_progress':
270
+ return M['manufacturing.production_run_status.in_progress'];
271
+ case 'done':
272
+ return M['manufacturing.production_run_status.done'];
273
+ default:
274
+ return M['manufacturing.production_run_status.cancelled'];
275
+ }
276
+ }
277
+ /** The `StatusBadge` tone for a run status. */
278
+ export function productionRunStatusTone(status) {
279
+ switch (status) {
280
+ case 'in_progress':
281
+ return 'info';
282
+ case 'done':
283
+ return 'success';
284
+ case 'cancelled':
285
+ return 'warning';
286
+ default:
287
+ return 'neutral';
288
+ }
289
+ }
290
+ /** `true` while a run can still take completions. */
291
+ export function isProductionRunOpen(status) {
292
+ return status === 'planned' || status === 'in_progress';
293
+ }
294
+ /**
295
+ * Check a typed completion quantity against what the run has left (the
296
+ * service checks again under its lock).
297
+ */
298
+ export function validateCompletionQty(raw, run) {
299
+ const text = raw.trim();
300
+ const qty = text === '' ? Number.NaN : Number(text);
301
+ if (!Number.isFinite(qty) || qty <= 0)
302
+ return { ok: false, reason: 'invalid' };
303
+ // Whole millionths compared exactly, as ProductionRunService does
304
+ // (QUANTITY_DECIMALS = 6, MAX_QUANTITY = 999,999,999).
305
+ const millionths = (value) => Number(value.toFixed(6).replace('.', ''));
306
+ const rounded = Number(qty.toFixed(6));
307
+ if (rounded <= 0 || rounded > 999_999_999)
308
+ return { ok: false, reason: 'invalid' };
309
+ const remaining = millionths(run.targetQty) - millionths(run.completedQty);
310
+ if (millionths(rounded) > remaining)
311
+ return { ok: false, reason: 'too_many' };
312
+ return { ok: true, qty: rounded };
313
+ }
314
+ function isPlanned(line) {
315
+ return 'short' in line;
316
+ }
317
+ /**
318
+ * Nest the depth-first lines of an {@link Explosion} or a
319
+ * {@link RequirementsPlan} for `RequirementsTree`.
320
+ */
321
+ export function toRequirementTree(source) {
322
+ const roots = [];
323
+ const open = [];
324
+ for (const line of source.lines) {
325
+ const view = {
326
+ key: [...line.path.map((entry) => entry.bomId), line.lineId].join('/'),
327
+ level: line.level,
328
+ name: line.name,
329
+ skuCode: line.skuCode,
330
+ kind: line.kind,
331
+ required: line.totalQty,
332
+ uom: line.uom,
333
+ available: isPlanned(line) ? line.available : null,
334
+ short: isPlanned(line) ? line.short : null,
335
+ buildable: line.buildable,
336
+ children: [],
337
+ };
338
+ open.length = Math.min(open.length, line.level - 1);
339
+ const parent = open[line.level - 2];
340
+ if (line.level > 1 && parent)
341
+ parent.children.push(view);
342
+ else
343
+ roots.push(view);
344
+ open[line.level - 1] = view;
345
+ }
346
+ return roots;
347
+ }
348
+ /**
349
+ * The totals of an {@link Explosion} or a {@link RequirementsPlan}: every line
350
+ * not opened, summed per component SKU (first unit kept).
351
+ */
352
+ export function toRequirementTotals(source) {
353
+ const totals = new Map();
354
+ for (const line of source.lines) {
355
+ if (line.expanded)
356
+ continue;
357
+ const short = isPlanned(line) ? line.short : null;
358
+ const existing = totals.get(line.componentSkuId);
359
+ if (existing) {
360
+ existing.required += line.totalQty;
361
+ if (existing.short !== null && short !== null)
362
+ existing.short += short;
363
+ }
364
+ else {
365
+ totals.set(line.componentSkuId, {
366
+ componentSkuId: line.componentSkuId,
367
+ name: line.name,
368
+ skuCode: line.skuCode,
369
+ required: line.totalQty,
370
+ uom: line.uom,
371
+ short,
372
+ });
373
+ }
374
+ }
375
+ return Array.from(totals.values());
376
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Reading a structure in its owner's tenant: the owner's rows and global
3
+ * ones, whatever tenant context is active.
4
+ *
5
+ * Under a tenant context the tenancy interceptor narrows every read to that
6
+ * tenant, which hides global rows (a shared material, a global bill, global
7
+ * stock); without a context it narrows nothing, which shows every tenant's
8
+ * rows. Neither is a bill's structure. {@link readOwnAndGlobal} runs list
9
+ * reads through `withTenantGlobalRead` (tenant rows plus global rows, refused
10
+ * for a tenant the active context may not read), and callers keep
11
+ * {@link isOwnOrGlobal} rows, which also covers tenancy being disabled.
12
+ *
13
+ * @packageDocumentation
14
+ */
15
+ /**
16
+ * Run `read` so its list reads return `owner`'s rows and global ones. For a
17
+ * global owner (`null`), reads see the active tenant's rows and global ones,
18
+ * and callers keep the global rows.
19
+ */
20
+ export declare function readOwnAndGlobal<T>(owner: string | null, read: () => Promise<T>): Promise<T>;
21
+ /** `true` for a global row or one of `owner`'s rows. */
22
+ export declare function isOwnOrGlobal(row: {
23
+ tenantId?: string | null;
24
+ }, owner: string | null): boolean;
25
+ //# sourceMappingURL=tenant-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant-scope.d.ts","sourceRoot":"","sources":["../src/tenant-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAOH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,EAChC,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GACrB,OAAO,CAAC,CAAC,CAAC,CAGZ;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAC3B,GAAG,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,EACjC,KAAK,EAAE,MAAM,GAAG,IAAI,GACnB,OAAO,CAGT"}