Java生鮮電商平臺-帳單模塊的設計與架構算法
補充說明:生鮮電商平臺-帳單模塊的設計與架構,即用戶的帳單造成過程。架構
因爲系統存在一個押帳功能的需求,(何爲押帳,就是造成公司的資金池,相似摩拜單車,ofo單車等等)。目前B2B平臺也是採用押帳的這種功能策略。ide
這裏有個特別說明的押帳方式:就是好比有個賣家張三,他是5月1日跟咱們平臺簽約開始入住平臺賣菜,咱們約定好押帳7天,那麼他5月1日的金額會在5月2日存入設計
他本身的餘額裏面,可是這個錢不能立刻提取出來,須要等一個星期,也就是5月8日能夠提現5月1日的金額,5月9日能夠提現5月2日之前的全部金額。code
這個算法的最大好處就是永遠的壓住客戶7天的金額。blog
這個算法採用的是Spring quartz定時器天天晚上23:00點處理的。ci
相關核心的代碼以下:get
/** * 任務工做 * @author wangfucai */ @Component public class TasksQuartz{ private static final Logger logger=LoggerFactory.getLogger(TasksQuartz.class); @Autowired private BillService billService; @Autowired private SellerService sellerService; @Autowired private DeliveryIncomeService deliveryIncomeService; @Autowired private BuyerService buyerService; @Autowired private OrderInfoService orderInfoService; @Autowired private GroupsBuyerService groupsBuyerService; /** * 計算天天帳單 * 天天23點執行 */ @Scheduled(cron="0 0 23 * * ?") protected void makeBill(){ try { logger.info("TasksQuartz.execute.start"); //統計當天的交易完成的訂單生成帳單 billService.addBills(); logger.info("帳單數據更新完成"); //根據賣家抽點金額更新帳單實際金額 billService.updateRealAmountByPercentage(); logger.info("根據賣家抽點金額更新帳單實際金額完成"); //更新賣家餘額 sellerService.updateBalanceByBill(); logger.info("賣家餘額數據更新完成"); logger.info("TasksQuartz.execute.end"); }catch(Exception ex) { logger.error("TasksQuartz.execute.exception",ex); } }
補充說明:1.須要統計每一個賣家今天的收入。it
2.並行的須要把訂單的數據存入帳單表。io
3.餘額來源於帳單表。造成一個數據的流轉體現。
帳單表的表結構以下:
補充說明:天天定時器會根據賣家的帳期造成帳單,最終更新到用賣家的餘額裏面。
實際運營狀況來說是每一個賣家的帳期是不同的,有的兩天,有的三天,有的一週,有的是一個月。
相關核心算法與代碼以下:
/** * 統計10天前的帳單更新賣家餘額和帳單金額 */ @Override public void updateMoney() { // 獲取10天前的日期d String day = DateUtil.dateToString(DateUtil.addDay(new Date(), -9), DateUtil.FMT_DATE); // 查詢十天前的全部賬單信息 List<Map<String, Object>> list = billDao.getBillsByDay(day); if (CollectionUtils.isEmpty(list)) { logger.info("TasksQuartz.updateMoney.isEmpty-->day:" + day); return; } for (Map<String, Object> map : list) { // 賣家ID Long sellerId = (Long) map.get("sellerId"); if (sellerId == null) { continue; } // 獲取提現的金額即最終帳單的金額 BigDecimal realityMoney = (BigDecimal) map.get("realIncome"); if (realityMoney == null) { continue; } // 獲取賣家的餘額 BigDecimal balanceMoney = (BigDecimal) map.get("balanceMoney"); if (balanceMoney == null) { balanceMoney = BigDecimal.ZERO; } // 獲取賣家的帳單金額 BigDecimal billMoney = (BigDecimal) map.get("billMoney"); if (billMoney == null) { billMoney = BigDecimal.ZERO; } // 金額相加 BigDecimal resultBalanceMoney = realityMoney.add(balanceMoney); BigDecimal resultBillMoney = realityMoney.add(billMoney); logger.info("當前用戶sellerId:" + sellerId + " 當前的餘額爲:balanceMoney=" + balanceMoney + " 最終金額:resultBalanceMoney=" + resultBalanceMoney); logger.info("當前的餘額爲:billMoney=" + billMoney + " 最終金額:resultBillMoney=" + resultBillMoney); // 更新賣家餘額和帳單金額 int result = sellerDao.updateMoney(sellerId, resultBalanceMoney, resultBillMoney); logger.info("當前用戶sellerId:" + sellerId + " 更新結果爲:" + (result > 0)); } // 更新十天前的全部帳單的狀態 int count = billDao.updateStatus(day); logger.info(" 更新" + count + "條帳單,狀態變爲已結算"); }
業務說明:
1. 無外乎天天須要統計賣家的今日收益狀況。
2. 更新賣家的最終餘額。
3. 根據賣家的所設置的帳單週期,造成用戶的帳單金額。
4. 最終根據帳單金額,造成用戶的可提現餘額的過程。
業務有點繞口,可是總體是很是地清晰的,思路就是押用戶所配置的帳期金額。配置10天就壓10天,配置15天就壓15天。
如下是帳單跟賣家的核心關聯表,就是配置所屬的賣家對應的所屬帳期時間。
總結:整個技術方面其實都不算複雜,主要是業務邏輯以及統計的一些概念,但願這些定時器計算,帳單思路造成,架構方面能給你們一些幫助。