修改下单邮箱模板

This commit is contained in:
wwb 2025-12-09 08:17:46 +08:00
parent 63c2099a74
commit 7c7db11e9f
24 changed files with 497 additions and 67 deletions

View File

@ -6,6 +6,7 @@ import lombok.Data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Schema(description = "分页结果")
@Data
@ -17,6 +18,10 @@ public final class PageResult<T> implements Serializable {
@Schema(description = "总量", requiredMode = Schema.RequiredMode.REQUIRED)
private Long total;
@Schema(description = "其他数据")
private Map<String,Object> otherMap;
public PageResult() {
}

View File

@ -27,5 +27,6 @@ public interface ErrorCodeConstants extends cn.hangtag.module.system.enums.Erro
ErrorCode PRODUCT_PRICE_NOT_EXISTS = new ErrorCode(600, "产品单价记录不存在");
ErrorCode CUSTOMER_EMAIL_EXISTS = new ErrorCode(600, "已存在重复的客户邮箱号");
ErrorCode SALE_ORDER_NOT_FILE_EXPORT = new ErrorCode(7000, "订单中没有可导出的稿件");
ErrorCode SALE_ORDER_NOT_ATTRFILE_EXPORT = new ErrorCode(7000, "订单中没有可导出的附件");
ErrorCode CUSTOMER_GROUP_NOT_EXISTS = new ErrorCode(7100, "客户组别 不存在");
}

View File

@ -22,6 +22,7 @@ import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.saleorder.SaleOrderService;
import cn.hangtag.module.system.api.user.AdminUserApi;
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
@ -43,6 +44,7 @@ import java.util.Map;
import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.hangtag.framework.common.pojo.CommonResult.error;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
import static cn.hangtag.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "APP - 销售订单")
@RestController
@ -109,7 +111,19 @@ public class AppSaleOrderController{
if(customer!=null){
pageReqVO.setCustomerId(customer.getId());
PageResult<SaleOrderDO> pageResult = saleOrderService.getSaleOrderPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, SaleOrderRespVO.class));
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}else{
// 拼接数据
Map<Long, CustomerDO> deptMap = customerService.getCustomerMap(
convertList(pageResult.getList(), SaleOrderDO::getCustomerId));
// 拼接数据
Map<Long, BrandDO> brandMap = brandService.getBrandMap(
convertList(pageResult.getList(), SaleOrderDO::getBrandId));
return success(new PageResult<>(SaleOrderConvert.INSTANCE.convertList(pageResult.getList(), deptMap,brandMap),
pageResult.getTotal()));
}
}
return error(new ErrorCode(99999,"该用户未绑定客户资料,请联系管理员维护数据!"));
}

View File

