package com.vincent.rsf.server.api.service.impl; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.vincent.rsf.framework.common.Cools; import com.vincent.rsf.framework.common.R; import com.vincent.rsf.framework.exception.CoolException; import com.vincent.rsf.server.api.controller.params.CheckObjParams; import com.vincent.rsf.server.api.controller.params.OpStockParams; import com.vincent.rsf.server.api.controller.params.OtherReceiptParams; import com.vincent.rsf.server.api.controller.params.ReceiptParams; import com.vincent.rsf.server.api.entity.dto.CheckObjDto; import com.vincent.rsf.server.api.entity.dto.InspectDetlDto; import com.vincent.rsf.server.api.entity.dto.InspectItemDto; import com.vincent.rsf.server.api.entity.dto.ReceiptDetlsDto; import com.vincent.rsf.server.api.entity.enums.OrderWorkType; import com.vincent.rsf.server.api.service.MobileService; import com.vincent.rsf.server.common.config.ConfigProperties; import com.vincent.rsf.server.common.enums.WarehouseAreaType; import com.vincent.rsf.server.common.security.JwtSubject; import com.vincent.rsf.server.common.utils.CommonUtil; import com.vincent.rsf.server.common.utils.JwtUtil; import com.vincent.rsf.server.manager.controller.params.IsptItemsParams; import com.vincent.rsf.server.manager.controller.params.WaitPakinParam; import com.vincent.rsf.server.manager.entity.*; import com.vincent.rsf.server.manager.mapper.*; import com.vincent.rsf.server.manager.service.*; import com.vincent.rsf.server.system.constant.CodeRes; import com.vincent.rsf.server.system.constant.SerialRuleCode; import com.vincent.rsf.server.system.controller.param.LoginParam; import com.vincent.rsf.server.system.controller.result.LoginResult; import com.vincent.rsf.server.system.entity.*; import com.vincent.rsf.server.system.mapper.FieldsMapper; import com.vincent.rsf.server.system.mapper.TenantMapper; import com.vincent.rsf.server.system.mapper.UserMapper; import com.vincent.rsf.server.system.service.FieldsItemService; import com.vincent.rsf.server.system.service.FieldsService; import com.vincent.rsf.server.system.service.UserLoginService; import com.vincent.rsf.server.system.utils.SerialRuleUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.*; /** * @author Ryan * @version 1.0 * @title MobileServiceImpl * @description * @create 2025/3/10 08:07 */ @Service public class MobileServiceImpl implements MobileService { @Value("${super.pwd}") private String superPwd; @Resource private ConfigProperties configProperties; @Autowired private TenantMapper tenantService; @Autowired private UserMapper userService; @Autowired private UserLoginService userLoginService; @Autowired private WarehouseAreasItemService warehouseAreasItemService; @Autowired private WarehouseAreasService warehouseAreasService; @Resource private AsnOrderItemMapper asnOrderItemMapper; @Autowired private AsnOrderService asnOrderMapper; @Resource private MatnrMapper matnrMapper; @Resource private QlyInspectMapper qlyInspectMapper; @Autowired private QlyIsptItemService qlyIsptItemService; @Resource private StockItemMapper stockItemMapper; @Resource private PurchaseItemMapper purchaseItemMapper; @Resource private FieldsMapper fieldsMapper; @Autowired private IsptHistoriesMapper isptHistoriesMapper; @Autowired private AsnOrderLogService asnOrderLogService; @Autowired private WaitPakinService waitPakinService; @Autowired private WaitPakinItemService waitPakinItemService; @Autowired private AsnOrderItemLogService asnOrderItemLogService; @Autowired private FieldsItemService fieldsItemService; @Autowired private LocService locService; /** * @author Ryan * @description 手持PDA登录接口 * @params LoginParam param, HttpServletRequest request * @return * @time 2025/3/10 15:36 */ @Override public R login(LoginParam param, HttpServletRequest request) { User user = userService.selectByUsernameWithoutTenant(param.getUsername(), null); if (param.getUsername().equals("super") && param.getPassword().equals(Cools.md5(superPwd))) { Map res = new HashMap<>(); res.put("username", param.getUsername()); res.put("token", JwtUtil.buildToken(new JwtSubject(param.getUsername(), user.getTenantId()), configProperties.getTokenExpireTime(), configProperties.getTokenKey())); return R.ok(res); } if (Cools.isEmpty(user)) { return R.parse(CodeRes.USER_10001); } if (user.getStatus() != 1) { return R.parse(CodeRes.USER_10002); } if (!user.getPassword().equals(param.getPassword())) { return R.parse(CodeRes.USER_10003); } String accessToken = JwtUtil.buildToken(new JwtSubject(param.getUsername(), user.getTenantId()), configProperties.getTokenExpireTime(), configProperties.getTokenKey()); userLoginService.saveAsync(user.getId(), accessToken, UserLogin.TYPE_LOGIN, user.getTenantId(), null, request); Tenant tenant = tenantService.selectById(user.getTenantId()); return R.ok("Sign In Success").add(new LoginResult(accessToken, user, tenant.getName())); } /** * @author Ryan * @description 扫码获取收货明细 * @param barcode * @return * @time 2025/3/10 15:37 */ @Override public R getOrderByCode(String barcode) { if (StringUtils.isBlank(barcode)) { return R.error("标签码不能为空!!"); } List asnOrderItem = asnOrderItemMapper.selectList(new LambdaQueryWrapper().eq(AsnOrderItem::getTrackCode, barcode)); if (Objects.isNull(asnOrderItem)) { throw new CoolException("单据明细不存在!!"); } return getAsnOrderItem(asnOrderItem); } /** * @author Ryan * @description 收货至收货区 * @param params * @return * @time 2025/3/10 15:41 */ @Override @Transactional(rollbackFor = Exception.class) public R receiptToWarehouse(ReceiptParams params) { if (params.getReceipts().isEmpty()) { throw new CoolException("收货明细不能为空!!"); } if (Objects.isNull(params.getWhAreaId())) { throw new CoolException("库区标识不能为空!!"); } WarehouseAreas areasItem = warehouseAreasService.getOne(new LambdaQueryWrapper() .eq(WarehouseAreas::getId, params.getWhAreaId())); if (Objects.isNull(areasItem)) { throw new CoolException("数据错误:当前库区不存在!!"); } //获取已启用的动态扩展字 List fields = fieldsMapper.selectList(new LambdaQueryWrapper() .eq(Fields::getFlagEnable, 1) .eq(Fields::getStatus, 1)); List receipts = params.getReceipts(); List allOrders = new ArrayList<>(); double receiptQty = receipts.stream().mapToDouble(ReceiptDetlsDto::getReceiptQty).sum(); String asnCode = receipts.stream().findFirst().get().getAsnCode(); AsnOrder asnOrder = asnOrderMapper.getOne(new LambdaQueryWrapper() .eq(AsnOrder::getCode, asnCode)); if (Objects.isNull(asnOrder)) { throw new CoolException("数据错误:主单不存在!!"); } asnOrder.setQty(receiptQty); if (!asnOrderMapper.updateById(asnOrder)) { throw new CoolException("已收货数量修改失败!!"); } receipts.forEach(dto -> { Matnr matnr = matnrMapper.selectById(dto.getMatnrId()); if (Objects.isNull(matnr)) { throw new CoolException("数据错误:当前物料不存在!!"); } if (Objects.isNull(dto.getReceiptQty())) { throw new CoolException("收货数据不能为空!!"); } if (dto.getReceiptQty().compareTo(dto.getAnfme()) > 0) { throw new CoolException("收货数量不能大于采购数量!!"); } AsnOrderItem orderItem = asnOrderItemMapper.selectOne(new LambdaQueryWrapper() .eq(AsnOrderItem::getAsnCode, asnCode) .eq(AsnOrderItem::getMatnrId, dto.getMatnrId())); if (Objects.isNull(orderItem)) { throw new CoolException("通知单明细不存在!!"); } if (Objects.isNull(dto.getReceiptQty()) || Double.compare(dto.getReceiptQty(), 0.0) == 0) { throw new CoolException("收货数量不能为零!!"); } orderItem.setQty(dto.getReceiptQty()) .setProdTime(dto.getProdTime()); if (asnOrderItemMapper.updateById(orderItem) < 1) { throw new CoolException("通知单明细数量修改失败!!"); } WarehouseAreasItem item = new WarehouseAreasItem(); // SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // String format = null; // if (Objects.isNull(dto.getProdTime())) { // format = dateFormat.format(dto.getProdTime()); // } item.setBarcode(dto.getBarcode()) .setAreaName(areasItem.getName()) .setAreaId(areasItem.getId()) .setProdTime(dto.getProdTime()) .setWeight(dto.getWeigth()) .setStockUnit(dto.getStockUnit()) .setBatch(SerialRuleUtils.generateRuleCode(SerialRuleCode.SYS_RECEIPT_BATCH, dto)) .setAnfme(dto.getReceiptQty()) .setSplrBtch(dto.getSplrBatch()) .setMatnrCode(matnr.getCode()) .setMatnrId(matnr.getId()) .setMatnrName(matnr.getName()) //库存单位为最小单位 .setUnit(dto.getStockUnit()) .setStockUnit(dto.getStockUnit()) .setWeight(matnr.getWeight()) .setShipperId(matnr.getShipperId()); //TODO 供应商标识未设置,标识由PO单供应商编码转换 if (!Objects.isNull(fields)) { if (!Objects.isNull(dto.getExtendFields())) { //获取16位uuid String uuid16 = CommonUtil.randomUUID16(); Map extendFields = dto.getExtendFields(); //字段集合申明 List fieldsItems = new ArrayList<>(); extendFields.keySet().forEach(key -> { fields.forEach(obj -> { //判断key值与fields表字段是否相同 if (obj.getFields().equals(key)) { FieldsItem fieldsItem = new FieldsItem(); fieldsItem.setMatnrId(matnr.getId()).setFieldsId(obj.getId()) .setShiperId(matnr.getShipperId()) .setValue(extendFields.get(key).toString()) .setUuid(uuid16); fieldsItems.add(fieldsItem); //唯一标识入库 item.setFieldsIndex(uuid16); } }); }); if (!fieldsItemService.saveBatch(fieldsItems)) { throw new CoolException("扩展字段保存失败!!"); } } } allOrders.add(item); }); if (!warehouseAreasItemService.saveBatch(allOrders)) { throw new CoolException("收货失败!!"); } //获取采购数量 double purQty = receipts.stream().mapToDouble(ReceiptDetlsDto::getPurQty).sum(); BigDecimal subtract = BigDecimal.valueOf(receiptQty).subtract(BigDecimal.valueOf(purQty)); //判断已收货数量是否小于等于采购数量 if (subtract.compareTo(new BigDecimal("0.0")) <= 0) { asnOrder.setRleStatus(Short.valueOf("1")); //日志表操作 operateOrderLogs(asnOrder); } return R.ok("操作成功"); } /** * @author Ryan * @description 删除原主单及明细,加入历史档 * @param * @return * @time 2025/3/19 19:53 */ private void operateOrderLogs(AsnOrder asnOrder) { if (!asnOrderMapper.removeById(asnOrder.getId())) { throw new CoolException("原单据删除失败!!"); } AsnOrderLog orderLog = new AsnOrderLog(); BeanUtils.copyProperties(asnOrder, orderLog); orderLog.setAsnId(asnOrder.getId()); if (!asnOrderLogService.save(orderLog)) { throw new CoolException("主单历史档添加失败!!"); } List logs = new ArrayList<>(); List items = asnOrderItemMapper.selectList(new LambdaQueryWrapper().eq(AsnOrderItem::getAsnId, asnOrder.getId())); items.forEach(item -> { AsnOrderItemLog itemLog = new AsnOrderItemLog(); BeanUtils.copyProperties(item, itemLog); itemLog.setAsnItemId(itemLog.getId()) .setAsnId(item.getAsnId()); logs.add(itemLog); }); if (!asnOrderItemLogService.saveBatch(logs)) { throw new CoolException("通知单明细历史档保存失败!!"); } if (asnOrderItemMapper.delete(new LambdaQueryWrapper().eq(AsnOrderItem::getAsnId, asnOrder.getId())) < 1) { throw new CoolException("原单据明细删除失败!!"); } } /** * @author Ryan * @description 其它收货 * @param params * @return */ @Override public R otherReceipt(OtherReceiptParams params) { if (Objects.isNull(params.getAsnCode())) { throw new CoolException("通知单不能为空!!"); } List asnOrderItem = asnOrderItemMapper.selectList(new LambdaQueryWrapper() .eq(AsnOrderItem::getAsnCode, params.getAsnCode()) .eq(!Objects.isNull(params.getTrackCode()) ,AsnOrderItem::getTrackCode, params.getTrackCode())); if (Objects.isNull(asnOrderItem)) { throw new CoolException("单据明细不存在!!"); } return getAsnOrderItem(asnOrderItem); } /** * @author Ryan * @description 获取所有通知单 * @return */ @Override public List getAllAsnOrders() { List asnOrders = asnOrderMapper.list(new LambdaQueryWrapper().eq(AsnOrder::getWkType, OrderWorkType.ORDER_PURCHASE_IN.type)); return asnOrders; } /** * @author Ryan * @description 获取收货区 * @param * @return * @time 2025/3/11 10:12 */ @Override public R getReceiptAreas() { return R.ok(warehouseAreasService.list(new LambdaQueryWrapper().eq(WarehouseAreas::getType, WarehouseAreaType.WAREHOUSE_AREA_RECEIPT.type))); } /** * @author Ryan * @description 获取所有启用动态字段 * @param * @return * @time 2025/3/12 09:23 */ @Override public List getDynamicFields() { return fieldsMapper.selectList(new LambdaQueryWrapper().eq(Fields::getFlagEnable, 1).eq(Fields::getStatus, 1)); } @Override public R getDeltByCode(String code) { return R.ok(asnOrderItemMapper.selectOne(new LambdaQueryWrapper().eq(AsnOrderItem::getTrackCode, code))); } /** * @author Ryan * @description PDA组拖 * @param * @return * @time 2025/3/29 14:26 */ @Override public WaitPakin mergeItems(WaitPakinParam waitPakin) { return waitPakinService.mergeItems(waitPakin); } @Override public WaitPakin unBind(WaitPakinParam param) { return waitPakinService.unBind(param); } /** * 报检功能 * @param code * @param loginUserId * @return */ @Override public R inspect(String code, Long loginUserId) { AsnOrder asnOrders = asnOrderMapper.getOne(new LambdaQueryWrapper().eq(AsnOrder::getCode, code)); if (Objects.isNull(asnOrders)) { throw new CoolException("单据不存在!!"); } InspectDetlDto detlDto = new InspectDetlDto(); detlDto.setCode(asnOrders.getCode()).setId(asnOrders.getId()).setPoCode(asnOrders.getPoCode()); List orderItems = asnOrderItemMapper.selectList(new LambdaQueryWrapper().eq(AsnOrderItem::getAsnCode, code)); if (orderItems.isEmpty()) { detlDto.setItems(new ArrayList<>()); } else { List itemDtos = new ArrayList<>(); orderItems.forEach(dto -> { InspectItemDto itemDto = new InspectItemDto(); if (!Objects.isNull(dto.getMatnrCode())) { Matnr matnr = matnrMapper.selectOne(new LambdaQueryWrapper().eq(Matnr::getCode, dto.getMatnrCode())); itemDto.setGroup(matnr.getGroupCode()); } itemDto.setMaktx(dto.getMaktx()) .setMatnrCode(dto.getMatnrCode()) .setPurUnit(dto.getPurUnit()) .setSuplierCode(dto.getSplrCode()) .setSuplierName(dto.getSplrName()) .setPurQty(dto.getPurQty()); itemDtos.add(itemDto); }); detlDto.setItems(itemDtos); } List histories = isptHistoriesMapper.selectList(new LambdaQueryWrapper().eq(IsptHistories::getAsnId, asnOrders.getId())); detlDto.setHistories(histories); return R.ok(detlDto); } /** * @author Ryan * @description 提交报检 * @param * @return * @time 2025/4/1 16:47 */ @Override public R confirmIspt(String id) { if (org.apache.commons.lang3.StringUtils.isBlank(id)) { throw new CoolException("参数不能为空!!"); } AsnOrder asnOrder = asnOrderMapper.getById(id); if (Objects.isNull(asnOrder)) { throw new CoolException("单据不存在!!"); } List orders = new ArrayList<>(); orders.add(asnOrder); if (asnOrderMapper.notifyInspect(orders)) { return R.ok("上报成功!!"); }else { return R.error("上报失败!!"); } } /** * 通过物料,质检单获取需要质检单据 * @param params * @return */ @Override public R checkObjs(CheckObjParams params) { if (Objects.isNull(params.getIsptCode())) { throw new CoolException("质检单不能为空"); } if (Objects.isNull(params.getMatnrCode())) { throw new CoolException("物料编码不能为空!"); } QlyInspect inspect = qlyInspectMapper.selectOne(new LambdaQueryWrapper().eq(QlyInspect::getCode, params.getIsptCode())); if (Objects.isNull(inspect)) { throw new CoolException("质检单据不存在!!"); } QlyIsptItem isptItem = qlyIsptItemService.getOne(new LambdaQueryWrapper() .eq(QlyIsptItem::getMatnrCode, params.getMatnrCode()) .eq(QlyIsptItem::getIspectId, inspect.getId())); if (Objects.isNull(isptItem)) { throw new CoolException("质检单明细不存在!!"); } CheckObjDto objDto = new CheckObjDto(); objDto.setIsptCode(inspect.getCode()) .setAsnCode(inspect.getAsnCode()) .setId(isptItem.getId()) .setMatnrCode(isptItem.getMatnrCode()) .setMaktx(isptItem.getMaktx()) .setDisQty(isptItem.getDisQty()) .setDlyQty(isptItem.getDlyQty()) .setRcptQty(isptItem.getRcptQty()) .setIsptResult(isptItem.getIsptResult()) .setSplrBatch(isptItem.getSplrBatch()) .setSplrName(isptItem.getSplrName()) .setPicPath(isptItem.getPicPath()) .setMemo(isptItem.getMemo()) .setSafeQty(isptItem.getSafeQty()); return R.ok(objDto); } /** * 快速质检 * @param params * @return */ @Override public R checkUpdate(QlyIsptItem params) { if (Objects.isNull(params.getId())) { throw new CoolException("参数不能为空!!"); } IsptItemsParams itemsParams = new IsptItemsParams(); List items = new ArrayList<>(); items.add(params); itemsParams.setIsptItem(items).setType("0"); if (qlyIsptItemService.batchUpdate(itemsParams)) { return R.ok(); } else { return R.error("保存失败!!"); } } /** * @author Ryan * @description 人工上架 * @param * @return * @time 2025/4/2 16:33 */ @Override public R operateToStock(OpStockParams params) { if (org.apache.commons.lang3.StringUtils.isBlank(params.getBarcode())) { throw new CoolException("拖盘码不能为空!!"); } if (StringUtils.isBlank(params.getAsnCode())) { throw new CoolException("单据不能为空!!"); } if (StringUtils.isBlank(params.getMatnrCode())) { throw new CoolException("物料编码不能为空!!"); } AsnOrder asnOrders = asnOrderMapper.getOne(new LambdaQueryWrapper().eq(AsnOrder::getCode, params.getAsnCode())); if (Objects.isNull(asnOrders)) { throw new CoolException("单据不存在!!"); } List locs = locService.list(new LambdaQueryWrapper().eq(Loc::getBarcode, params.getBarcode())); if (!locs.isEmpty()) { throw new CoolException("拖盘已使用"); } List waitPakins = waitPakinService.list(new LambdaQueryWrapper().eq(WaitPakin::getBarcode, params.getBarcode())); if (!waitPakins.isEmpty()) { throw new CoolException("拖盘已使用!!"); } List orderItems = asnOrderItemMapper.selectList(new LambdaQueryWrapper() .eq(AsnOrderItem::getAsnId, asnOrders.getId()) .eq(AsnOrderItem::getMatnrCode, params.getMatnrCode())); if (orderItems.isEmpty()) { throw new CoolException("单据明细不存在!!"); } List stocks = new ArrayList<>(); orderItems.forEach(item -> { item.setBarcode(params.getBarcode()); stocks.add(item); }); return R.ok(stocks); } /** * 获取ReceiptDetlsDtos */ private R getAsnOrderItem(List items) { List detlsDtos = new ArrayList<>(); items.forEach(asnOrderItem -> { ReceiptDetlsDto detlsDto = new ReceiptDetlsDto(); detlsDto.setAsnCode(asnOrderItem.getAsnCode()) .setMaktx(asnOrderItem.getMaktx()) .setBarcode(asnOrderItem.getTrackCode()) .setQty(asnOrderItem.getQty()) .setPoCode(asnOrderItem.getPoCode()) .setAnfme(asnOrderItem.getAnfme()) .setPurQty(asnOrderItem.getPurQty()) .setSplrBatch(asnOrderItem.getSplrBatch()); Matnr matnr = matnrMapper.selectById(asnOrderItem.getMatnrId()); if (Objects.isNull(matnr)) { throw new CoolException("数据错误:当前物料不存在!!"); } //SET 物料最大存放数量 detlsDto.setMaxQty(matnr.getMaxQty()) .setMatnrId(matnr.getId()) .setStockUnit(matnr.getStockUnit()); QlyInspect inspect = qlyInspectMapper.selectOne(new LambdaQueryWrapper() .eq(QlyInspect::getAsnId, asnOrderItem.getAsnId())); if (!Objects.isNull(inspect)) { //set 质检结果 detlsDto.setInspect(inspect.getStatus$()); } //获取当前库存信息 StockItem stockItem = stockItemMapper.selectOne(new LambdaQueryWrapper() .eq(StockItem::getAsnItemId, asnOrderItem.getId()) .eq(StockItem::getMatnrId, asnOrderItem.getMatnrId())); //SET 当前库存数量 if (Objects.isNull(stockItem)) { detlsDto.setStockQty(0.0); } else { detlsDto.setStockQty(stockItem.getQty() + stockItem.getWorkQty()); } if (!Objects.isNull(asnOrderItem.getPoDetlId())) { //获取采购单明细信息 PurchaseItem purchaseItem = purchaseItemMapper.selectOne(new LambdaQueryWrapper().eq(PurchaseItem::getId, asnOrderItem.getPoDetlId())); if (Objects.isNull(purchaseItem)) { //SET 平台行号 detlsDto.setPlatformId(purchaseItem.getPlatItemId()); } } detlsDtos.add(detlsDto); }); return R.ok(detlsDtos); } }