Commit d6ed695b by 杨浩

询价管理-导入items

parent f86390e9
package cn.iocoder.foodnexus.framework.common.pojo;
import com.google.common.collect.Lists;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.util.List;
/**
* @author : yanghao
* create at: 2025/10/30 17:58
* @description: 导入结果
*/
@Data
@AllArgsConstructor
@Builder
public class ImportResult<T> {
public ImportResult() {
this.list = Lists.newArrayList();
this.errorMsg = Lists.newArrayList();
}
@Schema(description = "导入结果集合")
private List<T> list;
@Schema(description = "导入总数")
private Integer totalCount;
@Schema(description = "成功数")
private Integer successCount;
@Schema(description = "失败数")
private Integer errorCount;
@Schema(description = "失败信息")
private List<ErrorMsg> errorMsg;
public void putError(Integer errorRow, String msg, String content) {
errorMsg.add(new ErrorMsg(errorRow, msg, content));
}
public void add(T data) {
list.add(data);
}
@Data
@AllArgsConstructor
public static class ErrorMsg {
@Schema(description = "失败行数")
private Integer errorRow;
@Schema(description = "失败原因")
private String msg;
@Schema(description = "内容")
private String content;
}
}
package cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice; package cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice;
import cn.iocoder.foodnexus.framework.common.pojo.ImportResult;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemImportVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemRespVO; import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemRespVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemSaveReqVO;
import cn.iocoder.foodnexus.module.operations.service.inquirepriceitem.InquirePriceItemService; import cn.iocoder.foodnexus.module.operations.service.inquirepriceitem.InquirePriceItemService;
import cn.iocoder.foodnexus.module.product.service.spu.ProductSpuService; import cn.iocoder.foodnexus.module.product.service.spu.ProductSpuService;
import cn.iocoder.foodnexus.module.system.controller.admin.user.vo.user.UserImportExcelVO;
import cn.iocoder.foodnexus.module.system.controller.admin.user.vo.user.UserImportRespVO;
import io.swagger.v3.oas.annotations.Parameters;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
...@@ -32,6 +38,7 @@ import static cn.iocoder.foodnexus.framework.apilog.core.enums.OperateTypeEnum.* ...@@ -32,6 +38,7 @@ import static cn.iocoder.foodnexus.framework.apilog.core.enums.OperateTypeEnum.*
import cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice.vo.*; import cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice.vo.*;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquireprice.InquirePriceDO; import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquireprice.InquirePriceDO;
import cn.iocoder.foodnexus.module.operations.service.inquireprice.InquirePriceService; import cn.iocoder.foodnexus.module.operations.service.inquireprice.InquirePriceService;
import org.springframework.web.multipart.MultipartFile;
@Tag(name = "管理后台 - 询价管理") @Tag(name = "管理后台 - 询价管理")
@RestController @RestController
...@@ -123,4 +130,23 @@ public class InquirePriceController { ...@@ -123,4 +130,23 @@ public class InquirePriceController {
BeanUtils.toBean(list, InquirePriceRespVO.class)); BeanUtils.toBean(list, InquirePriceRespVO.class));
} }
@PostMapping("/import")
@Operation(summary = "导入items")
@Parameters({@Parameter(name = "file", description = "Excel 文件", required = true)})
public CommonResult<ImportResult<InquirePriceItemSaveReqVO>> importExcel(@RequestParam("file") MultipartFile file) throws Exception {
List<InquirePriceItemImportVO> list = ExcelUtils.read(file, InquirePriceItemImportVO.class);
return success(inquirePriceService.importItems(list));
}
@GetMapping("/get-import-template")
@Operation(summary = "获得导入items模版")
public void importTemplate(HttpServletResponse response) throws IOException {
// 手动创建导出 demo
List<InquirePriceItemImportVO> list = Collections.singletonList(
InquirePriceItemImportVO.builder().productName("商品A").categoryName("分类A").productStandard("规格123")
.marketPrice("9.99").productUnit("个").build());
// 输出
ExcelUtils.write(response, "添加询价记录表.xls", "添加询价记录表", InquirePriceItemImportVO.class, list);
}
} }
\ No newline at end of file
package cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo;
import cn.idev.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.math.BigDecimal;
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题
public class InquirePriceItemImportVO {
@Schema(description = "商品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "10941")
@ExcelProperty("商品名称")
@NotBlank(message = "商品名称")
private String productName;
@Schema(description = "商品类型", example = "李四")
@ExcelProperty("商品类型")
@NotBlank(message = "商品类型不能为空")
private String categoryName;
@Schema(description = "规格")
@ExcelProperty("规格")
private String productStandard;
@Schema(description = "市场均价(元)", example = "22500")
@ExcelProperty("市场均价")
@NotBlank(message = "市场均价不能为空")
private String marketPrice;
@Schema(description = "商品单位")
@ExcelProperty("商品单位")
private String productUnit;
}
\ No newline at end of file
...@@ -21,6 +21,9 @@ public class InquirePriceItemSaveReqVO { ...@@ -21,6 +21,9 @@ public class InquirePriceItemSaveReqVO {
@NotNull(message = "商品id不能为空") @NotNull(message = "商品id不能为空")
private Long productId; private Long productId;
@Schema(description = "商品名称", hidden = true)
private String productName;
@Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13698") @Schema(description = "商品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13698")
@NotNull(message = "商品分类编号不能为空") @NotNull(message = "商品分类编号不能为空")
private Long categoryId; private Long categoryId;
......
...@@ -2,7 +2,10 @@ package cn.iocoder.foodnexus.module.operations.service.inquireprice; ...@@ -2,7 +2,10 @@ package cn.iocoder.foodnexus.module.operations.service.inquireprice;
import java.util.*; import java.util.*;
import cn.iocoder.foodnexus.framework.common.pojo.ImportResult;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil; import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemImportVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemSaveReqVO;
import jakarta.validation.*; import jakarta.validation.*;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice.vo.*; import cn.iocoder.foodnexus.module.operations.controller.admin.inquireprice.vo.*;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquireprice.InquirePriceDO; import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquireprice.InquirePriceDO;
...@@ -72,4 +75,6 @@ public interface InquirePriceService { ...@@ -72,4 +75,6 @@ public interface InquirePriceService {
default Map<Long, InquirePriceDO> getMap(List<Long> collect) { default Map<Long, InquirePriceDO> getMap(List<Long> collect) {
return CommonUtil.listConvertMap(getInquirePrice(collect), InquirePriceDO::getId); return CommonUtil.listConvertMap(getInquirePrice(collect), InquirePriceDO::getId);
} }
ImportResult<InquirePriceItemSaveReqVO> importItems(List<InquirePriceItemImportVO> list);
} }
\ No newline at end of file
...@@ -2,7 +2,10 @@ package cn.iocoder.foodnexus.module.operations.service.inquireprice; ...@@ -2,7 +2,10 @@ package cn.iocoder.foodnexus.module.operations.service.inquireprice;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.foodnexus.framework.common.enums.CommonStatusEnum; import cn.iocoder.foodnexus.framework.common.enums.CommonStatusEnum;
import cn.iocoder.foodnexus.framework.common.pojo.ImportResult;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil; import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.framework.common.util.json.JsonUtils;
import cn.iocoder.foodnexus.framework.common.util.validation.ValidationUtils;
import cn.iocoder.foodnexus.module.erp.api.enums.ErpAuditStatus; import cn.iocoder.foodnexus.module.erp.api.enums.ErpAuditStatus;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.product.ProductSupplierDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.product.ProductSupplierDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpSupplierDO;
...@@ -11,12 +14,19 @@ import cn.iocoder.foodnexus.module.erp.service.product.ProductSupplierService; ...@@ -11,12 +14,19 @@ import cn.iocoder.foodnexus.module.erp.service.product.ProductSupplierService;
import cn.iocoder.foodnexus.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.foodnexus.module.erp.service.purchase.ErpSupplierService;
import cn.iocoder.foodnexus.module.erp.service.sale.ErpCustomerService; import cn.iocoder.foodnexus.module.erp.service.sale.ErpCustomerService;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirecustomerpush.vo.InquireCustomerPushSaveReqVO; import cn.iocoder.foodnexus.module.operations.controller.admin.inquirecustomerpush.vo.InquireCustomerPushSaveReqVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemImportVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirepriceitem.vo.InquirePriceItemSaveReqVO;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquiresupplierpush.vo.InquireSupplierPushSaveReqVO; import cn.iocoder.foodnexus.module.operations.controller.admin.inquiresupplierpush.vo.InquireSupplierPushSaveReqVO;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquirepriceitem.InquirePriceItemDO; import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquirepriceitem.InquirePriceItemDO;
import cn.iocoder.foodnexus.module.operations.service.inquirecustomerpush.InquireCustomerPushService; import cn.iocoder.foodnexus.module.operations.service.inquirecustomerpush.InquireCustomerPushService;
import cn.iocoder.foodnexus.module.operations.service.inquirepriceitem.InquirePriceItemService; import cn.iocoder.foodnexus.module.operations.service.inquirepriceitem.InquirePriceItemService;
import cn.iocoder.foodnexus.module.operations.service.inquiresupplierpush.InquireSupplierPushService; import cn.iocoder.foodnexus.module.operations.service.inquiresupplierpush.InquireSupplierPushService;
import cn.iocoder.foodnexus.module.product.api.ProductSpuApi; import cn.iocoder.foodnexus.module.product.api.ProductSpuApi;
import cn.iocoder.foodnexus.module.product.dal.dataobject.category.ProductCategoryDO;
import cn.iocoder.foodnexus.module.product.dal.dataobject.spu.ProductSpuDO;
import cn.iocoder.foodnexus.module.product.dal.mysql.category.ProductCategoryMapper;
import cn.iocoder.foodnexus.module.product.dal.mysql.spu.ProductSpuMapper;
import cn.iocoder.foodnexus.module.product.service.category.ProductCategoryService;
import cn.iocoder.foodnexus.module.product.service.spu.ProductSpuService; import cn.iocoder.foodnexus.module.product.service.spu.ProductSpuService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
...@@ -74,6 +84,12 @@ public class InquirePriceServiceImpl implements InquirePriceService { ...@@ -74,6 +84,12 @@ public class InquirePriceServiceImpl implements InquirePriceService {
@Autowired @Autowired
private ErpCustomerService customerService; private ErpCustomerService customerService;
@Autowired
private ProductSpuMapper productMapper;
@Autowired
private ProductCategoryMapper productCategoryMapper;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createInquirePrice(InquirePriceSaveReqVO createReqVO) { public Long createInquirePrice(InquirePriceSaveReqVO createReqVO) {
...@@ -205,4 +221,86 @@ public class InquirePriceServiceImpl implements InquirePriceService { ...@@ -205,4 +221,86 @@ public class InquirePriceServiceImpl implements InquirePriceService {
} }
return inquirePriceMapper.selectByIds(collect); return inquirePriceMapper.selectByIds(collect);
} }
@Override
public ImportResult<InquirePriceItemSaveReqVO> importItems(List<InquirePriceItemImportVO> list) {
if (CommonUtil.isEmpty(list)) {
return new ImportResult<InquirePriceItemSaveReqVO>().setTotalCount(0);
}
int totalCount = 0;
int successCount = 0;
int errorCount = 0;
ImportResult<InquirePriceItemSaveReqVO> result = new ImportResult<>();
// 根据商品名称查询
List<ProductSpuDO> productSpuList = productMapper.selectList(Wrappers.<ProductSpuDO>lambdaQuery()
.in(ProductSpuDO::getName, CommonUtil.listConvertSet(list, i -> i.getProductName().trim())));
Map<String, ProductSpuDO> productMap = CommonUtil.listConvertMap(productSpuList, ProductSpuDO::getName);
List<ProductCategoryDO> productCategoryDOS = productCategoryMapper.selectList(Wrappers.<ProductCategoryDO>lambdaQuery()
.in(ProductCategoryDO::getName, CommonUtil.listConvertSet(list, InquirePriceItemImportVO::getCategoryName)));
Map<String, ProductCategoryDO> categoryMap = CommonUtil.listConvertMap(productCategoryDOS, ProductCategoryDO::getName);
Map<Long, ProductCategoryDO> categoryIdMap = CommonUtil.listConvertMap(productCategoryDOS, ProductCategoryDO::getId);
// 根据分类查询
for (InquirePriceItemImportVO item : list) {
totalCount ++;
try {
ValidationUtils.validate(item);
} catch (Exception e) {
errorCount ++;
result.putError(totalCount, "参数空缺", JsonUtils.toJsonString(item));
continue;
}
InquirePriceItemSaveReqVO saveReq = new InquirePriceItemSaveReqVO();
// 商品名称查询
String productName = item.getProductName().trim();
String categoryName = item.getCategoryName().trim();
if (!categoryMap.containsKey(categoryName)) {
errorCount ++;
result.putError(totalCount, String.format("未查询到对应分类【%s】", categoryName), JsonUtils.toJsonString(item));
continue;
}
if (!productMap.containsKey(productName)) {
errorCount ++;
result.putError(totalCount, String.format("未查询到对应商品【%s】", productName), JsonUtils.toJsonString(item));
continue;
} else {
ProductSpuDO productSpuDO = productMap.get(productName);
if (!categoryIdMap.containsKey(productSpuDO.getCategoryId())) {
errorCount ++;
result.putError(totalCount, String.format("分类【%s】下未查询到商品【%s】", categoryName, productName), JsonUtils.toJsonString(item));
continue;
}
ProductCategoryDO category = categoryIdMap.get(productSpuDO.getCategoryId());
saveReq.setProductId(productSpuDO.getId());
saveReq.setProductName(productSpuDO.getName());
saveReq.setCategoryId(category.getId());
saveReq.setCategoryName(category.getName());
saveReq.setProductStandard(productSpuDO.getIntroduction());
saveReq.setProductUnit(productSpuDO.getUnitName());
// 处理价格
try {
// 将String转换为double
double value = Double.parseDouble(item.getMarketPrice());
// 乘以100
double multiplied = value * 100;
// 转换为int,自动舍弃小数部分
saveReq.setMarketPrice((int) multiplied);
} catch (NumberFormatException e) {
errorCount ++;
result.putError(totalCount, String.format("商品【%s】市场均价转换失败", productName), JsonUtils.toJsonString(item));
continue;
}
result.add(saveReq);
successCount ++;
}
result.setTotalCount(totalCount);
result.setErrorCount(errorCount);
result.setSuccessCount(successCount);
}
return result;
}
} }
\ No newline at end of file
...@@ -8,10 +8,13 @@ import jakarta.validation.constraints.NotEmpty; ...@@ -8,10 +8,13 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size; import jakarta.validation.constraints.Size;
import lombok.Data; import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.List; import java.util.List;
import static cn.iocoder.foodnexus.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Schema(description = "管理后台 - 客户总订单新增/修改 Request VO") @Schema(description = "管理后台 - 客户总订单新增/修改 Request VO")
@Data @Data
public class AppCustomerOrderSaveReqVO { public class AppCustomerOrderSaveReqVO {
...@@ -34,9 +37,11 @@ public class AppCustomerOrderSaveReqVO { ...@@ -34,9 +37,11 @@ public class AppCustomerOrderSaveReqVO {
private DeliveryMode deliveryMode; private DeliveryMode deliveryMode;
@Schema(description = "预计配送开始时间") @Schema(description = "预计配送开始时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime planDeliveryStartTime; private LocalDateTime planDeliveryStartTime;
@Schema(description = "预计配送结束时间") @Schema(description = "预计配送结束时间")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime planDeliveryEndTime; private LocalDateTime planDeliveryEndTime;
@Schema(description = "配送公司") @Schema(description = "配送公司")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment