jiaweiqi 2 jaren geleden
bovenliggende
commit
4dc4612a79

+ 10 - 1
apps/rebate/bussiness.py

@@ -148,6 +148,10 @@ class CustomerRebateTransfer(object):
             raise CustomError(u'转账总金额大于收款总金额!')
         if instance.amount == 0:
             raise CustomError(u'转账总金额为0!')
+        if instance.rebate.status != CashRebate.DEFAULT:
+            raise CustomError(u'该返利已转账,禁止重复申请!')
+        instance.rebate.status = CashRebate.TRANSFERING
+        instance.rebate.save()
 
         tc = TransferCashRebate.objects.create(order=instance.main.order, transfer_num=1, transfer_amount=instance.amount)
         tc_no = 'TC{}{:0>4}'.format(timezone.now().strftime('%Y%m%d%H%M%S'), tc.id)
@@ -172,12 +176,14 @@ class CustomerRebateTransfer(object):
             raise CustomError(u'该返利已申请转账,禁止重复申请!')
         tc = TransferCashRebate.objects.create(order=self.order)
         tc_no = 'TC{}{:0>4}'.format(timezone.now().strftime('%Y%m%d%H%M%S'), tc.id)
-        rows = CashRebate.objects.filter(order=self.order)
+        rows = CashRebate.objects.filter(order=self.order, status=CashRebate.DEFAULT)
         transfer_amount = 0
         transfer_num = 0
         for row in rows:
             if row.customer.balance < row.amount:
                 raise CustomError(u'客户[{}]余额不足!'.format(row.customer.name))
+            row.status = CashRebate.TRANSFERING
+            row.save()
             transfer_num += 1
             transfer_amount += row.amount
             tcd = TransferCashRebateDetail.objects.create(main=tc, rebate=row, amount=row.amount, customer=row.customer)
@@ -335,6 +341,9 @@ def transfer_detail_refresh(detail):
             CashTransferLog.addnew(detail)
         elif detail_status == 'FAIL':
             detail.status = TransferCashRebateDetail.FAIL
+            # 转账失败 将返利表状态改回 未处理  后边手动处理或重新申请转账都可以
+            detail.rebate.status = CashRebate.DEFAULT
+            detail.rebate.save()
 
     if fail_reason:
         detail.fail_reason = fail_reason

+ 20 - 3
apps/rebate/models.py

@@ -57,8 +57,17 @@ class CashLog(models.Model):
 
 
 class CashRebate(models.Model):
+    DEFAULT = 0      # 未处理
+    TRANSFERING = 1  # 转账中
+    TRANSFERED = 2   # 已转账
+    STATUS = (
+        (DEFAULT, u'未处理'),
+        (TRANSFERING, u'转账中'),
+        (TRANSFERED, u'已转账'),
+    )
 
     order = models.ForeignKey(Order, verbose_name=u'订单', related_name='cash_rebate_order', editable=False, on_delete=models.PROTECT)
+    status = models.PositiveSmallIntegerField(choices=STATUS, verbose_name=u"状态", default=DEFAULT)
     ratio = models.FloatField(verbose_name=u'返利比例', default=0)
     amount = models.BigIntegerField(verbose_name=u'返利金额', default=0)
     customer = models.ForeignKey(Customer, verbose_name=u'客户', editable=False, on_delete=models.PROTECT)
@@ -74,7 +83,7 @@ class CashRebate(models.Model):
 
 
 class CashRebateLog(models.Model):
-    rebate = models.OneToOneField(CashRebate, verbose_name=u'现金返利', related_name='rebate', editable=False, on_delete=models.PROTECT)
+    rebate = models.ForeignKey(CashRebate, verbose_name=u'现金返利', related_name='rebate', editable=False, on_delete=models.PROTECT)
     log = models.OneToOneField(CashLog, verbose_name=u'日志', related_name='rebate_log', editable=False, on_delete=models.PROTECT)
 
     class Meta:
@@ -86,9 +95,15 @@ class CashRebateLog(models.Model):
         permissions = []
 
     @staticmethod
-    def addnew(rebate):
+    def addnew(rebate, off=False):
+        # off = True 手动核销现金返利 记录一条日志
         customer = Customer.objects.select_for_update().filter(id=rebate.customer.id).first()
-        log = CashLog.addnew(customer, CashLog.CASH_REBATE, rebate.amount)
+        type = CashLog.CASH_REBATE
+        amount = rebate.amount
+        if off:
+            type = CashLog.CASH_TRANSFER
+            amount = - rebate.amount
+        log = CashLog.addnew(customer, type, amount)
         instance = CashRebateLog.objects.create(rebate=rebate, log=log)
         return instance
 
