新增 币种和产品默认价格

This commit is contained in:
YuanFeng 2024-12-02 23:41:06 +08:00
parent 116e703093
commit ab5b66e9b4
20 changed files with 1363 additions and 119 deletions

View File

@ -0,0 +1,490 @@
package cn.hangtag.framework.common.util;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.TreeNode;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.CollectionLikeType;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.lang.Nullable;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.text.SimpleDateFormat;
import java.util.*;
@Slf4j
public class JsonUtil {
public static <T> String toJson(T value) {
try {
return getFastInstance().writeValueAsString(value);
} catch (Exception var2) {
log.error(var2.getMessage(), var2);
return null;
}
}
public static <T> String toJson(T value, String defaultValue) {
if (value == null) {
return defaultValue;
}
try {
return getFastInstance().writeValueAsString(value);
} catch (Exception var2) {
return defaultValue;
}
}
@SneakyThrows
public static byte[] toJsonAsBytes(Object object) {
return getFastInstance().writeValueAsBytes(object);
}
public static <T> T parse(String content, Class<T> valueType) {
try {
return getInstance().readValue(content, valueType);
} catch (Exception var3) {
log.error(var3.getMessage(), var3);
return null;
}
}
public static <T> T parseFast(String content, Class<T> valueType) {
try {
return getFastInstance().readValue(content, valueType);
} catch (Exception var3) {
log.error(var3.getMessage(), var3);
return null;
}
}
@SneakyThrows
public static <T> T parse(String content, TypeReference<T> typeReference) {
return getInstance().readValue(content, typeReference);
}
@SneakyThrows
public static <T> T parse(byte[] bytes, Class<T> valueType) {
return getInstance().readValue(bytes, valueType);
}
@SneakyThrows
public static <T> T parse(byte[] bytes, TypeReference<T> typeReference) {
return getInstance().readValue(bytes, typeReference);
}
@SneakyThrows
public static <T> T parse(InputStream in, Class<T> valueType) {
return getInstance().readValue(in, valueType);
}
@SneakyThrows
public static <T> T parse(InputStream in, TypeReference<T> typeReference) {
return getInstance().readValue(in, typeReference);
}
public static <T> List<T> parseArray(String content, Class<T> valueTypeRef) {
try {
if (!content.toLowerCase().startsWith("[")) {
content = "[" + content + "]";
}
List<Map<String, Object>> list = getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() {
});
List<T> result = new ArrayList();
Iterator var4 = list.iterator();
while (var4.hasNext()) {
Map<String, Object> map = (Map) var4.next();
result.add(toPojo(map, valueTypeRef));
}
return result;
} catch (IOException var6) {
log.error(var6.getMessage(), var6);
return null;
}
}
@SneakyThrows
public static JsonNode readTree(String jsonString) {
Objects.requireNonNull(jsonString, "jsonString is null");
return getInstance().readTree(jsonString);
}
@SneakyThrows
public static JsonNode readTree(InputStream in) {
Objects.requireNonNull(in, "InputStream in is null");
return getInstance().readTree(in);
}
@SneakyThrows
public static JsonNode readTree(byte[] content) {
Objects.requireNonNull(content, "byte[] content is null");
return getInstance().readTree(content);
}
@SneakyThrows
public static JsonNode readTree(JsonParser jsonParser) {
return getFastInstance().readTree(jsonParser);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable byte[] content, Class<T> valueType) {
if (ObjectUtil.isEmpty(content)) {
return null;
}
return getInstance().readValue(content, valueType);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable String jsonString, Class<T> valueType) {
if (jsonString == null || jsonString.contains(" ")) {
return null;
}
return getInstance().readValue(jsonString, valueType);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable InputStream in, Class<T> valueType) {
if (in == null) {
return null;
}
return getInstance().readValue(in, valueType);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable byte[] content, TypeReference<T> typeReference) {
if (ObjectUtil.isEmpty(content)) {
return null;
}
return getInstance().readValue(content, typeReference);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable String jsonString, TypeReference<T> typeReference) {
if (jsonString == null || jsonString.contains(" ")) {
return null;
}
return getInstance().readValue(jsonString, typeReference);
}
@SneakyThrows
@Nullable
public static <T> T readValue(@Nullable InputStream in, TypeReference<T> typeReference) {
if (in == null) {
return null;
}
return getInstance().readValue(in, typeReference);
}
public static MapType getMapType(Class<?> keyClass, Class<?> valueClass) {
return getFastInstance().getTypeFactory().constructMapType(Map.class, keyClass, valueClass);
}
public static CollectionLikeType getListType(Class<?> elementClass) {
return getFastInstance().getTypeFactory().constructCollectionLikeType(List.class, elementClass);
}
@SneakyThrows
public static <T> List<T> readList(@Nullable byte[] content, Class<T> elementClass) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyList();
}
return getInstance().readValue(content, getListType(elementClass));
}
@SneakyThrows
public static <T> List<T> readList(@Nullable InputStream content, Class<T> elementClass) {
if (content == null) {
return Collections.emptyList();
}
return getInstance().readValue(content, getListType(elementClass));
}
@SneakyThrows
public static <T> List<T> readList(@Nullable String content, Class<T> elementClass) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyList();
}
return getInstance().readValue(content, getListType(elementClass));
}
@SneakyThrows
public static <K, V> Map<K, V> readMap(@Nullable byte[] content, Class<?> keyClass, Class<?> valueClass) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyMap();
}
return getInstance().readValue(content, getMapType(keyClass, valueClass));
}
@SneakyThrows
public static <K, V> Map<K, V> readMap(@Nullable InputStream content, Class<?> keyClass, Class<?> valueClass) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyMap();
}
return getInstance().readValue(content, getMapType(keyClass, valueClass));
}
@SneakyThrows
public static <K, V> Map<K, V> readMap(@Nullable String content, Class<?> keyClass, Class<?> valueClass) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyMap();
}
return getInstance().readValue(content, getMapType(keyClass, valueClass));
}
public static Map<String, Object> readMap(@Nullable String content) {
return readMap(content, String.class, Object.class);
}
@SneakyThrows
public static List<Map<String, Object>> readListMap(@Nullable String content) {
if (ObjectUtil.isEmpty(content)) {
return Collections.emptyList();
}
return getInstance().readValue(content, new TypeReference<List<Map<String, Object>>>() {
});
}
public static <T> T convertValue(Object fromValue, Class<T> toValueType) {
return getFastInstance().convertValue(fromValue, toValueType);
}
public static <T> T convertValue(Object fromValue, JavaType toValueType) {
return getFastInstance().convertValue(fromValue, toValueType);
}
public static <T> T convertValue(Object fromValue, TypeReference<T> toValueTypeRef) {
return getFastInstance().convertValue(fromValue, toValueTypeRef);
}
public static <T> T treeToValue(TreeNode treeNode, Class<T> valueType) {
try {
return getFastInstance().treeToValue(treeNode, valueType);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return null;
}
public static JsonNode valueToTree(@Nullable Object value) {
return getInstance().valueToTree(value);
}
public static boolean canSerialize(@Nullable Object value) {
return value == null || getInstance().canSerialize(value.getClass());
}
public static Map<String, Object> toMap(String content) {
try {
return (Map) getInstance().readValue(content, Map.class);
} catch (IOException var2) {
log.error(var2.getMessage(), var2);
return null;
}
}
public static <T> Map<String, T> toMap(String content, Class<T> valueTypeRef) {
try {
Map<String, Map<String, Object>> map = getInstance().readValue(content, new TypeReference<Map<String, Map<String, Object>>>() {
});
Map<String, T> result = new HashMap(16);
Iterator var4 = map.entrySet().iterator();
while (var4.hasNext()) {
Map.Entry<String, Map<String, Object>> entry = (Map.Entry) var4.next();
result.put(entry.getKey(), toPojo(entry.getValue(), valueTypeRef));
}
return result;
} catch (IOException var6) {
log.error(var6.getMessage(), var6);
return null;
}
}
public static <T> T toPojo(Map fromValue, Class<T> toValueType) {
return getFastInstance().convertValue(fromValue, toValueType);
}
/**
* 使用这个覆盖更多类型配置效率一点些但是精度更高
*
* @param fromValue 从价值
* @param toValueType 指向值类型
* @return {@link T }
*/
public static <T> T toPojoFull(Object fromValue, Class<T> toValueType) {
return getInstance().convertValue(fromValue, toValueType);
}
/**
* 使用这个覆盖更多类型配置效率一点些但是精度更高
*
* @param fromValue
* @param toValueType
* @param <T>
* @return
*/
public static <T> T convertValueFull(Object fromValue, Class<T> toValueType) {
return getInstance().convertValue(fromValue, toValueType);
}
private static final ObjectMapper INSTANCE = new NormalJacksonObjectMapper();
private static final ObjectMapper FAST_INSTANCE = new FastObjectMapper();
public static ObjectMapper getInstance() {
return INSTANCE;
}
public static ObjectMapper getFastInstance() {
return FAST_INSTANCE;
}
/**
* 使用表达式获取值
* String city = getValue2(jsonString, "person.address.city2", String.class);
*
* @param jsonString JSON字符串
* @param expression 表达式
* @param targetType 目标类型
* @return {@link T}
*/
public static <T> T getJsonValue(String jsonString, String expression, Class<T> targetType) {
JSONObject jsonObject = JSONUtil.parseObj(jsonString);
Object result = jsonObject.getByPath(expression);
return targetType.cast(result);
}
/**
* 一般的配置
*
* @author YuanFeng
* @date 2022/11/21
*/
private static class NormalJacksonObjectMapper extends ObjectMapper implements Serializable {
public NormalJacksonObjectMapper(ObjectMapper src) {
super(src);
}
public NormalJacksonObjectMapper() {
//序列化BigDecimal时之间输出原始数字还是科学计数, 默认false, 即是否以toPlainString()科学计数方式来输出
disable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
//允许将JSON空字符串强制转换为null对象值
enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
//允许单个数值当做数组处理
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
//禁止重复键, 抛出异常
enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
//禁止使用int代表Enum的order()來反序列化Enum, 抛出异常
enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
//有属性不能映射的时候不报错
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//使用null表示集合类型字段是时不抛异常
disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
//对象为空时不抛异常
disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//允许在JSON中使用c/c++风格注释
enable(JsonParser.Feature.ALLOW_COMMENTS);
//强制转义非ascii字符
disable(JsonGenerator.Feature.ESCAPE_NON_ASCII);
//允许未知字段
enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
//在JSON中允许未引用的字段名
enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
//时间格式
disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
//识别单引号
enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
// 配置 ObjectMapper
setSerializationInclusion(JsonInclude.Include.NON_NULL); // NULL不参与序列化
// 设置时区为默认系统时区
setTimeZone(TimeZone.getDefault()); // 默认时区
}
}
/**
* 快速对象映射器 不做复杂的序列化配置
*
* @author YuanFeng
* @date 2022/11/26
*/
private static class FastObjectMapper extends ObjectMapper implements Serializable {
public FastObjectMapper(ObjectMapper src) {
super(src);
}
public FastObjectMapper() {
//序列化BigDecimal时之间输出原始数字还是科学计数, 默认false,不以toPlainString()科学计数方式来输出
disable(JsonGenerator.Feature.WRITE_BIGDECIMAL_AS_PLAIN);
//允许将JSON空字符串强制转换为null对象值
enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
//允许单个数值当做数组处理
enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
//禁止重复键, 抛出异常
enable(DeserializationFeature.FAIL_ON_READING_DUP_TREE_KEY);
//禁止使用int代表Enum的order()來反序列化Enum, 抛出异常
enable(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS);
//有属性不能映射的时候不报错
disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
//使用null表示集合类型字段是时不抛异常
disable(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES);
//对象为空时不抛异常
disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
//允许未知字段
enable(JsonGenerator.Feature.IGNORE_UNKNOWN);
//在JSON中允许未引用的字段名
enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
}
}
}

