Merge remote-tracking branch 'origin/dev_天津_建诚恒商贸' into dev_天津_建诚恒商贸
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | -- æ°éåæ®µç»ä¸ä¿ç 8 ä½å°æ°ï¼decimal(20, 8)ï¼æ´æ°ä½ä¿ç 12 ä½ï¼ |
| | | -- æ¶ååè½ï¼ |
| | | -- 1. 产åç»æï¼BOMï¼åä½äº§åºæéæ°éï¼äº§åç»æè¯¦æ
ãç¼è¾å¼¹çªï¼ |
| | | -- 2. ç产订å-å·¥èºè·¯çº¿ BOM ç»æåä½äº§åºæéæ°é |
| | | -- 3. ç产订å-颿æ°éï¼é¢æå°è´¦å¼¹çªï¼ |
| | | -- 4. åºåé¾è·¯ï¼é¢ææ£ååºåãåºåº/å
¥åºè®°å½ãåæ ¼/ä¸åæ ¼åºåã订åé宿°éï¼ |
| | | |
| | | -- ---------------------------- |
| | | -- BOM ç»æè¡¨ |
| | | -- ---------------------------- |
| | | ALTER TABLE `technology_bom_structure` |
| | | MODIFY COLUMN `unit_quantity` decimal(20, 8) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é'; |
| | | |
| | | ALTER TABLE `production_bom_structure` |
| | | MODIFY COLUMN `unit_quantity` decimal(20, 8) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é'; |
| | | |
| | | -- ---------------------------- |
| | | -- é¢æè¡¨ï¼production_order_pick.quantity åé¢ç¨æ°éï¼ |
| | | -- ---------------------------- |
| | | ALTER TABLE `production_order_pick` |
| | | MODIFY COLUMN `quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é'; |
| | | |
| | | ALTER TABLE `production_order_pick_record` |
| | | MODIFY COLUMN `pick_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿æ°é', |
| | | MODIFY COLUMN `before_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿忰é', |
| | | MODIFY COLUMN `after_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿åå©ä½æ°é'; |
| | | |
| | | -- ---------------------------- |
| | | -- åºåé¾è·¯è¡¨ |
| | | -- ---------------------------- |
| | | ALTER TABLE `stock_inventory` |
| | | MODIFY COLUMN `qualitity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | MODIFY COLUMN `locked_quantity` decimal(20, 8) NULL DEFAULT 0.00000000 COMMENT '被订åé宿°é'; |
| | | |
| | | ALTER TABLE `stock_uninventory` |
| | | MODIFY COLUMN `qualitity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é'; |
| | | |
| | | ALTER TABLE `stock_in_record` |
| | | MODIFY COLUMN `stock_in_num` decimal(20, 8) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é'; |
| | | |
| | | ALTER TABLE `stock_out_record` |
| | | MODIFY COLUMN `stock_out_num` decimal(20, 8) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é'; |
| | |
| | | `product_model_id` bigint NOT NULL COMMENT '产åè§æ ¼id', |
| | | `technology_operation_id` bigint NULL DEFAULT NULL COMMENT 'å·¥åºid', |
| | | `production_order_bom_id` bigint NULL DEFAULT NULL COMMENT 'ç产订åBOMid', |
| | | `unit_quantity` decimal(16, 4) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é', |
| | | `unit_quantity` decimal(20, 8) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é', |
| | | `demanded_quantity` decimal(16, 4) NULL DEFAULT NULL COMMENT 'éæ±æ°é', |
| | | `unit` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'åä½', |
| | | `create_user` bigint NULL DEFAULT NULL COMMENT 'å建人ID', |
| | |
| | | CREATE TABLE `production_order_pick` ( |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®id', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT '产åè§æ ¼id', |
| | | `quantity` decimal(16, 2) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `create_time` timestamp NULL DEFAULT NULL, |
| | | `update_time` timestamp NULL DEFAULT NULL COMMENT 'æ´æ°æ¶é´', |
| | |
| | | `production_operation_task_id` bigint NULL DEFAULT 0 COMMENT 'ç产工åid', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT '产åè§æ ¼id', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `pick_quantity` decimal(16, 4) NULL DEFAULT NULL COMMENT '颿æ°é', |
| | | `before_quantity` decimal(16, 4) NULL DEFAULT NULL COMMENT '颿忰é', |
| | | `after_quantity` decimal(16, 4) NULL DEFAULT NULL COMMENT '颿åå©ä½æ°é', |
| | | `pick_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿æ°é', |
| | | `before_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿忰é', |
| | | `after_quantity` decimal(20, 8) NULL DEFAULT NULL COMMENT '颿åå©ä½æ°é', |
| | | `pick_type` tinyint NULL DEFAULT 1 COMMENT 'é¢æç±»åï¼1æ£å¸¸é¢æ 2è¡¥æ', |
| | | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '夿³¨', |
| | | `create_time` datetime NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'å建æ¶é´', |
| | |
| | | `id` int NOT NULL AUTO_INCREMENT, |
| | | `inbound_batches` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'å
¥åºæ¹æ¬¡', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `stock_in_num` decimal(16, 4) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é', |
| | | `stock_in_num` decimal(20, 8) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é', |
| | | `record_id` int NULL DEFAULT NULL COMMENT 'å
¥åºæ¥æºid', |
| | | `record_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'å
¥åºç±»å', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT '产åè§æ ¼id', |
| | |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®id', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT 'è§æ ¼id', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `qualitity` decimal(16, 4) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `qualitity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `create_time` timestamp NULL DEFAULT NULL, |
| | | `update_time` timestamp NULL DEFAULT NULL COMMENT 'æ´æ°æ¶é´', |
| | | `version` int NULL DEFAULT NULL COMMENT 'çæ¬å·', |
| | | `locked_quantity` decimal(16, 4) NULL DEFAULT 0.0000 COMMENT '被订åé宿°é', |
| | | `locked_quantity` decimal(20, 8) NULL DEFAULT 0.00000000 COMMENT '被订åé宿°é', |
| | | `warn_num` decimal(16, 4) NULL DEFAULT NULL COMMENT 'é¢è¦æ°é', |
| | | `remark` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '夿³¨', |
| | | `create_user` bigint NULL DEFAULT NULL COMMENT 'å建人ID', |
| | |
| | | `id` int NOT NULL AUTO_INCREMENT, |
| | | `outbound_batches` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'å
¥åºæ¹æ¬¡', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `stock_out_num` decimal(16, 4) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é', |
| | | `stock_out_num` decimal(20, 8) NULL DEFAULT NULL COMMENT 'å
¥åºæ°é', |
| | | `record_id` int NULL DEFAULT NULL COMMENT 'å
¥åºæ¥æºid', |
| | | `record_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'å
¥åºç±»å', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT '产åè§æ ¼id', |
| | |
| | | `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主é®id', |
| | | `product_model_id` int NULL DEFAULT NULL COMMENT 'è§æ ¼id', |
| | | `batch_no` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'æ¹å·', |
| | | `qualitity` decimal(16, 4) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `qualitity` decimal(20, 8) NULL DEFAULT NULL COMMENT 'æ°é', |
| | | `create_time` timestamp NULL DEFAULT NULL, |
| | | `update_time` timestamp NULL DEFAULT NULL COMMENT 'æ´æ°æ¶é´', |
| | | `version` int NULL DEFAULT NULL COMMENT 'çæ¬å·', |
| | |
| | | `parent_id` bigint NULL DEFAULT NULL COMMENT 'ç¶èç¹ID', |
| | | `product_model_id` bigint NOT NULL COMMENT '产åid', |
| | | `operation_id` bigint NULL DEFAULT NULL COMMENT 'å·¥åºid', |
| | | `unit_quantity` decimal(16, 4) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é', |
| | | `unit_quantity` decimal(20, 8) NOT NULL COMMENT 'åä½äº§åºéè¦æ°é', |
| | | `demanded_quantity` decimal(16, 4) NULL DEFAULT NULL COMMENT 'éæ±æ°é', |
| | | `unit` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT 'åä½', |
| | | `bom_id` bigint NOT NULL COMMENT 'bomçid', |
| | |
| | | |
| | | @Override |
| | | public IPage<AfterSalesServiceNewDto> listPage(Page page, AfterSalesServiceNewDto afterSalesService) { |
| | | Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | SysDept sysDept = sysDeptMapper.selectDeptById(tenantId); |
| | | //Long tenantId = SecurityUtils.getLoginUser().getTenantId(); |
| | | //SysDept sysDept = sysDeptMapper.selectDeptById(tenantId); |
| | | IPage<AfterSalesServiceNewDto> afterSalesServiceIPage = afterSalesServiceMapper.listPage(page, afterSalesService); |
| | | afterSalesServiceIPage.getRecords().forEach(item -> { |
| | | item.setDeptName(sysDept.getDeptName()); |
| | | }); |
| | | //afterSalesServiceIPage.getRecords().forEach(item -> { |
| | | // item.setDeptName(sysDept.getDeptName()); |
| | | //}); |
| | | return afterSalesServiceIPage; |
| | | } |
| | | |
| | |
| | | import dev.langchain4j.store.embedding.pinecone.PineconeServerlessIndexConfig; |
| | | import io.pinecone.clients.Index; |
| | | import io.pinecone.clients.Pinecone; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Value; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Configuration; |
| | | |
| | | import java.io.IOException; |
| | | import java.util.function.Supplier; |
| | | |
| | | /** |
| | | * åéåå¨é
ç½® |
| | | */ |
| | | @Slf4j |
| | | @Configuration |
| | | public class EmbeddingStoreConfig { |
| | | |
| | | /** Pinecone è¿æ¥éè¯æ¬¡æ°ï¼æé æä¼åæ¥åèµ· HTTP/2 æ¡æï¼å¶å "Required SETTINGS preface not received" */ |
| | | private static final int CONNECT_ATTEMPTS = 3; |
| | | |
| | | /** éè¯é´éåºæ°ï¼æ¯«ç§ï¼ï¼ææ¬¡æ°çº¿æ§éé¿ */ |
| | | private static final long RETRY_BACKOFF_MILLIS = 1500L; |
| | | |
| | | @Value("${pinecone.api-key:pcsk_4SJLnh_tNB3wSLJU8tc4E5P28PcXX8eCLdURqZpVhg1FMV8CRYxjneWdzqRdB5Ftqooi9}") |
| | | private String pineconeApiKey; |
| | |
| | | |
| | | @Bean |
| | | public Index pineconeIndex(Pinecone pinecone) { |
| | | return pinecone.getIndexConnection(indexName); |
| | | return retry("è·å Pinecone ç´¢å¼è¿æ¥", () -> pinecone.getIndexConnection(indexName)); |
| | | } |
| | | |
| | | @Bean |
| | | public EmbeddingStore<TextSegment> embeddingStore(EmbeddingModel embeddingModel) { |
| | | return PineconeEmbeddingStore.builder() |
| | | return retry("åå§å Pinecone åéåå¨", () -> PineconeEmbeddingStore.builder() |
| | | .apiKey(pineconeApiKey) |
| | | .index(indexName) |
| | | .nameSpace(namespace) |
| | |
| | | .region("us-east-1") |
| | | .dimension(embeddingModel.dimension()) |
| | | .build()) |
| | | .build(); |
| | | .build()); |
| | | } |
| | | |
| | | /** |
| | | * 对 Pinecone å¯å¨æè¿æ¥åæé次éè¯ã |
| | | * <p> |
| | | * Pinecone 客æ·ç«¯åºå®èµ° HTTP/2ï¼æé EmbeddingStore / è·åç´¢å¼è¿æ¥æ¶ä¼åæ¥è°ç¨æ§å¶é¢æ¥å£ï¼ |
| | | * å¶åæ¡æå¤±è´¥ï¼java.io.IOException: Required SETTINGS preface not receivedï¼ä¼ä»¥è¿è¡æ¶å¼å¸¸æåºï¼ |
| | | * ç´æ¥å¯¼è´æ´ä¸ª ApplicationContext å 载失败ãè¿éä»
对è¿ç±»ç¬æ¶ç½ç»å¼å¸¸éè¯ï¼å
¶å®å¼å¸¸ç«å³æåºã |
| | | */ |
| | | private <T> T retry(String action, Supplier<T> supplier) { |
| | | RuntimeException last = null; |
| | | for (int attempt = 1; attempt <= CONNECT_ATTEMPTS; attempt++) { |
| | | try { |
| | | return supplier.get(); |
| | | } catch (RuntimeException e) { |
| | | if (!isTransientConnectFailure(e) || attempt == CONNECT_ATTEMPTS) { |
| | | throw e; |
| | | } |
| | | last = e; |
| | | log.warn("{}失败ï¼ç¬¬ {}/{} 次ï¼ï¼{}ms åéè¯ï¼{}", |
| | | action, attempt, CONNECT_ATTEMPTS, RETRY_BACKOFF_MILLIS * attempt, rootMessage(e)); |
| | | sleep(RETRY_BACKOFF_MILLIS * attempt); |
| | | } |
| | | } |
| | | throw last; |
| | | } |
| | | |
| | | /** 沿 cause é¾å¤ææ¯å¦ä¸º HTTP/2 æ¡æç±»çç¬æ¶è¿æ¥å¤±è´¥ */ |
| | | private boolean isTransientConnectFailure(Throwable e) { |
| | | for (Throwable t = e; t != null; t = t.getCause()) { |
| | | if (t instanceof IOException) { |
| | | return true; |
| | | } |
| | | String message = t.getMessage(); |
| | | if (message != null && (message.contains("SETTINGS preface") |
| | | || message.contains("Connection reset") |
| | | || message.contains("timed out"))) { |
| | | return true; |
| | | } |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | private String rootMessage(Throwable e) { |
| | | Throwable root = e; |
| | | while (root.getCause() != null && root.getCause() != root) { |
| | | root = root.getCause(); |
| | | } |
| | | return root.getMessage(); |
| | | } |
| | | |
| | | private void sleep(long millis) { |
| | | try { |
| | | Thread.sleep(millis); |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.ruoyi.basic.dto.ProductDto; |
| | | import com.ruoyi.basic.dto.ProductModelDto; |
| | | import com.ruoyi.basic.dto.ProductModelExportDto; |
| | | import com.ruoyi.basic.dto.ProductTreeDto; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.service.IProductModelService; |
| | | import com.ruoyi.basic.service.IProductService; |
| | | import com.ruoyi.basic.vo.ProductModelVo; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Log; |
| | | import com.ruoyi.framework.aspectj.lang.enums.BusinessType; |
| | | import com.ruoyi.framework.web.controller.BaseController; |
| | |
| | | */ |
| | | @PostMapping("/import") |
| | | @Log(title = "导å
¥äº§å", businessType = BusinessType.IMPORT) |
| | | public AjaxResult importProductModel(@RequestParam("file") MultipartFile file, Integer productId) { |
| | | return productModelService.importProductModel(file, productId); |
| | | public AjaxResult importProductModel(@RequestParam("file") MultipartFile file) { |
| | | return productModelService.importProductModel(file); |
| | | } |
| | | |
| | | /** |
| | |
| | | @Operation(summary = "产å导å
¥æ¨¡æ¿") |
| | | @Log(title = "产å导å
¥æ¨¡æ¿", businessType = BusinessType.EXPORT) |
| | | public void importProduct(HttpServletResponse response) { |
| | | ExcelUtil<ProductModelExportDto> excelUtil = new ExcelUtil<>(ProductModelExportDto.class); |
| | | excelUtil.importTemplateExcel(response, "产åè§æ ¼å¯¼å
¥æ¨¡æ¿"); |
| | | productService.exportImportTemplate(response); |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.basic.dto; |
| | | |
| | | import com.ruoyi.framework.aspectj.lang.annotation.Excel; |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * äº§åæ¹é导å
¥è¡ï¼ä¸ä¸ªsheetï¼åæ/åæå/æåï¼ |
| | | */ |
| | | @Data |
| | | public class ProductImportRowDto { |
| | | |
| | | @Excel(name = "产åç¶ç±»") |
| | | private String productParentName; |
| | | |
| | | @Excel(name = "产å大类") |
| | | private String productCategoryName; |
| | | |
| | | @Excel(name = "产ååç§°") |
| | | private String productName; |
| | | |
| | | @Excel(name = "产åç¼ç ") |
| | | private String productCode; |
| | | |
| | | @Excel(name = "è§æ ¼åå·") |
| | | private String model; |
| | | |
| | | @Excel(name = "åä½") |
| | | private String unit; |
| | | } |
| | |
| | | */ |
| | | IPage<ProductModel> modelListPage(Page page , ProductDto productDto); |
| | | |
| | | AjaxResult importProductModel(MultipartFile file, Integer productId); |
| | | AjaxResult importProductModel(MultipartFile file); |
| | | } |
| | |
| | | import com.ruoyi.basic.pojo.Product; |
| | | import com.ruoyi.basic.pojo.ProductModel; |
| | | import com.ruoyi.basic.vo.ProductModelVo; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | |
| | | import java.util.List; |
| | | |
| | |
| | | List<ProductTreeDto> selectProductList(ProductDto productDto); |
| | | |
| | | IPage<ProductModelVo> listPageProductModel(Page<ProductModelVo> page, ProductModel productModel); |
| | | |
| | | void exportImportTemplate(HttpServletResponse response); |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.plugins.pagination.Page; |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.basic.dto.ProductDto; |
| | | import com.ruoyi.basic.dto.ProductImportRowDto; |
| | | import com.ruoyi.basic.dto.ProductModelDto; |
| | | import com.ruoyi.basic.mapper.ProductMapper; |
| | | import com.ruoyi.basic.mapper.ProductModelMapper; |
| | |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import com.ruoyi.common.utils.poi.ExcelUtil; |
| | | import com.ruoyi.framework.web.domain.AjaxResult; |
| | | import com.ruoyi.sales.dto.LossProductModelDto; |
| | | import com.ruoyi.sales.mapper.SalesLedgerProductMapper; |
| | | import com.ruoyi.sales.pojo.SalesLedgerProduct; |
| | | import com.ruoyi.technology.mapper.TechnologyBomMapper; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Set; |
| | | import java.util.stream.Collectors; |
| | | import java.util.concurrent.ThreadLocalRandom; |
| | | |
| | | /** |
| | | * ã请填ååè½åç§°ãServiceä¸å¡å±å¤ç |
| | |
| | | private final SalesLedgerProductMapper salesLedgerProductMapper; |
| | | private final TechnologyBomMapper technologyBomMapper; |
| | | private ProductModelMapper productModelMapper; |
| | | |
| | | private static final List<String> IMPORT_SHEET_NAMES = Arrays.asList("åææ", "åæ", "åæå", "æå"); |
| | | |
| | | @Override |
| | | public int addOrEditProductModel(ProductModelDto productModelDto) { |
| | |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public AjaxResult importProductModel(MultipartFile file, Integer productId) { |
| | | if (productId == null) { |
| | | return AjaxResult.error("请å
éæ©äº§åå导å
¥è§æ ¼åå·"); |
| | | public AjaxResult importProductModel(MultipartFile file) { |
| | | if (file == null || file.isEmpty()) { |
| | | return AjaxResult.error("è¯·éæ©è¦å¯¼å
¥çæä»¶"); |
| | | } |
| | | |
| | | Product product = productMapper.selectById(productId); |
| | | if (product == null) { |
| | | return AjaxResult.error("éæ©ç产åä¸åå¨"); |
| | | } |
| | | |
| | | Map<String, List<ProductImportRowDto>> sheetMap; |
| | | try { |
| | | ExcelUtil<ProductModel> productModelExcelUtil = new ExcelUtil<>(ProductModel.class); |
| | | List<ProductModel> productModelList = productModelExcelUtil.importExcel(file.getInputStream()); |
| | | |
| | | if (CollectionUtils.isEmpty(productModelList)) { |
| | | return AjaxResult.error("导å
¥æ°æ®ä¸è½ä¸ºç©º"); |
| | | ExcelUtil<ProductImportRowDto> excelUtil = new ExcelUtil<>(ProductImportRowDto.class); |
| | | sheetMap = excelUtil.importExcelMultiSheet(IMPORT_SHEET_NAMES, file.getInputStream(), 0); |
| | | } catch (Exception e) { |
| | | log.error("è§£æäº§å导å
¥æä»¶å¼å¸¸", e); |
| | | throw new ServiceException("产å导å
¥æä»¶è§£æå¤±è´¥"); |
| | | } |
| | | if (sheetMap.isEmpty()) { |
| | | return AjaxResult.error("æªæ¾å° [åæ/åæå/æå] å·¥ä½è¡¨ï¼ææä»¶ä¸æ²¡ææ°æ®"); |
| | | } |
| | | |
| | | // è·åå½å产å䏿æçè§æ ¼åå·å |
| | | List<ProductModel> existingModels = list(new LambdaQueryWrapper<ProductModel>().eq(ProductModel::getProductId, productId)); |
| | | Set<String> existingModelNames = existingModels.stream().map(ProductModel::getModel).collect(Collectors.toSet()); |
| | | |
| | | List<ProductModel> waitToSaveList = new ArrayList<>(); |
| | | int successCount = 0; |
| | | int skipCount = 0; |
| | | |
| | | for (int i = 0; i < productModelList.size(); i++) { |
| | | ProductModel item = productModelList.get(i); |
| | | Set<String> generatedCodes = new HashSet<>(); |
| | | for (String sheetName : IMPORT_SHEET_NAMES) { |
| | | List<ProductImportRowDto> rows = sheetMap.get(sheetName); |
| | | if (CollectionUtils.isEmpty(rows)) { |
| | | continue; |
| | | } |
| | | Long topId = findOrCreateTopProduct(sheetName); |
| | | Map<String, Long> nodeCache = new HashMap<>(); |
| | | Map<Long, Set<String>> codeCache = new HashMap<>(); |
| | | Map<Long, Set<String>> modelCache = new HashMap<>(); |
| | | for (int i = 0; i < rows.size(); i++) { |
| | | ProductImportRowDto row = rows.get(i); |
| | | int rowNum = i + 2; |
| | | |
| | | if (StringUtils.isEmpty(item.getProductCode())) { |
| | | return AjaxResult.error("第 " + rowNum + " è¡å¯¼å
¥å¤±è´¥: [产åç¼ç ] ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(item.getModel())) { |
| | | return AjaxResult.error("第 " + rowNum + " è¡å¯¼å
¥å¤±è´¥: [è§æ ¼åå·] ä¸è½ä¸ºç©º"); |
| | | } |
| | | if (StringUtils.isEmpty(item.getUnit())) { |
| | | return AjaxResult.error("第 " + rowNum + " è¡å¯¼å
¥å¤±è´¥: [åä½] ä¸è½ä¸ºç©º"); |
| | | String parentName = trimToNull(row.getProductParentName()); |
| | | String categoryName = trimToNull(row.getProductCategoryName()); |
| | | String productName = trimToNull(row.getProductName()); |
| | | if (productName == null) { |
| | | throw new ServiceException("第 " + rowNum + " è¡ [产ååç§°] ä¸è½ä¸ºç©º"); |
| | | } |
| | | |
| | | // å»é,妿已å
å«è¯¥åå·,åè·³è¿ |
| | | if (existingModelNames.contains(item.getModel())) { |
| | | String path = String.valueOf(topId); |
| | | Long currentParentId = topId; |
| | | if (parentName != null) { |
| | | path = path + ">" + parentName; |
| | | currentParentId = ensureChildNode(nodeCache, path, currentParentId, parentName); |
| | | } |
| | | if (categoryName != null) { |
| | | path = path + ">" + categoryName; |
| | | currentParentId = ensureChildNode(nodeCache, path, currentParentId, categoryName); |
| | | } |
| | | path = path + ">" + productName; |
| | | Long leafId = ensureChildNode(nodeCache, path, currentParentId, productName); |
| | | |
| | | String model = StringUtils.isEmpty(row.getModel()) ? "/" : row.getModel().trim(); |
| | | |
| | | // åä¸äº§åä¸åç§°ï¼äº§åèç¹ï¼+ åå·ç¸ååè·³è¿ |
| | | Set<String> models = modelCache.computeIfAbsent(leafId, this::loadProductModels); |
| | | if (!models.add(model)) { |
| | | skipCount++; |
| | | continue; |
| | | } |
| | | |
| | | item.setProductId(product.getId()); |
| | | waitToSaveList.add(item); |
| | | |
| | | existingModelNames.add(item.getModel()); |
| | | String code = trimToNull(row.getProductCode()); |
| | | if (code == null) { |
| | | code = generateUniqueCode(generatedCodes); |
| | | } |
| | | Set<String> codes = codeCache.computeIfAbsent(leafId, this::loadProductCodes); |
| | | if (!codes.add(code)) { |
| | | skipCount++; |
| | | continue; |
| | | } |
| | | |
| | | if (!waitToSaveList.isEmpty()) { |
| | | saveBatch(waitToSaveList); |
| | | ProductModel productModel = new ProductModel(); |
| | | productModel.setProductId(leafId); |
| | | productModel.setProductCode(code); |
| | | productModel.setModel(model); |
| | | productModel.setUnit(trimToNull(row.getUnit())); |
| | | productModelMapper.insert(productModel); |
| | | successCount++; |
| | | } |
| | | } |
| | | |
| | | if (skipCount == 0) { |
| | | return AjaxResult.success(String.format("æå导å
¥ %d æ¡æ°æ®", waitToSaveList.size())); |
| | | String message = skipCount > 0 |
| | | ? String.format("æå导å
¥ %d æ¡ï¼è·³è¿å·²åå¨ %d æ¡", successCount, skipCount) |
| | | : String.format("æå导å
¥ %d æ¡", successCount); |
| | | return AjaxResult.success(message); |
| | | } |
| | | |
| | | private Long findOrCreateTopProduct(String name) { |
| | | Product root = productMapper.selectOne(new LambdaQueryWrapper<Product>() |
| | | .isNull(Product::getParentId) |
| | | .eq(Product::getProductName, name) |
| | | .last("limit 1")); |
| | | if (root != null) { |
| | | return root.getId(); |
| | | } |
| | | Product product = new Product(); |
| | | product.setProductName(name); |
| | | productMapper.insert(product); |
| | | return product.getId(); |
| | | } |
| | | |
| | | private Long ensureChildNode(Map<String, Long> nodeCache, String path, Long parentId, String name) { |
| | | Long id = nodeCache.get(path); |
| | | if (id != null) { |
| | | return id; |
| | | } |
| | | Product existing = productMapper.selectOne(new LambdaQueryWrapper<Product>() |
| | | .eq(Product::getParentId, parentId) |
| | | .eq(Product::getProductName, name) |
| | | .last("limit 1")); |
| | | if (existing != null) { |
| | | nodeCache.put(path, existing.getId()); |
| | | return existing.getId(); |
| | | } |
| | | Product product = new Product(); |
| | | product.setParentId(parentId); |
| | | product.setProductName(name); |
| | | productMapper.insert(product); |
| | | nodeCache.put(path, product.getId()); |
| | | return product.getId(); |
| | | } |
| | | |
| | | private Set<String> loadProductCodes(Long productId) { |
| | | List<ProductModel> list = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>() |
| | | .eq(ProductModel::getProductId, productId)); |
| | | Set<String> codes = new HashSet<>(); |
| | | for (ProductModel productModel : list) { |
| | | if (productModel.getProductCode() != null) { |
| | | codes.add(productModel.getProductCode().trim()); |
| | | } |
| | | } |
| | | return codes; |
| | | } |
| | | |
| | | private Set<String> loadProductModels(Long productId) { |
| | | List<ProductModel> list = productModelMapper.selectList(new LambdaQueryWrapper<ProductModel>() |
| | | .eq(ProductModel::getProductId, productId)); |
| | | Set<String> models = new HashSet<>(); |
| | | for (ProductModel productModel : list) { |
| | | if (StringUtils.isEmpty(productModel.getModel())) { |
| | | models.add("/"); |
| | | } else { |
| | | return AjaxResult.success(String.format("æå导å
¥ %d æ¡ï¼è·³è¿å·²å卿°æ® %d æ¡", waitToSaveList.size(), skipCount)); |
| | | models.add(productModel.getModel().trim()); |
| | | } |
| | | } catch (Exception e) { |
| | | log.error("导å
¥äº§åè§æ ¼å¼å¸¸", e); |
| | | throw new ServiceException("导å
¥å¤±è´¥"); |
| | | } |
| | | return models; |
| | | } |
| | | |
| | | private String generateUniqueCode(Set<String> generatedCodes) { |
| | | for (int i = 0; i < 200; i++) { |
| | | String code = randomCode(5); |
| | | if (generatedCodes.contains(code)) { |
| | | continue; |
| | | } |
| | | Long count = productModelMapper.selectCount(new LambdaQueryWrapper<ProductModel>() |
| | | .eq(ProductModel::getProductCode, code)); |
| | | if (count == null || count == 0) { |
| | | generatedCodes.add(code); |
| | | return code; |
| | | } |
| | | } |
| | | throw new ServiceException("çæå¯ä¸äº§åç¼ç 失败ï¼è¯·éè¯"); |
| | | } |
| | | |
| | | private static String randomCode(int length) { |
| | | String chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789"; |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (int i = 0; i < length; i++) { |
| | | sb.append(chars.charAt(ThreadLocalRandom.current().nextInt(chars.length()))); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | private static String trimToNull(String value) { |
| | | if (value == null) { |
| | | return null; |
| | | } |
| | | String trimmed = value.trim(); |
| | | return trimmed.isEmpty() ? null : trimmed; |
| | | } |
| | | } |
| | |
| | | import com.ruoyi.basic.vo.ProductModelVo; |
| | | import com.ruoyi.common.utils.StringUtils; |
| | | import com.ruoyi.common.utils.bean.BeanUtils; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.io.FileNotFoundException; |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.io.OutputStream; |
| | | import java.net.URLEncoder; |
| | | import java.util.ArrayList; |
| | | import java.util.Arrays; |
| | | import java.util.List; |
| | | |
| | | @Service |
| | | @AllArgsConstructor |
| | | @Slf4j |
| | | public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService { |
| | | |
| | | private ProductMapper productMapper; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void exportImportTemplate(HttpServletResponse response) { |
| | | String templatePath = "static/产å导å
¥æ¨¡æ¿.xlsx"; |
| | | try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(templatePath)) { |
| | | if (inputStream == null) { |
| | | throw new FileNotFoundException("æ¨¡æ¿æä»¶ä¸åå¨ï¼" + templatePath); |
| | | } |
| | | response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"); |
| | | response.setCharacterEncoding("utf-8"); |
| | | String fileName = URLEncoder.encode("产å导å
¥æ¨¡æ¿.xlsx", "utf-8").replaceAll("\\+", "%20"); |
| | | response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName); |
| | | try (OutputStream outputStream = response.getOutputStream()) { |
| | | byte[] buffer = new byte[1024]; |
| | | int len; |
| | | while ((len = inputStream.read(buffer)) > 0) { |
| | | outputStream.write(buffer, 0, len); |
| | | } |
| | | outputStream.flush(); |
| | | } |
| | | } catch (IOException e) { |
| | | log.error("导åºäº§å导å
¥æ¨¡æ¿å¤±è´¥", e); |
| | | try { |
| | | response.getWriter().write("模æ¿å¯¼åºå¤±è´¥ï¼" + e.getMessage()); |
| | | } catch (IOException ex) { |
| | | log.error("ååºè¾åºé误", ex); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public int delProductByIds(Long[] ids) { |
| | | // 1. å é¤å表 product_model ä¸å
³èçæ°æ® |
| | | LambdaQueryWrapper<ProductModel> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.in(ProductModel::getProductId, ids); |
| | | productModelMapper.delete(queryWrapper); |
| | | |
| | | // 2. å é¤ä¸»è¡¨ product æ°æ® |
| | | int deleteCount = productMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | |
| | | return deleteCount; |
| | | return productMapper.deleteBatchIds(Arrays.asList(ids)); |
| | | } |
| | | |
| | | } |
| | |
| | | return; |
| | | } |
| | | List<ProductionBomStructure> updateList = new ArrayList<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | // éæ±éæâç¶èç¹éæ±é à æ¬è¡åèâéå±è®¡ç®ï¼å
å¼èç¹äºä¸å½±åï¼ç»æä¸å½å
¥é¡ºåºæ å
³ã |
| | | Map<Long, BigDecimal> demandedQuantityById = new HashMap<>(); |
| | | for (ProductionBomStructure structure : structureList) { |
| | | if (structure == null || structure.getId() == null) { |
| | | continue; |
| | | } |
| | | |
| | | BigDecimal demandedQuantity = lastProcessDemandedQuantity.multiply(defaultDecimal(structure.getUnitQuantity())); |
| | | // if (compareDecimal(structure.getDemandedQuantity(), demandedQuantity) == 0) { |
| | | // continue; |
| | | // } |
| | | // æ ¹èç¹ä»¥è®¢åæ°éä¸ºåºæ°ï¼åèç¹ä»¥ç¶èç¹éæ±éä¸ºåºæ°ã |
| | | boolean rootNode = structure.getParentId() == null || structure.getParentId() == 0L; |
| | | BigDecimal baseQuantity = rootNode |
| | | ? orderQuantity |
| | | : demandedQuantityById.get(structure.getParentId()); |
| | | if (baseQuantity == null) { |
| | | throw new ServiceException("BOMç»ææ°æ®å¼å¸¸ï¼å卿¾ä¸å°ç¶èç¹çåèç¹"); |
| | | } |
| | | BigDecimal demandedQuantity = baseQuantity.multiply(defaultDecimal(structure.getUnitQuantity())); |
| | | ProductionBomStructure update = new ProductionBomStructure(); |
| | | update.setId(structure.getId()); |
| | | update.setDemandedQuantity(demandedQuantity); |
| | | updateList.add(update); |
| | | structure.setDemandedQuantity(demandedQuantity); |
| | | lastProcessDemandedQuantity = demandedQuantity; |
| | | demandedQuantityById.put(structure.getId(), demandedQuantity); |
| | | } |
| | | if (!updateList.isEmpty()) { |
| | | this.updateBatchById(updateList); |
| | |
| | | productionOrderBomMapper.insert(orderBom); |
| | | |
| | | Map<Long, Long> idMap = new HashMap<>(); |
| | | BigDecimal lastProcessDemandedQuantity = orderQuantity; |
| | | // éæ±éæâç¶èç¹éæ±é à æ¬è¡åèâéå±è®¡ç®ï¼å
å¼èç¹äºä¸å½±åï¼ç»æä¸å½å
¥é¡ºåºæ å
³ã |
| | | Map<Long, BigDecimal> demandedQuantityBySourceId = new HashMap<>(); |
| | | for (TechnologyBomStructure source : structureList) { |
| | | // åèç¹ parentId éè¦æ å°ææ°å¿«ç
§èç¹ idï¼æè½ä¿çåå§ BOM å±çº§ã |
| | | ProductionBomStructure target = new ProductionBomStructure(); |
| | |
| | | target.setProductModelId(source.getProductModelId()); |
| | | target.setTechnologyOperationId(source.getOperationId()); |
| | | target.setUnitQuantity(source.getUnitQuantity()); |
| | | target.setDemandedQuantity(lastProcessDemandedQuantity.multiply(source.getUnitQuantity())); |
| | | // æ ¹èç¹ä»¥è®¢åæ°éä¸ºåºæ°ï¼åèç¹ä»¥ç¶èç¹éæ±éä¸ºåºæ°ã |
| | | boolean rootNode = source.getParentId() == null || source.getParentId() == 0L; |
| | | BigDecimal baseQuantity = rootNode |
| | | ? orderQuantity |
| | | : demandedQuantityBySourceId.get(source.getParentId()); |
| | | if (baseQuantity == null) { |
| | | throw new ServiceException("BOMç»ææ°æ®å¼å¸¸ï¼å卿¾ä¸å°ç¶èç¹çåèç¹"); |
| | | } |
| | | target.setDemandedQuantity(baseQuantity.multiply(defaultDecimal(source.getUnitQuantity()))); |
| | | target.setUnit(source.getUnit()); |
| | | productionBomStructureMapper.insert(target); |
| | | idMap.put(source.getId(), target.getId()); |
| | | lastProcessDemandedQuantity = target.getDemandedQuantity(); |
| | | demandedQuantityBySourceId.put(source.getId(), target.getDemandedQuantity()); |
| | | } |
| | | return orderBom; |
| | | } |
| | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.deepoove.poi.XWPFTemplate; |
| | | import com.deepoove.poi.config.Configure; |
| | | import com.deepoove.poi.data.TextRenderData; |
| | | import com.deepoove.poi.policy.TextRenderPolicy; |
| | | import com.deepoove.poi.template.run.RunTemplate; |
| | | import com.ruoyi.common.enums.StockInQualifiedRecordTypeEnum; |
| | | import com.ruoyi.common.exception.ServiceException; |
| | | import com.ruoyi.common.utils.DateUtils; |
| | |
| | | import com.ruoyi.stock.service.StockInventoryService; |
| | | import jakarta.servlet.http.HttpServletResponse; |
| | | import lombok.AllArgsConstructor; |
| | | import org.apache.poi.xwpf.usermodel.XWPFRun; |
| | | import org.springframework.beans.BeanUtils; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | import java.time.LocalDate; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Arrays; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.List; |
| | | import java.util.stream.Collectors; |
| | |
| | | InputStream inputStream = this.getClass().getResourceAsStream("/static/report-template.docx"); |
| | | Configure configure = Configure.builder() |
| | | .bind("paramList", new HackLoopTableRenderPolicy()) |
| | | .bind("inspect.checkTime", (eleTemplate, data, xwpfTemplate) -> { |
| | | XWPFRun run = ((RunTemplate) eleTemplate).getRun(); |
| | | String text = data == null ? "" : DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD, (Date) data); |
| | | TextRenderPolicy.Helper.renderTextRun(run, new TextRenderData(text)); |
| | | }) |
| | | .build(); |
| | | String finalInspectType = inspectType; |
| | | XWPFTemplate template = XWPFTemplate.compile(inputStream, configure).render( |
| | |
| | | import java.time.ZoneId; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.Arrays; |
| | | import java.util.HashMap; |
| | | import java.util.HashSet; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | | import java.util.Set; |
| | | import java.util.function.Function; |
| | |
| | | shippingInfoService.delete(shippingInfos.stream().map(ShippingInfo::getId).collect(Collectors.toList())); |
| | | } |
| | | |
| | | // å¯è½å±äºå¤ä¸ªä¸»è¡¨ |
| | | Set<Long> mainIds = deletedProducts.stream() |
| | | .map(SalesLedgerProduct::getSalesLedgerId) |
| | | .filter(Objects::nonNull) |
| | | .collect(Collectors.toSet()); |
| | | // å¯è½å±äºå¤ä¸ªä¸»è¡¨ï¼æ type åç»ï¼éå®/éè´äº§åå表å
±ç¨ä¸ä¸»è¡¨ id å¯è½ç¸åï¼ |
| | | Map<Integer, Set<Long>> mainIdsByType = new HashMap<>(); |
| | | deletedProducts.stream() |
| | | .filter(product -> product.getSalesLedgerId() != null) |
| | | .forEach(product -> mainIdsByType |
| | | .computeIfAbsent(product.getType() == null ? 1 : product.getType(), key -> new HashSet<>()) |
| | | .add(product.getSalesLedgerId())); |
| | | |
| | | // 2. æ§è¡å é¤æä½ |
| | | int result = salesLedgerProductMapper.deleteBatchIds(Arrays.asList(ids)); |
| | |
| | | deleteProductionData(Arrays.asList(ids)); |
| | | |
| | | // 3. 对æ¯ä¸ªä¸»è¡¨IDè¿è¡é颿´æ° |
| | | mainIdsByType.forEach((type, mainIds) -> { |
| | | for (Long salesLedgerId : mainIds) { |
| | | LambdaQueryWrapper<SalesLedgerProduct> wrapper = new LambdaQueryWrapper<>(); |
| | | wrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId); |
| | | wrapper.eq(SalesLedgerProduct::getSalesLedgerId, salesLedgerId) |
| | | .eq(SalesLedgerProduct::getType, type); |
| | | List<SalesLedgerProduct> remainingProducts = salesLedgerProductMapper.selectList(wrapper); |
| | | |
| | | // è°ç¨éç¨æ¹æ³æ´æ°ä¸»è¡¨éé¢ |
| | | if (type == 1) { |
| | | updateMainContractAmount( |
| | | salesLedgerId, |
| | | remainingProducts, |
| | |
| | | salesLedgerMapper, |
| | | SalesLedger.class |
| | | ); |
| | | } else { |
| | | updateMainContractAmount( |
| | | salesLedgerId, |
| | | remainingProducts, |
| | | SalesLedgerProduct::getTaxInclusiveTotalPrice, |
| | | purchaseLedgerMapper, |
| | | PurchaseLedger.class |
| | | ); |
| | | } |
| | | } |
| | | }); |
| | | return result; |
| | | } |
| | | |
| | |
| | | return 0; |
| | | } |
| | | // å é¤éå®ç®¡çæ°æ® |
| | | // 产åå表éå®/éè´å
±ç¨ï¼ä¸ä¸»è¡¨ id å¯è½ç¸åï¼å¿
é¡»æ type åºåï¼å¦åä¼è¯¯å éè´å°è´¦çäº§åæ°æ® |
| | | LambdaQueryWrapper<SalesLedgerProduct> queryWrapper = new LambdaQueryWrapper<>(); |
| | | queryWrapper.in(SalesLedgerProduct::getSalesLedgerId, idList) |
| | | .eq(SalesLedgerProduct::getType, 1) |
| | | .select(SalesLedgerProduct::getId); |
| | | |
| | | List<SalesLedgerProduct> products = salesLedgerProductMapper.selectList(queryWrapper); |
| | |
| | | } |
| | | if (oldBom.getProductModelId() != null && !oldBom.getProductModelId().equals(technologyBom.getProductModelId())) { |
| | | technologyRoutingMapper.updateProductModelByBomId(technologyBom.getProductModelId(), technologyBom.getId().longValue()); |
| | | technologyBomStructureService.remove(Wrappers.<TechnologyBomStructure>lambdaQuery() |
| | | .eq(TechnologyBomStructure::getBomId, technologyBom.getId().longValue())); |
| | | // è§æ ¼ååæ¶ä»
æ´æ°æ ¹èç¹æåçè§æ ¼ï¼ä¿çä¸çº§BOMç»æ |
| | | List<TechnologyBomStructure> roots = technologyBomStructureService.list(Wrappers.<TechnologyBomStructure>lambdaQuery() |
| | | .eq(TechnologyBomStructure::getBomId, technologyBom.getId().longValue()) |
| | | //.isNull(TechnologyBomStructure::getParentId) |
| | | ); |
| | | if (roots.isEmpty()) { |
| | | initRootStructure(technologyBom.getId().longValue(), technologyBom.getProductModelId()); |
| | | } else { |
| | | ProductModel productModel = productModelService.getById(technologyBom.getProductModelId()); |
| | | for (TechnologyBomStructure root : roots) { |
| | | root.setProductModelId(technologyBom.getProductModelId()); |
| | | root.setUnit(productModel.getUnit()); |
| | | technologyBomStructureService.updateById(root); |
| | | } |
| | | } |
| | | } |
| | | if (technologyBom.getBomNo() == null) { |
| | | technologyBom.setBomNo(oldBom.getBomNo()); |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | # 项ç®ç¸å
³é
ç½® |
| | | ruoyi: |
| | | # åç§° |
| | | name: RuoYi |
| | | # çæ¬ |
| | | version: 3.8.9 |
| | | # çæå¹´ä»½ |
| | | copyrightYear: 2025 |
| | | # æä»¶è·¯å¾ 示ä¾ï¼ Windowsé
ç½®D:/ruoyi/uploadPathï¼Linuxé
ç½® /home/ruoyi/uploadPathï¼ |
| | | profile: /javaWork/product-inventory-management/file |
| | | |
| | | # è·åipå°åå¼å
³ |
| | | addressEnabled: false |
| | | # éªè¯ç ç±»å math æ°åè®¡ç® char å符éªè¯ |
| | | captchaType: math |
| | | # åå审æ¹ç¼å·åç¼(é
ç½®æä»¶åç¼å½å) |
| | | approvalNumberPrefix: NEW |
| | | |
| | | # ä¸ªæ¨ Unipush é
ç½® |
| | | getui: |
| | | appId: PfjyAAE0FK64FaO1w2CMb1 |
| | | appKey: zTMb831OEL6J4GK1uE3Ob4 |
| | | masterSecret: K1GFtsv42v61tXGnF7SGE5 |
| | | domain: https://restapi.getui.cn/v2/ |
| | | # 离线æ¨é使ç¨çå
å/ç»ä»¶å |
| | | intentComponent: uni.app.UNI099A590/io.dcloud.PandoraEntry |
| | | |
| | | # å¼åç¯å¢é
ç½® |
| | | server: |
| | | # æå¡å¨çHTTP端å£ï¼é»è®¤ä¸º8080 |
| | | port: 9003 |
| | | servlet: |
| | | # åºç¨ç访é®è·¯å¾ |
| | | context-path: / |
| | | tomcat: |
| | | # tomcatçURIç¼ç |
| | | uri-encoding: UTF-8 |
| | | # è¿æ¥æ°æ»¡åçæéæ°ï¼é»è®¤ä¸º100 |
| | | accept-count: 1000 |
| | | threads: |
| | | # tomcatæå¤§çº¿ç¨æ°ï¼é»è®¤ä¸º200 |
| | | max: 800 |
| | | # Tomcatå¯å¨åå§åççº¿ç¨æ°ï¼é»è®¤å¼10 |
| | | min-spare: 100 |
| | | |
| | | # æ¥å¿é
ç½® |
| | | logging: |
| | | level: |
| | | com.ruoyi: warn |
| | | org.springframework: warn |
| | | |
| | | minio: |
| | | endpoint: http://114.132.189.42/ |
| | | port: 7019 |
| | | secure: false |
| | | accessKey: admin |
| | | secretKey: 12345678 |
| | | preview-expiry: 24 # é¢è§å°åé»è®¤24å°æ¶ |
| | | default-bucket: jxc |
| | | # ç¨æ·é
ç½® |
| | | user: |
| | | password: |
| | | # å¯ç æå¤§éè¯¯æ¬¡æ° |
| | | maxRetryCount: 5 |
| | | # å¯ç é宿¶é´ï¼é»è®¤10åéï¼ |
| | | lockTime: 10 |
| | | |
| | | # Springé
ç½® |
| | | spring: |
| | | datasource: |
| | | type: com.alibaba.druid.pool.DruidDataSource |
| | | driverClassName: com.mysql.cj.jdbc.Driver |
| | | druid: |
| | | # ä¸»åºæ°æ®æº |
| | | master: |
| | | url: jdbc:mysql://172.17.0.1:3306/product-inventory-management-qhddzxc?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 |
| | | username: root |
| | | password: xd@123456.. |
| | | # ä»åºæ°æ®æº |
| | | slave: |
| | | # 仿°æ®æºå¼å
³/é»è®¤å
³é |
| | | enabled: false |
| | | url: |
| | | username: |
| | | password: |
| | | # åå§è¿æ¥æ° |
| | | initialSize: 5 |
| | | # æå°è¿æ¥æ± æ°é |
| | | minIdle: 10 |
| | | # æå¤§è¿æ¥æ± æ°é |
| | | maxActive: 20 |
| | | # é
ç½®è·åè¿æ¥çå¾
è¶
æ¶çæ¶é´ |
| | | maxWait: 60000 |
| | | # é
ç½®è¿æ¥è¶
æ¶æ¶é´ |
| | | connectTimeout: 30000 |
| | | # é
ç½®ç½ç»è¶
æ¶æ¶é´ |
| | | socketTimeout: 60000 |
| | | # é
ç½®é´éå¤ä¹
æè¿è¡ä¸æ¬¡æ£æµï¼æ£æµéè¦å
³éç空é²è¿æ¥ï¼å使¯æ¯«ç§ |
| | | timeBetweenEvictionRunsMillis: 60000 |
| | | # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿å°çåçæ¶é´ï¼å使¯æ¯«ç§ |
| | | minEvictableIdleTimeMillis: 300000 |
| | | # é
ç½®ä¸ä¸ªè¿æ¥å¨æ± 䏿大çåçæ¶é´ï¼å使¯æ¯«ç§ |
| | | maxEvictableIdleTimeMillis: 900000 |
| | | # é
ç½®æ£æµè¿æ¥æ¯å¦ææ |
| | | validationQuery: SELECT 1 FROM DUAL |
| | | testWhileIdle: true |
| | | testOnBorrow: false |
| | | testOnReturn: false |
| | | webStatFilter: |
| | | enabled: true |
| | | statViewServlet: |
| | | enabled: true |
| | | # 设置ç½ååï¼ä¸å¡«åå
许ææè®¿é® |
| | | allow: |
| | | url-pattern: /druid/* |
| | | # æ§å¶å°ç®¡çç¨æ·ååå¯ç |
| | | login-username: ruoyi |
| | | login-password: 123456 |
| | | filter: |
| | | stat: |
| | | enabled: true |
| | | # æ
¢SQLè®°å½ |
| | | log-slow-sql: true |
| | | slow-sql-millis: 1000 |
| | | merge-sql: true |
| | | wall: |
| | | config: |
| | | multi-statement-allow: true |
| | | # èµæºä¿¡æ¯ |
| | | messages: |
| | | # å½é
åèµæºæä»¶è·¯å¾ |
| | | basename: i18n/messages |
| | | # æä»¶ä¸ä¼ |
| | | servlet: |
| | | multipart: |
| | | # å个æä»¶å¤§å° |
| | | max-file-size: 1GB |
| | | # 设置æ»ä¸ä¼ çæä»¶å¤§å° |
| | | max-request-size: 2GB |
| | | # æå¡æ¨¡å |
| | | devtools: |
| | | restart: |
| | | # çé¨ç½²å¼å
³ |
| | | enabled: false |
| | | # redis é
ç½® |
| | | data: |
| | | mongodb: |
| | | uri: mongodb://114.132.189.42:9028/chat_memory_db_qhddzxc |
| | | # redis é
ç½® |
| | | redis: |
| | | # å°å |
| | | # host: 127.0.0.1 |
| | | host: 172.17.0.1 |
| | | # 端å£ï¼é»è®¤ä¸º6379 |
| | | port: 6379 |
| | | # æ°æ®åºç´¢å¼ |
| | | database: 0 |
| | | # å¯ç |
| | | # password: root2022! |
| | | password: |
| | | |
| | | # è¿æ¥è¶
æ¶æ¶é´ |
| | | timeout: 10s |
| | | lettuce: |
| | | pool: |
| | | # è¿æ¥æ± ä¸çæå°ç©ºé²è¿æ¥ |
| | | min-idle: 0 |
| | | # è¿æ¥æ± ä¸çæå¤§ç©ºé²è¿æ¥ |
| | | max-idle: 8 |
| | | # è¿æ¥æ± çæå¤§æ°æ®åºè¿æ¥æ° |
| | | max-active: 8 |
| | | # #è¿æ¥æ± æå¤§é»å¡çå¾
æ¶é´ï¼ä½¿ç¨è´å¼è¡¨ç¤ºæ²¡æéå¶ï¼ |
| | | max-wait: -1ms |
| | | |
| | | # Quartz宿¶ä»»å¡é
ç½®ï¼æ°å¢é¨åï¼ |
| | | quartz: |
| | | job-store-type: jdbc # ä½¿ç¨æ°æ®åºåå¨ |
| | | jdbc: |
| | | initialize-schema: never # 馿¬¡è¿è¡æ¶èªå¨åå»ºè¡¨ç»æï¼æååæ¹ä¸ºnever |
| | | schema: classpath:org/quartz/impl/jdbcjobstore/tables_mysql_innodb.sql # MySQLè¡¨ç»æèæ¬ |
| | | properties: |
| | | org: |
| | | quartz: |
| | | scheduler: |
| | | instanceName: RuoYiScheduler |
| | | instanceId: AUTO |
| | | jobStore: |
| | | class: org.quartz.impl.jdbcjobstore.JobStoreTX |
| | | driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate # MySQLéé
|
| | | tablePrefix: qrtz_ # 表ååç¼ï¼ä¸èæ¬ä¸è´ |
| | | isClustered: false # åèç¹æ¨¡å¼ï¼éç¾¤éæ¹ä¸ºtrueï¼ |
| | | clusterCheckinInterval: 10000 |
| | | txIsolationLevelSerializable: true |
| | | threadPool: |
| | | class: org.quartz.simpl.SimpleThreadPool |
| | | threadCount: 10 # çº¿ç¨æ± å¤§å° |
| | | threadPriority: 5 |
| | | makeThreadsDaemons: true |
| | | updateCheck: false # å
³éçæ¬æ£æ¥ |
| | | # tokené
ç½® |
| | | token: |
| | | # 令çèªå®ä¹æ è¯ |
| | | header: Authorization |
| | | # 令çå¯é¥ |
| | | secret: xpAVjhCjQDaDB7mjPAzMDSbQWXNu2zYkTdDNUsPMS5Xx8QMmQVYN7n74eZrYJxDJ |
| | | # ä»¤çæææï¼é»è®¤30åéï¼ |
| | | expireTime: 450 |
| | | |
| | | # MyBatis Plusé
ç½® |
| | | mybatis-plus: |
| | | # æç´¢æå®å
å«å æ ¹æ®èªå·±çé¡¹ç®æ¥ |
| | | typeAliasesPackage: com.ruoyi.**.pojo |
| | | # é
ç½®mapperçæ«æï¼æ¾å°ææçmapper.xmlæ å°æä»¶ |
| | | mapperLocations: classpath*:mapper/**/*Mapper.xml |
| | | # å è½½å
¨å±çé
ç½®æä»¶ |
| | | configLocation: classpath:mybatis/mybatis-config.xml |
| | | global-config: |
| | | enable-sql-runner: true |
| | | db-config: |
| | | id-type: auto |
| | | |
| | | # PageHelperå页æä»¶ |
| | | pagehelper: |
| | | helperDialect: mysql |
| | | supportMethodsArguments: true |
| | | params: count=countSql |
| | | |
| | | # Swaggeré
ç½® |
| | | swagger: |
| | | # æ¯å¦å¼å¯swagger |
| | | enabled: true |
| | | # 请æ±åç¼ |
| | | pathMapping: /dev-api |
| | | |
| | | # 鲿¢XSSæ»å» |
| | | xss: |
| | | # è¿æ»¤å¼å
³ |
| | | enabled: true |
| | | # æé¤é¾æ¥ï¼å¤ä¸ªç¨éå·åéï¼ |
| | | excludes: /system/notice |
| | | # å¹é
龿¥ |
| | | urlPatterns: /system/*,/monitor/*,/tool/* |
| | | |
| | | # 代ç çæ |
| | | gen: |
| | | # ä½è
|
| | | author: ruoyi |
| | | # é»è®¤çæå
è·¯å¾ system éæ¹æèªå·±ç模ååç§° å¦ system monitor tool |
| | | packageName: com.ruoyi.project.system |
| | | # èªå¨å»é¤è¡¨åç¼ï¼é»è®¤æ¯true |
| | | autoRemovePre: false |
| | | # 表åç¼ï¼çæç±»åä¸ä¼å
å«è¡¨åç¼ï¼å¤ä¸ªç¨éå·åéï¼ |
| | | tablePrefix: sys_ |
| | | # æ¯å¦å
è®¸çææä»¶è¦çå°æ¬å°ï¼èªå®ä¹è·¯å¾ï¼ï¼é»è®¤ä¸å
许 |
| | | allowOverwrite: false |
| | | |
| | | # æä»¶ä¸ä¼ é
ç½® |
| | | file: |
| | | temp-dir: /javaWork/product-inventory-management/file/temp/uploads # 临æ¶ç®å½ |
| | | upload-dir: /javaWork/product-inventory-management/file/prod/uploads # æ£å¼ç®å½ |
| | | path: /javaWork/product-inventory-management/file # ä¸ä¼ ç®å½ |
| | | urlPrefix: /prod-api/common # 龿¥åç¼ |
| | | domain: http://1.15.17.182:9111 # åååç¼ |
| | | expired: 120 # è¿ææ¶é´(åä½:åé) |
| | | useLimit: 10 # ä½¿ç¨æ¬¡æ° |
| | | compress: true # æ¯å¦å缩 |
| | | needCompressSize: 10MB # å缩éå¼ |
| | | compressQuality: 0.5 # å缩质é(0.0-1.0) |
| | |
| | | -- è¿é¡¹ç¨æç»ï¼éè´è®¢åï¼ |
| | | SELECT |
| | | pl.purchase_contract_number AS invoiceNo, |
| | | pl.sales_contract_no AS salesContractNo, |
| | | pl.supplier_name AS supplierName, |
| | | NULL AS customerName, |
| | | pl.purchase_contract_number AS salesContractNo, |
| | | NULL AS supplierName, |
| | | pl.supplier_name AS customerName, |
| | | 'è¿é¡¹' AS orderType, |
| | | pl.entry_date AS invoiceDate, |
| | | slp.tax_rate AS taxRate, |
| | | MAX(slp.tax_rate) AS taxRate, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS jTaxAmount, |
| | | 0 AS xTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS taxAmount |
| | |
| | | sl.customer_name AS customerName, |
| | | 'é项' AS orderType, |
| | | sl.entry_date AS invoiceDate, |
| | | slp.tax_rate AS taxRate, |
| | | MAX(slp.tax_rate) AS taxRate, |
| | | 0 AS jTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS xTaxAmount, |
| | | ROUND(SUM(slp.tax_inclusive_total_price - slp.tax_exclusive_total_price), 2) AS taxAmount |
| | |
| | | </where> |
| | | </select> |
| | | <select id="supplierTransactions" resultType="com.ruoyi.purchase.vo.SupplierTransactionsVo"> |
| | | select T1.supplier_id, |
| | | select c.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 |
| | | c.contractAmounts, |
| | | -- 仿¬¾éé¢ï¼éååæååéé¢å°é¡¶ååæ±æ»ï¼é¿å
éå¤ä»æ¬¾å¯¼è´ä»æ¬¾éé¢å¤§äºååéé¢ |
| | | c.paymentAmount, |
| | | -- åºä»éé¢ï¼éååãå(å
¥åºéé¢, ååéé¢)è¾å°è
- å°é¡¶å仿¬¾éé¢ - éè´§éé¢ãååæ±æ»ï¼ä¸é为 0 |
| | | c.payableAmount |
| | | from ( |
| | | select pl.supplier_id, |
| | | sum(COALESCE(pl.contract_amount, 0)) as contractAmounts, |
| | | sum(LEAST(IFNULL(pay.paymentAmount, 0), COALESCE(pl.contract_amount, 0))) as paymentAmount, |
| | | sum(GREATEST( |
| | | IFNULL(ib.InboundAmount, 0) |
| | | - IF(ib.InboundAmount <![CDATA[ > ]]> COALESCE(pl.contract_amount, 0), ib.InboundAmount - COALESCE(pl.contract_amount, 0), 0) |
| | | - LEAST(IFNULL(pay.paymentAmount, 0), COALESCE(pl.contract_amount, 0)) |
| | | - IFNULL(rt.returnAmount, 0) |
| | | , 0)) as payableAmount |
| | | from purchase_ledger pl |
| | | left join ( |
| | | select |
| | | supplier_id, |
| | | sum(total_amount) as returnAmount |
| | | t.purchase_ledger_id as id, |
| | | sum(t.payment_amount) as paymentAmount |
| | | from ( |
| | | select |
| | | app.id, |
| | | app.payment_amount, |
| | | pl.id as purchase_ledger_id |
| | | 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 |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | 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 app.id, pl.id |
| | | ) t |
| | | group by t.purchase_ledger_id |
| | | ) pay on pay.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 |
| | | LEFT JOIN quality_inspect qi ON sir.record_type = 10 AND sir.record_id = qi.id |
| | | 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 |
| | | ) ib on ib.id = pl.id |
| | | left join ( |
| | | select pl.id, |
| | | sum(pro.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 |
| | | left join purchase_ledger pl on pro.purchase_ledger_id = pl.id |
| | | group by pl.id |
| | | ) rt on rt.id = pl.id |
| | | group by pl.supplier_id |
| | | ) c |
| | | left join supplier_manage sm on c.supplier_id = sm.id |
| | | <where> |
| | | <if test="supplierName!=null and supplierName!=''"> |
| | | AND sm.supplier_name LIKE CONCAT('%',#{supplierName},'%') |
| | | </if> |
| | | </where> |
| | | order by T1.supplier_id desc |
| | | order by c.supplier_id desc |
| | | </select> |
| | | <select id="supplierTransactionsDetails" |
| | | resultType="com.ruoyi.purchase.vo.SupplierTransactionsDetailsVo"> |
| | |
| | | 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 |
| | | -- 仿¬¾é颿ååéé¢å°é¡¶ï¼é¿å
éå¤ä»æ¬¾å¯¼è´ä»æ¬¾éé¢å¤§äºååéé¢ |
| | | LEAST(IFNULL(T1.paymentAmount, 0), COALESCE(pl.contract_amount, 0)) AS paymentAmount, |
| | | -- åºä»éé¢ = å(å
¥åºéé¢, ååéé¢)çè¾å°è
- å°é¡¶å仿¬¾éé¢ - éè´§éé¢ |
| | | -- å
¥åºé颿ååéé¢å°é¡¶ï¼é¿å
å
¥åºæµç¨éå¤æäº¤å¯¼è´åºä»éé¢å¤§äºååéé¢ï¼ |
| | | -- 已仿¬¾éé¢ï¼å款/仿¬¾åï¼ä¸éè´§éé¢åéä»åºä»ä¸æ£åã |
| | | GREATEST( |
| | | IFNULL(T2.InboundAmount, 0) |
| | | - IF(T2.InboundAmount <![CDATA[ > ]]> COALESCE(pl.contract_amount, 0), T2.InboundAmount - COALESCE(pl.contract_amount, 0), 0) |
| | | - LEAST(IFNULL(T1.paymentAmount, 0), COALESCE(pl.contract_amount, 0)) |
| | | - IFNULL(T3.returnAmount, 0) |
| | | , 0) AS payableAmount |
| | | from purchase_ledger pl |
| | | left join ( |
| | | select |
| | |
| | | unit, |
| | | product_name, |
| | | product_id |
| | | order by combined.create_time desc |
| | | order by MAX(combined.create_time) desc |
| | | </select> |
| | | |
| | | <select id="listStockInventoryExportData" resultType="com.ruoyi.stock.execl.StockInventoryExportData"> |
| | |
| | | left join product p on pm.product_id = p.id |
| | | where si.product_model_id = #{productModelId} |
| | | and si.qualitity > IFNULL(sd.qualitity, 0) |
| | | order by si.create_time asc |
| | | </select> |
| | | |
| | | <select id="getBatchNoQty" resultType="com.ruoyi.stock.dto.StockInventoryDto"> |