@@ -186,6 +201,8 @@ class CashTransferLog(models.Model):
     @staticmethod
     def addnew(transfer):
         customer = Customer.objects.select_for_update().filter(id=transfer.customer.id).first()
+        transfer.rebate.status = CashRebate.TRANSFERED
+        transfer.rebate.save()
         log = CashLog.addnew(customer, CashLog.CASH_TRANSFER, -transfer.amount)
         instance = CashTransferLog.objects.create(transfer=transfer, log=log)
         return instance

+ 24 - 3
apps/rebate/serializers.py

@@ -7,7 +7,7 @@ from rest_framework import serializers
 from django.db.models import Q, Sum
 
 from apps.order.models import Order
-from apps.rebate.models import CashRebate, PointRebate, TransferCashRebate, TransferCashRebateDetail
+from apps.rebate.models import CashRebate, PointRebate, TransferCashRebate, TransferCashRebateDetail, CashRebateLog, CashLog
 from apps.base import Formater
 
 
@@ -38,13 +38,21 @@ class OrderRebateSerializer(serializers.ModelSerializer):
 
     def get_transfer(self, obj):
         transfer = TransferCashRebate.objects.filter(order=obj).count()
-        return transfer
+        cash_bate = CashRebate.objects.filter(order=obj, status=CashRebate.DEFAULT).aggregate(sum_amount=Sum('amount'))['sum_amount'] or 0
+        if transfer:  # 有转账记录 前端显示转账记录按钮
+            return 2
+        if not transfer and cash_bate > 0:  # 没有转账记录 且  未转账的返利合计大于0  前端显示申请转账按钮
+            return 1
+        return 0  # 其他情况不显示按钮
 
 
 class CashRebateSerializer(serializers.ModelSerializer):
     amount = serializers.SerializerMethodField()
     create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
     customer_name = serializers.CharField(source='customer.name', read_only=True)
+    ratio = serializers.SerializerMethodField()
+    status_text = serializers.CharField(source='get_status_display', read_only=True)
+    transfer = serializers.SerializerMethodField()
 
     class Meta:
         model = CashRebate
@@ -53,6 +61,17 @@ class CashRebateSerializer(serializers.ModelSerializer):
     def get_amount(self, obj):
         return Formater.formatValueShow(obj.amount)
 
+    def get_ratio(self, obj):
+        return str(obj.ratio) + '%'
+
+    def get_transfer(self, obj):
+        if obj.status != CashRebate.TRANSFERED:
+            return ''
+        count = CashRebateLog.objects.filter(rebate=obj, log__type=CashLog.CASH_TRANSFER).count()
+        if count:
+            return '手动核销'
+        return '自动转账'
+
 
 class PointRebateSerializer(serializers.ModelSerializer):
     create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
@@ -103,4 +122,6 @@ class TransferCashRebateDetailSerializer(serializers.ModelSerializer):
 
     def get_transfer(self, obj):
         count = TransferCashRebateDetail.objects.filter(Q(rebate=obj.rebate), ~Q(status=TransferCashRebateDetail.FAIL)).count()
-        return count
+        if obj.rebate.status == CashRebate.DEFAULT and not count:
+            return 0
+        return 1

+ 20 - 9
apps/rebate/views.py

@@ -16,7 +16,7 @@ from utils.custom_modelviewset import CustomModelViewSet
 from apps.log.models import BizLog
 from apps.order.models import Order
 from apps.order.filters import OrderFilter
-from apps.rebate.models import PointRebate, CashRebate, TransferCashRebate, TransferCashRebateDetail
+from apps.rebate.models import PointRebate, CashRebate, TransferCashRebate, TransferCashRebateDetail, CashRebateLog
 from apps.rebate.filters import TransferCashRebateFilter, TransferCashRebateDetailFilter
 from apps.rebate.serializers import OrderRebateSerializer, CashRebateSerializer, PointRebateSerializer, TransferCashRebateSerializer, TransferCashRebateDetailSerializer
 from apps.rebate.bussiness import CustomerRebateTransfer, transfer_detail_refresh, transfer_refresh
@@ -52,6 +52,25 @@ class OrderRebateViewSet(CustomModelViewSet):
         serializer = CashRebateSerializer(rows, many=True)
         return response_ok(serializer.data)
 
