Merge branch 'devlop' of http://47.97.1.152:5880/r/wms-master into devlop
 
	
	
	
	
	
	
	
	
	
	
	
	
	
 |  |  | 
 |  |  | VITE_BASE_IP=192.168.4.24 | 
 |  |  | VITE_BASE_IP=127.0.0.1 | 
 |  |  | # VITE_BASE_IP=47.76.147.249 | 
 |  |  | VITE_BASE_PORT=8080 | 
 
 |  |  | 
 |  |  |   ], | 
 |  |  |   ignorePatterns: ["dist", ".eslintrc.cjs"], | 
 |  |  |   parser: "@typescript-eslint/parser", | 
 |  |  |   "react/jsx-key": [false, { "checkFragmentShorthand": false }], | 
 |  |  |   env: { | 
 |  |  |     browser: true, | 
 |  |  |     es2021: true, | 
 
 |  |  | 
 |  |  |                         </> | 
 |  |  |                     } | 
 |  |  |                     rowClick={(id, resource, record) => false} | 
 |  |  |                     // expand={() => <TaskPanel />} | 
 |  |  |                     // expandSingle={true} | 
 |  |  |                     expand={() => <TaskPanel />} | 
 |  |  |                     expandSingle={true} | 
 |  |  |                     omit={['id', 'createTime', 'createBy', 'memo', 'robotCode', 'exceStatus', 'expDesc', 'expCode', 'sort']} | 
 |  |  |                 > | 
 |  |  |                     <NumberField source="id" /> | 
 
 |  |  | 
 |  |  | import React, { useState, useRef, useEffect, useMemo } from "react"; | 
 |  |  | import { Box, Card, CardContent, Grid, Typography, Tooltip } from '@mui/material'; | 
 |  |  | import { | 
 |  |  |     useTranslate, | 
 |  |  |     List, | 
 |  |  |     DatagridConfigurable, | 
 |  |  |     SearchInput, | 
 |  |  |     TopToolbar, | 
 |  |  |     SelectColumnsButton, | 
 |  |  |     EditButton, | 
 |  |  |     FilterButton, | 
 |  |  |     CreateButton, | 
 |  |  |     ExportButton, | 
 |  |  |     BulkDeleteButton, | 
 |  |  |     WrapperField, | 
 |  |  |     useRecordContext, | 
 |  |  |     useTranslate, | 
 |  |  |     useNotify, | 
 |  |  |     useListContext, | 
 |  |  |     FunctionField, | 
 |  |  |     TextField, | 
 |  |  |     NumberField, | 
 |  |  |     DateField, | 
 |  |  |     BooleanField, | 
 |  |  |     ReferenceField, | 
 |  |  |     TextInput, | 
 |  |  |     DateTimeInput, | 
 |  |  |     DateInput, | 
 |  |  |     SelectInput, | 
 |  |  |     NumberInput, | 
 |  |  |     ReferenceInput, | 
 |  |  |     ReferenceArrayInput, | 
 |  |  |     AutocompleteInput, | 
 |  |  |     DeleteButton, | 
 |  |  | } from 'react-admin'; | 
 |  |  | import PanelTypography from "../components/PanelTypography"; | 
 |  |  | import * as Common from '@/utils/common' | 
 |  |  | import { styled } from '@mui/material/styles'; | 
 |  |  | import PageDrawer from "../components/PageDrawer"; | 
 |  |  | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; | 
 |  |  | import * as Common from '@/utils/common'; | 
 |  |  |  | 
 |  |  | const StyledDatagrid = styled(DatagridConfigurable)(({ theme }) => ({ | 
 |  |  |     '& .css-1vooibu-MuiSvgIcon-root': { | 
 |  |  |         height: '.9em' | 
 |  |  |     }, | 
 |  |  |     '& .RaDatagrid-row': { | 
 |  |  |         cursor: 'auto' | 
 |  |  |     }, | 
 |  |  |     '& .column-name': { | 
 |  |  |     }, | 
 |  |  |     '& .opt': { | 
 |  |  |         width: 200 | 
 |  |  |     }, | 
 |  |  | })); | 
 |  |  |  | 
 |  |  | const filters = [ | 
 |  |  |     <SearchInput source="condition" alwaysOn />, | 
 |  |  |     <DateInput label='common.time.after' source="timeStart"  />, | 
 |  |  |     <DateInput label='common.time.before' source="timeEnd" />, | 
 |  |  |     <NumberInput source="taskId" label="table.field.taskItem.taskId" />, | 
 |  |  |     <NumberInput source="orderId" label="table.field.taskItem.orderId" />, | 
 |  |  |     <NumberInput source="orderType" label="table.field.taskItem.orderType" />, | 
 |  |  |     <NumberInput source="orderItemId" label="table.field.taskItem.orderItemId" />, | 
 |  |  |     <NumberInput source="matnrId" label="table.field.taskItem.matnrId" />, | 
 |  |  |     <TextInput source="maktx" label="table.field.taskItem.maktx" />, | 
 |  |  |     <TextInput source="matnrCode" label="table.field.taskItem.matnrCode" />, | 
 |  |  |     <TextInput source="unit" label="table.field.taskItem.unit" />, | 
 |  |  |     <NumberInput source="anfme" label="table.field.taskItem.anfme" />, | 
 |  |  |     <TextInput source="batch" label="table.field.taskItem.batch" />, | 
 |  |  |     <TextInput source="spec" label="table.field.taskItem.spec" />, | 
 |  |  |     <TextInput source="model" label="table.field.taskItem.model" />, | 
 |  |  |     <TextInput label="common.field.memo" source="memo" />, | 
 |  |  |     <SelectInput | 
 |  |  |         label="common.field.status" | 
 |  |  |         source="status" | 
 |  |  |         choices={[ | 
 |  |  |             { id: '1', name: 'common.enums.statusTrue' }, | 
 |  |  |             { id: '0', name: 'common.enums.statusFalse' }, | 
 |  |  |         ]} | 
 |  |  |         resettable | 
 |  |  |     />, | 
 |  |  | ] | 
 |  |  |  | 
 |  |  | const TaskPanel = () => { | 
 |  |  |     const record = useRecordContext(); | 
 |  |  |     if (!record) return null; | 
 |  |  |     const translate = useTranslate(); | 
 |  |  |     const [createDialog, setCreateDialog] = useState(false); | 
 |  |  |     const [drawerVal, setDrawerVal] = useState(false); | 
 |  |  |  | 
 |  |  |     return ( | 
 |  |  |         <> | 
 |  |  |             <Box display="flex"> | 
 |  |  | 
 |  |  |                     actions={( | 
 |  |  |                         <TopToolbar> | 
 |  |  |                             <FilterButton /> | 
 |  |  |                             {/* <MyCreateButton onClick={() => { setCreateDialog(true) }} /> */} | 
 |  |  |                             <SelectColumnsButton preferenceKey='taskItem' /> | 
 |  |  |                             {/* <MyExportButton /> */} | 
 |  |  |                         </TopToolbar> | 
 |  |  |                     )} | 
 |  |  |                     perPage={DEFAULT_PAGE_SIZE} | 
 |  |  |                 > | 
 |  |  |                     <StyledDatagrid | 
 |  |  |                         preferenceKey='taskItem' | 
 |  |  |                         // bulkActionButtons={() => <BulkDeleteButton mutationMode={OPERATE_MODE} />} | 
 |  |  |                         bulkActionButtons={false} | 
 |  |  |                         rowClick={(id, resource, record) => false} | 
 |  |  |                         // expand={() => <TaskItemPanel />} | 
 |  |  |                         expandSingle={true} | 
 |  |  |                         omit={['id', 'createTime', 'createBy', 'memo', 'taskId', 'orderId', 'orderItemId', 'matnrId']} | 
 |  |  |                     > | 
 |  |  | 
 |  |  |                         <TextField source="batch" label="table.field.taskItem.batch" /> | 
 |  |  |                         <TextField source="spec" label="table.field.taskItem.spec" /> | 
 |  |  |                         <TextField source="model" label="table.field.taskItem.model" /> | 
 |  |  |  | 
 |  |  |                         <ReferenceField source="updateBy" label="common.field.updateBy" reference="user" link={false} sortable={false}> | 
 |  |  |                             <TextField source="nickname" /> | 
 |  |  |                         </ReferenceField> | 
 
 |  |  | 
 |  |  | } from 'react-admin'; | 
 |  |  | import { Box, Typography, Card, Stack } from '@mui/material'; | 
 |  |  | import { styled } from '@mui/material/styles'; | 
 |  |  | import TaskItemCreate from "./TaskItemCreate"; | 
 |  |  | import TaskItemPanel from "./TaskItemPanel"; | 
 |  |  | import EmptyData from "../components/EmptyData"; | 
 |  |  | import MyCreateButton from "../components/MyCreateButton"; | 
 |  |  | import MyExportButton from '../components/MyExportButton'; | 
 |  |  | import PageDrawer from "../components/PageDrawer"; | 
 |  |  | import MyField from "../components/MyField"; | 
 |  |  | import { PAGE_DRAWER_WIDTH, OPERATE_MODE, DEFAULT_PAGE_SIZE } from '@/config/setting'; | 
 |  |  | 
 |  |  |  | 
 |  |  | const TaskItemList = () => { | 
 |  |  |     const translate = useTranslate(); | 
 |  |  |  | 
 |  |  |     const [createDialog, setCreateDialog] = useState(false); | 
 |  |  |     const [drawerVal, setDrawerVal] = useState(false); | 
 |  |  |  | 
 
 |  |  | 
 |  |  |  | 
 |  |  | import com.alibaba.fastjson.JSONObject; | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | 
 |  |  | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; | 
 |  |  | import com.vincent.rsf.framework.common.Cools; | 
 |  |  | import com.vincent.rsf.framework.common.R; | 
 |  |  | import com.vincent.rsf.framework.exception.CoolException; | 
 |  |  | 
 |  |  |                     .setSplrBatch(dto.getSplrBatch()) | 
 |  |  |                     .setMatnrCode(matnr.getCode()) | 
 |  |  |                     .setMatnrId(matnr.getId()) | 
 |  |  |                     .setMatnrName(matnr.getName()) | 
 |  |  |                     .setMaktx(matnr.getName()) | 
 |  |  |                     //库存单位为最小单位 | 
 |  |  |                     .setUnit(dto.getStockUnit()) | 
 |  |  |                     .setStockUnit(dto.getStockUnit()) | 
 |  |  | 
 |  |  |         return fieldsMapper.selectList(new LambdaQueryWrapper<Fields>().eq(Fields::getFlagEnable, 1).eq(Fields::getStatus, 1)); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @author Ryan | 
 |  |  |      * @description 获取组盘明细 | 
 |  |  |      * @param | 
 |  |  |      * @return | 
 |  |  |      * @time 2025/4/7 16:58 | 
 |  |  |      */ | 
 |  |  |     @Override | 
 |  |  |     public R getDeltByCode(String code) { | 
 |  |  |         return R.ok(warehouseAreasItemService.getOne(new LambdaQueryWrapper<WarehouseAreasItem>().eq(WarehouseAreasItem::getTrackCode, code))); | 
 |  |  |         //TODO 后续需根据策略配置,获取组拖数据。如:混装,按批次混装等 | 
 |  |  |         LambdaQueryWrapper<WarehouseAreasItem> queryWrapper = new QueryWrapper<WarehouseAreasItem>() | 
 |  |  |                 .select("SUM(anfme) as anfme, track_code, asn_code, id, splr_batch, ispt_result, plat_item_id, batch, qty, work_qty, matnr_code, matnr_id, maktx").lambda() | 
 |  |  |                 .eq(WarehouseAreasItem::getTrackCode, code) | 
 |  |  |                 .groupBy(WarehouseAreasItem::getSplrBatch, WarehouseAreasItem::getAsnId, WarehouseAreasItem::getAreaId, WarehouseAreasItem::getMatnrId); | 
 |  |  |         return R.ok(warehouseAreasItemService.getOne(queryWrapper)); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  | 
 |  |  |         return waitPakinService.mergeItems(waitPakin); | 
 |  |  |     } | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * @author Ryan | 
 |  |  |      * @description 解绑 | 
 |  |  |      * @param param | 
 |  |  |      * @return | 
 |  |  |      */ | 
 |  |  |     @Override | 
 |  |  |     public WaitPakin unBind(WaitPakinParam param) { | 
 |  |  |         return waitPakinService.unBind(param); | 
 
 |  |  | 
 |  |  |     @ApiModelProperty("单据明细ID") | 
 |  |  |     private Long asnItemId; | 
 |  |  |  | 
 |  |  |     @ApiModelProperty("行号") | 
 |  |  |     private String platItemId; | 
 |  |  |  | 
 |  |  |     @ApiModelProperty("质检结果") | 
 |  |  |     private Short isptResult; | 
 |  |  |  | 
 |  |  |     @ApiModelProperty("已收货数量") | 
 |  |  |     private Double qty; | 
 |  |  |  | 
 |  |  |     @ApiModelProperty("执行数量") | 
 |  |  |     private Double workQty; | 
 |  |  |  | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 区域名称 | 
 |  |  |      */ | 
 |  |  | 
 |  |  |      * 物料名称 | 
 |  |  |      */ | 
 |  |  |     @ApiModelProperty(value= "物料名称") | 
 |  |  |     private String matnrName; | 
 |  |  |     private String maktx; | 
 |  |  |  | 
 |  |  |     /** | 
 |  |  |      * 物料编码 | 
 |  |  | 
 |  |  |         this.areaId = areaId; | 
 |  |  |         this.areaName = areaName; | 
 |  |  |         this.matnrId = matnrId; | 
 |  |  |         this.matnrName = matnrName; | 
 |  |  |         this.maktx = matnrName; | 
 |  |  |         this.matnrCode = matnrCode; | 
 |  |  |         this.trackCode = trackCode; | 
 |  |  |         this.anfme = anfme; | 
 
 |  |  | 
 |  |  |  | 
 |  |  |     //质检状态 | 
 |  |  |     PAKIN_IO_STATUS_HOLD("0", "待入库"), | 
 |  |  |     QLY_ISPT_STAS_DONE("1", "组拖完成"), | 
 |  |  |     PAKIN_IO_STATUS_DONE("1", "组拖完成"), | 
 |  |  |     PAKIN_IO_STATUS_TASK_EXCE("2", "任务执行中"), | 
 |  |  |     PAKIN_IO_STATUS_TASK_DONE("3", "任务完成") | 
 |  |  |             ; | 
 
 |  |  | 
 |  |  | import com.vincent.rsf.server.common.utils.CommonUtil; | 
 |  |  | import com.vincent.rsf.server.common.utils.DateUtils; | 
 |  |  | import com.vincent.rsf.server.manager.entity.*; | 
 |  |  | import com.vincent.rsf.server.manager.enums.PakinIOStatus; | 
 |  |  | import com.vincent.rsf.server.manager.service.*; | 
 |  |  | import com.vincent.rsf.server.system.constant.SerialRuleCode; | 
 |  |  | import com.vincent.rsf.server.system.utils.SerialRuleUtils; | 
 |  |  | 
 |  |  |      * @return | 
 |  |  |      * @time 2025/3/29 12:36 | 
 |  |  |      */ | 
 |  |  |     @Scheduled(cron = "0/5 * * * * ?") | 
 |  |  | //    @Scheduled(cron = "0 0/05 * * * ?  ") | 
 |  |  |     @Scheduled(cron = "0/25 * * * * ?") | 
 |  |  |     @Transactional(rollbackFor = Exception.class) | 
 |  |  |     public void pakinLog() { | 
 |  |  |         List<WaitPakin>  pakinIds = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>().eq(WaitPakin::getIoStatus, 2).select(WaitPakin::getId)); | 
 |  |  |         List<WaitPakin>  pakinIds = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>() | 
 |  |  |                 .eq(WaitPakin::getIoStatus, Short.valueOf(PakinIOStatus.PAKIN_IO_STATUS_TASK_DONE.val)) | 
 |  |  |                 .select(WaitPakin::getId)); | 
 |  |  |         if (pakinIds.isEmpty()) { | 
 |  |  |             return; | 
 |  |  |         } | 
 |  |  | 
 |  |  |         if (!waitPakinItemLogService.saveBatch(itemLogs)) { | 
 |  |  |             throw new CoolException("历史明细档保存失败!!"); | 
 |  |  |         } | 
 |  |  |         if (!waitPakinService.removeByIds(pakins)) { | 
 |  |  |         if (!waitPakinService.removeByIds(list)) { | 
 |  |  |             throw new CoolException("原单据删除失败!!"); | 
 |  |  |         } | 
 |  |  |         if (!waitPakinItemService.removeByIds(pakinItems)) { | 
 |  |  |         if (!waitPakinItemService.remove(new LambdaQueryWrapper<WaitPakinItem>().in(WaitPakinItem::getPakinId, list))) { | 
 |  |  |             throw new CoolException("原单据明细删除失败!!"); | 
 |  |  |         } | 
 |  |  |     } | 
 
 |  |  | 
 |  |  |         List<Long> ids = waitPakin.stream().map(WaitPakin::getId).collect(Collectors.toList()); | 
 |  |  |         List<WaitPakin> waitPakins = waitPakinService.list(new LambdaQueryWrapper<WaitPakin>() | 
 |  |  |                 .in(WaitPakin::getId, ids) | 
 |  |  |                 .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.QLY_ISPT_STAS_DONE.val))); | 
 |  |  |                 .eq(WaitPakin::getIoStatus, Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val))); | 
 |  |  |         if (waitPakins.isEmpty()) { | 
 |  |  |             throw new CoolException("请检查组拖状态是否完成!!"); | 
 |  |  |         } | 
 |  |  | 
 |  |  |             if (!this.save(task)) { | 
 |  |  |                 throw new CoolException("任务保存失败!!"); | 
 |  |  |             } | 
 |  |  |             if (!locService.update(new LambdaUpdateWrapper<Loc>().eq(Loc::getCode, pakin.getCode()) | 
 |  |  |             if (!locService.update(new LambdaUpdateWrapper<Loc>().eq(Loc::getCode, task.getTargLoc()) | 
 |  |  |                     .set(Loc::getUseStatus, LocStsType.LOC_STS_TYPE_S.type).set(Loc::getBarcode, pakin.getBarcode()))) { | 
 |  |  |                 throw new CoolException("库位预约失败!!"); | 
 |  |  |             } | 
 
 |  |  | 
 |  |  |         } | 
 |  |  |         pakin.setCode(ruleCode) | 
 |  |  |                 //状态修改为入库中 | 
 |  |  |                 .setIoStatus(Short.parseShort(PakinIOStatus.QLY_ISPT_STAS_DONE.val)) | 
 |  |  |                 .setIoStatus(Short.parseShort(PakinIOStatus.PAKIN_IO_STATUS_DONE.val)) | 
 |  |  |                 .setAnfme(sum) | 
 |  |  |                 .setBarcode(waitPakin.getBarcode()); | 
 |  |  |         if (!this.save(pakin)) { | 
 |  |  | 
 |  |  |                     .setAsnId(item.getAsnId()) | 
 |  |  |                     .setAsnCode(item.getAsnCode()) | 
 |  |  |                     .setAsnItemId(item.getId()) | 
 |  |  |                     .setMatnrCode(item.getMatnrCode()) | 
 |  |  |                     .setBatch(item.getSplrBatch()) | 
 |  |  |                     .setUnit(item.getStockUnit()) | 
 |  |  |                     .setFieldsIndex(item.getFieldsIndex()) | 
 |  |  |                     .setUnit(item.getStockUnit()) | 
 |  |  |                     .setMatnrId(item.getMatnrId()) | 
 |  |  |                     .setMaktx(item.getMaktx()) | 
 |  |  |                     .setMatnrCode(item.getMatnrCode()); | 
 |  |  |             for (PakinItem waitPakinItem : waitPakin.getItems()) { | 
 |  |  |                 if (waitPakinItem.getTrackCode().equals(item.getTrackCode())) { | 
 |  |  |                     Double v = item.getWorkQty() + waitPakinItem.getReceiptQty(); | 
 |  |  |                     pakinItem.setWorkQty(v) | 
 |  |  | //                    Double v = item.getWorkQty() + waitPakinItem.getReceiptQty(); | 
 |  |  |                     pakinItem | 
 |  |  |                             .setWorkQty(waitPakinItem.getReceiptQty()) | 
 |  |  |                             .setAnfme(waitPakinItem.getReceiptQty()) | 
 |  |  |                             .setTrackCode(waitPakinItem.getTrackCode()); | 
 |  |  |                     /**更新单据执行中库存*/ | 
 |  |  |                     if (v.compareTo(item.getAnfme()) > 0) {throw new CoolException("执行中数量大于收货数量!!");} | 
 |  |  |                     if (!asnOrderItemService.update(new LambdaUpdateWrapper<AsnOrderItem>() | 
 |  |  |                             .eq(AsnOrderItem::getTrackCode, waitPakinItem.getTrackCode()).set(AsnOrderItem::getWorkQty, v))) { | 
 |  |  |                         throw new CoolException("执行中库存更新失败!!"); | 
 |  |  |                     } | 
 |  |  | //                    if (v.compareTo(item.getAnfme()) > 0) {throw new CoolException("执行中数量大于收货数量!!");} | 
 |  |  | //                    if (!asnOrderItemService.update(new LambdaUpdateWrapper<AsnOrderItem>() | 
 |  |  | //                            .eq(AsnOrderItem::getTrackCode, waitPakinItem.getTrackCode()).set(AsnOrderItem::getWorkQty, v))) { | 
 |  |  | //                        throw new CoolException("执行中库存更新失败!!"); | 
 |  |  | //                    } | 
 |  |  |                 } | 
 |  |  |             } | 
 |  |  |             items.add(pakinItem); | 
 
 |  |  | 
 |  |  |   #  global-config:
 | 
 |  |  |   #    field-strategy: 0
 | 
 |  |  |   configuration:
 | 
 |  |  | #    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
 | 
 |  |  |     log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
 | 
 |  |  |     map-underscore-to-camel-case: true
 | 
 |  |  |     cache-enabled: true
 | 
 |  |  |     call-setters-on-nulls: true
 |