| | |
| | | !gradle/wrapper/gradle-wrapper.jar
|
| | | claude.md
|
| | | target/
|
| | | test/
|
| | | !.mvn/wrapper/maven-wrapper.jar
|
| | |
|
| | | ######################################################################
|
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | alter table stock_in_record |
| | | add warn_num decimal(16, 4) null comment 'é¢è¦æ°é'; |
| | |
| | | |
| | | // è·åç°æè§¦åå¨å¹¶è½¬æ¢ä¸º CronTrigger |
| | | Trigger oldTrigger = scheduler.getTrigger(triggerKey); |
| | | if (oldTrigger == null) { |
| | | JobKey jobKey = new JobKey("timingTask_" + task.getId()); |
| | | JobDetail jobDetail = scheduler.getJobDetail(jobKey); |
| | | if (jobDetail != null) { |
| | | Trigger trigger = buildJobTrigger(task, jobDetail); |
| | | scheduler.scheduleJob(trigger); |
| | | } else { |
| | | scheduleTimingTask(task); |
| | | } |
| | | return; |
| | | } |
| | | if (!(oldTrigger instanceof CronTrigger)) { |
| | | throw new SchedulerException("Existing trigger is not a CronTrigger"); |
| | | } |
| | |
| | | |
| | | // 使ç¨switchç¡®ä¿æ¡ä»¶äºæ¥ |
| | | String frequencyType = task.getFrequencyType().toUpperCase(); // ç»ä¸è½¬ä¸ºå¤§åæ¯è¾ |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | return convertDailyToCron(task.getFrequencyDetail()); |
| | | case "WEEKLY": |
| | | return convertWeeklyToCron(task.getFrequencyDetail()); |
| | | case "MONTHLY": |
| | | return convertMonthlyToCron(task.getFrequencyDetail()); |
| | | case "QUARTERLY": |
| | | return convertQuarterlyToCron(task.getFrequencyDetail()); |
| | | default: |
| | | throw new IllegalArgumentException("䏿¯æçé¢çç±»å: " + task.getFrequencyType()); |
| | | } |
| | | return switch (frequencyType) { |
| | | case "DAILY" -> convertDailyToCron(task.getFrequencyDetail()); |
| | | case "WEEKLY" -> convertWeeklyToCron(task.getFrequencyDetail()); |
| | | case "MONTHLY" -> convertMonthlyToCron(task.getFrequencyDetail()); |
| | | case "QUARTERLY" -> convertQuarterlyToCron(task.getFrequencyDetail()); |
| | | default -> throw new IllegalArgumentException("䏿¯æçé¢çç±»å: " + task.getFrequencyType()); |
| | | }; |
| | | } |
| | | |
| | | // æ¯æ¥ä»»å¡è½¬æ¢ |
| | |
| | | @Schema(description = "ååéé¢") |
| | | private BigDecimal contractAmount; |
| | | |
| | | @Schema(description = "仿¬¾éé¢") |
| | | private BigDecimal paymentAmount; |
| | | @Schema(description = "å·²å
¥åºéé¢") |
| | | private BigDecimal shippedAmount; |
| | | |
| | | @Schema(description = "åºä»éé¢") |
| | | private BigDecimal payableAmount; |
| | | @Schema(description = "æªå
¥åºéé¢") |
| | | private BigDecimal unshippedAmount; |
| | | |
| | | } |
| | |
| | | private String supplierName; |
| | | |
| | | @Schema(description = "ååæ»éé¢") |
| | | //该ä¾åºåéè´åå累计éé¢ |
| | | private BigDecimal contractAmounts; |
| | | |
| | | @Schema(description = "仿¬¾éé¢") |
| | | //该ä¾åºåéè´ä»æ¬¾ç´¯è®¡éé¢ |
| | | private BigDecimal paymentAmount; |
| | | @Schema(description = "å·²å
¥åºéé¢") |
| | | private BigDecimal shippedAmount; |
| | | |
| | | @Schema(description = "åºä»éé¢") |
| | | //该ä¾åºåéè´åºä»ç´¯è®¡éé¢=è´¢å¡(å
¥åº-éè´§) |
| | | private BigDecimal payableAmount; |
| | | @Schema(description = "æªå
¥åºéé¢") |
| | | private BigDecimal unshippedAmount; |
| | | |
| | | } |
| | |
| | | @Schema(description = "ååéé¢") |
| | | private BigDecimal contractAmount; |
| | | |
| | | @Schema(description = "æ¶æ¬¾éé¢") |
| | | private BigDecimal receiptPaymentAmount; |
| | | @Schema(description = "å·²åºåºéé¢") |
| | | private BigDecimal shippedAmount; |
| | | |
| | | @Schema(description = "åºæ¶éé¢") |
| | | private BigDecimal receiptableAmount; |
| | | @Schema(description = "æªåºåºéé¢") |
| | | private BigDecimal unshippedAmount; |
| | | |
| | | } |
| | |
| | | private String customerName; |
| | | |
| | | @Schema(description = "ååæ»éé¢") |
| | | //该客æ·éå®åå累计éé¢ |
| | | private BigDecimal contractAmounts; |
| | | |
| | | @Schema(description = "æ¶æ¬¾éé¢") |
| | | //该客æ·é宿¶æ¬¾ç´¯è®¡éé¢ |
| | | private BigDecimal receiptPaymentAmount; |
| | | @Schema(description = "å·²åºåºéé¢") |
| | | private BigDecimal shippedAmount; |
| | | |
| | | @Schema(description = "åºæ¶éé¢") |
| | | //该客æ·éå®åºæ¶ç´¯è®¡éé¢=è´¢å¡(åºåº-éè´§) |
| | | private BigDecimal receiptableAmount; |
| | | @Schema(description = "æªåºåºéé¢") |
| | | private BigDecimal unshippedAmount; |
| | | |
| | | } |
| | |
| | | import lombok.Data; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | | |
| | | import java.io.Serial; |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | @TableName("stock_in_record") |
| | | @Schema(name = "å
¥åºç®¡ç") |
| | | public class StockInRecord { |
| | | public class StockInRecord implements Serializable { |
| | | |
| | | @Serial |
| | | private static final long serialVersionUID = 1L; |
| | | /** |
| | | * åºå· |
| | |
| | | private String remark; |
| | | |
| | | @Schema(description = "é¢è¦æ°é") |
| | | @TableField(exist = false) |
| | | private BigDecimal warnNum; |
| | | |
| | | @Schema(description = "ç±»å 0åæ ¼å
¥åº 1ä¸åæ ¼å
¥åº") |
| | |
| | | throw new BaseException("该å
¥åºè®°å½ä¸åå¨,æ æ³æ´æ°!!!"); |
| | | } |
| | | |
| | | // è®°å½ä¿®æ¹åç batch_no |
| | | String oldBatchNo = stockInRecord.getBatchNo(); |
| | | String newBatchNo = stockInRecordDto.getBatchNo(); |
| | | |
| | | String[] ignoreProperties = {"id", "inbound_batches"};//æé¤id屿§ |
| | | BeanUtils.copyProperties(stockInRecordDto, stockInRecord, ignoreProperties); |
| | | return stockInRecordMapper.updateById(stockInRecord); |
| | | int result = stockInRecordMapper.updateById(stockInRecord); |
| | | |
| | | // 妿 batch_no åçååï¼éè¦åæ¥æ´æ°å
³è表 |
| | | if (newBatchNo != null && !newBatchNo.equals(oldBatchNo)) { |
| | | updateRelatedBatchNo(stockInRecord, oldBatchNo, newBatchNo); |
| | | } |
| | | |
| | | return result; |
| | | } |
| | | |
| | | /** |
| | | * åæ¥æ´æ°å
³è表ç batch_no |
| | | * @param stockInRecord å
¥åºè®°å½ |
| | | * @param oldBatchNo ä¿®æ¹åçæ¹å· |
| | | * @param newBatchNo ä¿®æ¹åçæ¹å· |
| | | */ |
| | | private void updateRelatedBatchNo(StockInRecord stockInRecord, String oldBatchNo, String newBatchNo) { |
| | | // 1. æ´æ° stock_inventory 表ï¼åæ ¼åºåï¼ |
| | | LambdaQueryWrapper<StockInventory> inventoryEq = new LambdaQueryWrapper<StockInventory>() |
| | | .eq(StockInventory::getProductModelId, stockInRecord.getProductModelId()); |
| | | if (StringUtils.isEmpty(oldBatchNo)) { |
| | | inventoryEq.isNull(StockInventory::getBatchNo); |
| | | } else { |
| | | inventoryEq.eq(StockInventory::getBatchNo, oldBatchNo); |
| | | } |
| | | StockInventory stockInventory = stockInventoryMapper.selectOne(inventoryEq); |
| | | if (stockInventory != null) { |
| | | stockInventory.setBatchNo(newBatchNo); |
| | | stockInventoryMapper.updateById(stockInventory); |
| | | } |
| | | |
| | | // 2. æ´æ° stock_uninventory 表ï¼ä¸åæ ¼åºåï¼ |
| | | LambdaQueryWrapper<StockUninventory> uninventoryEq = new LambdaQueryWrapper<StockUninventory>() |
| | | .eq(StockUninventory::getProductModelId, stockInRecord.getProductModelId()); |
| | | if (StringUtils.isEmpty(oldBatchNo)) { |
| | | uninventoryEq.isNull(StockUninventory::getBatchNo); |
| | | } else { |
| | | uninventoryEq.eq(StockUninventory::getBatchNo, oldBatchNo); |
| | | } |
| | | StockUninventory stockUninventory = stockUninventoryMapper.selectOne(uninventoryEq); |
| | | if (stockUninventory != null) { |
| | | stockUninventory.setBatchNo(newBatchNo); |
| | | stockUninventoryMapper.updateById(stockUninventory); |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | approve_user_names,approve_reason,approve_time,approve_over_time,approve_status, |
| | | approve_delete,tenant_id,approve_type,approve_remark,start_date_time,end_date_time |
| | | </sql> |
| | | |
| | | <select id="listPage" resultType="com.ruoyi.approve.vo.ApproveProcessVo"> |
| | | select * from approve_process where approve_delete = 0 |
| | | <if test="req.approveId != null and req.approveId != ''"> |
| | | and approve_id like concat('%',#{req.approveId},'%') |
| | | </if> |
| | | <if test="req.approveStatus != null or req.approveStatus == 0"> |
| | | <if test="req.approveStatus != null"> |
| | | and approve_status = #{req.approveStatus} |
| | | </if> |
| | | <if test="req.approveType != null "> |
| | | and approve_type = #{req.approveType} |
| | | </if> |
| | | order by id desc |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | <select id="listPage" resultType="com.ruoyi.basic.vo.CustomerVo"> |
| | | select |
| | | c.*, |
| | | u.user_name usage_user_name, |
| | | u.nick_name as usage_user_name, |
| | | ( |
| | | select group_concat(u2.user_name separator ', ') |
| | | select group_concat(u2.nick_name separator ', ') |
| | | from customer_user cu |
| | | left join sys_user u2 on cu.user_id = u2.user_id |
| | | where cu.customer_id = c.id |
| | |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <select id="customewTransactions" resultType="com.ruoyi.sales.vo.CustomerTransactionsVo"> |
| | | select T1.customer_id, |
| | | c.customer_name, |
| | | T1.contractAmounts, |
| | | IFNULL(T2.receiptPaymentAmount, 0) AS receiptPaymentAmount, |
| | | IFNULL(T3.outboundAmount, 0) - IFNULL(T4.returnAmount, 0) AS receiptableAmount |
| | | IFNULL(T3.outboundAmount, 0) AS shippedAmount, |
| | | GREATEST(T1.contractAmounts - IFNULL(T3.outboundAmount, 0), 0) AS unshippedAmount |
| | | from (select customer_id, sum(contract_amount) as contractAmounts from sales_ledger group by customer_id) T1 |
| | | left join (select customer_id, sum(collection_amount) as receiptPaymentAmount from account_sales_collection group by customer_id) T2 on T1.customer_id = T2.customer_id |
| | | left join ( |
| | | SELECT |
| | | sl.customer_id, |
| | |
| | | and slp.type = 1 |
| | | group by sl.customer_id |
| | | ) T3 on T3.customer_id=T1.customer_id |
| | | left join ( |
| | | select |
| | | sl.customer_id, |
| | | sum(rm.refund_amount) as returnAmount |
| | | from return_management rm |
| | | left join shipping_info si on rm.shipping_id = si.id |
| | | left join sales_ledger sl on si.sales_ledger_id = sl.id |
| | | where rm.status=1 |
| | | group by sl.customer_id |
| | | ) T4 on T4.customer_id=T1.customer_id |
| | | left join customer c on T1.customer_id = c.id |
| | | <where> |
| | | <if test="customerName!=null and customerName!=''"> |
| | |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <select id="customewTransactionsDetails" |
| | | resultType="com.ruoyi.sales.vo.CustomerTransactionsDetailsVo"> |
| | | select sl.id salesLedgerId, |
| | | sl.sales_contract_no, |
| | | sl.execution_date, |
| | | sl.contract_amount, |
| | | IFNULL(T1.receiptPaymentAmount, 0) AS receiptPaymentAmount, |
| | | IFNULL(T2.outboundAmount, 0) - IFNULL(T3.returnAmount, 0) AS receiptableAmount |
| | | IFNULL(T2.outboundAmount, 0) AS shippedAmount, |
| | | GREATEST(sl.contract_amount - IFNULL(T2.outboundAmount, 0), 0) AS unshippedAmount |
| | | from sales_ledger sl |
| | | left join ( |
| | | select |
| | | sl.id, |
| | | sum(ascc.collection_amount) as receiptPaymentAmount |
| | | from account_sales_collection ascc |
| | | left join stock_out_record sor on FIND_IN_SET(sor.id, ascc.stock_out_record_ids) > 0 |
| | | left join shipping_info s on sor.record_id = s.id |
| | | LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id |
| | | WHERE sor.record_type='13' |
| | | and sor.approval_status=1 |
| | | group by sl.id |
| | | )T1 on T1.id = sl.id |
| | | left join ( |
| | | SELECT |
| | | sl.id, |
| | |
| | | and slp.type = 1 |
| | | group by sl.id |
| | | )T2 on T2.id = sl.id |
| | | left join ( |
| | | select sl.id, |
| | | sum(rm.refund_amount) as returnAmount |
| | | from return_management rm |
| | | left join shipping_info si on rm.shipping_id = si.id |
| | | left join sales_ledger sl on si.sales_ledger_id = sl.id |
| | | where rm.status=1 |
| | | group by sl.id |
| | | )T3 on T3.id = sl.id |
| | | where sl.customer_id = #{customerId} |
| | | </select> |
| | | </mapper> |
| | |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <select id="supplierTransactions" resultType="com.ruoyi.purchase.vo.SupplierTransactionsVo"> |
| | | select T1.supplier_id, |
| | | SELECT T1.supplier_id, |
| | | sm.supplier_name, |
| | | T1.contractAmounts, |
| | | IFNULL(T2.paymentAmount, 0) AS paymentAmount, |
| | | IFNULL(T3.InboundAmount, 0) - IFNULL(T4.returnAmount, 0) AS payableAmount |
| | | from (select supplier_id, sum(contract_amount) as contractAmounts from purchase_ledger group by supplier_id) T1 |
| | | left join (select supplier_id, sum(payment_amount) as paymentAmount from account_purchase_payment group by supplier_id) T2 on T1.supplier_id = T2.supplier_id |
| | | left join ( |
| | | SELECT |
| | | pl.supplier_id, |
| | | sum(sir.stock_in_num * slp.tax_inclusive_unit_price) AS InboundAmount |
| | | FROM stock_in_record sir |
| | | -- 10 ç±»åæå
³èè´¨æ£è¡¨ |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | -- 卿å
³èéè´ï¼èªå¨éé
7 å 10ï¼ |
| | | LEFT JOIN purchase_ledger pl |
| | | ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id) |
| | | -- 产åå
³èä¸å¨ |
| | | LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id |
| | | -- æ¡ä»¶ |
| | | WHERE sir.approval_status = 1 AND slp.type = 2 |
| | | AND sir.record_type IN ('7','10') |
| | | group by pl.supplier_id |
| | | ) T3 on T3.supplier_id=T1.supplier_id |
| | | left join ( |
| | | select |
| | | supplier_id, |
| | | sum(total_amount) as returnAmount |
| | | from purchase_return_orders pro |
| | | group by supplier_id |
| | | ) T4 on T4.supplier_id=T1.supplier_id |
| | | left join supplier_manage sm on T1.supplier_id = sm.id |
| | | IFNULL(T3.InboundAmount, 0) AS shippedAmount, |
| | | T1.contractAmounts - IFNULL(T3.InboundAmount, 0) AS unshippedAmount |
| | | FROM (SELECT supplier_id, SUM(contract_amount) AS contractAmounts FROM purchase_ledger GROUP BY supplier_id) T1 |
| | | LEFT JOIN ( |
| | | SELECT t.supplier_id, |
| | | SUM(t.inbound_amount) AS InboundAmount |
| | | FROM ( |
| | | SELECT sir.stock_in_num * slp.tax_inclusive_unit_price AS inbound_amount, pl.supplier_id |
| | | FROM stock_in_record sir |
| | | INNER JOIN sales_ledger_product slp ON slp.id = sir.record_id |
| | | INNER JOIN purchase_ledger pl ON pl.id = slp.sales_ledger_id |
| | | WHERE sir.approval_status = 1 AND sir.record_type = 7 AND slp.type = 2 |
| | | UNION ALL |
| | | SELECT sir.stock_in_num * slp.tax_inclusive_unit_price AS inbound_amount, pl.supplier_id |
| | | FROM stock_in_record sir |
| | | INNER JOIN quality_inspect qi ON qi.id = sir.record_id |
| | | INNER JOIN purchase_ledger pl ON pl.id = qi.purchase_ledger_id |
| | | INNER JOIN sales_ledger_product slp ON slp.sales_ledger_id = pl.id AND slp.product_model_id = sir.product_model_id |
| | | WHERE sir.approval_status = 1 AND sir.record_type = 10 AND slp.type = 2 |
| | | ) t |
| | | GROUP BY t.supplier_id |
| | | ) T3 ON T3.supplier_id = T1.supplier_id |
| | | LEFT JOIN supplier_manage sm ON T1.supplier_id = sm.id |
| | | <where> |
| | | <if test="supplierName!=null and supplierName!=''"> |
| | | AND sm.supplier_name LIKE CONCAT('%',#{supplierName},'%') |
| | | </if> |
| | | </where> |
| | | </select> |
| | | |
| | | <select id="supplierTransactionsDetails" |
| | | resultType="com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo"> |
| | | select pl.id purchaseLedgerId, |
| | | SELECT pl.id purchaseLedgerId, |
| | | pl.purchase_contract_number, |
| | | pl.execution_date, |
| | | pl.contract_amount, |
| | | IFNULL(T1.paymentAmount, 0) AS paymentAmount, |
| | | IFNULL(T2.InboundAmount, 0) - IFNULL(T3.returnAmount, 0) AS payableAmount |
| | | from purchase_ledger pl |
| | | left join ( |
| | | select |
| | | pl.id, |
| | | sum(app.payment_amount) as paymentAmount |
| | | from account_purchase_payment app |
| | | left join account_payment_application apa on app.account_payment_application_id = apa.id |
| | | left join stock_in_record sir on FIND_IN_SET(sir.id, apa.stock_in_record_ids) > 0 |
| | | -- 10 ç±»åæå
³èè´¨æ£è¡¨ |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | -- 卿å
³èéè´ï¼èªå¨éé
7 å 10ï¼ |
| | | LEFT JOIN purchase_ledger pl |
| | | ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id) |
| | | WHERE sir.approval_status = 1 |
| | | AND sir.record_type IN ('7','10') |
| | | group by pl.id |
| | | )T1 on T1.id = pl.id |
| | | left join ( |
| | | SELECT |
| | | pl.id, |
| | | sum(sir.stock_in_num * slp.tax_inclusive_unit_price) AS InboundAmount |
| | | FROM stock_in_record sir |
| | | -- 10 ç±»åæå
³èè´¨æ£è¡¨ |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | -- 卿å
³èéè´ï¼èªå¨éé
7 å 10ï¼ |
| | | LEFT JOIN purchase_ledger pl |
| | | ON pl.id = IF(sir.record_type = 7, sir.record_id, qi.purchase_ledger_id) |
| | | -- 产åå
³èä¸å¨ |
| | | LEFT JOIN sales_ledger_product slp ON pl.id = slp.sales_ledger_id |
| | | -- æ¡ä»¶ |
| | | WHERE sir.approval_status = 1 AND slp.type = 2 |
| | | AND sir.record_type IN ('7','10') |
| | | group by pl.id |
| | | )T2 on T2.id = pl.id |
| | | left join ( |
| | | select pl.id, |
| | | sum(pro.total_amount) as returnAmount |
| | | from purchase_return_orders pro |
| | | left join purchase_ledger pl on pro.purchase_ledger_id = pl.id |
| | | group by pl.id |
| | | )T3 on T3.id = pl.id |
| | | where pl.supplier_id = #{supplierId} |
| | | IFNULL(T2.InboundAmount, 0) AS shippedAmount, |
| | | pl.contract_amount - IFNULL(T2.InboundAmount, 0) AS unshippedAmount |
| | | FROM purchase_ledger pl |
| | | LEFT JOIN ( |
| | | SELECT t.sales_ledger_id, |
| | | SUM(t.inbound_amount) AS InboundAmount |
| | | FROM ( |
| | | SELECT sir.stock_in_num * slp.tax_inclusive_unit_price AS inbound_amount, slp.sales_ledger_id |
| | | FROM stock_in_record sir |
| | | INNER JOIN sales_ledger_product slp ON slp.id = sir.record_id |
| | | WHERE sir.approval_status = 1 AND sir.record_type = 7 AND slp.type = 2 |
| | | UNION ALL |
| | | SELECT sir.stock_in_num * slp.tax_inclusive_unit_price AS inbound_amount, slp.sales_ledger_id |
| | | FROM stock_in_record sir |
| | | INNER JOIN quality_inspect qi ON qi.id = sir.record_id |
| | | INNER JOIN purchase_ledger pl2 ON pl2.id = qi.purchase_ledger_id |
| | | INNER JOIN sales_ledger_product slp ON slp.sales_ledger_id = pl2.id AND slp.product_model_id = sir.product_model_id |
| | | WHERE sir.approval_status = 1 AND sir.record_type = 10 AND slp.type = 2 |
| | | ) t |
| | | GROUP BY t.sales_ledger_id |
| | | ) T2 ON T2.sales_ledger_id = pl.id |
| | | WHERE pl.supplier_id = #{supplierId} |
| | | </select> |
| | | |
| | | </mapper> |
| | |
| | | left join device_ledger dl on dm.device_ledger_id = dl.id |
| | | left join sys_user su on dm.create_user = su.user_id |
| | | <where> |
| | | 1 = 1 |
| | | <if test="deviceMaintenanceDto.deviceName != null"> |
| | | and dl.device_name like concat('%',#{deviceMaintenanceDto.deviceName},'%') |
| | | <if test="deviceMaintenanceDto.deviceName != null and deviceMaintenanceDto.deviceName != ''"> |
| | | and dl.device_name like concat('%', #{deviceMaintenanceDto.deviceName}, '%') |
| | | </if> |
| | | <if test="deviceMaintenanceDto.deviceModel != null"> |
| | | and dl.device_model like concat('%',#{deviceMaintenanceDto.deviceModel},'%') |
| | | <if test="deviceMaintenanceDto.deviceModel != null and deviceMaintenanceDto.deviceModel != ''"> |
| | | and dl.device_model like concat('%', #{deviceMaintenanceDto.deviceModel}, '%') |
| | | </if> |
| | | <if test="deviceMaintenanceDto.status != null"> |
| | | and dm.status = #{deviceMaintenanceDto.status} |
| | | </if> |
| | | <if test="deviceMaintenanceDto.maintenanceActuallyName != null"> |
| | | and dm.maintenance_actually_name like concat('%',#{deviceMaintenanceDto.maintenanceActuallyName},'%') |
| | | <if test="deviceMaintenanceDto.maintenanceActuallyName != null and deviceMaintenanceDto.maintenanceActuallyName != ''"> |
| | | and dm.maintenance_actually_name like concat('%', #{deviceMaintenanceDto.maintenanceActuallyName}, '%') |
| | | </if> |
| | | <if test="deviceMaintenanceDto.maintenancePlanTime != null"> |
| | | and dm.maintenance_plan_time like concat('%',#{deviceMaintenanceDto.maintenancePlanTime},'%') |
| | | and dm.maintenance_plan_time = #{deviceMaintenanceDto.maintenancePlanTime} |
| | | </if> |
| | | <if test="deviceMaintenanceDto.maintenanceActuallyTime != null"> |
| | | and dm.maintenance_actually_time like concat('%',#{deviceMaintenanceDto.maintenanceActuallyTime},'%') |
| | | </if> |
| | | <if test="deviceMaintenanceDto.maintenanceActuallyTime != null"> |
| | | and dm.maintenance_actually_time >= str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d') |
| | | and dm.maintenance_actually_time < date_add(str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d'), interval 1 day) |
| | | and dm.maintenance_actually_time >= str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, |
| | | '%Y-%m-%d') |
| | | and dm.maintenance_actually_time < |
| | | date_add(str_to_date(#{deviceMaintenanceDto.maintenanceActuallyTime}, '%Y-%m-%d'), interval 1 day) |
| | | </if> |
| | | </where> |
| | | order by |
| | | <!-- å¾
ä¿å
»(0)ä¼å
æå¨ä¸é¢ï¼å·²å®ç»(1)å¨ä¸é¢ --> |
| | | dm.status asc, |
| | | case |
| | | <!-- å½ç¶ææ¯ 0ï¼å¾
ä¿å
»ï¼æ¶ï¼æè®¡åæ¶é´ååºï¼å³æ¶é´æè¿çåå卿ä¸é¢ --> |
| | | when dm.status = 0 then dm.maintenance_plan_time |
| | | end asc, |
| | | case |
| | | <!-- å½ç¶ææ¯ 1ï¼å·²å®ç»ï¼æ¶ï¼æå®é
ä¿å
»æ¶é´éåºï¼æè¿åä¿å
»å®çååå¨å·²å®ç»éææå --> |
| | | when dm.status = 1 then dm.maintenance_actually_time |
| | | end desc |
| | | </select> |
| | | |
| | | <select id="detailById" resultType="com.ruoyi.device.vo.DeviceMaintenanceVo"> |
| | | select dm.id, |
| | | dm.device_ledger_id, |
| | |
| | | <if test="endDateTime != null"> |
| | | and ppo.create_time <= #{endDateTime} |
| | | </if> |
| | | <if test="userId != null"> |
| | | and ppm.create_user = #{userId} |
| | | </if> |
| | | <!-- <if test="userId != null">--> |
| | | <!-- and ppm.create_user = #{userId}--> |
| | | <!-- </if>--> |
| | | <if test="processIds != null and processIds.size() > 0"> |
| | | and poro.technology_operation_id in |
| | | <foreach collection="processIds" item="id" open="(" separator="," close=")"> |
| | |
| | | and p.id in (select id from product_tree) |
| | | </if> |
| | | </where> |
| | | order by sir.id desc |
| | | order by sir.create_time desc |
| | | </select> |
| | | <select id="listStockInRecordExportData" resultType="com.ruoyi.stock.execl.StockInRecordExportData"> |
| | | SELECT |
| | |
| | | and sir.record_type = #{params.recordType} |
| | | </if> |
| | | </where> |
| | | order by sir.id desc |
| | | order by sir.create_time desc |
| | | </select> |
| | | <select id="listPageAccountPurchase" resultType="com.ruoyi.account.bean.vo.purchase.PurchaseInboundVo"> |
| | | SELECT |
| | |
| | | and p.id in (select id from product_tree) |
| | | </if> |
| | | </where> |
| | | order by sor.id desc |
| | | order by sor.create_time desc |
| | | </select> |
| | | <select id="listStockOutRecordExportData" resultType="com.ruoyi.stock.execl.StockOutRecordExportData"> |
| | | SELECT |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.approve.service.impl; |
| | | |
| | | import com.ruoyi.approve.mapper.ApproveNodeMapper; |
| | | import com.ruoyi.approve.mapper.ApproveProcessMapper; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import java.sql.Timestamp; |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | @SpringBootTest |
| | | public class ApproveProcessIdModifyTest { |
| | | |
| | | @Autowired |
| | | private JdbcTemplate jdbcTemplate; |
| | | |
| | | @Autowired |
| | | private ApproveProcessMapper approveProcessMapper; |
| | | |
| | | @Autowired |
| | | private ApproveNodeMapper approveNodeMapper; |
| | | |
| | | /** |
| | | * ä¿®æ¹å®¡æ¹æµç¨ç¼å· |
| | | */ |
| | | @Test |
| | | void testModifyApproveId() { |
| | | Map<String, String> modifyMap = new LinkedHashMap<>(); |
| | | modifyMap.put("20260523020", "2026-05-09"); |
| | | modifyMap.put("20260523019", "2026-04-29"); |
| | | modifyMap.put("20260523018", "2026-04-16"); |
| | | modifyMap.put("20260523009", "2026-05-07"); |
| | | modifyMap.put("20260523008", "2026-04-11"); |
| | | modifyMap.put("20260523007", "2026-04-10"); |
| | | modifyMap.put("20260523006", "2026-04-07"); |
| | | modifyMap.put("20260523003", "2026-04-07"); |
| | | |
| | | for (Map.Entry<String, String> entry : modifyMap.entrySet()) { |
| | | processOne(entry.getKey(), entry.getValue()); |
| | | } |
| | | System.out.println("å
¨é¨å®æï¼"); |
| | | } |
| | | |
| | | private void processOne(String oldApproveId, String targetDateStr) { |
| | | LocalDate targetDate = LocalDate.parse(targetDateStr); |
| | | String datePrefix = targetDate.format(DateTimeFormatter.ofPattern("yyyyMMdd")); |
| | | |
| | | String maxId = jdbcTemplate.queryForObject( |
| | | "SELECT MAX(approve_id) FROM approve_process WHERE approve_id LIKE ?", |
| | | String.class, datePrefix + "%"); |
| | | |
| | | long nextSeq = 1; |
| | | if (maxId != null && maxId.length() >= 11) { |
| | | nextSeq = Long.parseLong(maxId.substring(8)) + 1; |
| | | } |
| | | String newApproveId = datePrefix + String.format("%03d", nextSeq); |
| | | |
| | | System.out.println("æ§æ¹å·: " + oldApproveId + " -> æ°æ¹å·: " + newApproveId); |
| | | |
| | | List<Map<String, Object>> processList = jdbcTemplate.queryForList( |
| | | "SELECT * FROM approve_process WHERE approve_id = ?", oldApproveId); |
| | | |
| | | if (processList.isEmpty()) { |
| | | System.out.println(" â æªæ¾å°è®°å½ï¼è·³è¿"); |
| | | return; |
| | | } |
| | | |
| | | Map<String, Object> process = processList.get(0); |
| | | |
| | | Timestamp newApproveTime = replaceDate(process.get("approve_time"), targetDate); |
| | | Timestamp newApproveOverTime = replaceDate(process.get("approve_over_time"), targetDate); |
| | | Timestamp newCreateTime = replaceDate(process.get("create_time"), targetDate); |
| | | |
| | | jdbcTemplate.update( |
| | | "UPDATE approve_process SET approve_id = ?, approve_time = ?, approve_over_time = ?, create_time = ? WHERE approve_id = ?", |
| | | newApproveId, newApproveTime, newApproveOverTime, newCreateTime, oldApproveId); |
| | | System.out.println(" â approve_process å·²æ´æ°"); |
| | | |
| | | List<Map<String, Object>> nodeList = jdbcTemplate.queryForList( |
| | | "SELECT * FROM approve_node WHERE approve_process_id = ?", oldApproveId); |
| | | |
| | | if (!nodeList.isEmpty()) { |
| | | Map<String, Object> node = nodeList.get(0); |
| | | |
| | | Timestamp newNodeTime = replaceDate(node.get("approve_node_time"), targetDate); |
| | | Timestamp newNodeCreateTime = replaceDate(node.get("create_time"), targetDate); |
| | | Timestamp newNodeUpdateTime = replaceDate(node.get("update_time"), targetDate); |
| | | |
| | | jdbcTemplate.update( |
| | | "UPDATE approve_node SET approve_process_id = ?, approve_node_time = ?, create_time = ?, update_time = ? WHERE approve_process_id = ?", |
| | | newApproveId, newNodeTime, newNodeCreateTime, newNodeUpdateTime, oldApproveId); |
| | | System.out.println(" â approve_node å·²æ´æ° (" + nodeList.size() + " æ¡)"); |
| | | } else { |
| | | System.out.println(" - approve_node æ è®°å½"); |
| | | } |
| | | } |
| | | |
| | | private static Timestamp replaceDate(Object dateObj, LocalDate targetDate) { |
| | | if (dateObj == null) return null; |
| | | LocalDateTime ldt; |
| | | if (dateObj instanceof Timestamp ts) { |
| | | ldt = ts.toLocalDateTime(); |
| | | } else if (dateObj instanceof LocalDateTime dt) { |
| | | ldt = dt; |
| | | } else { |
| | | return null; |
| | | } |
| | | return Timestamp.valueOf(LocalDateTime.of(targetDate, ldt.toLocalTime())); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.device.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.device.mapper.MaintenanceTaskMapper; |
| | | import com.ruoyi.device.pojo.DeviceMaintenance; |
| | | import com.ruoyi.device.pojo.MaintenanceTask; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.time.YearMonth; |
| | | import java.time.LocalDate; |
| | | import java.time.DayOfWeek; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 设å¤ä¿å
»ä»»å¡æµè¯ç±» |
| | | * |
| | | * æ¥è¯¢æ°æ®åºä¸çä¿å
»ä»»å¡ï¼æ ¹æ®ç»è®°æ¥æã颿¬¡ãå¼å§æ¥æä¸æ¶é´æ¥çæä¿å
»è®°å½ |
| | | * ä»ç»è®°æ¥æå°ä»å¤©ï¼æé¢æ¬¡çæææç¬¦åçè®°å½ |
| | | */ |
| | | @SpringBootTest |
| | | public class MaintenanceTaskJobTest { |
| | | |
| | | @Autowired |
| | | private MaintenanceTaskMapper maintenanceTaskMapper; |
| | | |
| | | @Autowired |
| | | private DeviceMaintenanceServiceImpl deviceMaintenanceService; |
| | | |
| | | @Autowired |
| | | private JdbcTemplate jdbcTemplate; |
| | | |
| | | /** |
| | | * æµè¯ï¼ææ¥æåæ£çæä¿å
»è®°å½ |
| | | * ä»ç»è®°æ¥æå°ä»å¤©ï¼ææ¥æé¡ºåºï¼æ¯å¤©çææè®¾å¤ä¿å
»è®°å½ä¸èµ·çæ |
| | | */ |
| | | @Test |
| | | void testGenerateOneByOne() { |
| | | // æ¥è¯¢ææå¯ç¨çä¿å
»ä»»å¡ |
| | | List<MaintenanceTask> tasks = maintenanceTaskMapper.selectList( |
| | | new LambdaQueryWrapper<MaintenanceTask>() |
| | | .eq(MaintenanceTask::getIsActive, 1) |
| | | .eq(MaintenanceTask::getDeleted, 0) |
| | | ); |
| | | |
| | | if (tasks.isEmpty()) { |
| | | System.out.println("=== æ²¡ææ¾å°ä¿å
»ä»»å¡ ==="); |
| | | return; |
| | | } |
| | | |
| | | // æ¾åºææ©åææçç»è®°æ¥æ |
| | | LocalDate earliestDate = tasks.stream() |
| | | .map(MaintenanceTask::getRegistrationDate) |
| | | .filter(Objects::nonNull) |
| | | .min(LocalDate::compareTo) |
| | | .orElse(LocalDate.now()); |
| | | LocalDate latestDate = LocalDate.now(); |
| | | |
| | | System.out.println("=== ç»è®°æ¥æèå´: " + earliestDate + " è³ " + latestDate + " ==="); |
| | | System.out.println("=== å
±æ¾å° " + tasks.size() + " 个ä¿å
»ä»»å¡ ===\n"); |
| | | |
| | | // ææ¥æé¡ºåºçæï¼æ¯å¤©çæä¸æ¬¡ |
| | | LocalDate currentDate = earliestDate; |
| | | int totalRecords = 0; |
| | | |
| | | while (!currentDate.isAfter(latestDate)) { |
| | | final LocalDate date = currentDate; |
| | | final List<DeviceMaintenance> recordsToSave = new ArrayList<>(); |
| | | |
| | | // æ¾åºå½å¤©éè¦ä¿å
»çææä»»å¡ |
| | | for (MaintenanceTask task : tasks) { |
| | | LocalDate startDate = task.getRegistrationDate() != null ? task.getRegistrationDate() : LocalDate.now(); |
| | | if (date.isBefore(startDate)) { |
| | | continue; // è·³è¿ç»è®°æ¥æä¹åçæ¥æ |
| | | } |
| | | |
| | | // æ£æ¥è¯¥ä»»å¡ç颿¬¡æ¯å¦å¹é
å½å¤© |
| | | if (isExecutionDate(task.getFrequencyType(), task.getFrequencyDetail(), startDate, date)) { |
| | | LocalTime time = getExecutionTime(task.getFrequencyDetail()); |
| | | LocalDateTime executionDateTime = LocalDateTime.of(date, time); |
| | | |
| | | DeviceMaintenance record = createMaintenanceRecord(task, executionDateTime); |
| | | recordsToSave.add(record); |
| | | } |
| | | } |
| | | |
| | | // 妿å½å¤©æè®°å½ï¼æ¹éä¿å |
| | | if (!recordsToSave.isEmpty()) { |
| | | for (DeviceMaintenance record : recordsToSave) { |
| | | try { |
| | | deviceMaintenanceService.save(record); |
| | | System.out.println(" â è®¡åæ¥æ: " + date + " | 设å¤: " + record.getDeviceName() |
| | | + " | è®°å½ID: " + record.getId()); |
| | | } catch (Exception e) { |
| | | System.out.println(" â è®¡åæ¥æ: " + date + " | 设å¤: " + record.getDeviceName() |
| | | + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | totalRecords += recordsToSave.size(); |
| | | System.out.println(" === æ¥æ " + date + " å
±çæ " + recordsToSave.size() + " æ¡è®°å½ ===\n"); |
| | | } |
| | | |
| | | currentDate = currentDate.plusDays(1); |
| | | } |
| | | |
| | | System.out.println("=== æ§è¡å®æ: å
±çæ " + totalRecords + " æ¡è®°å½ ==="); |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥æå®æ¥ææ¯å¦ç¬¦åä»»å¡çæ§è¡é¢æ¬¡ |
| | | */ |
| | | private boolean isExecutionDate(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate checkDate) { |
| | | if (checkDate.isBefore(startDate)) { |
| | | return false; |
| | | } |
| | | |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | return true; // æ¯å¤©é½éè¦æ§è¡ |
| | | case "WEEKLY": |
| | | return isWeeklyMatch(frequencyDetail, checkDate); |
| | | case "MONTHLY": |
| | | return isMonthlyMatch(frequencyDetail, checkDate); |
| | | case "QUARTERLY": |
| | | return isQuarterlyMatch(frequencyDetail, checkDate); |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private boolean isWeeklyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | DayOfWeek targetDay = parseDayOfWeek(dayOfWeekStr); |
| | | return date.getDayOfWeek() == targetDay; |
| | | } |
| | | |
| | | private boolean isMonthlyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | int targetDay = Integer.parseInt(parts[0]); |
| | | return date.getDayOfMonth() == targetDay; |
| | | } |
| | | |
| | | private boolean isQuarterlyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); // å£åº¦ä¸ç第å 个æ |
| | | int targetDay = Integer.parseInt(parts[1]); |
| | | |
| | | int currentMonth = date.getMonthValue(); |
| | | int monthInQuarter = (currentMonth - 1) % 3 + 1; |
| | | |
| | | return monthInQuarter == quarterMonth && date.getDayOfMonth() == targetDay; |
| | | } |
| | | |
| | | private LocalTime getExecutionTime(String frequencyDetail) { |
| | | String[] parts = frequencyDetail.split(","); |
| | | if (parts.length >= 2 && (parts.length == 2 || parts.length == 3)) { |
| | | return LocalTime.parse(parts[parts.length - 1]); |
| | | } |
| | | return LocalTime.of(9, 0); // é»è®¤æ¶é´ |
| | | } |
| | | |
| | | /** |
| | | * æµè¯ï¼æ ¹æ®ææä¿å
»ä»»å¡çæè®¾å¤ä¿å
»è®°å½ |
| | | * æé¡ºåºå¤çæ¯ä¸ªä»»å¡ï¼ä»ç»è®°æ¥æå°ä»å¤©ï¼æé¢æ¬¡ä¾æ¬¡çæææç¬¦åçè®°å½ |
| | | */ |
| | | @Test |
| | | void testGenerateMaintenanceRecordForAllTasks() { |
| | | // æ¥è¯¢ææå¯ç¨çä¿å
»ä»»å¡ï¼æIDæåº |
| | | List<MaintenanceTask> tasks = maintenanceTaskMapper.selectList( |
| | | new LambdaQueryWrapper<MaintenanceTask>() |
| | | .eq(MaintenanceTask::getIsActive, 1) |
| | | .eq(MaintenanceTask::getDeleted, 0) |
| | | .orderByAsc(MaintenanceTask::getId) |
| | | ); |
| | | |
| | | System.out.println("=== å
±æ¾å° " + tasks.size() + " 个ä¿å
»ä»»å¡ ===\n"); |
| | | |
| | | int totalRecords = 0; |
| | | for (MaintenanceTask task : tasks) { |
| | | try { |
| | | // æé¡ºåºçæè¯¥ä»»å¡ææç¬¦å颿¬¡çè®°å½ |
| | | int recordCount = generateRecordsForTaskSequentially(task); |
| | | totalRecords += recordCount; |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() |
| | | + " | ç»è®°æ¥æ: " + task.getRegistrationDate() |
| | | + " | çæè®°å½æ°: " + recordCount); |
| | | } catch (Exception e) { |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | System.out.println("\n=== æ§è¡å®æ: å
±çæ " + totalRecords + " æ¡è®°å½ ==="); |
| | | } |
| | | |
| | | /** |
| | | * 为åä¸ªä»»å¡æé¡ºåºçæææç¬¦å颿¬¡çè®°å½ |
| | | */ |
| | | private int generateRecordsForTaskSequentially(MaintenanceTask task) { |
| | | LocalDate startDate = task.getRegistrationDate(); |
| | | if (startDate == null) { |
| | | startDate = LocalDate.now(); |
| | | } |
| | | LocalDate endDate = LocalDate.now(); |
| | | |
| | | // æ ¹æ®é¢æ¬¡è·åææéè¦æ§è¡çæ¥æ |
| | | List<LocalDateTime> executionDates = getExecutionDates(task.getFrequencyType(), task.getFrequencyDetail(), startDate, endDate); |
| | | |
| | | if (executionDates.isEmpty()) { |
| | | return 0; |
| | | } |
| | | |
| | | int count = 0; |
| | | for (LocalDateTime executionDate : executionDates) { |
| | | try { |
| | | // æé¡ºåºçæä¿å
»è®°å½ |
| | | DeviceMaintenance record = createMaintenanceRecord(task, executionDate); |
| | | deviceMaintenanceService.save(record); |
| | | count++; |
| | | } catch (Exception e) { |
| | | System.out.println(" â æ¥æ: " + executionDate + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | if (count > 0) { |
| | | // first_execution = ç¬¬ä¸æ¡è®°å½çæ¥æ = last_execution_time |
| | | LocalDateTime firstExecution = executionDates.get(0); |
| | | // next_execution = æå䏿¡è®°å½çä¸ä¸æ¬¡æ§è¡æ¥æ |
| | | LocalDateTime lastExecution = executionDates.get(executionDates.size() - 1); |
| | | LocalDateTime nextExecution = calculateNextExecutionTime(task.getFrequencyType(), task.getFrequencyDetail(), lastExecution); |
| | | updateTaskExecutionTime(task.getId(), firstExecution, nextExecution); |
| | | } |
| | | |
| | | return count; |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®æ¥æèå´å
ææç¬¦å颿¬¡çæ§è¡æ¶é´ |
| | | */ |
| | | private List<LocalDateTime> getExecutionDates(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate endDate) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | dates.addAll(getDailyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "WEEKLY": |
| | | dates.addAll(getWeeklyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "MONTHLY": |
| | | dates.addAll(getMonthlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "QUARTERLY": |
| | | dates.addAll(getQuarterlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | } |
| | | |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getDailyDates(LocalDate startDate, LocalDate endDate, String timeStr) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | LocalTime time = LocalTime.parse(timeStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getMonthlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | // ä»ç»è®°æ¥ææå¨ææ¾ç¬¬ä¸ä¸ªç¬¦åæ¡ä»¶çæ¥æ |
| | | int actualDay = Math.min(dayOfMonth, startDate.lengthOfMonth()); |
| | | LocalDate current = startDate.withDayOfMonth(actualDay); |
| | | |
| | | // 妿è¿ä¸ªæ¥æå¨ç»è®°æ¥æä¹åï¼å¾åæ¨ä¸ä¸ªæ |
| | | if (current.isBefore(startDate)) { |
| | | current = current.plusMonths(1); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(1); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getWeeklyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | java.time.DayOfWeek targetDay = parseDayOfWeek(dayOfWeekStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | if (current.getDayOfWeek() == targetDay) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | } |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getQuarterlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonth = startDate.getMonthValue(); |
| | | int targetMonth = ((currentMonth - 1) / 3) * 3 + quarterMonth; |
| | | int yearAdjust = 0; |
| | | |
| | | if (targetMonth > 12) { |
| | | targetMonth -= 12; |
| | | yearAdjust = 1; |
| | | } |
| | | |
| | | int actualDay = Math.min(dayOfMonth, YearMonth.of(startDate.getYear() + yearAdjust, targetMonth).lengthOfMonth()); |
| | | LocalDate current = startDate.withYear(startDate.getYear() + yearAdjust) |
| | | .withMonth(targetMonth) |
| | | .withDayOfMonth(actualDay); |
| | | |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(3); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private java.time.DayOfWeek parseDayOfWeek(String dayOfWeekStr) { |
| | | switch (dayOfWeekStr.toUpperCase()) { |
| | | case "MON": return java.time.DayOfWeek.MONDAY; |
| | | case "TUE": return java.time.DayOfWeek.TUESDAY; |
| | | case "WED": return java.time.DayOfWeek.WEDNESDAY; |
| | | case "THU": return java.time.DayOfWeek.THURSDAY; |
| | | case "FRI": return java.time.DayOfWeek.FRIDAY; |
| | | case "SAT": return java.time.DayOfWeek.SATURDAY; |
| | | case "SUN": return java.time.DayOfWeek.SUNDAY; |
| | | default: throw new IllegalArgumentException("æ æçææå : " + dayOfWeekStr); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å建ä¿å
»è®°å½ |
| | | */ |
| | | private DeviceMaintenance createMaintenanceRecord(MaintenanceTask task, LocalDateTime executionDate) { |
| | | DeviceMaintenance record = new DeviceMaintenance(); |
| | | record.setDeviceName(task.getTaskName()); |
| | | record.setMaintenanceTaskId(task.getId()); |
| | | record.setDeviceLedgerId(task.getTaskId()); |
| | | record.setMaintenancePlanTime(executionDate); |
| | | record.setMaintenanceActuallyName(task.getMaintenancePerson()); |
| | | record.setFrequencyType(task.getFrequencyType()); |
| | | record.setFrequencyDetail(task.getFrequencyDetail()); |
| | | record.setTenantId(task.getTenantId()); |
| | | record.setStatus(0); // å¾
ä¿å
» |
| | | record.setDeviceModel(task.getDeviceModel()); |
| | | record.setMachineryCategory(task.getMachineryCategory()); |
| | | record.setCreateUser(Integer.parseInt(task.getRegistrantId().toString())); |
| | | record.setUpdateTime(executionDate); |
| | | record.setCreateTime(executionDate); |
| | | record.setUpdateUser(Integer.parseInt(task.getRegistrantId().toString())); |
| | | return record; |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°ä»»å¡çæ§è¡æ¶é´ |
| | | */ |
| | | private void updateTaskExecutionTime(Long taskId, LocalDateTime lastExecutionTime, LocalDateTime nextExecutionTime) { |
| | | String sql = "UPDATE maintenance_task SET last_execution_time = ?, next_execution_time = ? WHERE id = ?"; |
| | | jdbcTemplate.update(sql, lastExecutionTime, nextExecutionTime, taskId); |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸æ¬¡æ§è¡æ¶é´ |
| | | */ |
| | | private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) { |
| | | return switch (frequencyType) { |
| | | case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime); |
| | | case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime); |
| | | case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime); |
| | | case "QUARTERLY" -> calculateQuarterlyNextTime(frequencyDetail, currentTime); |
| | | default -> throw new IllegalArgumentException("䏿¯æç颿¬¡ç±»å: " + frequencyType); |
| | | }; |
| | | } |
| | | |
| | | private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) { |
| | | LocalTime executionTime = LocalTime.parse(timeStr); |
| | | LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime); |
| | | return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1); |
| | | } |
| | | |
| | | private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | return current.plusMonths(1) |
| | | .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth())) |
| | | .with(time); |
| | | } |
| | | |
| | | private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) { |
| | | return current.plusWeeks(1); |
| | | } |
| | | |
| | | private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1; |
| | | |
| | | YearMonth targetYearMonth; |
| | | if (currentMonthInQuarter < quarterMonth) { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter); |
| | | } else { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth); |
| | | } |
| | | |
| | | int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth()); |
| | | return LocalDateTime.of(targetYearMonth.getYear(), targetYearMonth.getMonthValue(), adjustedDay, time.getHour(), time.getMinute()); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.inspectiontask.service.impl; |
| | | |
| | | import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; |
| | | import com.ruoyi.inspectiontask.pojo.InspectionTask; |
| | | import com.ruoyi.inspectiontask.pojo.TimingTask; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import java.time.DayOfWeek; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.time.YearMonth; |
| | | import java.time.LocalDate; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Set; |
| | | |
| | | /** |
| | | * 设å¤å·¡æ£å®æ¶ä»»å¡æµè¯ç±» |
| | | * |
| | | * æ¥è¯¢æ°æ®åºä¸çå·¡æ£ä»»å¡ï¼æ ¹æ®ç»è®°æ¥æã颿¬¡ãå¼å§æ¥æä¸æ¶é´æ¥çæå·¡æ£è®°å½ |
| | | * å¹¶æ´æ° timing_task 表çæåæ§è¡æ¶é´å䏿¬¡æ§è¡æ¶é´ |
| | | */ |
| | | @SpringBootTest |
| | | public class TimingTaskJobTest { |
| | | |
| | | @Autowired |
| | | private InspectionTaskMapper inspectionTaskMapper; |
| | | |
| | | @Autowired |
| | | private JdbcTemplate jdbcTemplate; |
| | | |
| | | /** |
| | | * æµè¯ï¼æ ¹æ®ææå·¡æ£ä»»å¡çæå·¡æ£è®°å½ |
| | | * ä»ç»è®°æ¥æå°ä»å¤©ï¼æé¢æ¬¡æ¯å¨çæä¸æ¡è®°å½ |
| | | */ |
| | | @Test |
| | | void testGenerateInspectionRecordForAllTasks() { |
| | | // æ¥è¯¢ææå¯ç¨çå·¡æ£ä»»å¡ |
| | | String sql = "SELECT * FROM timing_task WHERE is_enabled = 1 AND deleted = 0"; |
| | | List<TimingTask> tasks = jdbcTemplate.query(sql, |
| | | (rs, rowNum) -> { |
| | | TimingTask task = new TimingTask(); |
| | | task.setId(rs.getLong("id")); |
| | | task.setTaskName(rs.getString("task_name")); |
| | | task.setInspectionProject(rs.getString("inspection_project")); |
| | | task.setTaskId(rs.getInt("task_id")); |
| | | task.setInspectorIds(rs.getString("inspector_ids")); |
| | | task.setInspectionLocation(rs.getString("inspection_location")); |
| | | task.setFrequencyType(rs.getString("frequency_type")); |
| | | task.setFrequencyDetail(rs.getString("frequency_detail")); |
| | | task.setRemarks(rs.getString("remarks")); |
| | | task.setRegistrantId(rs.getLong("registrant_id")); |
| | | task.setRegistrant(rs.getString("registrant")); |
| | | task.setTenantId(rs.getLong("tenant_id")); |
| | | // è·åç»è®°æ¥æ |
| | | java.sql.Date regDate = rs.getDate("registration_date"); |
| | | if (regDate != null) { |
| | | task.setRegistrationDate(regDate.toLocalDate()); |
| | | } |
| | | return task; |
| | | }); |
| | | |
| | | System.out.println("=== å
±æ¾å° " + tasks.size() + " 个巡æ£ä»»å¡ ===\n"); |
| | | |
| | | int totalRecords = 0; |
| | | for (TimingTask task : tasks) { |
| | | try { |
| | | // çæææç¬¦å颿¬¡çè®°å½ |
| | | int recordCount = generateRecordsForTask(task); |
| | | totalRecords += recordCount; |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() |
| | | + " | ç»è®°æ¥æ: " + task.getRegistrationDate() |
| | | + " | çæè®°å½æ°: " + recordCount); |
| | | } catch (Exception e) { |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | System.out.println("\n=== æ§è¡å®æ: å
±çæ " + totalRecords + " æ¡è®°å½ ==="); |
| | | } |
| | | |
| | | /** |
| | | * 为å个任å¡çæææç¬¦å颿¬¡çè®°å½ |
| | | */ |
| | | private int generateRecordsForTask(TimingTask task) { |
| | | LocalDate startDate = task.getRegistrationDate(); |
| | | if (startDate == null) { |
| | | startDate = LocalDate.now(); |
| | | } |
| | | LocalDate endDate = LocalDate.now(); |
| | | |
| | | // æ ¹æ®é¢æ¬¡è·åææéè¦æ§è¡çæ¥æ |
| | | List<LocalDateTime> executionDates = getExecutionDates(task.getFrequencyType(), task.getFrequencyDetail(), startDate, endDate); |
| | | |
| | | int count = 0; |
| | | for (LocalDateTime executionDate : executionDates) { |
| | | try { |
| | | // çæå·¡æ£è®°å½ |
| | | InspectionTask record = createInspectionRecord(task, executionDate); |
| | | inspectionTaskMapper.insert(record); |
| | | |
| | | // æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | updateTaskLastExecutionTime(task.getId(), executionDate); |
| | | |
| | | count++; |
| | | } catch (Exception e) { |
| | | System.out.println(" â æ¥æ: " + executionDate + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | if (count > 0) { |
| | | LocalDateTime lastExecution = executionDates.get(executionDates.size() - 1); |
| | | LocalDateTime nextExecution = calculateNextExecutionTime(task.getFrequencyType(), task.getFrequencyDetail(), lastExecution); |
| | | updateTaskNextExecutionTime(task.getId(), nextExecution); |
| | | } |
| | | |
| | | return count; |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®æ¥æèå´å
ææç¬¦å颿¬¡çæ§è¡æ¶é´ |
| | | */ |
| | | private List<LocalDateTime> getExecutionDates(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate endDate) { |
| | | List<LocalDateTime> dates = new java.util.ArrayList<>(); |
| | | |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | dates.addAll(getDailyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "WEEKLY": |
| | | dates.addAll(getWeeklyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "MONTHLY": |
| | | dates.addAll(getMonthlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "QUARTERLY": |
| | | dates.addAll(getQuarterlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | } |
| | | |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getDailyDates(LocalDate startDate, LocalDate endDate, String timeStr) { |
| | | List<LocalDateTime> dates = new java.util.ArrayList<>(); |
| | | LocalTime time = LocalTime.parse(timeStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getWeeklyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new java.util.ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | if (targetDays.contains(current.getDayOfWeek())) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | } |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getMonthlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new java.util.ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | LocalDate current = startDate.plusMonths(0).withDayOfMonth(Math.min(dayOfMonth, startDate.lengthOfMonth())); |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(1).withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).lengthOfMonth())); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getQuarterlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new java.util.ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonth = startDate.getMonthValue(); |
| | | int targetMonth = ((currentMonth - 1) / 3) * 3 + quarterMonth; |
| | | int yearAdjust = 0; |
| | | |
| | | if (targetMonth > 12) { |
| | | targetMonth -= 12; |
| | | yearAdjust = 1; |
| | | } |
| | | |
| | | LocalDate current = startDate.withYear(startDate.getYear() + yearAdjust) |
| | | .withMonth(targetMonth) |
| | | .withDayOfMonth(Math.min(dayOfMonth, YearMonth.of(startDate.getYear() + yearAdjust, targetMonth).lengthOfMonth())); |
| | | |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(3).withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(3).lengthOfMonth())); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private Set<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) { |
| | | Set<DayOfWeek> days = new HashSet<>(); |
| | | String[] dayStrs = dayOfWeekStr.split("\\|"); |
| | | |
| | | for (String dayStr : dayStrs) { |
| | | switch (dayStr.toUpperCase()) { |
| | | case "MON": days.add(DayOfWeek.MONDAY); break; |
| | | case "TUE": days.add(DayOfWeek.TUESDAY); break; |
| | | case "WED": days.add(DayOfWeek.WEDNESDAY); break; |
| | | case "THU": days.add(DayOfWeek.THURSDAY); break; |
| | | case "FRI": days.add(DayOfWeek.FRIDAY); break; |
| | | case "SAT": days.add(DayOfWeek.SATURDAY); break; |
| | | case "SUN": days.add(DayOfWeek.SUNDAY); break; |
| | | } |
| | | } |
| | | return days; |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸æ¬¡æ§è¡æ¶é´ |
| | | */ |
| | | private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) { |
| | | return switch (frequencyType) { |
| | | case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime); |
| | | case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime); |
| | | case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime); |
| | | case "QUARTERLY" -> calculateQuarterlyNextTime(frequencyDetail, currentTime); |
| | | default -> throw new IllegalArgumentException("䏿¯æç颿¬¡ç±»å: " + frequencyType); |
| | | }; |
| | | } |
| | | |
| | | private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) { |
| | | LocalTime executionTime = LocalTime.parse(timeStr); |
| | | LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime); |
| | | return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1); |
| | | } |
| | | |
| | | private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | return current.plusMonths(1) |
| | | .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth())) |
| | | .with(time); |
| | | } |
| | | |
| | | private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | Set<DayOfWeek> targetDays = parseDayOfWeeks(dayOfWeekStr); |
| | | |
| | | LocalDateTime nextTime = current; |
| | | while (true) { |
| | | nextTime = nextTime.plusDays(1); |
| | | if (targetDays.contains(nextTime.getDayOfWeek())) { |
| | | return LocalDateTime.of(nextTime.toLocalDate(), time); |
| | | } |
| | | if (nextTime.isAfter(current.plusYears(1))) { |
| | | throw new RuntimeException("æ æ³æ¾å°ä¸æ¬¡æ§è¡æ¶é´"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1; |
| | | |
| | | YearMonth targetYearMonth; |
| | | if (currentMonthInQuarter < quarterMonth) { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter); |
| | | } else { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth); |
| | | } |
| | | |
| | | int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth()); |
| | | return LocalDateTime.of(targetYearMonth.getYear(), targetYearMonth.getMonthValue(), adjustedDay, time.getHour(), time.getMinute()); |
| | | } |
| | | |
| | | /** |
| | | * å建巡æ£è®°å½ |
| | | */ |
| | | private InspectionTask createInspectionRecord(TimingTask timingTask, LocalDateTime executionDate) { |
| | | InspectionTask inspectionTask = new InspectionTask(); |
| | | inspectionTask.setTaskName(timingTask.getTaskName()); |
| | | inspectionTask.setInspectionProject(timingTask.getInspectionProject()); |
| | | inspectionTask.setTaskId(timingTask.getTaskId()); |
| | | inspectionTask.setInspectorId(timingTask.getInspectorIds()); |
| | | inspectionTask.setInspectionLocation(timingTask.getInspectionLocation()); |
| | | inspectionTask.setRemarks("èªå¨çæèªå®æ¶ä»»å¡ID: " + timingTask.getId() + "ï¼" + timingTask.getRemarks()); |
| | | inspectionTask.setRegistrantId(timingTask.getRegistrantId()); |
| | | inspectionTask.setFrequencyType(timingTask.getFrequencyType()); |
| | | inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); |
| | | inspectionTask.setTenantId(timingTask.getTenantId()); |
| | | // 设置ç»è®°æ¥æä¸ºæ§è¡æ¥æ |
| | | inspectionTask.setCreateTime(executionDate); |
| | | inspectionTask.setUpdateTime(executionDate); |
| | | return inspectionTask; |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | */ |
| | | private void updateTaskLastExecutionTime(Long taskId, LocalDateTime lastExecutionTime) { |
| | | String updateSql = "UPDATE timing_task SET last_execution_time = ? WHERE id = ?"; |
| | | jdbcTemplate.update(updateSql, lastExecutionTime, taskId); |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | */ |
| | | private void updateTaskNextExecutionTime(Long taskId, LocalDateTime nextExecutionTime) { |
| | | String updateSql = "UPDATE timing_task SET next_execution_time = ? WHERE id = ?"; |
| | | jdbcTemplate.update(updateSql, nextExecutionTime, taskId); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.stock.service.impl; |
| | | |
| | | import com.ruoyi.production.mapper.ProductionOrderMapper; |
| | | import com.ruoyi.production.mapper.ProductionOrderPickMapper; |
| | | import com.ruoyi.production.pojo.ProductionOrder; |
| | | import com.ruoyi.production.pojo.ProductionOrderPick; |
| | | import com.ruoyi.purchase.mapper.PurchaseReturnOrdersMapper; |
| | | import com.ruoyi.purchase.pojo.PurchaseReturnOrders; |
| | | import com.ruoyi.sales.mapper.SalesLedgerMapper; |
| | | import com.ruoyi.sales.mapper.ShippingInfoMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import com.ruoyi.sales.pojo.ShippingInfo; |
| | | import com.ruoyi.stock.mapper.StockOutRecordMapper; |
| | | import com.ruoyi.stock.pojo.StockOutRecord; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | @SpringBootTest |
| | | public class StockOutRecordBatchUpdateTest { |
| | | |
| | | @Autowired |
| | | private JdbcTemplate jdbcTemplate; |
| | | |
| | | @Autowired |
| | | private StockOutRecordMapper stockOutRecordMapper; |
| | | |
| | | @Autowired |
| | | private PurchaseReturnOrdersMapper purchaseReturnOrdersMapper; |
| | | |
| | | @Autowired |
| | | private ShippingInfoMapper shippingInfoMapper; |
| | | |
| | | @Autowired |
| | | private SalesLedgerMapper salesLedgerMapper; |
| | | |
| | | @Autowired |
| | | private ProductionOrderPickMapper productionOrderPickMapper; |
| | | |
| | | @Autowired |
| | | private ProductionOrderMapper productionOrderMapper; |
| | | |
| | | /** |
| | | * æ´æ°åºåºåæ¶é´ |
| | | */ |
| | | @Test |
| | | void testUpdateStockOutRecords() { |
| | | List<StockOutRecord> allRecords = stockOutRecordMapper.selectList(null); |
| | | System.out.println("æ»è®°å½æ°: " + allRecords.size()); |
| | | |
| | | List<RecordWithDate> recordWithDates = new ArrayList<>(); |
| | | |
| | | for (StockOutRecord record : allRecords) { |
| | | String type = record.getRecordType(); |
| | | if (type == null) continue; |
| | | |
| | | switch (type) { |
| | | case "1": |
| | | case "10": |
| | | recordWithDates.add(resolveType1or10(record, type)); |
| | | break; |
| | | case "3": |
| | | System.out.println("ç±»å3ï¼ç产æ¥å·¥-åºåºï¼é¢ç忝ï¼å½åæ æ°æ®ï¼è·³è¿"); |
| | | break; |
| | | case "8": |
| | | System.out.println("ç±»å8ï¼éå®-åºåºï¼é¢ç忝ï¼å½åæ æ°æ®ï¼è·³è¿"); |
| | | break; |
| | | case "9": |
| | | recordWithDates.add(resolveType9(record)); |
| | | break; |
| | | case "13": |
| | | recordWithDates.add(resolveType13(record)); |
| | | break; |
| | | case "14": |
| | | recordWithDates.add(resolveType14or15(record)); |
| | | break; |
| | | case "15": |
| | | recordWithDates.add(resolveType14or15(record)); |
| | | break; |
| | | default: |
| | | System.out.println("æªç¥ç±»å " + type + "ï¼è·³è¿ ID=" + record.getId()); |
| | | } |
| | | } |
| | | |
| | | Map<LocalDate, List<RecordWithDate>> byDate = recordWithDates.stream() |
| | | .collect(Collectors.groupingBy( |
| | | rwd -> rwd.dateTime.toLocalDate(), |
| | | LinkedHashMap::new, |
| | | Collectors.toList() |
| | | )); |
| | | |
| | | int totalUpdated = 0; |
| | | for (Map.Entry<LocalDate, List<RecordWithDate>> dateEntry : byDate.entrySet()) { |
| | | LocalDate date = dateEntry.getKey(); |
| | | List<RecordWithDate> records = dateEntry.getValue(); |
| | | records.sort(Comparator.comparing(rwd -> rwd.dateTime)); |
| | | |
| | | assignRandomTimes(records, date); |
| | | |
| | | records.sort(Comparator.comparing(rwd -> rwd.dateTime)); |
| | | |
| | | int seq = 1; |
| | | for (RecordWithDate rwd : records) { |
| | | StockOutRecord record = rwd.record; |
| | | String type = record.getRecordType(); |
| | | String batchNo = "CK" + date.format(DateTimeFormatter.ofPattern("yyyyMMdd")) + String.format("%03d", seq++); |
| | | LocalDateTime createTime = rwd.dateTime; |
| | | |
| | | jdbcTemplate.update( |
| | | "UPDATE stock_out_record SET outbound_batches = ?, create_time = ?, update_time = ? WHERE id = ?", |
| | | batchNo, createTime, createTime, record.getId()); |
| | | |
| | | System.out.println("ID=" + record.getId() |
| | | + " type=" + type |
| | | + " batch=" + batchNo |
| | | + " time=" + createTime); |
| | | totalUpdated++; |
| | | } |
| | | } |
| | | |
| | | System.out.println("å
¨é¨å®æï¼å
±æ´æ° " + totalUpdated + " æ¡è®°å½"); |
| | | } |
| | | |
| | | private void assignRandomTimes(List<RecordWithDate> records, LocalDate date) { |
| | | List<RecordWithDate> individual = new ArrayList<>(); |
| | | Map<Long, List<RecordWithDate>> grouped = new LinkedHashMap<>(); |
| | | |
| | | for (RecordWithDate rwd : records) { |
| | | String type = rwd.record.getRecordType(); |
| | | if (!"1".equals(type) && !"9".equals(type) && !"10".equals(type) |
| | | && !"13".equals(type) && !"14".equals(type) && !"15".equals(type)) { |
| | | continue; |
| | | } |
| | | if (("14".equals(type) || "15".equals(type)) && rwd.record.getRecordId() != null) { |
| | | grouped.computeIfAbsent(rwd.record.getRecordId(), k -> new ArrayList<>()).add(rwd); |
| | | } else { |
| | | individual.add(rwd); |
| | | } |
| | | } |
| | | |
| | | List<TimeSlot> slots = new ArrayList<>(); |
| | | for (RecordWithDate rwd : individual) { |
| | | slots.add(new TimeSlot(rwd.record.getId(), List.of(rwd))); |
| | | } |
| | | for (Map.Entry<Long, List<RecordWithDate>> entry : grouped.entrySet()) { |
| | | long minId = entry.getValue().stream() |
| | | .mapToLong(rwd -> rwd.record.getId()) |
| | | .min().orElse(0); |
| | | slots.add(new TimeSlot(minId, entry.getValue())); |
| | | } |
| | | |
| | | if (slots.isEmpty()) return; |
| | | |
| | | slots.sort(Comparator.comparingLong(s -> s.sortKey)); |
| | | |
| | | int totalMinutes = 480; |
| | | for (int i = 0; i < slots.size(); i++) { |
| | | int offsetMinutes = (int) ((long) i * totalMinutes / slots.size()); |
| | | int jitter = (int) (Math.random() * 6 - 3); |
| | | offsetMinutes = Math.max(0, Math.min(479, offsetMinutes + jitter)); |
| | | |
| | | LocalTime time; |
| | | if (offsetMinutes < 240) { |
| | | time = LocalTime.of(8, 0).plusMinutes(offsetMinutes); |
| | | } else { |
| | | time = LocalTime.of(14, 0).plusMinutes(offsetMinutes - 240); |
| | | } |
| | | LocalDateTime dt = LocalDateTime.of(date, time); |
| | | for (RecordWithDate rwd : slots.get(i).members) { |
| | | rwd.dateTime = dt; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private static class TimeSlot { |
| | | final long sortKey; |
| | | final List<RecordWithDate> members; |
| | | |
| | | TimeSlot(long sortKey, List<RecordWithDate> members) { |
| | | this.sortKey = sortKey; |
| | | this.members = members; |
| | | } |
| | | } |
| | | |
| | | private RecordWithDate resolveType1or10(StockOutRecord record, String type) { |
| | | LocalDate date = record.getCreateTime() != null |
| | | ? record.getCreateTime().toLocalDate() |
| | | : LocalDate.now(); |
| | | return new RecordWithDate(record, LocalDateTime.of(date, LocalTime.of(8, 0))); |
| | | } |
| | | |
| | | private RecordWithDate resolveType9(StockOutRecord record) { |
| | | Long recordId = record.getRecordId(); |
| | | if (recordId != null) { |
| | | PurchaseReturnOrders pro = purchaseReturnOrdersMapper.selectById(recordId); |
| | | if (pro != null && pro.getPreparedAt() != null) { |
| | | return new RecordWithDate(record, LocalDateTime.of(pro.getPreparedAt(), LocalTime.of(8, 0))); |
| | | } |
| | | } |
| | | return fallbackDateTime(record); |
| | | } |
| | | |
| | | private RecordWithDate resolveType13(StockOutRecord record) { |
| | | Long recordId = record.getRecordId(); |
| | | if (recordId != null) { |
| | | ShippingInfo shippingInfo = shippingInfoMapper.selectById(recordId); |
| | | if (shippingInfo != null && shippingInfo.getSalesLedgerId() != null) { |
| | | SalesLedger salesLedger = salesLedgerMapper.selectById(shippingInfo.getSalesLedgerId()); |
| | | if (salesLedger != null && salesLedger.getDeliveryDate() != null) { |
| | | return new RecordWithDate(record, LocalDateTime.of(salesLedger.getDeliveryDate(), LocalTime.of(8, 0))); |
| | | } |
| | | } |
| | | } |
| | | return fallbackDateTime(record); |
| | | } |
| | | |
| | | private RecordWithDate resolveType14or15(StockOutRecord record) { |
| | | Long recordId = record.getRecordId(); |
| | | if (recordId != null) { |
| | | ProductionOrderPick pick = productionOrderPickMapper.selectById(recordId); |
| | | if (pick != null && pick.getProductionOrderId() != null) { |
| | | ProductionOrder order = productionOrderMapper.selectById(pick.getProductionOrderId()); |
| | | if (order != null && order.getStartTime() != null) { |
| | | return new RecordWithDate(record, LocalDateTime.of(order.getStartTime().toLocalDate(), LocalTime.of(8, 0))); |
| | | } |
| | | } |
| | | } |
| | | return fallbackDateTime(record); |
| | | } |
| | | |
| | | private RecordWithDate fallbackDateTime(StockOutRecord record) { |
| | | return record.getCreateTime() != null |
| | | ? new RecordWithDate(record, record.getCreateTime()) |
| | | : new RecordWithDate(record, LocalDateTime.now()); |
| | | } |
| | | |
| | | private static class RecordWithDate { |
| | | final StockOutRecord record; |
| | | LocalDateTime dateTime; |
| | | |
| | | RecordWithDate(StockOutRecord record, LocalDateTime dateTime) { |
| | | this.record = record; |
| | | this.dateTime = dateTime; |
| | | } |
| | | } |
| | | } |