+    @action(methods=['get'], detail=False)
+    def cash_rebae_off(self, request):
+        id = request.GET.get('id')
+        try:
+            id = int(id)
+        except:
+            raise CustomError(u'参数异常!')
+        rebate = CashRebate.objects.filter(id=id).first()
+        if not rebate:
+            raise CustomError(u'未找到相应的返利')
+        if rebate.status != CashRebate.DEFAULT:
+            raise CustomError(u'该返利已申请转账,禁止手动核销!')
+        with transaction.atomic():
+            rebate.status = CashRebate.TRANSFERED
+            rebate.save()
+            CashRebateLog.addnew(rebate, off=True)
+            BizLog.objects.addnew(self.request.user, BizLog.INSERT, u'手动核销返利,id=%d' % rebate.id, )
+        return response_ok()
+
     @action(methods=['get'], detail=True)
     def point_rebate(self, request, pk):
         '''积分返利明细'''
@@ -97,14 +116,6 @@ class TransferCashRebateViewSet(CustomModelViewSet):
         serializer = self.get_serializer(queryset, many=True)
         return response_ok(serializer.data)
 
-    @action(methods=['post'], detail=True)
-    def apply_again(self, request, pk):
-        instance = self.get_object()
-        if instance.transfer_status != TransferCashRebate.DEFAULT:
-            return
-        # 再次申请转账 但是不需要创建转账表
-        return response_ok()
-
 
 class TransferCashRebateDetailViewSet(CustomModelViewSet):
     permission_classes = [IsEmployee, ]

+ 1 - 1
uis/views/customer/index.html

@@ -94,7 +94,7 @@
        ,{field:'total_amount', align: 'right', title:'累计消费金额',width: 120}
        ,{field:'total_point', align: 'right', title:'累计消费积分',width: 120}
        ,{field:'date_join', title:'注册时间',width: 150}
