| | |
| | | tenant_id bigint not null comment 'ç§æ·id', |
| | | create_time datetime null comment 'å½å
¥æ¶é´', |
| | | update_time datetime null comment 'æ´æ°æ¶é´', |
| | | index idx_staff_on_job_id (staff_on_job_id) |
| | | index idx_staff_on_job_id (staff_on_job_id), |
| | | unique idx_staff_on_job_id_date (staff_on_job_id, date) |
| | | ); |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.basic.dto.ProductDto; |
| | | import com.ruoyi.basic.dto.ProductModelDto; |
| | | import com.ruoyi.basic.dto.ProductModelExportDto; |
| | | import com.ruoyi.basic.dto.ProductTreeDto; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.service.IProductModelService; |
| | | import com.ruoyi.basic.service.IProductService; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | @RestController |
| | |
| | | /** |
| | | * 导å
¥äº§å |
| | | */ |
| | | @Log(title = "导å
¥äº§å",businessType = BusinessType.IMPORT) |
| | | @PostMapping("import") |
| | | public AjaxResult importProduct(MultipartFile file) { |
| | | return AjaxResult.success(productModelService.importProduct(file)); |
| | | @PostMapping("/import") |
| | | @Log(title = "导å
¥äº§å", businessType = BusinessType.IMPORT) |
| | | public AjaxResult importProductModel(@RequestParam("file") MultipartFile file, Integer productId) { |
| | | return productModelService.importProductModel(file, productId); |
| | | } |
| | | |
| | | /** |
| | | * 产å导å
¥æ¨¡æ¿ |
| | | */ |
| | | @GetMapping("/export") |
| | | @ApiOperation("产å导å
¥æ¨¡æ¿") |
| | | @Log(title = "产å导å
¥æ¨¡æ¿", businessType = BusinessType.EXPORT) |
| | | public void importProduct(HttpServletResponse response) { |
| | | ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class); |
| | | excelUtil.importTemplateExcel(response, "产åè§æ ¼å¯¼å
¥æ¨¡æ¿"); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.basic.dto; |
| | | |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * <br> |
| | | * 产åå¯¼åºæ¨¡æ¿ |
| | | * </br> |
| | | * |
| | | * @author deslrey |
| | | * @version 1.0 |
| | | * @since 2026/02/10 14:39 |
| | | */ |
| | | @Data |
| | | public class ProductModelExportDto { |
| | | |
| | | @Excel(name = "è§æ ¼åå·") |
| | | private String model; |
| | | |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | |
| | | } |
| | |
| | | import com.ruoyi.basic.dto.ProductDto; |
| | | import com.ruoyi.basic.dto.ProductModelDto; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.List; |
| | |
| | | */ |
| | | IPage<ProductModel> modelListPage(Page page , ProductDto productDto); |
| | | |
| | | Boolean importProduct(MultipartFile file); |
| | | AjaxResult importProductModel(MultipartFile file, Integer productId); |
| | | } |
| | |
| | | import com.ruoyi.basic.pojo.Product; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.service.IProductModelService; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.common.utils.uuid.IdUtils; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import lombok.AllArgsConstructor; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | |
| | | |
| | | if (productModelDto.getId() == null) { |
| | | ProductModel productModel = new ProductModel(); |
| | | BeanUtils.copyProperties(productModelDto,productModel); |
| | | BeanUtils.copyProperties(productModelDto, productModel); |
| | | return productModelMapper.insert(productModel); |
| | | } else { |
| | | return productModelMapper.updateById(productModelDto); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | @Override |
| | |
| | | |
| | | /** |
| | | * æ ¹æ®idæ¥è¯¢äº§åè§æ ¼å页æ¥è¯¢ |
| | | * |
| | | * @param page |
| | | * @param productDto |
| | | * @return |
| | |
| | | } |
| | | |
| | | @Override |
| | | public Boolean importProduct(MultipartFile file) { |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult importProductModel(MultipartFile file, Integer productId) { |
| | | if (productId == null) { |
| | | return AjaxResult.error("请å
éæ©äº§åå导å
¥è§æ ¼åå·"); |
| | | } |
| | | |
| | | Product product = productMapper.selectById(productId); |
| | | if (product == null) { |
| | | return AjaxResult.error("éæ©ç产åä¸åå¨"); |
| | | } |
| | | |
| | | try { |
| | | ExcelUtil<ProductModel> productModelExcelUtil = new ExcelUtil<>(ProductModel.class); |
| | | List<ProductModel> productModelList = productModelExcelUtil.importExcel(file.getInputStream()); |
| | | Map<String, List<ProductModel>> collect = productModelList.stream().collect(Collectors.groupingBy(ProductModel::getProductName)); |
| | | collect.forEach((k,v)->{ |
| | | Product product = productMapper.selectOne(new LambdaQueryWrapper<Product>().eq(Product::getProductName, k).last("LIMIT 1")); |
| | | if (product != null) { |
| | | v.forEach(productModel -> { |
| | | productModel.setProductId(product.getId()); |
| | | }); |
| | | this.saveOrUpdateBatch(v); |
| | | |
| | | if (productModelList == null || productModelList.isEmpty()) { |
| | | return AjaxResult.error("导å
¥æ°æ®ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | for (int i = 0; i < productModelList.size(); i++) { |
| | | ProductModel item = productModelList.get(i); |
| | | int rowNum = i + 2; |
| | | |
| | | if (StringUtils.isEmpty(item.getModel())) { |
| | | return AjaxResult.error("第 " + rowNum + " è¡å¯¼å
¥å¤±è´¥: [è§æ ¼åå·] ä¸è½ä¸ºç©º"); |
| | | } |
| | | }); |
| | | return true; |
| | | }catch (Exception e) { |
| | | e.printStackTrace(); |
| | | if (StringUtils.isEmpty(item.getUnit())) { |
| | | return AjaxResult.error("第 " + rowNum + " è¡å¯¼å
¥å¤±è´¥: [åä½] ä¸è½ä¸ºç©º"); |
| | | } |
| | | item.setProductId(product.getId()); |
| | | } |
| | | |
| | | saveOrUpdateBatch(productModelList); |
| | | return AjaxResult.success("æå导å
¥ " + productModelList.size() + " æ¡æ°æ®"); |
| | | } catch (Exception e) { |
| | | log.error("导å
¥äº§åè§æ ¼å¼å¸¸", e); |
| | | return AjaxResult.error("导å
¥å¤±è´¥"); |
| | | } |
| | | return false; |
| | | } |
| | | } |
| | |
| | | * @date : 2025/9/19 10:52 |
| | | */ |
| | | @RestController |
| | | @Api(tags = "å·¡æ£ä»»å¡ç®¡ç") |
| | | @Api(tags = "å·¡æ£ä»»å¡è®°å½") |
| | | @RequestMapping("/inspectionTask") |
| | | public class InspectionTaskController extends BaseController { |
| | | |
| | |
| | | * @date : 2025/9/19 10:53 |
| | | */ |
| | | @RestController |
| | | @Api(tags = "宿¶ä»»å¡ç®¡ç") |
| | | @Api(tags = "å·¡æ£ç®¡ç") |
| | | @RequestMapping("/timingTask") |
| | | public class TimingTaskController extends BaseController { |
| | | |
| | |
| | | @PostMapping("/export") |
| | | public void export(HttpServletResponse response, ProductOrderDto productOrderDto) { |
| | | List<ProductOrderDto> list = productOrderService.pageProductOrder(new Page<>(1, -1), productOrderDto).getRecords(); |
| | | |
| | | if (list != null && !list.isEmpty()) { |
| | | list.forEach(item -> { |
| | | // å¤ç©º |
| | | if (item.getQuantity() == null || item.getCompleteQuantity() == null) { |
| | | item.setCompletionStatus(BigDecimal.ZERO); |
| | | return; |
| | | } |
| | | |
| | | // å¤é¶ |
| | | if (item.getQuantity().compareTo(BigDecimal.ZERO) == 0) { |
| | | item.setCompletionStatus(BigDecimal.ZERO); |
| | | return; |
| | | } |
| | | BigDecimal progress = item.getCompleteQuantity() |
| | | .divide(item.getQuantity(), 4, BigDecimal.ROUND_HALF_UP) |
| | | .multiply(new BigDecimal(100)) |
| | | .setScale(2, BigDecimal.ROUND_HALF_UP); |
| | | |
| | | item.setCompletionStatus(progress); |
| | | }); |
| | | } |
| | | |
| | | ExcelUtil<ProductOrderDto> util = new ExcelUtil<>(ProductOrderDto.class); |
| | | util.exportExcel(response, list, "çäº§è®¢åæ°æ®"); |
| | | } |
| | |
| | | private LocalDate schedulingDate; |
| | | private String schedulingUserName; |
| | | private String customerName; |
| | | //å·¥åº |
| | | @Excel(name = "å·¥åº") |
| | | private String process; |
| | | private BigDecimal workHours; |
| | | private BigDecimal wages; |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.metadata.IPage; |
| | | import com.baomidou.mybatisplus.core.toolkit.ObjectUtils; |
| | | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.common.enums.StockOutQualifiedRecordTypeEnum; |
| | |
| | | |
| | | @Override |
| | | public Boolean delete(Long[] ids) { |
| | | |
| | | //æ¹éæ¥è¯¢productOrder |
| | | List<ProductOrder> productOrders = productOrderMapper.selectList( |
| | | new LambdaQueryWrapper<ProductOrder>() |
| | | .in(ProductOrder::getId, ids) |
| | | ); |
| | | if (!org.springframework.util.CollectionUtils.isEmpty(productOrders)) { |
| | | |
| | | |
| | | // æ¹éæ¥è¯¢processRouteItems |
| | | List<ProductProcessRouteItem> allRouteItems = productProcessRouteItemMapper.selectList( |
| | | new LambdaQueryWrapper<ProductProcessRouteItem>() |
| | | .in(ProductProcessRouteItem::getProductOrderId, ids) |
| | | ); |
| | | |
| | | if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(allRouteItems)) { |
| | | // è·åè¦å é¤çå·¥åºé¡¹ID |
| | | List<Long> routeItemIds = allRouteItems.stream() |
| | | .map(ProductProcessRouteItem::getId) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // æ¥è¯¢å
³èçå·¥åID |
| | | List<ProductWorkOrder> workOrders = productWorkOrderMapper.selectList( |
| | | new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds) |
| | | ); |
| | | if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(workOrders)) { |
| | | List<Long> workOrderIds = workOrders.stream() |
| | | .map(ProductWorkOrder::getId) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // æ¥è¯¢å
³èçç产主表ID |
| | | List<ProductionProductMain> productMains = productionProductMainMapper.selectList( |
| | | new LambdaQueryWrapper<ProductionProductMain>() |
| | | .in(ProductionProductMain::getWorkOrderId, workOrderIds) |
| | | ); |
| | | List<Long> productMainIds = productMains.stream() |
| | | .map(ProductionProductMain::getId) |
| | | .collect(Collectors.toList()); |
| | | |
| | | // å é¤äº§åºè¡¨ãæå
¥è¡¨æ°æ® |
| | | if (!com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(productMainIds)) { |
| | | productionProductOutputMapper.deleteByProductMainIds(productMainIds); |
| | | productionProductInputMapper.deleteByProductMainIds(productMainIds); |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList( |
| | | new LambdaQueryWrapper<QualityInspect>() |
| | | .in(QualityInspect::getProductMainId, productMainIds) |
| | | ); |
| | | //å é¤åºåºè®°å½ |
| | | for (Long productMainId : productMainIds) { |
| | | //å é¤ç产åºåºè®°å½ |
| | | stockUtils.deleteStockOutRecord(productMainId, StockOutQualifiedRecordTypeEnum.PRODUCTION_REPORT_STOCK_OUT.getCode()); |
| | | //å 餿¥åºçå
¥åºè®°å½ |
| | | stockUtils.deleteStockInRecord(productMainId, StockInUnQualifiedRecordTypeEnum.PRODUCTION_SCRAP.getCode()); |
| | | } |
| | | qualityInspects.forEach(qualityInspect -> { |
| | | //inspectState=1 å·²æäº¤ ä¸è½å é¤ |
| | | if (qualityInspect.getInspectState() == 1) { |
| | | throw new RuntimeException("å·²æäº¤çæ£éªåä¸è½å é¤"); |
| | | } |
| | | }); |
| | | qualityInspectMapper.deleteByProductMainIds(productMainIds); |
| | | salesLedgerProductionAccountingMapper.delete(new LambdaQueryWrapper<SalesLedgerProductionAccounting>() |
| | | .in(SalesLedgerProductionAccounting::getProductMainId, productMainIds)); |
| | | } |
| | | |
| | | // å é¤çäº§ä¸»è¡¨æ°æ® |
| | | productionProductMainMapper.deleteByWorkOrderIds(workOrderIds); |
| | | |
| | | // å é¤å·¥åæ°æ® |
| | | productWorkOrderMapper.delete(new LambdaQueryWrapper<ProductWorkOrder>() |
| | | .in(ProductWorkOrder::getProductProcessRouteItemId, routeItemIds)); |
| | | } |
| | | //妿已ç»å¼å§ç产,ä¸è½å é¤ |
| | | //æ¥è¯¢ç产订åä¸çå·¥å |
| | | List<ProductWorkOrder> productWorkOrders = productWorkOrderMapper.selectList(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids)); |
| | | if (productWorkOrders.size()>0){ |
| | | //夿æ¯å¦ææ¥å·¥æ°æ® |
| | | List<ProductionProductMain> productionProductMains = productionProductMainMapper.selectList(Wrappers.<ProductionProductMain>lambdaQuery() |
| | | .in(ProductionProductMain::getWorkOrderId, productWorkOrders.stream().map(ProductWorkOrder::getId).collect(Collectors.toList()))); |
| | | if (productionProductMains.size()>0){ |
| | | throw new RuntimeException("ç产订åå·²ç»å¼å§ç产,ä¸è½å é¤"); |
| | | } |
| | | // æ¹éå é¤processRouteItem |
| | | productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>() |
| | | .in(ProductProcessRouteItem::getProductOrderId, ids)); |
| | | |
| | | // æ¹éå é¤productProcessRoute |
| | | productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>() |
| | | .in(ProductProcessRoute::getProductOrderId, ids)); |
| | | |
| | | // æ¹éå é¤productOrder |
| | | productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>() |
| | | .in(ProductOrder::getId, ids)); |
| | | //å é¤å·¥å |
| | | productWorkOrderMapper.delete(Wrappers.<ProductWorkOrder>lambdaQuery().in(ProductWorkOrder::getProductOrderId, ids)); |
| | | } |
| | | //å é¤å·¥èºè·¯çº¿ |
| | | productProcessRouteItemMapper.delete(new LambdaQueryWrapper<ProductProcessRouteItem>() |
| | | .in(ProductProcessRouteItem::getProductOrderId, ids)); |
| | | productProcessRouteMapper.delete(new LambdaQueryWrapper<ProductProcessRoute>() |
| | | .in(ProductProcessRoute::getProductOrderId, ids)); |
| | | //å é¤ç产订å |
| | | productOrderMapper.delete(new LambdaQueryWrapper<ProductOrder>() |
| | | .in(ProductOrder::getId, ids)); |
| | | return true; |
| | | } |
| | | |
| | |
| | | public Boolean removeProductMain(Long id) { |
| | | //å¤æè¯¥æ¡æ¥å·¥æ¯å¦ä¸åæ ¼å¤ç,妿ä¸åæ ¼å¤çäºï¼åä¸å
许å é¤ |
| | | List<QualityInspect> qualityInspects = qualityInspectMapper.selectList(Wrappers.<QualityInspect>lambdaQuery().eq(QualityInspect::getProductMainId, id)); |
| | | List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(Wrappers.<QualityUnqualified>lambdaQuery() |
| | | .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()))); |
| | | if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState()==1) { |
| | | throw new ServiceException("è¯¥æ¡æ¥å·¥å·²ç»ä¸åæ ¼å¤çäºï¼ä¸å
许å é¤"); |
| | | if (qualityInspects.size() > 0){ |
| | | List<QualityUnqualified> qualityUnqualifieds = qualityUnqualifiedMapper.selectList(Wrappers.<QualityUnqualified>lambdaQuery() |
| | | .in(QualityUnqualified::getInspectId, qualityInspects.stream().map(QualityInspect::getId).collect(Collectors.toList()))); |
| | | if (qualityUnqualifieds.size() > 0 && qualityUnqualifieds.get(0).getInspectState()==1) { |
| | | throw new ServiceException("è¯¥æ¡æ¥å·¥å·²ç»ä¸åæ ¼å¤çäºï¼ä¸å
许å é¤"); |
| | | } |
| | | } |
| | | ProductionProductMain productionProductMain = productionProductMainMapper.selectById(id); |
| | | //该æ¥å·¥å¯¹åºçå·¥èºè·¯çº¿è¯¦æ
|
| | |
| | | /** è·³è½¬è·¯å¾ */
|
| | | private String jumpPath;
|
| | |
|
| | | /** APPè·³è½¬è·¯å¾ */
|
| | | private String appJumpPath;
|
| | |
|
| | | /** å建è
*/
|
| | | @TableField(fill = FieldFill.INSERT)
|
| | | private String createBy;
|
| | |
| | | }
|
| | |
|
| | | @Override
|
| | | public void simpleNoticeByUser(String title, String message, List<Long> consigneeId, String jumpPath) {
|
| | | public void simpleNoticeByUser(String title, String message, List<Long> consigneeId, String jumpPath) {
|
| | | Long userId = SecurityUtils.getLoginUser().getUserId();
|
| | | Long tenantId = SecurityUtils.getLoginUser().getTenantId();
|
| | | List<SysNotice> sysNotices = consigneeId.stream().map(it -> convertSysNotice(title, message, it,tenantId, jumpPath, userId)).collect(Collectors.toList());
|
| | | List<SysNotice> sysNotices = consigneeId.stream()
|
| | | .map(it -> convertSysNotice(title, message, it, tenantId, jumpPath, unipushService.convertWebPathToAppPath(jumpPath), userId))
|
| | | .collect(Collectors.toList());
|
| | | sysNoticeService.saveBatch(sysNotices);
|
| | | try {
|
| | | unipushService.sendClientMessage(sysNotices);
|
| | |
| | | it.getUserId(),
|
| | | it.getTenantId(),
|
| | | jumpPath,
|
| | | unipushService.convertWebPathToAppPath(jumpPath),
|
| | | userId
|
| | | ))
|
| | | .collect(Collectors.toList());
|
| | |
| | | }
|
| | |
|
| | |
|
| | | private SysNotice convertSysNotice(String title,String message,Long consigneeId, Long tenantId,String jumpPath,Long currentUserId) {
|
| | | private SysNotice convertSysNotice(String title,String message,Long consigneeId, Long tenantId,String jumpPath,String appJumpPath,Long currentUserId) {
|
| | | SysNotice sysNotice = new SysNotice();
|
| | | sysNotice.setNoticeType("1");
|
| | | sysNotice.setNoticeTitle(title);//æ é¢
|
| | |
| | | sysNotice.setConsigneeId(consigneeId);
|
| | | sysNotice.setSenderId(currentUserId);
|
| | | sysNotice.setJumpPath(jumpPath);
|
| | | sysNotice.setAppJumpPath(appJumpPath);
|
| | | sysNotice.setTenantId(tenantId);
|
| | | return sysNotice;
|
| | | }
|
| | |
| | | /** |
| | | * å° Web 端åå±å
¨è·¯å¾è½¬æ¢ä¸º App 端ç»ä»¶è·¯ç± |
| | | */ |
| | | private String convertWebPathToAppPath(String webPath) { |
| | | public String convertWebPathToAppPath(String webPath) { |
| | | if (StringUtils.isEmpty(webPath)) { |
| | | return DEFAULT_APP_PAGE; |
| | | } |
| | |
| | | List<QualityUnqualified> qualityUnqualifiedExport(@Param("qualityUnqualified") QualityUnqualified qualityUnqualified); |
| | | |
| | | QualityUnqualified getUnqualified(@Param("id") Integer id); |
| | | |
| | | //æå¨æ°å¢ä¸åæ ¼çæ¶å,æ ¹æ®äº§ååç§°åè§æ ¼åå·æ¥åºå¯¹åºçè§æ ¼åå·id |
| | | Long getModelId(@Param("productName") String productName, @Param("model") String model); |
| | | } |
| | |
| | | break; |
| | | } |
| | | } else { |
| | | //æ¥è¯¢å¯¹åºçè§æ ¼åå·id |
| | | Long modelId = qualityUnqualifiedMapper.getModelId(qualityUnqualified.getProductName(), qualityUnqualified.getModel()); |
| | | switch (qualityUnqualified.getDealResult()) { |
| | | case "æ¥åº": |
| | | //è°ç¨ä¸åæ ¼åºåæ¥å£ å
¥ä¸åæ ¼åº |
| | | stockUtils.addUnStock(Long.valueOf(unqualified.getModel()), unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId()); |
| | | stockUtils.addUnStock(modelId, unqualified.getQuantity(), StockInUnQualifiedRecordTypeEnum.DEFECTIVE_SCRAP.getCode(), unqualified.getId()); |
| | | break; |
| | | case "è®©æ¥æ¾è¡": |
| | | //è°ç¨æäº¤åæ ¼çæ¥å£ |
| | | stockUtils.addStock(Long.valueOf(unqualified.getModel()), unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId()); |
| | | stockUtils.addStock(modelId, unqualified.getQuantity(), StockInQualifiedRecordTypeEnum.DEFECTIVE_PASS.getCode(), unqualified.getId()); |
| | | break; |
| | | default: |
| | | break; |
| | |
| | | import org.apache.ibatis.annotations.Mapper; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * <p> |
| | | * Mapper æ¥å£ |
| | |
| | | @Mapper |
| | | public interface PersonalAttendanceRecordsMapper extends BaseMapper<PersonalAttendanceRecords> { |
| | | IPage<PersonalAttendanceRecordsDto> listPage(Page page, @Param("params") PersonalAttendanceRecordsDto personalAttendanceRecordsDto); |
| | | |
| | | List<StaffOnJob> selectStaffWithoutAttendanceRecordBeforeTime(@Param("date") LocalDate date, @Param("entryDeadline") LocalDateTime entryDeadline); |
| | | |
| | | boolean existsAttendanceRecord(@Param("staffOnJobId") Long staffOnJobId, @Param("date") LocalDate date); |
| | | } |
| | |
| | | @Excel(name = "å·¥æ¶(å°æ¶)", sort = 7) |
| | | private BigDecimal workHours; |
| | | |
| | | @ApiModelProperty("ç¶æ 0æ£å¸¸ 1è¿å° 2æ©é") |
| | | @Excel(name = "ç¶æ", sort = 8,readConverterExp = "0=æ£å¸¸,1=è¿å°,2=æ©é") |
| | | private Byte status; |
| | | @ApiModelProperty("ç¶æ 0æ£å¸¸ 1è¿å° 2æ©é 3è¿å°æ©é 4缺å¤") |
| | | @Excel(name = "ç¶æ", sort = 8,readConverterExp = "0=æ£å¸¸,1=è¿å°,2=æ©é,3=è¿å°ãæ©é,4=缺å¤") |
| | | private Integer status; |
| | | |
| | | @ApiModelProperty("夿³¨") |
| | | @Excel(name = "夿³¨", sort = 9) |
| | |
| | | import com.ruoyi.staff.pojo.StaffOnJob; |
| | | import com.ruoyi.staff.service.PersonalAttendanceRecordsService; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.staff.task.PersonalAttendanceRecordsTask; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private StaffOnJobMapper staffOnJobMapper; |
| | | |
| | | @Autowired |
| | | private PersonalAttendanceRecordsTask personalAttendanceRecordsTask; |
| | | |
| | | @Autowired |
| | | private ISysDictDataService dictDataService; |
| | | |
| | | @Autowired |
| | |
| | | throw new BaseException("å½åç¨æ·æ²¡æå¯¹åºçå工信æ¯"); |
| | | } |
| | | |
| | | // å½åæ¶é´ |
| | | LocalDateTime currentDateTime = LocalDateTime.now(); |
| | | |
| | | // 妿æå¡æ¶é´è¶
è¿èå¤ä¸çæ¶é´ä¸è½æå¡ |
| | | // è·åèå¤ä¸çæ¶é´ç¹ |
| | | String[] timeConfigs = getAttendanceTimeConfig(); |
| | | String timeConfig = timeConfigs[1]; |
| | | String[] timeParts = timeConfig.split(":"); |
| | | int standardHour = Integer.parseInt(timeParts[0]); |
| | | int standardMinute = Integer.parseInt(timeParts[1]); |
| | | // å½åæ¶é´ |
| | | int actualHour = currentDateTime.getHour(); |
| | | int actualMinute = currentDateTime.getMinute(); |
| | | // 夿æå¡æ¶é´æ¯å¦æäºå½åæ¶é´ |
| | | if (actualHour > standardHour || (actualHour == standardHour && actualMinute > standardMinute)) { |
| | | throw new BaseException("æå¡æ¶é´ä¸è½æäºä¸çæ¶é´"); |
| | | } |
| | | |
| | | // æ ¹æ®åå·¥IDåå½åæ¥ææ¥è¯¢æå¡è®°å½ |
| | | QueryWrapper<PersonalAttendanceRecords> attendanceQueryWrapper = new QueryWrapper<>(); |
| | | attendanceQueryWrapper.eq("staff_on_job_id", staffOnJob.getId()) |
| | | .eq("date", currentDate); |
| | | PersonalAttendanceRecords attendanceRecord = personalAttendanceRecordsMapper.selectOne(attendanceQueryWrapper); |
| | | DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm"); |
| | | // æ ¹æ®åå
¸è®¾ç½®çè夿¶é´å¤æè¿å°æ©é |
| | | if (attendanceRecord == null) { |
| | | // ä¸å卿å¡è®°å½ï¼å建æ°è®°å½ |
| | | personalAttendanceRecords.setStaffOnJobId(staffOnJob.getId()); |
| | | personalAttendanceRecords.setDate(currentDate); |
| | | personalAttendanceRecords.setWorkStartAt(LocalDateTime.now()); |
| | | personalAttendanceRecords.setStatus(determineAttendanceStatus(personalAttendanceRecords.getWorkStartAt(), true)); |
| | | personalAttendanceRecords.setWorkStartAt(currentDateTime); |
| | | personalAttendanceRecords.setStatus(determineAttendanceStatus(personalAttendanceRecords, true)); |
| | | personalAttendanceRecords.setRemark(personalAttendanceRecords.getRemark()); |
| | | personalAttendanceRecords.setTenantId(staffOnJob.getTenantId()); |
| | | return personalAttendanceRecordsMapper.insert(personalAttendanceRecords); |
| | | } else { |
| | | if (attendanceRecord.getWorkEndAt() == null) { |
| | | // æ´æ°å·¥ä½ç»ææ¶é´å工使¶é¿ |
| | | attendanceRecord.setWorkEndAt(LocalDateTime.now()); |
| | | attendanceRecord.setWorkEndAt(currentDateTime); |
| | | // 计ç®å·¥ä½æ¶é¿ï¼ç²¾ç¡®å°åéï¼ä¿ç2ä½å°æ°ï¼ |
| | | LocalDateTime startTime = attendanceRecord.getWorkStartAt(); |
| | | LocalDateTime endTime = attendanceRecord.getWorkEndAt(); |
| | |
| | | .divide(BigDecimal.valueOf(60), 2, RoundingMode.HALF_UP); |
| | | attendanceRecord.setWorkHours(workHours); |
| | | // æ´æ°èå¤ç¶æ |
| | | attendanceRecord.setStatus(determineAttendanceStatus(attendanceRecord.getWorkEndAt(), false)); |
| | | attendanceRecord.setStatus(determineAttendanceStatus(attendanceRecord, false)); |
| | | return personalAttendanceRecordsMapper.updateById(attendanceRecord); |
| | | } else { |
| | | throw new BaseException("æ¨å·²ç»æè¿å¡äº,æ éé夿å¡!!!"); |
| | |
| | | } |
| | | } |
| | | |
| | | // è·åè夿¶é´é
ç½® |
| | | private String[] getAttendanceTimeConfig() { |
| | | String[] timeConfigs = new String[2]; |
| | | try { |
| | | String dictType = "sys_work_time"; |
| | | |
| | | // è·åä¸çæ¶é´é
ç½®ï¼é»è®¤ä¸º09:00 |
| | | String startTimeConfig = dictDataService.selectDictLabel(dictType, "start_at"); |
| | | timeConfigs[0] = (startTimeConfig == null || startTimeConfig.trim().isEmpty()) ? "09:00" : startTimeConfig; |
| | | |
| | | // è·åä¸çæ¶é´é
ç½®ï¼é»è®¤ä¸º18:00 |
| | | String endTimeConfig = dictDataService.selectDictLabel(dictType, "end_at"); |
| | | timeConfigs[1] = (endTimeConfig == null || endTimeConfig.trim().isEmpty()) ? "18:00" : endTimeConfig; |
| | | |
| | | return timeConfigs; |
| | | } catch (Exception e) { |
| | | timeConfigs[0] = "09:00"; // é»è®¤ä¸çæ¶é´ |
| | | timeConfigs[1] = "18:00"; // é»è®¤ä¸çæ¶é´ |
| | | return timeConfigs; |
| | | } |
| | | } |
| | | |
| | | // æ ¹æ®å®é
æ¶é´åæ¯å¦ä¸çæ¶é´å¤æèå¤ç¶æ |
| | | // 0 æ£å¸¸ 1 è¿å° 2 æ©é |
| | | private byte determineAttendanceStatus(LocalDateTime actualTime, boolean isStart) { |
| | | // 0 æ£å¸¸ 1 è¿å° 2 æ©é 3 è¿å°æ©é 4 ç¼ºå¤ |
| | | private Integer determineAttendanceStatus(PersonalAttendanceRecords attendanceRecord, boolean isStart) { |
| | | LocalDateTime actualTime = isStart ? attendanceRecord.getWorkStartAt() : attendanceRecord.getWorkEndAt(); |
| | | try { |
| | | // è·åè夿¶é´é
ç½® |
| | | String dictType = "sys_work_time"; // è夿¶é´åå
¸ç±»å |
| | | String timeConfig; |
| | | |
| | | if (isStart) { |
| | | // ä¸çæ¶é´é
ç½®ï¼é»è®¤ä¸º09:00 |
| | | timeConfig = dictDataService.selectDictLabel(dictType, "work_start_time"); |
| | | if (timeConfig == null || timeConfig.trim().isEmpty()) { |
| | | timeConfig = "09:00"; |
| | | } |
| | | } else { |
| | | // ä¸çæ¶é´é
ç½®ï¼é»è®¤ä¸º18:00 |
| | | timeConfig = dictDataService.selectDictLabel(dictType, "work_end_time"); |
| | | if (timeConfig == null || timeConfig.trim().isEmpty()) { |
| | | timeConfig = "18:00"; |
| | | } |
| | | } |
| | | String[] timeConfigs = getAttendanceTimeConfig(); |
| | | String timeConfig = isStart ? timeConfigs[0] : timeConfigs[1]; |
| | | |
| | | // è§£ææ åæ¶é´ |
| | | String[] timeParts = timeConfig.split(":"); |
| | |
| | | } else { |
| | | // ä¸çæå¡ï¼æ©äºæ åæ¶é´ç®æ©é |
| | | if (actualHour < standardHour || (actualHour == standardHour && actualMinute < standardMinute)) { |
| | | if (attendanceRecord.getStatus() == 1) { |
| | | return 3; // è¿å°æ©é |
| | | } |
| | | return 2; // æ©é |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.staff.task; |
| | | |
| | | import com.ruoyi.staff.pojo.PersonalAttendanceRecords; |
| | | import com.ruoyi.staff.pojo.StaffOnJob; |
| | | import com.ruoyi.staff.service.PersonalAttendanceRecordsService; |
| | | import com.ruoyi.staff.mapper.PersonalAttendanceRecordsMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.scheduling.annotation.Scheduled; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * 个人èå¤è®°å½å®æ¶ä»»å¡ |
| | | * |
| | | * @author è¯å¯¼è½¯ä»¶ï¼æ±èï¼æéå
¬å¸ |
| | | * @since 2026-02-09 |
| | | */ |
| | | @Slf4j |
| | | @Component |
| | | public class PersonalAttendanceRecordsTask { |
| | | |
| | | @Autowired |
| | | private PersonalAttendanceRecordsMapper personalAttendanceRecordsMapper; |
| | | |
| | | @Autowired |
| | | private PersonalAttendanceRecordsService personalAttendanceRecordsService; |
| | | |
| | | /** |
| | | * æ¯å¤©åæ¨çææ¨æ¥ç缺å¤è®°å½ |
| | | * 宿¶ä»»å¡ï¼æ¯å¤©åæ¨1ç¹æ§è¡ |
| | | * æé¤ä»å¤©åå
¥èçåå·¥ |
| | | */ |
| | | @Scheduled(cron = "0 0 1 * * ?") |
| | | public void generateAbsenceRecords() { |
| | | try { |
| | | // è·åæ¨æ¥æ¥æ |
| | | LocalDate yesterday = LocalDate.now().minusDays(1); |
| | | |
| | | // ç´æ¥æ¥è¯¢æ¨å¤©æ²¡æèå¤è®°å½çå¨èåå·¥ï¼æé¤ä»å¤©åå
¥èçï¼ |
| | | LocalDateTime todayStart = LocalDate.now().atStartOfDay(); |
| | | List<StaffOnJob> staffWithoutAttendance = personalAttendanceRecordsMapper.selectStaffWithoutAttendanceRecordBeforeTime(yesterday, todayStart); |
| | | |
| | | |
| | | // éåæ²¡æèå¤è®°å½çåå·¥ï¼çæç¼ºå¤è®°å½ |
| | | for (StaffOnJob staff : staffWithoutAttendance) { |
| | | try { |
| | | boolean exists = personalAttendanceRecordsMapper.existsAttendanceRecord(staff.getId(), yesterday); |
| | | if (exists) { |
| | | continue; |
| | | } |
| | | |
| | | PersonalAttendanceRecords absenceRecord = new PersonalAttendanceRecords(); |
| | | absenceRecord.setStaffOnJobId(staff.getId()); |
| | | absenceRecord.setDate(yesterday); |
| | | absenceRecord.setStatus(4); // è®¾ç½®ç¶æä¸ºç¼ºå¤ |
| | | absenceRecord.setRemark("ç³»ç»èªå¨çæ-缺å¤"); |
| | | personalAttendanceRecordsService.save(absenceRecord); |
| | | |
| | | } catch (Exception e) { |
| | | log.error("为åå·¥{}çæç¼ºå¤è®°å½å¤±è´¥ï¼{}", staff.getStaffName(), e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | log.info("æ¨æ¥ç¼ºå¤è®°å½çæå®æ"); |
| | | } catch (Exception e) { |
| | | log.error("çææ¨æ¥ç¼ºå¤è®°å½ä»»å¡æ§è¡å¤±è´¥ï¼{}", e.getMessage(), e); |
| | | } |
| | | } |
| | | } |
| | |
| | | pwo.status as workOrderStatus, |
| | | u.nick_name as nickName, |
| | | p.product_name as productName, |
| | | pp.name as process, |
| | | pm.model as productModelName, |
| | | ppo.quantity, |
| | | ppo.scrap_qty, |
| | |
| | | from |
| | | production_product_main ppm |
| | | left join product_work_order pwo on pwo.id = ppm.work_order_id |
| | | left join product_process_route_item ppri on ppri.id = pwo.product_process_route_item_id |
| | | left join product_process pp on pp.id = ppri.process_id |
| | | left join product_order po on po.id = pwo.product_order_id |
| | | left join production_product_output ppo on ppm.id = ppo.product_main_id |
| | | left join product_model pm on pm.id = ppo.product_model_id |
| | |
| | | 1=1 |
| | | and qu.id = #{id} |
| | | </select> |
| | | <select id="getModelId" resultType="java.lang.Long"> |
| | | select pm.id |
| | | from product_model pm |
| | | left join product p on pm.product_id=p.id |
| | | where pm.model=#{model} |
| | | and p.product_name=#{productName} |
| | | </select> |
| | | </mapper> |
| | |
| | | and personal_attendance_records.date < DATE_ADD(DATE(#{params.date}), INTERVAL 1 DAY) |
| | | </if> |
| | | </select> |
| | | |
| | | <!-- æ¥è¯¢æå®æ¥ææ²¡æèå¤è®°å½çå¨èåå·¥ï¼å¨æå®æ¶é´ä¹åå
¥èçï¼ --> |
| | | <select id="selectStaffWithoutAttendanceRecordBeforeTime" resultType="com.ruoyi.staff.pojo.StaffOnJob"> |
| | | SELECT soj.* |
| | | FROM staff_on_job soj |
| | | WHERE soj.staff_state = 1 |
| | | AND soj.create_time < #{entryDeadline} |
| | | AND NOT EXISTS ( |
| | | SELECT 1 |
| | | FROM personal_attendance_records par |
| | | WHERE par.staff_on_job_id = soj.id |
| | | AND par.date = #{date} |
| | | ) |
| | | </select> |
| | | |
| | | <!-- æ£æ¥æå®å工卿宿¥ææ¯å¦å·²åå¨èå¤è®°å½ --> |
| | | <select id="existsAttendanceRecord" resultType="boolean"> |
| | | SELECT EXISTS ( |
| | | SELECT 1 |
| | | FROM personal_attendance_records |
| | | WHERE staff_on_job_id = #{staffOnJobId} |
| | | AND date = #{date} |
| | | ) |
| | | </select> |
| | | </mapper> |
| | |
| | | sender_id, |
| | | consignee_id, |
| | | jump_path, |
| | | app_jump_path, |
| | | tenant_id |
| | | from sys_notice |
| | | </sql> |
| | |
| | | <if test="senderId != null and senderId != ''">sender_id,</if> |
| | | <if test="consigneeId != null and consigneeId != ''">consignee_id,</if> |
| | | <if test="jumpPath != null and jumpPath != ''">jump_path,</if> |
| | | <if test="appJumpPath != null and appJumpPath != ''">app_jump_path,</if> |
| | | <if test="createBy != null and createBy != ''">create_by,</if> |
| | | <if test="tenantId != null and tenantId != ''">tenant_id,</if> |
| | | create_time |
| | |
| | | <if test="senderId != null and senderId != ''">#{senderId},</if> |
| | | <if test="consigneeId != null and consigneeId != ''">#{consigneeId},</if> |
| | | <if test="jumpPath != null and jumpPath != ''">#{jumpPath},</if> |
| | | <if test="appJumpPath != null and appJumpPath != ''">#{appJumpPath},</if> |
| | | <if test="pathParms != null and pathParms != ''">#{queryParms},</if> |
| | | <if test="createBy != null and createBy != ''">#{createBy},</if> |
| | | <if test="tenantId != null and tenantId != ''">#{tenantId},</if> |