Kaynağa Gözat

分账逻辑修改 增加分润0.01分的归属检测

zjl 1 yıl önce
ebeveyn
işleme
97372c0641
1 değiştirilmiş dosya ile 34 ekleme ve 11 silme
  1. 34 11
      apps/web/report/ledger.py

+ 34 - 11
apps/web/report/ledger.py

@@ -392,23 +392,42 @@ class LedgerConsumeOrder(object):
         group = self._record.group      # type: GroupDict
         partners = group.partners
 
+        # 计算出电费 以及合伙人总分润
         elecFee = group.elecFee * self._record.elecCount    # type: RMB
+        totalPartnerShare = sum((Percent(_["percent"]) for _ in partners), Percent(0))
         if elecFee < RMB(0):
-            raise ValueError("elec lt 0, record = {}".format(self._record))
-
+            raise ValueError("elec lt 0, record = {}".format(self._record.id))
         if self._record.amount < RMB(0):
-            raise ValueError("totalAmount lt 0, record = {}".format(self._record))
+            raise ValueError("totalAmount lt 0, record = {}".format(self._record.id))
+        if totalPartnerShare > Percent(100):
+            raise ValueError("totalPartnerShare gt 100, record = {}".format(self._record.id))
+
+        # 剩下的即为经销商的分润比例
+        dealerShare = Percent(100) - totalPartnerShare
+
+        # 按照分成比例从小到大排序 方便最后一分的归属
+        partners = sorted(partners, key=lambda x: Percent(x["percent"]))
+        logger.info("[LedgerConsumeOrder] record = {}, partners = {}".format(self._record.id, partners))
 
         # 找出电费承担方 如果电费承担不存在 则集体承担
         # 不对totalAmount做非0校验 这个数值确实可能小于0 比如全部使用的是赠送金额的钱 但是存在电费
         elecPayer = self._get_elec_payer(partners)
         totalAmount = self._record.amount - elecFee if elecPayer else self._record.amount
 
-        totalMoney, totalP, partition = RMB(0), Percent(0), list()
+        # 然后计算出总体要分得的金额 这个金额有可能是一个负数 根据totalAmount而定
+        totalPartnerAmount = totalAmount * totalPartnerShare.as_ratio
 
+        # 开始计算各个合伙人的收益
+        totalMoney, totalP, partition, leftShareMoney, elecPayerCount = RMB(0), Percent(0), list(), totalPartnerAmount, 0
         for _partner in partners:
-            _m = totalAmount * Percent(_partner["percent"]).as_ratio
             _s = Percent(_partner["percent"])
+            _m = totalAmount * Percent(_partner["percent"]).as_ratio
+
+            if abs(_m) > abs(leftShareMoney):
+                _m = leftShareMoney
+
+            leftShareMoney -= _m
+
             _p = {
                 "role": PARTITION_ROLE.PARTNER,
                 "id": _partner["id"],
@@ -420,26 +439,30 @@ class LedgerConsumeOrder(object):
                 _p.update({
                     "elecFee": elecFee.mongo_amount
                 })
+                elecPayerCount += 1
 
             totalMoney += _m
             totalP += _s
             partition.append(_p)
 
+        if elecPayerCount > 1:
+            raise ValueError("elecPayerCount gt 1, record = {}".format(self._record.id))
         if abs(totalMoney) > abs(totalAmount):
-            raise ValueError("total share money <{}> gt total amount <{}>, record = {}".format(totalMoney, totalAmount, self._record))
-        if totalP > Percent(100):
-            raise ValueError(u"total share percent gt 100, record = {}".format(self._record))
+            raise ValueError("total share money <{}> gt total amount <{}>, record = {}".format(totalMoney, totalAmount, self._record.id))
+        if totalP != totalPartnerShare:
+            raise ValueError(u"total share percent gt 100, record = {}".format(self._record.id))
+        if totalMoney != totalPartnerAmount:
+            raise ValueError("total share money <{}> gt total partner amount <{}>, record = {}".format(totalMoney, totalPartnerAmount, self._record.id))
 
         partition.append({
             "role": PARTITION_ROLE.OWNER,
             "id": str(self._record.dealerId),
             "share": (Percent(100) - totalP).mongo_amount,
-            "money": (totalAmount - totalMoney).mongo_amount
+            "money": (totalAmount - totalPartnerAmount).mongo_amount
         })
 
-        # TODO 最后再校验一次是否有必要
 
-        logger.info('[_get_partition_map] record = {}, get partition = {}'.format(self._record, partition))
+        logger.info('[_get_partition_map] record = {}, get partition = {}'.format(self._record.id, partition))
         return partition
 
     def _record_balance(self, partition):