fix:1.退料审核
2.工序加上工时-生产订单-报工填写
3.核算加上工时计算
| | |
| | | import java.time.LocalDate; |
| | | |
| | | @Data |
| | | @Schema(name = "ProductionAccountDto", description = "production account query dto") |
| | | @Schema(name = "ProductionAccountDto", description = "生产核算查询参数") |
| | | public class ProductionAccountDto extends ProductionAccount { |
| | | |
| | | @Schema(description = "sales contract no") |
| | | @Schema(description = "销售合同号") |
| | | private String salesContractNo; |
| | | |
| | | @Schema(description = "customer contract no") |
| | | @Schema(description = "客户合同号") |
| | | private String customerContractNo; |
| | | |
| | | @Schema(description = "project name") |
| | | @Schema(description = "项目名称") |
| | | private String projectName; |
| | | |
| | | @Schema(description = "customer name") |
| | | @Schema(description = "客户名称") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "product category") |
| | | @Schema(description = "产品类别") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "specification model") |
| | | @Schema(description = "规格型号") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "scheduling user id") |
| | | @Schema(description = "排产人员ID") |
| | | private Long schedulingUserId; |
| | | |
| | | @Schema(description = "scheduling user name") |
| | | @Schema(description = "排产人员名称") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "process") |
| | | @Schema(description = "工序") |
| | | private String process; |
| | | |
| | | @Schema(description = "date type(day/month)") |
| | | @Schema(description = "日期类型(按天/按月)") |
| | | private String dateType; |
| | | |
| | | @Schema(description = "day query date") |
| | | @Schema(description = "按天查询日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDate; |
| | | |
| | | @Schema(description = "date range") |
| | | @Schema(description = "日期范围") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate[] dateRange; |
| | | |
| | | @Schema(description = "start date") |
| | | @Schema(description = "开始日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDateStart; |
| | | |
| | | @Schema(description = "end date") |
| | | @Schema(description = "结束日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate entryDateEnd; |
| | |
| | | @DateTimeFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate requiredDateEnd; |
| | | |
| | | @Schema(description = "销售合同号") |
| | | private String salesContractNo; |
| | | |
| | | } |
| | |
| | | |
| | | @EqualsAndHashCode(callSuper = true) |
| | | @Data |
| | | @Schema(name = "ProductionProductMainDto", description = "production report query dto") |
| | | @Schema(name = "ProductionProductMainDto", description = "生产报工查询参数") |
| | | public class ProductionProductMainDto extends ProductionProductMain { |
| | | |
| | | @Schema(description = "product process route item id") |
| | | @Schema(description = "产品工艺路线工序ID") |
| | | private Long productProcessRouteItemId; |
| | | |
| | | @Schema(description = "production report id") |
| | | @Schema(description = "报工ID") |
| | | private Long productMainId; |
| | | |
| | | @Schema(description = "tenant id") |
| | | @Schema(description = "租户ID") |
| | | private Long tenantId; |
| | | |
| | | @Schema(description = "work order no") |
| | | @Schema(description = "工单编号") |
| | | private String workOrderNo; |
| | | |
| | | @Schema(description = "work order status") |
| | | @Schema(description = "工单状态") |
| | | private String workOrderStatus; |
| | | |
| | | @Schema(description = "nick name") |
| | | @Schema(description = "昵称") |
| | | private String nickName; |
| | | |
| | | @Schema(description = "quantity") |
| | | @Schema(description = "数量") |
| | | private BigDecimal quantity; |
| | | |
| | | @Schema(description = "scrap quantity") |
| | | @Schema(description = "报废数量") |
| | | private BigDecimal scrapQty; |
| | | |
| | | @Schema(description = "product name") |
| | | @Schema(description = "产品名称") |
| | | private String productName; |
| | | |
| | | @Schema(description = "product model name") |
| | | @Schema(description = "产品规格型号") |
| | | private String productModelName; |
| | | |
| | | @Schema(description = "unit") |
| | | @Schema(description = "单位") |
| | | private String unit; |
| | | |
| | | @Schema(description = "sales contract no") |
| | | @Schema(description = "销售合同号") |
| | | private String salesContractNo; |
| | | |
| | | @Schema(description = "scheduling date") |
| | | @Schema(description = "排产日期") |
| | | private LocalDate schedulingDate; |
| | | |
| | | @Schema(description = "scheduling user name") |
| | | @Schema(description = "排产人员名称") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "customer name") |
| | | @Schema(description = "客户名称") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "process") |
| | | @Schema(description = "工序") |
| | | private String process; |
| | | |
| | | @Schema(description = "salary quota") |
| | | @Schema(description = "工资定额") |
| | | private BigDecimal workHours; |
| | | |
| | | @Schema(description = "wages") |
| | | @Schema(description = "工资") |
| | | private BigDecimal wages; |
| | | |
| | | @Schema(description = "operation param list") |
| | | @Schema(description = "工序参数列表") |
| | | private List<ProductionOrderRoutingOperationParam> productionOperationParamList; |
| | | } |
| | |
| | | import java.time.LocalDate; |
| | | |
| | | @Data |
| | | @Schema(name = "ProductionAccountVo", description = "production account page result") |
| | | @Schema(name = "ProductionAccountVo", description = "生产核算分页结果") |
| | | public class ProductionAccountVo { |
| | | |
| | | @Schema(description = "customer contract no") |
| | | @Schema(description = "客户合同号") |
| | | private String customerContractNo; |
| | | |
| | | @Schema(description = "project name") |
| | | @Schema(description = "项目名称") |
| | | private String projectName; |
| | | |
| | | @Schema(description = "customer name") |
| | | @Schema(description = "客户名称") |
| | | private String customerName; |
| | | |
| | | @Schema(description = "product category") |
| | | @Schema(description = "产品类别") |
| | | private String productCategory; |
| | | |
| | | @Schema(description = "specification model") |
| | | @Schema(description = "规格型号") |
| | | private String specificationModel; |
| | | |
| | | @Schema(description = "unit") |
| | | @Schema(description = "单位") |
| | | private String unit; |
| | | |
| | | @Schema(description = "scheduling user id") |
| | | @Schema(description = "排产人员ID") |
| | | private Long schedulingUserId; |
| | | |
| | | @Schema(description = "scheduling user name") |
| | | @Schema(description = "排产人员名称") |
| | | private String schedulingUserName; |
| | | |
| | | @Schema(description = "wages") |
| | | @Schema(description = "工资") |
| | | private BigDecimal wages; |
| | | |
| | | @Schema(description = "finished quantity") |
| | | @Schema(description = "完成数量") |
| | | private BigDecimal finishedNum; |
| | | |
| | | @Schema(description = "salary quota") |
| | | @Schema(description = "工资定额") |
| | | private BigDecimal workHours; |
| | | |
| | | @Schema(description = "output rate") |
| | | @Schema(description = "工时") |
| | | private BigDecimal workHour; |
| | | |
| | | @Schema(description = "产出率") |
| | | private String outputRate; |
| | | |
| | | @Schema(description = "process") |
| | | @Schema(description = "工序") |
| | | private String process; |
| | | |
| | | @Schema(description = "scheduling date") |
| | | @Schema(description = "排产日期") |
| | | @JsonFormat(pattern = "yyyy-MM-dd") |
| | | private LocalDate schedulingDate; |
| | | |
| | | @Schema(description = "scheduling month(yyyy-MM)") |
| | | @Schema(description = "排产月份(yyyy-MM)") |
| | | private String schedulingMonth; |
| | | } |
| | |
| | | |
| | | @Schema(description = "是否结束)") |
| | | private Boolean endOrder; |
| | | |
| | | @Schema(description = "类型 区分计时和计件(0计时1计件)") |
| | | private Integer type; |
| | | } |
| | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | |
| | | @Schema(description = "报工主信息") |
| | | private ProductionProductMain reportMain; |
| | | |
| | | @Schema(description = "工时") |
| | | private BigDecimal workHour; |
| | | |
| | | @Schema(description = "报工产出明细") |
| | | private List<ProductionProductOutput> reportOutputList; |
| | | |
| | |
| | | @Schema(description = "报工主信息") |
| | | private ProductionProductMain reportMain; |
| | | |
| | | @Schema(description = "工时") |
| | | private BigDecimal workHour; |
| | | |
| | | @Schema(description = "质检主信息") |
| | | private QualityInspect inspect; |
| | | |
| | |
| | | |
| | | @Schema(description = "工序表id") |
| | | private Long technologyOperationId; |
| | | |
| | | @Schema(description = "类型 区分计时和计件,0计时,1计件") |
| | | private Integer type; |
| | | } |
| | |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | |
| | | @Schema(description = "工时") |
| | | private BigDecimal workHour; |
| | | |
| | | } |
| | |
| | | BigDecimal totalReturnQty = oldReturnQty.add(currentReturnQty); |
| | | if (currentReturnQty.compareTo(BigDecimal.ZERO) > 0) { |
| | | String returnBatchNo = resolveInventoryBatchNoFromStored(oldPick.getBatchNo()); |
| | | addInventory(oldPick.getId(), oldPick.getProductModelId(), returnBatchNo, currentReturnQty, FEED_RETURN_IN_RECORD_TYPE); |
| | | addInventoryRecordOnly(oldPick.getId(), oldPick.getProductModelId(), returnBatchNo, currentReturnQty, FEED_RETURN_IN_RECORD_TYPE); |
| | | } |
| | | |
| | | BigDecimal actualQty = defaultDecimal(oldPick.getQuantity()) |
| | |
| | | } |
| | | } |
| | | |
| | | private void addInventoryRecordOnly(Long recordId, |
| | | Long productModelId, |
| | | String batchNo, |
| | | BigDecimal quantity, |
| | | String stockInRecordType) { |
| | | // 仅记录入库申请,不做审核通过。 |
| | | BigDecimal addQuantity = defaultDecimal(quantity); |
| | | if (addQuantity.compareTo(BigDecimal.ZERO) <= 0) { |
| | | return; |
| | | } |
| | | try { |
| | | StockInventoryDto stockInventoryDto = new StockInventoryDto(); |
| | | stockInventoryDto.setProductModelId(productModelId); |
| | | stockInventoryDto.setBatchNo(batchNo); |
| | | stockInventoryDto.setQualitity(addQuantity); |
| | | stockInventoryDto.setRecordType(stockInRecordType); |
| | | stockInventoryDto.setRecordId(recordId == null ? 0L : recordId); |
| | | stockInventoryService.addStockInRecordOnly(stockInventoryDto); |
| | | } catch (ServiceException ex) { |
| | | throw ex; |
| | | } catch (Exception ex) { |
| | | throw new ServiceException("退料入库记录保存失败:" + ex.getMessage()); |
| | | } |
| | | } |
| | | |
| | | private List<ProductionOrderPickDto> resolvePickItems(ProductionOrderPickDto dto) { |
| | | // 解析新增场景的领料明细集合。 |
| | | if (dto == null) { |
| | |
| | | ProductionOrder update = new ProductionOrder(); |
| | | update.setId(productionOrder.getId()); |
| | | update.setTechnologyRoutingId(targetRoutingId); |
| | | // 持久化或输出处理结果 |
| | | if (!this.updateById(update)) { |
| | | throw new ServiceException("绑定工艺路线失败"); |
| | | } |
| | |
| | | clearProductionSnapshot(productionOrderId); |
| | | ProductionOrderBom orderBom = syncProductionOrderBomSnapshot(productionOrder, technologyRouting); |
| | | |
| | | //生产订单工艺路线表 |
| | | ProductionOrderRouting orderRouting = new ProductionOrderRouting(); |
| | | orderRouting.setProductionOrderId(productionOrder.getId()); |
| | | orderRouting.setTechnologyRoutingId(technologyRouting.getId()); |
| | |
| | | orderRouting.setDescription(technologyRouting.getDescription()); |
| | | orderRouting.setBomId(technologyRouting.getBomId()); |
| | | orderRouting.setOrderBomId(orderBom == null ? null : orderBom.getId()); |
| | | // 持久化或输出处理结果 |
| | | productionOrderRoutingMapper.insert(orderRouting); |
| | | |
| | | int syncedParamCount = 0; |
| | |
| | | targetOperation.setIsQuality(sourceOperation.getIsQuality()); |
| | | targetOperation.setOperationName(operationNameMap.get(sourceOperation.getTechnologyOperationId())); |
| | | targetOperation.setTechnologyOperationId(sourceOperation.getTechnologyOperationId()); |
| | | targetOperation.setType(sourceOperation.getType()); |
| | | productionOrderRoutingOperationMapper.insert(targetOperation); |
| | | |
| | | boolean isLastOperation = lastDragSort != null && Objects.equals(sourceOperation.getDragSort(), lastDragSort); |
| | |
| | | : workOrderPage.getRecords().stream() |
| | | .filter(Objects::nonNull) |
| | | .sorted(Comparator.comparing(ProductionOperationTaskVo::getId, Comparator.nullsLast(Comparator.naturalOrder()))) |
| | | .collect(Collectors.toList()); |
| | | if (workOrderList == null || workOrderList.isEmpty()) { |
| | | .toList(); |
| | | if (workOrderList.isEmpty()) { |
| | | detailVo.setWorkOrderList(Collections.emptyList()); |
| | | return detailVo; |
| | | } |
| | |
| | | |
| | | ProductionOrderWorkOrderDetailVo.ReportDetail reportDetail = new ProductionOrderWorkOrderDetailVo.ReportDetail(); |
| | | reportDetail.setReportMain(reportMain); |
| | | reportDetail.setWorkHour(reportMain.getWorkHour()); |
| | | reportDetail.setReportOutputList(reportOutputMap.getOrDefault(reportMainId, Collections.emptyList())); |
| | | reportDetail.setReportParamList(reportParamMap.getOrDefault(reportMainId, Collections.emptyList())); |
| | | reportDetailList.add(reportDetail); |
| | |
| | | inspectDetail.setReportId(reportMainId); |
| | | inspectDetail.setReportNo(reportMain.getProductNo()); |
| | | inspectDetail.setReportMain(reportMain); |
| | | inspectDetail.setWorkHour(reportMain.getWorkHour()); |
| | | inspectDetail.setInspect(inspect); |
| | | inspectDetail.setInspectParamList(inspectParamMap.getOrDefault(inspect.getId(), Collections.emptyList())); |
| | | inspectDetail.setInspectFileList(inspectFileMap.getOrDefault(inspect.getId(), Collections.emptyList())); |
| | |
| | | productionProductMain.setUserName(user == null ? dto.getUserName() : user.getNickName()); |
| | | productionProductMain.setProductionOperationTaskId(taskId); |
| | | productionProductMain.setStatus(0); |
| | | productionProductMain.setWorkHour(dto.getWorkHour()); |
| | | productionProductMainMapper.insert(productionProductMain); |
| | | syncOperationParamInputValue(dto, routingOperation.getId(), productionProductMain.getId()); |
| | | |
| | |
| | | @Schema(description = "是否质检") |
| | | private Boolean isQuality; |
| | | |
| | | @Schema(description = "类型 区分计时和计件") |
| | | @Schema(description = "类型 区分计时和计件,0计时,1计件") |
| | | private Integer type; |
| | | |
| | | @Schema(description = "设备id") |
| | |
| | | @Schema(description = "部门ID") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | private Long deptId; |
| | | |
| | | @Schema(description = "类型 区分计时和计件,0计时,1计件") |
| | | private Integer type; |
| | | } |
| | |
| | | routingOperation.setProductModelId(resolveOutputProductModelId(bomStructure, structureById, technologyRouting.getProductModelId())); |
| | | routingOperation.setTechnologyOperationId(bomStructure.getOperationId()); |
| | | routingOperation.setDragSort(dragSort++); |
| | | routingOperation.setIsQuality(getOperationQuality(bomStructure.getOperationId())); |
| | | TechnologyOperation technologyOperation = getOperation(bomStructure.getOperationId()); |
| | | routingOperation.setIsQuality(technologyOperation != null ? technologyOperation.getIsQuality() : null); |
| | | routingOperation.setIsProduction(technologyOperation != null ? technologyOperation.getIsProduction() : null); |
| | | routingOperation.setType(technologyOperation != null ? technologyOperation.getType() : null); |
| | | technologyRoutingOperationMapper.insert(routingOperation); |
| | | syncRoutingOperationParams(routingOperation.getId(), bomStructure.getOperationId()); |
| | | } |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * 质检标识以工序基础表定义为准。 |
| | | */ |
| | | private Boolean getOperationQuality(Long operationId) { |
| | | TechnologyOperation technologyOperation = technologyOperationMapper.selectById(operationId); |
| | | return technologyOperation != null ? technologyOperation.getIsQuality() : null; |
| | | private TechnologyOperation getOperation(Long operationId) { |
| | | if (operationId == null) { |
| | | return null; |
| | | } |
| | | return technologyOperationMapper.selectById(operationId); |
| | | } |
| | | |
| | | private String buildProcessRouteCode(Long id) { |
| | |
| | | pa.scheduling_user_id as schedulingUserId, |
| | | pa.scheduling_user_name as schedulingUserName, |
| | | cast(sum( |
| | | ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when poro.type = 0 then ifnull(pa.work_hours, 0) * ifnull(ppm.work_hour, 0) |
| | | else ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$' |
| | | then cast(substring_index(pm.model, '*', -1) as decimal(18,4)) |
| | | else 1 |
| | | end |
| | | end |
| | | ) as decimal(18,4)) as wages, |
| | | cast(sum(ifnull(pa.finished_num, 0)) as decimal(18,4)) as finishedNum, |
| | | cast(sum(ifnull(pa.work_hours, 0)) as decimal(18,4)) as workHours, |
| | | cast(sum(ifnull(ppm.work_hour, 0)) as decimal(18,4)) as workHour, |
| | | case |
| | | when sum(ifnull(ppo.quantity, 0) + ifnull(ppo.scrapQty, 0)) = 0 then '0%' |
| | | else concat( |
| | |
| | | pm.model as model, |
| | | pm.unit as unit, |
| | | poro.operation_name as operationName, |
| | | poro.type as type, |
| | | IFNULL(scrapStat.scrapQty, 0) AS scrapQty, |
| | | ROUND(IFNULL(pot.complete_quantity, 0) / NULLIF(pot.plan_quantity, 0) * 100, 2) AS completionStatus, |
| | | CASE |
| | |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="drag_sort" property="dragSort" /> |
| | | <result column="is_quality" property="isQuality" /> |
| | | <result column="type" property="type" /> |
| | | <result column="create_user" property="createUser" /> |
| | | <result column="dept_id" property="deptId" /> |
| | | </resultMap> |
| | |
| | | <if test="c.requiredDateStart != null and c.requiredDateEnd != null"> |
| | | and pp.required_date between #{c.requiredDateStart} and #{c.requiredDateEnd} |
| | | </if> |
| | | <if test="c.salesContractNo != null and c.salesContractNo != ''"> |
| | | and sl.sales_contract_no like concat('%', #{c.salesContractNo}, '%') |
| | | </if> |
| | | </if> |
| | | </where> |
| | | ORDER BY COALESCE(pp.id) DESC |
| | |
| | | ifnull(ppo.scrap_qty, 0) as scrapQty, |
| | | date(pa.scheduling_date) as schedulingDate, |
| | | pa.scheduling_user_name as schedulingUserName, |
| | | cast(ifnull(ppm.work_hour, 0) as decimal(18,4)) as workHour, |
| | | cast(ifnull(pa.work_hours, 0) as decimal(18,4)) as workHours, |
| | | cast( |
| | | ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when poro.type = 0 then ifnull(pa.work_hours, 0) * ifnull(ppm.work_hour, 0) |
| | | else ifnull(pa.work_hours, 0) * ifnull(pa.finished_num, 0) * |
| | | case |
| | | when substring_index(pm.model, '*', -1) regexp '^[0-9]+(\\.[0-9]+)?$' |
| | | then cast(substring_index(pm.model, '*', -1) as decimal(18,4)) |
| | | else 1 |
| | | end |
| | | end |
| | | as decimal(18,4) |
| | | ) as wages |
| | | from production_account pa |
| | |
| | | <result column="update_time" property="updateTime" /> |
| | | <result column="drag_sort" property="dragSort" /> |
| | | <result column="is_quality" property="isQuality" /> |
| | | <result column="type" property="type" /> |
| | | <result column="create_user" property="createUser" /> |
| | | <result column="dept_id" property="deptId" /> |
| | | </resultMap> |