@seedtactics/insight-client 16.4.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.
- package/README.md +37 -0
- package/dist/cell-status/buffers.d.ts +36 -0
- package/dist/cell-status/buffers.js +127 -0
- package/dist/cell-status/current-status.d.ts +30 -0
- package/dist/cell-status/current-status.js +200 -0
- package/dist/cell-status/estimated-cycle-times.d.ts +41 -0
- package/dist/cell-status/estimated-cycle-times.js +257 -0
- package/dist/cell-status/inspections.d.ts +55 -0
- package/dist/cell-status/inspections.js +213 -0
- package/dist/cell-status/loading.d.ts +26 -0
- package/dist/cell-status/loading.js +112 -0
- package/dist/cell-status/material-details.d.ts +116 -0
- package/dist/cell-status/material-details.js +422 -0
- package/dist/cell-status/material-summary.d.ts +52 -0
- package/dist/cell-status/material-summary.js +312 -0
- package/dist/cell-status/names.d.ts +19 -0
- package/dist/cell-status/names.js +134 -0
- package/dist/cell-status/pallet-cycles.d.ts +24 -0
- package/dist/cell-status/pallet-cycles.js +78 -0
- package/dist/cell-status/rebookings.d.ts +30 -0
- package/dist/cell-status/rebookings.js +139 -0
- package/dist/cell-status/scheduled-jobs.d.ts +18 -0
- package/dist/cell-status/scheduled-jobs.js +94 -0
- package/dist/cell-status/sim-day-usage.d.ts +14 -0
- package/dist/cell-status/sim-day-usage.js +54 -0
- package/dist/cell-status/sim-production.d.ts +22 -0
- package/dist/cell-status/sim-production.js +91 -0
- package/dist/cell-status/sim-station-use.d.ts +25 -0
- package/dist/cell-status/sim-station-use.js +71 -0
- package/dist/cell-status/station-cycles.d.ts +34 -0
- package/dist/cell-status/station-cycles.js +145 -0
- package/dist/cell-status/tool-replacements.d.ts +44 -0
- package/dist/cell-status/tool-replacements.js +155 -0
- package/dist/cell-status/tool-usage.d.ts +25 -0
- package/dist/cell-status/tool-usage.js +95 -0
- package/dist/components/App.d.ts +15 -0
- package/dist/components/App.js +549 -0
- package/dist/components/AxisAndGrid.d.ts +51 -0
- package/dist/components/AxisAndGrid.js +47 -0
- package/dist/components/BarcodeScanning.d.ts +6 -0
- package/dist/components/BarcodeScanning.js +150 -0
- package/dist/components/ChartTooltip.d.ts +28 -0
- package/dist/components/ChartTooltip.js +95 -0
- package/dist/components/ChooseMode.d.ts +18 -0
- package/dist/components/ChooseMode.js +136 -0
- package/dist/components/ChooseOperator.d.ts +1 -0
- package/dist/components/ChooseOperator.js +93 -0
- package/dist/components/ErrorsAndLoading.d.ts +9 -0
- package/dist/components/ErrorsAndLoading.js +55 -0
- package/dist/components/LoadingIcon.d.ts +1 -0
- package/dist/components/LoadingIcon.js +48 -0
- package/dist/components/LogEntry.d.ts +16 -0
- package/dist/components/LogEntry.js +365 -0
- package/dist/components/ManualSerialEntry.d.ts +5 -0
- package/dist/components/ManualSerialEntry.js +91 -0
- package/dist/components/MonthSelect.d.ts +6 -0
- package/dist/components/MonthSelect.js +67 -0
- package/dist/components/Navigation.d.ts +23 -0
- package/dist/components/Navigation.js +120 -0
- package/dist/components/VerboseLogging.d.ts +1 -0
- package/dist/components/VerboseLogging.js +47 -0
- package/dist/components/analysis/AnalysisSelectToolbar.d.ts +1 -0
- package/dist/components/analysis/AnalysisSelectToolbar.js +55 -0
- package/dist/components/analysis/BufferChart.d.ts +1 -0
- package/dist/components/analysis/BufferChart.js +139 -0
- package/dist/components/analysis/CostPerPiece.d.ts +2 -0
- package/dist/components/analysis/CostPerPiece.js +175 -0
- package/dist/components/analysis/CycleChart.d.ts +42 -0
- package/dist/components/analysis/CycleChart.js +281 -0
- package/dist/components/analysis/DataTable.d.ts +83 -0
- package/dist/components/analysis/DataTable.js +215 -0
- package/dist/components/analysis/EfficiencyPage.d.ts +2 -0
- package/dist/components/analysis/EfficiencyPage.js +138 -0
- package/dist/components/analysis/HeatChart.d.ts +22 -0
- package/dist/components/analysis/HeatChart.js +161 -0
- package/dist/components/analysis/InspectionDataTable.d.ts +10 -0
- package/dist/components/analysis/InspectionDataTable.js +148 -0
- package/dist/components/analysis/InspectionSankey.d.ts +12 -0
- package/dist/components/analysis/InspectionSankey.js +140 -0
- package/dist/components/analysis/PalletCycleCards.d.ts +1 -0
- package/dist/components/analysis/PalletCycleCards.js +137 -0
- package/dist/components/analysis/PartCycleCards.d.ts +2 -0
- package/dist/components/analysis/PartCycleCards.js +331 -0
- package/dist/components/analysis/QualityPage.d.ts +1 -0
- package/dist/components/analysis/QualityPage.js +49 -0
- package/dist/components/analysis/ScheduleHistory.d.ts +3 -0
- package/dist/components/analysis/ScheduleHistory.js +108 -0
- package/dist/components/analysis/StationDataTable.d.ts +25 -0
- package/dist/components/analysis/StationDataTable.js +246 -0
- package/dist/components/analysis/ToolReplacements.d.ts +1 -0
- package/dist/components/analysis/ToolReplacements.js +370 -0
- package/dist/components/operations/AllMaterial.d.ts +5 -0
- package/dist/components/operations/AllMaterial.js +267 -0
- package/dist/components/operations/ChartRangeEdit.d.ts +4 -0
- package/dist/components/operations/ChartRangeEdit.js +148 -0
- package/dist/components/operations/CloseoutReport.d.ts +2 -0
- package/dist/components/operations/CloseoutReport.js +172 -0
- package/dist/components/operations/CompletedParts.d.ts +2 -0
- package/dist/components/operations/CompletedParts.js +286 -0
- package/dist/components/operations/CurrentWorkorders.d.ts +3 -0
- package/dist/components/operations/CurrentWorkorders.js +368 -0
- package/dist/components/operations/Dashboard.d.ts +2 -0
- package/dist/components/operations/Dashboard.js +90 -0
- package/dist/components/operations/OEEChart.d.ts +10 -0
- package/dist/components/operations/OEEChart.js +173 -0
- package/dist/components/operations/Outliers.d.ts +4 -0
- package/dist/components/operations/Outliers.js +69 -0
- package/dist/components/operations/ProgramHighlight.d.ts +1 -0
- package/dist/components/operations/ProgramHighlight.js +9 -0
- package/dist/components/operations/Programs.d.ts +5 -0
- package/dist/components/operations/Programs.js +363 -0
- package/dist/components/operations/Rebookings.d.ts +1 -0
- package/dist/components/operations/Rebookings.js +213 -0
- package/dist/components/operations/RecentCycleChart.d.ts +4 -0
- package/dist/components/operations/RecentCycleChart.js +240 -0
- package/dist/components/operations/RecentProduction.d.ts +2 -0
- package/dist/components/operations/RecentProduction.js +213 -0
- package/dist/components/operations/RecentSchedules.d.ts +12 -0
- package/dist/components/operations/RecentSchedules.js +180 -0
- package/dist/components/operations/RecentStationCycles.d.ts +4 -0
- package/dist/components/operations/RecentStationCycles.js +159 -0
- package/dist/components/operations/ShiftSettings.d.ts +6 -0
- package/dist/components/operations/ShiftSettings.js +134 -0
- package/dist/components/operations/SimDayUsage.d.ts +1 -0
- package/dist/components/operations/SimDayUsage.js +133 -0
- package/dist/components/operations/ToolReport.d.ts +3 -0
- package/dist/components/operations/ToolReport.js +233 -0
- package/dist/components/operations/WorkorderGantt.d.ts +1 -0
- package/dist/components/operations/WorkorderGantt.js +124 -0
- package/dist/components/quality/QualityMaterial.d.ts +2 -0
- package/dist/components/quality/QualityMaterial.js +169 -0
- package/dist/components/quality/QualityPaths.d.ts +1 -0
- package/dist/components/quality/QualityPaths.js +53 -0
- package/dist/components/quality/RecentFailedInspections.d.ts +1 -0
- package/dist/components/quality/RecentFailedInspections.js +123 -0
- package/dist/components/routes.d.ts +170 -0
- package/dist/components/routes.js +301 -0
- package/dist/components/station-monitor/BulkRawMaterial.d.ts +11 -0
- package/dist/components/station-monitor/BulkRawMaterial.js +251 -0
- package/dist/components/station-monitor/Closeout.d.ts +5 -0
- package/dist/components/station-monitor/Closeout.js +162 -0
- package/dist/components/station-monitor/CustomStationMonitorDialog.d.ts +1 -0
- package/dist/components/station-monitor/CustomStationMonitorDialog.js +55 -0
- package/dist/components/station-monitor/Inspection.d.ts +8 -0
- package/dist/components/station-monitor/Inspection.js +164 -0
- package/dist/components/station-monitor/InvalidateCycle.d.ts +33 -0
- package/dist/components/station-monitor/InvalidateCycle.js +262 -0
- package/dist/components/station-monitor/JobDetails.d.ts +7 -0
- package/dist/components/station-monitor/JobDetails.js +108 -0
- package/dist/components/station-monitor/LoadStation.d.ts +10 -0
- package/dist/components/station-monitor/LoadStation.js +450 -0
- package/dist/components/station-monitor/Material.d.ts +77 -0
- package/dist/components/station-monitor/Material.js +489 -0
- package/dist/components/station-monitor/MoveMaterialArrows.d.ts +11 -0
- package/dist/components/station-monitor/MoveMaterialArrows.js +118 -0
- package/dist/components/station-monitor/PrintedLabel.d.ts +29 -0
- package/dist/components/station-monitor/PrintedLabel.js +166 -0
- package/dist/components/station-monitor/QuarantineButton.d.ts +4 -0
- package/dist/components/station-monitor/QuarantineButton.js +184 -0
- package/dist/components/station-monitor/Queues.d.ts +23 -0
- package/dist/components/station-monitor/Queues.js +312 -0
- package/dist/components/station-monitor/QueuesAddMaterial.d.ts +30 -0
- package/dist/components/station-monitor/QueuesAddMaterial.js +248 -0
- package/dist/components/station-monitor/SelectInspType.d.ts +2 -0
- package/dist/components/station-monitor/SelectInspType.js +99 -0
- package/dist/components/station-monitor/SelectWorkorder.d.ts +4 -0
- package/dist/components/station-monitor/SelectWorkorder.js +100 -0
- package/dist/components/station-monitor/StationToolbar.d.ts +3 -0
- package/dist/components/station-monitor/StationToolbar.js +168 -0
- package/dist/components/station-monitor/SystemOverview.d.ts +46 -0
- package/dist/components/station-monitor/SystemOverview.js +439 -0
- package/dist/components/station-monitor/Whiteboard.d.ts +10 -0
- package/dist/components/station-monitor/Whiteboard.js +67 -0
- package/dist/data/all-material-bins.d.ts +45 -0
- package/dist/data/all-material-bins.js +224 -0
- package/dist/data/chart-times.d.ts +20 -0
- package/dist/data/chart-times.js +99 -0
- package/dist/data/cost-per-piece.d.ts +32 -0
- package/dist/data/cost-per-piece.js +183 -0
- package/dist/data/current-cycles.d.ts +13 -0
- package/dist/data/current-cycles.js +144 -0
- package/dist/data/inspection-sankey.d.ts +15 -0
- package/dist/data/inspection-sankey.js +147 -0
- package/dist/data/move-arrows.d.ts +48 -0
- package/dist/data/move-arrows.js +217 -0
- package/dist/data/operators.d.ts +2 -0
- package/dist/data/operators.js +44 -0
- package/dist/data/part-summary.d.ts +17 -0
- package/dist/data/part-summary.js +107 -0
- package/dist/data/path-lookup.d.ts +13 -0
- package/dist/data/path-lookup.js +107 -0
- package/dist/data/queue-material.d.ts +46 -0
- package/dist/data/queue-material.js +256 -0
- package/dist/data/results.bufferchart.d.ts +10 -0
- package/dist/data/results.bufferchart.js +90 -0
- package/dist/data/results.completed-parts.d.ts +26 -0
- package/dist/data/results.completed-parts.js +181 -0
- package/dist/data/results.cycles.d.ts +86 -0
- package/dist/data/results.cycles.js +454 -0
- package/dist/data/results.inspection.d.ts +36 -0
- package/dist/data/results.inspection.js +188 -0
- package/dist/data/results.oee.d.ts +40 -0
- package/dist/data/results.oee.js +330 -0
- package/dist/data/results.schedules.d.ts +23 -0
- package/dist/data/results.schedules.js +157 -0
- package/dist/data/tools-programs.d.ts +78 -0
- package/dist/data/tools-programs.js +376 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -0
- package/dist/network/api.d.ts +1390 -0
- package/dist/network/api.js +4971 -0
- package/dist/network/backend-mock.d.ts +11 -0
- package/dist/network/backend-mock.js +512 -0
- package/dist/network/backend.d.ts +57 -0
- package/dist/network/backend.js +77 -0
- package/dist/network/load-specific-month.d.ts +13 -0
- package/dist/network/load-specific-month.js +77 -0
- package/dist/network/server-settings.d.ts +12 -0
- package/dist/network/server-settings.js +92 -0
- package/dist/network/websocket.d.ts +4 -0
- package/dist/network/websocket.js +165 -0
- package/dist/renderer.d.ts +8 -0
- package/dist/renderer.js +55 -0
- package/dist/seedtactics-logo.d.ts +2 -0
- package/dist/seedtactics-logo.js +4 -0
- package/dist/util/chart-colors.d.ts +1 -0
- package/dist/util/chart-colors.js +116 -0
- package/dist/util/chart-helpers.d.ts +3 -0
- package/dist/util/chart-helpers.js +51 -0
- package/dist/util/parseISODuration.d.ts +4 -0
- package/dist/util/parseISODuration.js +40 -0
- package/docs/client-efficiency.md +355 -0
- package/docs/client-engineering.md +54 -0
- package/docs/client-launch.md +55 -0
- package/docs/client-operations.md +88 -0
- package/docs/client-quality.md +74 -0
- package/docs/client-sales.md +61 -0
- package/docs/client-scanners.md +41 -0
- package/docs/client-station-monitor.md +149 -0
- package/docs/client-tools-programs.md +74 -0
- package/docs/improve-fms.md +141 -0
- package/docs/makino.md +40 -0
- package/docs/material-quarantine.md +82 -0
- package/docs/material-tracking.md +236 -0
- package/docs/mazak.md +115 -0
- package/docs/niigata.md +228 -0
- package/docs/operator-procedures.md +106 -0
- package/docs/part-instructions.md +63 -0
- package/docs/screenshots/insight-all-material.png +0 -0
- package/docs/screenshots/insight-analysis-pallets.png +0 -0
- package/docs/screenshots/insight-analysis-part-completed.png +0 -0
- package/docs/screenshots/insight-analysis-sankey.png +0 -0
- package/docs/screenshots/insight-analysis-station-oee.png +0 -0
- package/docs/screenshots/insight-buffer-occupancy.png +0 -0
- package/docs/screenshots/insight-choose-analysis-month.png +0 -0
- package/docs/screenshots/insight-closeout.png +0 -0
- package/docs/screenshots/insight-cost-percentages.png +0 -0
- package/docs/screenshots/insight-dashboard.png +0 -0
- package/docs/screenshots/insight-event-custom-view.jpg +0 -0
- package/docs/screenshots/insight-event-viewer.jpg +0 -0
- package/docs/screenshots/insight-inspection.png +0 -0
- package/docs/screenshots/insight-load-station-details.png +0 -0
- package/docs/screenshots/insight-load-station.png +0 -0
- package/docs/screenshots/insight-loadcycle-graph.png +0 -0
- package/docs/screenshots/insight-loadstation-small.jpg +0 -0
- package/docs/screenshots/insight-machinecycle-graph.png +0 -0
- package/docs/screenshots/insight-machinecycle-table.png +0 -0
- package/docs/screenshots/insight-machinecycles.png +0 -0
- package/docs/screenshots/insight-machinehours.png +0 -0
- package/docs/screenshots/insight-machineoutliers.png +0 -0
- package/docs/screenshots/insight-monthly-schedules.png +0 -0
- package/docs/screenshots/insight-operations-material.png +0 -0
- package/docs/screenshots/insight-operations-overview.png +0 -0
- package/docs/screenshots/insight-operations-reports.png +0 -0
- package/docs/screenshots/insight-part-cost.png +0 -0
- package/docs/screenshots/insight-program-report.png +0 -0
- package/docs/screenshots/insight-quality-material-details.png +0 -0
- package/docs/screenshots/insight-quality-material.png +0 -0
- package/docs/screenshots/insight-quality-quarantine.png +0 -0
- package/docs/screenshots/insight-quality-sankey.png +0 -0
- package/docs/screenshots/insight-quality-similar-paths.png +0 -0
- package/docs/screenshots/insight-queue-details.png +0 -0
- package/docs/screenshots/insight-queues-jobs-table.png +0 -0
- package/docs/screenshots/insight-queues.png +0 -0
- package/docs/screenshots/insight-sim-day-usage.png +0 -0
- package/docs/screenshots/insight-station-system-overview-buttons.png +0 -0
- package/docs/screenshots/insight-station-system-overview.png +0 -0
- package/docs/screenshots/insight-system-overview.png +0 -0
- package/docs/screenshots/insight-tool-replacements.png +0 -0
- package/docs/screenshots/insight-tool-report.png +0 -0
- package/docs/screenshots/insight-toolbar-btns.png +0 -0
- package/docs/screenshots/insight-workorder-gantt.png +0 -0
- package/docs/screenshots/insight-workorders.png +0 -0
- package/docs/security.md +131 -0
- package/docs/server-config.md +56 -0
- package/docs/server-errors.md +44 -0
- package/package.json +90 -0
- package/src/index.ts +65 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/* Copyright (c) 2019, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import * as api from "../network/api.js";
|
|
34
|
+
import { LazySeq } from "@seedtactics/immutable-collections";
|
|
35
|
+
import { atomWithStorage } from "jotai/utils";
|
|
36
|
+
export const LoadStationBinId = "__FMS_INSIGHT_LOAD_STATION_BIN__";
|
|
37
|
+
export const PalletsBinId = "__FMS_INSIGHT_PALLETS_BIN__";
|
|
38
|
+
export const ActiveQueuesBinId = "__FMS_INSIGHT_ACTIVE_QUEUE_BIN__";
|
|
39
|
+
export const currentMaterialBinOrder = atomWithStorage("material-bins", []);
|
|
40
|
+
export function moveMaterialBin(curBinOrder, oldIdx, newIdx) {
|
|
41
|
+
const newBinOrder = Array.from(curBinOrder);
|
|
42
|
+
const [removed] = newBinOrder.splice(oldIdx, 1);
|
|
43
|
+
newBinOrder.splice(newIdx, 0, removed);
|
|
44
|
+
return newBinOrder;
|
|
45
|
+
}
|
|
46
|
+
function addToMap(m, k, mat) {
|
|
47
|
+
const mats = m.get(k);
|
|
48
|
+
if (mats) {
|
|
49
|
+
mats.push(mat);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
m.set(k, [mat]);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export var MaterialBinType;
|
|
56
|
+
(function (MaterialBinType) {
|
|
57
|
+
MaterialBinType["LoadStations"] = "Bin_LoadStations";
|
|
58
|
+
MaterialBinType["Pallets"] = "Bin_Pallets";
|
|
59
|
+
MaterialBinType["ActiveQueues"] = "Bin_ActiveQueues";
|
|
60
|
+
MaterialBinType["QuarantineQueues"] = "Bin_Quarantine";
|
|
61
|
+
})(MaterialBinType || (MaterialBinType = {}));
|
|
62
|
+
export function selectAllMaterialIntoBins(curSt, curBinOrder) {
|
|
63
|
+
const loadStations = new Map();
|
|
64
|
+
const pallets = new Map();
|
|
65
|
+
const queues = new Map();
|
|
66
|
+
const palLoc = LazySeq.ofObject(curSt.pallets).toRMap(([, st]) => [
|
|
67
|
+
st.palletNum,
|
|
68
|
+
st.palletNum.toString() +
|
|
69
|
+
" (" +
|
|
70
|
+
st.currentPalletLocation.group +
|
|
71
|
+
" #" +
|
|
72
|
+
st.currentPalletLocation.num.toString() +
|
|
73
|
+
")",
|
|
74
|
+
]);
|
|
75
|
+
for (const mat of curSt.material) {
|
|
76
|
+
switch (mat.location.type) {
|
|
77
|
+
case api.LocType.InQueue:
|
|
78
|
+
if (mat.action.type === api.ActionType.Loading) {
|
|
79
|
+
const pal = curSt.pallets[mat.action.loadOntoPalletNum ?? 0];
|
|
80
|
+
if (pal && pal.currentPalletLocation.loc === api.PalletLocationEnum.LoadUnload) {
|
|
81
|
+
const lul = pal.currentPalletLocation.num;
|
|
82
|
+
addToMap(loadStations, lul, mat);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
addToMap(queues, mat.location.currentQueue || "Queue", mat);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
addToMap(queues, mat.location.currentQueue || "Queue", mat);
|
|
90
|
+
}
|
|
91
|
+
break;
|
|
92
|
+
case api.LocType.OnPallet:
|
|
93
|
+
if (mat.location.palletNum) {
|
|
94
|
+
const palSt = curSt.pallets[mat.location.palletNum];
|
|
95
|
+
if (palSt.currentPalletLocation.loc === api.PalletLocationEnum.LoadUnload) {
|
|
96
|
+
addToMap(loadStations, palSt.currentPalletLocation.num, mat);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
addToMap(pallets, palLoc.get(mat.location.palletNum) ?? "", mat);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
addToMap(pallets, "Pallet", mat);
|
|
104
|
+
}
|
|
105
|
+
break;
|
|
106
|
+
case api.LocType.Free:
|
|
107
|
+
switch (mat.action.type) {
|
|
108
|
+
case api.ActionType.Loading: {
|
|
109
|
+
const lul = curSt.pallets[mat.action.loadOntoPalletNum ?? 0]?.currentPalletLocation.num;
|
|
110
|
+
addToMap(loadStations, lul, mat);
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
default:
|
|
114
|
+
addToMap(queues, "Free Material", mat);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const activeQueues = LazySeq.ofObject(curSt.jobs)
|
|
121
|
+
.flatMap(([_, job]) => job.procsAndPaths)
|
|
122
|
+
.flatMap((proc) => proc.paths)
|
|
123
|
+
.flatMap((path) => {
|
|
124
|
+
const q = [];
|
|
125
|
+
if (path.inputQueue !== undefined)
|
|
126
|
+
q.push(path.inputQueue);
|
|
127
|
+
if (path.outputQueue !== undefined)
|
|
128
|
+
q.push(path.outputQueue);
|
|
129
|
+
return q;
|
|
130
|
+
})
|
|
131
|
+
.concat(LazySeq.ofObject(curSt.queues)
|
|
132
|
+
.filter(([, info]) => info.role === api.QueueRole.RawMaterial || info.role === api.QueueRole.InProcessTransfer)
|
|
133
|
+
.map(([qname, _]) => qname))
|
|
134
|
+
.toRSet((x) => x);
|
|
135
|
+
const quarantineQueues = LazySeq.ofObject(curSt.queues)
|
|
136
|
+
.filter(([qname, _]) => !activeQueues.has(qname))
|
|
137
|
+
.toRSet(([qname, _]) => qname);
|
|
138
|
+
const bins = curBinOrder.filter((b) => b === LoadStationBinId || b === PalletsBinId || b === ActiveQueuesBinId || quarantineQueues.has(b));
|
|
139
|
+
if (bins.indexOf(ActiveQueuesBinId) < 0) {
|
|
140
|
+
bins.unshift(ActiveQueuesBinId);
|
|
141
|
+
}
|
|
142
|
+
if (bins.indexOf(PalletsBinId) < 0) {
|
|
143
|
+
bins.unshift(PalletsBinId);
|
|
144
|
+
}
|
|
145
|
+
if (bins.indexOf(LoadStationBinId) < 0) {
|
|
146
|
+
bins.unshift(LoadStationBinId);
|
|
147
|
+
}
|
|
148
|
+
for (const queue of LazySeq.of(quarantineQueues).sortBy((x) => x)) {
|
|
149
|
+
if (bins.indexOf(queue) < 0) {
|
|
150
|
+
bins.push(queue);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return bins.map((binId) => {
|
|
154
|
+
if (binId === LoadStationBinId) {
|
|
155
|
+
return { type: MaterialBinType.LoadStations, binId: LoadStationBinId, byLul: loadStations };
|
|
156
|
+
}
|
|
157
|
+
else if (binId === PalletsBinId) {
|
|
158
|
+
return { type: MaterialBinType.Pallets, binId: PalletsBinId, byPallet: pallets };
|
|
159
|
+
}
|
|
160
|
+
else if (binId === ActiveQueuesBinId) {
|
|
161
|
+
return {
|
|
162
|
+
type: MaterialBinType.ActiveQueues,
|
|
163
|
+
binId: ActiveQueuesBinId,
|
|
164
|
+
byQueue: LazySeq.of(activeQueues).toRMap((queueName) => {
|
|
165
|
+
const mat = queues.get(queueName) ?? [];
|
|
166
|
+
mat.sort((m1, m2) => (m1.location.queuePosition ?? 0) - (m2.location.queuePosition ?? 0));
|
|
167
|
+
return [queueName, mat];
|
|
168
|
+
}, (ms1, ms2) => ms1.concat(ms2)),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
const queueName = binId;
|
|
173
|
+
const mat = queues.get(queueName) ?? [];
|
|
174
|
+
mat.sort((m1, m2) => (m1.location.queuePosition ?? 0) - (m2.location.queuePosition ?? 0));
|
|
175
|
+
return {
|
|
176
|
+
type: MaterialBinType.QuarantineQueues,
|
|
177
|
+
binId: queueName,
|
|
178
|
+
queueName,
|
|
179
|
+
material: mat,
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
export function moveMaterialInBin(bins, mat, queue, queuePosition) {
|
|
185
|
+
return bins.map((bin) => {
|
|
186
|
+
switch (bin.type) {
|
|
187
|
+
case MaterialBinType.QuarantineQueues:
|
|
188
|
+
if (bin.queueName === queue) {
|
|
189
|
+
const mats = bin.material.filter((m) => m.materialID !== mat.materialID);
|
|
190
|
+
mats.splice(queuePosition, 0, mat);
|
|
191
|
+
return { ...bin, material: mats };
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
return { ...bin, material: bin.material.filter((m) => m.materialID !== mat.materialID) };
|
|
195
|
+
}
|
|
196
|
+
default:
|
|
197
|
+
return bin;
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
export function findMaterialInQuarantineQueues(matId, bins) {
|
|
202
|
+
for (const bin of bins) {
|
|
203
|
+
switch (bin.type) {
|
|
204
|
+
case MaterialBinType.QuarantineQueues:
|
|
205
|
+
for (let i = 0; i < bin.material.length; i++) {
|
|
206
|
+
if (bin.material[i].materialID === matId) {
|
|
207
|
+
return { bin, idx: i };
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
break;
|
|
211
|
+
default:
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
export function findQueueInQuarantineQueues(queue, bins) {
|
|
218
|
+
for (const bin of bins) {
|
|
219
|
+
if (bin.type === MaterialBinType.QuarantineQueues && bin.queueName === queue) {
|
|
220
|
+
return { bin, idx: 0 };
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Atom, WritableAtom } from "jotai";
|
|
2
|
+
export type Last30ChartStart = "StartOfToday" | "StartOfYesterday" | "StartOfWeek" | "StartOfLastWeek" | "Last30";
|
|
3
|
+
export type Last30ChartEnd = "Now" | "EndOfYesterday" | "EndOfLastWeek";
|
|
4
|
+
export declare const last30WeekdayStartIdx: WritableAtom<0 | 2 | 1 | 3 | 4 | 5 | 6, [0 | 2 | 1 | 3 | 4 | 5 | 6 | typeof import("jotai/utils").RESET | ((prev: 0 | 2 | 1 | 3 | 4 | 5 | 6) => 0 | 2 | 1 | 3 | 4 | 5 | 6 | typeof import("jotai/utils").RESET)], void>;
|
|
5
|
+
export declare const last30WeekdayStartMinuteOffset: WritableAtom<number, [number | typeof import("jotai/utils").RESET | ((prev: number) => number | typeof import("jotai/utils").RESET)], void>;
|
|
6
|
+
export declare const last30ChartStartTimes: import("jotai-family").AtomFamily<Last30ChartStart, Atom<Date>>;
|
|
7
|
+
export declare const last30ChartEndTimes: import("jotai-family").AtomFamily<Last30ChartEnd, Atom<Date | null>>;
|
|
8
|
+
export type Last30ChartRangeAtom = WritableAtom<{
|
|
9
|
+
readonly startType: Last30ChartStart | Date;
|
|
10
|
+
readonly endType: Last30ChartEnd | Date;
|
|
11
|
+
readonly startDate: Date | null;
|
|
12
|
+
readonly endDate: Date | null;
|
|
13
|
+
}, [
|
|
14
|
+
{
|
|
15
|
+
start: Last30ChartStart | Date;
|
|
16
|
+
} | {
|
|
17
|
+
end: Last30ChartEnd | Date;
|
|
18
|
+
}
|
|
19
|
+
], void>;
|
|
20
|
+
export declare function chartRangeAtom(chartName: string): Last30ChartRangeAtom;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/* Copyright (c) 2025, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import { addDays, addMinutes, startOfDay, startOfWeek } from "date-fns";
|
|
34
|
+
import { atom } from "jotai";
|
|
35
|
+
import { atomWithStorage } from "jotai/utils";
|
|
36
|
+
import { atomFamily } from "jotai-family";
|
|
37
|
+
const minsSinceEpochAtom = atom(Math.floor(Date.now() / 60_000));
|
|
38
|
+
minsSinceEpochAtom.onMount = (setSelf) => {
|
|
39
|
+
const interval = setInterval(() => {
|
|
40
|
+
setSelf(Math.floor(Date.now() / 60_000));
|
|
41
|
+
}, 60_000);
|
|
42
|
+
return () => clearInterval(interval);
|
|
43
|
+
};
|
|
44
|
+
export const last30WeekdayStartIdx = atomWithStorage("charts_last30WeekdayStartIdx", 0);
|
|
45
|
+
export const last30WeekdayStartMinuteOffset = atomWithStorage("charts_last30WeekdayStartMinuteOffset", 6 * 60);
|
|
46
|
+
export const last30ChartStartTimes = atomFamily((start) => atom((get) => {
|
|
47
|
+
const weekStart = get(last30WeekdayStartIdx);
|
|
48
|
+
const weekStartMins = get(last30WeekdayStartMinuteOffset);
|
|
49
|
+
const now = new Date(get(minsSinceEpochAtom) * 60_000);
|
|
50
|
+
const startOfT = addMinutes(startOfDay(now), weekStartMins);
|
|
51
|
+
const startOfW = addMinutes(startOfWeek(now, { weekStartsOn: weekStart }), weekStartMins);
|
|
52
|
+
switch (start) {
|
|
53
|
+
case "StartOfToday":
|
|
54
|
+
return startOfT;
|
|
55
|
+
case "StartOfYesterday":
|
|
56
|
+
return addDays(startOfT, -1);
|
|
57
|
+
case "StartOfWeek":
|
|
58
|
+
return startOfW;
|
|
59
|
+
case "StartOfLastWeek":
|
|
60
|
+
return addDays(startOfW, -7);
|
|
61
|
+
case "Last30":
|
|
62
|
+
return addDays(now, -30);
|
|
63
|
+
}
|
|
64
|
+
}));
|
|
65
|
+
export const last30ChartEndTimes = atomFamily((cEnd) => atom((get) => {
|
|
66
|
+
if (cEnd === "Now") {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const weekStart = get(last30WeekdayStartIdx);
|
|
70
|
+
const weekStartMins = get(last30WeekdayStartMinuteOffset);
|
|
71
|
+
const now = new Date(get(minsSinceEpochAtom) * 60_000);
|
|
72
|
+
switch (cEnd) {
|
|
73
|
+
case "EndOfYesterday":
|
|
74
|
+
return addMinutes(startOfDay(now), weekStartMins);
|
|
75
|
+
case "EndOfLastWeek":
|
|
76
|
+
return addMinutes(startOfWeek(now, { weekStartsOn: weekStart }), weekStartMins);
|
|
77
|
+
}
|
|
78
|
+
}));
|
|
79
|
+
export function chartRangeAtom(chartName) {
|
|
80
|
+
const startA = atomWithStorage(`charts_${chartName}_start`, "StartOfWeek");
|
|
81
|
+
const endA = atomWithStorage(`charts_${chartName}_end`, "Now");
|
|
82
|
+
return atom((get) => {
|
|
83
|
+
const start = get(startA);
|
|
84
|
+
const end = get(endA);
|
|
85
|
+
return {
|
|
86
|
+
startType: start,
|
|
87
|
+
endType: end,
|
|
88
|
+
startDate: start instanceof Date ? start : get(last30ChartStartTimes(start)),
|
|
89
|
+
endDate: end instanceof Date ? end : get(last30ChartEndTimes(end)),
|
|
90
|
+
};
|
|
91
|
+
}, (_, set, update) => {
|
|
92
|
+
if ("start" in update) {
|
|
93
|
+
set(startA, update.start);
|
|
94
|
+
}
|
|
95
|
+
if ("end" in update) {
|
|
96
|
+
set(endA, update.end);
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { MaterialSummaryAndCompletedData } from "../cell-status/material-summary.js";
|
|
2
|
+
import { PartCycleData } from "../cell-status/station-cycles.js";
|
|
3
|
+
import { HashMap, HashSet, LazySeq, OrderedMap } from "@seedtactics/immutable-collections";
|
|
4
|
+
export interface PartCost {
|
|
5
|
+
readonly part: string;
|
|
6
|
+
readonly parts_completed: number;
|
|
7
|
+
readonly machine: OrderedMap<string, number>;
|
|
8
|
+
readonly labor: number;
|
|
9
|
+
readonly automation: number;
|
|
10
|
+
}
|
|
11
|
+
export type MachineCostPerYear = {
|
|
12
|
+
readonly [stationGroup: string]: number;
|
|
13
|
+
};
|
|
14
|
+
export interface CostData {
|
|
15
|
+
readonly machineQuantities: OrderedMap<string, number>;
|
|
16
|
+
readonly type: {
|
|
17
|
+
month: Date;
|
|
18
|
+
} | {
|
|
19
|
+
thirtyDaysAgo: Date;
|
|
20
|
+
};
|
|
21
|
+
readonly parts: ReadonlyArray<PartCost>;
|
|
22
|
+
}
|
|
23
|
+
export declare function compute_monthly_cost_percentages(cycles: LazySeq<PartCycleData>, partsToIgnore: HashSet<string>, matsById: HashMap<number, MaterialSummaryAndCompletedData>, type: {
|
|
24
|
+
month: Date;
|
|
25
|
+
} | {
|
|
26
|
+
thirtyDaysAgo: Date;
|
|
27
|
+
}): CostData;
|
|
28
|
+
export declare function convert_cost_percent_to_cost_per_piece(costs: CostData, machineCostPerYear: MachineCostPerYear, automationCostPerYear: number | null, totalLaborCostForPeriod: number): CostData;
|
|
29
|
+
export declare function buildCostPerPieceTable(costs: CostData): string;
|
|
30
|
+
export declare function copyCostPerPieceToClipboard(costs: CostData): void;
|
|
31
|
+
export declare function buildCostBreakdownTable(costs: CostData): string;
|
|
32
|
+
export declare function copyCostBreakdownToClipboard(costs: CostData): void;
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/* Copyright (c) 2020, John Lenz
|
|
2
|
+
|
|
3
|
+
All rights reserved.
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
* Redistributions of source code must retain the above copyright
|
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
* Redistributions in binary form must reproduce the above
|
|
12
|
+
copyright notice, this list of conditions and the following
|
|
13
|
+
disclaimer in the documentation and/or other materials provided
|
|
14
|
+
with the distribution.
|
|
15
|
+
|
|
16
|
+
* Neither the name of John Lenz, Black Maple Software, SeedTactics,
|
|
17
|
+
nor the names of other contributors may be used to endorse or
|
|
18
|
+
promote products derived from this software without specific
|
|
19
|
+
prior written permission.
|
|
20
|
+
|
|
21
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
22
|
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
23
|
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
24
|
+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
25
|
+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
26
|
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
27
|
+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
28
|
+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
29
|
+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
30
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
31
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
32
|
+
*/
|
|
33
|
+
import { addMonths, getDaysInMonth, addDays } from "date-fns";
|
|
34
|
+
import copy from "copy-to-clipboard";
|
|
35
|
+
import { LazySeq } from "@seedtactics/immutable-collections";
|
|
36
|
+
function isUnloadCycle(c) {
|
|
37
|
+
return c.isLabor && c.operation === "UNLOAD";
|
|
38
|
+
}
|
|
39
|
+
function isMonthType(type) {
|
|
40
|
+
return Object.prototype.hasOwnProperty.call(type, "month");
|
|
41
|
+
}
|
|
42
|
+
export function compute_monthly_cost_percentages(cycles, partsToIgnore, matsById, type) {
|
|
43
|
+
const start = isMonthType(type) ? type.month : type.thirtyDaysAgo;
|
|
44
|
+
const end = isMonthType(type) ? addMonths(type.month, 1) : addDays(type.thirtyDaysAgo, 31);
|
|
45
|
+
let totalPalletCycles = 0;
|
|
46
|
+
const totalStatUseMinutes = new Map();
|
|
47
|
+
let totalLaborUseMinutes = 0;
|
|
48
|
+
const stationCount = new Map();
|
|
49
|
+
const filteredCycles = cycles.filter((c) => c.endTime >= start && c.endTime <= end && !c.material.some((m) => partsToIgnore.has(m.part)));
|
|
50
|
+
for (const c of filteredCycles) {
|
|
51
|
+
if (isUnloadCycle(c)) {
|
|
52
|
+
totalPalletCycles += 1;
|
|
53
|
+
}
|
|
54
|
+
if (c.isLabor) {
|
|
55
|
+
totalLaborUseMinutes += c.activeMinutes;
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
totalStatUseMinutes.set(c.stationGroup, c.activeMinutes + (totalStatUseMinutes.get(c.stationGroup) ?? 0));
|
|
59
|
+
const s = stationCount.get(c.stationGroup);
|
|
60
|
+
if (s) {
|
|
61
|
+
s.add(c.stationNumber);
|
|
62
|
+
}
|
|
63
|
+
else {
|
|
64
|
+
stationCount.set(c.stationGroup, new Set([c.stationNumber]));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const completed = LazySeq.of(matsById)
|
|
69
|
+
.filter(([, details]) => {
|
|
70
|
+
if (partsToIgnore.has(details.partName))
|
|
71
|
+
return false;
|
|
72
|
+
if (details.numProcesses === undefined)
|
|
73
|
+
return false;
|
|
74
|
+
const unload = details.unloaded_processes?.[details.numProcesses];
|
|
75
|
+
return !!unload && unload >= start && unload <= end;
|
|
76
|
+
})
|
|
77
|
+
.toRMap(([, details]) => [details.partName, 1], (v1, v2) => v1 + v2);
|
|
78
|
+
const parts = filteredCycles
|
|
79
|
+
.groupBy((c) => c.part)
|
|
80
|
+
.map(([partName, forPart]) => ({
|
|
81
|
+
part: partName,
|
|
82
|
+
parts_completed: completed.get(partName) ?? 0,
|
|
83
|
+
machine: LazySeq.of(forPart)
|
|
84
|
+
.filter((c) => !c.isLabor)
|
|
85
|
+
.buildOrderedMap((c) => c.stationGroup, (old, c) => (old ?? 0) + c.activeMinutes)
|
|
86
|
+
.mapValues((minutes, statGroup) => {
|
|
87
|
+
const totalUse = totalStatUseMinutes.get(statGroup) ?? 1;
|
|
88
|
+
return minutes / totalUse;
|
|
89
|
+
}),
|
|
90
|
+
labor: LazySeq.of(forPart)
|
|
91
|
+
.filter((c) => c.isLabor)
|
|
92
|
+
.sumBy((c) => c.activeMinutes / totalLaborUseMinutes),
|
|
93
|
+
automation: forPart.reduce((acc, v) => (isUnloadCycle(v) ? acc + 1 : acc), 0) / totalPalletCycles,
|
|
94
|
+
}))
|
|
95
|
+
.toRArray();
|
|
96
|
+
const machineQuantities = LazySeq.of(stationCount).toOrderedMap(([statGroup, nums]) => [
|
|
97
|
+
statGroup,
|
|
98
|
+
nums.size,
|
|
99
|
+
]);
|
|
100
|
+
return {
|
|
101
|
+
parts,
|
|
102
|
+
machineQuantities,
|
|
103
|
+
type,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
export function convert_cost_percent_to_cost_per_piece(costs, machineCostPerYear, automationCostPerYear, totalLaborCostForPeriod) {
|
|
107
|
+
const days = isMonthType(costs.type) ? getDaysInMonth(costs.type.month) : 30;
|
|
108
|
+
const automationCostForPeriod = automationCostPerYear ? (automationCostPerYear * days) / 365 : 0;
|
|
109
|
+
const stationCostForPeriod = costs.machineQuantities.mapValues((cnt, statGroup) => ((machineCostPerYear[statGroup] ?? 0) * cnt * days) / 365);
|
|
110
|
+
return {
|
|
111
|
+
machineQuantities: costs.machineQuantities,
|
|
112
|
+
type: costs.type,
|
|
113
|
+
parts: costs.parts.map((p) => ({
|
|
114
|
+
part: p.part,
|
|
115
|
+
parts_completed: p.parts_completed,
|
|
116
|
+
machine: p.machine.mapValues((pct, statGroup) => p.parts_completed > 0 ? (pct * (stationCostForPeriod.get(statGroup) ?? 0)) / p.parts_completed : 0),
|
|
117
|
+
labor: p.parts_completed > 0 ? (p.labor * totalLaborCostForPeriod) / p.parts_completed : 0,
|
|
118
|
+
automation: p.parts_completed > 0 ? (p.automation * automationCostForPeriod) / p.parts_completed : 0,
|
|
119
|
+
})),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function buildCostPerPieceTable(costs) {
|
|
123
|
+
let table = "<table>\n<thead><tr>";
|
|
124
|
+
table += "<th>Part</th>";
|
|
125
|
+
table += "<th>Completed Quantity</th>";
|
|
126
|
+
for (const m of costs.machineQuantities.keys()) {
|
|
127
|
+
table += "<th>" + m + " Cost %</th>";
|
|
128
|
+
}
|
|
129
|
+
table += "<th>Labor Cost</th>";
|
|
130
|
+
table += "<th>Automation Cost</th>";
|
|
131
|
+
table += "</tr></thead>\n<tbody>\n";
|
|
132
|
+
const rows = LazySeq.of(costs.parts).sortBy((c) => c.part);
|
|
133
|
+
const format = Intl.NumberFormat(undefined, {
|
|
134
|
+
maximumFractionDigits: 1,
|
|
135
|
+
});
|
|
136
|
+
for (const c of rows) {
|
|
137
|
+
table += "<tr><td>" + c.part + "</td>";
|
|
138
|
+
table += "<td>" + c.parts_completed.toString() + "</td>";
|
|
139
|
+
for (const m of costs.machineQuantities.keys()) {
|
|
140
|
+
table += "<td>" + format.format(c.machine.get(m) ?? 0) + "</td>";
|
|
141
|
+
}
|
|
142
|
+
table += "<td>" + (c.parts_completed > 0 ? format.format(c.labor) : "0") + "</td>";
|
|
143
|
+
table += "<td>" + (c.parts_completed > 0 ? format.format(c.automation) : "0") + "</td>";
|
|
144
|
+
table += "</tr>\n";
|
|
145
|
+
}
|
|
146
|
+
table += "</tbody>\n</table>";
|
|
147
|
+
return table;
|
|
148
|
+
}
|
|
149
|
+
export function copyCostPerPieceToClipboard(costs) {
|
|
150
|
+
copy(buildCostPerPieceTable(costs));
|
|
151
|
+
}
|
|
152
|
+
export function buildCostBreakdownTable(costs) {
|
|
153
|
+
let table = "<table>\n<thead><tr>";
|
|
154
|
+
table += "<th>Part</th>";
|
|
155
|
+
table += "<th>Completed Quantity</th>";
|
|
156
|
+
for (const m of costs.machineQuantities.keys()) {
|
|
157
|
+
table += "<th>" + m + " Cost %</th>";
|
|
158
|
+
}
|
|
159
|
+
table += "<th>Labor Cost %</th>";
|
|
160
|
+
table += "<th>Automation Cost %</th>";
|
|
161
|
+
table += "</tr></thead>\n<tbody>\n";
|
|
162
|
+
const rows = LazySeq.of(costs.parts).sortBy((c) => c.part);
|
|
163
|
+
const pctFormat = new Intl.NumberFormat(undefined, {
|
|
164
|
+
style: "percent",
|
|
165
|
+
minimumFractionDigits: 1,
|
|
166
|
+
maximumFractionDigits: 1,
|
|
167
|
+
});
|
|
168
|
+
for (const c of rows) {
|
|
169
|
+
table += "<tr><td>" + c.part + "</td>";
|
|
170
|
+
table += "<td>" + c.parts_completed.toString() + "</td>";
|
|
171
|
+
for (const m of costs.machineQuantities.keys()) {
|
|
172
|
+
table += "<td>" + pctFormat.format(c.machine.get(m) ?? 0) + "</td>";
|
|
173
|
+
}
|
|
174
|
+
table += "<td>" + pctFormat.format(c.labor) + "</td>";
|
|
175
|
+
table += "<td>" + pctFormat.format(c.automation) + "</td>";
|
|
176
|
+
table += "</tr>\n";
|
|
177
|
+
}
|
|
178
|
+
table += "</tbody>\n</table>";
|
|
179
|
+
return table;
|
|
180
|
+
}
|
|
181
|
+
export function copyCostBreakdownToClipboard(costs) {
|
|
182
|
+
copy(buildCostBreakdownTable(costs));
|
|
183
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EstimatedCycleTimes } from "../cell-status/estimated-cycle-times.js";
|
|
2
|
+
import { ICurrentStatus } from "../network/api.js";
|
|
3
|
+
export type CurrentCycle = {
|
|
4
|
+
readonly station: string;
|
|
5
|
+
readonly start: Date;
|
|
6
|
+
readonly expectedEnd: Date;
|
|
7
|
+
readonly isOutlier: boolean;
|
|
8
|
+
readonly parts: ReadonlyArray<{
|
|
9
|
+
readonly part: string;
|
|
10
|
+
readonly oper: string;
|
|
11
|
+
}>;
|
|
12
|
+
};
|
|
13
|
+
export declare function currentCycles(currentSt: ICurrentStatus, estimated: EstimatedCycleTimes): ReadonlyArray<CurrentCycle>;
|