@@ -18,6 +18,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.time.LocalDate ;
import java.time.LocalDateTime ;
import java.time.format.DateTimeFormatter ;
@@ -41,6 +42,11 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
private static final String SUM_DATA_TYPE = " sum_data " ;
/** 按买家手机号 + 购买日期汇总的人天统计 */
private static final String BUYER_DAY_STAT_DATA_TYPE = " day_stat " ;
private static final long BUYER_DAY_STAT_ID_BASE = 20_000_000_000_000_000L ;
private static final int DINGTALK_SELLER_CONFIRM_BATCH_SIZE = 15 ;
private static final String DINGTALK_SELLER_CONFIRM_PREFIX =
@@ -462,19 +468,45 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
String nowStr = LocalDateTime . now ( ) . format ( DAY_TIME_FMT ) ;
List < LbOrderRow > sumRows = new ArrayList < > ( byDay . size ( ) ) ;
List < LbOrderRow > buyerDayStatRows = new ArrayList < > ( ) ;
int skippedNoBuyerPhone = 0 ;
for ( Map . Entry < LocalDate , List < LbOrderRow > > entry : byDay . entrySet ( ) ) {
sumRows . add ( buildDailySumRow ( tid , entry . getKey ( ) , entry . getValue ( ) , nowStr ) ) ;
LocalDate day = entry . getKey ( ) ;
List < LbOrderRow > dayRows = entry . getValue ( ) ;
sumRows . add ( buildDailySumRow ( tid , day , dayRows , nowStr ) ) ;
Map < String , List < LbOrderRow > > byBuyerPhone = new LinkedHashMap < > ( ) ;
for ( LbOrderRow row : dayRows ) {
String buyerPhone = trimToNull ( row . getBuyerPhone ( ) ) ;
if ( buyerPhone = = null ) {
skippedNoBuyerPhone + + ;
continue ;
}
byBuyerPhone . computeIfAbsent ( buyerPhone , k - > new ArrayList < > ( ) ) . add ( row ) ;
}
for ( Map . Entry < String , List < LbOrderRow > > buyerEntry : byBuyerPhone . entrySet ( ) ) {
buyerDayStatRows . add (
buildBuyerDayStatRow (
tid , day , buyerEntry . getKey ( ) , buyerEntry . getValue ( ) , nowStr ) ) ;
}
}
int upserted = upsertBatch ( sumRows ) ;
List < LbOrderRow > allStatRows = new ArrayList < > ( sumRows . size ( ) + buyerDayStatRows . size ( ) ) ;
allStatRows . addAll ( sumRows ) ;
allStatRows . addAll ( buyerDayStatRows ) ;
int upserted = upsertBatch ( allStatRows ) ;
boolean ok = upserted > = 0 ;
result . put ( " success " , ok ) ;
result . put ( " message " , ok ? " 按日汇总完成 " : " 保存失败 " ) ;
result . put ( " generated " , ok ? upserted : 0 ) ;
result . put ( " sumDataGenerated " , ok ? sumRows . size ( ) : 0 ) ;
result . put ( " buyerDayStatGenerated " , ok ? buyerDayStatRows . size ( ) : 0 ) ;
result . put ( " sourceCount " , details . size ( ) ) ;
result . put ( " skippedNoBuyTime " , skippedNoBuyTime ) ;
result . put ( " skippedNoBuyerPhone " , skippedNoBuyerPhone ) ;
if ( ok ) {
result . put ( " data " , sumRows ) ;
result . put ( " buyerDayStatData " , buyerDayStatRows ) ;
}
return result ;
} catch ( Exception e ) {
@@ -586,6 +618,11 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
}
}
int orderCount = dayRows . size ( ) ;
BigDecimal avgAmt = orderCount > 0
? moneySum . divide ( BigDecimal . valueOf ( orderCount ) , 2 , RoundingMode . HALF_UP )
: BigDecimal . ZERO ;
String payTime = day . atStartOfDay ( ) . format ( DAY_TIME_FMT ) ;
Long id = resolveSumRowId ( tenantId , payTime ) ;
@@ -595,7 +632,8 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
sum . setDataType ( SUM_DATA_TYPE ) ;
sum . setTodayTotalMoneySum ( moneySum ) ;
sum . setTodayUnresellCount ( unresellCount ) ;
sum . setTodayOrderCount ( dayRows . size ( ) ) ;
sum . setTodayOrderCount ( orderCount ) ;
sum . setAvgAmt ( avgAmt ) ;
sum . setSellerId ( SUM_PLACEHOLDER_USER_ID ) ;
sum . setBuyerId ( SUM_PLACEHOLDER_USER_ID ) ;
sum . setOrderSn ( SUM_ORDER_SN ) ;
@@ -613,6 +651,70 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
return sum ;
}
/** 按 buyer_phone + 购买日期生成人天统计( day_stat) */
private LbOrderRow buildBuyerDayStatRow (
String tenantId ,
LocalDate day ,
String buyerPhone ,
List < LbOrderRow > buyerDayRows ,
String nowStr ) {
BigDecimal moneySum = BigDecimal . ZERO ;
for ( LbOrderRow row : buyerDayRows ) {
if ( row . getTotalMoney ( ) ! = null ) {
moneySum = moneySum . add ( row . getTotalMoney ( ) ) ;
}
}
int orderCount = buyerDayRows . size ( ) ;
BigDecimal avgAmt = orderCount > 0
? moneySum . divide ( BigDecimal . valueOf ( orderCount ) , 2 , RoundingMode . HALF_UP )
: BigDecimal . ZERO ;
String payTime = day . atStartOfDay ( ) . format ( DAY_TIME_FMT ) ;
Long id = resolveBuyerDayStatRowId ( tenantId , buyerPhone , payTime ) ;
LbOrderRow sample = buyerDayRows . get ( 0 ) ;
LbOrderRow stat = new LbOrderRow ( ) ;
stat . setId ( id ) ;
stat . setTenantId ( tenantId ) ;
stat . setDataType ( BUYER_DAY_STAT_DATA_TYPE ) ;
stat . setBuyerPhone ( buyerPhone ) ;
stat . setBuyerId ( sample . getBuyerId ( ) ) ;
stat . setBuyerName ( sample . getBuyerName ( ) ) ;
stat . setPhone ( buyerPhone ) ;
stat . setTodayTotalMoneySum ( moneySum ) ;
stat . setTodayOrderCount ( orderCount ) ;
stat . setAvgAmt ( avgAmt ) ;
stat . setTotalMoney ( moneySum ) ;
stat . setOrderSn ( " day_stat_ " + buyerPhone + " _ " + day . format ( DAY_FMT ) ) ;
stat . setPayTime ( payTime ) ;
stat . setBuyTime ( payTime ) ;
stat . setStatus ( 1 ) ;
stat . setIsShow ( 1 ) ;
stat . setCreatedAt ( nowStr ) ;
stat . setUpdatedAt ( nowStr ) ;
return stat ;
}
/** 同一天、同一租户、同一 buyer_phone 已存在 day_stat 则复用其 id, 否则生成占位 id */
private Long resolveBuyerDayStatRowId ( String tenantId , String buyerPhone , String payTime ) {
LambdaQueryWrapper < LbOrderRow > w = new LambdaQueryWrapper < > ( ) ;
w . eq ( LbOrderRow : : getTenantId , tenantId )
. eq ( LbOrderRow : : getDataType , BUYER_DAY_STAT_DATA_TYPE )
. eq ( LbOrderRow : : getBuyerPhone , buyerPhone )
. eq ( LbOrderRow : : getPayTime , payTime )
. last ( " LIMIT 1 " ) ;
LbOrderRow existing = this . getOne ( w , false ) ;
if ( existing ! = null & & existing . getId ( ) ! = null ) {
return existing . getId ( ) ;
}
LocalDate day = LocalDate . parse ( payTime . substring ( 0 , 10 ) , DAY_FMT ) ;
long dayKey = day . getYear ( ) * 10000L + day . getMonthValue ( ) * 100L + day . getDayOfMonth ( ) ;
int phoneSlot = Math . floorMod ( buyerPhone . hashCode ( ) , 10000 ) ;
int tenantSlot = Math . floorMod ( tenantId . hashCode ( ) , 100 ) ;
return BUYER_DAY_STAT_ID_BASE + dayKey * 1_000_000L + phoneSlot * 100L + tenantSlot ;
}
/** 同一天、同一租户已存在 sum_data 则复用其 id, 否则生成占位 id */
private Long resolveSumRowId ( String tenantId , String payTime ) {
LambdaQueryWrapper < LbOrderRow > w = new LambdaQueryWrapper < > ( ) ;