diff --git a/youchain-common/src/main/java/com/youchain/exception/OperBadRequestException.java b/youchain-common/src/main/java/com/youchain/exception/OperBadRequestException.java new file mode 100644 index 0000000..6a3ac6c --- /dev/null +++ b/youchain-common/src/main/java/com/youchain/exception/OperBadRequestException.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019-2020 Zheng Jie + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.youchain.exception; + +import lombok.Getter; +import org.springframework.http.HttpStatus; + +import static org.springframework.http.HttpStatus.BAD_REQUEST; + +/** + * @author Liu Xue + * @date 2018-11-23 + * 统一异常处理 + */ +@Getter +public class OperBadRequestException extends RuntimeException{ + + private Integer status = BAD_REQUEST.value(); + + public OperBadRequestException(String msg){ + super(msg); + } + + public OperBadRequestException(HttpStatus status, String msg){ + super(msg); + this.status = status.value(); + } +} diff --git a/youchain-logging/src/main/java/com/youchain/aspect/DefaultOperDataUtil.java b/youchain-logging/src/main/java/com/youchain/aspect/DefaultOperDataUtil.java new file mode 100644 index 0000000..0f88935 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/aspect/DefaultOperDataUtil.java @@ -0,0 +1,71 @@ +package com.youchain.aspect; + +import java.util.HashMap; +import java.util.Map; + +/** + * 默认数据工具类 + */ +public class DefaultOperDataUtil { + + // 私有静态Map,用于存储默认数据 + private static final Map DEFAULT_DATA_MAP = new HashMap<>(); + + // 静态初始化块,在类加载时初始化默认数据 + static { + initDefaultData(); + } + + /** + * 初始化默认数据 + */ + private static void initDefaultData() { + // 添加默认数据 + DEFAULT_DATA_MAP.put("com.youchain.businessdata.rest.XppRecordController.putawayXppApp", "现品票上架"); + DEFAULT_DATA_MAP.put("com.youchain.businessdata.rest.XppRecordController.zzjlPickApp", "制造叫料拣货"); + // 可以继续添加更多默认数据 + // DEFAULT_DATA_MAP.put("key2", "value2"); + // DEFAULT_DATA_MAP.put("key3", "value3"); + } + + /** + * 根据key获取对应的value + * @param key 要查找的键 + * @return 对应的值,如果key不存在则返回null + */ + public static String getValue(String key) { + return DEFAULT_DATA_MAP.get(key); + } + + /** + * 根据key获取对应的value,如果不存在则返回默认值 + * @param key 要查找的键 + * @param defaultValue 默认值 + * @return 对应的值,如果key不存在则返回默认值 + */ + public static String getValueOrDefault(String key, String defaultValue) { + return DEFAULT_DATA_MAP.getOrDefault(key, defaultValue); + } + + /** + * 检查是否包含指定的key + * @param key 要检查的键 + * @return 如果包含则返回true,否则返回false + */ + public static boolean containsKey(String key) { + return DEFAULT_DATA_MAP.containsKey(key); + } + + /** + * 获取所有默认数据的副本(防止外部修改内部数据) + * @return 默认数据的副本 + */ + public static Map getAllData() { + return new HashMap<>(DEFAULT_DATA_MAP); + } + + // 私有构造方法,防止实例化 + private DefaultOperDataUtil() { + throw new UnsupportedOperationException("工具类不能实例化"); + } +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/aspect/LogAspect.java b/youchain-logging/src/main/java/com/youchain/aspect/LogAspect.java index dd8db45..b786ad1 100644 --- a/youchain-logging/src/main/java/com/youchain/aspect/LogAspect.java +++ b/youchain-logging/src/main/java/com/youchain/aspect/LogAspect.java @@ -15,8 +15,10 @@ */ package com.youchain.aspect; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONUtil; +import com.youchain.domain.OperLog; +import com.youchain.repository.OperLogRepository; +import com.youchain.service.OperLogService; import com.youchain.utils.RequestHolder; import com.youchain.utils.SecurityUtils; import com.youchain.utils.StringUtils; @@ -27,11 +29,11 @@ import com.youchain.service.LogService; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; -import org.springframework.security.web.context.HttpRequestResponseHolder; import org.springframework.stereotype.Component; import javax.servlet.http.HttpServletRequest; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; +import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author Liu Xue @@ -43,11 +45,13 @@ import java.util.Arrays; public class LogAspect { private final LogService logService; + private final OperLogService operLogService; ThreadLocal currentTime = new ThreadLocal<>(); - public LogAspect(LogService logService) { + public LogAspect(LogService logService, OperLogService operLogService) { this.logService = logService; + this.operLogService = operLogService; } /** @@ -80,7 +84,6 @@ public class LogAspect { } logService.save(url,result_data,getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request),joinPoint, log_data); - return result; } @@ -156,9 +159,10 @@ public class LogAspect { String errDetail=ThrowableUtil.getStackTrace(e)+""; log.error("拦截到异常消息", errDetail); Log log_data = new Log("ERROR",System.currentTimeMillis() - currentTime.get()); + OperLog oper_log_data = new OperLog("ERROR",System.currentTimeMillis() - currentTime.get()); currentTime.remove(); - log_data.setExceptionDetail(errDetail); + HttpServletRequest request = RequestHolder.getHttpServletRequest(); String url=handlerUrl(request); @@ -166,7 +170,18 @@ public class LogAspect { if(parm!=null&&parm.length()>0){ url=url+"?"+parm; } + log_data.setExceptionDetail(errDetail); + logService.save(url,"",getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, log_data); + String operErrDetail=""; + Pattern pattern = Pattern.compile("com\\.youchain\\.exception\\.OperBadRequestException: .*"); + Matcher matcher = pattern.matcher(errDetail); + if (matcher.find()) { + operErrDetail = matcher.group(0); // com.youchain.exception.BadRequestException: 拆分数量不能大于原数量 + oper_log_data.setExceptionDetail(operErrDetail.substring(operErrDetail.indexOf(":")+1)); + operLogService.save(url,"",getUsername(), StringUtils.getBrowser(request), StringUtils.getIp(request), (ProceedingJoinPoint)joinPoint, oper_log_data); + + } } public String getUsername() { diff --git a/youchain-logging/src/main/java/com/youchain/domain/OperLog.java b/youchain-logging/src/main/java/com/youchain/domain/OperLog.java new file mode 100644 index 0000000..0fb8487 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/domain/OperLog.java @@ -0,0 +1,117 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.domain; + +import lombok.Data; +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiModelProperty; +import cn.hutool.core.bean.copier.CopyOptions; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import javax.persistence.*; +import javax.validation.constraints.*; +import java.sql.Timestamp; +import java.io.Serializable; + +/** +* @website https://eladmin.vip +* @description / +* @author houjianlan +* @date 2025-12-23 +**/ +@Entity +@Getter +@Setter +@Table(name = "sys_oper_log") +@NoArgsConstructor +public class OperLog implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "`id`") + @ApiModelProperty(value = "ID") + private Long id; + + @Column(name = "`description`") + @ApiModelProperty(value = "描述") + private String description; + + @Column(name = "`log_type`") + @ApiModelProperty(value = "类型") + private String logType; + + @Column(name = "`params`") + @ApiModelProperty(value = "参数") + private String params; + + @Column(name = "`return_data`") + @ApiModelProperty(value = "返回") + private String returnData; + + @Column(name = "`request_ip`") + @ApiModelProperty(value = "requestIp") + private String requestIp; + + @Column(name = "`time`") + @ApiModelProperty(value = "耗时") + private Long time; + + @Column(name = "`username`") + @ApiModelProperty(value = "操作人") + private String username; + + @Column(name = "`address`") + @ApiModelProperty(value = "address") + private String address; + + @Column(name = "`module`") + @ApiModelProperty(value = "模块名") + private String module; + + @Column(name = "`method`") + @ApiModelProperty(value = "方法名") + private String method; + + @Column(name = "`content`") + @ApiModelProperty(value = "操作内容") + private String content; + + @Column(name = "`source_id`") + @ApiModelProperty(value = "来源序号") + private Long sourceId; + + @Column(name = "`browser`") + @ApiModelProperty(value = "browser") + private String browser; + + @Column(name = "`exception_detail`") + @ApiModelProperty(value = "exceptionDetail") + private String exceptionDetail; + + @Column(name = "`create_time`") + @ApiModelProperty(value = "创建时间") + private Timestamp createTime; + + public void copy(OperLog source){ + BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); + } + public OperLog(String logType, Long time) { + this.logType = logType; + this.time = time; + } +} diff --git a/youchain-logging/src/main/java/com/youchain/repository/OperLogRepository.java b/youchain-logging/src/main/java/com/youchain/repository/OperLogRepository.java new file mode 100644 index 0000000..a17f70f --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/repository/OperLogRepository.java @@ -0,0 +1,28 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.repository; + +import com.youchain.domain.OperLog; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2025-12-23 +**/ +public interface OperLogRepository extends JpaRepository, JpaSpecificationExecutor { +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/rest/OperLogController.java b/youchain-logging/src/main/java/com/youchain/rest/OperLogController.java new file mode 100644 index 0000000..47ad6c5 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/rest/OperLogController.java @@ -0,0 +1,79 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.rest; + +import com.youchain.annotation.Log; +import com.youchain.domain.OperLog; +import com.youchain.service.OperLogService; +import com.youchain.service.dto.OperLogQueryCriteria; +import org.springframework.data.domain.Pageable; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import io.swagger.annotations.*; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2025-12-23 +**/ +@RestController +@RequiredArgsConstructor +@Api(tags = "operLog管理") +@RequestMapping("/api/operLog") +public class OperLogController { + + private final OperLogService operLogService; + + @Log("导出数据") + @ApiOperation("导出数据") + @GetMapping(value = "/download") + @PreAuthorize("@el.check('operLog:list')") + public void exportOperLog(HttpServletResponse response, OperLogQueryCriteria criteria) throws Exception { + operLogService.download(operLogService.queryAll(criteria), response); + } + + @GetMapping + @Log("查询operLog") + @ApiOperation("查询operLog") + @PreAuthorize("@el.check('operLog:list')") + public ResponseEntity queryOperLog(OperLogQueryCriteria criteria, Pageable pageable){ + return new ResponseEntity<>(operLogService.queryAll(criteria,pageable),HttpStatus.OK); + } + + @PostMapping + @Log("新增operLog") + @ApiOperation("新增operLog") + @PreAuthorize("@el.check('operLog:add')") + public ResponseEntity createOperLog(@Validated @RequestBody OperLog resources){ + return new ResponseEntity<>(operLogService.create(resources),HttpStatus.CREATED); + } + + + @DeleteMapping + @Log("删除operLog") + @ApiOperation("删除operLog") + @PreAuthorize("@el.check('operLog:del')") + public ResponseEntity deleteOperLog(@RequestBody Long[] ids) { + operLogService.deleteAll(ids); + return new ResponseEntity<>(HttpStatus.OK); + } +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/service/LogService.java b/youchain-logging/src/main/java/com/youchain/service/LogService.java index 461ed0b..ce69ac3 100644 --- a/youchain-logging/src/main/java/com/youchain/service/LogService.java +++ b/youchain-logging/src/main/java/com/youchain/service/LogService.java @@ -18,12 +18,9 @@ package com.youchain.service; import com.youchain.service.dto.LogQueryCriteria; import com.youchain.domain.Log; import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.data.domain.Pageable; -import org.springframework.scheduling.annotation.Async; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; import java.util.List; /** @@ -66,7 +63,6 @@ public interface LogService { void save(String url,String returnValue,String username, String browser, String ip, JoinPoint joinPoint, Log log); - void saveLog(Log log); /** * 查询异常详情 diff --git a/youchain-logging/src/main/java/com/youchain/service/OperLogService.java b/youchain-logging/src/main/java/com/youchain/service/OperLogService.java new file mode 100644 index 0000000..e266e5b --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/service/OperLogService.java @@ -0,0 +1,74 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.service; + +import com.youchain.domain.Log; +import com.youchain.domain.OperLog; +import com.youchain.service.dto.OperLogDto; +import com.youchain.service.dto.OperLogQueryCriteria; +import org.aspectj.lang.JoinPoint; +import org.springframework.data.domain.Pageable; +import java.util.Map; +import java.util.List; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://eladmin.vip +* @description 服务接口 +* @author houjianlan +* @date 2025-12-23 +**/ +public interface OperLogService { + + /** + * 查询数据分页 + * @param criteria 条件 + * @param pageable 分页参数 + * @return Map + */ + Map queryAll(OperLogQueryCriteria criteria, Pageable pageable); + + /** + * 查询所有数据不分页 + * @param criteria 条件参数 + * @return List + */ + List queryAll(OperLogQueryCriteria criteria); + + /** + * 创建 + * @param resources / + * @return OperLogDto + */ + OperLogDto create(OperLog resources); + void save(String url, String returnValue, String username, String browser, String ip, JoinPoint joinPoint, OperLog log); + + + /** + * 多选删除 + * @param ids / + */ + void deleteAll(Long[] ids); + + /** + * 导出数据 + * @param all 待导出的数据 + * @param response / + * @throws Exception / + */ + void download(List all, HttpServletResponse response) throws Exception; +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/service/dto/OperLogDto.java b/youchain-logging/src/main/java/com/youchain/service/dto/OperLogDto.java new file mode 100644 index 0000000..0afa884 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/service/dto/OperLogDto.java @@ -0,0 +1,74 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.service.dto; + +import lombok.Data; +import java.sql.Timestamp; +import java.io.Serializable; + +/** +* @website https://eladmin.vip +* @description / +* @author houjianlan +* @date 2025-12-23 +**/ +@Data +public class OperLogDto implements Serializable { + + /** ID */ + private Long id; + + /** 描述 */ + private String description; + + /** 类型 */ + private String logType; + + /** 参数 */ + private String params; + + /** 返回 */ + private String returnData; + + private String requestIp; + + /** 耗时 */ + private Long time; + + /** 操作人 */ + private String username; + + private String address; + + /** 模块名 */ + private String module; + + /** 方法名 */ + private String method; + + /** 操作内容 */ + private String content; + + /** 来源序号 */ + private Long sourceId; + + private String browser; + + private String exceptionDetail; + + /** 创建时间 */ + private Timestamp createTime; +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/service/dto/OperLogQueryCriteria.java b/youchain-logging/src/main/java/com/youchain/service/dto/OperLogQueryCriteria.java new file mode 100644 index 0000000..39384c1 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/service/dto/OperLogQueryCriteria.java @@ -0,0 +1,41 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.service.dto; + +import lombok.Data; +import java.sql.Timestamp; +import java.util.List; +import com.youchain.annotation.Query; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2025-12-23 +**/ +@Data +public class OperLogQueryCriteria{ + + /** 模糊 */ + @Query(type = Query.Type.INNER_LIKE) + private String logType; + + /** 模糊 */ + @Query(type = Query.Type.INNER_LIKE) + private String username; + /** BETWEEN */ + @Query(type = Query.Type.BETWEEN) + private List createTime; +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/service/impl/LogServiceImpl.java b/youchain-logging/src/main/java/com/youchain/service/impl/LogServiceImpl.java index 8b98d13..743f819 100644 --- a/youchain-logging/src/main/java/com/youchain/service/impl/LogServiceImpl.java +++ b/youchain-logging/src/main/java/com/youchain/service/impl/LogServiceImpl.java @@ -16,7 +16,6 @@ package com.youchain.service.impl; import cn.hutool.core.lang.Dict; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.youchain.domain.Log; @@ -27,10 +26,8 @@ import com.youchain.service.mapstruct.LogSmallMapper; import com.youchain.utils.*; import lombok.RequiredArgsConstructor; import com.youchain.service.mapstruct.LogErrorMapper; -import com.youchain.utils.*; import lombok.extern.slf4j.Slf4j; import org.aspectj.lang.JoinPoint; -import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -41,7 +38,6 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import javax.servlet.http.HttpServletResponse; -import java.io.IOException; import java.lang.reflect.Method; import java.lang.reflect.Parameter; import java.util.*; diff --git a/youchain-logging/src/main/java/com/youchain/service/impl/OperLogServiceImpl.java b/youchain-logging/src/main/java/com/youchain/service/impl/OperLogServiceImpl.java new file mode 100644 index 0000000..8091b06 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/service/impl/OperLogServiceImpl.java @@ -0,0 +1,180 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.service.impl; + +import cn.hutool.core.lang.Dict; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.youchain.aspect.DefaultOperDataUtil; +import com.youchain.domain.Log; +import com.youchain.domain.OperLog; +import com.youchain.utils.*; +import lombok.RequiredArgsConstructor; +import com.youchain.repository.OperLogRepository; +import com.youchain.service.OperLogService; +import com.youchain.service.dto.OperLogDto; +import com.youchain.service.dto.OperLogQueryCriteria; +import com.youchain.service.mapstruct.OperLogMapper; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestParam; + +import java.lang.reflect.Method; +import java.lang.reflect.Parameter; +import java.sql.Timestamp; +import java.util.*; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://eladmin.vip +* @description 服务实现 +* @author houjianlan +* @date 2025-12-23 +**/ +@Service +@RequiredArgsConstructor +@Slf4j +public class OperLogServiceImpl implements OperLogService { + + private final OperLogRepository operLogRepository; + private final OperLogMapper operLogMapper; + + @Override + public Map queryAll(OperLogQueryCriteria criteria, Pageable pageable){ + Page page = operLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); + return PageUtil.toPage(page.map(operLogMapper::toDto)); + } + + @Override + public List queryAll(OperLogQueryCriteria criteria){ + return operLogMapper.toDto(operLogRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); + } + + + @Override + @Transactional(rollbackFor = Exception.class) + public OperLogDto create(OperLog resources) { + return operLogMapper.toDto(operLogRepository.save(resources)); + } + + + + @Override + public void deleteAll(Long[] ids) { + for (Long id : ids) { + operLogRepository.deleteById(id); + } + } + + @Override + public void download(List all, HttpServletResponse response) throws Exception { + List> list = new ArrayList<>(); + for (OperLogDto operLog : all) { + Map map = new LinkedHashMap<>(); + map.put("描述", operLog.getDescription()); + map.put("类型", operLog.getLogType()); + map.put("参数", operLog.getParams()); + map.put("返回", operLog.getReturnData()); + map.put(" requestIp", operLog.getRequestIp()); + map.put("耗时", operLog.getTime()); + map.put("操作人", operLog.getUsername()); + map.put(" address", operLog.getAddress()); + map.put("模块名", operLog.getModule()); + map.put("方法名", operLog.getMethod()); + map.put("操作内容", operLog.getContent()); + map.put("来源序号", operLog.getSourceId()); + map.put(" browser", operLog.getBrowser()); + map.put(" exceptionDetail", operLog.getExceptionDetail()); + map.put("创建时间", operLog.getCreateTime()); + list.add(map); + } + FileUtil.downloadExcel(list, response); + } + + @Async + @Override + @Transactional(rollbackFor = Exception.class) + public void save(String url, String returnValue, String username, String browser, String ip, JoinPoint joinPoint, OperLog log_data) { + if (log_data == null) { + throw new IllegalArgumentException("Log 不能为 null!"); + } + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + Method method = signature.getMethod(); + com.youchain.annotation.Log aopLog = method.getAnnotation(com.youchain.annotation.Log.class); + + // 方法路径 + String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()"; + + // 描述 + log_data.setDescription(aopLog.value()); + + log_data.setRequestIp(ip); + log_data.setAddress(StringUtils.getCityInfo(log_data.getRequestIp())); + log_data.setMethod(url+"---"+methodName); + log_data.setUsername(username); + log_data.setParams(getParameter(method, joinPoint.getArgs())); + log_data.setCreateTime(new Timestamp(new Date().getTime())); + // 记录登录用户,隐藏密码信息 + if(signature.getName().equals("login") && StringUtils.isNotEmpty(log_data.getParams())){ + JSONObject obj = JSONUtil.parseObj(log_data.getParams()); + log_data.setUsername(obj.getStr("username", "")); + log_data.setParams(JSONUtil.toJsonStr(Dict.create().set("username", log_data.getUsername()))); + } + log_data.setBrowser(browser); + log_data.setReturnData(returnValue); + String module= DefaultOperDataUtil.getValue(methodName); + log_data.setModule(module); + operLogRepository.save(log_data); + } + /** + * 根据方法和传入的参数获取请求参数 + */ + private String getParameter(Method method, Object[] args) { + List argList = new ArrayList<>(); + Parameter[] parameters = method.getParameters(); + for (int i = 0; i < parameters.length; i++) { + //将RequestBody注解修饰的参数作为请求参数 + RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class); + if (requestBody != null) { + argList.add(args[i]); + } + //将RequestParam注解修饰的参数作为请求参数 + RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class); + if (requestParam != null) { + Map map = new HashMap<>(2); + String key = parameters[i].getName(); + if (!StringUtils.isEmpty(requestParam.value())) { + key = requestParam.value(); + } + map.put(key, args[i]); + argList.add(map); + } + } + if (argList.isEmpty()) { + return ""; + } + return argList.size() == 1 ? JSONUtil.toJsonStr(argList.get(0)) : JSONUtil.toJsonStr(argList); + } + +} \ No newline at end of file diff --git a/youchain-logging/src/main/java/com/youchain/service/mapstruct/OperLogMapper.java b/youchain-logging/src/main/java/com/youchain/service/mapstruct/OperLogMapper.java new file mode 100644 index 0000000..9928230 --- /dev/null +++ b/youchain-logging/src/main/java/com/youchain/service/mapstruct/OperLogMapper.java @@ -0,0 +1,32 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.service.mapstruct; + +import com.youchain.base.BaseMapper; +import com.youchain.domain.OperLog; +import com.youchain.service.dto.OperLogDto; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2025-12-23 +**/ +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface OperLogMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/domain/Area.java b/youchain-system/src/main/java/com/youchain/basicdata/domain/Area.java index 07ac867..35f82f3 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/domain/Area.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/domain/Area.java @@ -125,7 +125,7 @@ public class Area extends BaseEntity implements Serializable { @Column(name = "`betc`") @ApiModelProperty(value = "台车库区") - private Boolean betc; + private Boolean betc=false; @Column(name = "`shdd`") @ApiModelProperty(value = "收货担当") diff --git a/youchain-system/src/main/java/com/youchain/basicdata/domain/ProductionPlan.java b/youchain-system/src/main/java/com/youchain/basicdata/domain/ProductionPlan.java index a8fa56b..fff6bab 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/domain/ProductionPlan.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/domain/ProductionPlan.java @@ -53,16 +53,16 @@ public class ProductionPlan extends BaseEntity implements Serializable { private Boolean enabled; @OneToOne - @JoinColumn(name = "`big_item_id`",nullable = false) + @JoinColumn(name = "`big_item_id`") @ApiModelProperty(value = "完成品番") private BigItem bigItem; - @Column(name = "`working_station`",nullable = false) + @Column(name = "`working_station`") @NotBlank @ApiModelProperty(value = "工位") private String workingStation; - @Column(name = "`No`",nullable = false) + @Column(name = "`No`") @NotNull @ApiModelProperty(value = "No") private Integer no; @@ -75,7 +75,7 @@ public class ProductionPlan extends BaseEntity implements Serializable { @ApiModelProperty(value = "计划日期") private Timestamp plannedDate; - @Column(name = "`downline_date`",nullable = false) + @Column(name = "`downline_date`") @NotNull @ApiModelProperty(value = "下线日期") private Timestamp downlineDate; @@ -145,7 +145,7 @@ public class ProductionPlan extends BaseEntity implements Serializable { @ApiModelProperty(value = "下线零件ID") private Long offLinePart; - @Column(name = "`machine_no`",nullable = false) + @Column(name = "`machine_no`") @NotNull @ApiModelProperty(value = "机号") private String machineNo; diff --git a/youchain-system/src/main/java/com/youchain/basicdata/repository/BomAccountRepository.java b/youchain-system/src/main/java/com/youchain/basicdata/repository/BomAccountRepository.java index eef1e81..d5f35f9 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/repository/BomAccountRepository.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/repository/BomAccountRepository.java @@ -59,7 +59,7 @@ public interface BomAccountRepository extends JpaRepository, J Double getPcQty(Long area_id, Long item_id, Long point_id); /**台车库位对应的bom*/ @Query(value = "SELECT * FROM `base_bom_account` b where b.station_type=:station_type", nativeQuery = true) - List queryTchws(String station_type); + List queryTchws(String station_type ); /**固定库位二维码解析*/ @Query(value = "SELECT * FROM `base_bom_account` b where b.item_id=:item_id and b.z_point_id=:z_point_id and b.bonded=:bonded", nativeQuery = true) List queryEwmJx(Long item_id, Long z_point_id,String bonded); @@ -139,5 +139,26 @@ public interface BomAccountRepository extends JpaRepository, J @Query(value = "select v.tckw hw,v.jxs from bom_tckw_print_view v " + "where (v.tckw=:tckw or :tckw is null) " + " and (v.jxs LIKE CONCAT('%',:jx,'%') or :jx is null) ", nativeQuery = true) + List queryTckwPrintAll_old(String tckw,String jx); + + @Query(value = "SELECT `ba`.`tckw` AS `hw`,bi.code ,MAX(bi.name) pm\n" + + "FROM `base_bom_account` `ba`\n" + + "LEFT JOIN `base_big_item` `bi` ON `bi`.`id` = `ba`.`big_item_id` \n" + + "where ba.tckw is not null and ba.tckw!='' and (ba.tckw LIKE CONCAT('%',:tckw,'%') or :tckw is null) and (bi.code=:jx or :jx is null)" + + "GROUP BY `ba`.`tckw`,bi.code " + + "order by ba.tckw,bi.code ", nativeQuery = true) List queryTckwPrintAll(String tckw,String jx); + + /**查找台车库位*/ + @Query(value = "SELECT `ba`.* FROM `base_bom_account` `ba` " + + "LEFT JOIN `base_big_item` `bi` ON `bi`.`id` = `ba`.`big_item_id` " + + "where (ba.tckw=:tckw or :tckw is null) and (bi.code=:bigItemCode or :bigItemCode is null) " , nativeQuery = true) + List queryTckwBom(String tckw,String bigItemCode); + + @Query(value = "select ba.tckw,bi.code,ba.item_id,ba.ky_qz,CAST(sum(ba.singles) as SIGNED) singles from base_bom_account ba\n" + + "\tLEFT JOIN base_big_item bi on bi.id=ba.big_item_id\n" + + "\twhere ba.tckw is not null and ba.tckw!='' and ba.ky_qz is not null and ba.singles>0 \n" + + "\tGROUP BY ba.tckw,bi.code,ba.item_id,ba.ky_qz \n" + + "\tORDER BY ba.tckw,bi.code;" , nativeQuery = true) + List queryTckwBom(); } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/rest/BomAccountController.java b/youchain-system/src/main/java/com/youchain/basicdata/rest/BomAccountController.java index a5a3baa..f59a37e 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/rest/BomAccountController.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/rest/BomAccountController.java @@ -32,6 +32,7 @@ import com.youchain.basicdata.service.dto.*; import com.youchain.basicdata.service.impl.TableConfigServiceImpl; import com.youchain.basicdata.service.mapstruct.BomAccountMapper; import com.youchain.businessdata.returnJson.*; +import com.youchain.exception.BadRequestException; import com.youchain.utils.*; import lombok.extern.slf4j.Slf4j; import net.dreamlu.mica.core.utils.JsonUtil; @@ -119,6 +120,18 @@ public class BomAccountController { return new ResponseEntity<>(list,HttpStatus.OK); } + @GetMapping("/queryBomPrintListTC_old") + @Log("查询台车标签") + @ApiOperation("查询台车标签") + @AnonymousAccess + public ResponseEntity queryBomPrintListTC_old(BomAccountQueryCriteria criteria){ + RedisUtils redisUtils = SpringContextHolder.getBean(RedisUtils.class); + redisUtils.del(SecurityUtils.getCurrentUsername()+"_BiaoQian_TC"); + List list=bomAccountService.queryTckwPrintAll(criteria); + redisUtils.set(SecurityUtils.getCurrentUsername()+"_BiaoQian_TC",JsonUtil.toJson(list)); + return new ResponseEntity<>(list,HttpStatus.OK); + } + @GetMapping("/queryBomPrintListTC") @Log("查询台车标签") @ApiOperation("查询台车标签") @@ -223,14 +236,19 @@ public class BomAccountController { List list=bomAccountService.queryTckwPrintAll(criteria); List list_bq=new ArrayList<>(); for(BomPrint p:list){ - String key=p.getHw(); - String jx=p.getJxs(); - String[] jxs=jx.split(","); BomPrint_BiaoQian bq=new BomPrint_BiaoQian(); - bq.setCode(key); - bq.setHw(key); - bq.setJxs(jxs); - bq.setJx(jx); +// String key=p.getHw(); +// String jx=p.getJxs(); +// String[] jxs=jx.split(","); +// bq.setCode(key); +// bq.setHw(key); +// bq.setJxs(jxs); +// bq.setJx(jx); + bq.setCode(p.getCode()); + bq.setHw(p.getHw()); + bq.setPm(p.getPm()); + bq.setJx(p.getCode()); + bq.setEwm(p.getHw()+"]"+p.getCode()); list_bq.add(bq); } redisUtils.set(SecurityUtils.getCurrentUsername()+BaseStatus.TCBQ,JsonUtil.toJson(list_bq)); @@ -339,7 +357,7 @@ public class BomAccountController { @DuplicateSubmission(10) public ResponseEntity tcOut(@Validated @RequestBody String[] tckws){ for (String tckw : tckws) { - bomAccountService.tcCount(tckw); + bomAccountService.tcCount(tckw,null); } return new ResponseEntity<>(HttpStatus.OK); } @@ -351,8 +369,20 @@ public class BomAccountController { @Transactional @DuplicateSubmission(10) public ResponseEntity tcOutApp( @RequestBody HashMap map){ - String tckw=map.get("tckw")==null?null:map.get("tckw").toString(); - bomAccountService.tcCount(tckw); + String ewm=map.get("tckw")==null?null:map.get("tckw").toString(); + String tckw=null; + String bigItemCode=null; + if(ewm.length()>=82) { + tckw=ewm.substring(3,13); + }else{ + String[] tckws = ewm.split("]"); + if (tckws.length < 2) { + throw new BadRequestException("扫描内容有误"); + } + tckw=tckws[0]; + bigItemCode=tckws[1]; + } + bomAccountService.tcCount(tckw,bigItemCode); return new ResponseEntity<>("配料成功", HttpStatus.OK); } @@ -361,9 +391,21 @@ public class BomAccountController { @ApiOperation("制造叫料拣货列表") @AnonymousAccess public ResponseEntity tcOutList(@RequestBody HashMap map) throws Exception { - String tckw=map.get("tckw")==null?null:map.get("tckw").toString(); + String ewm=map.get("tckw")==null?null:map.get("tckw").toString(); + String tckw=null; + String bigItemCode=null; + if(ewm.length()>=82) { + tckw=ewm.substring(3,13); + }else{ + String[] tckws = ewm.split("]"); + if (tckws.length < 2) { + throw new BadRequestException("扫描内容有误"); + } + tckw=tckws[0]; + bigItemCode=tckws[1]; + } //查询叫料返回数据 - List list=bomAccountService.queryTckwList(tckw); + List list=bomAccountService.queryTckwList(tckw,bigItemCode); return new ResponseEntity<>(list,HttpStatus.OK); } } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/rest/ImportDataController.java b/youchain-system/src/main/java/com/youchain/basicdata/rest/ImportDataController.java index e80b72c..9869e0a 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/rest/ImportDataController.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/rest/ImportDataController.java @@ -76,6 +76,7 @@ public class ImportDataController { private final ImportAsnDetailService importAsnDetailService; private final ImportPickDetailService importPickDetailService; private final ImportCountDetailService importCountDetailService; + private final ImportXppPlanService importXppPlanService; @Log("导入完成品品番") @ApiOperation("导入完成品品番") @@ -282,4 +283,17 @@ public class ImportDataController { return new ResponseEntity("导入成功", OK); } + @Log("导入现品票计划") + @ApiOperation("导入现品票计划") + @PostMapping(value = "/importXppPlan") + @Transactional + @AnonymousAccess + public ResponseEntity importXppPlan(@RequestParam("file") MultipartFile multipartFile) { + log.info("开始导入"); + long start = System.currentTimeMillis(); + importXppPlanService.importData(multipartFile); + log.info("导入结束,耗时:{}ms", (System.currentTimeMillis() - start)); + return new ResponseEntity("导入成功", OK); + } + } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/rest/ProductionPlanController.java b/youchain-system/src/main/java/com/youchain/basicdata/rest/ProductionPlanController.java index bf516b7..23e5609 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/rest/ProductionPlanController.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/rest/ProductionPlanController.java @@ -38,6 +38,7 @@ import com.youchain.exception.handler.ApiError; import com.youchain.exception.handler.ApiResult; import com.youchain.modules.system.domain.Dept; import com.youchain.utils.*; +import com.youchain.utils.readFilebak.ReadUbuntuFiles; import lombok.extern.slf4j.Slf4j; import org.springframework.data.domain.Pageable; import lombok.RequiredArgsConstructor; @@ -81,6 +82,7 @@ public class ProductionPlanController { private final ItemLisRepository itemLisRepository; private final FileProperties properties; private final SparepartsService sparepartsService; + private final ReadUbuntuFiles readUbuntuFiles; @PostMapping(value = "/import_data") @ApiOperation("导入生产顺序计划") @@ -205,6 +207,16 @@ public class ProductionPlanController { return new ResponseEntity<>("耗用成功!",HttpStatus.OK); } + @PutMapping(value = "/readHaoYongData") + @ApiOperation("下线数据读取") + @Log("下线数据读取") + @Transactional + @PreAuthorize("@el.check('super:man')") + @DuplicateSubmission(5) + public ResponseEntity readHaoYongData(){ + readUbuntuFiles.readFtp(); + return new ResponseEntity<>("耗用成功!",HttpStatus.OK); + } @Log("导出数据") @ApiOperation("导出数据") diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/BomAccountService.java b/youchain-system/src/main/java/com/youchain/basicdata/service/BomAccountService.java index 6194837..51e3fcb 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/service/BomAccountService.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/BomAccountService.java @@ -145,12 +145,12 @@ public interface BomAccountService { * @param tckw * @return */ - List queryTckwList(String tckw) ; + List queryTckwList(String tckw,String bigItemCode); /*** * 台车配料出库 * @param tckw */ - void tcCount(String tckw); + void tcCount(String tckw,String bigItemCode); /** * Bom对应库存扣减 @@ -161,6 +161,15 @@ public interface BomAccountService { * @param refObjId * @param description */ - void bomInvDeal(List bs,double orderQty,String logType,String billCode,Long refObjId,String description); + void bomInvDeal(List bs,double orderQty,String logType,String billCode,Long refObjId,String xpp,String description); + + /*** + * 台车BOM下线 + * @param bs + * @param orderQty + * @param billCode + * @param refObjId + */ + void bomTcInvDeal(List bs,double orderQty,String billCode,Long refObjId); } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/ImportXppPlanService.java b/youchain-system/src/main/java/com/youchain/basicdata/service/ImportXppPlanService.java new file mode 100644 index 0000000..7c7f72a --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/ImportXppPlanService.java @@ -0,0 +1,12 @@ +package com.youchain.basicdata.service; + +import org.springframework.web.multipart.MultipartFile; + +public interface ImportXppPlanService { + /** + * 批量导入 + * @param file 文件 + */ + void importData(MultipartFile file); + +} diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/dto/BomAccountQueryCriteria.java b/youchain-system/src/main/java/com/youchain/basicdata/service/dto/BomAccountQueryCriteria.java index 50fa324..490c278 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/service/dto/BomAccountQueryCriteria.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/dto/BomAccountQueryCriteria.java @@ -64,6 +64,9 @@ public class BomAccountQueryCriteria{ private String bp_type; @Query private String tckw; + + @Query + private String kyQz; @Query private String supplier; diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/impl/BomAccountServiceImpl.java b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/BomAccountServiceImpl.java index 73bb88d..c4fb37a 100644 --- a/youchain-system/src/main/java/com/youchain/basicdata/service/impl/BomAccountServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/BomAccountServiceImpl.java @@ -306,7 +306,7 @@ public class BomAccountServiceImpl implements BomAccountService { hql+=" and t.rArea.id = " + shAreaId; } if(kyh!=null&&!kyh.equals("")){ - hql+=" and t.kyQz = '" + kyh+"'"; + hql+=" and t.kyQz = '" + kyh+"' and t.zPoint.type='"+BaseStatus.ZZKW+"'"; } Query query = entityManager.createQuery(hql); List resultList = query.getResultList(); @@ -371,8 +371,8 @@ public class BomAccountServiceImpl implements BomAccountService { } - public List queryTckwList(String tckw) { - List bs = bomAccountRepository.queryTchws(tckw); + public List queryTckwList(String tckw,String bigItemCode){ + List bs = bomAccountRepository.queryTckwBom(tckw,bigItemCode); List list =new ArrayList<>(); for(BomAccount ba:bs){ TcOutList tc=new TcOutList(); @@ -389,27 +389,40 @@ public class BomAccountServiceImpl implements BomAccountService { } @Transactional - public void tcCount(String tckw){ - List bs = bomAccountRepository.queryTchws(tckw); + public void tcCount(String tckw,String bigItemCode){ +// List bs = bomAccountRepository.queryTchws(tckw); + List bs = bomAccountRepository.queryTckwBom(tckw,bigItemCode); if (bs.size() <= 0) { throw new BadRequestException(tckw + "未查到对应BOM工位清单"); } - this.bomInvDeal(bs,1d,BizStatus.TC_OUT,tckw,null,"台车配料出库"); + this.bomInvDeal(bs,1d,BizStatus.TC_OUT,tckw,null,null,"台车配料出库"); } //根据BOM进行库存扣减 - public void bomInvDeal(List bs,double orderQty,String logType,String billCode,Long refObjId,String description){ + public void bomInvDeal(List bs,double orderQty,String logType,String billCode,Long refObjId,String xpp,String description){ Area tcArea=areaRepository.getByCode(BaseStatus.DEFAULT_TC_AREA); + int i=0; for(BomAccount ba:bs){ + log.info(i+++"====join........"+ba.getId()); + String stockCode=ba.getBigItem().getCode(); + if(ba.getZPoint()==null){ - throw new BadRequestException(ba.getItem().getCode()+"维护制造库位"); + if(logType.equals(BizStatus.TC_XX)) { + ba.setDescription(ba.getItem().getCode() + "维护制造库位"); + }else{ + throw new BadRequestException(ba.getItem().getCode() + "维护制造库位"); + } } if(!ba.getZPoint().getType().equals(BaseStatus.ZZKW)){ - throw new BadRequestException(ba.getZPoint().getCode()+"库位类型错误"); + if(logType.equals(BizStatus.TC_XX)) { + ba.setDescription(ba.getZPoint().getCode()+"库位类型错误"); + }else{ + throw new BadRequestException(ba.getZPoint().getCode()+"库位类型错误"); + } } double qty=orderQty*ba.getSingles(); //扣除线边库存 - List inventorys=inventoryService.getXbHyInv(ba.getItem(),ba.getRArea(),ba.getZPoint(),"耗用"); + List inventorys=inventoryService.getXbHyInv(ba.getItem(),ba.getRArea(),ba.getZPoint(),"耗用",null); if(inventorys.size()>0){ int num=0; for(Inventory inv:inventorys){ @@ -432,34 +445,25 @@ public class BomAccountServiceImpl implements BomAccountService { inv.setQuantity(inv.getQuantity()-hyQty); inventoryService.update(inv); InventoryLog log= inventoryLogService.storeInventoryLog(logType,BizStatus.REDUCE,billCode,ba.getRArea(),inv.getItemKey(), - inv.getPoint(),inv.getPoint(),null,null,srcQty,hyQty,null,null,ba.getBigItem().getCode(), + inv.getPoint(),inv.getPoint(),null,null,srcQty,hyQty,stockCode,null,ba.getBigItem().getCode(), refObjId,inv.getId(),description); - log.setZzkw(ba.getZPoint()); - inventoryLogService.update(log); } }else{ -// Point point=ba.getCArea().getPoint(); - Point point=pointService.findEntityById(ba.getRArea().getPointId()); - if(point==null){ - throw new BadRequestException(ba.getRArea().getCode()+"库区无对应待投料库位"); - } ItemKey itemKey=itemKeyService.getItemKey(ba.getItem(),null,ba.getBonded()); Inventory inventory = new Inventory(); inventory.setItemKey(itemKey); inventory.setPoint(ba.getZPoint()); inventory.setPointCode(ba.getZPoint().getCode()); // inventory.setZzkw(ba.getZPoint()); - inventory.setDept(UserUtils.getDept()); + inventory.setDept(ba.getRArea().getDept()); inventory.setArea(ba.getRArea()); inventory.setQuantity(-qty); inventoryService.create(inventory); InventoryLog log=inventoryLogService.storeInventoryLog(logType,BizStatus.REDUCE,billCode,ba.getRArea(),inventory.getItemKey(), inventory.getPoint(),inventory.getPoint(),null,null,0d,qty,null,null,ba.getBigItem().getCode(), refObjId,inventory.getId(),description); -// log.setZzkw(ba.getZPoint()); - inventoryLogService.update(log); } - ItemKey dstItemKey = itemKeyService.getItemKey(ba.getItem(), null,ba.getBonded()); + ItemKey dstItemKey = itemKeyService.getItemKey(ba.getItem(), ba.getKyQz(),ba.getBonded()); //台车出库,创建台车库位 if(logType.equals(BizStatus.TC_OUT)) { Point dstPoint=pointRepository.findByCode(ba.getTckw()); @@ -476,15 +480,82 @@ public class BomAccountServiceImpl implements BomAccountService { dstPoint.setType(BaseStatus.HCKW); pointRepository.save(dstPoint); } - Inventory dstInventory = inventoryService.getInventory(dstItemKey, tcArea, dstPoint, dstPoint, dstPoint.getDept(), BizStatus.TC_RK, null); + + Inventory dstInventory = inventoryService.getInventory(dstItemKey, tcArea, dstPoint, dstPoint, dstPoint.getDept(), BizStatus.TC_RK, stockCode); double srcQty = dstInventory.getQuantity(); dstInventory.setQuantity(dstInventory.getQuantity() + orderQty*ba.getSingles()); inventoryService.update(dstInventory); - InventoryLog inventoryLog = inventoryLogService.storeInventoryLog(BizStatus.TC_RK, BizStatus.ADD, billCode, tcArea, dstItemKey, dstInventory.getPoint(), dstInventory.getPoint(), null, null, srcQty, qty+0d, null, null, + InventoryLog inventoryLog = inventoryLogService.storeInventoryLog(BizStatus.TC_RK, BizStatus.ADD, billCode, tcArea, dstItemKey, dstInventory.getPoint(), dstInventory.getPoint(), null, null, srcQty, orderQty*ba.getSingles(), stockCode, null, ba.getBigItem().getCode(), ba.getId(), dstInventory.getId(), "台车配料入库"); inventoryLogService.update(inventoryLog); } } } + + //根据BOM进行库存扣减 + @Override + @Transactional + public void bomTcInvDeal(List bs,double orderQty,String billCode,Long refObjId){ + Area tcArea=areaRepository.getByCode(BaseStatus.DEFAULT_TC_AREA); + for(BomAccount ba:bs){ + String stockCode=ba.getBigItem().getCode(); + double qty=orderQty*ba.getSingles(); + String tckw=ba.getTckw(); + if(tckw==null){ + tckw="空台车"; + } + Point tcPoint=pointRepository.findByCode(tckw); + if (tcPoint==null){ + tcPoint=new Point(); + tcPoint.setDept(ba.getZPoint().getDept()); + tcPoint.setCode(tckw); + tcPoint.setName(tckw); + tcPoint.setType(BaseStatus.HCKW); + tcPoint.setArea(tcArea); + pointRepository.save(tcPoint); + }else{ + tcPoint.setArea(tcArea); + tcPoint.setType(BaseStatus.HCKW); + pointRepository.save(tcPoint); + } + //扣除台车库存 + List inventorys=inventoryService.getXbHyInv(ba.getItem(),tcArea,tcPoint,"台车下线",stockCode); + if(inventorys.size()>0){ + int num=0; + for(Inventory inv:inventorys){ + if(qty<=0){ + break; + } + num++; + if(numqty||num==inventorys.size()){ + hyQty=qty; + qty-=hyQty; + }else{ + hyQty=inv.getQuantity(); + qty-=hyQty; + } + inv.setQuantity(inv.getQuantity()-hyQty); + inventoryService.update(inv); + inventoryLogService.storeInventoryLog(BizStatus.TC_XX,BizStatus.REDUCE,billCode,tcArea,inv.getItemKey(), + inv.getPoint(),inv.getPoint(),null,null,srcQty,hyQty,stockCode,null,ba.getBigItem().getCode(), + refObjId,inv.getId(),ba.getRArea().getName()+"台车BOM下线"); + + } + }else{ + ItemKey itemKey = itemKeyService.getItemKey(ba.getItem(), ba.getKyQz(),ba.getBonded()); + Inventory inventory = inventoryService.getInventory(itemKey, tcArea, tcPoint, tcPoint, tcPoint.getDept(), BizStatus.TC_XX, stockCode); + inventory.setQuantity(-qty); + inventoryService.create(inventory); + inventoryLogService.storeInventoryLog(BizStatus.TC_XX,BizStatus.REDUCE,billCode,tcArea,inventory.getItemKey(), + inventory.getPoint(),inventory.getPoint(),null,null,0d,qty,null,null,ba.getBigItem().getCode(), + refObjId,inventory.getId(),ba.getRArea().getName()+"台车BOM下线"); + } + } + } } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/basicdata/service/impl/ImportXppPlanServiceImpl.java b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/ImportXppPlanServiceImpl.java new file mode 100644 index 0000000..907f887 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/basicdata/service/impl/ImportXppPlanServiceImpl.java @@ -0,0 +1,134 @@ +package com.youchain.basicdata.service.impl; + +import com.youchain.basicdata.domain.Item; +import com.youchain.basicdata.repository.ItemRepository; +import com.youchain.basicdata.service.ImportXppPlanService; +import com.youchain.basicdata.service.ItemService; +import com.youchain.businessdata.domain.XppPlan; +import com.youchain.businessdata.inputJson.imports.XppPlanImport; +import com.youchain.businessdata.repository.XppPlanRepository; +import com.youchain.businessdata.service.XppPlanService; +import com.youchain.exception.BadRequestException; +import com.youchain.utils.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.multipart.MultipartFile; + +import java.sql.Timestamp; +import java.util.*; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +@Slf4j +public class ImportXppPlanServiceImpl implements ImportXppPlanService { + + private final XppPlanRepository xppPlanRepository; + + private final ItemRepository itemRepository; + + private final ItemService itemService; + + private final XppPlanService xppPlanService; + + + + @Override + @Transactional(rollbackFor = Exception.class) + public void importData(MultipartFile file) { + // 根据模板类型进行不同的处理 + List requiredColumns = Arrays.asList( + "项目名", + "工厂", + "品番", + "定单编号", + "分支号", + "受入受領NO", + "创建日期", + "端末NO", + "検収受入数", + "早遅日" + ); + // 验证模板类型是否正确 + isValidTemplateType(file,requiredColumns); + + // 根据模板类型进行不同的处理 + baseImportTemplate(file); + } + + // 处理标准模板 + @Transactional + public void baseImportTemplate(MultipartFile file) { + // 读取sheet数据,从第三行开始读取 + List dataList = FastExcelUtil.readExcelData(file, XppPlanImport.class, 0, 3); + //批量导入 + importPointData(dataList); + } + + /** + * 处理批量导入 + */ + private void importPointData(List dataList) { + // TODO: 实现批量导入逻辑 + log.info("处理批量导入,数据条数: {}", dataList.size()); + + //获取文件中所有的库位编码 +// List itemcodes = dataList.stream().map(XppPlanImport::getPf).collect(Collectors.toList()); + List itemcodes = dataList.stream() + .map(XppPlanImport::getPf) + .filter(Objects::nonNull) + .map(pf -> pf.length() >= 10 ? pf.substring(0, 10) : pf) + .collect(Collectors.toList()); + itemcodes = itemcodes.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()); + Map exitItemMap = validateItem(itemcodes); + for (XppPlanImport data : dataList) { + String pf=data.getPf().length() >= 10 ? data.getPf().substring(0, 10) : data.getPf(); + Item item = exitItemMap.get(pf); + Timestamp cjrq = Timestamp.valueOf(data.getCjrq()); + Timestamp gxrq = Timestamp.valueOf(data.getGxrq()); + XppPlan xppPlan=new XppPlan(); + xppPlan.setItem(item); + xppPlan.setItemCode(pf); + xppPlan.setRelaCode(data.getXmm()); + xppPlan.setAreaCode(data.getGc()); + xppPlan.setDdbh(data.getDdbh()); + xppPlan.setFzh(data.getFzh()); + xppPlan.setZf(data.getSrsl()); + xppPlan.setNrDate(gxrq); + xppPlan.setCjDate(cjrq); + xppPlan.setCjr(data.getDmno()); + xppPlan.setNrs(Integer.parseInt(data.getSrs())); + xppPlan.setShQuantity(data.getZcr()); + xppPlanRepository.save(xppPlan); + } + } + //验证品番 + private Map validateItem(List codes) { + Map existMap = itemService.queryByItemCodesToMap(codes); + if (existMap.isEmpty()) { + throw new BadRequestException("品番不存在或已失效"); + } + List existCodes = new ArrayList(existMap.keySet()); + // 获取两个集合的非交集说明品番不存在或失效,直接提示 +// List difference = SmartStringUtil.getDifference(codes, existCodes); +// if (CollectionUtils.isNotEmpty(difference)) { +// throw new BadRequestException(difference + "品番不存在或已失效"); +// } + return existMap; + } + + + //验证模板是否使用正确 + private List isValidTemplateType(MultipartFile file,List requiredColumns) { + List headers = FastExcelUtil.readHeadContent(file, 0, 2); + if (!SmartStringUtil.containsAllIgnoreCase(requiredColumns, headers)) { + throw new BadRequestException("标准导入模板不正确,请确认模板信息"); + } + return headers; + } + + +} diff --git a/youchain-system/src/main/java/com/youchain/businessdata/domain/XppPlan.java b/youchain-system/src/main/java/com/youchain/businessdata/domain/XppPlan.java new file mode 100644 index 0000000..cadcd75 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/domain/XppPlan.java @@ -0,0 +1,145 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.domain; + +import com.youchain.basicdata.domain.Item; +import lombok.Data; +import cn.hutool.core.bean.BeanUtil; +import io.swagger.annotations.ApiModelProperty; +import cn.hutool.core.bean.copier.CopyOptions; +import javax.persistence.*; +import javax.validation.constraints.*; +import javax.persistence.Entity; +import com.youchain.base.BaseEntity; +import javax.persistence.Table; +import org.hibernate.annotations.*; +import java.sql.Timestamp; +import java.io.Serializable; + +/** +* @website https://eladmin.vip +* @description / +* @author houjianlan +* @date 2026-02-11 +**/ +@Entity +@Data +@Table(name="data_xpp_plan") +public class XppPlan extends BaseEntity implements Serializable { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "`id`") + @ApiModelProperty(value = "ID") + private Long id; + + @OneToOne + @JoinColumn(name = "`item_id`") + @ApiModelProperty(value = "品番") + private Item item; + + @Column(name = "`ac`") + @ApiModelProperty(value = "ac") + private String ac; + + @Column(name = "`nrs`") + @ApiModelProperty(value = "纳入数") + private Integer nrs; + + @Column(name = "`ddbh`") + @ApiModelProperty(value = "定单编号") + private String ddbh; + + @Column(name = "`zf`") + @ApiModelProperty(value = "受入受領NO") + private String zf; + + @Column(name = "`fzh`") + @ApiModelProperty(value = "分支号") + private String fzh; + + @Column(name = "`nr_date`") + @ApiModelProperty(value = "更新日期") + private Timestamp nrDate; + + @Column(name = "`cj_date`") + @ApiModelProperty(value = "创建日期") + private Timestamp cjDate; + + @Column(name = "`sh_quantity`") + @ApiModelProperty(value = "送货数量") + private String shQuantity; + + @Column(name = "`cjr`") + @ApiModelProperty(value = "采集人") + private String cjr; + + @Column(name = "`bhr`") + @ApiModelProperty(value = "备货人") + private String bhr; + + @Column(name = "`fhr`") + @ApiModelProperty(value = "发货人") + private String fhr; + + @Column(name = "`contents`") + @ApiModelProperty(value = "加工内容") + private String contents; + + @Column(name = "`rela_supplier`") + @ApiModelProperty(value = "供应商") + private String relaSupplier; + + @Column(name = "`rela_door`") + @ApiModelProperty(value = "门号") + private String relaDoor; + + @Column(name = "`rela_code`") + @ApiModelProperty(value = "纳入场所") + private String relaCode; + + @Column(name = "`rela_type`") + @ApiModelProperty(value = "箱种") + private String relaType; + + @Column(name = "`rela_quantity`") + @ApiModelProperty(value = "收容数") + private Double relaQuantity; + + @Column(name = "`area_code`") + @ApiModelProperty(value = "品区") + private String areaCode; + + @Column(name = "`item_code`") + @ApiModelProperty(value = "品番") + private String itemCode; + + @Column(name = "`dept_id`") + @ApiModelProperty(value = "仓库ID") + private Long deptId; + + @Column(name = "`description`") + @ApiModelProperty(value = "描述") + private String description; + + @Column(name = "`ewm`",unique = true) + @ApiModelProperty(value = "现品票二维码") + private String ewm; + + public void copy(XppPlan source){ + BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); + } +} diff --git a/youchain-system/src/main/java/com/youchain/businessdata/inputJson/imports/XppPlanImport.java b/youchain-system/src/main/java/com/youchain/businessdata/inputJson/imports/XppPlanImport.java new file mode 100644 index 0000000..7db9e83 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/inputJson/imports/XppPlanImport.java @@ -0,0 +1,47 @@ +package com.youchain.businessdata.inputJson.imports; + +import cn.idev.excel.annotation.ExcelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @description: 基础导入 + * @author: youzhi.gao + * @date: 2020-04-01 15:01 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class XppPlanImport { + @ExcelProperty("项目名") + private String xmm; + @ExcelProperty("工厂") + private String gc; + + @ExcelProperty("品番") + private String pf; + + @ExcelProperty("定单编号") + private String ddbh; + + @ExcelProperty("分支号") + private String fzh; + + @ExcelProperty("受入受領NO") + private String srsl; + + @ExcelProperty("创建日期") + private String cjrq; + @ExcelProperty("更新日期") + private String gxrq; + @ExcelProperty("端末NO") + private String dmno; + @ExcelProperty("検収受入数") + private String srs; + @ExcelProperty("早遅日") + private String zcr; + +} diff --git a/youchain-system/src/main/java/com/youchain/businessdata/repository/SparepartsRepository.java b/youchain-system/src/main/java/com/youchain/businessdata/repository/SparepartsRepository.java index 801107b..e746d07 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/repository/SparepartsRepository.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/repository/SparepartsRepository.java @@ -15,9 +15,15 @@ */ package com.youchain.businessdata.repository; +import com.youchain.basicdata.domain.BomAccount; import com.youchain.businessdata.domain.Spareparts; +import com.youchain.utils.BaseStatus; +import com.youchain.utils.BizStatus; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; + +import java.util.List; /** * @website https://eladmin.vip @@ -25,4 +31,7 @@ import org.springframework.data.jpa.repository.JpaSpecificationExecutor; * @date 2024-01-30 **/ public interface SparepartsRepository extends JpaRepository, JpaSpecificationExecutor { + @Query(value = "SELECT * FROM `data_spareparts` s where s.status='UN_CONSUME'", nativeQuery = true) + List getSparepartsList(); + } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/repository/XppPlanRepository.java b/youchain-system/src/main/java/com/youchain/businessdata/repository/XppPlanRepository.java new file mode 100644 index 0000000..c237214 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/repository/XppPlanRepository.java @@ -0,0 +1,34 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.repository; + +import com.youchain.businessdata.domain.XppPlan; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2026-02-11 +**/ +public interface XppPlanRepository extends JpaRepository, JpaSpecificationExecutor { + /** + * 根据 Ewm 查询 + * @param ewm / + * @return / + */ + XppPlan findByEwm(String ewm); +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/rest/AsnDetailController.java b/youchain-system/src/main/java/com/youchain/businessdata/rest/AsnDetailController.java index 9d8d88a..d01c64a 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/rest/AsnDetailController.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/rest/AsnDetailController.java @@ -24,10 +24,7 @@ import com.youchain.basicdata.domain.*; import com.youchain.basicdata.repository.BigItemRepository; import com.youchain.basicdata.repository.BomAccountRepository; import com.youchain.basicdata.repository.StockRepository; -import com.youchain.basicdata.service.AreaService; -import com.youchain.basicdata.service.ItemService; -import com.youchain.basicdata.service.StockService; -import com.youchain.basicdata.service.PointService; +import com.youchain.basicdata.service.*; import com.youchain.basicdata.service.dto.AreaDto; import com.youchain.basicdata.service.mapstruct.PointMapper; import com.youchain.businessdata.inputJson.IRkConfirm; @@ -48,6 +45,7 @@ import com.youchain.businessdata.service.mapstruct.AsnMapper; import com.youchain.businessdata.service.mapstruct.InventoryMapper; import com.youchain.config.FileProperties; import com.youchain.exception.BadRequestException; +import com.youchain.exception.OperBadRequestException; import com.youchain.exception.handler.ApiError; import com.youchain.exception.handler.ApiResult; import com.youchain.utils.*; @@ -102,6 +100,7 @@ public class AsnDetailController { private final PointService pointService; private final AreaService areaService; + private final BomAccountService bomAccountService; private final InventoryRepository inventoryRepository; private final PointMapper pointMapper; @@ -283,7 +282,7 @@ public class AsnDetailController { } Point point = pointService.getPoint(pointCode,null, null, null); if (point == null) { - throw new BadRequestException(pointCode + "库位不存在"); + throw new OperBadRequestException(pointCode + "库位不存在"); } if(bomItemCode==null){ bomItemCode=point.getItemCode(); @@ -293,7 +292,7 @@ public class AsnDetailController { if(seq==2) {//收货上架 //只能材管库位 if(!point.getType().equals(BaseStatus.CH)){ - throw new BadRequestException("库位不为材管库位"); + throw new OperBadRequestException(point.getCode()+"库位不为材管库位"); } XppRecord xppRecord = xppRecordService.saveXppRecord(ewm, point.getArea(), BillParmType.XPP_1001); AsnDetail asnDetail = xppRecordService.addAsnDetail(xppRecord); @@ -305,14 +304,39 @@ public class AsnDetailController { } asnDetailRepository.save(asnDetail); asnDetailService.putawayInv(asnDetail.getId(), area.getId(), point.getId(), xppRecord.getNrs(), xppRecord.getEwm()); + //获取品番,如果品番为台车库位码,则台车配料 + if(!nrcs.equals("00404")&&!nrcs.equals("00405")) { + String tckw = ewm.substring(3, 13); + List bs = bomAccountRepository.queryTckwBom(tckw, null); + if (bs.size() > 0) { + bomAccountService.bomInvDeal(bs, xppRecord.getNrs(), BizStatus.TC_ZGP_OUT, tckw, xppRecord.getId(), xppRecord.getEwm(),"台车配料支给品出库"); + } + } }else if(seq==3){//制造投料 if(!point.getType().equals(BaseStatus.ZZKW)){ - throw new BadRequestException("库位不为制造库位"); + throw new OperBadRequestException(point.getCode()+"库位不为制造库位"); } if(bonded==null){ - throw new BadRequestException(bonded + "税别不能为空"); + throw new OperBadRequestException(bonded + "税别不能为空"); + } + String xppItemCode = ewm.substring(3, 13); + if(!xppItemCode.equals(bomItemCode)){ + throw new OperBadRequestException("现品票品番"+xppItemCode+"和库位品番"+bomItemCode+"不一致"); + } + XppRecord xppRecord = xppRecordService.saveXppRecord(ewm,point.getArea(),BillParmType.XPP_2001); + xppRecordService.xppPutaway(ewm,xppRecord,bonded,bomItemCode,point); + String nrcs=xppRecord.getRelaCode(); + if(!nrcs.equals("00404")&&!nrcs.equals("00405")) { + //获取品番,如果品番为台车库位码,则台车配料 + String tckw = ewm.substring(3, 13); + List bs = bomAccountRepository.queryTckwBom(tckw, null); + if (bs.size() > 0) { + XppRecord xppRecord2 = xppRecordRepository.findByEwmType(ewm,BillParmType.XPP_1001); + if(xppRecord2==null) { + bomAccountService.bomInvDeal(bs, xppRecord.getNrs(), BizStatus.TC_ZGP_OUT, tckw, xppRecord.getId(), xppRecord.getEwm(), "台车配料支给品出库"); + } + } } - xppRecordService.xppPutaway(ewm,bonded,bomItemCode,point); } } } @@ -339,12 +363,25 @@ public class AsnDetailController { asnDetail.setPropC2(BaseStatus.KS); } asnDetailService.putawayInv(asnDetail.getId(),point.getArea().getId(),pointId,xppRecord.getNrs(),xppRecord.getEwm()); + //获取品番,如果品番为台车库位码,则台车配料 + String tckw=ewm.substring(3,13); + List bs = bomAccountRepository.queryTckwBom(tckw,null); + if(bs.size()>0){ + bomAccountService.bomInvDeal(bs,xppRecord.getNrs(),BizStatus.TC_ZGP_OUT,tckw,xppRecord.getId(),xppRecord.getEwm(),"台车配料支给品出库"); + } }else if(type.equals(BillParmType.XPP_2001)){//制造投料上架 //查找线边库存是否存在,插入 Long bomId=Long.parseLong(rk.get("bomId").toString()); BomAccount bom=bomAccountRepository.getById(bomId); String bomItemCode=bom.getItem().getCode(); - xppRecordService.xppPutaway(ewm,bom.getBonded(),bomItemCode,point); + String xppItemCode = ewm.substring(3, 13); + if(!xppItemCode.equals(bomItemCode)){ + throw new BadRequestException("现品票品番"+xppItemCode+"和库位品番"+bomItemCode+"不一致"); + //return new ResponseEntity<>( "现品票品番"+xppItemCode+"和库位品番"+bomItemCode+"不一致", BAD_REQUEST); + } + XppRecord xppRecord = xppRecordService.saveXppRecord(ewm,point.getArea(),BillParmType.XPP_2001); + xppRecordService.xppPutaway(ewm,xppRecord,bom.getBonded(),bomItemCode,point); + } return new ResponseEntity<>("操作成功", HttpStatus.OK); } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryController.java b/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryController.java index 29cc7bc..1196407 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryController.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryController.java @@ -56,6 +56,7 @@ import org.springframework.web.bind.annotation.*; import io.swagger.annotations.*; import java.io.IOException; +import java.math.BigInteger; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -96,7 +97,24 @@ public class InventoryController { @GetMapping(value = "/downloadXb") @AnonymousAccess public void downloadXb(HttpServletResponse response, InventoryQueryCriteria criteria) throws Exception { - inventoryService.downloadXb(inventoryService.queryAll(criteria), response); + List contentList = inventoryService.queryAll(criteria); + if(criteria.getBetc()&&criteria.getPointType().equals("HCKW")&&contentList.size()>0){ + //得到bom刻印台车 + List tckws=bomAccountRepository.queryTckwBom(); + Map tckw_tyl=new HashMap<>(); + for(Object[] tckw:tckws){ + String key=tckw[0].toString()+tckw[1].toString()+tckw[2].toString()+tckw[3].toString(); + Integer singles =Integer.parseInt(tckw[4].toString()); + tckw_tyl.put(key,singles); + } + for (InventoryDto dto: contentList) { + // 计算qty值(这里示例,具体逻辑根据业务需求) + String key=dto.getPoint().getCode()+dto.getStockCode()+dto.getItemKey().getItem().getId()+dto.getItemKey().getPropC1(); + dto.setWeight(tckw_tyl.get(key)==null?1d:tckw_tyl.get(key)+0d); + dto.setVolume(dto.getQuantity()/dto.getWeight()); + } + } + inventoryService.downloadXb(contentList, response); } @Log("导出协同数据") @ApiOperation("导出协同数据") @@ -122,7 +140,29 @@ public class InventoryController { // if (criteria.getItemCodeOne() != null && criteria.getItemCode() != null) { // criteria.setItemCodeOne(null); // } - return new ResponseEntity<>(inventoryService.queryAll(criteria, pageable), HttpStatus.OK); + Map list=inventoryService.queryAll(criteria, pageable); + if(criteria.getBetc()&&criteria.getPointType().equals("HCKW")){ + if (list.containsKey("content") && list.get("content") instanceof List) { + List contentList = (List) list.get("content"); + //得到bom刻印台车 + List tckws=bomAccountRepository.queryTckwBom(); + Map tckw_tyl=new HashMap<>(); + for(Object[] tckw:tckws){ + String key=tckw[0].toString()+tckw[1].toString()+tckw[2].toString()+tckw[3].toString(); + Integer singles =Integer.parseInt(tckw[4].toString()); + tckw_tyl.put(key,singles); + } + for (InventoryDto dto: contentList) { + // 计算qty值(这里示例,具体逻辑根据业务需求) + String key=dto.getPoint().getCode()+dto.getStockCode()+dto.getItemKey().getItem().getId()+dto.getItemKey().getPropC1(); + dto.setWeight(tckw_tyl.get(key)==null?1d:tckw_tyl.get(key)+0d); + dto.setVolume(dto.getQuantity()/dto.getWeight()); + } + // 如果需要,将修改后的列表放回原map + list.put("content", contentList); + } + } + return new ResponseEntity<>(list, HttpStatus.OK); // return new ResponseEntity<>(inventoryService.queryInvAll(criteria, pageable), HttpStatus.OK); } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryLogController.java b/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryLogController.java index e3e6302..55a7c66 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryLogController.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/rest/InventoryLogController.java @@ -46,21 +46,21 @@ public class InventoryLogController { private final InventoryLogService inventoryLogService; - /*@Log("导出数据") + @Log("导出数据") @ApiOperation("导出数据") @GetMapping(value = "/download") @AnonymousAccess public void exportInventoryLog(HttpServletResponse response, InventoryLogQueryCriteria criteria) throws Exception { inventoryLogService.download(inventoryLogService.queryAll(criteria), response); - }*/ + } - @Log("导出数据") + /*@Log("导出数据") @ApiOperation("导出数据") @GetMapping("/download") @AnonymousAccess public void exportInventoryLogs(HttpServletResponse response, InventoryLogQueryCriteria criteria) throws IOException{ inventoryLogService.exportInventoryLogs(criteria, response); - } + }*/ @GetMapping @Log("查询inventoryLog") diff --git a/youchain-system/src/main/java/com/youchain/businessdata/rest/PickDetailController.java b/youchain-system/src/main/java/com/youchain/businessdata/rest/PickDetailController.java index c47a8da..e882c8f 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/rest/PickDetailController.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/rest/PickDetailController.java @@ -36,6 +36,7 @@ import com.youchain.businessdata.service.*; import com.youchain.businessdata.service.dto.*; import com.youchain.businessdata.service.dto.jsonDto.CxjlDto; import com.youchain.exception.BadRequestException; +import com.youchain.exception.OperBadRequestException; import com.youchain.exception.handler.ApiResult; import com.youchain.utils.*; import lombok.extern.slf4j.Slf4j; @@ -425,7 +426,7 @@ public class PickDetailController { } } if(no_exits){ - throw new BadRequestException( "扫描箱单号不正确"); + throw new OperBadRequestException( stock_code+"扫描箱单号不正确"); } for(Task task:ts){ pickTicketService.pickForTask(task.getId(), task.getSrcStockCode(), task.getPlanQty()-task.getMoveQty(), null, SecurityUtils.getCurrentUsername()); @@ -445,14 +446,14 @@ public class PickDetailController { //扫描箱单内现品票即可 String xpp=zzjlPick.getXpp(); if(xpp==null){ - throw new BadRequestException( "请扫描现品票"); + throw new OperBadRequestException( "请扫描现品票"); } RRkXpp rRkXpp=xppRecordService.xppAnalysis(xpp,null); //查询是否能找到对应的库存 List invs = inventoryRepository.queryInvStockItemCode(stock_code,rRkXpp.getItemCode()); Inventory inv=invs.get(0); if(inv.getQuantity() queryXppPlan(XppPlanQueryCriteria criteria, Pageable pageable){ + return new ResponseEntity<>(xppPlanService.queryAll(criteria,pageable),HttpStatus.OK); + } + + @PostMapping + @Log("新增xppPlan") + @ApiOperation("新增xppPlan") + @PreAuthorize("@el.check('xppPlan:add')") + public ResponseEntity createXppPlan(@Validated @RequestBody XppPlan resources){ + return new ResponseEntity<>(xppPlanService.create(resources),HttpStatus.CREATED); + } + + @PutMapping + @Log("修改xppPlan") + @ApiOperation("修改xppPlan") + @PreAuthorize("@el.check('xppPlan:edit')") + public ResponseEntity updateXppPlan(@Validated @RequestBody XppPlan resources){ + xppPlanService.update(resources); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @DeleteMapping + @Log("删除xppPlan") + @ApiOperation("删除xppPlan") + @PreAuthorize("@el.check('xppPlan:del')") + public ResponseEntity deleteXppPlan(@RequestBody Long[] ids) { + xppPlanService.deleteAll(ids); + return new ResponseEntity<>(HttpStatus.OK); + } +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/rest/XppRecordController.java b/youchain-system/src/main/java/com/youchain/businessdata/rest/XppRecordController.java index 25d8675..3fe5f6e 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/rest/XppRecordController.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/rest/XppRecordController.java @@ -295,7 +295,7 @@ public class XppRecordController { if(tl.getSlQty()>0){ //扣减线边库存 PickDetail pickDetail=task.getPickDetail(); - List inventorys=inventoryService.getXbHyInv(pickDetail.getItem(),pickDetail.getShArea(),pickDetail.getPoint(),"退库接收"); + List inventorys=inventoryService.getXbHyInv(pickDetail.getItem(),pickDetail.getShArea(),pickDetail.getPoint(),"退库接收",null); if(inventorys.size()>0){ Inventory inv= inventorys.get(0); double srcQty=inv.getQuantity(); @@ -897,8 +897,12 @@ public class XppRecordController { XppRecord old_xpp=xppRecordRepository.getById(id); String ewm=old_xpp.getEwm(); //替换后三位 - if(ewm.length()==85) { - ewm = ewm.substring(0, ewm.length() - 3) + fzh; + if(ewm.length()>=85) { + if(ewm.length()>85) { + ewm = ewm.substring(0, ewm.length() - 3) + fzh+ewm.substring(85); + }else { + ewm = ewm.substring(0, ewm.length() - 3) + fzh; + } }else{ ewm = ewm+ fzh; } diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryBakService.java b/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryBakService.java index 32b5a4a..b6f98e7 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryBakService.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryBakService.java @@ -100,4 +100,9 @@ public interface InventoryBakService { * @return */ Double getXbQty(long itemId, long areaId,Long zzkwId,Long detailId); + + /** + * 自动备份库存 + */ + void insertInvHis(); } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryService.java b/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryService.java index 14f65bd..7c91bca 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryService.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/InventoryService.java @@ -129,7 +129,7 @@ public interface InventoryService { * @param type * @return */ - List getXbHyInv(Item item, Area area,Point zzkw,String type); + List getXbHyInv(Item item, Area area,Point zzkw,String type,String big_item_code); List getInventoryXbTl(Item item, Area area, Point point,Point zzkw); List queryInventory(Stock stock); diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/XppPlanService.java b/youchain-system/src/main/java/com/youchain/businessdata/service/XppPlanService.java new file mode 100644 index 0000000..33f3bd8 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/XppPlanService.java @@ -0,0 +1,83 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.service; + +import com.youchain.businessdata.domain.XppPlan; +import com.youchain.businessdata.service.dto.XppPlanDto; +import com.youchain.businessdata.service.dto.XppPlanQueryCriteria; +import org.springframework.data.domain.Pageable; +import java.util.Map; +import java.util.List; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; + +/** +* @website https://eladmin.vip +* @description 服务接口 +* @author houjianlan +* @date 2026-02-11 +**/ +public interface XppPlanService { + + /** + * 查询数据分页 + * @param criteria 条件 + * @param pageable 分页参数 + * @return Map + */ + Map queryAll(XppPlanQueryCriteria criteria, Pageable pageable); + + /** + * 查询所有数据不分页 + * @param criteria 条件参数 + * @return List + */ + List queryAll(XppPlanQueryCriteria criteria); + + /** + * 根据ID查询 + * @param id ID + * @return XppPlanDto + */ + XppPlanDto findById(Long id); + + /** + * 创建 + * @param resources / + * @return XppPlanDto + */ + XppPlanDto create(XppPlan resources); + + /** + * 编辑 + * @param resources / + */ + void update(XppPlan resources); + + /** + * 多选删除 + * @param ids / + */ + void deleteAll(Long[] ids); + + /** + * 导出数据 + * @param all 待导出的数据 + * @param response / + * @throws Exception / + */ + void download(List all, HttpServletResponse response) throws Exception; +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/XppRecordService.java b/youchain-system/src/main/java/com/youchain/businessdata/service/XppRecordService.java index d6e033f..b30b6cf 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/XppRecordService.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/XppRecordService.java @@ -141,6 +141,6 @@ public interface XppRecordService { * @param bomItemCode * @param point */ - void xppPutaway(String ewm,String bonded,String bomItemCode,Point point); + void xppPutaway(String ewm,XppRecord xppRecord ,String bonded,String bomItemCode,Point point); } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryCriteria.java b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryCriteria.java index 6bee393..b0a51f7 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryCriteria.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryCriteria.java @@ -64,7 +64,7 @@ public class InventoryQueryCriteria{ private Timestamp propD1; // NOT_EQUAL 不等于 - @Query(type = Query.Type.NOT_EQUAL) + @Query(type = Query.Type.NOT_EQUAL, propName="quantity") private Double quantity; @Query(joinName = "stock", propName="name",type = Query.Type.INNER_LIKE) @@ -99,4 +99,7 @@ public class InventoryQueryCriteria{ @Query(type = Query.Type.EQUAL) private Boolean kcyj; + + @Query(type = Query.Type.LESS_THAN_NQ, propName="quantity") + private Double quantity2; } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryDto.java b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryDto.java index 976e7d3..bbcffe1 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryDto.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/InventoryQueryDto.java @@ -36,6 +36,7 @@ public class InventoryQueryDto implements Serializable { private Long id; private String area_name; private String point_code; + private String point_zflx; private String item_code; private String item_name; private String quantity; diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanDto.java b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanDto.java new file mode 100644 index 0000000..6358cdd --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanDto.java @@ -0,0 +1,114 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.service.dto; + +import lombok.Data; +import java.sql.Timestamp; +import java.io.Serializable; + +/** +* @website https://eladmin.vip +* @description / +* @author houjianlan +* @date 2026-02-11 +**/ +@Data +public class XppPlanDto implements Serializable { + + /** ID */ + private Long id; + + /** 品番 */ + private Long itemId; + + /** ac */ + private String ac; + + /** 纳入数 */ + private Integer nrs; + + /** 定单编号 */ + private String ddbh; + + /** 制番 */ + private String zf; + + /** 分支号 */ + private String fzh; + + /** 更新日期 */ + private Timestamp nrDate; + + /** 创建日期 */ + private Timestamp cjDate; + + /** 送货数量 */ + private String shQuantity; + + /** 采集人 */ + private String cjr; + + /** 备货人 */ + private String bhr; + + /** 发货人 */ + private String fhr; + + /** 加工内容 */ + private String contents; + + /** 供应商 */ + private String relaSupplier; + + /** 门号 */ + private String relaDoor; + + /** 纳入场所 */ + private String relaCode; + + /** 箱种 */ + private String relaType; + + /** 收容数 */ + private Double relaQuantity; + + /** 品区 */ + private String areaCode; + + /** 品番 */ + private String itemCode; + + /** 仓库ID */ + private Long deptId; + + /** 描述 */ + private String description; + + /** 创建人 */ + private String createBy; + + /** 修改人 */ + private String updateBy; + + /** 导入时间 */ + private Timestamp createTime; + + /** 更新时间 */ + private Timestamp updateTime; + + /** 现品票二维码 */ + private String ewm; +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanQueryCriteria.java b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanQueryCriteria.java new file mode 100644 index 0000000..99c05c6 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/dto/XppPlanQueryCriteria.java @@ -0,0 +1,48 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.service.dto; + +import lombok.Data; +import java.sql.Timestamp; +import java.util.List; +import com.youchain.annotation.Query; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2026-02-11 +**/ +@Data +public class XppPlanQueryCriteria{ + + /** 模糊 */ + @Query(type = Query.Type.INNER_LIKE) + private String ddbh; + + /** 精确 */ + @Query + private String fzh; + + /** 模糊 */ + @Query(type = Query.Type.INNER_LIKE) + private String itemCode; + /** BETWEEN */ + @Query(type = Query.Type.BETWEEN) + private List nrDate; + /** BETWEEN */ + @Query(type = Query.Type.BETWEEN) + private List createTime; +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryBakServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryBakServiceImpl.java index 7f865b4..8c700b6 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryBakServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryBakServiceImpl.java @@ -135,4 +135,13 @@ public class InventoryBakServiceImpl implements InventoryBakService { } return 0d; } + + @Override + @Transactional + public void insertInvHis() { + String sql="INSERT INTO data_inventory_his (id,item_key_id,point_id,point_code,stock_code, quantity,queued_qty,description,dept_id,create_by,update_by,create_time,update_time,area_id,zzkw,back_time) \n" + + "select id,item_key_id,point_id,point_code,stock_code, quantity,queued_qty,description,dept_id,create_by,update_by,create_time,update_time,area_id,zzkw,SYSDATE() from data_inventory inv "; + Query query=entityManager.createNativeQuery(sql); + query.executeUpdate(); + } } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryServiceImpl.java index 5a47bbc..4659fd1 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/InventoryServiceImpl.java @@ -183,7 +183,7 @@ public class InventoryServiceImpl implements InventoryService { } hql+=" and inv.area.code not like '%盘点%'"; hql+=" and inv.area.code not like '%临时%'"; - hql+= " order by inv.itemKey.propC1 asc,inv.stockCode asc "; + hql+= " order by inv.itemKey.propC1 asc,inv.point.bqlx asc,inv.stockCode asc "; Query query = entityManager.createQuery(hql); List inventoryList = query.getResultList(); return inventoryList; @@ -241,7 +241,7 @@ public class InventoryServiceImpl implements InventoryService { } public Query getQuery(InventoryQueryCriteria criteria,String type){ - String midSql="SELECT inv.id,area.name area_name,p.code point_code,it.code item_code,it.name item_name," + + String midSql="SELECT inv.id,area.name area_name,p.code point_code,p.zflx point_zflx,it.code item_code,it.name item_name," + " inv.quantity ,inv.queued_qty,ik.prop_c2 ,p.inv_min,IF(inv.quantity getXbHyInv(Item item, Area area, Point zzkw,String type) { + public List getXbHyInv(Item item, Area area, Point zzkw,String type,String big_item_code) { //生成Inventory String hql = " from Inventory inv where 1=1 and inv.point.type not in ('"+BaseStatus.BHZC+"','"+BaseStatus.SHZC+"')"; if (item != null) { @@ -396,9 +400,12 @@ public class InventoryServiceImpl implements InventoryService { if(area!=null) { hql += " and inv.area.id=" + area.getId() ; } - if(type.equals("耗用")){//直接制造库位库存耗用 + if(type.equals("耗用")||type.equals("台车下线")){//直接制造库位库存耗用 hql += " and inv.point.id=" + zzkw.getId(); } + if(big_item_code!=null){ + hql += " and inv.stockCode='" + big_item_code+"'" ; + } hql+=" order by inv.itemKey.propC1 asc"; Query query = entityManager.createQuery(hql); List inventoryList = query.getResultList(); diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/SparepartsServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/SparepartsServiceImpl.java index 4f91ef1..f83804f 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/SparepartsServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/SparepartsServiceImpl.java @@ -141,16 +141,26 @@ public class SparepartsServiceImpl implements SparepartsService { throw new BadRequestException("状态必须未未耗用"); } String kyQz=s.getKyQz(); - List bs = bomAccountService.queryBomAccountKy(s.getBigItemId().getId(), s.getShArea().getId(),kyQz); - if (bs.size() <= 0) { - throw new BadRequestException(s.getBigItemId().getCode() + "未查到"+kyQz+"对应BOM工位清单"); + Long areaId=null; + if(s.getShArea()!=null){ + areaId=s.getShArea().getId(); } - bomAccountService.bomInvDeal(bs,s.getOrderQuantity(),BizStatus.XB_HY,s.getBigItemId().getCode(),s.getId(),"零件耗用"); + List bs = bomAccountService.queryBomAccountKy(s.getBigItemId().getId(), areaId,kyQz); + if (bs.size() <= 0) { + if(areaId==null){ + s.setSourceId(s.getBigItemId().getCode() + "未查到"+kyQz+"对应BOM工位清单"); + }else { + throw new BadRequestException(s.getBigItemId().getCode() + "未查到" + kyQz + "对应BOM工位清单"); + } + } +// if(areaId==null){ + bomAccountService.bomTcInvDeal(bs,s.getOrderQuantity(),s.getBigItemId().getCode(),s.getId()); +// }else{ +// bomAccountService.bomInvDeal(bs,s.getOrderQuantity(),BizStatus.XB_HY,s.getBigItemId().getCode(),s.getId(),"零件耗用"); +// } s.setStatus(BizStatus.CONSUME); s.setHyBy(SecurityUtils.getCurrentUsername()); s.setHyTime(new Timestamp(new Date().getTime())); this.update(s); } - - } \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppPlanServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppPlanServiceImpl.java new file mode 100644 index 0000000..270dbd9 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppPlanServiceImpl.java @@ -0,0 +1,96 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.service.impl; + +import com.youchain.businessdata.domain.XppPlan; +import com.youchain.utils.*; +import lombok.RequiredArgsConstructor; +import com.youchain.businessdata.repository.XppPlanRepository; +import com.youchain.businessdata.service.XppPlanService; +import com.youchain.businessdata.service.dto.XppPlanDto; +import com.youchain.businessdata.service.dto.XppPlanQueryCriteria; +import com.youchain.businessdata.service.mapstruct.XppPlanMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import java.util.List; +import java.util.Map; +import java.io.IOException; +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.LinkedHashMap; + +/** +* @website https://eladmin.vip +* @description 服务实现 +* @author houjianlan +* @date 2026-02-11 +**/ +@Service +@RequiredArgsConstructor +public class XppPlanServiceImpl implements XppPlanService { + + private final XppPlanRepository xppPlanRepository; + private final XppPlanMapper xppPlanMapper; + + @Override + public Map queryAll(XppPlanQueryCriteria criteria, Pageable pageable){ + Page page = xppPlanRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder),pageable); + return PageUtil.toPage(page.map(xppPlanMapper::toDto)); + } + + @Override + public List queryAll(XppPlanQueryCriteria criteria){ + return xppPlanMapper.toDto(xppPlanRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root,criteria,criteriaBuilder))); + } + + @Override + @Transactional + public XppPlanDto findById(Long id) { + XppPlan xppPlan = xppPlanRepository.findById(id).orElseGet(XppPlan::new); + ValidationUtil.isNull(xppPlan.getId(),"XppPlan","id",id); + return xppPlanMapper.toDto(xppPlan); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public XppPlanDto create(XppPlan resources) { + return xppPlanMapper.toDto(xppPlanRepository.save(resources)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(XppPlan resources) { + XppPlan xppPlan = xppPlanRepository.findById(resources.getId()).orElseGet(XppPlan::new); + ValidationUtil.isNull( xppPlan.getId(),"XppPlan","id",resources.getId()); + xppPlan.copy(resources); + xppPlanRepository.save(xppPlan); + } + + @Override + public void deleteAll(Long[] ids) { + for (Long id : ids) { + xppPlanRepository.deleteById(id); + } + } + + @Override + public void download(List all, HttpServletResponse response) throws Exception { + List> list= ExcelDownUtils.CreateMap(all,"XppPlan"); + FileUtil.downloadExcel(list, response); + } +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppRecordServiceImpl.java b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppRecordServiceImpl.java index ca1e4fa..ad23a93 100644 --- a/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppRecordServiceImpl.java +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/impl/XppRecordServiceImpl.java @@ -187,7 +187,7 @@ public class XppRecordServiceImpl implements XppRecordService { String cgkw = ewm.substring(i, i += 6); String fzh =null; String sb=null; - if(ewm.length()==85){//85为国产 + if(ewm.length()>=85){//85为国产 fzh=ewm.substring(i, i += 3); } //纳入场所包含0055不接收 @@ -410,7 +410,7 @@ public class XppRecordServiceImpl implements XppRecordService { String zzkw = ewm.substring(i, i += 6); String cgkw = ewm.substring(i, i += 6); String fzh =null; - if(ewm.length()==85){//85为国产 + if(ewm.length()>=85){//85为国产 fzh=ewm.substring(i, i += 3); } // //纳入场所包含0055不接收 @@ -535,13 +535,8 @@ public class XppRecordServiceImpl implements XppRecordService { inventoryLogService.storeInventoryLog(type, BizStatus.REDUCE, billCode, area, ik, srcPoint, srcPoint, null, null, srcQty, xppRecord.getNrs()+0d,null,xppRecord.getEwm(), BizStatus.ASN, xppRecord.getId(), inventory.getId(), des); } - public void xppPutaway(String ewm,String bonded,String bomItemCode,Point point) { - String xppItemCode = ewm.substring(3, 13); - if(!xppItemCode.equals(bomItemCode)){ - throw new BadRequestException("现品票品番"+xppItemCode+"和库位品番"+bomItemCode+"不一致"); - //return new ResponseEntity<>( "现品票品番"+xppItemCode+"和库位品番"+bomItemCode+"不一致", BAD_REQUEST); - } - XppRecord xppRecord = this.saveXppRecord(ewm,point.getArea(),BillParmType.XPP_2001); + public void xppPutaway(String ewm,XppRecord xppRecord,String bonded,String bomItemCode,Point point) { + ItemKey itemKey = itemKeyService.getItemKey(xppRecord.getItem(), null,bonded); Inventory inventory = inventoryService.getInventory(itemKey, point.getArea(), point, point, point.getDept(), BizStatus.ZZKW_TL,null); double srcQty = inventory.getQuantity(); diff --git a/youchain-system/src/main/java/com/youchain/businessdata/service/mapstruct/XppPlanMapper.java b/youchain-system/src/main/java/com/youchain/businessdata/service/mapstruct/XppPlanMapper.java new file mode 100644 index 0000000..bf16283 --- /dev/null +++ b/youchain-system/src/main/java/com/youchain/businessdata/service/mapstruct/XppPlanMapper.java @@ -0,0 +1,32 @@ +/* +* Copyright 2019-2020 Zheng Jie +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package com.youchain.businessdata.service.mapstruct; + +import com.youchain.base.BaseMapper; +import com.youchain.businessdata.domain.XppPlan; +import com.youchain.businessdata.service.dto.XppPlanDto; +import org.mapstruct.Mapper; +import org.mapstruct.ReportingPolicy; + +/** +* @website https://eladmin.vip +* @author houjianlan +* @date 2026-02-11 +**/ +@Mapper(componentModel = "spring", unmappedTargetPolicy = ReportingPolicy.IGNORE) +public interface XppPlanMapper extends BaseMapper { + +} \ No newline at end of file diff --git a/youchain-system/src/main/java/com/youchain/utils/BizStatus.java b/youchain-system/src/main/java/com/youchain/utils/BizStatus.java index c90c7e1..79cc5fe 100644 --- a/youchain-system/src/main/java/com/youchain/utils/BizStatus.java +++ b/youchain-system/src/main/java/com/youchain/utils/BizStatus.java @@ -188,6 +188,11 @@ public class BizStatus { * 库存日志-台车配料出库 */ public static String TC_OUT = "TC_OUT"; + + /** + * 库存日志-台车配料出库 + */ + public static String TC_ZGP_OUT = "TC_ZGP_OUT"; /** * 盘点类型-库区 */ @@ -257,6 +262,12 @@ public class BizStatus { */ public static String TC_RK = "TC_RK"; + + /** + * 台车下线 + */ + public static String TC_XX = "TC_XX"; + /** * 制造库位移位 */ diff --git a/youchain-system/src/main/java/com/youchain/utils/readFilebak/ReadUbuntuFiles.java b/youchain-system/src/main/java/com/youchain/utils/readFilebak/ReadUbuntuFiles.java index 9c23ac4..ad6ff1b 100644 --- a/youchain-system/src/main/java/com/youchain/utils/readFilebak/ReadUbuntuFiles.java +++ b/youchain-system/src/main/java/com/youchain/utils/readFilebak/ReadUbuntuFiles.java @@ -1,9 +1,25 @@ package com.youchain.utils.readFilebak; +import com.google.common.collect.Maps; +import com.youchain.annotation.Log; +import com.youchain.basicdata.domain.Area; +import com.youchain.basicdata.domain.BigItem; +import com.youchain.basicdata.domain.BomAccount; +import com.youchain.basicdata.domain.ProductionPlan; +import com.youchain.basicdata.repository.BigItemRepository; +import com.youchain.basicdata.repository.ProductionPlanRepository; +import com.youchain.basicdata.service.BomAccountService; +import com.youchain.businessdata.domain.Spareparts; +import com.youchain.businessdata.repository.SparepartsRepository; +import com.youchain.businessdata.service.InventoryBakService; +import com.youchain.utils.BizStatus; import com.youchain.utils.DateUtil; -import com.youchain.utils.UserUtils; +import com.youchain.utils.SecurityUtils; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; +import org.springframework.web.bind.annotation.RequestMapping; import javax.annotation.PostConstruct; import java.io.IOException; @@ -12,91 +28,159 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardCopyOption; +import java.sql.Timestamp; import java.util.ArrayList; +import java.util.Date; import java.util.List; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.stream.Stream; @Component +@Slf4j +@Service public class ReadUbuntuFiles { - private static final String SOURCE_DIR = "/home/test"; + private static final String SOURCE_DIR = "/home/1panel/1panel/apps/sftpgo/sftpgo/data/data/data/kcw"; +// private static final String SOURCE_DIR = "E:/data/kcw"; // bak文件夹测试路径:E:\test\bak private static final Path BAK_DIR = Paths.get(SOURCE_DIR).resolve("bak"); @Autowired private ReadFileDataRepository readFileDataRepository; + @Autowired + private SparepartsRepository sparepartsRepository; + @Autowired + private BigItemRepository bigItemRepository; + @Autowired + private BomAccountService bomAccountService; + @Autowired + private InventoryBakService inventoryBakService; + public ReadUbuntuFiles () { - System.out.println("定时读取ubuntu文件"); + log.info("定时读取ubuntu文件"); } // 定时任务执行器 private ScheduledExecutorService scheduler; - @PostConstruct - public void init() { - // 初始化定时任务:延迟0秒开始,每次执行完间隔3秒 - scheduler = Executors.newSingleThreadScheduledExecutor(); - scheduler.scheduleWithFixedDelay( - this::read, // 执行的任务(调用read方法) - 0, // 首次执行延迟时间(0秒后立即开始) - 5, // 上一次任务结束到下一次任务开始的间隔(3秒) - TimeUnit.SECONDS // 时间单位 - ); - System.out.println("定时任务已启动,每次执行完间隔3秒"); - } +// @PostConstruct +// public void init() { +// // 初始化定时任务:延迟0秒开始,每次执行完间隔3秒 +// scheduler = Executors.newSingleThreadScheduledExecutor(); +// scheduler.scheduleWithFixedDelay( +// this::read, // 执行的任务(调用read方法) +// 0, // 首次执行延迟时间(0秒后立即开始) +// 5, // 上一次任务结束到下一次任务开始的间隔(3秒) +// TimeUnit.SECONDS // 时间单位 +// ); +// log.info("定时任务已启动,每次执行完间隔3秒"); +// } // 业务逻辑:读取文件并处理 - public void read() { + public void readFtp() { + log.info("开始读取ubuntu文件"); Path directory = Paths.get(SOURCE_DIR); // 检查目录有效性 if (!Files.exists(directory)) { - System.err.println("目录不存在:" + SOURCE_DIR); + log.error("目录不存在:" + SOURCE_DIR); return; } if (!Files.isDirectory(directory)) { - System.err.println("路径不是目录:" + SOURCE_DIR); + log.error("路径不是目录:" + SOURCE_DIR); return; } // 解析结果集 List readFileDataList=new ArrayList<>(); + List sparepartsList=new ArrayList<>(); + List bigItemRepositories=bigItemRepository.findAll(); + Map itemMap = Maps.newHashMap(); + for (BigItem item : bigItemRepositories) { + itemMap.put(item.getCode(), item); + } + Map zsbigCode = Maps.newHashMap(); + List sparepartsList1=sparepartsRepository.findAll(); + for (Spareparts spareparts : sparepartsList1) { + if(spareparts.getStartNumber()!=null&&!spareparts.getStartNumber().equals("")) { + zsbigCode.put(spareparts.getStartNumber(), spareparts.getStartNumber()); + } + } // 遍历目录下的文件并处理每行内容 try (Stream pathStream = Files.list(directory)) { pathStream.filter(Files::isRegularFile) .forEach(file -> { - System.out.println("\n===== 处理文件:" + file + " ====="); + log.info("\n===== 处理文件:" + file + " ====="); try { // 读取文件所有行(UTF-8编码) List lines = Files.readAllLines(file, StandardCharsets.UTF_8); - + int i=1; // 遍历每行并处理 for (String line : lines) { // 1. 去除首尾空格;2. 将连续空格(1个以上)替换为单个空格 String processedLine = line.trim().replaceAll("\\s+", " "); // 输出处理后的行 - System.out.println(processedLine); + log.info(processedLine); String[] processed = processedLine.split(" "); // 校验格式,并写入结果集 ReadFileData readFileData=new ReadFileData(); + String bigItemCode=processed[0]; readFileData.setBigItemCode(processed[0]); readFileData.setAreaCode(processed[1]); readFileData.setWorkingStation(processed[2]); readFileData.setDownlineDate(processed[3]); readFileData.setMakeLine(processed[4]); readFileDataList.add(readFileData); + + if(bigItemCode!=null&&bigItemCode.length()>=19){ + String idNo=bigItemCode.substring(0,9); + String bigCode=bigItemCode.substring(9,19); + String startNumber=bigItemCode.substring(0,19); + BigItem bigItem=itemMap.get(bigCode); + Spareparts spareparts = new Spareparts(); + spareparts.setStatus("UN_CONSUME"); + if(zsbigCode.get(startNumber)!=null){ + spareparts.setStatus("CF_DATA"); + } + spareparts.setDate(new Timestamp(new Date().getTime())); + spareparts.setKyQz(idNo.substring(0,2)); + spareparts.setBigItemId(bigItem); + spareparts.setOrderQuantity(1); + spareparts.setDescription("FTP自动耗用:"+bigItemCode); + spareparts.setStartNumber(startNumber);//重复则直接将状态改为重复接收 + sparepartsList.add(spareparts); + i++; + } } // 关键修改:将当前处理的文件(file)移动到bak文件夹,而非目录(directory) moveToBakWithoutSubDir(file, DateUtil.getCurrentTimeAsString()); } catch (IOException e) { - System.err.println("处理文件失败:" + file + ",原因:" + e.getMessage()); + log.error("处理文件失败:" + file + ",原因:" + e.getMessage()); } }); } catch (IOException e) { - System.err.println("遍历目录失败:" + e.getMessage()); + log.error("遍历目录失败:" + e.getMessage()); } readFileDataRepository.saveAll(readFileDataList); + sparepartsRepository.saveAll(sparepartsList); + } + + public void ftpHy() { + log.info("开始自动耗用下线数据"); + List list=sparepartsRepository.getSparepartsList(); + for(Spareparts s:list) { + String kyQz = s.getKyQz(); + List bs = bomAccountService.queryBomAccountKy(s.getBigItemId().getId(),null, kyQz); + if (bs.size() <= 0) { + s.setSourceId("未查到" + kyQz + "对应BOM工位清单"); + } + bomAccountService.bomTcInvDeal(bs,s.getOrderQuantity(),s.getBigItemId().getCode(),s.getId()); + s.setStatus(BizStatus.CONSUME); + s.setHyBy("系统自动耗用"); + s.setHyTime(new Timestamp(new Date().getTime())); + sparepartsRepository.save(s); + } } /** @@ -115,7 +199,7 @@ public class ReadUbuntuFiles { // 2. 确保bak文件夹存在 if (!Files.exists(bakDir)) { Files.createDirectory(bakDir); - System.out.println("已创建bak文件夹:" + bakDir); + log.info("已创建bak文件夹:" + bakDir); } // 3. 生成目标文件名(原文件名 + 时间后缀) @@ -133,6 +217,13 @@ public class ReadUbuntuFiles { StandardCopyOption.REPLACE_EXISTING ); - System.out.println("文件已移动至:" + targetFile); + log.info("文件已移动至:" + targetFile); + } + + @Log("定时备份库存数据") + public void backInvHis() { + log.info("开始定时备份库存数据"+new Date()); + inventoryBakService.insertInvHis(); + log.info("定时备份库存数据完成"+new Date()); } }