Compare commits

...
6 Commits
Author SHA1 Message Date
timi d65424e5bf Merge pull request 'v1.0.43' (#55) from dev into master
Reviewed-on: #55
2026-09-11 17:26:21 +00:00
Timi f0b72b70e7 v1.0.43
CI / build-deploy (pull_request) Successful in 25s
CI / notify-on-failure (pull_request) Skipped
2026-09-12 01:24:03 +08:00
Timi daa5a6aa5e fix off product sku for keep fulfillment 2026-09-12 01:23:47 +08:00
timi 2a35793baf Merge pull request 'v1.0.42' (#54) from dev into master
Reviewed-on: #54
2026-09-11 16:16:04 +00:00
Timi 4a157e9578 v1.0.42
CI / build-deploy (pull_request) Successful in 24s
CI / notify-on-failure (pull_request) Skipped
2026-09-12 00:11:21 +08:00
Timi eabb4c6aa6 fix event record CONTINUOUS_DAYS rank 2026-09-12 00:11:07 +08:00
5 changed files with 64 additions and 10 deletions
+1 -1
View File
@@ -11,7 +11,7 @@
<groupId>com.imyeyu.timiserverapi</groupId> <groupId>com.imyeyu.timiserverapi</groupId>
<artifactId>TimiServerAPI</artifactId> <artifactId>TimiServerAPI</artifactId>
<version>1.0.41</version> <version>1.0.43</version>
<packaging>jar</packaging> <packaging>jar</packaging>
<name>TimiServerAPI</name> <name>TimiServerAPI</name>
<description>imyeyu.com API</description> <description>imyeyu.com API</description>
@@ -33,6 +33,14 @@ public interface GaoProductSkuService extends BaseService<GaoProductSku, String>
/// 查询并校验可销售 SKU 单位 /// 查询并校验可销售 SKU 单位
GaoProductSkuUnitSelection getSellableSkuUnit(String storeId, String skuId, String skuUnitId); GaoProductSkuUnitSelection getSellableSkuUnit(String storeId, String skuId, String skuUnitId);
/// 查询并校验可用于历史订单履约的 SKU 单位
///
/// @param storeId 门店 ID
/// @param skuId SKU ID
/// @param skuUnitId SKU 单位 ID
/// @return SKU 单位选择结果
GaoProductSkuUnitSelection getFulfillableSkuUnit(String storeId, String skuId, String skuUnitId);
/// 查询并校验 SKU 单位 /// 查询并校验 SKU 单位
GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase); GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase);
@@ -450,12 +450,32 @@ public class GaoOrderFulfillmentServiceImplement extends AbstractEntityService<G
GaoSalesOrderItem.ItemType expectedItemType = order.getOrderType() == GaoSalesOrder.OrderType.PACKAGE GaoSalesOrderItem.ItemType expectedItemType = order.getOrderType() == GaoSalesOrder.OrderType.PACKAGE
? GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT : GaoSalesOrderItem.ItemType.DIRECT_PRODUCT; ? GaoSalesOrderItem.ItemType.PACKAGE_ENTITLEMENT : GaoSalesOrderItem.ItemType.DIRECT_PRODUCT;
TimiException.requiredTrue(source.getItemType() == expectedItemType, "订单项类型与订单类型不匹配"); TimiException.requiredTrue(source.getItemType() == expectedItemType, "订单项类型与订单类型不匹配");
GaoProductSkuUnitSelection selection = skuService.getSellableSkuUnit(order.getStoreId(), source.getSkuId(), requestItem.getSkuUnitId()); if (requestItem.getSkuUnitId().equals(source.getSkuUnitId())) {
result.add(toSourceByOrderSnapshot(order, source, requestItem.getQuantity(), checkAvailable));
continue;
}
GaoProductSkuUnitSelection selection = skuService.getFulfillableSkuUnit(order.getStoreId(), source.getSkuId(), requestItem.getSkuUnitId());
result.add(toSource(order, source, selection.getProduct(), selection.getSku(), selection.getUnit(), requestItem.getQuantity(), checkAvailable)); result.add(toSource(order, source, selection.getProduct(), selection.getSku(), selection.getUnit(), requestItem.getQuantity(), checkAvailable));
} }
return result; return result;
} }
private SourceEntry toSourceByOrderSnapshot(GaoSalesOrder order, GaoSalesOrderItem source, BigDecimal quantity, boolean checkAvailable) {
GaoProductSku sku = skuService.get(source.getSkuId());
TimiException.required(sku, "履约来源 SKU 不存在");
GaoProduct product = productService.get(sku.getProductId());
TimiException.required(product, "履约来源产品不存在");
TimiException.requiredTrue(order.getStoreId().equals(product.getStoreId()), "履约来源产品不属于当前门店");
quantity = requiredPositiveQuantity(quantity, "履约数量");
if (!Boolean.TRUE.equals(sku.getAllowDecimalQuantity())) {
TimiException.requiredTrue(quantity.stripTrailingZeros().scale() <= 0, "该产品不允许小数数量");
}
BigDecimal baseQuantityPerUnit = requiredBaseQuantityPerUnit(source.getBaseQuantityPerUnitSnapshot());
BigDecimal baseQuantity = toBaseQuantity(quantity, baseQuantityPerUnit, "履约基础数量最多保留三位小数");
return buildSource(order, source, source.getSkuUnitId(), source.getUnitSnapshot(), baseQuantityPerUnit, quantity,
baseQuantity, product, sku, checkAvailable);
}
private List<SourceEntry> loadPersistedSources(GaoSalesOrder order, List<GaoOrderFulfillmentItem> itemList) { private List<SourceEntry> loadPersistedSources(GaoSalesOrder order, List<GaoOrderFulfillmentItem> itemList) {
TimiException.requiredTrue(itemList != null && !itemList.isEmpty(), "履约单没有明细"); TimiException.requiredTrue(itemList != null && !itemList.isEmpty(), "履约单没有明细");
List<GaoOrderFulfillmentItem> sortedItemList = new ArrayList<>(itemList); List<GaoOrderFulfillmentItem> sortedItemList = new ArrayList<>(itemList);
@@ -109,6 +109,22 @@ public class GaoProductSkuServiceImplement extends AbstractEntityService<GaoProd
return getSkuUnit(storeId, skuId, skuUnitId, false); return getSkuUnit(storeId, skuId, skuUnitId, false);
} }
@Override
public GaoProductSkuUnitSelection getFulfillableSkuUnit(String storeId, String skuId, String skuUnitId) {
TimiException.required(storeId, "门店 ID 不能为空");
TimiException.required(skuId, "SKU ID 不能为空");
TimiException.required(skuUnitId, "SKU 单位 ID 不能为空");
GaoProductSku sku = mapper.selectForUpdate(skuId);
TimiException.required(sku, "SKU 不存在");
TimiException.requiredTrue(storeId.equals(sku.getStoreId()), "SKU 不属于当前门店");
GaoProduct product = productServiceProvider.getObject().get(sku.getProductId());
TimiException.required(product, "产品不存在");
GaoProductSkuUnit unit = unitMapper.selectForUpdate(skuUnitId);
TimiException.required(unit, "SKU 单位不存在");
TimiException.requiredTrue(skuId.equals(unit.getSkuId()), "SKU 单位不属于当前 SKU");
return new GaoProductSkuUnitSelection(product, sku, unit);
}
@Override @Override
public GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase) { public GaoProductSkuUnitSelection getSkuUnit(String storeId, String skuId, String skuUnitId, boolean purchase) {
TimiException.required(storeId, "not found storeId"); TimiException.required(storeId, "not found storeId");
@@ -354,11 +370,8 @@ public class GaoProductSkuServiceImplement extends AbstractEntityService<GaoProd
TimiException.requiredTrue(1 == unitMapper.updateUnit(unit), "SKU 单位更新失败"); TimiException.requiredTrue(1 == unitMapper.updateUnit(unit), "SKU 单位更新失败");
} }
} }
for (GaoProductSkuUnit existing : existingUnitList) { TimiException.requiredTrue(existingUnitList.stream().allMatch(existing -> retainedIdSet.contains(existing.getId())),
if (!retainedIdSet.contains(existing.getId())) { "已保存的 SKU 单位不能删除,请关闭允许销售和允许采购");
unitMapper.delete(existing.getId());
}
}
} }
private void saveSpecValues(String skuId, List<String> specValueIdList) { private void saveSpecValues(String skuId, List<String> specValueIdList) {
@@ -348,10 +348,23 @@
FROM `daily_stat` d FROM `daily_stat` d
JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue` JOIN `open_calendar` o ON d.`registeredDateValue` = o.`dateValue`
), ),
`customer_stat` AS (
SELECT
d.`customerId`,
MAX(CASE WHEN d.`registeredDateValue` = #{todayDateValue} THEN 1 ELSE 0 END) AS `hasToday`
FROM `daily_stat` d
GROUP BY d.`customerId`
),
`anchor_date` AS ( `anchor_date` AS (
SELECT SELECT
MAX(`openIndex`) AS `anchorOpenIndex` s.`customerId`,
FROM `open_calendar` CASE
WHEN s.`hasToday` = 1 THEN MAX(CASE WHEN c.`dateValue` = #{todayDateValue} THEN c.`openIndex` END)
ELSE MAX(CASE WHEN c.`dateValue` &lt; #{todayDateValue} THEN c.`openIndex` END)
END AS `anchorOpenIndex`
FROM `customer_stat` s
CROSS JOIN `open_calendar` c
GROUP BY s.`customerId`, s.`hasToday`
), ),
`continuous_stat` AS ( `continuous_stat` AS (
SELECT SELECT
@@ -361,7 +374,7 @@
ELSE COUNT(1) ELSE COUNT(1)
END AS `recentContinuousEventDays` END AS `recentContinuousEventDays`
FROM `continuous_ordered` o FROM `continuous_ordered` o
JOIN `anchor_date` a JOIN `anchor_date` a ON o.`customerId` = a.`customerId`
WHERE WHERE
o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1 o.`openIndex` + o.`dayIndex` = a.`anchorOpenIndex` + 1
<if test="eventIdList == null or eventIdList.size() != 1"> <if test="eventIdList == null or eventIdList.size() != 1">