feat(quality): 增加检验管理功能并完善库存预警
- 新增批量快速检验功能,支持一键通过并提交多个检验单
- 实现出厂检验直接绑定销售订单功能,无需通过生产工单链路
- 完善备件库存预警机制,在设备维护和维修时触发预警通知
- 优化采购台账收货状态管理,支持待收货、收货中、已收货状态
- 增加销售台账关联采购合同号功能,便于合同追溯管理
- 完善备件库存预警通知,当库存低于预警数量时自动通知相关人员
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- åºåæ£éªç»å®éå®è®¢å |
| | | -- å¨ quality_inspect 表æ°å¢ sales_ledger_id åæ®µ |
| | | ALTER TABLE quality_inspect |
| | | ADD COLUMN sales_ledger_id BIGINT DEFAULT NULL COMMENT 'éå®å°è´¦idï¼åºåæ£éªç»å®éå®è®¢åï¼'; |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- ============================================================ |
| | | -- éå®å°è´¦(sales_ledger)æ·»å éè´å°è´¦å
³èåæ®µ |
| | | -- 说æï¼éå®å°è´¦å
³èéè´å°è´¦ï¼ç¨äºå¨éå®å°è´¦å表ä¸å±ç¤ºéè´ååå· |
| | | -- æ§è¡å请å¤ä»½æ°æ®åº |
| | | -- ============================================================ |
| | | |
| | | -- 1. æ·»å éè´å°è´¦idåæ®µ |
| | | ALTER TABLE sales_ledger |
| | | ADD COLUMN purchase_ledger_id BIGINT NULL COMMENT 'éè´å°è´¦id' |
| | | AFTER delivery_date; |
| | | |
| | | -- 2. æ·»å ç´¢å¼ï¼å¯éï¼å¦éæéè´å°è´¦idæ¥è¯¢æ¶å»ºè®®æ·»å ï¼ |
| | | -- ALTER TABLE sales_ledger ADD INDEX idx_purchase_ledger_id (purchase_ledger_id); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # åºåæ£éª - éå®è®¢åç»å®èè°ææ¡£ |
| | | |
| | | ## åæ´æ¦è¿° |
| | | |
| | | åºåæ£éªï¼`inspectType = 2`ï¼æ¯æç´æ¥ç»å®éå®è®¢åï¼æ ééè¿ç产工åé¾è·¯è·åéå®ååå·ã |
| | | |
| | | ## ä¸ãæ°æ®åºåæ´ |
| | | |
| | | æ§è¡ `docs/quality_inspect_add_sales_ledger_id.sql`ï¼ |
| | | |
| | | ```sql |
| | | ALTER TABLE quality_inspect |
| | | ADD COLUMN sales_ledger_id BIGINT DEFAULT NULL COMMENT 'éå®å°è´¦idï¼åºåæ£éªç»å®éå®è®¢åï¼'; |
| | | ``` |
| | | |
| | | ## äºãå端æ¥å£åæ´ |
| | | |
| | | ### 2.1 æ°å¢/ç¼è¾åºåæ£éª |
| | | |
| | | **POST** `/quality/qualityInspect/add` |
| | | **POST** `/quality/qualityInspect/update` |
| | | |
| | | æ°å¢åæ®µï¼ |
| | | |
| | | | åæ®µ | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | `salesLedgerId` | Long | å¦ | éå®å°è´¦IDï¼åºåæ£éªæ¶éæ©ç»å®çéå®è®¢å | |
| | | |
| | | 请æ±ä½ç¤ºä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "inspectType": 2, |
| | | "salesLedgerId": 1001, |
| | | "checkTime": "2026-05-30", |
| | | "customer": "客æ·åç§°", |
| | | "productName": "产åA", |
| | | ... |
| | | } |
| | | ``` |
| | | |
| | | ### 2.2 å表æ¥è¯¢ |
| | | |
| | | **GET** `/quality/qualityInspect/listPage?inspectType=2` |
| | | |
| | | è¿ååæ®µä¸åï¼`salesContractNo` ç°å¨ä¼å
ä»ç´æ¥ç»å®ç `sales_ledger_id` è·åï¼ä¸ºç©ºæ¶åéå°ç产工åé¾è·¯ã |
| | | |
| | | ```json |
| | | { |
| | | "records": [ |
| | | { |
| | | "id": 1, |
| | | "inspectType": 2, |
| | | "salesLedgerId": 1001, |
| | | "salesContractNo": "XS-2026-0001", |
| | | "workOrderNo": "GD-2026-001", |
| | | ... |
| | | } |
| | | ] |
| | | } |
| | | ``` |
| | | |
| | | | åæ®µ | ç±»å | 说æ | |
| | | |------|------|------| |
| | | | `salesLedgerId` | Long | ç»å®çéå®å°è´¦ID | |
| | | | `salesContractNo` | String | éå®ååå·ï¼å符串ï¼ä¼å
åç´æ¥ç»å®ï¼ | |
| | | | `workOrderNo` | String | å·¥åå·ï¼éè¿æ¥å·¥é¾è·¯è·åï¼åºåæ£éªå¯è½ä¸ºç©ºï¼ | |
| | | |
| | | ## ä¸ãå端对æ¥è¦ç¹ |
| | | |
| | | ### 3.1 åºåæ£éªè¡¨å |
| | | |
| | | å¨åºåæ£éªï¼`inspectType = 2`ï¼çæ°å¢/ç¼è¾è¡¨åä¸ï¼æ°å¢"éå®è®¢å"éæ©å¨ï¼ |
| | | |
| | | - **åæ®µå**ï¼`salesLedgerId` |
| | | - **ç»ä»¶ç±»å**ï¼ä¸æéæ© / å¼¹çªéæ© |
| | | - **æ°æ®æº**ï¼è°ç¨éå®å°è´¦å表æ¥å£ï¼å±ç¤º `salesContractNo`ï¼éå®ååå·ï¼ |
| | | - **æ¾ç¤ºå¼**ï¼éå®ååå· |
| | | - **ç»å®å¼**ï¼éå®å°è´¦ `id` |
| | | - **交äºå»ºè®®**ï¼åºåæ£éªæ¶ï¼å
è®¸ç¨æ·ç´æ¥æç´¢/éæ©éå®è®¢åï¼éä¸åèªå¨å¡«å
¥ `salesLedgerId` |
| | | |
| | | ### 3.2 å表页 |
| | | |
| | | åºåæ£éªå表页已æ `salesContractNo` åï¼æ éé¢å¤æ¹å¨ãå端已èªå¨è¿åç´æ¥ç»å®çéå®ååå·ã |
| | | |
| | | ### 3.3 详æ
页 |
| | | |
| | | 详æ
æ¥å£ **GET** `/quality/qualityInspect/{id}` è¿åç `salesLedgerId` å¯ç¨äºåæ¾å·²ç»å®çéå®è®¢åã |
| | | |
| | | ## åãæ³¨æäºé¡¹ |
| | | |
| | | 1. `salesLedgerId` ä»
å¨ `inspectType = 2`ï¼åºåæ£éªï¼æ¶ä½¿ç¨ï¼åæææ£éªåè¿ç¨æ£éªå¿½ç¥æ¤å段 |
| | | 2. åºåæ£éªéè¿æ¥å·¥ï¼`productMainId`ï¼ç»å®çå·¥åå·ï¼`workOrderNo`ï¼ä»ç¶ä¿çï¼ä¸åå½±å |
| | | 3. `salesContractNo` çåå¼ä¼å
级ï¼ç´æ¥ç»å® > ç产工åé¾è·¯ |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # æ£éªç®¡ç - æ¹éå¿«éæ£éªèè°ææ¡£ |
| | | |
| | | ## åæ´æ¦è¿° |
| | | |
| | | åæææ£éªãè¿ç¨æ£éªãåºåæ£éªä¸ç§ç±»å忝æ"å¿«éæ£éª"ï¼éä¸å¤æ¡æªæäº¤çæ£éªåï¼ä¸é®èªå¨éè¿å¹¶æäº¤ã |
| | | |
| | | ## ä¸ãæ¥å£è¯´æ |
| | | |
| | | ### æ¹éå¿«éæ£éª |
| | | |
| | | **POST** `/quality/qualityInspect/batchQuickInspect` |
| | | |
| | | 请æ±ä½ï¼ |
| | | |
| | | ```json |
| | | [1001, 1002, 1003] |
| | | ``` |
| | | |
| | | | åæ° | ç±»å | å¿
å¡« | 说æ | |
| | | |------|------|------|------| |
| | | | `ids` | Long[] | æ¯ | éè¦å¿«éæ£éªçæ£éªåIDæ°ç» | |
| | | |
| | | è¿å示ä¾ï¼ |
| | | |
| | | ```json |
| | | { |
| | | "code": 200, |
| | | "msg": "å¿«éæ£éªå®æï¼æå 3 æ¡ï¼å¤±è´¥ 0 æ¡" |
| | | } |
| | | ``` |
| | | |
| | | ## äºãä¸å¡é»è¾ |
| | | |
| | | 对æ¯ä¸ªéä¸çæ£éªåæ§è¡ä»¥ä¸æµç¨ï¼å¤ç¨ `autoSubmit` é»è¾ï¼ï¼ |
| | | |
| | | 1. **æ ¡éª**ï¼æ£éªåä¸åå¨ â è·³è¿ï¼è®¡å¤±è´¥ |
| | | 2. **è·³è¿å·²æäº¤**ï¼`inspectState == 1` çæ£éªåç´æ¥è¿åæåï¼ä¸éå¤å¤ç |
| | | 3. **èªå¨å¡«å
åæ ¼**ï¼ |
| | | - `checkResult` 为空 â 设为 `"åæ ¼"` |
| | | - `qualifiedQuantity` 为空 â 设为 `quantity`ï¼æ»æ°ï¼ |
| | | - `unqualifiedQuantity` 为空 â 设为 `0` |
| | | 4. **æäº¤å
¥åº**ï¼ |
| | | - åæ ¼æ°é > 0 â å建å
¥åºè®°å½ï¼`stock_in_record`ï¼ |
| | | - ä¸åæ ¼æ°é > 0 â å建ä¸åæ ¼åè®°å½ï¼`quality_unqualified`ï¼ |
| | | - `inspectState` æ´æ°ä¸º `1`ï¼å·²æäº¤ï¼ |
| | | |
| | | è¿åæå/失败计æ°ã |
| | | |
| | | ## ä¸ãå端对æ¥è¦ç¹ |
| | | |
| | | ### 3.1 æé®ä½ç½® |
| | | |
| | | 卿£éªå表页ï¼åææ/è¿ç¨/åºåæ£éªï¼çå·¥å
·æ å¢å "å¿«éæ£éª"æé®ã |
| | | |
| | | ### 3.2 äº¤äºæµç¨ |
| | | |
| | | ``` |
| | | 1. ç¨æ·å¾é夿¡æ£éªåï¼inspectState = 0ï¼æªæäº¤ç¶æï¼ |
| | | 2. ç¹å»"å¿«éæ£éª"æé® |
| | | 3. å¼¹åºç¡®è®¤æ¡ï¼ |
| | | âââââââââââââââââââââââââââââââ |
| | | â å¿«éæ£éª â |
| | | â â |
| | | â 已鿩 X æ¡æ£éªå â |
| | | â â |
| | | â 确认åå°èªå¨ï¼ â |
| | | â · æ£éªç»æè®¾ä¸º"åæ ¼" â |
| | | â · åæ ¼æ°éè®¾ä¸ºæ»æ° â |
| | | â · ä¸åæ ¼æ°é设为 0 â |
| | | â · æäº¤å¹¶å
¥åº â |
| | | â â |
| | | â å·²æäº¤çæ£éªåå°èªå¨è·³è¿ â |
| | | â â |
| | | â [åæ¶] [确认] â |
| | | âââââââââââââââââââââââââââââââ |
| | | 4. 确认åè°ç¨ /batchQuickInspect |
| | | 5. æ ¹æ®è¿åç»æå·æ°åè¡¨ï¼æç¤ºæå/失败æ°é |
| | | ``` |
| | | |
| | | ### 3.3 注æäºé¡¹ |
| | | |
| | | - æ¹éå¿«éæ£éªä»
对**æªæäº¤**ï¼`inspectState = 0`ï¼çæ£éªåçæ |
| | | - å·²æäº¤çæ£éªåä¼èªå¨è·³è¿ï¼ä¸ä¼éå¤å¤ç |
| | | - ä¸ç§æ£éªç±»åï¼åææ/è¿ç¨/åºåï¼å
±ç¨åä¸ä¸ªæ¥å£ |
| | | - å端建议å¨åè¡¨æ°æ®ä¸éè¿ `inspectState` åæ®µ**ç½®ç°å·²æäº¤è¡**ï¼é²æ¢ç¨æ·è¯¯é |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # éå®å°è´¦å表 - æ°å¢éè´ååå·å段 |
| | | |
| | | ## åæ´æ¦è¿° |
| | | |
| | | éå®å°è´¦å表æ¥å£æ°å¢ **éè´ååå·** åæ®µè¿åï¼åæ¶ `sales_ledger` 表æ°å¢ `purchase_ledger_id` åæ®µç¨äºå
³èéè´å°è´¦ã |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãæ°æ®åºåæ´ |
| | | |
| | | **æ§è¡æä»¶**: `docs/sales_ledger_add_purchase_ledger_id.sql` |
| | | |
| | | | 表å | åæ´ç±»å | åæ®µ | ç±»å | 说æ | |
| | | |------|---------|------|------|------| |
| | | | sales_ledger | æ°å¢ | purchase_ledger_id | BIGINT | å
³è purchase_ledger.id | |
| | | |
| | | --- |
| | | |
| | | ## äºãæ¥å£åæ´ |
| | | |
| | | ### æ¶åæ¥å£ |
| | | |
| | | ``` |
| | | GET /sales/ledger/listPage |
| | | ``` |
| | | |
| | | ### 请æ±åæ° |
| | | |
| | | æ åæ´ï¼æ²¿ç¨ç°æåæ°ã |
| | | |
| | | ### ååºåæ´ |
| | | |
| | | ååºå¤å±ç»æä¸åï¼ä»æ¯ `IPage<SalesLedgerVo>` åé¡µæ ¼å¼ï¼ï¼`records` 䏿¯æ¡è®°å½æ°å¢ä¸ä¸ªåæ®µï¼ |
| | | |
| | | | åæ®µå | ç±»å | 说æ | 示ä¾å¼ | |
| | | |--------|------|------|--------| |
| | | | `purchaseContractNumber` | String | éè´ååå·ï¼æªå
³èéè´å°è´¦æ¶ä¸º null | `"CG202605001"` | |
| | | |
| | | ### ååºç¤ºä¾ï¼ä»
å±ç¤ºæ°å¢åæ®µï¼ |
| | | |
| | | ```json |
| | | { |
| | | "records": [ |
| | | { |
| | | "id": 1, |
| | | "salesContractNo": "XS202605001", |
| | | "customerName": "XXå
¬å¸", |
| | | "contractAmount": 100000.00, |
| | | "purchaseContractNumber": "CG202605001" |
| | | }, |
| | | { |
| | | "id": 2, |
| | | "salesContractNo": "XS202605002", |
| | | "customerName": "YYå
¬å¸", |
| | | "contractAmount": 50000.00, |
| | | "purchaseContractNumber": null |
| | | } |
| | | ], |
| | | "total": 2, |
| | | "current": 1, |
| | | "size": 10 |
| | | } |
| | | ``` |
| | | |
| | | ### æ°æ®æ¥æºè¯´æ |
| | | |
| | | - `purchaseContractNumber` éè¿ `sales_ledger.purchase_ledger_id` å
³è `purchase_ledger.id` è·å |
| | | - åèª `purchase_ledger.purchase_contract_number` åæ®µ |
| | | - éè¿ LEFT JOIN æ¥è¯¢ï¼æªå
³èæ¶ä¸é»å¡å表å±ç¤º |
| | | |
| | | --- |
| | | |
| | | ## ä¸ãä¿å/ç¼è¾æ¥å£è¯´æ |
| | | |
| | | ä¿åéå®å°è´¦æ¶å¦éå
³èéè´å°è´¦ï¼ä¼ å
¥æ°å¢åæ®µï¼ |
| | | |
| | | ```json |
| | | POST /sales/ledger/addOrUpdateSalesLedger |
| | | |
| | | { |
| | | "id": 1, |
| | | "salesContractNo": "XS202605001", |
| | | "purchaseLedgerId": 10, |
| | | "...": "..." |
| | | } |
| | | ``` |
| | | |
| | | | åæ®µå | ç±»å | å¿
å¡« | 说æ | |
| | | |--------|------|------|------| |
| | | | `purchaseLedgerId` | Long | å¦ | éè´å°è´¦idï¼å¯¹åº purchase_ledger.id | |
| | | |
| | | --- |
| | | |
| | | ## åãåç«¯å¯¹æ¥æ¸
å |
| | | |
| | | - [ ] éå®å°è´¦**å表页**ï¼æ°å¢"éè´ååå·"åï¼ç»å® `record.purchaseContractNumber` |
| | | - [ ] éå®å°è´¦**æ°å¢/ç¼è¾è¡¨å**ï¼æ°å¢"å
³èéè´å°è´¦"䏿鿩æ¡ï¼ç»å® `form.purchaseLedgerId` |
| | | - [ ] éè´ååå·å建议设置为å¯ç¹å»é¾æ¥ï¼è·³è½¬è³å¯¹åºéè´å°è´¦è¯¦æ
|
| | | - [ ] 妿 `purchaseContractNumber` 为 nullï¼åå±ç¤º "-" æç½®ç©º |
| | |
| | | import com.ruoyi.device.vo.DeviceRepairVo; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper; |
| | | import com.ruoyi.project.system.service.ISysNoticeService; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SpareParts; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord; |
| | | import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService; |
| | |
| | | private final SparePartsMapper sparePartsMapper; |
| | | private final SparePartsRequisitionRecordService sparePartsRequisitionRecordService; |
| | | private final FileUtil fileUtil; |
| | | private final ISysNoticeService sysNoticeService; |
| | | |
| | | @Override |
| | | public IPage<DeviceMaintenanceDto> queryPage(Page page, DeviceMaintenanceDto deviceMaintenanceDto) { |
| | |
| | | sparePartsMapper.updateById(spareParts); |
| | | sparePartIds.add(sparePartUse.getId()); |
| | | |
| | | // åºåé¢è¦éç¥ |
| | | if (spareParts.getWarnNum() != null && spareParts.getNotifyPersonId() != null |
| | | && spareParts.getQuantity().compareTo(spareParts.getWarnNum()) < 0) { |
| | | sysNoticeService.simpleNoticeByUser( |
| | | "å¤ä»¶åºåé¢è¦", |
| | | "å¤ä»¶ã" + spareParts.getName() + "ãå½ååºå(" + spareParts.getQuantity() |
| | | + ")å·²ä½äºé¢è¦æ°é(" + spareParts.getWarnNum() + ")ï¼è¯·åæ¶éè´è¡¥å
ã", |
| | | List.of(spareParts.getNotifyPersonId()), |
| | | "/equipmentManagement/spareParts" |
| | | ); |
| | | } |
| | | |
| | | // å建å¤ä»¶é¢ç¨è®°å½ |
| | | SparePartsRequisitionRecord record = new SparePartsRequisitionRecord(); |
| | | record.setSourceType(1); // 1 ä¿å
» |
| | |
| | | import com.ruoyi.device.vo.DeviceRepairVo; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper; |
| | | import com.ruoyi.project.system.service.ISysNoticeService; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SpareParts; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SparePartsRequisitionRecord; |
| | | import com.ruoyi.measuringinstrumentledger.service.SparePartsRequisitionRecordService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.RequiredArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.commons.compress.utils.Lists; |
| | | import org.apache.commons.lang3.StringUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | private final SparePartsMapper sparePartsMapper; |
| | | private final SparePartsRequisitionRecordService sparePartsRequisitionRecordService; |
| | | private final FileUtil fileUtil; |
| | | private final ISysNoticeService sysNoticeService; |
| | | |
| | | private static final int STATUS_PENDING_REPAIR = 0; |
| | | private static final int STATUS_COMPLETED = 1; |
| | |
| | | sparePartsMapper.updateById(spareParts); |
| | | sparePartIds.add(sparePartUse.getId()); |
| | | |
| | | // åºåé¢è¦éç¥ |
| | | if (spareParts.getWarnNum() != null && spareParts.getNotifyPersonId() != null |
| | | && spareParts.getQuantity().compareTo(spareParts.getWarnNum()) < 0) { |
| | | sysNoticeService.simpleNoticeByUser( |
| | | "å¤ä»¶åºåé¢è¦", |
| | | "å¤ä»¶ã" + spareParts.getName() + "ãå½ååºå(" + spareParts.getQuantity() |
| | | + ")å·²ä½äºé¢è¦æ°é(" + spareParts.getWarnNum() + ")ï¼è¯·åæ¶éè´è¡¥å
ã", |
| | | List.of(spareParts.getNotifyPersonId()), |
| | | "/equipmentManagement/spareParts"); |
| | | } |
| | | |
| | | // å建å¤ä»¶é¢ç¨è®°å½ |
| | | SparePartsRequisitionRecord record = new SparePartsRequisitionRecord(); |
| | | record.setSourceType(0); // 0 ç»´ä¿® |
| | |
| | | package com.ruoyi.measuringinstrumentledger.dto; |
| | | |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SpareParts; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | |
| | | * å¤ä»¶åç±»ç¶åç§° |
| | | */ |
| | | private String parentName; |
| | | @Schema(description = "é¢è¦éç¥äººæµç§°") |
| | | private String notifyPersonName; |
| | | private List<SparePartsDto> children; |
| | | } |
| | |
| | | * å¤ä»¶åç±»æè¿° |
| | | */ |
| | | private String description; |
| | | @Schema(description = "åºåé¢è¦æ°é") |
| | | private BigDecimal warnNum; |
| | | @Schema(description = "é¢è¦éç¥äººid") |
| | | private Long notifyPersonId; |
| | | @Schema(description = "å建æ¶é´") |
| | | @TableField(fill = FieldFill.INSERT) |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") |
| | |
| | | * @param title æ é¢
|
| | | * @param message æ¶æ¯
|
| | | * @param jumpPath 跳转å°å
|
| | | * @param consigneeId æ¶ä»¶äººid
|
| | | */
|
| | | void simpleNoticeByUser(final String title, final String message, final List<Long> consigneeId, final String jumpPath);
|
| | |
|
| | |
| | | private String paymentMethod; |
| | | @Schema(description = "审æ¹ç¶æ") |
| | | private Integer approvalStatus; |
| | | @Schema(description = "æ¶è´§ç¶æ 1-å¾
æ¶è´§ 2-æ¶è´§ä¸ 3-å·²æ¶è´§") |
| | | private Integer status; |
| | | @Schema(description = "模æ¿åç§°") |
| | | private String templateName; |
| | | @Schema(description = "审æ¹äººid") |
| | |
| | | @Excel(name = "审æ¹ç¶æ", readConverterExp = "1=å¾
å®¡æ ¸,2=审æ¹ä¸,3=审æ¹éè¿,4=审æ¹å¤±è´¥") |
| | | private Integer approvalStatus; |
| | | |
| | | @Schema(description = "æ¶è´§ç¶æ 1-å¾
æ¶è´§ 2-æ¶è´§ä¸ 3-å·²æ¶è´§") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "模æ¿åç§°") |
| | | private String templateName; |
| | | @Schema(description = "审æ¹äººid") |
| | |
| | | import com.ruoyi.framework.security.LoginUser; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.framework.web.domain.R; |
| | | import com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper; |
| | | import com.ruoyi.measuringinstrumentledger.pojo.SpareParts; |
| | | import com.ruoyi.other.mapper.TempFileMapper; |
| | | import com.ruoyi.procurementrecord.mapper.ProcurementRecordMapper; |
| | | import com.ruoyi.procurementrecord.pojo.ProcurementRecordStorage; |
| | |
| | | private final StockInRecordService stockInRecordService; |
| | | private final StockUtils stockUtils; |
| | | private final ApprovalTemplateMapper approvalTemplateMapper; |
| | | private final SparePartsMapper sparePartsMapper; |
| | | |
| | | @Override |
| | | public List<PurchaseLedger> selectPurchaseLedgerList(PurchaseLedger purchaseLedger) { |
| | |
| | | purchaseLedger.setRecorderId(purchaseLedgerDto.getRecorderId()); |
| | | |
| | | purchaseLedger.setApprovalStatus(1); |
| | | if (purchaseLedger.getId() == null) { |
| | | purchaseLedger.setStatus(1); |
| | | } |
| | | // 3. æ°å¢ææ´æ°ä¸»è¡¨ |
| | | if (purchaseLedger.getId() == null) { |
| | | purchaseLedgerMapper.insert(purchaseLedger); |
| | |
| | | for (SalesLedgerProduct product : products) { |
| | | try { |
| | | boolean processed; |
| | | if (Boolean.TRUE.equals(product.getIsChecked())) { |
| | | if (product.getProductType() != null && product.getProductType() == 2) { |
| | | processed = processPurchaseSparePart(purchaseLedger, product); |
| | | } else if (Boolean.TRUE.equals(product.getIsChecked())) { |
| | | processed = processPurchaseQualityProduct(purchaseLedger, product); |
| | | } else { |
| | | processed = processPurchaseDirectProduct(purchaseLedger, product); |
| | |
| | | detail.put("message", ex.getMessage()); |
| | | details.add(detail); |
| | | log.error("æ¹éæ¨è¿éè´å°è´¦å¤±è´¥, purchaseLedgerId={}", id, ex); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°æ¶è´§ç¶æ |
| | | List<Long> processedIds = details.stream() |
| | | .filter(d -> "SUCCESS".equals(d.get("status")) || "PARTIAL".equals(d.get("status"))) |
| | | .map(d -> (Long) d.get("purchaseLedgerId")) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toList()); |
| | | if (!processedIds.isEmpty()) { |
| | | PurchaseLedgerDto statusQuery = new PurchaseLedgerDto(); |
| | | statusQuery.setIds(processedIds); |
| | | IPage<PurchaseLedgerDto> statusPage = this.selectPurchaseLedgerListPage( |
| | | new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(1, processedIds.size()), |
| | | statusQuery |
| | | ); |
| | | if (statusPage != null && CollectionUtils.isNotEmpty(statusPage.getRecords())) { |
| | | for (PurchaseLedgerDto dto : statusPage.getRecords()) { |
| | | PurchaseLedger update = new PurchaseLedger(); |
| | | update.setId(dto.getId()); |
| | | if ("å®å
¨å
¥åº".equals(dto.getStockInStatus())) { |
| | | update.setStatus(3); |
| | | } else if ("å
¥åºä¸".equals(dto.getStockInStatus())) { |
| | | update.setStatus(2); |
| | | } else { |
| | | update.setStatus(1); |
| | | } |
| | | purchaseLedgerMapper.updateById(update); |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | return hasApprovedStockRecord(stockRecords); |
| | | } |
| | | |
| | | private boolean processPurchaseSparePart(PurchaseLedger purchaseLedger, SalesLedgerProduct product) { |
| | | if (purchaseLedger == null || product == null || product.getProductModelId() == null) { |
| | | return false; |
| | | } |
| | | SpareParts spareParts = sparePartsMapper.selectById(product.getProductModelId()); |
| | | if (spareParts == null) { |
| | | return false; |
| | | } |
| | | BigDecimal newQty = spareParts.getQuantity() != null |
| | | ? spareParts.getQuantity().add(product.getQuantity()) |
| | | : product.getQuantity(); |
| | | spareParts.setQuantity(newQty); |
| | | sparePartsMapper.updateById(spareParts); |
| | | return true; |
| | | } |
| | | |
| | | private LocalDateTime toStartOfDayPlusDays(Date date, int days) { |
| | | if (date == null) { |
| | | return null; |
| | |
| | | if (productModelId != null && modelMap.containsKey(productModelId)) { |
| | | product.setSpecificationModel(modelMap.get(productModelId)); |
| | | } |
| | | |
| | | if (product.getProductType() != null && product.getProductType() == 2) { |
| | | SpareParts spareParts = sparePartsMapper.selectById(productModelId); |
| | | if (spareParts != null) { |
| | | product.setProductCategory(spareParts.getName()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | // åç»å¤ç |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ¹éå¿«éæ£éªï¼ä¸é®éè¿å¹¶æäº¤ |
| | | */ |
| | | @PostMapping("/batchQuickInspect") |
| | | @Operation(summary = "æ¹éå¿«éæ£éª") |
| | | @Log(title = "æ¹éå¿«éæ£éª", businessType = BusinessType.OTHER) |
| | | public R<?> batchQuickInspect(@RequestBody List<Long> ids) { |
| | | return qualityInspectService.batchQuickInspect(ids); |
| | | } |
| | | |
| | | /** |
| | | * ä¸è½½ |
| | | * |
| | | * @param response |
| | |
| | | private Long purchaseLedgerId; |
| | | |
| | | /** |
| | | * éå®å°è´¦idï¼åºåæ£éªï¼ |
| | | */ |
| | | private Long salesLedgerId; |
| | | |
| | | /** |
| | | * æ¥å·¥id |
| | | */ |
| | | private Long productMainId; |
| | |
| | | import com.ruoyi.quality.pojo.QualityInspect; |
| | | |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import java.util.List; |
| | | |
| | | public interface IQualityInspectService extends IService<QualityInspect> { |
| | | |
| | |
| | | |
| | | R autoSubmit(Long id); |
| | | |
| | | /** |
| | | * æ¹éå¿«éæ£éªï¼ä¸é®éè¿å¹¶æäº¤ |
| | | */ |
| | | R batchQuickInspect(List<Long> ids); |
| | | |
| | | void down(HttpServletResponse response, QualityInspect qualityInspect); |
| | | } |
| | |
| | | return rows > 0 ? R.ok("æ£éªåæäº¤æå") : R.fail("æ£éªåæäº¤å¤±è´¥"); |
| | | } |
| | | |
| | | @Override |
| | | public R batchQuickInspect(List<Long> ids) { |
| | | if (ids == null || ids.isEmpty()) { |
| | | return R.fail("è¯·éæ©è³å°ä¸æ¡æ£éªå"); |
| | | } |
| | | int success = 0; |
| | | int fail = 0; |
| | | for (Long id : ids) { |
| | | R result = autoSubmit(id); |
| | | if (R.isSuccess(result)) { |
| | | success++; |
| | | } else { |
| | | fail++; |
| | | } |
| | | } |
| | | return R.ok(String.format("å¿«éæ£éªå®æï¼æå %d æ¡ï¼å¤±è´¥ %d æ¡", success, fail)); |
| | | } |
| | | |
| | | private String resolveProductionBatchNo(Long productionProductMainId, |
| | | Long qualityInspectId, |
| | | Long productModelId) { |
| | |
| | | //åè´§æ°é |
| | | private BigDecimal totalQuantity; |
| | | |
| | | //éè´ååå· |
| | | private String purchaseContractNumber; |
| | | |
| | | private Long templateId; |
| | | |
| | | private String templateName; |
| | |
| | | @TableField(exist = false) |
| | | private Boolean hasProductionRecord; |
| | | |
| | | @Schema(description = "éè´å°è´¦id") |
| | | private Long purchaseLedgerId; |
| | | |
| | | } |
| | | |
| | |
| | | //é对éå®å°è´¦ï¼æ¯å¦ç产 |
| | | private Boolean isProduction; |
| | | |
| | | @Schema(description = "产åç±»å 1-产å 2-设å¤å¤ä»¶") |
| | | private Integer productType; |
| | | |
| | | @TableField(exist = false) |
| | | @Schema(description = "å¾
åè´§æ°é") |
| | | private BigDecimal noQuantity; |
| | |
| | | @Excel(name = "客æ·åç§°") |
| | | private String customerName; |
| | | |
| | | @TableField(exist = false) |
| | | @Schema(description = "客æ·id") |
| | | private Long customerId; |
| | | |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Long id; |
| | | |
| | |
| | | |
| | | import com.ruoyi.basic.dto.StorageBlobVO; |
| | | import com.ruoyi.sales.pojo.SalesLedger; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.util.List; |
| | |
| | | public class SalesLedgerVo extends SalesLedger { |
| | | |
| | | private List<StorageBlobVO> storageBlobVOs; |
| | | |
| | | @Schema(description = "éè´ååå·") |
| | | private String purchaseContractNumber; |
| | | } |
| | |
| | | stockInRecordDto.setBatchNo(stockInventoryDto.getBatchNo()); |
| | | stockInRecordDto.setProductModelId(stockInventoryDto.getProductModelId()); |
| | | stockInRecordDto.setType("0"); |
| | | stockInRecordDto.setCreateTime(stockInventoryDto.getCreateTime()); |
| | | stockInRecordService.add(stockInRecordDto); |
| | | //åè¿è¡æ°å¢åºåæ°éåºå |
| | | //å
æ¥è¯¢åºå表ä¸çäº§åæ¯å¦åå¨ï¼ä¸å卿°å¢ï¼å卿´æ° |
| | |
| | | stockInRecordDto.setType("0"); |
| | | stockInRecordDto.setRemark(stockInventoryDto.getRemark()); |
| | | stockInRecordDto.setWarnNum(stockInventoryDto.getWarnNum()); |
| | | stockInRecordDto.setCreateTime(stockInventoryDto.getCreateTime()); |
| | | stockInRecordService.add(stockInRecordDto); |
| | | return true; |
| | | } |
| | |
| | | stockInRecordDto.setBatchNo(stockUninventoryDto.getBatchNo()); |
| | | stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId()); |
| | | stockInRecordDto.setType("1"); |
| | | stockInRecordDto.setCreateTime(stockUninventoryDto.getCreateTime()); |
| | | stockInRecordService.add(stockInRecordDto); |
| | | //审æ¹åæ·»å |
| | | return 1; |
| | |
| | | stockInRecordDto.setProductModelId(stockUninventoryDto.getProductModelId()); |
| | | stockInRecordDto.setType("1"); |
| | | stockInRecordDto.setRemark(stockUninventoryDto.getRemark()); |
| | | stockInRecordDto.setCreateTime(stockUninventoryDto.getCreateTime()); |
| | | stockInRecordService.add(stockInRecordDto); |
| | | return 1; |
| | | } |
| | |
| | | "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> |
| | | <mapper namespace="com.ruoyi.measuringinstrumentledger.mapper.SparePartsMapper"> |
| | | <select id="listPage" resultType="com.ruoyi.measuringinstrumentledger.dto.SparePartsDto"> |
| | | select sp.*,sp1.name as parentName |
| | | select sp.*,sp1.name as parentName, su.nick_name as notifyPersonName |
| | | from spare_parts sp |
| | | left join spare_parts sp1 on sp1.id = sp.parent_id |
| | | left join sys_user su on su.user_id = sp.notify_person_id |
| | | <where> |
| | | <if test="spareParts.name != null and spareParts.name != ''"> |
| | | and sp.name like concat('%',#{spareParts.name},'%') |
| | |
| | | pl.approve_user_ids, |
| | | sm.is_white, |
| | | pl.approval_status, |
| | | pl.status, |
| | | pl.payment_method, |
| | | pl.remarks, |
| | | CASE |
| | |
| | | </when> |
| | | <otherwise> |
| | | pot.work_order_no, |
| | | po_sales.sales_contract_no |
| | | COALESCE(sl.sales_contract_no, po_sales.sales_contract_no) as sales_contract_no |
| | | </otherwise> |
| | | </choose> |
| | | FROM |
| | |
| | | <otherwise> |
| | | LEFT JOIN production_product_main ppm ON qi.product_main_id = ppm.id |
| | | LEFT JOIN production_operation_task pot ON ppm.production_operation_task_id = pot.id |
| | | LEFT JOIN sales_ledger sl ON sl.id = qi.sales_ledger_id |
| | | left join production_order po ON po.id = pot.production_order_id |
| | | left join ( |
| | | select po2.id as order_id, |
| | |
| | | AND pot.work_order_no like concat('%',#{qualityInspect.workOrderNo},'%') |
| | | </if> |
| | | <if test="qualityInspect.salesContractNo != null and qualityInspect.salesContractNo != '' "> |
| | | AND po_sales.sales_contract_no like concat('%',#{qualityInspect.salesContractNo},'%') |
| | | AND (sl.sales_contract_no like concat('%',#{qualityInspect.salesContractNo},'%') |
| | | OR po_sales.sales_contract_no like concat('%',#{qualityInspect.salesContractNo},'%')) |
| | | </if> |
| | | ORDER BY qi.check_time DESC |
| | | </select> |
| | |
| | | T1.payment_method, |
| | | T1.delivery_date, |
| | | DATEDIFF(T1.delivery_date, CURDATE()) AS delivery_days_diff, |
| | | IFNULL(shipping_status_counts.is_all_shipped, FALSE) AS is_fh |
| | | IFNULL(shipping_status_counts.is_all_shipped, FALSE) AS is_fh, |
| | | T3.purchase_contract_number |
| | | FROM sales_ledger T1 |
| | | LEFT JOIN sys_user T2 ON T1.entry_person = T2.user_id |
| | | LEFT JOIN ( |
| | |
| | | FROM shipping_info |
| | | GROUP BY sales_ledger_id |
| | | ) shipping_status_counts ON T1.id = shipping_status_counts.sales_ledger_id |
| | | LEFT JOIN purchase_ledger T3 ON T1.purchase_ledger_id = T3.id |
| | | |
| | | <where> |
| | | <if test="salesLedgerDto.customerName != null and salesLedgerDto.customerName != '' "> |
| | |
| | | p.product_name, |
| | | sl.customer_name, |
| | | spd.totalQuantity, |
| | | sor.outboundBatches |
| | | sor.outboundBatches, |
| | | pl.purchase_contract_number |
| | | FROM shipping_info s |
| | | LEFT JOIN (select shipping_info_id,sum(quantity) totalQuantity from shipping_product_detail GROUP BY shipping_info_id) spd ON spd.shipping_info_id = s.id |
| | | LEFT JOIN sales_ledger sl ON s.sales_ledger_id = sl.id |
| | | LEFT JOIN purchase_ledger pl ON sl.purchase_ledger_id = pl.id |
| | | LEFT JOIN sales_ledger_product slp ON s.sales_ledger_product_id = slp.id and slp.type = 1 |
| | | left join product_model pm on slp.product_model_id = pm.id |
| | | left join product p on pm.product_id = p.id |
| | |
| | | <if test="req.expressNumber != null and req.expressNumber != ''"> |
| | | AND s.express_number LIKE CONCAT('%',#{req.expressNumber},'%') |
| | | </if> |
| | | <if test="req.customerId != null"> |
| | | AND sl.customer_id = #{req.customerId} |
| | | </if> |
| | | order by create_time DESC |
| | | </select> |
| | | <select id="listAll" resultType="com.ruoyi.sales.pojo.ShippingInfo"> |