-        ,{width:150, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
+        //,{width:150, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
       ]]
       ,totalRow:true
       ,parseData:function(res) {

+ 74 - 117
uis/views/order_rebate/cash_rebate_detail.html

@@ -1,134 +1,91 @@
 <!DOCTYPE html>
 <html>
 <head>
-    <meta charset="utf-8">
-    <title>现金返利明细</title>
-    <meta name="renderer" content="webkit">
-    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
-    <meta name="viewport"
-          content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
-    <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
-    <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
-    <style type="text/css">
-        /*您可以将下列样式写入自己的样式表中*/
-        /*layui 元素样式改写*/
-        .layui-btn-sm {
-            line-height: normal;
-            font-size: 12.5px;
-        }
-
-        .layui-table-view .layui-table-body {
-            min-height: 256px;
-        }
-
-        .layui-table-cell .layui-input.layui-unselect {
-            height: 30px;
-            line-height: 30px;
-        }
-
-        /*设置 layui 表格中单元格内容溢出可见样式*/
-        .table-overlay .layui-table-view,
-        .table-overlay .layui-table-box,
-        .table-overlay .layui-table-body {
-            overflow: visible;
-        }
-
-        .table-overlay .layui-table-cell {
-            height: auto;
-            overflow: visible;
-        }
-
-        .imgStyle {
-            padding-left: 10px;
-            width: 80px;
-            height: 50px;
-        }
-
-        .layui-table-cell {
-            font-size: 14px;
-            padding: 0 5px;
-            height: auto;
-            overflow: visible;
-            text-overflow: inherit;
-            white-space: normal;
-            word-break: break-all;
-        }
-    </style>
+  <meta charset="utf-8">
+  <title>门店管理</title>
+  <meta name="renderer" content="webkit">
+  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=0">
+  <link rel="stylesheet" href="../../layuiadmin/layui/css/layui.css" media="all">
+  <link rel="stylesheet" href="../../layuiadmin/style/admin.css" media="all">
 </head>
 <body>
 
-<div class="layui-fluid">
-    <div class="layui-col-md12">
-        <div class="layui-card">
-            <div class="layui-card-body">
-                <div style="height: 5px"></div>
-                <div id="tableRes" class="table-overlay">
-                    <table id="dataTable" lay-filter="dataTable" class="layui-hide"></table>
+  <div class="layui-fluid">
+    <div class="layui-card">
+        <div class="layui-card-body" pad15>
+        <div class="layui-row layui-col-space15">
+          <div class="layui-col-md12">
+
+            <table class="layui-hide" id="datagrid-log" lay-filter="datagrid-operate"></table>
+
+            <script type="text/html" id="datagrid-operate-bar">
+                <div class="layui-btn-group">
+                    {{# if(d.status == 0){ }}
+                    <a class="layui-btn layui-btn-danger layui-btn-xs"  lay-event="detail">手动核销</a>
+                    {{# } }}
                 </div>
-            </div>
+            </script>
+          </div>
+        </div>
         </div>
     </div>
-</div>
+  </div>
 
-<script src="../../layuiadmin/layui/layui.js"></script>
-<script>
-    layui.config({
-        base: '../../../layuiadmin/' //静态资源所在路径
-    }).extend({
-        index: 'lib/index' //主入口模块
-    }).use(['index', 'table', 'layer',], function () {
-        var $ = layui.$
-            , admin = layui.admin
-            , table = layui.table
-            , layer = layui.layer;
+  <script src="../../layuiadmin/layui/layui.js?t=1"></script>
+  <script>
+  var _params = '';
+  layui.config({
+    base: '../../../layuiadmin/' //静态资源所在路径
+  }).extend({
+    index: 'lib/index' //主入口模块
+  }).use(['index', 'table'], function(){
+    var $ = layui.$
+    ,form = layui.form;
+    var table = layui.table;
+    var id = layui.view.getParameterByName('id');
 
-        var id = layui.view.getParameterByName('id');
-        var editdata = JSON.parse(JSON.stringify(parent.layui.table.editdata)); // 框架有Bug所以这么转换
-        var tbWidth = $("#tableRes").width();
-        var layTableId = "layTable";
-        var tableIns = table.render({
-            elem: '#dataTable',
-            id: layTableId,
-            data: [],
-            width: tbWidth,
-            page: false,
-            limit: 100,
-            loading: true,
-            even: true, //不开启隔行背景
-            cols: [[
-                {title: '序号', type: 'numbers'},
-                {field: 'customer_name', title: '用户名', width: '30%',},
-                {field: 'ratio', title: '返利比例', width: '20%',},
-                {field: 'amount', title: '返利', width: '20%',},
-            ]]
-        });
+    table.render({
+      elem: '#datagrid-log'
+      ,url: '/rebate/' + id + '/cash_rebate/'
+      ,where: {}
+      ,cols: [[
+        {title: '序号', type: 'numbers'},
+        {field: 'customer_name', title: '用户名', width: '200',},
+        //{field: 'batch_id', title: '微信批次号', width: '10%',},
+        {field: 'ratio', title: '返利比例', width: '100',},
+        {field: 'amount', title: '返利', width: '100',},
+        {field: 'status_text', title: '状态', width: '100',},
+        {field: 'transfer', title: '转账方式', width: '100',},
+        {width:150, align:'center', fixed: 'right', toolbar: '#datagrid-operate-bar'}
+      ]]
+      ,page: false
+      ,height: 'full-104'
+      ,done: function () {
+        layui.index.removeNoPermButtons();
+      }
+    });
 
-        admin.req({
-            url: '/rebate/' + id + '/cash_rebate/',
-            done: function (res) {
-                if (res.code === 0) {
-                    var rows = res.data;
-                    var oldData = table.cache[layTableId];
-                    for (var k in rows) {
-                        oldData.push(
-                            {
-                                customer_name: rows[k].customer_name,
-                                ratio: rows[k].ratio + '%',
-                                amount: rows[k].amount
-                            }
-                        )
+    //监听工具条
+    table.on('tool(datagrid-operate)', function(obj){
+        var data = obj.data;
+        if(obj.event === 'detail'){
+            layer.confirm('确定要核销该笔现金返利么?', function(index){
+                layer.close(index);
+                layui.admin.req({
+                    notice: true
+                    ,url: '/rebate/cash_rebae_off/?id=' + data.id
+                    ,type: 'get'
+                    ,done: function(res){
+                        table.reload('datagrid-log',{});
                     }
-                    tableIns.reload({
-                        data: oldData
-                    });
-                }else{
-                    layer.msg('获取现金返利明细失败', {icon: 5});
-                }
-            }
-        });
-
+                });
+            });
+          }
     });
 
-</script>
+  });
+  </script>
 </body>
 </html>
+

+ 2 - 2
uis/views/order_rebate/index.html

@@ -56,10 +56,10 @@
 
             <script type="text/html" id="datagrid-operate-bar">
                 <div class="layui-btn-group">
-                    {{# if(d.transfer == 0 && d.cash_rebate > 0){ }}
+                    {{# if(d.transfer == 1){ }}
                     <a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="rebate_transfer">转账申请</a>
                     {{# } }}
-                    {{# if(d.transfer > 0){ }}
+                    {{# if(d.transfer == 2){ }}
                     <a class="layui-btn layui-btn-xs layui-btn-normal" lay-event="rebate_transfer_log">转账记录</a>
                     {{# } }}
                 </div>