update product unit
This commit is contained in:
@@ -30,8 +30,8 @@ public class GaoCustomerPackageItem extends UUIDEntity {
|
|||||||
/// 产品单位快照
|
/// 产品单位快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 总权益数量
|
/// 总权益数量
|
||||||
private BigDecimal totalQuantity;
|
private BigDecimal totalQuantity;
|
||||||
|
|||||||
@@ -53,6 +53,6 @@ public class GaoOrderFulfillmentItem extends UUIDEntity {
|
|||||||
/// 单位快照
|
/// 单位快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public class GaoPackageConfigItem extends UUIDEntity {
|
|||||||
/// 单位快照
|
/// 单位快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 默认数量
|
/// 默认数量
|
||||||
private BigDecimal defaultQuantity;
|
private BigDecimal defaultQuantity;
|
||||||
|
|||||||
@@ -77,9 +77,6 @@ public class GaoProduct extends UUIDEntity {
|
|||||||
/// 状态
|
/// 状态
|
||||||
private Status status;
|
private Status status;
|
||||||
|
|
||||||
/// 建议售价,单位分
|
|
||||||
private Long salePrice;
|
|
||||||
|
|
||||||
/// 参考成本,单位分
|
/// 参考成本,单位分
|
||||||
private Long referenceCost;
|
private Long referenceCost;
|
||||||
|
|
||||||
|
|||||||
@@ -20,8 +20,11 @@ public class GaoProductUnit extends UUIDEntity {
|
|||||||
/// 单位名称
|
/// 单位名称
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
/// 折算为基础单位的比例
|
/// 每个业务单位对应的基础单位数量
|
||||||
private BigDecimal conversionToBase;
|
private BigDecimal baseQuantityPerUnit;
|
||||||
|
|
||||||
|
/// 该业务单位建议售价,单位分
|
||||||
|
private Long salePrice;
|
||||||
|
|
||||||
/// true 为基础库存单位
|
/// true 为基础库存单位
|
||||||
private Boolean isBase;
|
private Boolean isBase;
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ public class GaoSalesOrderItem extends UUIDEntity {
|
|||||||
/// 单位快照
|
/// 单位快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 购买数量
|
/// 购买数量
|
||||||
private BigDecimal quantity;
|
private BigDecimal quantity;
|
||||||
|
|||||||
@@ -79,8 +79,8 @@ public class GaoStockRecord implements IDEntity<String>, Creatable {
|
|||||||
/// 单位名称快照
|
/// 单位名称快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 业务数量
|
/// 业务数量
|
||||||
private BigDecimal quantity;
|
private BigDecimal quantity;
|
||||||
|
|||||||
@@ -19,10 +19,10 @@ public interface GaoProductUnitService {
|
|||||||
/// @return 规范化后的单位列表
|
/// @return 规范化后的单位列表
|
||||||
List<GaoProductUnit> validateAndNormalize(GaoProduct product, List<GaoProductUnit> unitList);
|
List<GaoProductUnit> validateAndNormalize(GaoProduct product, List<GaoProductUnit> unitList);
|
||||||
|
|
||||||
/// 按基础单位换算数量
|
/// 按基础单位数量系数换算业务数量
|
||||||
///
|
///
|
||||||
/// @param unit 单位
|
/// @param unit 单位
|
||||||
/// @param quantity 业务数量
|
/// @param quantity 业务数量
|
||||||
/// @return 基础单位数量
|
/// @return 基础单位数量
|
||||||
BigDecimal convertToBase(GaoProductUnit unit, BigDecimal quantity);
|
BigDecimal convertQuantityToBase(GaoProductUnit unit, BigDecimal quantity);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -250,7 +250,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setProductUnitId(source.getProductUnitId());
|
item.setProductUnitId(source.getProductUnitId());
|
||||||
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
item.setUnitSnapshot(source.getUnitSnapshot());
|
item.setUnitSnapshot(source.getUnitSnapshot());
|
||||||
item.setConversionToBaseSnapshot(source.getConversionToBaseSnapshot());
|
item.setBaseQuantityPerUnitSnapshot(source.getBaseQuantityPerUnitSnapshot());
|
||||||
item.setTotalQuantity(source.getTotalQuantity());
|
item.setTotalQuantity(source.getTotalQuantity());
|
||||||
item.setReservedQuantity(ZERO);
|
item.setReservedQuantity(ZERO);
|
||||||
item.setFulfilledQuantity(ZERO);
|
item.setFulfilledQuantity(ZERO);
|
||||||
@@ -315,7 +315,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
item.setProductUnitId(configItem.getProductUnitId());
|
item.setProductUnitId(configItem.getProductUnitId());
|
||||||
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
||||||
item.setUnitSnapshot(configItem.getUnitSnapshot());
|
item.setUnitSnapshot(configItem.getUnitSnapshot());
|
||||||
item.setConversionToBaseSnapshot(configItem.getConversionToBaseSnapshot());
|
item.setBaseQuantityPerUnitSnapshot(configItem.getBaseQuantityPerUnitSnapshot());
|
||||||
item.setTotalQuantity(configItem.getDefaultQuantity());
|
item.setTotalQuantity(configItem.getDefaultQuantity());
|
||||||
item.setSort(configItem.getSort());
|
item.setSort(configItem.getSort());
|
||||||
item.setRemark(configItem.getRemark());
|
item.setRemark(configItem.getRemark());
|
||||||
@@ -357,7 +357,7 @@ public class GaoCustomerPackageServiceImplement extends AbstractEntityService<Ga
|
|||||||
TimiException.required(item, "套餐权益项目必须与事件绑定套餐一致");
|
TimiException.required(item, "套餐权益项目必须与事件绑定套餐一致");
|
||||||
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
item.setProductNameSnapshot(configItem.getProductNameSnapshot());
|
||||||
item.setUnitSnapshot(configItem.getUnitSnapshot());
|
item.setUnitSnapshot(configItem.getUnitSnapshot());
|
||||||
item.setConversionToBaseSnapshot(configItem.getConversionToBaseSnapshot());
|
item.setBaseQuantityPerUnitSnapshot(configItem.getBaseQuantityPerUnitSnapshot());
|
||||||
TimiException.requiredTrue(item.getSort().equals(configItem.getSort())
|
TimiException.requiredTrue(item.getSort().equals(configItem.getSort())
|
||||||
&& sameText(item.getRemark(), configItem.getRemark()), "套餐权益项目的名称、单位、排序和备注不可修改");
|
&& sameText(item.getRemark(), configItem.getRemark()), "套餐权益项目的名称、单位、排序和备注不可修改");
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-18
@@ -462,10 +462,10 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
GaoProduct product = productService.get(source.getProductId());
|
GaoProduct product = productService.get(source.getProductId());
|
||||||
TimiException.required(product, "履约来源产品不存在");
|
TimiException.required(product, "履约来源产品不存在");
|
||||||
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
|
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
|
||||||
BigDecimal conversion = requiredConversion(source.getConversionToBaseSnapshot());
|
BigDecimal baseQuantityPerUnit = requiredBaseQuantityPerUnit(source.getBaseQuantityPerUnitSnapshot());
|
||||||
GaoProductUnit unit = snapshotUnit(source.getProductUnitId(), source.getUnitSnapshot(), conversion);
|
GaoProductUnit unit = snapshotUnit(source.getProductUnitId(), source.getUnitSnapshot(), baseQuantityPerUnit);
|
||||||
return buildSource(order, source.getId(), null, source.getProductId(), source.getProductUnitId(), source.getProductNameSnapshot(),
|
return buildSource(order, source.getId(), null, source.getProductId(), source.getProductUnitId(), source.getProductNameSnapshot(),
|
||||||
source.getUnitSnapshot(), conversion, quantity, source.getQuantity(), source.getReservedQuantity(), source.getFulfilledQuantity(),
|
source.getUnitSnapshot(), baseQuantityPerUnit, quantity, source.getQuantity(), source.getReservedQuantity(), source.getFulfilledQuantity(),
|
||||||
product, unit, packageSource, checkAvailable);
|
product, unit, packageSource, checkAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -475,15 +475,15 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
GaoProduct product = productService.get(source.getProductId());
|
GaoProduct product = productService.get(source.getProductId());
|
||||||
TimiException.required(product, "履约来源产品不存在");
|
TimiException.required(product, "履约来源产品不存在");
|
||||||
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
|
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
|
||||||
BigDecimal conversion = requiredConversion(source.getConversionToBaseSnapshot());
|
BigDecimal baseQuantityPerUnit = requiredBaseQuantityPerUnit(source.getBaseQuantityPerUnitSnapshot());
|
||||||
GaoProductUnit unit = snapshotUnit(source.getProductUnitId(), source.getUnitSnapshot(), conversion);
|
GaoProductUnit unit = snapshotUnit(source.getProductUnitId(), source.getUnitSnapshot(), baseQuantityPerUnit);
|
||||||
return buildSource(order, null, source.getId(), source.getProductId(), source.getProductUnitId(), source.getProductNameSnapshot(),
|
return buildSource(order, null, source.getId(), source.getProductId(), source.getProductUnitId(), source.getProductNameSnapshot(),
|
||||||
source.getUnitSnapshot(), conversion, quantity, source.getTotalQuantity(), source.getReservedQuantity(), fulfilledQuantity(source),
|
source.getUnitSnapshot(), baseQuantityPerUnit, quantity, source.getTotalQuantity(), source.getReservedQuantity(), fulfilledQuantity(source),
|
||||||
product, unit, packageSource, checkAvailable);
|
product, unit, packageSource, checkAvailable);
|
||||||
}
|
}
|
||||||
|
|
||||||
private SourceEntry buildSource(GaoSalesOrder order, String orderItemId, String packageItemId, String productId, String unitId,
|
private SourceEntry buildSource(GaoSalesOrder order, String orderItemId, String packageItemId, String productId, String unitId,
|
||||||
String productName, String unitName, BigDecimal conversion, BigDecimal quantity, BigDecimal totalQuantity,
|
String productName, String unitName, BigDecimal baseQuantityPerUnit, BigDecimal quantity, BigDecimal totalQuantity,
|
||||||
BigDecimal reservedQuantity, BigDecimal fulfilledQuantity, GaoProduct product, GaoProductUnit unit,
|
BigDecimal reservedQuantity, BigDecimal fulfilledQuantity, GaoProduct product, GaoProductUnit unit,
|
||||||
boolean packageSource, boolean checkAvailable) {
|
boolean packageSource, boolean checkAvailable) {
|
||||||
if (!Boolean.TRUE.equals(product.getAllowDecimalQuantity())) {
|
if (!Boolean.TRUE.equals(product.getAllowDecimalQuantity())) {
|
||||||
@@ -495,7 +495,7 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
BigDecimal available = decimal(totalQuantity).subtract(reservedBefore).subtract(fulfilledBefore);
|
BigDecimal available = decimal(totalQuantity).subtract(reservedBefore).subtract(fulfilledBefore);
|
||||||
TimiException.requiredTrue(0 <= available.compareTo(quantity), "来源产品可履约数量不足");
|
TimiException.requiredTrue(0 <= available.compareTo(quantity), "来源产品可履约数量不足");
|
||||||
}
|
}
|
||||||
return new SourceEntry(orderItemId, packageItemId, productId, unitId, productName, unitName, conversion,
|
return new SourceEntry(orderItemId, packageItemId, productId, unitId, productName, unitName, baseQuantityPerUnit,
|
||||||
quantity, decimal(totalQuantity), reservedBefore, fulfilledBefore, product, unit, packageSource);
|
quantity, decimal(totalQuantity), reservedBefore, fulfilledBefore, product, unit, packageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -508,7 +508,7 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
GaoProductUnit baseUnit = productService.listUnitByProductId(source.product().getId()).stream()
|
GaoProductUnit baseUnit = productService.listUnitByProductId(source.product().getId()).stream()
|
||||||
.filter(unit -> Boolean.TRUE.equals(unit.getIsBase())).findFirst().orElse(null);
|
.filter(unit -> Boolean.TRUE.equals(unit.getIsBase())).findFirst().orElse(null);
|
||||||
TimiException.required(baseUnit, "实物产品缺少基础库存单位");
|
TimiException.required(baseUnit, "实物产品缺少基础库存单位");
|
||||||
BigDecimal baseQuantity = unitService.convertToBase(source.unit(), source.quantity());
|
BigDecimal baseQuantity = unitService.convertQuantityToBase(source.unit(), source.quantity());
|
||||||
GaoStockChangeItem item = itemMap.get(source.product().getId());
|
GaoStockChangeItem item = itemMap.get(source.product().getId());
|
||||||
if (item == null) {
|
if (item == null) {
|
||||||
item = GaoStockChangeItem.of(source.product(), baseUnit, baseQuantity, baseQuantity);
|
item = GaoStockChangeItem.of(source.product(), baseUnit, baseQuantity, baseQuantity);
|
||||||
@@ -590,21 +590,21 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
result.setBaseQuantity(source.getBaseQuantity());
|
result.setBaseQuantity(source.getBaseQuantity());
|
||||||
result.setProductNameSnapshot(source.getProductNameSnapshot());
|
result.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
result.setUnitSnapshot(source.getUnitSnapshot());
|
result.setUnitSnapshot(source.getUnitSnapshot());
|
||||||
result.setConversionToBaseSnapshot(source.getConversionToBaseSnapshot());
|
result.setBaseQuantityPerUnitSnapshot(source.getBaseQuantityPerUnitSnapshot());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoProductUnit snapshotUnit(String id, String name, BigDecimal conversion) {
|
private GaoProductUnit snapshotUnit(String id, String name, BigDecimal baseQuantityPerUnit) {
|
||||||
GaoProductUnit unit = new GaoProductUnit();
|
GaoProductUnit unit = new GaoProductUnit();
|
||||||
unit.setId(id);
|
unit.setId(id);
|
||||||
unit.setName(name);
|
unit.setName(name);
|
||||||
unit.setConversionToBase(conversion);
|
unit.setBaseQuantityPerUnit(baseQuantityPerUnit);
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BigDecimal requiredConversion(BigDecimal value) {
|
private BigDecimal requiredBaseQuantityPerUnit(BigDecimal value) {
|
||||||
TimiException.required(value, "履约来源缺少折算率快照");
|
TimiException.required(value, "履约来源缺少基础单位数量系数快照");
|
||||||
TimiException.requiredTrue(0 < value.signum(), "履约来源折算率无效");
|
TimiException.requiredTrue(0 < value.signum(), "履约来源基础单位数量系数无效");
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -665,7 +665,7 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
}
|
}
|
||||||
|
|
||||||
private record SourceEntry(String sourceOrderItemId, String sourceCustomerPackageItemId, String productId, String productUnitId,
|
private record SourceEntry(String sourceOrderItemId, String sourceCustomerPackageItemId, String productId, String productUnitId,
|
||||||
String productNameSnapshot, String unitSnapshot, BigDecimal conversionToBaseSnapshot, BigDecimal quantity,
|
String productNameSnapshot, String unitSnapshot, BigDecimal baseQuantityPerUnitSnapshot, BigDecimal quantity,
|
||||||
BigDecimal totalQuantity, BigDecimal reservedBefore, BigDecimal fulfilledBefore, GaoProduct product,
|
BigDecimal totalQuantity, BigDecimal reservedBefore, BigDecimal fulfilledBefore, GaoProduct product,
|
||||||
GaoProductUnit unit, boolean packageSource) {
|
GaoProductUnit unit, boolean packageSource) {
|
||||||
|
|
||||||
@@ -681,14 +681,14 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
|
|||||||
result.setSourceOrderItemId(sourceOrderItemId);
|
result.setSourceOrderItemId(sourceOrderItemId);
|
||||||
result.setSourceCustomerPackageItemId(sourceCustomerPackageItemId);
|
result.setSourceCustomerPackageItemId(sourceCustomerPackageItemId);
|
||||||
result.setQuantity(quantity);
|
result.setQuantity(quantity);
|
||||||
result.setBaseQuantity(quantity.multiply(conversionToBaseSnapshot).setScale(3));
|
result.setBaseQuantity(quantity.multiply(baseQuantityPerUnitSnapshot).setScale(3));
|
||||||
result.setReservedBefore(reservedBefore);
|
result.setReservedBefore(reservedBefore);
|
||||||
result.setReservedAfter(reservedBefore.add(quantity));
|
result.setReservedAfter(reservedBefore.add(quantity));
|
||||||
result.setFulfilledBefore(fulfilledBefore);
|
result.setFulfilledBefore(fulfilledBefore);
|
||||||
result.setFulfilledAfter(fulfilledBefore);
|
result.setFulfilledAfter(fulfilledBefore);
|
||||||
result.setProductNameSnapshot(productNameSnapshot);
|
result.setProductNameSnapshot(productNameSnapshot);
|
||||||
result.setUnitSnapshot(unitSnapshot);
|
result.setUnitSnapshot(unitSnapshot);
|
||||||
result.setConversionToBaseSnapshot(conversionToBaseSnapshot);
|
result.setBaseQuantityPerUnitSnapshot(baseQuantityPerUnitSnapshot);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -196,12 +196,12 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
if (!Boolean.TRUE.equals(product.getAllowDecimalQuantity())) {
|
if (!Boolean.TRUE.equals(product.getAllowDecimalQuantity())) {
|
||||||
TimiException.requiredTrue(quantity.stripTrailingZeros().scale() <= 0, "该产品不允许小数数量");
|
TimiException.requiredTrue(quantity.stripTrailingZeros().scale() <= 0, "该产品不允许小数数量");
|
||||||
}
|
}
|
||||||
unitService.convertToBase(unitEntity, quantity);
|
unitService.convertQuantityToBase(unitEntity, quantity);
|
||||||
String key = item.getProductId() + "|" + item.getProductUnitId();
|
String key = item.getProductId() + "|" + item.getProductUnitId();
|
||||||
TimiException.requiredTrue(keySet.add(key), "同一套餐内产品和单位不能重复");
|
TimiException.requiredTrue(keySet.add(key), "同一套餐内产品和单位不能重复");
|
||||||
item.setProductNameSnapshot(product.getName());
|
item.setProductNameSnapshot(product.getName());
|
||||||
item.setUnitSnapshot(unitEntity.getName());
|
item.setUnitSnapshot(unitEntity.getName());
|
||||||
item.setConversionToBaseSnapshot(unitEntity.getConversionToBase());
|
item.setBaseQuantityPerUnitSnapshot(unitEntity.getBaseQuantityPerUnit());
|
||||||
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
item.setSort(TimiJava.defaultIfNull(item.getSort(), i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ public class GaoPackageConfigServiceImplement extends AbstractEntityService<GaoP
|
|||||||
item.setProductUnitId(source.getProductUnitId());
|
item.setProductUnitId(source.getProductUnitId());
|
||||||
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
item.setProductNameSnapshot(source.getProductNameSnapshot());
|
||||||
item.setUnitSnapshot(source.getUnitSnapshot());
|
item.setUnitSnapshot(source.getUnitSnapshot());
|
||||||
item.setConversionToBaseSnapshot(source.getConversionToBaseSnapshot());
|
item.setBaseQuantityPerUnitSnapshot(source.getBaseQuantityPerUnitSnapshot());
|
||||||
item.setDefaultQuantity(source.getDefaultQuantity());
|
item.setDefaultQuantity(source.getDefaultQuantity());
|
||||||
item.setSort(source.getSort());
|
item.setSort(source.getSort());
|
||||||
item.setRemark(source.getRemark());
|
item.setRemark(source.getRemark());
|
||||||
|
|||||||
+2
-3
@@ -143,7 +143,6 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
product.setStockEnabled(TimiJava.defaultIfNull(request.getStockEnabled(), product.getStockEnabled()));
|
product.setStockEnabled(TimiJava.defaultIfNull(request.getStockEnabled(), product.getStockEnabled()));
|
||||||
product.setAllowDecimalQuantity(TimiJava.defaultIfNull(request.getAllowDecimalQuantity(), product.getAllowDecimalQuantity()));
|
product.setAllowDecimalQuantity(TimiJava.defaultIfNull(request.getAllowDecimalQuantity(), product.getAllowDecimalQuantity()));
|
||||||
product.setStatus(TimiJava.defaultIfNull(request.getStatus(), product.getStatus()));
|
product.setStatus(TimiJava.defaultIfNull(request.getStatus(), product.getStatus()));
|
||||||
product.setSalePrice(request.getSalePrice());
|
|
||||||
product.setReferenceCost(request.getReferenceCost());
|
product.setReferenceCost(request.getReferenceCost());
|
||||||
product.setMinStockQuantity(request.getMinStockQuantity());
|
product.setMinStockQuantity(request.getMinStockQuantity());
|
||||||
product.setSort(TimiJava.defaultIfNull(request.getSort(), product.getSort()));
|
product.setSort(TimiJava.defaultIfNull(request.getSort(), product.getSort()));
|
||||||
@@ -197,7 +196,6 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
TimiException.requiredTrue(product.getProductType() != GaoProduct.ProductType.SERVICE || !product.getStockEnabled(), "SERVICE 产品不能启用库存");
|
TimiException.requiredTrue(product.getProductType() != GaoProduct.ProductType.SERVICE || !product.getStockEnabled(), "SERVICE 产品不能启用库存");
|
||||||
product.setAllowDecimalQuantity(TimiJava.defaultIfNull(product.getAllowDecimalQuantity(), false));
|
product.setAllowDecimalQuantity(TimiJava.defaultIfNull(product.getAllowDecimalQuantity(), false));
|
||||||
product.setStatus(TimiJava.defaultIfNull(product.getStatus(), GaoProduct.Status.ACTIVE));
|
product.setStatus(TimiJava.defaultIfNull(product.getStatus(), GaoProduct.Status.ACTIVE));
|
||||||
product.setSalePrice(nonNegative(product.getSalePrice(), "建议售价不能为负数"));
|
|
||||||
product.setReferenceCost(nonNegative(product.getReferenceCost(), "参考成本不能为负数"));
|
product.setReferenceCost(nonNegative(product.getReferenceCost(), "参考成本不能为负数"));
|
||||||
if (!Boolean.TRUE.equals(product.getStockEnabled())) {
|
if (!Boolean.TRUE.equals(product.getStockEnabled())) {
|
||||||
TimiException.requiredNull(product.getMinStockQuantity(), "未启用库存的产品不能填写最低库存");
|
TimiException.requiredNull(product.getMinStockQuantity(), "未启用库存的产品不能填写最低库存");
|
||||||
@@ -232,7 +230,8 @@ public class GaoProductServiceImplement extends AbstractEntityService<GaoProduct
|
|||||||
unit.setId(existing == null ? null : existing.getId());
|
unit.setId(existing == null ? null : existing.getId());
|
||||||
unit.setProductId(productId);
|
unit.setProductId(productId);
|
||||||
unit.setName(source.getName());
|
unit.setName(source.getName());
|
||||||
unit.setConversionToBase(source.getConversionToBase());
|
unit.setBaseQuantityPerUnit(source.getBaseQuantityPerUnit());
|
||||||
|
unit.setSalePrice(source.getSalePrice());
|
||||||
unit.setIsBase(source.getIsBase());
|
unit.setIsBase(source.getIsBase());
|
||||||
unit.setAllowPurchase(source.getAllowPurchase());
|
unit.setAllowPurchase(source.getAllowPurchase());
|
||||||
unit.setAllowSale(source.getAllowSale());
|
unit.setAllowSale(source.getAllowSale());
|
||||||
|
|||||||
+2
-2
@@ -175,7 +175,7 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
GaoProductUnit unit = selection.getUnit();
|
GaoProductUnit unit = selection.getUnit();
|
||||||
TimiException.requiredTrue(Boolean.TRUE.equals(product.getStockEnabled()), "该产品未启用库存管理");
|
TimiException.requiredTrue(Boolean.TRUE.equals(product.getStockEnabled()), "该产品未启用库存管理");
|
||||||
BigDecimal quantity = validateQuantity(product, request.getQuantity());
|
BigDecimal quantity = validateQuantity(product, request.getQuantity());
|
||||||
BigDecimal baseQuantity = unitService.convertToBase(unit, quantity);
|
BigDecimal baseQuantity = unitService.convertQuantityToBase(unit, quantity);
|
||||||
List<GaoStockRecord> existingList = recordService.listByRequestNo(storeId, requestNo);
|
List<GaoStockRecord> existingList = recordService.listByRequestNo(storeId, requestNo);
|
||||||
if (!existingList.isEmpty()) {
|
if (!existingList.isEmpty()) {
|
||||||
GaoStockRecord existing = existingList.getFirst();
|
GaoStockRecord existing = existingList.getFirst();
|
||||||
@@ -237,7 +237,7 @@ public class GaoProductStockServiceImplement implements GaoProductStockService {
|
|||||||
record.setProductUnitId(item.getProductUnitId());
|
record.setProductUnitId(item.getProductUnitId());
|
||||||
record.setProductNameSnapshot(item.getProductNameSnapshot());
|
record.setProductNameSnapshot(item.getProductNameSnapshot());
|
||||||
record.setUnitSnapshot(item.getUnitSnapshot());
|
record.setUnitSnapshot(item.getUnitSnapshot());
|
||||||
record.setConversionToBaseSnapshot(item.getConversionToBaseSnapshot());
|
record.setBaseQuantityPerUnitSnapshot(item.getBaseQuantityPerUnitSnapshot());
|
||||||
record.setQuantity(item.getQuantity());
|
record.setQuantity(item.getQuantity());
|
||||||
record.setBaseQuantity(item.getBaseQuantity());
|
record.setBaseQuantity(item.getBaseQuantity());
|
||||||
record.setOperationType(operationType);
|
record.setOperationType(operationType);
|
||||||
|
|||||||
+16
-8
@@ -44,16 +44,17 @@ public class GaoProductUnitServiceImplement implements GaoProductUnitService {
|
|||||||
}
|
}
|
||||||
unit.setName(requiredText(source.getName(), "产品单位名称不能为空"));
|
unit.setName(requiredText(source.getName(), "产品单位名称不能为空"));
|
||||||
TimiException.requiredTrue(nameSet.add(unit.getName()), "同一产品的单位名称不能重复");
|
TimiException.requiredTrue(nameSet.add(unit.getName()), "同一产品的单位名称不能重复");
|
||||||
unit.setConversionToBase(TimiJava.defaultIfNull(source.getConversionToBase(), ONE));
|
unit.setBaseQuantityPerUnit(TimiJava.defaultIfNull(source.getBaseQuantityPerUnit(), ONE));
|
||||||
TimiException.requiredTrue(0 < unit.getConversionToBase().signum(), "单位折算率必须大于 0");
|
TimiException.requiredTrue(0 < unit.getBaseQuantityPerUnit().signum(), "基础单位数量系数必须大于 0");
|
||||||
TimiException.requiredTrue(6 >= unit.getConversionToBase().scale(), "单位折算率最多保留六位小数");
|
TimiException.requiredTrue(6 >= unit.getBaseQuantityPerUnit().scale(), "基础单位数量系数最多保留六位小数");
|
||||||
|
unit.setSalePrice(nonNegative(source.getSalePrice(), "单位建议售价不能为负数"));
|
||||||
unit.setIsBase(Boolean.TRUE.equals(source.getIsBase()));
|
unit.setIsBase(Boolean.TRUE.equals(source.getIsBase()));
|
||||||
unit.setAllowPurchase(TimiJava.defaultIfNull(source.getAllowPurchase(), true));
|
unit.setAllowPurchase(TimiJava.defaultIfNull(source.getAllowPurchase(), true));
|
||||||
unit.setAllowSale(TimiJava.defaultIfNull(source.getAllowSale(), true));
|
unit.setAllowSale(TimiJava.defaultIfNull(source.getAllowSale(), true));
|
||||||
unit.setSort(TimiJava.defaultIfNull(source.getSort(), i));
|
unit.setSort(TimiJava.defaultIfNull(source.getSort(), i));
|
||||||
if (unit.getIsBase()) {
|
if (unit.getIsBase()) {
|
||||||
TimiException.requiredNull(base, "一个产品只能有一个基础单位");
|
TimiException.requiredNull(base, "一个产品只能有一个基础单位");
|
||||||
TimiException.requiredTrue(unit.getConversionToBase().compareTo(ONE) == 0, "基础单位折算率必须为 1");
|
TimiException.requiredTrue(unit.getBaseQuantityPerUnit().compareTo(ONE) == 0, "基础单位数量系数必须为 1");
|
||||||
TimiException.requiredTrue(baseUnit.equals(unit.getName()), "基础单位名称必须与产品基础单位一致");
|
TimiException.requiredTrue(baseUnit.equals(unit.getName()), "基础单位名称必须与产品基础单位一致");
|
||||||
base = unit;
|
base = unit;
|
||||||
}
|
}
|
||||||
@@ -65,22 +66,22 @@ public class GaoProductUnitServiceImplement implements GaoProductUnitService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BigDecimal convertToBase(GaoProductUnit unit, BigDecimal quantity) {
|
public BigDecimal convertQuantityToBase(GaoProductUnit unit, BigDecimal quantity) {
|
||||||
TimiException.required(unit, "not found product unit");
|
TimiException.required(unit, "not found product unit");
|
||||||
TimiException.required(quantity, "数量不能为空");
|
TimiException.required(quantity, "数量不能为空");
|
||||||
TimiException.requiredTrue(0 < quantity.signum(), "数量必须大于 0");
|
TimiException.requiredTrue(0 < quantity.signum(), "数量必须大于 0");
|
||||||
BigDecimal result = quantity.multiply(unit.getConversionToBase());
|
BigDecimal result = quantity.multiply(unit.getBaseQuantityPerUnit());
|
||||||
try {
|
try {
|
||||||
return result.setScale(3, RoundingMode.UNNECESSARY);
|
return result.setScale(3, RoundingMode.UNNECESSARY);
|
||||||
} catch (ArithmeticException e) {
|
} catch (ArithmeticException e) {
|
||||||
throw new TimiException(com.imyeyu.java.bean.timi.TimiCode.ERROR, "业务数量折算后不能精确保存为三位小数", e);
|
throw new TimiException(com.imyeyu.java.bean.timi.TimiCode.ERROR, "业务数量换算后不能精确保存为三位小数", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private GaoProductUnit createBaseUnit(GaoProduct product) {
|
private GaoProductUnit createBaseUnit(GaoProduct product) {
|
||||||
GaoProductUnit unit = new GaoProductUnit();
|
GaoProductUnit unit = new GaoProductUnit();
|
||||||
unit.setName(product.getBaseUnit());
|
unit.setName(product.getBaseUnit());
|
||||||
unit.setConversionToBase(ONE);
|
unit.setBaseQuantityPerUnit(ONE);
|
||||||
unit.setIsBase(true);
|
unit.setIsBase(true);
|
||||||
unit.setAllowPurchase(Boolean.TRUE.equals(product.getStockEnabled()));
|
unit.setAllowPurchase(Boolean.TRUE.equals(product.getStockEnabled()));
|
||||||
unit.setAllowSale(true);
|
unit.setAllowSale(true);
|
||||||
@@ -94,4 +95,11 @@ public class GaoProductUnitServiceImplement implements GaoProductUnitService {
|
|||||||
TimiException.requiredTrue(!result.isEmpty(), message);
|
TimiException.requiredTrue(!result.isEmpty(), message);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Long nonNegative(Long value, String message) {
|
||||||
|
if (value != null) {
|
||||||
|
TimiException.requiredTrue(0 <= value, message);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -357,13 +357,13 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
GaoProduct product = selection.getProduct();
|
GaoProduct product = selection.getProduct();
|
||||||
GaoProductUnit unit = selection.getUnit();
|
GaoProductUnit unit = selection.getUnit();
|
||||||
BigDecimal quantity = validateQuantity(product, source.getQuantity());
|
BigDecimal quantity = validateQuantity(product, source.getQuantity());
|
||||||
unitService.convertToBase(unit, quantity);
|
unitService.convertQuantityToBase(unit, quantity);
|
||||||
Long unitPrice = TimiJava.defaultIfNull(source.getUnitPrice(), product.getSalePrice());
|
Long unitPrice = TimiJava.defaultIfNull(source.getUnitPrice(), unit.getSalePrice());
|
||||||
TimiException.required(unitPrice, "产品单价不能为空");
|
TimiException.required(unitPrice, "产品单价不能为空");
|
||||||
TimiException.requiredTrue(0 <= unitPrice, "产品单价不能为负数");
|
TimiException.requiredTrue(0 <= unitPrice, "产品单价不能为负数");
|
||||||
if (!canOverridePrice) {
|
if (!canOverridePrice) {
|
||||||
TimiException.required(product.getSalePrice(), "普通员工只能使用建议售价");
|
TimiException.required(unit.getSalePrice(), "普通员工只能使用单位建议售价");
|
||||||
TimiException.requiredTrue(product.getSalePrice().equals(unitPrice), "普通员工只能使用建议售价");
|
TimiException.requiredTrue(unit.getSalePrice().equals(unitPrice), "普通员工只能使用单位建议售价");
|
||||||
}
|
}
|
||||||
long lineAmount = toCentAmount(quantity, unitPrice);
|
long lineAmount = toCentAmount(quantity, unitPrice);
|
||||||
GaoSalesOrderItem item = new GaoSalesOrderItem();
|
GaoSalesOrderItem item = new GaoSalesOrderItem();
|
||||||
@@ -371,7 +371,7 @@ public class GaoSalesOrderServiceImplement extends AbstractEntityService<GaoSale
|
|||||||
item.setProductUnitId(unit.getId());
|
item.setProductUnitId(unit.getId());
|
||||||
item.setProductNameSnapshot(product.getName());
|
item.setProductNameSnapshot(product.getName());
|
||||||
item.setUnitSnapshot(unit.getName());
|
item.setUnitSnapshot(unit.getName());
|
||||||
item.setConversionToBaseSnapshot(unit.getConversionToBase());
|
item.setBaseQuantityPerUnitSnapshot(unit.getBaseQuantityPerUnit());
|
||||||
item.setQuantity(quantity);
|
item.setQuantity(quantity);
|
||||||
item.setReservedQuantity(ZERO);
|
item.setReservedQuantity(ZERO);
|
||||||
item.setFulfilledQuantity(ZERO);
|
item.setFulfilledQuantity(ZERO);
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public class GaoCustomerPackagePurchaseItem {
|
|||||||
/// 单位快照,由后端生成
|
/// 单位快照,由后端生成
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照,由后端生成
|
/// 基础单位数量系数快照,由后端生成
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 总权益数量
|
/// 总权益数量
|
||||||
private BigDecimal totalQuantity;
|
private BigDecimal totalQuantity;
|
||||||
|
|||||||
@@ -25,8 +25,8 @@ public class GaoStockChangeItem {
|
|||||||
/// 单位名称快照
|
/// 单位名称快照
|
||||||
private String unitSnapshot;
|
private String unitSnapshot;
|
||||||
|
|
||||||
/// 折算率快照
|
/// 基础单位数量系数快照
|
||||||
private BigDecimal conversionToBaseSnapshot;
|
private BigDecimal baseQuantityPerUnitSnapshot;
|
||||||
|
|
||||||
/// 业务数量
|
/// 业务数量
|
||||||
private BigDecimal quantity;
|
private BigDecimal quantity;
|
||||||
@@ -50,7 +50,7 @@ public class GaoStockChangeItem {
|
|||||||
result.productUnitId = unit.getId();
|
result.productUnitId = unit.getId();
|
||||||
result.productNameSnapshot = product.getName();
|
result.productNameSnapshot = product.getName();
|
||||||
result.unitSnapshot = unit.getName();
|
result.unitSnapshot = unit.getName();
|
||||||
result.conversionToBaseSnapshot = unit.getConversionToBase();
|
result.baseQuantityPerUnitSnapshot = unit.getBaseQuantityPerUnit();
|
||||||
result.quantity = quantity;
|
result.quantity = quantity;
|
||||||
result.baseQuantity = baseQuantity;
|
result.baseQuantity = baseQuantity;
|
||||||
return result;
|
return result;
|
||||||
|
|||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
ALTER TABLE `gao_product_unit`
|
||||||
|
ADD COLUMN IF NOT EXISTS `sale_price` BIGINT NULL COMMENT '该业务单位建议售价,单位分' AFTER `name`;
|
||||||
|
|
||||||
|
UPDATE `gao_product_unit` u
|
||||||
|
JOIN `gao_product` p ON p.`id` = u.`product_id`
|
||||||
|
SET u.`sale_price` = p.`sale_price`
|
||||||
|
WHERE u.`sale_price` IS NULL;
|
||||||
|
|
||||||
|
ALTER TABLE `gao_product_unit`
|
||||||
|
CHANGE COLUMN `conversion_to_base` `base_quantity_per_unit` DECIMAL(18,6) NOT NULL COMMENT '每个业务单位对应的基础单位数量';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_stock_record`
|
||||||
|
CHANGE COLUMN `conversion_to_base_snapshot` `base_quantity_per_unit_snapshot` DECIMAL(18,6) NOT NULL COMMENT '基础单位数量系数快照';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_sales_order_item`
|
||||||
|
CHANGE COLUMN `conversion_to_base_snapshot` `base_quantity_per_unit_snapshot` DECIMAL(18,6) NOT NULL COMMENT '基础单位数量系数快照';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_package_config_item`
|
||||||
|
CHANGE COLUMN `conversion_to_base_snapshot` `base_quantity_per_unit_snapshot` DECIMAL(18,6) NOT NULL COMMENT '基础单位数量系数快照';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_customer_package_item`
|
||||||
|
CHANGE COLUMN `conversion_to_base_snapshot` `base_quantity_per_unit_snapshot` DECIMAL(18,6) NOT NULL COMMENT '基础单位数量系数快照';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_order_fulfillment_item`
|
||||||
|
CHANGE COLUMN `conversion_to_base_snapshot` `base_quantity_per_unit_snapshot` DECIMAL(18,6) NOT NULL COMMENT '基础单位数量系数快照';
|
||||||
|
|
||||||
|
ALTER TABLE `gao_product`
|
||||||
|
DROP COLUMN `sale_price`;
|
||||||
@@ -5,7 +5,8 @@
|
|||||||
<id column="id" property="id"/>
|
<id column="id" property="id"/>
|
||||||
<result column="product_id" property="productId"/>
|
<result column="product_id" property="productId"/>
|
||||||
<result column="name" property="name"/>
|
<result column="name" property="name"/>
|
||||||
<result column="conversion_to_base" property="conversionToBase"/>
|
<result column="base_quantity_per_unit" property="baseQuantityPerUnit"/>
|
||||||
|
<result column="sale_price" property="salePrice"/>
|
||||||
<result column="is_base" property="isBase"/>
|
<result column="is_base" property="isBase"/>
|
||||||
<result column="allow_purchase" property="allowPurchase"/>
|
<result column="allow_purchase" property="allowPurchase"/>
|
||||||
<result column="allow_sale" property="allowSale"/>
|
<result column="allow_sale" property="allowSale"/>
|
||||||
@@ -37,7 +38,7 @@
|
|||||||
</select>
|
</select>
|
||||||
<update id="updateUnit">
|
<update id="updateUnit">
|
||||||
UPDATE `gao_product_unit`
|
UPDATE `gao_product_unit`
|
||||||
SET `name` = #{name}, `conversion_to_base` = #{conversionToBase}, `is_base` = #{isBase},
|
SET `name` = #{name}, `base_quantity_per_unit` = #{baseQuantityPerUnit}, `sale_price` = #{salePrice}, `is_base` = #{isBase},
|
||||||
`allow_purchase` = #{allowPurchase}, `allow_sale` = #{allowSale}, `sort` = #{sort},
|
`allow_purchase` = #{allowPurchase}, `allow_sale` = #{allowSale}, `sort` = #{sort},
|
||||||
`updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
`updated_at` = FLOOR(UNIX_TIMESTAMP(NOW(3)) * 1000)
|
||||||
WHERE `id` = #{id} AND `product_id` = #{productId} AND `deleted_at` IS NULL
|
WHERE `id` = #{id} AND `product_id` = #{productId} AND `deleted_at` IS NULL
|
||||||
|
|||||||
Reference in New Issue
Block a user