View File

@ -0,0 +1,14 @@
package cn.hangtag.module.oms.controller.admin.productinfo.dto;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
@Data
public class PriceListItemDTO implements Serializable {
private String c; // 币别
private BigDecimal p; // 单价
private Boolean d; // 是否默认
}

View File

@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
@ -63,6 +64,25 @@ public class ProductInfoPageDTO implements Serializable {
*/
private String summary;
/**
* 生产说明-富文本内容
*/
private String productionInfo;
/**
* 默认售价
*/
private BigDecimal sellingPrice;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* json数组数据 [{p:100.25,c:"RMB",d:true}]
* 1.p:价格 2.c:币种 3.d:是否默认
*/
private String priceList;
/**
* 规格尺寸宽度
*/

View File

@ -2,6 +2,8 @@ package cn.hangtag.module.oms.controller.admin.productinfo.vo;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import io.swagger.v3.oas.annotations.media.Schema;
import cn.hangtag.framework.common.pojo.PageParam;
@ -49,6 +51,25 @@ public class ProductInfoPageReqVO extends PageParam {
@Schema(description = "简述")
private String summary;
/**
* 生产说明-富文本内容
*/
private String productionInfo;
/**
* 默认售价
*/
private BigDecimal sellingPrice;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* json数组数据 [{p:100.25,c:"RMB",d:true}]
* 1.p:价格 2.c:币种 3.d:是否默认
*/
private String priceList;
/**
* 规格尺寸宽度
*/

View File

@ -3,6 +3,8 @@ package cn.hangtag.module.oms.controller.admin.productinfo.vo;
import com.baomidou.mybatisplus.annotation.TableField;
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;
@ -70,6 +72,25 @@ public class ProductInfoRespVO {
@ExcelProperty("简述")
private String summary;
/**
* 生产说明-富文本内容
*/
private String productionInfo;
/**
* 默认售价
*/
private BigDecimal sellingPrice;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* json数组数据 [{p:100.25,c:"RMB",d:true}]
* 1.p:价格 2.c:币种 3.d:是否默认
*/
private String priceList;
/**
* 规格尺寸宽度
*/

View File

@ -5,6 +5,8 @@ import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import javax.validation.constraints.*;
@ -49,6 +51,26 @@ public class ProductInfoSaveReqVO {
@Schema(description = "简述")
private String summary;
/**
* 生产说明-富文本内容
*/
private String productionInfo;
/**
* 默认售价
*/
private BigDecimal sellingPrice;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* json数组数据 [{p:100.25,c:"RMB",d:true}]
* 1.p:价格 2.c:币种 3.d:是否默认
*/
private String priceList;
/**
* 规格尺寸宽度
*/

View File

@ -1,9 +1,11 @@
package cn.hangtag.module.oms.controller.admin.saleorder.front.dto;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
@Data
@ -102,6 +104,16 @@ public class CreateSaleOrderDTO implements Serializable {
private Boolean isBatch;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* 驳回原因
*/
private String rejectReason;
private List<SaleOrderEntryItemDTO> saleOrderEntry;
}

View File

@ -2,6 +2,8 @@ package cn.hangtag.module.oms.dal.dataobject.productinfo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*;
import java.math.BigDecimal;
import java.util.*;
import java.time.LocalDateTime;
import java.time.LocalDateTime;
@ -75,6 +77,25 @@ public class ProductInfoDO extends BaseDO {
*/
private String summary;
/**
* 生产说明-富文本内容
*/
private String productionInfo;
/**
* 默认售价
*/
private BigDecimal sellingPrice;
/**
* 币种 字典 currency_type value
*/
private String currency;
/**
* json数组数据 [{p:100.25,c:"RMB",d:true}]
* 1.p:价格 2.c:币种 3.d:是否默认
*/
private String priceList;
/**
* 规格尺寸宽度
*/

View File

@ -47,6 +47,11 @@ public class SaleOrderEntryDO extends BaseDO {
* 单价
*/
private BigDecimal price;
/**
* 币种
*/
private String currency;
/**
* 折扣率
*/

View File

@ -8,6 +8,8 @@ import cn.hangtag.module.oms.controller.admin.productinfo.vo.*;
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
import cn.hangtag.framework.common.pojo.PageResult;
import java.math.BigDecimal;
/**
* 产品资料 Service 接口
*
@ -60,5 +62,14 @@ public interface ProductInfoService {
*
* @return {@link String }
*/
public String getNewCode();
String getNewCode();
/**
* 按产品ID查询价格
*
* @param productId 材质id
* @param currency 货币
* @return {@link BigDecimal }
*/
BigDecimal queryPriceByProductId(Long productId, String currency);
}

View File

@ -4,10 +4,12 @@ import cn.hangtag.framework.common.exception.ServiceException;
import cn.hangtag.framework.common.exception.enums.GlobalErrorCodeConstants;
import cn.hangtag.framework.common.util.FuncUtil;
import cn.hangtag.framework.common.util.JsonUtil;
import cn.hangtag.framework.mybatis.build.QueryFilterInfo;
import cn.hangtag.framework.mybatis.core.dataobject.BaseDO;
import cn.hangtag.module.oms.base.dal.dataobject.producttype.ProductTypeDO;
import cn.hangtag.module.oms.base.dal.mysql.producttype.ProductTypeMapper;
import cn.hangtag.module.oms.controller.admin.productinfo.dto.PriceListItemDTO;
import cn.hangtag.module.oms.controller.admin.productinfo.dto.ProductInfoPageDTO;
import cn.hangtag.module.oms.controller.admin.productprocess.vo.ProductProcessSaveReqVO;
import cn.hangtag.module.oms.dal.dataobject.brand.BrandDO;
@ -28,6 +30,7 @@ import javax.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.*;
import cn.hangtag.module.oms.controller.admin.productinfo.vo.*;
import cn.hangtag.module.oms.dal.dataobject.productinfo.ProductInfoDO;
@ -251,4 +254,22 @@ public class ProductInfoServiceImpl implements ProductInfoService {
}
}
}
@Override
public BigDecimal queryPriceByProductId(Long productId, String currency) {
ProductInfoDO infoDO = productInfoMapper.selectById(productId);
if(FuncUtil.isNotEmpty(infoDO)){
String priceList = infoDO.getPriceList();
if(FuncUtil.isNotEmpty(priceList)){
List<PriceListItemDTO> dtos = JsonUtil.readList(priceList, PriceListItemDTO.class);
for (PriceListItemDTO dto : dtos) {
if(FuncUtil.equals(dto.getC(), currency)){
return dto.getP();
}
}
}
}
return new BigDecimal(0);
}
}

View File

@ -108,6 +108,7 @@ public interface SaleOrderService {
* @return {@link Long }
*/
Long placeOrder(CreateSaleOrderDTO dto);
Long editOrder(Long id,CreateSaleOrderDTO dto);
/**

View File

@ -672,6 +672,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
List<SaleOrderEntryDO> entryList = new ArrayList<>();
List<SaleOrderSkuDO> skuList = new ArrayList<>();
String currency = order.getCurrency();
// 转成订单条目
for (SaleOrderEntryItemDTO itemDTO : saleOrderEntry) {
SaleOrderEntryDO entry = SaleOrderEntryDO.builder()
@ -681,7 +682,12 @@ public class SaleOrderServiceImpl implements SaleOrderService {
.materialName(itemDTO.getProductName())
.qty(itemDTO.getOrderQty())
.deliveryDate(FuncUtil.timeToLocalDate(itemDTO.getDeliveryDate())).build();
if(FuncUtil.isNotEmpty(currency)){
entry.setCurrency(currency);
BigDecimal price = productInfoService.queryPriceByProductId( entry.getMaterialId(),currency);
// 查询默认单价
entry.setPrice(price);
}
entryList.add(entry);
List<SaleOrderSkuDTO> productSkuList = itemDTO.getProductSkuList();
// sku
@ -702,7 +708,6 @@ public class SaleOrderServiceImpl implements SaleOrderService {
skuOrderSkuMapper.insertBatch(skuList);
updateCustomerInvoiceData(order);
System.out.println(order);
return order.getId();
}
@ -728,7 +733,7 @@ public class SaleOrderServiceImpl implements SaleOrderService {
// 删除之前的的订单条目
deleteSaleOrderEntryByParentId(order.getId());
saleOrderSkuService.delSkuByOrderId(order.getId());
String currency = order.getCurrency();
// 转成订单条目
for (SaleOrderEntryItemDTO itemDTO : saleOrderEntry) {
SaleOrderEntryDO entry = SaleOrderEntryDO.builder()
@ -738,6 +743,13 @@ public class SaleOrderServiceImpl implements SaleOrderService {
.materialName(itemDTO.getProductName())
.qty(itemDTO.getOrderQty())
.deliveryDate(FuncUtil.timeToLocalDate(itemDTO.getDeliveryDate())).build();
if(FuncUtil.isNotEmpty(currency)){
entry.setCurrency(currency);
BigDecimal price = productInfoService.queryPriceByProductId(entry.getMaterialId(),currency);
// 查询默认单价
entry.setPrice(price);
}
entryList.add(entry);
List<SaleOrderSkuDTO> productSkuList = itemDTO.getProductSkuList();
// sku

View File

@ -105,7 +105,9 @@ export enum DICT_TYPE {
COMMON_STATUS = 'common_status',
TERMINAL = 'terminal', // 终端
LANGUAGE_LOCALE = 'language_locale', // 地区语言标识
PRODUCT_DRAFT_TEMPLATE_TYPE = 'product_draft_template_type', // 地区语言标识
PRODUCT_DRAFT_TEMPLATE_TYPE = 'product_draft_template_type', // 1有模板 2无模板 3尺码唛
CURRENCY_TYPE = 'currency_type', // 币种
BRAND_INDUSTRY_FIELD = 'brand_industry_field',
DATE_INTERVAL = 'date_interval', // 数据间隔
// ========== SYSTEM 模块 ==========

View File

@ -0,0 +1,176 @@
<template>
<Dialog v-model="dialogVisible" :title="dialogTitle">
<el-form
ref="formRef"
v-loading="formLoading"
:model="formData"
:rules="formRules"
label-width="80px"
>
<el-form-item label="币种名称" prop="label">
<el-input v-model="formData.label" placeholder="请输入描述名称" />
</el-form-item>
<el-form-item label="币种代号" prop="value">
<el-input v-model="formData.value" placeholder="请输入语言编码" />
</el-form-item>
<el-form-item label="显示排序" prop="sort">
<el-input-number v-model="formData.sort" :min="0" controls-position="right" />
</el-form-item>
<el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status">
<el-radio
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.value"
>
{{ dict.label }}
</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="颜色类型" prop="colorType">
<el-select v-model="formData.colorType">
<el-option
v-for="item in colorTypeOptions"
:key="item.value"
:label="item.label + '(' + item.value + ')'"
:value="item.value"
/>
</el-select>
</el-form-item>
<el-form-item label="CSS Class" prop="cssClass">
<el-input v-model="formData.cssClass" placeholder="请输入 CSS Class" />
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="formData.remark" placeholder="请输入内容" type="textarea" />
</el-form-item>
</el-form>
<template #footer>
<el-button :disabled="formLoading" type="primary" @click="submitForm"> </el-button>
<el-button @click="dialogVisible = false"> </el-button>
</template>
</Dialog>
</template>
<script lang="ts" setup>
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
import * as DictDataApi from '@/api/system/dict/dict.data'
import { CommonStatusEnum } from '@/utils/constants'
defineOptions({ name: 'CurrencyForm' })
const { t } = useI18n() //
const message = useMessage() //
const dialogVisible = ref(false) //
const dialogTitle = ref('') //
const formLoading = ref(false) // 12
const formType = ref('') // create - update -
const formData = ref({
id: undefined,
sort: 1,
label: '',
value: '',
dictType: '',
status: CommonStatusEnum.ENABLE,
colorType: '',
cssClass: '',
remark: ''
})
const formRules = reactive({
label: [{ required: true, message: '数据标签不能为空', trigger: 'blur' }],
value: [{ required: true, message: '数据键值不能为空', trigger: 'blur' }],
sort: [{ required: true, message: '数据顺序不能为空', trigger: 'blur' }],
status: [{ required: true, message: '状态不能为空', trigger: 'change' }]
})
const formRef = ref() // Ref
//
const colorTypeOptions = readonly([
{
value: 'default',
label: '默认'
},
{
value: 'primary',
label: '主要'
},
{
value: 'success',
label: '成功'
},
{
value: 'info',
label: '信息'
},
{
value: 'warning',
label: '警告'
},
{
value: 'danger',
label: '危险'
}
])
/** 打开弹窗 */
const open = async (type: string, id?: number, dictType?: string) => {
dialogVisible.value = true
dialogTitle.value = t('action.' + type)
formType.value = type
resetForm()
if (dictType) {
formData.value.dictType = dictType
}
//
if (id) {
formLoading.value = true
try {
formData.value = await DictDataApi.getDictData(id)
} finally {
formLoading.value = false
}
}
}
defineExpose({ open }) // open
/** 提交表单 */
const emit = defineEmits(['success']) // success
const submitForm = async () => {
//
if (!formRef) return
const valid = await formRef.value.validate()
if (!valid) return
//
formLoading.value = true
try {
const data = formData.value as DictDataApi.DictDataVO
if (formType.value === 'create') {
await DictDataApi.createDictData(data)
message.success(t('common.createSuccess'))
} else {
await DictDataApi.updateDictData(data)
message.success(t('common.updateSuccess'))
}
dialogVisible.value = false
//
emit('success')
} finally {
formLoading.value = false
}
}
/** 重置表单 */
const resetForm = () => {
formData.value = {
id: undefined,
sort: 1,
label: '',
value: '',
dictType: '',
status: CommonStatusEnum.ENABLE,
colorType: '',
cssClass: '',
remark: ''
}
formRef.value?.resetFields()
}
</script>

View File

@ -0,0 +1,210 @@
<template>
<ContentWrap>
<el-form
class="-mb-15px"
:model="queryParams"
ref="queryFormRef"
:inline="true"
label-width="68px"
>
<el-form-item label="币种名称" prop="label">
<el-input
v-model="queryParams.label"
placeholder="请输入币种名称"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="币种代号" prop="label">
<el-input
v-model="queryParams.value"
placeholder="请输入币种代号"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</el-form-item>
<el-form-item label="状态" prop="status">
<el-select v-model="queryParams.status" placeholder="数据状态" clearable class="!w-240px">
<el-option
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
:key="dict.value"
:label="dict.label"
:value="dict.value"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
<el-button
type="primary"
plain
@click="openForm('create')"
v-hasPermi="['system:dict:create']"
>
<Icon icon="ep:plus" class="mr-5px" /> 新增
</el-button>
<el-button
type="success"
plain
@click="handleExport"
:loading="exportLoading"
v-hasPermi="['system:dict:export']"
>
<Icon icon="ep:download" class="mr-5px" /> 导出
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table v-loading="loading" :data="list">
<el-table-column label="币种名称" align="center" prop="label" />
<el-table-column label="币种代号" align="center" prop="value" />
<el-table-column label="排序" align="center" prop="sort" />
<el-table-column label="状态" align="center" prop="status">
<template #default="scope">
<dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column label="颜色类型" align="center" prop="colorType" />
<el-table-column label="CSS Class" align="center" prop="cssClass" />
<el-table-column label="备注" align="center" prop="remark" show-overflow-tooltip />
<el-table-column
label="创建时间"
align="center"
prop="createTime"
width="180"
:formatter="dateFormatter"
/>
<el-table-column label="操作" align="center">
<template #default="scope">
<el-button
link
type="primary"
@click="openForm('update', scope.row.id)"
v-hasPermi="['system:dict:update']"
>
修改
</el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['system:dict:delete']"
>
删除
</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total="total"
v-model:page="queryParams.pageNo"
v-model:limit="queryParams.pageSize"
@pagination="getList"
/>
</ContentWrap>
<!-- 表单弹窗添加/修改 -->
<CurrencyForm ref="formRef" @success="getList" />
</template>
<script lang="ts" setup>
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
import { dateFormatter } from '@/utils/formatTime'
import download from '@/utils/download'
import * as DictDataApi from '@/api/system/dict/dict.data'
import * as DictTypeApi from '@/api/system/dict/dict.type'
import CurrencyForm from "./CurrencyForm.vue";
//
defineOptions({ name: 'LanguageLocale' })
const message = useMessage() //
const { t } = useI18n() //
const route = useRoute() //
const loading = ref(true) //
const total = ref(0) //
const list = ref([]) //
const queryParams = reactive({
pageNo: 1,
pageSize: 20,
label: '',
value: '',
status: undefined,
dictType: 'currency_type'
})
const queryFormRef = ref() //
const exportLoading = ref(false) //
const dictTypeList = ref<DictTypeApi.DictTypeVO[]>() //
/** 查询列表 */
const getList = async () => {
loading.value = true
try {
const data = await DictDataApi.getDictDataPage(queryParams)
list.value = data.list
total.value = data.total
} finally {
loading.value = false
}
}
/** 搜索按钮操作 */
const handleQuery = () => {
queryParams.pageNo = 1
getList()
}
/** 重置按钮操作 */
const resetQuery = () => {
queryFormRef.value.resetFields()
handleQuery()
}
/** 添加/修改操作 */
const formRef = ref()
const openForm = (type: string, id?: number) => {
formRef.value.open(type, id, queryParams.dictType)
}
/** 删除按钮操作 */
const handleDelete = async (id: number) => {
try {
//
await message.delConfirm()
//
await DictDataApi.deleteDictData(id)
message.success(t('common.delSuccess'))
//
await getList()
} catch {}
}
/** 导出按钮操作 */
const handleExport = async () => {
try {
//
await message.exportConfirm()
//
exportLoading.value = true
const data = await DictDataApi.exportDictData(queryParams)
download.excel(data, '字典数据.xls')
} catch {
} finally {
exportLoading.value = false
}
}
/** 初始化 **/
onMounted(async () => {
await getList()
// )
dictTypeList.value = await DictTypeApi.getSimpleDictTypeList()
})
</script>

View File

@ -168,7 +168,84 @@
</el-table-column>
<el-table-column label="操作" width="80">
<template #default="{$index}">
<el-button size="small" type="danger" @click="removeRow($index) ">
<el-button size="small" type="danger" @click="removeRow(that.draftDesignList,$index) ">
<Icon icon="ep:delete"/>
</el-button>
</template>
</el-table-column>
</el-table>
</div>
</el-scrollbar>
</div>
</el-form-item>
<el-form-item label="单价设置" prop="priceList">
<div style="width: calc(100% - 20px);">
<el-button @click="addPriceRow">添加</el-button>
<el-scrollbar max-height="400px">
<div class="w-full">
<el-table
:data="that.priceList"
:stripe="true"
empty-text="未设置单价,点击添加单价"
:show-overflow-tooltip="true">
<el-table-column width="55">
<template #header>
<div>
<span>行号</span>
</div>
</template>
<template #default="scope">
<span>{{ scope.$index + 1 }}</span>
</template>
</el-table-column>
<el-table-column prop="label" width="280">
<template #header>
<div>
<span class="color-red">*</span>
<span>单价</span>
</div>
</template>
<template #default="scope">
<el-input-number :min="0" v-model="scope.row.p"
placeholder="请填写单价"/>
</template>
</el-table-column>
<el-table-column prop="id" width="220">
<template #header>
<div>
<span class="color-red">*</span>
<span>币种</span>
</div>
</template>
<template #default="scope">
<div
:class="{ 'duplicate-tips' : duplicatePriceCheck(scope.row.c)}">
<el-select v-model="that.priceList[scope.$index].c">
<el-option v-for="c in getStrDictOptions(DICT_TYPE.CURRENCY_TYPE)"
:key="`${c.value}`"
:label="c.label"
:value="`${c.value}`"/>
</el-select>
</div>
</template>
</el-table-column>
<el-table-column prop="remark">
<template #header>
<div>
<span>是否默认</span>
</div>
</template>
<template #default="scope">
<el-checkbox v-model="scope.row.d" @change="changSetDefault(scope.$index,scope.row.d)"/>
</template>
</el-table-column>
<el-table-column label="操作" width="80">
<template #default="{$index}">
<el-button size="small" type="danger" @click="removeRow(that.priceList,$index) ">
<Icon icon="ep:delete"/>
</el-button>
</template>
@ -180,7 +257,7 @@
</div>
</el-form-item>
</el-tab-pane>
<el-tab-pane label="产品工艺" name="processInfo">
<el-tab-pane label="产品工艺" name="processInfo" v-if="false">
<el-form-item label="工艺属性" prop="processInfo">
<div style="width: calc(100% - 20px);">
<el-button @click="addProcessRow">添加工艺</el-button>
@ -242,7 +319,11 @@
</el-form-item>
</el-tab-pane>
<el-tab-pane label="详情备注" name="details">
<el-tab-pane label="生产详情" name="details">
<el-form-item label="生产备注" prop="summary">
<Editor v-model="formData.productionInfo" height="150px"
placeholder="请填写生产备注"/>
</el-form-item>
<el-form-item label="产品简述" prop="summary">
<el-input type="textarea" v-model="formData.summary" placeholder="请输入产品简述"/>
</el-form-item>
@ -286,10 +367,15 @@ const formData = ref({
code: undefined,
name: undefined,
cover: undefined,
productionInfo: undefined,
summary: undefined,
brandId: '',
productTypeId: '',
draftDesignDataId: undefined,
draftDesignList: '',
priceList: '',
currency: undefined,
sellingPrice: undefined,
enabled: true,
remark: undefined,
details: undefined,
@ -303,6 +389,7 @@ const formData = ref({
const that = reactive({
brandId: undefined,
draftDesignList: [],
priceList: [],
updateProcess: false,
processInfoList: [{
key: Math.random().toString(36).substring(2, 6),
@ -320,10 +407,17 @@ const addRow = () => {
id: ''
})
}
const addPriceRow = () => {
that.priceList.push({
p: 1,
d: false,
c: 'CNY', //
})
}
const activeName = ref('base')
const removeRow = (index) => {
if (that.draftDesignList.length > 1) {
that.draftDesignList.splice(index, 1)
const removeRow = (data,index) => {
if (data.length > 1) {
data.splice(index, 1)
} else {
message.error('至少需要一个')
}
@ -352,6 +446,15 @@ const duplicateCheck = (id: string) => {
}
return count > 1;
}
const duplicatePriceCheck = (c: string) => {
let count = 0;
for (let i = 0; i < that.priceList.length; i++) {
if (that.priceList[i].c === c) {
count++;
}
}
return count > 1;
}
const duplicateInfoCheck = (name: string) => {
let count = 0;
for (let i = 0; i < that.processInfoList.length; i++) {
@ -361,6 +464,15 @@ const duplicateInfoCheck = (name: string) => {
}
return count > 1;
}
const changSetDefault = (index,d)=>{
if(d){
for(let i=0;i<that.priceList.length;i++){
if(index != i){
that.priceList[i].d = false
}
}
}
}
const formRules = reactive({
name: [{required: true, message: '产品名称不能为空', trigger: 'blur'}],
brandId: [{required: true, message: '产品类型选择品牌', trigger: 'blur'}],
@ -390,6 +502,7 @@ const open = async (type: string, id?: number) => {
try {
formData.value = await ProductInfoApi.getProductInfo(id)
that.draftDesignList = JSON.parse(formData.value.draftDesignList || '[]')
that.priceList = JSON.parse(formData.value.priceList || '[]')
if (isCopy) {
formData.value.id = null
formData.value.code = null
@ -435,15 +548,16 @@ const submitForm = async () => {
// 稿
let countInfo = {};
let ids = [];
if(`${formData.value.templateType}` !== '1'){
const data = formData.value;
if (`${data.templateType}` !== '1') {
data.draftDesignList = []
}
// 稿
if (`${formData.value.templateType}` === '1') {
if(that.draftDesignList.length == 0){
if (`${data.templateType}` === '1') {
if (that.draftDesignList.length == 0) {
//
formData.value.templateType = '2'
}else {
data.templateType = '2'
} else {
for (let i = 0; i < that.draftDesignList.length; i++) {
const id = that.draftDesignList[i].id
const l = that.draftDesignList[i].label
@ -464,12 +578,7 @@ const submitForm = async () => {
ids.push(id);
}
}
}
const data = formData.value;
if (that.updateProcess) {
//
let countInfo2 = {};
@ -495,6 +604,27 @@ const submitForm = async () => {
}
data.draftDesignList = JSON.stringify(that.draftDesignList)
//
if(that.priceList.length > 0){
let match = false;
for (let i = 0; i < that.priceList.length; i++) {
if(duplicatePriceCheck(that.priceList[i].c)){
message.error(`单价设置-第${i + 1} 行币种重复`)
return;
}
if (that.priceList[i].d) {
data.currency = that.priceList[i].c;
data.sellingPrice = that.priceList[i].p;
match = true;
}
}
if (!match) {
that.priceList[0].d = true;
data.currency = that.priceList[0].c;
data.sellingPrice = that.priceList[0].p;
}
}
data.priceList = JSON.stringify(that.priceList)
// 稿
if (ids.length > 0) {
data.draftDesignDataId = ids.join(",");
@ -539,10 +669,15 @@ const resetForm = () => {
code: undefined,
name: undefined,
cover: undefined,
productionInfo: undefined,
summary: undefined,
brandId: that.brandId || '',
productTypeId: '',
draftDesignDataId: undefined,
draftDesignList: [],
currency: undefined,
sellingPrice: undefined,
priceList: [],
enabled: true,
remark: undefined,
details: undefined,
@ -553,6 +688,7 @@ const resetForm = () => {
templateType: '1',
}
that.draftDesignList = []
that.priceList = []
that.processInfoList = [{
key: Math.random().toString(36).substring(2, 6),
id: null, // id

View File

@ -106,6 +106,10 @@ export enum DICT_TYPE {
TERMINAL = 'terminal', // 终端
LANGUAGE_LOCALE = 'language_locale', // 地区语言标识
BRAND_INDUSTRY_FIELD = 'brand_industry_field',
PRODUCT_DRAFT_TEMPLATE_TYPE = 'product_draft_template_type', // 1有模板 2无模板 3尺码唛
CURRENCY_TYPE = 'currency_type', // 币种
DATE_INTERVAL = 'date_interval', // 数据间隔
// ========== SYSTEM 模块 ==========
SYSTEM_USER_SEX = 'system_user_sex',

View File

@ -1,4 +1,5 @@
<template>
<el-alert v-show="formData.rejectReason" :title="`驳回理由: ${formData.rejectReason}`" type="error" effect="dark" />
<ContentWrap v-if="stepIndex==0">
<el-form
ref="formRef"
@ -62,7 +63,8 @@
<el-row>
<el-col :span="12">
<el-form-item label="品牌" prop="brandId">
<el-select :disabled="changeBrand" v-model="formData.brandId" filterable placeholder="请选择品牌">
<el-select :disabled="changeBrand" v-model="formData.brandId" filterable
placeholder="请选择品牌">
<el-option
v-for="brand in brandList"
:key="brand.id"
@ -145,14 +147,13 @@
<el-row>
<el-col :span="12">
<el-form-item label="合同号" prop="contractCode">
<el-form-item label="客户采购编号" prop="contractCode">
<div class="flex w-full">
<el-input
clearable
:disabled="isEditState"
v-model="formData.contractCode"
placeholder="请填写合同号"/>
<el-button v-show="!formData.contractCode && !isEditState" type="primary" @click="generateContractCode">获取</el-button>
placeholder="请填写客户采购编号"/>
</div>
</el-form-item>
</el-col>
@ -168,6 +169,17 @@
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="结算币种" prop="orderFollowerUser">
<el-select v-model="formData.currency" filterable placeholder="请选择结算币种">
<el-option
v-for="c in that.currencyList"
:key="`${c.value}`"
:label="`${c.label}(${c.value})`"
:value="`${c.value}`"/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="业务员" prop="orderFollowerUser">
<el-select v-model="formData.orderFollowerUser" filterable placeholder="业务员">
@ -262,12 +274,14 @@
<el-row>
<el-col :span="12">
<el-form-item label="发票抬头" prop="invoiceCode">
<el-input v-model="formData.invoiceCode" placeholder="请输入发票抬头"/>
<el-input v-model="formData.invoiceCode"
placeholder="请输入发票抬头"/>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="发票名称" prop="invoiceName">
<el-input v-model="formData.invoiceName" placeholder="请输入发票名称"/>
<el-input v-model="formData.invoiceName"
placeholder="请输入发票名称"/>
</el-form-item>
</el-col>
</el-row>
@ -304,7 +318,8 @@
<CardTitle title="收货信息"/>
<div class="pl-8px">
<AddressListDialog ref="addressRef">
<el-button type="primary" link @click="editAddress">管理收货地址</el-button>
<el-button type="primary" link @click="editAddress">管理收货地址
</el-button>
</AddressListDialog>
</div>
@ -320,7 +335,8 @@
placeholder="选择地址"
v-model="that.addressId"
@change="onChangeAddress">
<el-option v-for="item in that.addressList" :label="item.name" :key="item.id" :value="item.id">
<el-option v-for="item in that.addressList" :label="item.name"
:key="item.id" :value="item.id">
<span>{{ item.name }}</span>
</el-option>
</el-select>
@ -406,12 +422,15 @@ import * as BrandApi from "@/api/oms/brand";
import {AddressApi} from "@/api/oms/customer/address";
import {CustomerApi} from "@/api/oms/customer";
import {SaleOrderApi} from "@/api/oms/saleorder";
const { push } = useRouter()
const {push} = useRouter()
import OrderAddProductStep from "./components/OrderAddProductStep/index.vue";
import {useEmitt} from "@/hooks/web/useEmitt";
import {STEP0_FINISH_EVENT, UPDATE_ADDRESS_EVENT} from "@/constants/EmitEventName";
import {formatDate} from "@/utils/formatTime";
import {ElLoading} from "element-plus";
import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
const route = useRoute() //
//
const calculateDateAfterDays = (days) => {
@ -441,7 +460,7 @@ const editAddress = () => {
}
useEmitt({
name: UPDATE_ADDRESS_EVENT,
callback: ()=>{
callback: () => {
getCustomerAddressList();
},
});
@ -449,13 +468,14 @@ const that = reactive({
formLoading: false,
pageLoading: {},
addressList: [],
currencyList: [], //
addressId: null,
tmpFormData: {
inputEmail: '',
emailList: [],
planDate: calculateDateAfterDays(7),
},
followerUserList:[],
followerUserList: [],
subListSize: 0,
})
const formData = ref({
@ -467,6 +487,7 @@ const formData = ref({
username: '',
company: '',
brandId: '',
currency: '',
tel: '',
fax: '',
invoiceName: '',
@ -484,14 +505,15 @@ const formData = ref({
deliveryRemark: '',
saleOrderEntry: [],
orderFollowerUser: '',
rejectReason: '',
})
const isEditState = computed(()=>{
const isEditState = computed(() => {
return route.query.id != undefined
})
const formRules = reactive({
contactName: [{required: true, message: '联系人不能为空', trigger: 'blur'}],
brandId: [{required: true, message: '品牌不能为空', trigger: 'blur'}],
contractCode: [{required: true, message: '合同号不能为空', trigger: 'blur'}],
contractCode: [{required: true, message: '客户采购编号不能为空', trigger: 'blur'}],
phone: [{required: true, message: '联系人手机号不能为空', trigger: 'blur'},
{
pattern: /^(?:(?:\+|00)86)?1(?:3[\d]|4[5-79]|5[0-35-9]|6[5-7]|7[0-8]|8[\d]|9[189])\d{8}$/,
@ -502,7 +524,7 @@ const formRules = reactive({
})
const activeNames = ref(['1', '2', '3'])
const pushEmail = (input:string)=>{
const pushEmail = (input: string) => {
const tmp = input.trim();
const index = that.tmpFormData.emailList.indexOf(tmp);
if (index != -1) {
@ -535,12 +557,12 @@ const onDelEmail = () => {
const selectItem = async (index: number) => {
selectedIndex.value = index;
}
const changeBrand = computed(()=>{
const changeBrand = computed(() => {
return that.subListSize > 0;
})
const generateContractCode = () => {
//
SaleOrderApi.getContractCode().then(res =>{
SaleOrderApi.getContractCode().then(res => {
formData.value.contractCode = res;
})
@ -549,7 +571,7 @@ const generateContractCode = () => {
const backStep = async () => {
stepIndex.value = stepIndex.value - 1;
that.subListSize = 0;
if(stepRef.value){
if (stepRef.value) {
that.subListSize = stepRef.value.getTableData().length
}
}
@ -574,10 +596,10 @@ const nextStep = async () => {
stepIndex.value = stepIndex.value + 1;
}
}
const onChangeAddress = (id)=>{
const onChangeAddress = (id) => {
console.log(id)
for (let i = 0; i < that.addressList.length; i++) {
if(that.addressList[i].id === id){
if (that.addressList[i].id === id) {
formData.value.deliveryAddress = that.addressList[i].address
}
}
@ -590,7 +612,7 @@ const submitPreHandler = (showMsg = true) => {
// todo
const tableData = stepRef.value.getTableData();
if (tableData.length === 0) {
if(showMsg){
if (showMsg) {
useMessage().warning("请添加产品")
}
reject("请添加产品")
@ -601,20 +623,20 @@ const submitPreHandler = (showMsg = true) => {
if (!formData.isBatch && that.tmpFormData.planDate) {
formData.value.plansenddate = new Date(that.tmpFormData.planDate).getTime()
}
tableData.forEach((item,index)=>{
tableData.forEach((item, index) => {
if(!item.productSkuList || item.productSkuList.length === 0){
const t = `${index+1}${item.productName} SKU不能为空`;
if(showMsg){
if (!item.productSkuList || item.productSkuList.length === 0) {
const t = `${index + 1}${item.productName} SKU不能为空`;
if (showMsg) {
useMessage().warning(t)
}
reject(t)
return;
}
item.productSkuList.forEach((item2,i2)=>{
if(!item2.previewImage){
const t = `${index+1}${item.productName}SKU 第${i2+1}项 请批稿`;
if(showMsg){
item.productSkuList.forEach((item2, i2) => {
if (!item2.previewImage) {
const t = `${index + 1}${item.productName}SKU 第${i2 + 1}项 请批稿`;
if (showMsg) {
useMessage().warning(t)
}
reject(t)
@ -624,7 +646,7 @@ const submitPreHandler = (showMsg = true) => {
formData.value.saleOrderEntry = tableData
if ( formData.value.bizdate) {
if (formData.value.bizdate) {
formData.value.bizdate = new Date(formData.value.bizdate).getTime()
}
resolve(true);
@ -632,10 +654,10 @@ const submitPreHandler = (showMsg = true) => {
}
const addNewBill = () => {
console.log("stepRef.value.getTableData()", stepRef.value.getTableData())
submitPreHandler().then(res=>{
console.log("formData",formData.value)
if(formData.value.id){
SaleOrderApi.editOrder(formData.value.id,{
submitPreHandler().then(res => {
console.log("formData", formData.value)
if (formData.value.id) {
SaleOrderApi.editOrder(formData.value.id, {
...formData.value
}).then(res => {
that.pageLoading = ElLoading.service({
@ -643,14 +665,14 @@ const addNewBill = () => {
text: '修改成功...',
background: 'rgba(0,0,0,0.5)'
})
setTimeout(()=>{
setTimeout(() => {
that.pageLoading.close()
push("/")
},3000)
}).catch(e=>{
useMessage().warning("出错:"+ e.message ? e.message : e)
}, 3000)
}).catch(e => {
useMessage().warning("出错:" + e.message ? e.message : e)
})
}else {
} else {
SaleOrderApi.placeOrder({
...formData.value
}).then(res => {
@ -659,12 +681,12 @@ const addNewBill = () => {
text: '下单成功...',
background: 'rgba(0,0,0,0.5)'
})
setTimeout(()=>{
setTimeout(() => {
that.pageLoading.close()
push("/")
},3000)
}).catch(e=>{
useMessage().warning("出错:"+ e.message ? e.message : e)
}, 3000)
}).catch(e => {
useMessage().warning("出错:" + e.message ? e.message : e)
})
}
@ -675,7 +697,7 @@ const addNewBill = () => {
/** 初始化 **/
onMounted(() => {
queryParams.id = '';
if(route.query){
if (route.query) {
queryParams.id = route.query.id ?? ''
}
@ -689,21 +711,28 @@ const hasLastIndex = computed(() => {
const brandList = ref<any[]>([]) //
watch(() => formData.value.brandId, async (val)=>{
if(val){
watch(() => formData.value.brandId, async (val) => {
if (val) {
const data = await SaleOrderApi.getFollowerUser(val)
that.followerUserList = data
if(that.followerUserList.length > 0 && !formData.value.orderFollowerUser){
if (that.followerUserList.length > 0 && !formData.value.orderFollowerUser) {
formData.value.orderFollowerUser = `${that.followerUserList[0].id}`
}
}
})
onMounted(async () => {
//
that.currencyList = getStrDictOptions(DICT_TYPE.CURRENCY_TYPE)
if (!formData.value.currency) {
formData.value.currency = that.currencyList[0].value
}
//
BrandApi.getSimpleBrandList().then(res =>{
BrandApi.getSimpleBrandList().then(res => {
brandList.value = res
if(res.length > 0 && !formData.value.brandId){
if (res.length > 0 && !formData.value.brandId) {
formData.value.brandId = brandList.value[0].id
}
})
@ -715,23 +744,23 @@ onMounted(async () => {
formData.value.company = customerData.company;
formData.value.contactName = customerData.contacts;
formData.value.phone = customerData.phone;
if(customerData.email){
if (customerData.email) {
pushEmail(customerData.email);
}
formData.value.invoiceCode = customerData.invoiceCode;
formData.value.invoiceName = customerData.invoiceName;
formData.value.invoiceAddress = customerData.invoiceAddress;
if(!formData.value.deliveryAddress && that.addressList.length > 0){
if (!formData.value.deliveryAddress && that.addressList.length > 0) {
formData.value.deliveryAddress = that.addressList[0].address;
that.addressId = that.addressList[0].id;
}
}
//
if(queryParams.id){
const res = await SaleOrderApi.queryEditById(queryParams.id);
if (queryParams.id) {
const res = await SaleOrderApi.queryEditById(queryParams.id);
formData.value = res
formData.value.bizdate = formatDate( new Date(res.bizdate), 'YYYY-MM-DD hh:mm:ss');
that.tmpFormData.planDate = formatDate( new Date(res.plansenddate), 'YYYY-MM-DD');
formData.value.bizdate = formatDate(new Date(res.bizdate), 'YYYY-MM-DD hh:mm:ss');
that.tmpFormData.planDate = formatDate(new Date(res.plansenddate), 'YYYY-MM-DD');
that.tmpFormData.emailList = res.emails.split(";")
formData.value = {
...formData.value,
@ -741,53 +770,55 @@ onMounted(async () => {
}
})
const getCustomerAddressList = async () => {
const customerData = await CustomerApi.getCustomerInfo()
if (customerData) {
that.addressList = customerData.addressList;
const getCustomerAddressList = async () => {
const customerData = await CustomerApi.getCustomerInfo()
if (customerData) {
that.addressList = customerData.addressList;
}
}
}
const resFrom = (init = {}) => {
const resFrom = (init = {}) => {
formData.value = {
contactName: '',
phone: '',
invoiceAddress: '',
orderStatus: '',
customerId: '',
username: '',
company: '',
brandId: '',
tel: '',
fax: '',
invoiceName: '',
invoiceCode: '',
invoiceRemarks: '',
contractCode: '',
retailerCode: '',
remarks: '',
isBatch: false,
orderCode: '',
emails: '',
bizdate: undefined,
plansenddate: undefined,
saleOrderEntry: [],
...init
}
if (customerData && !init.id) {
that.addressList = customerData.addressList;
formData.value.customerId = customerData.id;
formData.value.username = customerData.name;
formData.value.company = customerData.company;
formData.value.contactName = customerData.contacts;
formData.value.phone = customerData.phone;
formData.value.invoiceCode = customerData.invoiceCode;
formData.value.invoiceName = customerData.invoiceName;
formData.value.invoiceAddress = customerData.invoiceAddress;
console.log("formData",formData)
}
formData.value = {
contactName: '',
phone: '',
invoiceAddress: '',
orderStatus: '',
customerId: '',
username: '',
company: '',
brandId: '',
currency: '',
tel: '',
fax: '',
invoiceName: '',
invoiceCode: '',
invoiceRemarks: '',
contractCode: '',
retailerCode: '',
remarks: '',
isBatch: false,
orderCode: '',
emails: '',
bizdate: undefined,
plansenddate: undefined,
saleOrderEntry: [],
rejectReason: '',
...init
}
if (customerData && !init.id) {
that.addressList = customerData.addressList;
formData.value.customerId = customerData.id;
formData.value.username = customerData.name;
formData.value.company = customerData.company;
formData.value.contactName = customerData.contacts;
formData.value.phone = customerData.phone;
formData.value.invoiceCode = customerData.invoiceCode;
formData.value.invoiceName = customerData.invoiceName;
formData.value.invoiceAddress = customerData.invoiceAddress;
console.log("formData", formData)
}
}
}
</script>

View File

@ -0,0 +1,14 @@
ALTER TABLE oms_product_info
ADD COLUMN `production_info` text DEFAULT NULL COMMENT '生产说明-富文本内容'
AFTER `summary`;
ALTER TABLE oms_product_info
ADD COLUMN `selling_price` DECIMAL(32,8) DEFAULT NULL COMMENT '默认售价';
ALTER TABLE oms_product_info
ADD COLUMN `currency` varchar(64) DEFAULT NULL COMMENT '币种编码 字典 currency_type';
ALTER TABLE oms_product_info
ADD COLUMN `price_list` text DEFAULT NULL COMMENT 'json数组数据 [{p:100.25,c:"RMB",d:true}]';