@ -1,47 +1,50 @@
package cn.hangtag.module.oms.controller.admin.saleorder;
import cn.hangtag.framework.apilog.core.annotation.ApiAccessLog;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.util.number.NumberUtils;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.framework.excel.core.util.ExcelUtils;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderPageReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRemarkReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRespVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderSaveReqVO;
import cn.hangtag.module.oms.convert.saleorder.SaleOrderConvert;
import cn.hangtag.module.oms.dal.dataobject.brand.BrandDO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.service.brand.BrandService;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.system.api.user.AdminUserApi;
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.fastjson.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.security.access.prepost.PreAuthorize;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.Operation;
import javax.annotation.security.PermitAll;
import javax.validation.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.IOException;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.CommonResult;
import cn.hangtag.framework.common.util.object.BeanUtils;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
import cn.hangtag.framework.excel.core.util.ExcelUtils;
import cn.hangtag.framework.apilog.core.annotation.ApiAccessLog;
import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.*;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.*;
import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
import cn.hangtag.module.oms.dal.dataobject.saleorderentry.SaleOrderEntryDO;
import cn.hangtag.module.oms.service.brand.BrandService;
import cn.hangtag.module.oms.service.customer.CustomerService;
import cn.hangtag.module.oms.service.saleorder.SaleOrderService;
import cn.hangtag.module.system.api.user.AdminUserApi;
import cn.hangtag.module.system.api.user.dto.AdminUserRespDTO;
import cn.hangtag.module.system.dal.dataobject.dept.DeptDO;
import cn.hangtag.module.system.dal.dataobject.user.AdminUserDO;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import static cn.hangtag.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.hangtag.framework.common.pojo.CommonResult.success;
import static cn.hangtag.framework.common.util.collection.CollectionUtils.convertList;
@Tag(name = "管理后台 - 销售订单")
@RestController
@ -110,7 +113,20 @@ public class SaleOrderController {
// @PreAuthorize("@ss.hasPermission('oms:sale-order:query')")
public CommonResult<PageResult<SaleOrderRespVO>> getSaleOrderPage(@Valid SaleOrderPageReqVO pageReqVO) {
PageResult<SaleOrderDO> pageResult = saleOrderService.getSaleOrderPage(pageReqVO);
return success(BeanUtils.toBean(pageResult, SaleOrderRespVO.class));
if (CollUtil.isEmpty(pageResult.getList())) {
return success(new PageResult<>(pageResult.getTotal()));
}
// 拼接数据
Map<Long, CustomerDO> deptMap = customerService.getCustomerMap(
convertList(pageResult.getList(), SaleOrderDO::getCustomerId));
// 拼接数据
Map<Long, BrandDO> brandMap = brandService.getBrandMap(
convertList(pageResult.getList(), SaleOrderDO::getBrandId));
PageResult<SaleOrderRespVO> saleOrderRespVOPageResult = new PageResult<>(SaleOrderConvert.INSTANCE.convertList(pageResult.getList(), deptMap,brandMap),
pageResult.getTotal());
saleOrderRespVOPageResult.setOtherMap(pageResult.getOtherMap());
return success(saleOrderRespVOPageResult);
}
@GetMapping("/export-excel")

View File

@ -21,6 +21,15 @@ public class SaleOrderPageReqVO extends PageParam {
@Schema(description = "客户id", example = "10257")
private Long customerId;
@Schema(description = "客户名称", example = "10257")
private String customerName;
@Schema(description = "品牌名称", example = "10257")
private String brandName;
@Schema(description = "物料名称", example = "10257")
private String materialName;
@Schema(description = "业务日期")
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
private LocalDateTime[] bizdate;

View File

@ -8,6 +8,8 @@ import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.enums.DictTypeConstants;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import org.springframework.format.annotation.DateTimeFormat;
import java.time.LocalDateTime;
@ -55,6 +57,15 @@ public class SaleOrderRespVO {
@DictFormat(DictTypeConstants.OMS_CURRENCY_TYPE)
private String currencyType;
@Schema(description = "总数量")
@ExcelProperty("总数量")
private Integer totalQty;
@Schema(description = "总金额")
@ExcelProperty("总金额")
private BigDecimal orderAmount;
@Schema(description = "业务日期")
@ExcelProperty("业务日期")
private LocalDateTime bizdate;
@ -133,6 +144,9 @@ public class SaleOrderRespVO {
@Schema(description = "客户")
private CustomerRespVO customer;
@Schema(description = "品牌")
private BrandRespVO brand;
@Schema(description = "产品明细")
private List<cn.hangtag.module.oms.dal.dataobject.saleorderentry.SaleOrderEntryDO> entrys;

View File

@ -1,6 +1,9 @@
package cn.hangtag.module.oms.convert.saleorder;
import cn.hangtag.framework.common.util.collection.CollectionUtils;
import cn.hangtag.framework.common.util.object.BeanUtils;
import cn.hangtag.module.oms.controller.admin.brand.vo.BrandRespVO;
import cn.hangtag.module.oms.controller.admin.customer.vo.CustomerRespVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRemarkReqVO;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderRespVO;
@ -15,6 +18,7 @@ import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;
import java.util.List;
import java.util.Map;
@Mapper
public interface SaleOrderConvert {
@ -29,13 +33,17 @@ public interface SaleOrderConvert {
@Mapping(source = "contractType", target = "contractType"),
@Mapping(source = "currencyType", target = "currencyType"),
@Mapping(source = "brandId", target = "brandId"),
@Mapping(source = "saleContractCode", target = "saleContractCode")
@Mapping(source = "saleContractCode", target = "saleContractCode"),
@Mapping(source = "totalQty", target = "totalQty"),
@Mapping(source = "orderAmount", target = "orderAmount")
})
SaleOrderRespVO convert(SaleOrderDO bean);
CustomerRespVO convert(CustomerDO bean);
BrandRespVO convert(BrandDO bean);
SaleOrderDO convert(SaleOrderRemarkReqVO reqVO);
@ -63,5 +71,19 @@ public interface SaleOrderConvert {
}
default List<SaleOrderRespVO> convertList(List<SaleOrderDO> list, Map<Long, CustomerDO> customerMap,Map<Long, BrandDO> brandMap) {
return CollectionUtils.convertList(list, user -> convert(user, customerMap.get(user.getCustomerId()),brandMap.get(user.getBrandId())));
}
default SaleOrderRespVO convert(SaleOrderDO user, CustomerDO customer,BrandDO brandDO) {
SaleOrderRespVO userVO = BeanUtils.toBean(user, SaleOrderRespVO.class);
if (customer != null) {
userVO.setCustomer(convert(customer));
}
if(brandDO != null){
userVO.setBrand(convert(brandDO));
}
return userVO;
}
}

View File

@ -42,6 +42,7 @@ public class SaleOrderDO extends BaseDO {
* 客户id
*/
private Long customerId;
/**
* 业务日期
*/
@ -183,6 +184,11 @@ public class SaleOrderDO extends BaseDO {
*/
private String logisticsCode;
/**
* 总数量
*/
private Integer totalQty;
/**
* 下单客户上传的 附件文件 infra_file id
* 允许多个

View File

@ -3,13 +3,14 @@ package cn.hangtag.module.oms.dal.mysql.saleorder;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.mybatis.core.mapper.BaseMapperX;
import cn.hangtag.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.hangtag.framework.mybatis.core.query.MPJLambdaWrapperX;
import cn.hangtag.module.oms.controller.admin.saleorder.vo.SaleOrderPageReqVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderSummaryRespVO;
import cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderTrendRespVO;
import cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO;
import cn.hangtag.module.oms.enums.common.BillStatusEnum;
import cn.hangtag.module.oms.enums.saleorder.SaleOrderStatusEnum;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
@ -26,9 +27,8 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
default PageResult<SaleOrderDO> selectPage(SaleOrderPageReqVO reqVO) {
String tabType = reqVO.getTabType();
LambdaQueryWrapperX<SaleOrderDO> queryWrapper = new LambdaQueryWrapperX<SaleOrderDO>()
MPJLambdaWrapperX<SaleOrderDO> queryWrapper = new MPJLambdaWrapperX<SaleOrderDO>()
.eqIfPresent(SaleOrderDO::getBillno, reqVO.getBillno())
.eqIfPresent(SaleOrderDO::getCustomerId, reqVO.getCustomerId())
.betweenIfPresent(SaleOrderDO::getBizdate, reqVO.getBizdate())
.betweenIfPresent(SaleOrderDO::getConfirmdate, reqVO.getConfirmdate())
.betweenIfPresent(SaleOrderDO::getPlansenddate, reqVO.getPlansenddate())
@ -37,7 +37,7 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
.eqIfPresent(SaleOrderDO::getBillStatus, reqVO.getBillStatus())
.eqIfPresent(SaleOrderDO::getOrderStatus, reqVO.getOrderStatus())
.orderByDesc(SaleOrderDO::getId);
appendTabQuery(tabType, queryWrapper);
appendTabQuery(tabType, queryWrapper,reqVO);
queryWrapper.orderByDesc(SaleOrderDO::getCreateTime);
return selectPage(reqVO, queryWrapper);
@ -50,7 +50,7 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
* @param tabType 标签类型
* @param query 查询条件
*/
default void appendTabQuery(String tabType, LambdaQueryWrapperX<SaleOrderDO> query) {
default void appendTabQuery(String tabType, MPJLambdaWrapperX<SaleOrderDO> query,SaleOrderPageReqVO reqVO) {
// 待审核
if (ObjectUtil.equals(BillStatusEnum.SUBMIT.getValue(), tabType)) {
query.eqIfPresent(SaleOrderDO::getBillStatus, BillStatusEnum.SUBMIT.getValue());
@ -66,6 +66,9 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
}
IPage<SaleOrderDO> selectPageV2(IPage<SaleOrderDO> page, @Param("reqVO") SaleOrderPageReqVO reqVO);
TradeOrderSummaryRespVO selectOrderQtySummaryByOrderStatusAndCreateTimeBetween(@Param("orderStatus") String orderStatus,
@Param("beginTime") LocalDateTime beginTime,
@Param("endTime") LocalDateTime endTime,@Param("customerId") Long customerId);
@ -90,4 +93,14 @@ public interface SaleOrderMapper extends BaseMapperX<SaleOrderDO> {
*/
List<TradeOrderTrendRespVO> selectListByPayTimeBetweenAndGroupByMonth(@Param("beginTime") LocalDateTime beginTime,
@Param("endTime") LocalDateTime endTime);
/**
* 更新汇总销售订单总数量总金额
* @param ids
* @return
*/
int updateSumQtyOrAmount(List<Long> ids);
long querySumTotalQty(@Param("reqVO") SaleOrderPageReqVO reqVO);
}

View File

@ -2,10 +2,13 @@ package cn.hangtag.module.oms.service.brand;
import java.util.*;
import javax.validation.*;
import cn.hangtag.framework.common.util.collection.CollectionUtils;
import cn.hangtag.module.oms.controller.admin.brand.vo.*;
import cn.hangtag.module.oms.dal.dataobject.brand.BrandDO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.framework.common.pojo.PageParam;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import static java.util.Collections.singleton;
@ -80,4 +83,23 @@ public interface BrandService {
Integer updateProductCount(Long id);
BrandDO getBrandByName(String brandName);
/**
* 获得客户信息数组
*
* @param ids 客户编号数组
* @return 客户信息数组
*/
List<BrandDO> getBrandList(Collection<Long> ids);
/**
* 获得指定编号的品牌 Map
*
* @param ids 客户编号数组
* @return 客户 Map
*/
default Map<Long, BrandDO> getBrandMap(Collection<Long> ids) {
List<BrandDO> list = getBrandList(ids);
return CollectionUtils.convertMap(list, BrandDO::getId);
}
}

View File

@ -183,6 +183,14 @@ public class BrandServiceImpl implements BrandService {
return null;
}
@Override
public List<BrandDO> getBrandList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return brandMapper.selectBatchIds(ids);
}
private void checkCode(Long id, String code) {
if (FuncUtil.isNotEmpty(code)) {

View File

@ -2,11 +2,14 @@ package cn.hangtag.module.oms.service.customer;
import java.util.*;
import javax.validation.*;
import cn.hangtag.framework.common.util.collection.CollectionUtils;
import cn.hangtag.module.oms.controller.admin.customer.vo.*;
import cn.hangtag.module.oms.controller.admin.customer.front.vo.CustomerInfoVO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerDO;
import cn.hangtag.module.oms.dal.dataobject.customer.CustomerAddressDO;
import cn.hangtag.framework.common.pojo.PageResult;
import cn.hangtag.module.system.dal.dataobject.dept.DeptDO;
/**
* 客户 Service 接口
@ -80,4 +83,26 @@ public interface CustomerService {
* @return {@link CustomerDO }
*/
CustomerDO getCanUseCustomer(Long userId);
/**
* 获得客户信息数组
*
* @param ids 客户编号数组
* @return 客户信息数组
*/
List<CustomerDO> getCustomerList(Collection<Long> ids);
/**
* 获得指定编号的客户 Map
*
* @param ids 客户编号数组
* @return 客户 Map
*/
default Map<Long, CustomerDO> getCustomerMap(Collection<Long> ids) {
List<CustomerDO> list = getCustomerList(ids);
return CollectionUtils.convertMap(list, CustomerDO::getId);
}
}

View File

@ -16,6 +16,7 @@ import cn.hangtag.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.hangtag.module.system.dal.dataobject.user.AdminUserDO;
import cn.hangtag.module.system.service.permission.PermissionService;
import cn.hangtag.module.system.service.user.AdminUserService;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
@ -290,4 +291,12 @@ public class CustomerServiceImpl implements CustomerService {
return customerDO;
}
@Override
public List<CustomerDO> getCustomerList(Collection<Long> ids) {
if (CollUtil.isEmpty(ids)) {
return Collections.emptyList();
}
return customerMapper.selectBatchIds(ids);
}
}

View File

@ -66,13 +66,18 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Maps;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
@ -194,6 +199,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
saleOrderMapper.updateById(updateObj);
// 更新子表
updateSaleOrderEntryList(updateReqVO.getId(), updateReqVO.getEntrys());
saleOrderMapper.updateSumQtyOrAmount(Collections.singletonList(updateReqVO.getId()));
}
@Override
@ -231,7 +237,27 @@ public class SaleOrderServiceImpl implements SaleOrderService {
@Override
public PageResult<SaleOrderDO> getSaleOrderPage(SaleOrderPageReqVO pageReqVO) {
return saleOrderMapper.selectPage(pageReqVO);
IPage<SaleOrderDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
// 待审核
if (ObjectUtil.equals(BillStatusEnum.SUBMIT.getValue(), pageReqVO.getTabType())) {
pageReqVO.setBillStatus(BillStatusEnum.SUBMIT.getValue());
}
// 待排产
if (ObjectUtil.equals(BillStatusEnum.AUDIT.getValue(), pageReqVO.getTabType())) {
pageReqVO.setBillStatus(BillStatusEnum.AUDIT.getValue());
}
// 已排产
if (ObjectUtil.equals(BillStatusEnum.YPLAN.getValue(), pageReqVO.getTabType())) {
pageReqVO.setBillStatus(BillStatusEnum.YPLAN.getValue());
}
saleOrderMapper.selectPageV2(page,pageReqVO);
PageResult<SaleOrderDO> saleOrderDOPageResult = new PageResult<>(page.getRecords(), page.getTotal());
saleOrderDOPageResult.setOtherMap(MapUtil.of("querySumTotalQty",BigDecimal.ZERO));
if(!StringUtils.isAllBlank(pageReqVO.getCustomerName(),pageReqVO.getBrandName(),pageReqVO.getMaterialName())){
long sumTotalQty = saleOrderMapper.querySumTotalQty(pageReqVO);
saleOrderDOPageResult.setOtherMap(MapUtil.of("querySumTotalQty",sumTotalQty));
}
return saleOrderDOPageResult;
}
// ==================== 子表销售订单明细 ====================
@ -318,6 +344,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
saleOrder.setOrderStatus(SaleOrderStatusEnum.YXD.getValue());
saleOrder.setRejectReason((String) params.get("rejectReason"));
saleOrderMapper.updateById(saleOrder);
saleOrderMapper.updateSumQtyOrAmount(Collections.singletonList(saleOrder.getId()));
}
}
break;
@ -340,6 +367,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
saleOrder.setBillStatus(BillStatusEnum.SUBMIT.getValue());
saleOrder.setOrderStatus(SaleOrderStatusEnum.SCZ.getValue());
saleOrderMapper.updateById(saleOrder);
saleOrderMapper.updateSumQtyOrAmount(Collections.singletonList(saleOrder.getId()));
} else {
if (BillStatusEnum.INVALID.getValue().equals(saleOrder.getBillStatus())) {
throw new ServiceException(001, "订单状态已作废,不允许提交!");
@ -454,6 +482,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
saleOrder.setBillStatus(BillStatusEnum.SUBMIT.getValue());
saleOrder.setOrderStatus(SaleOrderStatusEnum.YXD.getValue());
saleOrderMapper.updateById(saleOrder);
saleOrderMapper.updateSumQtyOrAmount(Collections.singletonList(saleOrder.getId()));
}
break;
}
@ -817,18 +846,72 @@ public class SaleOrderServiceImpl implements SaleOrderService {
for (AdminUserDO user : userList) {
MailSendMessage message = new MailSendMessage();
message.setAccountId(1L);
message.setMail(user.getEmail());
message.setTitle("OMS订单系统 "+order.getSaleContractCode()+" "+createTimestr);
StringBuffer content = new StringBuffer();
content.append("您好,客户:【" + customerDO.getName() + "】 来新的订单啦,订单号:" + order.getBillno() + ",下单时间:" + createTimestr + " 请进行处理!");
message.setContent(content.toString());
//message.setMail(user.getEmail());
message.setMail("782276617@qq.com");
message.setTitle("OMS订单系统");
//StringBuffer content = new StringBuffer();
//content.append("您好,客户:【" + customerDO.getName() + "】 来新的订单啦,订单号:" + order.getBillno() + ",下单时间:" + createTimestr + " 请进行处理!");
String htmlcontent = generateMailSendHtmlContent(order, entryList);
message.setContent(htmlcontent);
mailSendService.doSendMail(message);
}
}
return order.getId();
}
private String generateMailSendHtmlContent(SaleOrderDO saleOrder,List<SaleOrderEntryDO> entrys) {
CustomerDO customer = customerService.getCustomer(saleOrder.getCustomerId());
Context context = new Context();
context.setVariable("title", customer.getName());
context.setVariable("contractNo", saleOrder.getContractCode());
JSONArray items = new JSONArray();
for (int i = 0; i < entrys.size(); i++) {
SaleOrderEntryDO entry = entrys.get(i);
ProductInfoDO productInfo = productInfoService.getProductInfo(entry.getMaterialId());
Double specSizeHeight = productInfo.getSpecSizeHeight();
Double specSizeWidth = productInfo.getSpecSizeWidth();
Double specSizeThk = productInfo.getSpecSizeThk();
StringBuilder specBuilder = new StringBuilder();
// 处理宽度
Double width = FuncUtil.toDouble(specSizeWidth, 0d);
if (width > 0) {
specBuilder.append(width);
}
Double height = FuncUtil.toDouble(specSizeHeight, 0d);
if ( height > 0) {
if (specBuilder.length() > 0) {
specBuilder.append(" * ");
}
specBuilder.append(height);
}
Double thickness = FuncUtil.toDouble(specSizeThk, 0d);
if (thickness > 0) {
if (specBuilder.length() > 0) {
specBuilder.append(" ");
}
specBuilder.append(thickness);
}
String spec = specBuilder.toString();
int j = i + 1;
JSONObject item = new JSONObject();
item.put("itemcode", productInfo.getCode());
item.put("itemname", productInfo.getName());
item.put("itemdesc", spec);
item.put("unit", entry.getUnit());
item.put("qty", entry.getQty());
items.add(item);
}
context.setVariable("items",items);
return templateEngine.process("createorder_email", context);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Long editOrder(Long id, CreateSaleOrderDTO dto) {
@ -1368,13 +1451,13 @@ public class SaleOrderServiceImpl implements SaleOrderService {
queryWrapper.eq(SaleOrderDO::getId, id);
List<SaleOrderDO> entityData = saleOrderMapper.selectList(queryWrapper);
if (FuncUtil.isEmpty(entityData)) {
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_ATTRFILE_EXPORT);
}
String accessoryFileIds = entityData.get(0).getAccessoryFileIds();
if(StringUtils.isBlank(accessoryFileIds)){
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_ATTRFILE_EXPORT);
}
List<FileInfoVO> fileInfo = fileApi.getFileInfo(accessoryFileIds);
@ -1416,7 +1499,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
}
}
if (FuncUtil.isEmpty(files)) {
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_FILE_EXPORT);
throw exception(ErrorCodeConstants.SALE_ORDER_NOT_ATTRFILE_EXPORT);
}
String zipFileName = StrUtil.format(pathUrl + "/销售订单附件_{}.zip", entityData.get(0).getBillno());

