Commit 266040c5 by 杨浩

采购订单发货;

jimu报表;
质检附件
parent b6e17bf3
package cn.iocoder.foodnexus.module.customerpermission.core.db; package cn.iocoder.foodnexus.module.customerpermission.core.db;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.iocoder.foodnexus.framework.common.exception.ServiceException;
import cn.iocoder.foodnexus.module.customerpermission.core.rule.CustomerPermissionRule; import cn.iocoder.foodnexus.module.customerpermission.core.rule.CustomerPermissionRule;
import cn.iocoder.foodnexus.module.customerpermission.core.rule.CustomerPermissionRuleFactory; import cn.iocoder.foodnexus.module.customerpermission.core.rule.CustomerPermissionRuleFactory;
import cn.iocoder.foodnexus.framework.mybatis.core.util.MyBatisUtils; import cn.iocoder.foodnexus.framework.mybatis.core.util.MyBatisUtils;
...@@ -12,8 +13,10 @@ import net.sf.jsqlparser.schema.Table; ...@@ -12,8 +13,10 @@ import net.sf.jsqlparser.schema.Table;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.List; import java.util.List;
import java.util.Objects;
import static cn.iocoder.foodnexus.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck; import static cn.iocoder.foodnexus.framework.security.core.util.SecurityFrameworkUtils.skipPermissionCheck;
import static cn.iocoder.foodnexus.module.customerpermission.core.rule.customer.CustomerVisiblePermissionRule.NULL_PERMISSION_ERROR;
/** /**
* 基于 {@link CustomerPermissionRule} 的数据权限处理器 * 基于 {@link CustomerPermissionRule} 的数据权限处理器
......
...@@ -3,6 +3,7 @@ package cn.iocoder.foodnexus.module.customerpermission.core.rule.customer; ...@@ -3,6 +3,7 @@ package cn.iocoder.foodnexus.module.customerpermission.core.rule.customer;
import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil; import cn.hutool.core.map.MapUtil;
import cn.iocoder.foodnexus.framework.common.enums.UserSystemEnum; import cn.iocoder.foodnexus.framework.common.enums.UserSystemEnum;
import cn.iocoder.foodnexus.framework.common.exception.ServiceException;
import cn.iocoder.foodnexus.framework.common.util.CommonUtil; import cn.iocoder.foodnexus.framework.common.util.CommonUtil;
import cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils; import cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils;
import cn.iocoder.foodnexus.framework.common.util.json.JsonUtils; import cn.iocoder.foodnexus.framework.common.util.json.JsonUtils;
...@@ -17,9 +18,11 @@ import lombok.extern.slf4j.Slf4j; ...@@ -17,9 +18,11 @@ import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Alias; import net.sf.jsqlparser.expression.Alias;
import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.LongValue; import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.InExpression; import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList; import net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList;
import net.sf.jsqlparser.schema.Column;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -47,6 +50,8 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule { ...@@ -47,6 +50,8 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule {
public static final String PRODUCT_ID_COLUMN = "id"; public static final String PRODUCT_ID_COLUMN = "id";
public static final Integer NULL_PERMISSION_ERROR = 100010;
/** /**
* 根据表名和别名,生成对应的 WHERE / OR 过滤条件 * 根据表名和别名,生成对应的 WHERE / OR 过滤条件
* *
...@@ -74,8 +79,9 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule { ...@@ -74,8 +79,9 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule {
CustomerVisibleProductRespDTO customerVisibleDto = inquireCustomerApi.queryCustomerIdByCustomerId(customerId); CustomerVisibleProductRespDTO customerVisibleDto = inquireCustomerApi.queryCustomerIdByCustomerId(customerId);
if (customerVisibleDto == null || CommonUtil.isEmpty(customerVisibleDto.getItems())) { if (customerVisibleDto == null || CommonUtil.isEmpty(customerVisibleDto.getItems())) {
log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser)); log.error("[getExpression][LoginUser({}) 获取数据权限为 null]", JsonUtils.toJsonString(loginUser));
throw new NullPointerException(String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限", /*throw new ServiceException(NULL_PERMISSION_ERROR, String.format("LoginUser(%d) Table(%s/%s) 未返回数据权限",
loginUser.getId(), tableName, tableAlias.getName())); loginUser.getId(), tableName, tableAlias.getName()));*/
return this.buildNoDataExpression();
} }
/* // 添加到上下文中,避免重复计算 /* // 添加到上下文中,避免重复计算
loginUser.setContext(CONTEXT_KEY, customerVisibleDto); loginUser.setContext(CONTEXT_KEY, customerVisibleDto);
...@@ -98,4 +104,17 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule { ...@@ -98,4 +104,17 @@ public class CustomerVisiblePermissionRule implements CustomerPermissionRule {
// Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号 // Parenthesis 的目的,是提供 (1,2,3) 的 () 左右括号
new ParenthesedExpressionList(new ExpressionList<LongValue>(CollectionUtils.convertList(productIds, LongValue::new)))); new ParenthesedExpressionList(new ExpressionList<LongValue>(CollectionUtils.convertList(productIds, LongValue::new))));
} }
/**
* 构建返回空结果的表达式(恒不成立条件)
*/
private Expression buildNoDataExpression() {
// 方式1:通用版 - 构造 "1 = 0"(推荐,不依赖任何表字段)
EqualsTo equalsTo = new EqualsTo();
// 左值:1(LongValue适配JSqlParser 5.1的数值类型)
equalsTo.setLeftExpression(new LongValue(1));
// 右值:0
equalsTo.setRightExpression(new LongValue(0));
return equalsTo;
}
} }
...@@ -20,6 +20,7 @@ import cn.iocoder.foodnexus.module.erp.api.vo.warehouse.WarehouseInfo; ...@@ -20,6 +20,7 @@ import cn.iocoder.foodnexus.module.erp.api.vo.warehouse.WarehouseInfo;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderExportVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderExportVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderRespVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderRespVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.supplier.SupplierPurchaseOrderDeliveryReqVO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpSupplierDO;
...@@ -108,7 +109,7 @@ public class ErpPurchaseOrderController { ...@@ -108,7 +109,7 @@ public class ErpPurchaseOrderController {
@Operation(summary = "到货") @Operation(summary = "到货")
@Parameter(name = "ids", description = "编号", required = true) @Parameter(name = "ids", description = "编号", required = true)
public CommonResult<Boolean> arrival(@RequestParam("ids") List<Long> ids) { public CommonResult<Boolean> arrival(@RequestParam("ids") List<Long> ids) {
purchaseOrderService.delivery(ids, null, purchaseOrderService.delivery(SupplierPurchaseOrderDeliveryReqVO.transform(ids), null,
ErpDeliveryStatus.ALREADY, ErpDeliveryStatus.ARRIVAL, CustomerOrderStatus.SUPPLIER_ARRIVE); ErpDeliveryStatus.ALREADY, ErpDeliveryStatus.ARRIVAL, CustomerOrderStatus.SUPPLIER_ARRIVE);
return success(Boolean.TRUE); return success(Boolean.TRUE);
} }
...@@ -187,7 +188,7 @@ public class ErpPurchaseOrderController { ...@@ -187,7 +188,7 @@ public class ErpPurchaseOrderController {
@Parameter(name = "ids", description = "编号", required = true) @Parameter(name = "ids", description = "编号", required = true)
@AppSystemAuth(UserSystemEnum.SUPPLIER) @AppSystemAuth(UserSystemEnum.SUPPLIER)
public CommonResult<Boolean> supplierAcceptingOrders(@RequestParam("ids") List<Long> ids) { public CommonResult<Boolean> supplierAcceptingOrders(@RequestParam("ids") List<Long> ids) {
purchaseOrderService.delivery(ids, supplierApi.querySupplierIdByUserId(SecurityFrameworkUtils.getLoginUserId()), purchaseOrderService.delivery(SupplierPurchaseOrderDeliveryReqVO.transform(ids), supplierApi.querySupplierIdByUserId(SecurityFrameworkUtils.getLoginUserId()),
ErpDeliveryStatus.MATCHED, ErpDeliveryStatus.NOT_YET, CustomerOrderStatus.SUPPLIER_ACCEPT_ORDER); ErpDeliveryStatus.MATCHED, ErpDeliveryStatus.NOT_YET, CustomerOrderStatus.SUPPLIER_ACCEPT_ORDER);
return success(Boolean.TRUE); return success(Boolean.TRUE);
} }
...@@ -196,8 +197,8 @@ public class ErpPurchaseOrderController { ...@@ -196,8 +197,8 @@ public class ErpPurchaseOrderController {
@Operation(summary = "供应商 - 发货") @Operation(summary = "供应商 - 发货")
@Parameter(name = "ids", description = "编号", required = true) @Parameter(name = "ids", description = "编号", required = true)
@AppSystemAuth(UserSystemEnum.SUPPLIER) @AppSystemAuth(UserSystemEnum.SUPPLIER)
public CommonResult<Boolean> supplierPurchaseOrderDelivery(@RequestParam("ids") List<Long> ids) { public CommonResult<Boolean> supplierPurchaseOrderDelivery(@RequestBody @Valid SupplierPurchaseOrderDeliveryReqVO reqVO) {
purchaseOrderService.delivery(ids, supplierApi.querySupplierIdByUserId(SecurityFrameworkUtils.getLoginUserId()), purchaseOrderService.delivery(reqVO, supplierApi.querySupplierIdByUserId(SecurityFrameworkUtils.getLoginUserId()),
ErpDeliveryStatus.NOT_YET, ErpDeliveryStatus.ALREADY, CustomerOrderStatus.SUPPLIER_SHIP); ErpDeliveryStatus.NOT_YET, ErpDeliveryStatus.ALREADY, CustomerOrderStatus.SUPPLIER_SHIP);
return success(Boolean.TRUE); return success(Boolean.TRUE);
} }
......
package cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.supplier;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import java.util.ArrayList;
import java.util.List;
/**
* @author : yanghao
* create at: 2026/1/5 15:12
* @description:
*/
@Data
@Schema(description = "供应商后台发货")
public class SupplierPurchaseOrderDeliveryReqVO {
@Schema(description = "items", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "items不能为空")
private List<Item> items;
@Data
public static class Item {
@Schema(description = "id" , requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "id不能为空")
private Long id;
@Schema(description = "文件附件url")
private String file;
}
public static SupplierPurchaseOrderDeliveryReqVO transform(List<Long> ids) {
SupplierPurchaseOrderDeliveryReqVO data = new SupplierPurchaseOrderDeliveryReqVO();
List<Item> items = new ArrayList<>(ids.size());
for (Long id : ids) {
Item item = new Item();
item.setId(id);
items.add(item);
}
data.setItems(items);
return data;
}
}
...@@ -4,6 +4,7 @@ import cn.iocoder.foodnexus.framework.common.pojo.PageResult; ...@@ -4,6 +4,7 @@ import cn.iocoder.foodnexus.framework.common.pojo.PageResult;
import cn.iocoder.foodnexus.module.erp.api.enums.ErpDeliveryStatus; import cn.iocoder.foodnexus.module.erp.api.enums.ErpDeliveryStatus;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.supplier.SupplierPurchaseOrderDeliveryReqVO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.SupplierMonthOrderPageReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.SupplierMonthOrderPageReqVO;
...@@ -116,7 +117,7 @@ public interface ErpPurchaseOrderService { ...@@ -116,7 +117,7 @@ public interface ErpPurchaseOrderService {
* @param ids * @param ids
* @param supplierId * @param supplierId
*/ */
void delivery(List<Long> ids, Long supplierId, ErpDeliveryStatus oriStatus, ErpDeliveryStatus updateStatus, CustomerOrderStatus updateOrderStatus); void delivery(SupplierPurchaseOrderDeliveryReqVO reqVO, Long supplierId, ErpDeliveryStatus oriStatus, ErpDeliveryStatus updateStatus, CustomerOrderStatus updateOrderStatus);
Map<String, Long> queryCountByDeliveryStatus(ErpPurchaseOrderPageReqVO pageReqVO); Map<String, Long> queryCountByDeliveryStatus(ErpPurchaseOrderPageReqVO pageReqVO);
......
...@@ -13,6 +13,7 @@ import cn.iocoder.foodnexus.module.erp.api.enums.ErpDeliveryStatus; ...@@ -13,6 +13,7 @@ import cn.iocoder.foodnexus.module.erp.api.enums.ErpDeliveryStatus;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO;
import cn.iocoder.foodnexus.module.erp.controller.admin.purchase.vo.supplier.SupplierPurchaseOrderDeliveryReqVO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO;
import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; import cn.iocoder.foodnexus.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO;
import cn.iocoder.foodnexus.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper; import cn.iocoder.foodnexus.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper;
...@@ -41,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -41,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase; import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.multipart.MultipartFile;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.time.LocalDateTime;
...@@ -325,12 +327,13 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { ...@@ -325,12 +327,13 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
/** /**
* 发货/接单 * 发货/接单
* *
* @param ids
* @param supplierId * @param supplierId
*/ */
@Override @Override
@Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
public void delivery(List<Long> ids, Long supplierId, ErpDeliveryStatus oriStatus, ErpDeliveryStatus updateStatus, CustomerOrderStatus updateOrderStatus) { public void delivery(SupplierPurchaseOrderDeliveryReqVO reqVO, Long supplierId, ErpDeliveryStatus oriStatus, ErpDeliveryStatus updateStatus, CustomerOrderStatus updateOrderStatus) {
Map<Long, String> idMap = CommonUtil.listConvertMap(reqVO.getItems(), SupplierPurchaseOrderDeliveryReqVO.Item::getId, SupplierPurchaseOrderDeliveryReqVO.Item::getFile);
Set<Long> ids = CommonUtil.listConvertSet(reqVO.getItems(), SupplierPurchaseOrderDeliveryReqVO.Item::getId);
List<ErpPurchaseOrderDO> orderList = purchaseOrderMapper.selectList(Wrappers.<ErpPurchaseOrderDO>lambdaQuery() List<ErpPurchaseOrderDO> orderList = purchaseOrderMapper.selectList(Wrappers.<ErpPurchaseOrderDO>lambdaQuery()
.in(ErpPurchaseOrderDO::getId, ids) .in(ErpPurchaseOrderDO::getId, ids)
.eq(CommonUtil.isNotEmpty(supplierId) ,ErpPurchaseOrderDO::getSupplierId, supplierId)); .eq(CommonUtil.isNotEmpty(supplierId) ,ErpPurchaseOrderDO::getSupplierId, supplierId));
...@@ -365,11 +368,17 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { ...@@ -365,11 +368,17 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
orderRecordApi.recordEvent(event); orderRecordApi.recordEvent(event);
customerOrderSet.add(item.getCustomerOrderId()); customerOrderSet.add(item.getCustomerOrderId());
} }
String fileUrl = idMap.get(item.getId());
if (CommonUtil.isNotBlank(fileUrl)) {
item.setFileUrl(fileUrl);
}
purchaseOrderMapper.update(Wrappers.<ErpPurchaseOrderDO>lambdaUpdate()
.set(ErpPurchaseOrderDO::getDeliveryStatus, updateStatus)
.set(CommonUtil.isNotBlank(fileUrl), ErpPurchaseOrderDO::getFileUrl, fileUrl)
.eq(ErpPurchaseOrderDO::getId, item.getId()));
} }
purchaseOrderMapper.update(Wrappers.<ErpPurchaseOrderDO>lambdaUpdate()
.set(ErpPurchaseOrderDO::getDeliveryStatus, updateStatus)
.in(ErpPurchaseOrderDO::getId, ids));
if (updateStatus.equals(ErpDeliveryStatus.ARRIVAL)) { if (updateStatus.equals(ErpDeliveryStatus.ARRIVAL)) {
orderList.forEach(purchaseOrder -> { orderList.forEach(purchaseOrder -> {
...@@ -529,7 +538,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { ...@@ -529,7 +538,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// 通过代理对象调用,事务生效 // 通过代理对象调用,事务生效
proxyService.delivery(CommonUtil.asList(purchaseOrderId), supplierId, proxyService.delivery(SupplierPurchaseOrderDeliveryReqVO.transform(CommonUtil.asList(purchaseOrderId)), supplierId,
ErpDeliveryStatus.MATCHED, ErpDeliveryStatus.NOT_YET, CustomerOrderStatus.SUPPLIER_ACCEPT_ORDER); ErpDeliveryStatus.MATCHED, ErpDeliveryStatus.NOT_YET, CustomerOrderStatus.SUPPLIER_ACCEPT_ORDER);
} }
} }
......
...@@ -24,6 +24,8 @@ import org.springframework.validation.annotation.Validated; ...@@ -24,6 +24,8 @@ import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
import cn.iocoder.foodnexus.module.operations.controller.admin.inquirecustomerpush.vo.*; import cn.iocoder.foodnexus.module.operations.controller.admin.inquirecustomerpush.vo.*;
import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquirecustomerpush.InquireCustomerPushDO; import cn.iocoder.foodnexus.module.operations.dal.dataobject.inquirecustomerpush.InquireCustomerPushDO;
import cn.iocoder.foodnexus.framework.common.pojo.PageResult; import cn.iocoder.foodnexus.framework.common.pojo.PageResult;
...@@ -176,7 +178,13 @@ public class InquireCustomerPushServiceImpl implements InquireCustomerPushServic ...@@ -176,7 +178,13 @@ public class InquireCustomerPushServiceImpl implements InquireCustomerPushServic
if (list.size() == 1) { if (list.size() == 1) {
currentItemList.add(list.get(0)); currentItemList.add(list.get(0));
} else if (list.size() > 1) { } else if (list.size() > 1) {
currentItemList.add(list.stream().max(Comparator.comparing(InquirePriceItemDO::getCreateTime)).get()); List<InquirePriceItemDO> collect = list.stream().filter(itemPrice ->
supplierPushMapper.exists(Wrappers.<InquireSupplierPushDO>lambdaQuery()
.eq(InquireSupplierPushDO::getInquirePriceItemId, itemPrice.getId())
.eq(InquireSupplierPushDO::getConfirm, Boolean.TRUE))).toList();
if (CommonUtil.isNotEmpty(collect)) {
currentItemList.add(collect.stream().max(Comparator.comparing(InquirePriceItemDO::getCreateTime)).get());
}
} }
}); });
......
...@@ -96,6 +96,9 @@ public class InquirePriceServiceImpl implements InquirePriceService { ...@@ -96,6 +96,9 @@ public class InquirePriceServiceImpl implements InquirePriceService {
// 插入 // 插入
InquirePriceDO inquirePrice = BeanUtils.toBean(createReqVO, InquirePriceDO.class); InquirePriceDO inquirePrice = BeanUtils.toBean(createReqVO, InquirePriceDO.class);
inquirePrice.setIsPush(Boolean.FALSE); inquirePrice.setIsPush(Boolean.FALSE);
if (CommonUtil.isNotEmpty(createReqVO.getInquiryYearMonth())) {
createReqVO.setInquiryYearMonth(createReqVO.getInquiryYearMonth().length() >= 7 ? createReqVO.getInquiryYearMonth().substring(0, 7) : createReqVO.getInquiryYearMonth());
}
inquirePriceMapper.insert(inquirePrice); inquirePriceMapper.insert(inquirePrice);
inquirePriceItemService.addOrUpdateBatch(inquirePrice.getId(), createReqVO.getItems(), Boolean.FALSE); inquirePriceItemService.addOrUpdateBatch(inquirePrice.getId(), createReqVO.getItems(), Boolean.FALSE);
...@@ -112,6 +115,9 @@ public class InquirePriceServiceImpl implements InquirePriceService { ...@@ -112,6 +115,9 @@ public class InquirePriceServiceImpl implements InquirePriceService {
if (inquirePriceDO.getIsPush()) { if (inquirePriceDO.getIsPush()) {
throw exception("询价已推送,无法修改"); throw exception("询价已推送,无法修改");
} }
if (CommonUtil.isNotEmpty(updateReqVO.getInquiryYearMonth())) {
updateReqVO.setInquiryYearMonth(updateReqVO.getInquiryYearMonth().length() >= 7 ? updateReqVO.getInquiryYearMonth().substring(0, 7) : updateReqVO.getInquiryYearMonth());
}
// 更新 // 更新
InquirePriceDO updateObj = BeanUtils.toBean(updateReqVO, InquirePriceDO.class); InquirePriceDO updateObj = BeanUtils.toBean(updateReqVO, InquirePriceDO.class);
inquirePriceMapper.updateById(updateObj); inquirePriceMapper.updateById(updateObj);
......
...@@ -222,6 +222,7 @@ public class CustomerOrderServiceImpl implements CustomerOrderService, CustomerO ...@@ -222,6 +222,7 @@ public class CustomerOrderServiceImpl implements CustomerOrderService, CustomerO
Long customerId = customerApi.queryCustomerIdByUserId(loginUser.getId()); Long customerId = customerApi.queryCustomerIdByUserId(loginUser.getId());
List<CustomerWarehouseDO> customerWarehouse = customerWarehouseService.getCustomerWarehouseByCustomerId(customerId); List<CustomerWarehouseDO> customerWarehouse = customerWarehouseService.getCustomerWarehouseByCustomerId(customerId);
if (CommonUtil.isEmpty(customerWarehouse) || CommonUtil.isEmpty(customerWarehouse.get(0))) { if (CommonUtil.isEmpty(customerWarehouse) || CommonUtil.isEmpty(customerWarehouse.get(0))) {
log.error("客户订单下单失败,1_019_100_004, \"仓库不存在\", req:{}", createReqVO);
throw exception(CUSTOMER_ORDER_ADDRESS_NOEXISTS); throw exception(CUSTOMER_ORDER_ADDRESS_NOEXISTS);
} else { } else {
// TODO 理论上客户只对应一个库区 // TODO 理论上客户只对应一个库区
......
...@@ -80,10 +80,10 @@ public class ProductSpuController { ...@@ -80,10 +80,10 @@ public class ProductSpuController {
} }
@PutMapping("/pass-all") @PutMapping("/pass-all")
@Operation(summary = "审核通过所有产品") @Operation(summary = "上架所有产品")
@PreAuthorize("@ss.hasPermission('product:spu:update')") @PreAuthorize("@ss.hasPermission('product:spu:update')")
public CommonResult<Boolean> passAll(@RequestBody ProductSpuUpdateStatusBatchReqVO updateReqVO) { public CommonResult<Boolean> passAll() {
productSpuService.passAll(updateReqVO); productSpuService.passAll();
return success(Boolean.TRUE); return success(Boolean.TRUE);
} }
......
package cn.iocoder.foodnexus.module.product.controller.admin.spu.vo;
import cn.iocoder.foodnexus.framework.common.validation.InEnum;
import cn.iocoder.foodnexus.module.product.enums.spu.ProductSpuStatusEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import java.util.List;
@Schema(description = "管理后台 - 商品 SPU Status 更新 Request VO")
@Data
public class ProductSpuUpdateStatusBatchReqVO {
@Schema(description = "商品id集合(不传默认所有数据)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List<Long> ids;
@Schema(description = "商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
@NotNull(message = "商品状态不能为空")
@InEnum(ProductSpuStatusEnum.class)
private Integer status;
}
...@@ -6,7 +6,6 @@ import cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils; ...@@ -6,7 +6,6 @@ import cn.iocoder.foodnexus.framework.common.util.collection.CollectionUtils;
import cn.iocoder.foodnexus.module.customerpermission.core.annotation.CustomerVisible; import cn.iocoder.foodnexus.module.customerpermission.core.annotation.CustomerVisible;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusBatchReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuStatusRespVO; import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuStatusRespVO;
...@@ -156,7 +155,7 @@ public interface ProductSpuService { ...@@ -156,7 +155,7 @@ public interface ProductSpuService {
void audit(AuditCommonReqVO auditReqVO); void audit(AuditCommonReqVO auditReqVO);
void passAll(ProductSpuUpdateStatusBatchReqVO updateReqVO); void passAll();
default Map<Long, ProductSpuDO> getProductVOMap(Set<Long> longs) { default Map<Long, ProductSpuDO> getProductVOMap(Set<Long> longs) {
return this.getSpuMap(longs); return this.getSpuMap(longs);
......
...@@ -13,7 +13,6 @@ import cn.iocoder.foodnexus.module.erp.api.enums.ErpAuditStatus; ...@@ -13,7 +13,6 @@ import cn.iocoder.foodnexus.module.erp.api.enums.ErpAuditStatus;
import cn.iocoder.foodnexus.module.product.controller.admin.category.vo.ProductCategoryListReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.category.vo.ProductCategoryListReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuPageReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuPageReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuSaveReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusBatchReqVO;
import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO; import cn.iocoder.foodnexus.module.product.controller.admin.spu.vo.ProductSpuUpdateStatusReqVO;
import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuPageReqVO; import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuPageReqVO;
import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuStatusRespVO; import cn.iocoder.foodnexus.module.product.controller.app.spu.vo.AppProductSpuStatusRespVO;
...@@ -146,20 +145,25 @@ public class ProductSpuServiceImpl implements ProductSpuService { ...@@ -146,20 +145,25 @@ public class ProductSpuServiceImpl implements ProductSpuService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void passAll(ProductSpuUpdateStatusBatchReqVO updateReqVO) { public void passAll() {
List<ProductSpuDO> productSpuDOS = productSpuMapper.selectList(Wrappers.<ProductSpuDO>lambdaQuery() productSpuMapper.update(Wrappers.<ProductSpuDO>lambdaUpdate()
.in(CommonUtil.isNotEmpty(updateReqVO.getIds()), ProductSpuDO::getId, updateReqVO.getIds()) .set(ProductSpuDO::getStatus, ProductSpuStatusEnum.ENABLE.getStatus()));
.eq(ProductSpuDO::getAuditStatus, ErpAuditStatus.PROCESS.getStatus())); /*List<ProductSpuDO> productSpuDOS = productSpuMapper.selectList(Wrappers.<ProductSpuDO>lambdaQuery()
.eq(ProductSpuDO::getStatus, ProductSpuStatusEnum.)*/
if (CommonUtil.isNotEmpty(productSpuDOS)) { // .in(CommonUtil.isNotEmpty(updateReqVO.getIds()), ProductSpuDO::getId, updateReqVO.getIds())
AuditCommonReqVO auditCommonReqVO = new AuditCommonReqVO(); // .eq(ProductSpuDO::getAuditStatus, ErpAuditStatus.PROCESS.getStatus()));
/*if (CommonUtil.isNotEmpty(productSpuDOS)) {
*//*AuditCommonReqVO auditCommonReqVO = new AuditCommonReqVO();
auditCommonReqVO.setAuditReason("批量审核"); auditCommonReqVO.setAuditReason("批量审核");
auditCommonReqVO.setAuditStatus(updateReqVO.getStatus().toString()); auditCommonReqVO.setAuditStatus(updateReqVO.getStatus().toString());*//*
for (ProductSpuDO item : productSpuDOS) { for (ProductSpuDO item : productSpuDOS) {
auditCommonReqVO.setId(item.getId()); *//*auditCommonReqVO.setId(item.getId());
this.audit(auditCommonReqVO); this.audit(auditCommonReqVO);*//*
productSpuMapper.update(Wrappers.<ProductSpuDO>lambdaUpdate()
.);
} }
} }*/
} }
@Override @Override
......
...@@ -40,11 +40,11 @@ ...@@ -40,11 +40,11 @@
</dependency>--> </dependency>-->
<!-- 数据报表。默认注释,保证编译速度 --> <!-- 数据报表。默认注释,保证编译速度 -->
<!--<dependency> <dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
<artifactId>foodnexus-module-report</artifactId> <artifactId>foodnexus-module-report</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency>--> </dependency>
<!-- 工作流。默认注释,保证编译速度 --> <!-- 工作流。默认注释,保证编译速度 -->
<!--<dependency> <!--<dependency>
<groupId>cn.iocoder.boot</groupId> <groupId>cn.iocoder.boot</groupId>
......
server:
port: 49080
--- #################### 数据库相关配置 ####################
spring:
autoconfigure:
# noinspection SpringBootApplicationYaml
exclude:
- org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建
- org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建
# 数据源配置项
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: false
stat-view-servlet:
enabled: false
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: # 控制台管理用户名和密码
login-password:
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒(1 分钟)
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒(1 分钟)
min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒(10 分钟)
max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒(30 分钟)
validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
pool-prepared-statements: true # 是否开启 PreparedStatement 缓存
max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量
primary: master
datasource:
master:
url: jdbc:mysql://10.128.19.99:3316/foodnexus?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: foodnexus
password: X6e3ztPiWTzJpwz3
slave: # 模拟从库,可根据自己需要修改 # 模拟从库,可根据自己需要修改
lazy: true # 开启懒加载,保证启动速度
url: jdbc:mysql://10.128.19.99:3316/foodnexus?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
username: foodnexus
password: X6e3ztPiWTzJpwz3
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data:
redis:
host: 10.128.19.99 # 地址
port: 16379 # 端口
database: 9 # 数据库索引
password: 'd43ed845' # 密码,建议生产环境开启
--- #################### 定时任务相关配置 ####################
# Quartz 配置项,对应 QuartzProperties 配置类
spring:
quartz:
auto-startup: true # 测试环境,需要开启 Job
scheduler-name: schedulerName # Scheduler 名字。默认为 schedulerName
job-store-type: jdbc # Job 存储器类型。默认为 memory 表示内存,可选 jdbc 使用数据库。
wait-for-jobs-to-complete-on-shutdown: true # 应用关闭时,是否等待定时任务执行完成。默认为 false ,建议设置为 true
properties: # 添加 Quartz Scheduler 附加属性,更多可以看 http://www.quartz-scheduler.org/documentation/2.4.0-SNAPSHOT/configuration.html 文档
org:
quartz:
# Scheduler 相关配置
scheduler:
instanceName: schedulerName
instanceId: AUTO # 自动生成 instance ID
# JobStore 相关配置
jobStore:
# JobStore 实现类。可见博客:https://blog.csdn.net/weixin_42458219/article/details/122247162
class: org.springframework.scheduling.quartz.LocalDataSourceJobStore
isClustered: true # 是集群模式
clusterCheckinInterval: 15000 # 集群检查频率,单位:毫秒。默认为 15000,即 15 秒
misfireThreshold: 60000 # misfire 阀值,单位:毫秒。
# 线程池相关配置
threadPool:
threadCount: 25 # 线程池大小。默认为 10 。
threadPriority: 5 # 线程优先级
class: org.quartz.simpl.SimpleThreadPool # 线程池类型
jdbc: # 使用 JDBC 的 JobStore 的时候,JDBC 的配置
initialize-schema: NEVER # 是否自动使用 SQL 初始化 Quartz 表结构。这里设置成 never ,我们手动创建表结构。
--- #################### 消息队列相关 ####################
# rocketmq 配置项,对应 RocketMQProperties 配置类
rocketmq:
name-server: 127.0.0.1:9876 # RocketMQ Namesrv
spring:
# RabbitMQ 配置项,对应 RabbitProperties 配置类
rabbitmq:
host: 127.0.0.1 # RabbitMQ 服务的地址
port: 5672 # RabbitMQ 服务的端口
username: guest # RabbitMQ 服务的账号
password: guest # RabbitMQ 服务的密码
# Kafka 配置项,对应 KafkaProperties 配置类
kafka:
bootstrap-servers: 127.0.0.1:9092 # 指定 Kafka Broker 地址,可以设置多个,以逗号分隔
--- #################### 服务保障相关配置 ####################
# Lock4j 配置项
lock4j:
acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
--- #################### 监控相关配置 ####################
# Actuator 监控端点的配置项
management:
endpoints:
web:
base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
# Spring Boot Admin 配置项
spring:
boot:
admin:
# Spring Boot Admin Client 客户端的相关配置
client:
url: http://127.0.0.1:${server.port}/${spring.boot.admin.context-path} # 设置 Spring Boot Admin Server 地址
instance:
service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
# Spring Boot Admin Server 服务端的相关配置
context-path: /admin # 配置 Spring
# 日志文件配置
logging:
file:
name: ${user.home}/logs/${spring.application.name}.log # 日志文件名,全路径
--- #################### 微信公众号相关配置 ####################
wx: # 参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-mp-spring-boot-starter/README.md 文档
mp:
# 公众号配置(必填)
app-id: wx041349c6f39b268b
secret: 5abee519483bc9f8cb37ce280e814bd0
# 存储配置,解决 AccessToken 的跨节点的共享
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
key-prefix: wx # Redis Key 的前缀
http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档
appid: wx63c280fe3248a3e7
secret: 6f270509224a7ae1296bbf1c8cb97aed
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
key-prefix: wa # Redis Key 的前缀
http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
--- #################### 芋道相关配置 ####################
# 芋道配置项,设置当前项目所有自定义的配置
foodnexus:
captcha:
enable: false # 本地环境,暂时关闭图片验证码,方便登录等接口的测试;
pay:
order-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/order # 支付渠道的【支付】回调地址
refund-notify-url: http://yunai.natapp1.cc/admin-api/pay/notify/refund # 支付渠道的【退款】回调地址
transfer-notify-url: https://yunai.natapp1.cc/admin-api/pay/notify/transfer # 支付渠道的【转账】回调地址
demo: false # 开启演示模式
tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc
justauth:
enabled: true
type:
DINGTALK: # 钉钉
client-id: dingvrnreaje3yqvzhxg
client-secret: i8E6iZyDvZj51JIb0tYsYfVQYOks9Cq1lgryEjFRqC79P3iJcrxEwT6Qk2QvLrLI
ignore-check-redirect-uri: true
WECHAT_ENTERPRISE: # 企业微信
client-id: wwd411c69a39ad2e54
client-secret: 1wTb7hYxnpT2TUbIeHGXGo7T0odav1ic10mLdyyATOw
agent-id: 1000004
ignore-check-redirect-uri: true
# noinspection SpringBootApplicationYaml
WECHAT_MINI_PROGRAM: # 微信小程序
client-id: ${wx.miniapp.appid}
client-secret: ${wx.miniapp.secret}
ignore-check-redirect-uri: true
ignore-check-state: true # 微信小程序,不会使用到 state,所以不进行校验
WECHAT_MP: # 微信公众号
client-id: ${wx.mp.app-id}
client-secret: ${wx.mp.secret}
ignore-check-redirect-uri: true
cache:
type: REDIS
prefix: 'social_auth_state:' # 缓存前缀,目前只对 Redis 缓存生效,默认 JUSTAUTH::STATE::
timeout: 24h # 超时时长,目前只对 Redis 缓存生效,默认 3 分钟
--- #################### iot相关配置 TODO 芋艿:再瞅瞅 ####################
iot:
emq:
# 账号
username: anhaohao
# 密码
password: ahh@123456
# 主机地址
hostUrl: tcp://chaojiniu.top:1883
# 客户端Id,不能相同,采用随机数 ${random.value}
client-id: ${random.int}
# 默认主题
default-topic: test
# 保持连接
keepalive: 60
# 清除会话(设置为false,断开连接,重连后使用原来的会话 保留订阅的主题,能接收离线期间的消息)
clearSession: true
# 插件配置
pf4j:
pluginsDir: ${user.home}/plugins # 插件目录
springdoc:
api-docs:
enabled: false
swagger-ui:
enabled: false
\ No newline at end of file
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