|
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793 |
- "use server";
-
- import { cache } from 'react';
- import { Pageable, ServerFetchError, serverFetchBlob, serverFetchJson, serverFetchWithNoContent } from "@/app/utils/fetchUtil";
- import { JobOrder, JoStatus, Machine, Operator } from ".";
- import { BASE_API_URL } from "@/config/api";
- import { revalidateTag } from "next/cache";
- import { convertObjToURLSearchParams } from "@/app/utils/commonUtil";
- import { FileResponse } from "@/app/api/pdf/actions";
-
- export interface SaveJo {
- bomId: number;
- planStart: string;
- planEnd: string;
- reqQty: number;
- type: string;
- //jobType?: string;
- jobTypeId?: number;
- productionPriority?: number;
- }
-
- export interface SaveJoResponse {
- id: number;
- }
-
- export interface SearchJoResultRequest extends Pageable {
- code: string;
- itemName?: string;
- planStart?: string;
- planStartTo?: string;
- jobTypeName?: string;
- joSearchStatus?: string;
- }
-
- export interface productProcessLineQtyRequest {
- productProcessLineId: number;
- outputFromProcessQty: number;
- outputFromProcessUom: string;
- defectQty: number;
- defectUom: string;
- scrapQty: number;
- scrapUom: string;
- }
- export interface SearchJoResultResponse {
- records: JobOrder[];
- total: number;
- }
-
- // DEPRECIATED
- export interface SearchJoResult {
- id: number;
- code: string;
- itemCode: string;
- name: string;
- reqQty: number;
- uom: string;
- status: JoStatus;
- }
-
- export interface UpdateJoRequest {
- id: number;
- status: string;
- }
-
- // For Jo Button Actions
- export interface CommonActionJoRequest {
- id: number;
- }
-
- export interface CommonActionJoResponse {
- id: number;
- entity: { status: JoStatus }
- }
-
- // For Jo Process
- export interface IsOperatorExistResponse<T> {
- id: number | null;
- name: string;
- code: string;
- type?: string;
- message: string | null;
- errorPosition: string | keyof T;
- entity: T;
- }
-
- export interface isCorrectMachineUsedResponse<T> {
- id: number | null;
- name: string;
- code: string;
- type?: string;
- message: string | null;
- errorPosition: string | keyof T;
- entity: T;
- }
-
- export interface JobOrderDetail {
- id: number;
- code: string;
- name: string;
- reqQty: number;
- uom: string;
- pickLines: any[];
-
- jobTypeName: string;
- status: string;
- }
-
- export interface UnassignedJobOrderPickOrder {
- pickOrderId: number;
- pickOrderCode: string;
- pickOrderConsoCode: string;
- pickOrderTargetDate: string;
- pickOrderStatus: string;
- jobOrderId: number;
- jobOrderCode: string;
- jobOrderName: string;
- reqQty: number;
- uom: string;
- planStart: string;
- planEnd: string;
- }
-
- export interface AssignJobOrderResponse {
- id: number | null;
- code: string | null;
- name: string | null;
- type: string | null;
- message: string | null;
- errorPosition: string | null;
- }
-
- export interface PrintPickRecordRequest{
- pickOrderId: number;
- printerId: number;
- printQty: number;
- floor?: "2F" | "3F" | "4F" | "ALL";
- plasticBoxCartonQty?: number;
- plasticBoxCartonQty2f?: number;
- plasticBoxCartonQty3f?: number;
- plasticBoxCartonQty4f?: number;
- }
-
- export interface PrintPickRecordResponse{
- success: boolean;
- message?: string
- }
-
- export interface PickRecordPlasticBoxCartonQtyResponse {
- plasticBoxCartonQty2f: number | null;
- plasticBoxCartonQty3f: number | null;
- plasticBoxCartonQty4f: number | null;
- }
-
- export const fetchPickRecordPlasticBoxCartonQty = async (
- pickOrderId: number,
- ): Promise<PickRecordPlasticBoxCartonQtyResponse> => {
- return serverFetchJson<PickRecordPlasticBoxCartonQtyResponse>(
- `${BASE_API_URL}/jo/pick-record-plastic-box-carton-qty/${pickOrderId}`,
- {
- method: "GET",
- headers: { "Content-Type": "application/json" },
- },
- );
- };
-
- export interface PrintFGStockInLabelRequest {
- stockInLineId: number;
- printerId: number;
- printQty?: number;
- }
-
- export const printFGStockInLabel = cache(async(data: PrintFGStockInLabelRequest) => {
- const params = new URLSearchParams();
- if (data.stockInLineId) {
- params.append('stockInLineId', data.stockInLineId.toString());
- }
- params.append('printerId', data.printerId.toString());
- if (data.printQty !== undefined && data.printQty !== null) {
- params.append('printQty', data.printQty.toString());
- }
-
- return serverFetchWithNoContent(
- `${BASE_API_URL}/jo/print-FGStockInLabel?${params.toString()}`,
- {
- method: "GET",
- next: {
- tags: ["printFGStockInLabel"],
- },
- }
- );
- });
- export interface UpdateJoReqQtyRequest {
- id: number;
- reqQty: number;
- }
-
- // 添加更新 reqQty 的函数
- export const updateJoReqQty = cache(async (data: UpdateJoReqQtyRequest) => {
- return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/updateReqQty`, {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- })
- })
-
- export const recordSecondScanIssue = cache(async (
- pickOrderId: number,
- itemId: number,
- data: {
- qty: number; // verified qty (actual pick qty)
- missQty?: number; // 添加:miss qty
- badItemQty?: number; // 添加:bad item qty
- isMissing: boolean;
- isBad: boolean;
- reason: string;
- createdBy: number;
- type?: string; // type 也应该是可选的
- }
-
- ) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/second-scan-issue/${pickOrderId}/${itemId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- next: { tags: ["jo-second-scan"] },
- },
- );
- });
-
-
- export interface ProductProcessResponse {
- id: number;
- productProcessCode: string;
- status: string;
- startTime?: string;
- endTime?: string;
- date: string;
- bomId?: number;
- jobOrderId?: number;
- }
-
- export interface ProductProcessLineResponse {
- id: number,
- bomprocessId: number,
- operatorId: number,
- operatorName: string,
- equipmentId: number,
- handlerId: number,
- seqNo: number,
- name: string,
- description: string,
- equipmentDetailId: number,
- equipment_name: string,
- equipmentDetailCode: string,
- status: string,
- byproductId: number,
- byproductName: string,
- byproductQty: number,
- byproductUom: string,
- scrapQty: number,
- defectQty: number,
- defectUom: string,
- outputFromProcessQty: number,
- outputFromProcessUom: string,
- durationInMinutes: number,
- prepTimeInMinutes: number,
- postProdTimeInMinutes: number,
- startTime: string,
- endTime: string,
- isOringinal: boolean,
- }
-
- export interface ProductProcessWithLinesResponse {
- id: number;
- productProcessCode: string;
- status: string;
- startTime?: string;
- endTime?: string;
- date: string;
- bomId?: number;
- jobOrderId?: number;
- jobOrderCode: string;
- jobOrderStatus: string;
- bomDescription: string;
- jobType: string;
- isDark: number | null;
- bomBaseQty: number;
- isDense: number | null;
- isFloat: number | null;
- timeSequence: number | null;
- complexity: number | null;
- scrapRate: number;
- allergicSubstance: number | null;
- itemId: number;
- itemCode: string;
- itemName: string;
- outputQty: number;
- outputQtyUom: string;
- productionPriority: number;
- submitedBagRecord?: boolean;
- jobOrderLines: JobOrderLineInfo[];
-
- productProcessLines: ProductProcessLineResponse[];
-
- }
- export interface UpdateProductProcessLineQtyRequest {
- productProcessLineId: number;
- outputFromProcessQty: number;
- outputFromProcessUom: string;
- byproductName: string;
- byproductQty: number;
- byproductUom: string;
- defectQty: number;
- defectUom: string;
- defect2Qty: number;
- defect2Uom: string;
- defect3Qty: number;
- defect3Uom: string;
- defectDescription: string;
- defectDescription2: string;
- defectDescription3: string;
- scrapQty: number;
- scrapUom: string;
- }
- export interface UpdateProductProcessLineQtyResponse {
- id: number;
- outputFromProcessQty: number;
- outputFromProcessUom: string;
- defectQty: number;
- defectUom: string;
- defect2Qty: number;
- defect2Uom: string;
- defect3Qty: number;
- defect3Uom: string;
- defectDescription: string;
- defectDescription2: string;
- defectDescription3: string;
- scrapQty: number;
- scrapUom: string;
- byproductName: string;
- byproductQty: number;
- byproductUom: string;
- }
- export interface AllProductProcessResponse {
- id: number;
- productProcessCode: string;
- status: string;
- startTime?: string;
- endTime?: string;
- date: string;
- bomId?: number;
- }
- export interface AllJoborderProductProcessInfoResponse {
- id: number;
- productProcessCode: string;
- status: string;
- startTime?: string;
- endTime?: string;
- date: string;
- matchStatus: string;
- bomId?: number;
- productionPriority: number;
- assignedTo: number;
- pickOrderId: number;
- pickOrderStatus: string;
- itemCode: string;
- itemName: string;
- bomDescription?: string | null;
- /** BOM.type (e.g. drink / Powder_Mixture / other). */
- bomType?: string | null;
- lotNo: string;
- requiredQty: number;
- jobOrderId: number;
- timeNeedToComplete: number;
- uom: string;
- isDrink?: boolean | null;
- stockInLineId: number;
- /** Stock-in-line current status (e.g. receiving/received/partially_completed/completed/rejected). */
- stockInLineStatus?: string | null;
- jobOrderCode: string;
- productProcessLineCount: number;
- FinishedProductProcessLineCount: number;
- lines: ProductProcessInfoResponse[];
- isPicked?: boolean | null;
- /** Fine-grained pick/process bucket from backend. */
- pickProcessBucket?: ProductionProcessFinePickBucket | null;
- }
-
- /** Fine-grained buckets returned per row. */
- export type ProductionProcessFinePickBucket =
- | "not_picked_not_started"
- | "picked_not_started"
- | "picked_started"
- | "not_picked_started";
-
- /** Merged tab filter: pending = not started; processing = started. */
- export type ProductionProcessPickBucket = "pending" | "processing" | ProductionProcessFinePickBucket;
-
- export interface JobOrderProductProcessBucketCounts {
- notPickedNotStarted: number;
- pickedNotStarted: number;
- pickedStarted: number;
- notPickedStarted: number;
- }
-
- export interface JobOrderProductProcessPageResponse {
- content: AllJoborderProductProcessInfoResponse[];
- totalJobOrders: number;
- page: number;
- size: number;
- bucketCounts?: JobOrderProductProcessBucketCounts | null;
- searchDate?: string | null;
- carriedOverCount?: number | null;
- }
- export interface ProductProcessInfoResponse {
- id: number;
- operatorId?: number;
- operatorName?: string;
- equipmentId?: number;
- equipmentName?: string;
- startTime?: string;
- endTime?: string;
- status: string;
- }
- export interface ProductProcessLineQrscanUpadteRequest {
- productProcessLineId: number;
- //operatorId?: number;
- //equipmentId?: number;
- equipmentTypeSubTypeEquipmentNo?: string;
- staffNo?: string;
- }
- export interface NewProductProcessLineQrscanUpadteRequest{
- productProcessLineId: number;
- equipmentCode?: string;
- staffNo?: string;
- }
-
- export interface ProductProcessLineDetailResponse {
- id: number,
- productProcessId: number,
- bomProcessId: number,
- operatorId: number,
- equipmentType: string,
- operatorName: string,
- handlerId: number,
- seqNo: number,
- isDark: string,
- isDense: number,
- isFloat: string,
- outputQtyUom: string,
- outputQty: number,
- pickOrderId: number,
- jobOrderCode: string,
- jobOrderId: number,
- name: string,
- description: string,
- equipment: string,
- startTime: string,
- endTime: string,
- defectQty: number,
- defectUom: string,
- scrapQty: number,
- scrapUom: string,
- byproductId: number,
- byproductName: string,
- byproductQty: number,
- byproductUom: string | undefined,
- totalStockQty: number,
- insufficientStockQty: number,
- sufficientStockQty: number,
- productionPriority: number,
- productProcessLines: ProductProcessLineInfoResponse[],
- jobOrderLineInfo: JobOrderLineInfo[],
- }
- export interface JobOrderProcessLineDetailResponse {
- id: number;
- productProcessId: number;
- bomProcessId: number;
- operatorId: number;
- equipmentType: string | null;
- operatorName: string;
- handlerId: number;
- seqNo: number;
- durationInMinutes: number;
- name: string;
- description: string;
- equipmentId: number;
- startTime: string | number[]; // API 返回的是数组格式
- endTime: string | number[];
- stopTime: string | number[];
- totalPausedTimeMs?: number; // API 返回的是数组格式
- status: string;
- submitedBagRecord: boolean;
- outputFromProcessQty: number;
- outputFromProcessUom: string;
- defectQty: number;
- defectUom: string;
- defectDescription: string;
- defectQty2: number;
- defectUom2: string;
- defectDescription2: string;
- defectQty3: number;
- defectUom3: string;
- defectDescription3: string;
- scrapQty: number;
- scrapUom: string;
- byproductId: number;
- byproductName: string;
- byproductQty: number;
- byproductUom: string;
- productProcessIssueId: number;
- productProcessIssueStatus: string;
- }
- export interface JobOrderLineInfo {
- id: number,
- itemId: number,
- itemCode: string,
- itemName: string,
- type: string,
-
- reqQty: number,
- baseReqQty: number,
-
- stockReqQty: number,
-
- stockQty: number,
- baseStockQty: number,
-
- reqUom: string,
- reqBaseUom: string,
-
- stockUom: string,
- stockBaseUom: string,
-
- availableStatus: string,
- bomProcessId: number,
- bomProcessSeqNo: number,
- isOringinal: boolean
-
- }
- export interface ProductProcessLineInfoResponse {
- id: number,
- bomprocessId: number,
- operatorId: number,
- operatorName: string,
- equipmentId: number,
- handlerId: number,
- seqNo: number,
- name: string,
- description: string,
- equipment_name: string,
- equipmentDetailCode: string,
- status: string,
- byproductId: number,
- byproductName: string,
- byproductQty: number,
- byproductUom: string,
- scrapQty: number,
- defectQty: number,
- defectUom: string,
- durationInMinutes: number,
- prepTimeInMinutes: number,
- postProdTimeInMinutes: number,
- outputFromProcessQty: number,
- outputFromProcessUom: string,
- startTime: string,
- endTime: string
- }
- export interface FloorPickCount {
- floor: string;
- finishedCount: number;
- totalCount: number;
- }
- export interface AllJoPickOrderResponse {
- id: number;
- pickOrderId: number | null;
- pickOrderCode: string | null;
- jobOrderId: number | null;
- jobOrderCode: string | null;
- jobOrderTypeId: number | null;
- jobOrderType: string | null;
- itemId: number;
- itemName: string;
- itemCode?: string | null;
- bomDescription?: string | null;
- /** BOM.type (e.g. drink / Powder_Mixture / other). */
- bomType?: string | null;
- lotNo: string | null;
- planStart?: string | number[] | null;
- reqQty: number;
- uomId: number;
- uomName: string;
- jobOrderStatus: string;
- finishedPickOLineCount: number;
- floorPickCounts: FloorPickCount[];
- noLotPickCount?: FloorPickCount | null;
- suggestedFailCount?: number;
- }
- export interface UpdateJoPickOrderHandledByRequest {
- pickOrderId: number;
- itemId: number;
- userId: number;
- }
- export interface JobTypeResponse {
- id: number;
- name: string;
- }
- export interface SaveProductProcessIssueTimeRequest {
- productProcessLineId: number;
- reason: string;
- }
- export interface JobOrderLotsHierarchicalResponse {
- pickOrder: PickOrderInfoResponse;
- pickOrderLines: PickOrderLineWithLotsResponse[];
- }
-
- /** JO Workbench: same shape as [JobOrderLotsHierarchicalResponse] but `pickOrder.jobOrder` includes BOM code/name. */
- export interface JobOrderLotsHierarchicalWorkbenchResponse {
- pickOrder: PickOrderInfoWorkbenchResponse;
- pickOrderLines: PickOrderLineWithLotsResponse[];
- }
-
- export interface PickOrderInfoResponse {
- id: number | null;
- code: string | null;
- consoCode: string | null;
- targetDate: string | null;
- type: string | null;
- status: string | null;
- assignTo: number | null;
- jobOrder: JobOrderBasicInfoResponse;
- }
-
- export interface PickOrderInfoWorkbenchResponse {
- id: number | null;
- code: string | null;
- consoCode: string | null;
- targetDate: string | null;
- type: string | null;
- status: string | null;
- assignTo: number | null;
- jobOrder: JobOrderBasicInfoWorkbenchResponse;
- }
-
- export interface JobOrderBasicInfoResponse {
- id: number;
- code: string;
- name: string;
- }
-
- /** BOM header code/name from job order's BOM (workbench hierarchical API only). */
- export interface JobOrderBasicInfoWorkbenchResponse {
- id: number;
- code: string;
- name: string;
- itemCode: string | null;
- itemName: string | null;
- }
-
- export interface PickOrderLineWithLotsResponse {
- id: number;
- itemId: number | null;
- itemCode: string | null;
- itemName: string | null;
- requiredQty: number | null;
- totalAvailableQty?: number | null;
- uomCode: string | null;
- uomDesc: string | null;
- status: string | null;
- handler: string | null;
- lots: LotDetailResponse[];
- stockouts?: StockOutLineDetailResponse[];
- }
-
- export interface StockOutLineDetailResponse {
- id: number | null;
- status: string | null;
- qty: number | null;
- lotId: number | null;
- lotNo: string | null;
- location: string | null;
- availableQty: number | null;
- noLot: boolean;
- /** Workbench API: matched suggest_pick_lot qty for this SOL lot line */
- suggestedPickQty?: number | null;
- suggestedPickLotId?: number | null;
- }
-
- export interface LotDetailResponse {
- lotId: number | null;
- lotNo: string | null;
- expiryDate: string | null;
- location: string | null;
- availableQty: number | null;
- requiredQty: number | null;
- actualPickQty: number | null;
- processingStatus: string | null;
- lotAvailability: string | null;
- pickOrderId: number | null;
- pickOrderCode: string | null;
- pickOrderConsoCode: string | null;
- pickOrderLineId: number | null;
- stockOutLineId: number | null;
- stockInLineId: number | null;
- suggestedPickLotId: number | null;
- stockOutLineQty: number | null;
- stockOutLineStatus: string | null;
- routerIndex: number | null;
- routerArea: string | null;
- routerRoute: string | null;
- uomShortDesc: string | null;
- matchStatus?: string | null;
- matchBy?: number | null;
- matchQty?: number | null;
- }
-
- export interface JobOrderListForPrintQrCodeResponse {
- id: number;
- code: string;
- name: string;
- reqQty: number;
- stockOutLineId: number;
- stockOutLineQty: number;
- stockOutLineStatus: string;
- finihedTime: string;
- }
- export interface UpdateJoPlanStartRequest {
- id: number;
- planStart: string; // Format: YYYY-MM-DDTHH:mm:ss or YYYY-MM-DD
- }
-
- export const saveProductProcessIssueTime = cache(async (request: SaveProductProcessIssueTimeRequest) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/issue`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- }
- );
- });
- export const saveProductProcessResumeTime = cache(async (productProcessIssueId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/resume/${productProcessIssueId}`,
- {
- method: "POST",
- }
- );
- });
- export const deleteJobOrder=cache(async (jobOrderId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/demo/deleteJobOrder/${jobOrderId}`,
- {
- method: "POST",
- }
- );
- });
-
- export const setJobOrderHidden = cache(async (jobOrderId: number, hidden: boolean) => {
- const response = await serverFetchJson<any>(`${BASE_API_URL}/jo/set-hidden`, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify({ id: jobOrderId, hidden }),
- });
- revalidateTag("jos");
- return response;
- });
- export const fetchAllJobTypes = cache(async () => {
- return serverFetchJson<JobTypeResponse[]>(
- `${BASE_API_URL}/jo/jobTypes`,
- {
- method: "GET",
- }
- );
- });
- export const updateJoPickOrderHandledBy = cache(async (request: UpdateJoPickOrderHandledByRequest) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/update-jo-pick-order-handled-by`,
- {
- method: "POST",
- body: JSON.stringify(request),
- headers: { "Content-Type": "application/json" },
- },
- );
- });
- export const fetchJobOrderLotsHierarchicalByPickOrderId = cache(async (pickOrderId: number) => {
- return serverFetchJson<JobOrderLotsHierarchicalResponse>(
- `${BASE_API_URL}/jo/all-lots-hierarchical-by-pick-order/${pickOrderId}`,
- {
- method: "GET",
- next: { tags: ["jo-hierarchical"] },
- },
- );
- });
-
- /** JO Workbench: in−out available (matches scan-pick); stockouts include suggestedPickQty / suggestedPickLotId when SPL matches SOL lot line */
-
- export const fetchJobOrderLotsHierarchicalByPickOrderIdWorkbench = cache(
- async (pickOrderId: number) => {
- return serverFetchJson<JobOrderLotsHierarchicalWorkbenchResponse>(
- `${BASE_API_URL}/jo/all-lots-hierarchical-by-pick-order-workbench/${pickOrderId}`,
- {
- method: "GET",
- next: { tags: ["jo-hierarchical-workbench"] },
- },
- );
- },
- );
-
- // NOTE: Do NOT wrap in `cache()` because the list needs to reflect just-completed lines
- // immediately when navigating back from JobPickExecution.
- export interface FetchAllJoPickOrdersFilters {
- jobOrderCode?: string | null;
- pickOrderCode?: string | null;
- itemName?: string | null;
- bomDescription?: string | null;
- planStart?: string | null;
- }
-
- export const fetchAllJoPickOrders = async (
- type?: string | null,
- floor?: string | null,
- filters?: FetchAllJoPickOrdersFilters,
- ) => {
- const params = new URLSearchParams();
- if (type) params.set("type", type);
- if (floor) params.set("floor", floor);
- if (filters?.jobOrderCode) params.set("jobOrderCode", filters.jobOrderCode);
- if (filters?.pickOrderCode) params.set("pickOrderCode", filters.pickOrderCode);
- if (filters?.itemName) params.set("itemName", filters.itemName);
- if (filters?.bomDescription) params.set("bomDescription", filters.bomDescription);
- if (filters?.planStart) params.set("planStart", filters.planStart);
- const query = params.toString() ? `?${params.toString()}` : "";
- return serverFetchJson<AllJoPickOrderResponse[]>(
- `${BASE_API_URL}/jo/AllJoPickOrder${query}`,
- // Force re-fetch. This page reflects real-time pick completion state.
- { method: "GET", cache: "no-store" }
- );
- };
- export const fetchProductProcessLineDetail = cache(async (lineId: number) => {
- return serverFetchJson<JobOrderProcessLineDetailResponse>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/detail/${lineId}`,
- {
- method: "GET",
- }
- );
- });
- export const updateProductProcessLineQty = cache(async (request: UpdateProductProcessLineQtyRequest) => {
- return serverFetchJson<UpdateProductProcessLineQtyResponse>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/update/qty/${request.productProcessLineId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- }
- );
- });
-
- export const updateProductProcessLineQrscan = cache(async (request: ProductProcessLineQrscanUpadteRequest) => {
- const requestBody: any = {
- productProcessLineId: request.productProcessLineId,
- //operatorId: request.operatorId,
- //equipmentId: request.equipmentId,
- equipmentTypeSubTypeEquipmentNo: request.equipmentTypeSubTypeEquipmentNo,
- staffNo: request.staffNo,
- };
- if (request.equipmentTypeSubTypeEquipmentNo !== undefined) {
- requestBody["EquipmentType-SubType-EquipmentNo"] = request.equipmentTypeSubTypeEquipmentNo;
- }
-
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/update`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(requestBody),
- }
- );
- });
-
-
- export const newUpdateProductProcessLineQrscan = cache(async (request: NewProductProcessLineQrscanUpadteRequest) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/NewUpdate`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- }
- );
- });
- export const fetchAllJoborderProductProcessInfo = cache(async (type?: string | null) => {
- const query = type
- ? `?type=${encodeURIComponent(type)}`
- : "";
-
- return serverFetchJson<AllJoborderProductProcessInfoResponse[]>(
- `${BASE_API_URL}/product-process/Demo/Process/all${query}`,
- {
- method: "GET",
- next: { tags: ["productProcess"] },
- }
- );
- });
-
- /** FP-MTMS Version Checklist | Functions Ref. No. 40 | v1.0.7 | 2026-08-06 */
- export const fetchJoborderProductProcessesPage = cache(async (params: {
- /** Job order / process date(YYYY-MM-DD) */
- date?: string | null;
- itemCode?: string | null;
- jobOrderCode?: string | null;
- bomIds?: number[] | null;
- qcReady?: boolean | null;
- type?: string | null;
- includePutaway?: boolean | null;
- /** all | completed | notCompleted */
- putawayStatus?: string | null;
- /** Production list carry-over window (days before date). */
- lookbackDays?: number | null;
- /** Pick/process tab filter when lookbackDays is set. */
- bucket?: ProductionProcessPickBucket | "all" | null;
- page?: number;
- size?: number;
- }) => {
- const {
- date,
- itemCode,
- jobOrderCode,
- bomIds,
- qcReady,
- includePutaway,
- putawayStatus,
- type,
- lookbackDays,
- bucket,
- page = 0,
- size = 50,
- } = params;
-
- const queryParts: string[] = [];
- if (date) {
- queryParts.push(`date=${encodeURIComponent(date)}`);
- }
- if (itemCode) queryParts.push(`itemCode=${encodeURIComponent(itemCode)}`);
- if (jobOrderCode) queryParts.push(`jobOrderCode=${encodeURIComponent(jobOrderCode)}`);
- if (bomIds && bomIds.length > 0) queryParts.push(`bomIds=${bomIds.join(",")}`);
- if (qcReady !== undefined && qcReady !== null) queryParts.push(`qcReady=${qcReady}`);
- if (type) queryParts.push(`type=${encodeURIComponent(type)}`);
- if (includePutaway !== undefined && includePutaway !== null) {
- queryParts.push(`includePutaway=${includePutaway}`);
- }
- if (putawayStatus) queryParts.push(`putawayStatus=${encodeURIComponent(putawayStatus)}`);
- if (lookbackDays !== undefined && lookbackDays !== null) {
- queryParts.push(`lookbackDays=${lookbackDays}`);
- }
- if (bucket) queryParts.push(`bucket=${encodeURIComponent(bucket)}`);
- queryParts.push(`page=${page}`);
- queryParts.push(`size=${size}`);
-
- const query = queryParts.length > 0 ? `?${queryParts.join("&")}` : "";
-
- return serverFetchJson<JobOrderProductProcessPageResponse>(
- `${BASE_API_URL}/product-process/Demo/Process/search${query}`,
- {
- method: "GET",
- next: { tags: ["productProcessSearch"] },
- }
- );
- });
-
- /*
- export const updateProductProcessLineQty = async (request: UpdateProductProcessLineQtyRequest) => {
- return serverFetchJson<UpdateProductProcessLineQtyResponse>(
- `${BASE_API_URL}/product-process/lines/${request.productProcessLineId}/update/qty`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(request),
- }
- );
- };
- */
- export const startProductProcessLine = async (lineId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/start/${lineId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- export const completeProductProcessLine = async (lineId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/complete/${lineId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
-
- // 查询所有 production processes
- export const fetchProductProcesses = cache(async () => {
- return serverFetchJson<{ content: ProductProcessResponse[] }>(
- `${BASE_API_URL}/product-process`,
- {
- method: "GET",
- next: { tags: ["productProcess"] },
- }
- );
- });
-
- // 根据 ID 查询
- export const fetchProductProcessById = cache(async (id: number) => {
- return serverFetchJson<ProductProcessResponse>(
- `${BASE_API_URL}/product-process/${id}`,
- {
- method: "GET",
- next: { tags: ["productProcess"] },
- }
- );
- });
- export const updateProductProcessPriority = cache(async (productProcessId: number, productionPriority: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/Process/update/priority/${productProcessId}/${productionPriority}`,
- {
- method: "POST",
- }
- );
- });
- // 根据 Job Order ID 查询
- export const fetchProductProcessesByJobOrderId = cache(async (jobOrderId: number) => {
- return serverFetchJson<ProductProcessWithLinesResponse[]>(
- `${BASE_API_URL}/product-process/demo/joid/${jobOrderId}`,
- {
- method: "GET",
- next: { tags: ["productProcess"] },
- }
- );
- });
- export const newProductProcessLine = cache(async (lineId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/new/${lineId}`,
- {
- method: "POST",
- }
- );
- });
- // 获取 process 的所有 lines
- export const fetchProductProcessLines = cache(async (processId: number) => {
- return serverFetchJson<ProductProcessLineResponse[]>(
- `${BASE_API_URL}/product-process/${processId}/lines`,
- {
- method: "GET",
- next: { tags: ["productProcessLines"] },
- }
- );
- });
-
- // 创建 production process
- export const createProductProcess = async (data: {
- bomId: number;
- jobOrderId?: number;
- date?: string;
- }) => {
- return serverFetchJson<{ id: number; productProcessCode: string; linesCreated: number }>(
- `${BASE_API_URL}/product-process`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- }
- );
- };
-
- // 更新 line 产出数据
- export const updateLineOutput = async (lineId: number, data: {
- outputQty?: number;
- outputUom?: string;
- defectQty?: number;
- defectUom?: string;
- scrapQty?: number;
- scrapUom?: string;
- byproductName?: string;
- byproductQty?: number;
- byproductUom?: string;
- }) => {
- return serverFetchJson<ProductProcessLineResponse>(
- `${BASE_API_URL}/product-process/lines/${lineId}/output`,
- {
- method: "PUT",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- }
- );
- };
- export const updateSecondQrScanStatus = cache(async (pickOrderId: number, itemId: number, userId: number, qty: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/update-match-status`,
- {
- method: "POST",
- body: JSON.stringify({
- pickOrderId,
- itemId,
- userId,
- qty
- }),
- headers: {
- 'Content-Type': 'application/json',
- },
- next: { tags: ["update-match-status"] },
- },
- );
- });
-
- export const submitSecondScanQuantity = cache(async (
- pickOrderId: number,
- itemId: number,
- data: { qty: number; isMissing?: boolean; isBad?: boolean; reason?: string; userId?: number }
- ) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/second-scan-submit/${pickOrderId}/${itemId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(data),
- next: { tags: ["jo-second-scan"] },
- },
- );
- });
- // 获取未分配的 Job Order pick orders
- export const fetchUnassignedJobOrderPickOrders = cache(async () => {
- return serverFetchJson<UnassignedJobOrderPickOrder[]>(
- `${BASE_API_URL}/jo/unassigned-job-order-pick-orders`,
- {
- method: "GET",
- next: { tags: ["jo-unassigned"] },
- },
- );
- });
-
- // 分配 Job Order pick order 给用户
- export const assignJobOrderPickOrder = async (pickOrderId: number, userId: number) => {
- return serverFetchJson<AssignJobOrderResponse>(
- `${BASE_API_URL}/jo/assign-job-order-pick-order/${pickOrderId}/${userId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- export const unAssignJobOrderPickOrder = async (pickOrderId: number) => {
- return serverFetchJson<AssignJobOrderResponse>(
- `${BASE_API_URL}/jo/unassign-job-order-pick-order/${pickOrderId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- // 获取 Job Order 分层数据
- export const fetchJobOrderLotsHierarchical = cache(async (userId: number) => {
- return serverFetchJson<JobOrderLotsHierarchicalResponse>(
- `${BASE_API_URL}/jo/all-lots-hierarchical/${userId}`,
- {
- method: "GET",
- next: { tags: ["jo-hierarchical"] },
- },
- );
- });
- export const fetchCompletedJobOrderPickOrders = cache(async (userId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/completed-job-order-pick-orders/${userId}`,
- {
- method: "GET",
- next: { tags: ["jo-completed"] },
- },
- );
- });
- /*
- // 获取已完成的 Job Order pick orders
- export const fetchCompletedJobOrderPickOrdersrecords = cache(async () => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/jo/completed-job-order-pick-orders-only`,
- {
- method: "GET",
- next: { tags: ["jo-completed"] },
- },
- );
- });
- */
- export interface CompletedJobOrderPickOrderDashboardRecord {
- id?: number;
- pickOrderId?: number;
- pickOrderCode?: string;
- /** YYYY-MM-DD from backend (preferred for grouping) */
- statDate?: string | null;
- completedDate?: string | null;
- planStart?: string | null;
- plasticBoxCartonQty2f?: number | null;
- plasticBoxCartonQty3f?: number | null;
- plasticBoxCartonQty4f?: number | null;
- }
-
- export const fetchPlasticBoxCartonQtyDashboard = async (
- from: string,
- to: string,
- ): Promise<CompletedJobOrderPickOrderDashboardRecord[]> => {
- const params = new URLSearchParams({
- from: from.trim(),
- to: to.trim(),
- });
- return serverFetchJson<CompletedJobOrderPickOrderDashboardRecord[]>(
- `${BASE_API_URL}/jo/plastic-box-carton-qty-dashboard?${params.toString()}`,
- {
- method: "GET",
- cache: "no-store",
- },
- );
- };
-
- export const fetchCompletedJobOrderPickOrdersrecords = async (
- completedDate?: string | null,
- ): Promise<CompletedJobOrderPickOrderDashboardRecord[]> => {
- const q =
- completedDate && String(completedDate).trim() !== ""
- ? `?date=${encodeURIComponent(String(completedDate).trim())}`
- : "";
- return serverFetchJson<CompletedJobOrderPickOrderDashboardRecord[]>(
- `${BASE_API_URL}/jo/completed-job-order-pick-orders-only${q}`,
- {
- method: "GET",
- cache: "no-store",
- },
- );
- };
- export const fetchJobOrderPickOrdersrecords = async (
- date?: string | null,
- status?: string | null,
- ) => {
- const params = new URLSearchParams();
-
- // Backend expects LocalDate (YYYY-MM-DD); strip any time component.
- const dateOnly = (() => {
- if (!date || String(date).trim() === "") return null;
- const match = String(date).trim().match(/(\d{4}-\d{2}-\d{2})/);
- return match ? match[1] : String(date).trim().slice(0, 10);
- })();
-
- if (dateOnly) {
- params.set("date", dateOnly);
- }
- if (status && String(status).trim() !== "" && String(status) !== "All") {
- params.set("status", String(status).trim());
- }
-
- const q = params.toString() ? `?${params.toString()}` : "";
- return serverFetchJson<any>(`${BASE_API_URL}/jo/job-order-pick-orders${q}`, {
- method: "GET",
- cache: "no-store",
- });
- };
-
- export const fetchJobOrderPickOrderLotDetailsForPick = cache(async (pickOrderId: number) => {
- return serverFetchJson<any[]>(`${BASE_API_URL}/jo/job-order-pick-order-lot-details/${pickOrderId}`, {
- method: "GET",
- headers: { "Content-Type": "application/json" }
- })
- })
- export const fetchJoForPrintQrCode = cache(async (date: string) => {
- return serverFetchJson<JobOrderListForPrintQrCodeResponse[]>(
- `${BASE_API_URL}/jo/joForPrintQrCode/${date}`,
- {
- method: "GET",
- next: { tags: ["jo-print-qr-code"] },
- },
- );
- });
- // 获取已完成的 Job Order pick order records
- export const fetchCompletedJobOrderPickOrderRecords = cache(async (userId: number) => {
- return serverFetchJson<any[]>(
- `${BASE_API_URL}/jo/completed-job-order-pick-order-records/${userId}`,
- {
- method: "GET",
- next: { tags: ["jo-records"] },
- },
- );
- });
-
- export const fetchJobOrderDetailByCode = cache(async (code: string) => {
- return serverFetchJson<JobOrderDetail>(
- `${BASE_API_URL}/jo/detailByCode/${code}`,
- {
- method: "GET",
- next: { tags: ["jo"] },
- },
- );
- });
- export const isOperatorExist = async (username: string) => {
- const isExist = await serverFetchJson<IsOperatorExistResponse<Operator>>(
- `${BASE_API_URL}/jop/isOperatorExist`,
- {
- method: "POST",
- body: JSON.stringify({ username }),
- headers: { "Content-Type": "application/json" },
- },
- );
- revalidateTag("po");
- return isExist;
- };
-
- export const isCorrectMachineUsed = async (machineCode: string) => {
- const isExist = await serverFetchJson<isCorrectMachineUsedResponse<Machine>>(
- `${BASE_API_URL}/jop/isCorrectMachineUsed`,
- {
- method: "POST",
- body: JSON.stringify({ machineCode }),
- headers: { "Content-Type": "application/json" },
- },
- );
- revalidateTag("po");
- return isExist;
- };
-
-
- export const fetchJos = cache(async (data?: SearchJoResultRequest) => {
- const queryStr = convertObjToURLSearchParams(data)
- console.log("queryStr", queryStr)
- const fullUrl = `${BASE_API_URL}/jo/getRecordByPage?${queryStr}`;
- console.log("fetchJos full URL:", fullUrl);
- console.log("fetchJos BASE_API_URL:", BASE_API_URL);
- const response = await serverFetchJson<SearchJoResultResponse>(
- `${BASE_API_URL}/jo/getRecordByPage?${queryStr}`,
- {
- method: "GET",
- headers: { "Content-Type": "application/json" },
- next: {
- tags: ["jos"]
- }
- }
- )
- // console.log("fetchJos response:", response)
-
- return response
- })
- export interface PostPickOrderResponse<T = null> {
- id: number | null;
- name: string;
- code: string;
- type?: string;
- message: string | null;
- errorPosition: string
- entity?: T | T[];
- consoCode?: string;
- }
- export interface PickExecutionIssueData {
- type: string;
- pickOrderId: number;
- pickOrderCode: string;
- pickOrderCreateDate: string;
- pickExecutionDate: string;
- pickOrderLineId: number;
- itemId: number;
- itemCode: string;
- itemDescription: string;
- lotId: number|null;
- lotNo: string|null;
- storeLocation: string;
- requiredQty: number;
- actualPickQty: number;
- missQty: number;
- badItemQty: number;
- badPackageQty?: number;
- /** Optional: frontend-only reference to stock_out_line.id for the picked lot. */
- stockOutLineId?: number;
- issueRemark: string;
- pickerName: string;
- handledBy?: number;
- badReason?: string;
- reason?: string;
- }
- /** 无 miss/bad/bad package:仅后端 hold + SOL checked,不写 pick_execution_issue(避免 DUPLICATE)。 */
- export const applyPickExecutionHoldAndChecked = async (data: PickExecutionIssueData) => {
- const result = await serverFetchJson<PostPickOrderResponse>(
- `${BASE_API_URL}/pickExecution/applyHoldAndChecked`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- },
- );
- revalidateTag("pickorder");
- return result;
- };
- export const updateJo = cache(async (data: UpdateJoRequest) => {
- return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/update`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- })
- })
-
- export const releaseJo = cache(async (data: CommonActionJoRequest) => {
- const response = serverFetchJson<CommonActionJoResponse>(`${BASE_API_URL}/jo/release`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- })
-
- // Invalidate the cache after releasing
- revalidateTag("jo");
-
- return response;
- })
-
- export const startJo = cache(async (data: CommonActionJoRequest) => {
- const response = serverFetchJson<CommonActionJoResponse>(`${BASE_API_URL}/jo/start`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- })
-
- // Invalidate the cache after starting
- revalidateTag("jo");
-
- return response;
- })
-
- export const manualCreateJo = cache(async (data: SaveJo) => {
- return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/manualCreate`, {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" }
- })
- })
-
- export const fetchCompletedJobOrderPickOrdersWithCompletedSecondScan = cache(async (userId: number) => {
- return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-orders-with-completed-second-scan/${userId}`, {
- method: "GET",
- headers: { "Content-Type": "application/json" }
- })
- })
- export const fetchCompletedJobOrderPickOrderLotDetails = cache(async (pickOrderId: number) => {
- return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-order-lot-details/${pickOrderId}`, {
- method: "GET",
- headers: { "Content-Type": "application/json" }
- })
- })
- export const fetchCompletedJobOrderPickOrderLotDetailsForCompletedPick = cache(async (pickOrderId: number) => {
- return serverFetchJson<any[]>(`${BASE_API_URL}/jo/completed-job-order-pick-order-lot-details-completed-pick/${pickOrderId}`, {
- method: "GET",
- headers: { "Content-Type": "application/json" }
- })
- })
-
-
-
- export async function PrintPickRecord(request: PrintPickRecordRequest){
- const params = new URLSearchParams();
- params.append('pickOrderId', request.pickOrderId.toString())
- params.append('printerId', request.printerId.toString())
- if (request.printQty !== null && request.printQty !== undefined) {
- params.append('printQty', request.printQty.toString());
- }
- if (request.floor) {
- params.append('floor', request.floor);
- }
- if (request.plasticBoxCartonQty !== null && request.plasticBoxCartonQty !== undefined) {
- params.append('plasticBoxCartonQty', request.plasticBoxCartonQty.toString());
- }
- if (request.plasticBoxCartonQty2f !== null && request.plasticBoxCartonQty2f !== undefined) {
- params.append('plasticBoxCartonQty2f', request.plasticBoxCartonQty2f.toString());
- }
- if (request.plasticBoxCartonQty3f !== null && request.plasticBoxCartonQty3f !== undefined) {
- params.append('plasticBoxCartonQty3f', request.plasticBoxCartonQty3f.toString());
- }
- if (request.plasticBoxCartonQty4f !== null && request.plasticBoxCartonQty4f !== undefined) {
- params.append('plasticBoxCartonQty4f', request.plasticBoxCartonQty4f.toString());
- }
-
- try {
- await serverFetchWithNoContent(
- `${BASE_API_URL}/jo/print-PickRecord?${params.toString()}`,
- { method: "GET" },
- );
- return {
- success: true,
- message: "Print job sent successfully (Pick Record)",
- } as PrintPickRecordResponse;
- } catch (error) {
- const message =
- error instanceof ServerFetchError
- ? error.message
- : error instanceof Error
- ? error.message
- : "Print failed";
- return { success: false, message } as PrintPickRecordResponse;
- }
- }
-
- export interface ExportFGStockInLabelRequest {
- stockInLineId: number;
- }
-
- export const fetchFGStockInLabel = async (data: ExportFGStockInLabelRequest): Promise<FileResponse> => {
- const reportBlob = await serverFetchBlob<FileResponse>(
- `${BASE_API_URL}/jo/FGStockInLabel`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- },
- );
-
- return reportBlob;
- };
- export const updateJoPlanStart = cache(async (data: UpdateJoPlanStartRequest) => {
- return serverFetchJson<SaveJoResponse>(`${BASE_API_URL}/jo/update-jo-plan-start`,
- {
- method: "POST",
- body: JSON.stringify(data),
- headers: { "Content-Type": "application/json" },
- })
- })
-
- export interface UpdateProductProcessLineStatusRequest {
- productProcessLineId: number;
- status: string;
- }
-
-
- export const updateProductProcessLineStatus = async (request: UpdateProductProcessLineStatusRequest) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/update/status`,
- {
- method: "POST",
- body: JSON.stringify(request),
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- export const passProductProcessLine = async (lineId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/pass/${lineId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- export interface UpdateProductProcessLineProcessingTimeSetupTimeChangeoverTimeRequest {
- productProcessLineId: number;
- processingTime: number;
- setupTime: number;
- changeoverTime: number;
- }
- export const updateProductProcessLineProcessingTimeSetupTimeChangeoverTime = async (lineId: number, request: UpdateProductProcessLineProcessingTimeSetupTimeChangeoverTimeRequest) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/update/processingTimeSetupTimeChangeoverTime/${lineId}`,
- {
- method: "POST",
- body: JSON.stringify(request),
- headers: { "Content-Type": "application/json" },
- }
- );
-
- };
- export interface MaterialPickStatusItem {
- id: number;
- pickOrderId: number | null;
- pickOrderCode: string | null;
- jobOrderId: number | null;
- jobOrderCode: string | null;
- itemId: number | null;
- itemCode: string | null;
- itemName: string | null;
- jobOrderQty: number | null;
- uom: string | null;
- pickStartTime: string | null; // ISO datetime string
- pickEndTime: string | null; // ISO datetime string
- numberOfItemsToPick: number;
- numberOfItemsWithIssue: number;
- pickStatus: string | null;
- }
-
- export const fetchMaterialPickStatus = cache(async (date?: string): Promise<MaterialPickStatusItem[]> => {
- const params = new URLSearchParams();
- if (date) params.set("date", date); // yyyy-MM-dd
-
- const qs = params.toString();
- const url = `${BASE_API_URL}/jo/material-pick-status${qs ? `?${qs}` : ""}`;
-
- return await serverFetchJson<MaterialPickStatusItem[]>(
- url,
- {
- method: "GET",
- }
- );
- })
- export interface ProcessStatusInfo {
- processName?: string | null;
- equipmentName?: string | null;
- equipmentDetailName?: string | null;
- /** 經手人姓名(對應 product process line.handler) */
- handlerName?: string | null;
- startTime?: string | null;
- endTime?: string | null;
- isRequired: boolean;
- }
-
- export interface JobProcessStatusResponse {
- jobOrderId: number;
- jobOrderCode: string;
- itemCode: string;
- itemName: string;
- status: string;
- processingTime: number | null;
- setupTime: number | null;
- changeoverTime: number | null;
- planEndTime?: string | null;
- processes: ProcessStatusInfo[];
- }
-
- export const fetchJobProcessStatus = cache(
- async (date?: string, productProcessStatus?: string | null) => {
- const params = new URLSearchParams();
- if (date) params.set("date", date); // yyyy-MM-dd
- if (productProcessStatus && productProcessStatus.length > 0) {
- params.set("productProcessStatus", productProcessStatus);
- }
-
- const qs = params.toString();
- const url = `${BASE_API_URL}/product-process/Demo/JobProcessStatus${qs ? `?${qs}` : ""}`;
-
- return serverFetchJson<JobProcessStatusResponse[]>(url, {
- method: "GET",
- next: { tags: ["jobProcessStatus"] },
- });
- },
- );
-
- // ===== Operator KPI Dashboard =====
-
- export interface OperatorKpiProcessInfo {
- jobOrderId?: number | null;
- jobOrderCode?: string | null;
- productProcessId?: number | null;
- productProcessLineId?: number | null;
- processName?: string | null;
- equipmentName?: string | null;
- equipmentDetailName?: string | null;
- startTime?: string | number[] | null;
- endTime?: string | number[] | null;
- processingTime?: number | null;
- itemCode?: string | null;
- itemName?: string | null;
- }
-
- export interface OperatorKpiResponse {
- operatorId: number;
- operatorName?: string | null;
- staffNo?: string | null;
- totalProcessingMinutes: number;
- totalJobOrderCount: number;
- currentProcesses: OperatorKpiProcessInfo[];
- }
-
- export const fetchOperatorKpi = cache(async (date?: string) => {
- const params = new URLSearchParams();
- if (date) params.set("date", date);
- const qs = params.toString();
- const url = `${BASE_API_URL}/product-process/Demo/OperatorKpi${qs ? `?${qs}` : ""}`;
-
- return serverFetchJson<OperatorKpiResponse[]>(url, {
- method: "GET",
- next: { tags: ["operatorKpi"] },
- });
- });
-
- // ===== Drink Production Qty Dashboard =====
- export interface DrinkProductionQtyProcessStep {
- jobOrderId: number;
- jobOrderCode?: string | null;
- itemCode?: string | null;
- itemName?: string | null;
- seqNo?: number | null;
- processName?: string | null;
- operatorName?: string | null;
- handlerName?: string | null;
- startTime?: string | null;
- endTime?: string | null;
- status?: string | null;
- }
-
- export interface DrinkProductionQtyJobOrderDetail {
- jobOrderId: number;
- jobOrderCode?: string | null;
- productionDate?: string | null;
- reqQty: number;
- productionQty: number;
- jobOrderStatus?: string | null;
- startTime?: string | null;
- assumeTimeNeedMins?: number;
- assumeEndTime?: string | null;
- actualEndTime?: string | null;
- latestStartBy?: string | null;
- processOperators?: string | null;
- processHandlers?: string | null;
- qcUsers?: string | null;
- putAwayUsers?: string | null;
- processSteps?: DrinkProductionQtyProcessStep[];
- }
-
- export interface DrinkProductionQtyResponse {
- itemCode?: string | null;
- itemName?: string | null;
- uom?: string | null;
- totalReqQty: number;
- totalQty: number;
- jobOrders?: DrinkProductionQtyJobOrderDetail[];
- }
-
- /** FP-MTMS Version Checklist | Functions Ref. No. 26 | v1.0.0 | 2026-07-20 */
- export const fetchDrinkProductionQty = cache(
- async (date?: string, view: "actual" | "planned" = "actual") => {
- const params = new URLSearchParams();
- if (date) params.set("date", date);
- params.set("view", view);
- const qs = params.toString();
- const url = `${BASE_API_URL}/product-process/Demo/DrinkProductionQty${qs ? `?${qs}` : ""}`;
-
- return serverFetchJson<DrinkProductionQtyResponse[]>(url, {
- method: "GET",
- next: { tags: ["drinkProductionQty"] },
- });
- },
- );
-
- // ===== Equipment Status Dashboard =====
-
- export interface EquipmentStatusProcessInfo {
- jobOrderId?: number | null;
- jobOrderCode?: string | null;
- productProcessId?: number | null;
- productProcessLineId?: number | null;
- processName?: string | null;
- operatorName?: string | null;
- startTime?: string | number[] | null;
- processingTime?: number | null;
- }
-
- export interface EquipmentStatusPerDetail {
- equipmentDetailId: number;
- equipmentDetailCode?: string | null;
- equipmentDetailName?: string | null;
- equipmentId?: number | null;
- equipmentTypeName?: string | null;
- status: string;
- repairAndMaintenanceStatus?: boolean | null;
- latestRepairAndMaintenanceDate?: string | null;
- lastRepairAndMaintenanceDate?: string | null;
- repairAndMaintenanceRemarks?: string | null;
- currentProcess?: EquipmentStatusProcessInfo | null;
- }
-
- export interface EquipmentStatusByTypeResponse {
- equipmentTypeId: number;
- equipmentTypeName?: string | null;
- details: EquipmentStatusPerDetail[];
- }
-
- export const fetchEquipmentStatus = cache(async () => {
- const url = `${BASE_API_URL}/product-process/Demo/EquipmentStatus`;
- return serverFetchJson<EquipmentStatusByTypeResponse[]>(url, {
- method: "GET",
- next: { tags: ["equipmentStatus"] },
- });
- });
- export const deleteProductProcessLine = async (lineId: number) => {
- return serverFetchJson<any>(
- `${BASE_API_URL}/product-process/Demo/ProcessLine/delete/${lineId}`,
- {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- }
- );
- };
- ;
|