View File

@ -3,6 +3,29 @@
<mapper namespace="cn.hangtag.module.oms.dal.mysql.saleorder.SaleOrderMapper">
<select id="selectPageV2" resultType="cn.hangtag.module.oms.dal.dataobject.saleorder.SaleOrderDO">
select a.* from oms_saleorder a
left join oms_saleorder_entry b on a.id = b.parent_id
left join oms_customer cus on cus.id = a.customer_id
left join oms_brand brand on brand.id = a.brand_id
<where>
<if test="reqVO.billno != null and reqVO.billno != '' "> AND a.billno = #{reqVO.billno} </if>
<if test="reqVO.bizdate != null "> AND a.bizdate between #{reqVO.bizdate[0]} AND #{reqVO.bizdate[1]}</if>
<if test="reqVO.confirmdate != null "> AND a.confirmdate between #{reqVO.confirmdate[0]} AND #{reqVO.confirmdate[1}</if>
<if test="reqVO.plansenddate != null "> AND a.plansenddate between #{reqVO.plansenddate[0]} AND #{reqVO.plansenddate[1}</if>
<if test="reqVO.phone != null and reqVO.phone != '' "> AND a.phone = #{reqVO.phone} </if>
<if test="reqVO.remarks != null and reqVO.remarks != '' "> AND a.remarks = #{reqVO.remarks} </if>
<if test="reqVO.billStatus != null and reqVO.billStatus != '' "> AND a.bill_status = #{reqVO.billStatus} </if>
<if test="reqVO.orderStatus != null and reqVO.orderStatus != '' "> AND a.order_status = #{reqVO.orderStatus} </if>
<if test="reqVO.materialName != null and reqVO.materialName != '' "> AND (b.material_number LIKE CONCAT('%',#{reqVO.materialName},'%') OR b.material_name LIKE CONCAT('%',#{reqVO.materialName},'%')) </if>
<if test="reqVO.customerName != null and reqVO.customerName != '' "> AND cus.name LIKE CONCAT('%',#{reqVO.customerName},'%') </if>
<if test="reqVO.brandName != null and reqVO.brandName != '' "> AND brand.name LIKE CONCAT('%',#{reqVO.brandName},'%') </if>
</where>
order by create_time desc
</select>
<select id="selectOrderQtySummaryByOrderStatusAndCreateTimeBetween"
resultType="cn.hangtag.module.oms.controller.admin.trade.vo.TradeOrderSummaryRespVO">
@ -48,5 +71,29 @@
</select>
<select id="querySumTotalQty" resultType="Long" >
select sum(a.total_qty) from oms_saleorder a
left join oms_saleorder_entry b on a.id = b.parent_id
left join oms_customer cus on cus.id = a.customer_id
left join oms_brand brand on brand.id = a.brand_id
<where>
<if test="reqVO.materialName != null and reqVO.materialName != '' "> AND (b.material_number LIKE CONCAT('%',#{reqVO.materialName},'%') OR b.material_name LIKE CONCAT('%',#{reqVO.materialName},'%')) </if>
<if test="reqVO.customerName != null and reqVO.customerName != '' "> AND cus.name LIKE CONCAT('%',#{reqVO.customerName},'%') </if>
<if test="reqVO.brandName != null and reqVO.brandName != '' "> AND brand.name LIKE CONCAT('%',#{reqVO.brandName},'%') </if>
</where>
</select>
<update id="updateSumQtyOrAmount" parameterType="Long">
UPDATE oms_saleorder a
JOIN (
SELECT parent_id, SUM(qty) AS total_qty, SUM(amount) AS total_amount FROM oms_saleorder_entry GROUP BY parent_id
) s ON a.id = s.parent_id
SET a.total_qty = COALESCE(s.total_qty, 0), a.order_amount = COALESCE(s.total_amount, 0)
WHERE id in
<foreach item="id" collection="list" open="(" separator="," close=")">
#{id}
</foreach>
</update>
</mapper>

View File

@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>OMS订单系统</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 25px;
line-height: 1.8;
font-size: 14px; /* 贴近原图字体大小 */
color: #333;
}
h2 {
font-size: 16px;
margin: 0 0 15px 0;
font-weight: 600;
}
h3 {
font-size: 15px;
margin: 20px 0 10px 0;
font-weight: 600;
}
p {
margin: 8px 0;
}
.highlight {
background-color: #ffeb3b; /* 更接近原图的黄色高亮 */
padding: 2px 4px;
font-weight: 600;
}
table {
border-collapse: collapse;
width: 100%;
margin-top: 15px;
font-size: 13px;
}
th, td {
border: 1px solid #999; /* 加深表格边框更贴近原图 */
padding: 10px 8px;
text-align: left;
}
th {
background-color: #f5f5f5; /* 更自然的表头背景色 */
font-weight: 600;
}
a {
color: #0000ee;
text-decoration: underline;
}
a:hover {
color: #551a8b;
}
</style>
</head>
<body>
<h2 th:text="${title}">Dear 安徽亮志服装有限公司</h2>
<p>Thank you for your order for:</p>
<br/>
<p>For Order Tracking, please click the following link<br>
<a href="http://oms.silverprinting.com.hk/">http://oms.silverprinting.com.hk/</a></p>
<br/>
<p>Customer PO#* : <span th:text="${contractNo}">T25-24907</span><br>
<!-- E-Order# *: EPUGDH18553404<br>
Contact Person : <br>
Approval Date: 13/11/2025</p>-->
<h3>Item with Variable Data Summary</h3>
<table>
<thead>
<tr>
<th>Customer Item Code</th>
<th>Style Desc</th>
<th>Product Code</th>
<th>Qty Unit</th>
<th>Retailer Order Qty</th>
</tr>
</thead>
<tbody>
<tr th:each="item : ${items}">
<td th:text="${item.itemcode}"></td>
<td th:text="${item.itemdesc}"></td>
<td th:text="${item.itemname}"></td>
<td th:text="${item.unit}"></td>
<td th:text="${item.qty}"></td>
</tr>
</tbody>
</table>
</body>
</html>

View File

@ -20,6 +20,8 @@ export interface SaleOrderVO {
contractType: string // 合约类型
currencyType: string // 结算币种
saleContractCode: string // 销售合约号
totalQty: number // 总数量
totalAmount: number // 总金额
}
// 销售订单 API

View File

@ -77,6 +77,8 @@
</el-select>
</el-descriptions-item>
<el-descriptions-item label="结算币种: " v-else >{{ formData.currencyType }}</el-descriptions-item>
<el-descriptions-item label="总数量: ">{{ formData.totalQty }}</el-descriptions-item>
<el-descriptions-item label="总金额: ">{{ formData.orderAmount }}</el-descriptions-item>
<el-descriptions-item label="订单备注: ">{{ formData.remark }}</el-descriptions-item>
</el-descriptions>

View File

@ -17,10 +17,28 @@
class="!w-240px"
/>
</el-form-item>
<el-form-item label="客户" prop="customerId">
<el-form-item label="客户" prop="customerName">
<el-input
v-model="queryParams.customerId"
placeholder="请输入客户"
v-model="queryParams.customerName"
placeholder="请输入客户名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="品牌" prop="brandName">
<el-input
v-model="queryParams.brandName"
placeholder="请输入品牌名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="物料名称" prop="materialName">
<el-input
v-model="queryParams.materialName"
placeholder="请输入物料编码/名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
@ -209,14 +227,16 @@
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column label="单据编号" align="center" prop="billno" width="220px"/>
<el-table-column label="客户" align="center" prop="customerId" width="120px"/>
<el-table-column label="销售员" align="center" prop="customerId" width="180px"/>
<el-table-column label="跟单员" align="center" prop="customerId" width="180px"/>
<el-table-column label="订单状态" align="center" prop="billStatus" width="180px">
<el-table-column label="客户" align="center" prop="customer.name" width="160px"/>
<el-table-column label="品牌" align="center" prop="brand.name" width="100px"/>
<el-table-column label="订单状态" align="center" prop="billStatus" width="100px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.OMS_BILL_STATUS" :value="scope.row.billStatus" />
</template>
</el-table-column>
<el-table-column label="结算币别" align="center" prop="currencyType" width="80px"/>
<el-table-column label="总数量" align="center" prop="totalQty" width="80px"/>
<el-table-column label="总金额" align="center" prop="totalAmount" width="80px"/>
<!-- <el-table-column label="订单状态" align="center" prop="orderStatus" width="180px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.OMS_ORDER_STATUS" :value="scope.row.orderStatus" />
@ -227,24 +247,24 @@
align="center"
prop="bizdate"
:formatter="dateFormatter2"
width="180px"
width="120px"
/>
<el-table-column
label="确认日期"
align="center"
prop="confirmdate"
:formatter="dateFormatter2"
width="180px"
width="120px"
/>
<el-table-column
label="计划日期"
align="center"
prop="plansenddate"
:formatter="dateFormatter2"
width="180px"
width="120px"
/>
<el-table-column label="手机" align="center" prop="phone" />
<el-table-column label="备注" align="center" prop="remarks" />
<el-table-column label="手机" align="center" prop="phone" width="120px"/>
<el-table-column label="备注" align="center" prop="remarks" width="120px"/>
<el-table-column
label="创建时间"
align="center"
@ -315,6 +335,8 @@
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
<br/>
<h2 v-if="querySumTotalQtyOpen">条件查询汇总订单数量{{querySumTotalQty}}</h2>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
@ -374,7 +396,8 @@ const { t } = useI18n() // 国际化
const loading = ref(true) //
const list = ref<SaleOrderVO[]>([]) //
const total = ref(0) //
const querySumTotalQty = ref(0) //
const querySumTotalQtyOpen = ref(false)
// tabs
const tabsData = ref([
@ -406,6 +429,9 @@ const queryParams = reactive({
pageSize: 10,
billno: undefined,
customerId: undefined,
customerName: undefined,
brandName: undefined,
materialName: undefined,
tabType: 'All',
bizdate: [],
confirmdate: [],
@ -445,6 +471,10 @@ const getList = async () => {
const data = await SaleOrderApi.getSaleOrderPage(queryParams)
list.value = data.list
total.value = data.total
if((queryParams.customerName && queryParams.customerName.trim().length>0) || (queryParams.brandName && queryParams.brandName.trim().length>0) || (queryParams.materialName && queryParams.materialName.trim().length>0)){
querySumTotalQtyOpen.value = true
querySumTotalQty.value = data.otherMap['querySumTotalQty']
}
} finally {
loading.value = false
}

View File

@ -16,6 +16,8 @@ export interface SaleOrderVO {
address: string // 地址
currency: string // 货币
invoiceRemarks: string // 发票备注
totalQty: number // 总数量
totalAmount: number // 总金额
}
// 销售订单 API

View File

@ -526,6 +526,7 @@ export default {
},
billno:'orderNo',
customer:'customer',
brand:'brand',
salesperson:'salesPerson',
followUpPerson:'followUpPerson',
bizdate:'bizdate',
@ -542,6 +543,8 @@ export default {
customerNumber:'customerNumber',
customerName:'customerName',
currencyType:'currencyType',
totalQty:'totalQty',
orderAmount:'orderAmount',
invoiceCode:'invoiceCode',
invoiceName:'invoiceName',
invoiceAddress:'invoiceAddress',

View File

@ -521,6 +521,7 @@ export default {
},
billno:'订单号',
customer:'客户',
brand:'品牌',
salesperson:'销售员',
followUpPerson:'跟单员',
bizdate:'业务日期',
@ -537,6 +538,8 @@ export default {
customerNumber:'客户编号',
customerName:'客户名称',
currencyType:'结算币种',
totalQty:'订单总数量',
orderAmount:'订单总金额',
invoiceCode:'发票抬头',
invoiceName:'发票名称',
invoiceAddress:'发票地址',

View File

@ -28,6 +28,8 @@
<el-descriptions-item :label="t('saleorder.customerName')+':'">{{ formData?.customer?.name }}</el-descriptions-item>
<el-descriptions-item :label="t('saleorder.customerCompany')+':'">{{ formData?.customer?.company }}</el-descriptions-item>
<el-descriptions-item :label="t('saleorder.currencyType')+':'">{{ formData.currencyType }}</el-descriptions-item>
<el-descriptions-item :label="t('saleorder.totalQty')+':'">{{ formData.totalQty }}</el-descriptions-item>
<el-descriptions-item :label="t('saleorder.orderAmount')+':'">{{ formData.orderAmount }}</el-descriptions-item>
<el-descriptions-item :label="t('saleorder.remark')+':'">{{ formData.remark }}</el-descriptions-item>
</el-descriptions>

View File

@ -185,8 +185,9 @@
>
<el-table-column width="30" label="选择" type="selection" />
<el-table-column :label="t('saleorder.billno')" align="center" prop="billno" width="180px"/>
<el-table-column :label="t('saleorder.customer')" align="center" prop="customerId" width="120px"/>
<el-table-column :label="t('saleorder.orderstatus')" align="center" prop="billStatus" width="180px">
<el-table-column :label="t('saleorder.customer')" align="center" prop="customer.name" width="160px"/>
<el-table-column :label="t('saleorder.brand')" align="center" prop="brand.name" width="100px"/>
<el-table-column :label="t('saleorder.orderstatus')" align="center" prop="billStatus" width="100px">
<template #default="scope">
<dict-tag :type="DICT_TYPE.OMS_BILL_STATUS" :value="scope.row.billStatus" />
</template>