正在显示
27 个修改的文件
包含
713 行增加
和
43 行删除
| @@ -13,7 +13,6 @@ from .models import Auditor, Project, Result | @@ -13,7 +13,6 @@ from .models import Auditor, Project, Result | ||
| 13 | from utils.helpers import WxPushHelper | 13 | from utils.helpers import WxPushHelper |
| 14 | from utils.pagination import MyPageNumberPagination | 14 | from utils.pagination import MyPageNumberPagination |
| 15 | from utils.util import response | 15 | from utils.util import response |
| 16 | -from wxProject.settings import FRONT_URL | ||
| 17 | from wxProject.qywx_settings import Conf, project_conf | 16 | from wxProject.qywx_settings import Conf, project_conf |
| 18 | 17 | ||
| 19 | 18 | ||
| @@ -37,8 +36,8 @@ class CreateProject(CreateAPIView): | @@ -37,8 +36,8 @@ class CreateProject(CreateAPIView): | ||
| 37 | auditor_id=i.pk, | 36 | auditor_id=i.pk, |
| 38 | project_id=serializer.data['id'] | 37 | project_id=serializer.data['id'] |
| 39 | ) | 38 | ) |
| 40 | - url = re.sub("PK", str(obj_dict['id']), FRONT_URL['flow_detail']) | ||
| 41 | - url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), FRONT_URL['wx_authorize']) | 39 | + url = re.sub("PK", str(obj_dict['id']), project_conf['flow_detail']) |
| 40 | + url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), project_conf['wx_authorize']) | ||
| 42 | first_auditor = auditors[0] | 41 | first_auditor = auditors[0] |
| 43 | 42 | ||
| 44 | wx_client.push_card(first_auditor.user.wx_token, url, f"{request.user.username}提交了一个产品立项申请") | 43 | wx_client.push_card(first_auditor.user.wx_token, url, f"{request.user.username}提交了一个产品立项申请") |
| @@ -101,8 +100,8 @@ class AuditProject(UpdateAPIView): | @@ -101,8 +100,8 @@ class AuditProject(UpdateAPIView): | ||
| 101 | 100 | ||
| 102 | wx_client = WxPushHelper(Conf[project_conf['APP_ID']]) | 101 | wx_client = WxPushHelper(Conf[project_conf['APP_ID']]) |
| 103 | full_audit_done = self._check_audit(obj) | 102 | full_audit_done = self._check_audit(obj) |
| 104 | - url = re.sub("PK", str(obj.id), FRONT_URL['flow_detail']) | ||
| 105 | - url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), FRONT_URL['wx_authorize']) | 103 | + url = re.sub("PK", str(obj.id), project_conf['flow_detail']) |
| 104 | + url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), project_conf['wx_authorize']) | ||
| 106 | desc = "产品立项流程所有审批已完成" if full_audit_done else f"{request.user.username}已审批完成" | 105 | desc = "产品立项流程所有审批已完成" if full_audit_done else f"{request.user.username}已审批完成" |
| 107 | if full_audit_done: | 106 | if full_audit_done: |
| 108 | obj.is_done = True | 107 | obj.is_done = True |
不能预览此文件类型
sku/__pycache__/serializers.cpython-38.pyc
0 → 100644
不能预览此文件类型
sku/__pycache__/urls.cpython-38.pyc
0 → 100644
不能预览此文件类型
sku/__pycache__/views.cpython-38.pyc
0 → 100644
不能预览此文件类型
sku/migrations/0001_initial.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-03 08:15 | ||
| 2 | + | ||
| 3 | +from django.conf import settings | ||
| 4 | +from django.db import migrations, models | ||
| 5 | +import django.db.models.deletion | ||
| 6 | + | ||
| 7 | + | ||
| 8 | +class Migration(migrations.Migration): | ||
| 9 | + | ||
| 10 | + initial = True | ||
| 11 | + | ||
| 12 | + dependencies = [ | ||
| 13 | + migrations.swappable_dependency(settings.AUTH_USER_MODEL), | ||
| 14 | + ] | ||
| 15 | + | ||
| 16 | + operations = [ | ||
| 17 | + migrations.CreateModel( | ||
| 18 | + name='Auditor', | ||
| 19 | + fields=[ | ||
| 20 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 21 | + ('order', models.PositiveSmallIntegerField(blank=True, default=0, null=True, verbose_name='排序')), | ||
| 22 | + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sku_aud', to=settings.AUTH_USER_MODEL, verbose_name='审批人员')), | ||
| 23 | + ], | ||
| 24 | + options={ | ||
| 25 | + 'ordering': ('order',), | ||
| 26 | + }, | ||
| 27 | + ), | ||
| 28 | + migrations.CreateModel( | ||
| 29 | + name='Flow', | ||
| 30 | + fields=[ | ||
| 31 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 32 | + ('is_done', models.BooleanField(default=False, verbose_name='是否已结束')), | ||
| 33 | + ('create_time', models.DateTimeField(auto_now_add=True)), | ||
| 34 | + ('auditor', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to='sku.auditor', verbose_name='审核人员')), | ||
| 35 | + ('starter', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL, verbose_name='发起人')), | ||
| 36 | + ], | ||
| 37 | + ), | ||
| 38 | + migrations.CreateModel( | ||
| 39 | + name='SKU', | ||
| 40 | + fields=[ | ||
| 41 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 42 | + ('supplier', models.CharField(default='', max_length=100, verbose_name='供应商')), | ||
| 43 | + ('sku', models.CharField(default='', max_length=100, verbose_name='SKU')), | ||
| 44 | + ('model', models.CharField(default='', max_length=100, verbose_name='型号')), | ||
| 45 | + ('title', models.CharField(default='', max_length=100, verbose_name='SKU名称')), | ||
| 46 | + ('is_new', models.CharField(default='', max_length=100, verbose_name='是否新品')), | ||
| 47 | + ('qty', models.CharField(default='', max_length=100, verbose_name='需求单数量')), | ||
| 48 | + ('price_with_tax', models.DecimalField(decimal_places=4, default=0, max_digits=9, verbose_name='含税单价')), | ||
| 49 | + ('amount_with_tax', models.DecimalField(decimal_places=4, default=0, max_digits=9, verbose_name='含税总金额')), | ||
| 50 | + ('sell_day', models.PositiveIntegerField(default=0, null=True, verbose_name='可售天数')), | ||
| 51 | + ('qty_within_30', models.PositiveIntegerField(default=0, null=True, verbose_name='30天销量')), | ||
| 52 | + ('inventory', models.PositiveIntegerField(default=0, null=True, verbose_name='库存')), | ||
| 53 | + ('coming_inventory', models.PositiveIntegerField(default=0, null=True, verbose_name='采购在途')), | ||
| 54 | + ('gross_profit_rate', models.FloatField(default=0, null=True, verbose_name='毛利率')), | ||
| 55 | + ('return_rate', models.FloatField(default=0, null=True, verbose_name='客退率')), | ||
| 56 | + ('memo', models.CharField(default='', max_length=255, null=True, verbose_name='备注')), | ||
| 57 | + ('create_time', models.DateTimeField(auto_now_add=True)), | ||
| 58 | + ('purchaser', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='purchase_user', to=settings.AUTH_USER_MODEL, verbose_name='采购')), | ||
| 59 | + ], | ||
| 60 | + ), | ||
| 61 | + migrations.CreateModel( | ||
| 62 | + name='Result', | ||
| 63 | + fields=[ | ||
| 64 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 65 | + ('is_accept', models.CharField(choices=[('accept', '通过'), ('reject', '否决')], max_length=10, null=True, verbose_name='审核项目')), | ||
| 66 | + ('memo', models.CharField(blank=True, default='', max_length=300, verbose_name='审核结果陈述')), | ||
| 67 | + ('create_time', models.DateTimeField(auto_now_add=True)), | ||
| 68 | + ('auditor', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='result_auditor', to='sku.auditor', verbose_name='审核人员')), | ||
| 69 | + ('flow', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='result_flow', to='sku.flow', verbose_name='审核项目')), | ||
| 70 | + ], | ||
| 71 | + options={ | ||
| 72 | + 'ordering': ('pk',), | ||
| 73 | + }, | ||
| 74 | + ), | ||
| 75 | + migrations.CreateModel( | ||
| 76 | + name='Leader', | ||
| 77 | + fields=[ | ||
| 78 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 79 | + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sku_leader', to=settings.AUTH_USER_MODEL, verbose_name='采购负责人')), | ||
| 80 | + ], | ||
| 81 | + ), | ||
| 82 | + migrations.CreateModel( | ||
| 83 | + name='FlowSKU', | ||
| 84 | + fields=[ | ||
| 85 | + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), | ||
| 86 | + ('is_pass', models.BooleanField(default=False, verbose_name='是否通过,默认为否')), | ||
| 87 | + ('flow', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sku.flow', verbose_name='对应的流程')), | ||
| 88 | + ('sku', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='sku.sku', verbose_name='流程中的的SKU')), | ||
| 89 | + ], | ||
| 90 | + ), | ||
| 91 | + ] |
sku/migrations/0002_auto_20201103_1751.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-03 09:51 | ||
| 2 | + | ||
| 3 | +from django.db import migrations, models | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class Migration(migrations.Migration): | ||
| 7 | + | ||
| 8 | + dependencies = [ | ||
| 9 | + ('sku', '0001_initial'), | ||
| 10 | + ] | ||
| 11 | + | ||
| 12 | + operations = [ | ||
| 13 | + migrations.AlterField( | ||
| 14 | + model_name='sku', | ||
| 15 | + name='is_new', | ||
| 16 | + field=models.CharField(choices=[('是', '新品'), ('否', '非新品')], max_length=10, verbose_name='是否新品'), | ||
| 17 | + ), | ||
| 18 | + migrations.AlterField( | ||
| 19 | + model_name='sku', | ||
| 20 | + name='purchaser', | ||
| 21 | + field=models.CharField(max_length=255, verbose_name='采购名字'), | ||
| 22 | + ), | ||
| 23 | + migrations.AlterField( | ||
| 24 | + model_name='sku', | ||
| 25 | + name='supplier', | ||
| 26 | + field=models.CharField(default='', max_length=255, verbose_name='供应商'), | ||
| 27 | + ), | ||
| 28 | + ] |
sku/migrations/0003_auto_20201103_1818.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-03 10:18 | ||
| 2 | + | ||
| 3 | +from django.db import migrations, models | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class Migration(migrations.Migration): | ||
| 7 | + | ||
| 8 | + dependencies = [ | ||
| 9 | + ('sku', '0002_auto_20201103_1751'), | ||
| 10 | + ] | ||
| 11 | + | ||
| 12 | + operations = [ | ||
| 13 | + migrations.AlterField( | ||
| 14 | + model_name='sku', | ||
| 15 | + name='amount_with_tax', | ||
| 16 | + field=models.DecimalField(decimal_places=4, default=0, max_digits=12, verbose_name='含税总金额'), | ||
| 17 | + ), | ||
| 18 | + migrations.AlterField( | ||
| 19 | + model_name='sku', | ||
| 20 | + name='price_with_tax', | ||
| 21 | + field=models.DecimalField(decimal_places=4, default=0, max_digits=12, verbose_name='含税单价'), | ||
| 22 | + ), | ||
| 23 | + ] |
sku/migrations/0004_remove_flow_auditor.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-03 10:57 | ||
| 2 | + | ||
| 3 | +from django.db import migrations | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class Migration(migrations.Migration): | ||
| 7 | + | ||
| 8 | + dependencies = [ | ||
| 9 | + ('sku', '0003_auto_20201103_1818'), | ||
| 10 | + ] | ||
| 11 | + | ||
| 12 | + operations = [ | ||
| 13 | + migrations.RemoveField( | ||
| 14 | + model_name='flow', | ||
| 15 | + name='auditor', | ||
| 16 | + ), | ||
| 17 | + ] |
sku/migrations/0005_auto_20201105_1710.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-05 09:10 | ||
| 2 | + | ||
| 3 | +from django.db import migrations, models | ||
| 4 | +import django.db.models.deletion | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +class Migration(migrations.Migration): | ||
| 8 | + | ||
| 9 | + dependencies = [ | ||
| 10 | + ('sku', '0004_remove_flow_auditor'), | ||
| 11 | + ] | ||
| 12 | + | ||
| 13 | + operations = [ | ||
| 14 | + migrations.AlterField( | ||
| 15 | + model_name='flowsku', | ||
| 16 | + name='flow', | ||
| 17 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='sku_flow', to='sku.flow', verbose_name='对应的流程'), | ||
| 18 | + ), | ||
| 19 | + migrations.AlterField( | ||
| 20 | + model_name='flowsku', | ||
| 21 | + name='sku', | ||
| 22 | + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='flow_sku', to='sku.sku', verbose_name='流程中的的SKU'), | ||
| 23 | + ), | ||
| 24 | + migrations.AlterField( | ||
| 25 | + model_name='sku', | ||
| 26 | + name='memo', | ||
| 27 | + field=models.CharField(blank=True, default='', max_length=255, null=True, verbose_name='备注'), | ||
| 28 | + ), | ||
| 29 | + ] |
sku/migrations/0006_auto_20201105_1739.py
0 → 100644
| 1 | +# Generated by Django 3.1.1 on 2020-11-05 09:39 | ||
| 2 | + | ||
| 3 | +from django.db import migrations, models | ||
| 4 | + | ||
| 5 | + | ||
| 6 | +class Migration(migrations.Migration): | ||
| 7 | + | ||
| 8 | + dependencies = [ | ||
| 9 | + ('sku', '0005_auto_20201105_1710'), | ||
| 10 | + ] | ||
| 11 | + | ||
| 12 | + operations = [ | ||
| 13 | + migrations.AlterField( | ||
| 14 | + model_name='flowsku', | ||
| 15 | + name='is_pass', | ||
| 16 | + field=models.BooleanField(null=True, verbose_name='是否通过,默认为否'), | ||
| 17 | + ), | ||
| 18 | + ] |
不能预览此文件类型
不能预览此文件类型
不能预览此文件类型
不能预览此文件类型
不能预览此文件类型
不能预览此文件类型
| 1 | from django.db import models | 1 | from django.db import models |
| 2 | 2 | ||
| 3 | -# Create your models here. | 3 | + |
| 4 | +from usercenter.models import User | ||
| 5 | + | ||
| 6 | + | ||
| 7 | +class Auditor(models.Model): | ||
| 8 | + user = models.ForeignKey( | ||
| 9 | + User, | ||
| 10 | + on_delete=models.CASCADE, | ||
| 11 | + related_name="sku_aud", | ||
| 12 | + verbose_name="审批人员") | ||
| 13 | + order = models.PositiveSmallIntegerField(default=0, null=True, blank=True, verbose_name="排序") | ||
| 14 | + | ||
| 15 | + def __str__(self): | ||
| 16 | + return self.user.username | ||
| 17 | + | ||
| 18 | + class Meta: | ||
| 19 | + ordering = ('order', ) | ||
| 20 | + | ||
| 21 | + | ||
| 22 | +class SKU(models.Model): | ||
| 23 | + NEW_CHOICES = ( | ||
| 24 | + ("是", "新品"), | ||
| 25 | + ("否", "非新品") | ||
| 26 | + ) | ||
| 27 | + supplier = models.CharField(max_length=255, default="", verbose_name="供应商") | ||
| 28 | + sku = models.CharField(max_length=100, default="", verbose_name="SKU") | ||
| 29 | + model = models.CharField(max_length=100, default="", verbose_name="型号") | ||
| 30 | + title = models.CharField(max_length=100, default="", verbose_name="SKU名称") | ||
| 31 | + is_new = models.CharField(max_length=10, choices=NEW_CHOICES, verbose_name="是否新品") | ||
| 32 | + qty = models.CharField(max_length=100, default="", verbose_name="需求单数量") | ||
| 33 | + price_with_tax = models.DecimalField(max_digits=12, decimal_places=4, default=0, verbose_name="含税单价") | ||
| 34 | + amount_with_tax = models.DecimalField(max_digits=12, decimal_places=4, default=0, verbose_name="含税总金额") | ||
| 35 | + sell_day = models.PositiveIntegerField(default=0, null=True, verbose_name="可售天数") | ||
| 36 | + qty_within_30 = models.PositiveIntegerField(default=0, null=True, verbose_name="30天销量") | ||
| 37 | + inventory = models.PositiveIntegerField(default=0, null=True, verbose_name="库存") | ||
| 38 | + coming_inventory = models.PositiveIntegerField(default=0, null=True, verbose_name="采购在途") | ||
| 39 | + gross_profit_rate = models.FloatField(default=0, null=True, verbose_name="毛利率") | ||
| 40 | + return_rate = models.FloatField(default=0, null=True, verbose_name="客退率") | ||
| 41 | + memo = models.CharField(default="", max_length=255, null=True, verbose_name="备注", blank=True) | ||
| 42 | + create_time = models.DateTimeField(auto_now_add=True) | ||
| 43 | + purchaser = models.CharField(max_length=255, verbose_name="采购名字") | ||
| 44 | + | ||
| 45 | + | ||
| 46 | +class Flow(models.Model): | ||
| 47 | + """ 提交发起的流程""" | ||
| 48 | + starter = models.ForeignKey(User, on_delete=models.DO_NOTHING, verbose_name="发起人") | ||
| 49 | + is_done = models.BooleanField(default=False, verbose_name="是否已结束") | ||
| 50 | + create_time = models.DateTimeField(auto_now_add=True) | ||
| 51 | + | ||
| 52 | + | ||
| 53 | +class FlowSKU(models.Model): | ||
| 54 | + """ 流程中的SKU """ | ||
| 55 | + sku = models.ForeignKey(SKU, on_delete=models.CASCADE, verbose_name="流程中的的SKU", related_name="flow_sku") | ||
| 56 | + flow = models.ForeignKey(Flow, on_delete=models.CASCADE, verbose_name="对应的流程", related_name="sku_flow") | ||
| 57 | + is_pass = models.BooleanField(null=True, verbose_name="是否通过,默认为否") | ||
| 58 | + | ||
| 59 | + | ||
| 60 | +class Result(models.Model): | ||
| 61 | + ACCEPT_CHOICES = ( | ||
| 62 | + ('accept', '通过'), | ||
| 63 | + ('reject', '否决') | ||
| 64 | + ) | ||
| 65 | + | ||
| 66 | + auditor = models.ForeignKey(Auditor, on_delete=models.CASCADE, related_name="result_auditor", verbose_name="审核人员") | ||
| 67 | + flow = models.ForeignKey(Flow, on_delete=models.CASCADE, related_name="result_flow", verbose_name="审核项目") | ||
| 68 | + is_accept = models.CharField(max_length=10, null=True, choices=ACCEPT_CHOICES, verbose_name="审核项目") | ||
| 69 | + memo = models.CharField(max_length=300, blank=True, default="", verbose_name="审核结果陈述") | ||
| 70 | + create_time = models.DateTimeField(auto_now_add=True) | ||
| 71 | + | ||
| 72 | + class Meta: | ||
| 73 | + ordering = ('pk', ) | ||
| 74 | + | ||
| 75 | + | ||
| 76 | +class Leader(models.Model): | ||
| 77 | + """ 采购负责人""" | ||
| 78 | + user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="sku_leader", verbose_name="采购负责人") | ||
| 79 | + | ||
| 80 | + |
sku/serializers.py
0 → 100644
| 1 | +# _*_ coding: utf-8 _*_ | ||
| 2 | +# @Time : 2020/11/3 16:34 | ||
| 3 | +# @Author vanwhebin | ||
| 4 | + | ||
| 5 | +from rest_framework import serializers | ||
| 6 | + | ||
| 7 | +from .models import Auditor, Flow, Result, SKU, FlowSKU | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +class AuditorSerializer(serializers.ModelSerializer): | ||
| 11 | + | ||
| 12 | + class Meta: | ||
| 13 | + model = Auditor | ||
| 14 | + fields = '__all__' | ||
| 15 | + depth = 1 | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +class SKUSerializer(serializers.ModelSerializer): | ||
| 19 | + # pk = serializers.ReadOnlyField() | ||
| 20 | + # is_new = serializers.ReadOnlyField() | ||
| 21 | + # purchaser = serializers.ReadOnlyField() | ||
| 22 | + | ||
| 23 | + class Meta: | ||
| 24 | + model = SKU | ||
| 25 | + # fields = ("supplier", "sku", "model", "title", "is_new", "qty", "price_with_tax", "amount_with_tax", "sell_day", | ||
| 26 | + # "qty_within_30", "inventory", "coming_inventory", "gross_profit_rate", "return_rate", "memo", | ||
| 27 | + # "purchaser") | ||
| 28 | + fields = "__all__" | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +class FlowSerializer(serializers.ModelSerializer): | ||
| 32 | + result = serializers.ReadOnlyField() | ||
| 33 | + creator_name = serializers.ReadOnlyField() | ||
| 34 | + skus = serializers.ReadOnlyField() | ||
| 35 | + | ||
| 36 | + class Meta: | ||
| 37 | + model = Flow | ||
| 38 | + fields = ("result", "creator_name", "skus", "is_done", "create_time") | ||
| 39 | + | ||
| 40 | + | ||
| 41 | +class FlowListSerializer(serializers.ModelSerializer): | ||
| 42 | + result = serializers.BooleanField() | ||
| 43 | + creator_name = serializers.CharField() | ||
| 44 | + flow_id = serializers.IntegerField() | ||
| 45 | + | ||
| 46 | + class Meta: | ||
| 47 | + model = Result | ||
| 48 | + fields = ("creator_name", "result", "flow_id", "create_time") | ||
| 49 | + | ||
| 50 | + | ||
| 51 | +class ResultSerializer(serializers.ModelSerializer): | ||
| 52 | + | ||
| 53 | + class Meta: | ||
| 54 | + model = Result | ||
| 55 | + fields = "__all__" | ||
| 56 | + | ||
| 57 | + | ||
| 58 | +class FlowSKUSerializer(serializers.ModelSerializer): | ||
| 59 | + | ||
| 60 | + class Meta: | ||
| 61 | + model = FlowSKU | ||
| 62 | + fields = "__all__" | ||
| 63 | + depth = 1 | ||
| 64 | + |
| @@ -2,10 +2,17 @@ | @@ -2,10 +2,17 @@ | ||
| 2 | # @Time : 2020/11/2 18:41 | 2 | # @Time : 2020/11/2 18:41 |
| 3 | # @Author vanwhebin | 3 | # @Author vanwhebin |
| 4 | 4 | ||
| 5 | -from django.urls import path, include | 5 | +from django.urls import path |
| 6 | +from sku import views | ||
| 6 | 7 | ||
| 7 | app_name = "sku" | 8 | app_name = "sku" |
| 8 | 9 | ||
| 9 | urlpatterns = [ | 10 | urlpatterns = [ |
| 10 | - | 11 | + path('create', views.CreateSKUFlow.as_view(), name="create_sku_flow"), |
| 12 | + path('audit/<int:pk>', views.AuditFlow.as_view(), name="audit_flow"), | ||
| 13 | + path('right/<int:pk>', views.CheckAuth.as_view(), name="check_audit_auth"), | ||
| 14 | + path('list', views.AuditFlowList.as_view(), name="list_flow"), | ||
| 15 | + path('<int:pk>', views.FlowDetail.as_view(), name="retrieve_flow"), | ||
| 16 | + path('info/<int:pk>', views.UpdateSKUInfo.as_view(), name="update_sku"), | ||
| 17 | + path('template', views.ParseSKUExcel.as_view(), name="upload_sku_template"), | ||
| 11 | ] | 18 | ] |
| 1 | -from django.shortcuts import render | 1 | +import os |
| 2 | +import re | ||
| 3 | +from urllib import parse | ||
| 2 | 4 | ||
| 3 | -# Create your views here. | 5 | +from rest_framework.generics import CreateAPIView, RetrieveAPIView, UpdateAPIView, ListAPIView |
| 6 | +from rest_framework.views import APIView | ||
| 7 | +from rest_framework.permissions import IsAuthenticated, IsAdminUser | ||
| 8 | +from rest_framework import status | ||
| 9 | +import pyexcel as p | ||
| 10 | +from django.db import transaction | ||
| 11 | +from django.forms import model_to_dict | ||
| 12 | +from django.db.models import Q | ||
| 13 | + | ||
| 14 | +from .models import SKU, Auditor, Flow, FlowSKU, Result, Leader | ||
| 15 | +from wxProject.settings import MEDIA_ROOT | ||
| 16 | +from utils.pagination import MyPageNumberPagination | ||
| 17 | +from wxProject.qywx_settings import Conf, sku_conf | ||
| 18 | +from utils.util import response | ||
| 19 | +from utils.media import upload_media | ||
| 20 | +from .serializers import FlowSerializer, SKUSerializer, FlowListSerializer, FlowSKUSerializer | ||
| 21 | +from utils.helpers import WxPushHelper | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +class CreateSKUFlow(CreateAPIView): | ||
| 25 | + """ 创建SKU审核流程 """ | ||
| 26 | + serializer_class = FlowSerializer | ||
| 27 | + permission_classes = (IsAuthenticated,) | ||
| 28 | + | ||
| 29 | + # @transaction.atomic | ||
| 30 | + def post(self, request, *args, **kwargs): | ||
| 31 | + super(CreateSKUFlow, self).__init__() | ||
| 32 | + skus = request.data.get('sku', None) | ||
| 33 | + if not skus or skus == []: | ||
| 34 | + return response(msg=u"sku不能为空", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 35 | + # 提交过来sku的ID | ||
| 36 | + # flow 表 flow_sku表 result表 | ||
| 37 | + wx_client = WxPushHelper(Conf[sku_conf['APP_ID']]) | ||
| 38 | + with transaction.atomic(): | ||
| 39 | + save_id = transaction.savepoint() | ||
| 40 | + | ||
| 41 | + try: | ||
| 42 | + skus = list(set(skus)) | ||
| 43 | + sku_objs = SKU.objects.filter(pk__in=skus) | ||
| 44 | + flow = Flow.objects.create(starter=request.user) | ||
| 45 | + flow_sku_list = [FlowSKU(sku=sku, flow=flow) for sku in sku_objs] | ||
| 46 | + FlowSKU.objects.bulk_create(flow_sku_list) | ||
| 47 | + auditors = Auditor.objects.all().order_by('order') | ||
| 48 | + auditor_list = [Result(auditor=auditor, flow=flow) for auditor in auditors] | ||
| 49 | + Result.objects.bulk_create(auditor_list) | ||
| 50 | + | ||
| 51 | + transaction.savepoint_commit(save_id) | ||
| 52 | + | ||
| 53 | + url = re.sub("PK", str(flow.id), sku_conf['flow_detail']) | ||
| 54 | + url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), sku_conf['wx_authorize']) | ||
| 55 | + first_auditor = auditors[0] | ||
| 56 | + | ||
| 57 | + wx_client.push_card(first_auditor.user.wx_token, url, f"{request.user.username}发起一个毛利不达标产品审批流程") | ||
| 58 | + wx_client.push_card(request.user.wx_token, url, u"流程创建成功") | ||
| 59 | + # 通知创建人和审批人 | ||
| 60 | + return response() | ||
| 61 | + except Exception as e: | ||
| 62 | + print(e.args) | ||
| 63 | + print(e.with_traceback) | ||
| 64 | + transaction.savepoint_rollback(save_id) | ||
| 65 | + return response(msg=u"创建流程有误", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 66 | + | ||
| 67 | + | ||
| 68 | +class UpdateSKUInfo(UpdateAPIView): | ||
| 69 | + queryset = SKU.objects.all() | ||
| 70 | + serializer_class = SKUSerializer | ||
| 71 | + permission_classes = (IsAuthenticated,) | ||
| 72 | + | ||
| 73 | + def put(self, request, *args, **kwargs): | ||
| 74 | + """ 更新 单个sku的信息 """ | ||
| 75 | + serializer = SKUSerializer(data=request.data) | ||
| 76 | + # 查找对应用户是否拥有该sku的修改权 | ||
| 77 | + flow_id = request.data.get('flowID', None) | ||
| 78 | + if not flow_id: | ||
| 79 | + return response(msg=u"非法参数", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 80 | + flow_sku = FlowSKU.objects.filter(flow_id=flow_id, sku_id=kwargs['pk']).first() | ||
| 81 | + if not flow_sku or flow_sku.flow.starter.id != request.user.id: | ||
| 82 | + return response(msg=u"非法参数", status_code=status.HTTP_401_UNAUTHORIZED) | ||
| 83 | + | ||
| 84 | + if not serializer.is_valid(): | ||
| 85 | + raise ValueError(serializer.errors) | ||
| 86 | + else: | ||
| 87 | + serializer.update(instance=self.get_object(), validated_data=serializer.data) | ||
| 88 | + return response() | ||
| 89 | + | ||
| 90 | + | ||
| 91 | +class FlowDetail(RetrieveAPIView): | ||
| 92 | + """ 查看当前流程 """ | ||
| 93 | + # 查看当前流程的sku列表 流程进度 流程结果 | ||
| 94 | + queryset = Flow.objects.all() | ||
| 95 | + serializer_class = FlowSerializer | ||
| 96 | + permission_classes = (IsAuthenticated,) | ||
| 97 | + | ||
| 98 | + def get(self, request, *args, **kwargs): | ||
| 99 | + cur_obj = self.get_object() | ||
| 100 | + cur_obj.result = [] | ||
| 101 | + results = Result.objects.filter(flow=cur_obj) | ||
| 102 | + for i in results: | ||
| 103 | + cur_obj.result.append({ | ||
| 104 | + "auditor": i.auditor.user.username, | ||
| 105 | + "is_accept": i.is_accept, | ||
| 106 | + "memo": i.memo, | ||
| 107 | + }) | ||
| 108 | + # skus = (SKU.objects.filter(pk__in=FlowSKU.objects.filter(flow=cur_obj).values_list('sku_id', flat=True))) | ||
| 109 | + # cur_obj.skus = [model_to_dict(sku) for sku in skus] | ||
| 110 | + flow_skus = FlowSKU.objects.filter(flow=cur_obj) | ||
| 111 | + cur_obj.skus = [FlowSKUSerializer(sku).data for sku in flow_skus] | ||
| 112 | + | ||
| 113 | + return response(FlowSerializer(cur_obj).data) | ||
| 114 | + | ||
| 115 | + | ||
| 116 | +class AuditFlow(UpdateAPIView): | ||
| 117 | + """ 更新当前流程状态,对流程进行审批""" | ||
| 118 | + queryset = Flow.objects.all() | ||
| 119 | + serializer_class = FlowSerializer | ||
| 120 | + permission_classes = (IsAuthenticated, IsAdminUser) | ||
| 121 | + | ||
| 122 | + @staticmethod | ||
| 123 | + def _check_audit(flow_obj): | ||
| 124 | + # 查看是否已经全部审核完毕 进行更新flow表,只有所有sku都审批通过才能流向下一节点 | ||
| 125 | + # 所有的审核人员, 是否有result记录 | ||
| 126 | + aud_result_len = Result.objects.filter(flow=flow_obj, is_accept__isnull=False).count() | ||
| 127 | + auditor_len = Auditor.objects.count() | ||
| 128 | + return aud_result_len == auditor_len | ||
| 129 | + | ||
| 130 | + @transaction.atomic | ||
| 131 | + def partial_update(self, request, *args, **kwargs): | ||
| 132 | + # 对项目进行更新 | ||
| 133 | + | ||
| 134 | + accept_choices = ( | ||
| 135 | + ('accept', '通过'), | ||
| 136 | + ('reject', '否决') | ||
| 137 | + ) | ||
| 138 | + # accept_param = accept_choices[0][0] if request.data.get('is_accept') else accept_choices[1][0] | ||
| 139 | + skus = request.data.get('sku', []) | ||
| 140 | + if len(skus) == 0 or not isinstance(request.data.get('is_accept'), bool): | ||
| 141 | + return response(msg=u"非法审批参数", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 142 | + | ||
| 143 | + result_obj = Result.objects.filter(auditor_id=self.request.user.id, is_accept__isnull=True, | ||
| 144 | + flow__pk=kwargs['pk']).first() | ||
| 145 | + obj = self.get_object() | ||
| 146 | + if not obj or not result_obj: | ||
| 147 | + raise PermissionError | ||
| 148 | + else: | ||
| 149 | + # 只有当前flow的所有的sku审批通过,采流下一节点审批 | ||
| 150 | + flow_skus = FlowSKU.objects.filter(flow=obj) | ||
| 151 | + accept_bool = bool(request.data.get('is_accept')) | ||
| 152 | + if len(flow_skus) == len(request.data.get('sku')): | ||
| 153 | + accept_param = accept_choices[0][0] | ||
| 154 | + else: | ||
| 155 | + obj.is_done = True | ||
| 156 | + accept_param = accept_choices[1][0] | ||
| 157 | + result_obj.is_accept = accept_param | ||
| 158 | + result_obj.memo = request.data.get('memo', '') | ||
| 159 | + result_obj.save() | ||
| 160 | + for flow_sku in flow_skus: | ||
| 161 | + if flow_sku.sku.id in skus: | ||
| 162 | + flow_sku.is_pass = accept_bool | ||
| 163 | + else: | ||
| 164 | + flow_sku.is_pass = not accept_bool | ||
| 165 | + flow_sku.save() | ||
| 166 | + | ||
| 167 | + wx_client = WxPushHelper(Conf[sku_conf['APP_ID']]) | ||
| 168 | + full_audit_done = self._check_audit(obj) | ||
| 169 | + url = re.sub("PK", str(obj.id), sku_conf['flow_detail']) | ||
| 170 | + url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), sku_conf['wx_authorize']) | ||
| 171 | + desc = "返单特采流程所有审批已完成" if full_audit_done else f"{request.user.username}已审批完成" | ||
| 172 | + if full_audit_done: | ||
| 173 | + obj.is_done = True | ||
| 174 | + else: | ||
| 175 | + if not bool(request.data.get('is_accept')): | ||
| 176 | + obj.is_done = True | ||
| 177 | + else: | ||
| 178 | + next_auditor_id = Result.objects.filter(flow=obj, is_accept__isnull=True) \ | ||
| 179 | + .values_list('auditor_id', flat=True).order_by('pk').first() | ||
| 180 | + second_auditor = Auditor.objects.filter(pk=next_auditor_id).first() | ||
| 181 | + wx_client.push_card(second_auditor.user.wx_token, url, f"{request.user.username}已审核了一个返单特采申请") | ||
| 182 | + obj.save() | ||
| 183 | + wx_client.push_card(obj.starter.wx_token, url, desc) | ||
| 184 | + | ||
| 185 | + return response(FlowSerializer(obj).data) | ||
| 186 | + | ||
| 187 | + | ||
| 188 | +class AuditFlowList(ListAPIView): | ||
| 189 | + """ 查看当前审核人员名下的审核清单 """ | ||
| 190 | + queryset = Result.objects.all() | ||
| 191 | + serializer_class = FlowListSerializer | ||
| 192 | + pagination_class = MyPageNumberPagination | ||
| 193 | + permission_classes = (IsAuthenticated,) | ||
| 194 | + | ||
| 195 | + def get_queryset(self): | ||
| 196 | + data = Result.objects.filter(auditor_id=self.request.user.id).order_by('is_accept', '-create_time') | ||
| 197 | + for item in data: | ||
| 198 | + # result = Flow.objects.filter(=self.request.user).values_list('is_done', flat=True).first() | ||
| 199 | + item.creator_name = item.flow.starter.username | ||
| 200 | + item.result = True if item.is_accept else False | ||
| 201 | + item.flow_id = item.flow.id | ||
| 202 | + return data | ||
| 203 | + | ||
| 204 | + | ||
| 205 | +class CheckAuth(APIView): | ||
| 206 | + """ 查看当前查看用户是否有审批权限""" | ||
| 207 | + allowed_methods = ('GET',) | ||
| 208 | + permission_classes = (IsAuthenticated,) | ||
| 209 | + | ||
| 210 | + @staticmethod | ||
| 211 | + def get(request, *args, **kwargs): | ||
| 212 | + flow_result = Result.objects.filter(flow__pk=kwargs['pk']) | ||
| 213 | + # auditor=request.user) | Q(flow__starter=request.user) | ||
| 214 | + if not flow_result \ | ||
| 215 | + or flow_result.result_auditor.user.id != request.user.id: | ||
| 216 | + return response(False) | ||
| 217 | + else: | ||
| 218 | + order = int(Auditor.objects.filter(user=request.user).values_list('order', flat=True).first()) | ||
| 219 | + if order > 0: | ||
| 220 | + # 当审核人员排队时 需要判断是否已经流转到自己 前一个人员是否已经有处理 | ||
| 221 | + # 还要判断自己是否已经审核过了 | ||
| 222 | + index = order - 1 | ||
| 223 | + if bool(flow_result[index].is_accept) and not bool(flow_result[order].is_accept): | ||
| 224 | + return response(True) | ||
| 225 | + else: | ||
| 226 | + return response(False) | ||
| 227 | + else: | ||
| 228 | + return response(False) if bool(flow_result[0].is_accept) else response(True) | ||
| 229 | + | ||
| 230 | + | ||
| 231 | +class ParseSKUExcel(CreateAPIView): | ||
| 232 | + """ 解析上传excel的SKU数据""" | ||
| 233 | + serializer_class = SKUSerializer | ||
| 234 | + permission_classes = (IsAuthenticated,) | ||
| 235 | + allowed_extension = (".xls", ".xlsx") | ||
| 236 | + | ||
| 237 | + def post(self, request, *args, **kwargs): | ||
| 238 | + super(ParseSKUExcel, self).__init__() | ||
| 239 | + file_obj = self._upload(request) | ||
| 240 | + # 解析sku列表 插入数据库 | ||
| 241 | + path = os.path.join(MEDIA_ROOT, str(file_obj.file)) | ||
| 242 | + t = p.get_sheet(file_name=path, start_row=1, column_limit=16) | ||
| 243 | + with transaction.atomic(): | ||
| 244 | + save_id = transaction.savepoint() | ||
| 245 | + try: | ||
| 246 | + s_list = self._insert_data(list(t.rows())) | ||
| 247 | + transaction.savepoint_commit(save_id) | ||
| 248 | + return response(s_list) | ||
| 249 | + except ValueError as e: | ||
| 250 | + transaction.savepoint_rollback(save_id) | ||
| 251 | + return response(msg=u"文件上传数据有误", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 252 | + except IndexError as e: | ||
| 253 | + transaction.savepoint_rollback(save_id) | ||
| 254 | + return response(msg=u"文件上传数据有误", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 255 | + except Exception as e: | ||
| 256 | + transaction.savepoint_rollback(save_id) | ||
| 257 | + return response(msg=u"文件上传数据有误", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 258 | + | ||
| 259 | + @staticmethod | ||
| 260 | + def _insert_data(rows): | ||
| 261 | + obj_list = [] | ||
| 262 | + for row in rows: | ||
| 263 | + if len(row) < 16: | ||
| 264 | + raise IndexError("上传数据字段不完整") | ||
| 265 | + qty = 0 if row[5] == "" or row[5] == "#N/A" else int(row[5]) | ||
| 266 | + price_with_tax = 0 if row[6] == "" or row[6] == "#N/A" else float(row[6]) | ||
| 267 | + amount_with_tax = 0 if row[7] == "" or row[7] == "#N/A" else float(row[7]) | ||
| 268 | + sell_day = 0 if row[8] == "" or row[8] == "#N/A" else int(row[8]) | ||
| 269 | + qty_within_30 = 0 if row[9] == "" or row[9] == "#N/A" else int(row[9]) | ||
| 270 | + inventory = 0 if row[10] == "" or row[10] == "#N/A" else int(row[10]) | ||
| 271 | + coming_inventory = 0 if row[11] == "" or row[11] == "#N/A" else int(row[11]) | ||
| 272 | + gross_profit_rate = 0 if row[12] == "" or row[12] == "#N/A" else float(row[12]) | ||
| 273 | + return_rate = 0 if row[13] == "" or row[13] == "#N/A" else float(row[13]) | ||
| 274 | + memo = "" if row[14] == "#N/A" else row[14].strip() | ||
| 275 | + purchaser = row[15].strip() | ||
| 276 | + | ||
| 277 | + obj = SKU.objects.create( | ||
| 278 | + supplier=row[0], | ||
| 279 | + sku=row[1], | ||
| 280 | + model=row[2], | ||
| 281 | + title=row[3], | ||
| 282 | + is_new=row[4], | ||
| 283 | + qty=qty, | ||
| 284 | + price_with_tax=price_with_tax, | ||
| 285 | + amount_with_tax=amount_with_tax, | ||
| 286 | + sell_day=sell_day, | ||
| 287 | + qty_within_30=qty_within_30, | ||
| 288 | + inventory=inventory, | ||
| 289 | + coming_inventory=coming_inventory, | ||
| 290 | + gross_profit_rate=gross_profit_rate, | ||
| 291 | + return_rate=return_rate, | ||
| 292 | + memo=memo, | ||
| 293 | + purchaser=purchaser, | ||
| 294 | + | ||
| 295 | + ) | ||
| 296 | + obj_list.append(SKUSerializer(obj).data) | ||
| 297 | + return obj_list | ||
| 298 | + | ||
| 299 | + def _upload(self, request): | ||
| 300 | + excel = request.FILES.get('file') | ||
| 301 | + | ||
| 302 | + if not excel: | ||
| 303 | + return response(msg=u"文件上传失败", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 304 | + excel.name = excel.name.strip('"') | ||
| 305 | + ext_pos = excel.name.rfind('.') | ||
| 306 | + uploaded_file_ext = excel.name[ext_pos:] | ||
| 307 | + if uploaded_file_ext not in self.allowed_extension: | ||
| 308 | + return response(msg="非法文件类型", status_code=status.HTTP_400_BAD_REQUEST) | ||
| 309 | + return upload_media(excel, uploaded_file_ext, request.user) |
| @@ -59,7 +59,7 @@ class WxPushHelper: | @@ -59,7 +59,7 @@ class WxPushHelper: | ||
| 59 | "msgtype": "textcard", | 59 | "msgtype": "textcard", |
| 60 | "agentid": self.conf['APP_ID'], # 企业应用ID | 60 | "agentid": self.conf['APP_ID'], # 企业应用ID |
| 61 | "textcard": { | 61 | "textcard": { |
| 62 | - "title": "产品立项流程通知", | 62 | + "title": f"{self.conf['title']}流程通知", |
| 63 | "description": description, | 63 | "description": description, |
| 64 | "url": url, | 64 | "url": url, |
| 65 | "btntxt": "点击查看" | 65 | "btntxt": "点击查看" |
| @@ -15,6 +15,34 @@ from rest_framework.permissions import IsAuthenticated, AllowAny | @@ -15,6 +15,34 @@ from rest_framework.permissions import IsAuthenticated, AllowAny | ||
| 15 | from rest_framework import status | 15 | from rest_framework import status |
| 16 | 16 | ||
| 17 | 17 | ||
| 18 | +def upload_media(uploaded_file, uploaded_file_ext, user): | ||
| 19 | + """ 处理上传新建媒体记录 """ | ||
| 20 | + hash_file_name = uuid() + uploaded_file_ext | ||
| 21 | + time_tag = time.strftime('%Y-%m-%d') | ||
| 22 | + file_path = time_tag + os.sep + hash_file_name | ||
| 23 | + dir_path = os.path.join(MEDIA_ROOT, time_tag) | ||
| 24 | + | ||
| 25 | + if not os.path.exists(dir_path): | ||
| 26 | + os.makedirs(dir_path) | ||
| 27 | + with open(os.path.join(dir_path, hash_file_name), 'wb') as f: | ||
| 28 | + f.write(uploaded_file.read()) | ||
| 29 | + | ||
| 30 | + file_hash = get_md5_hash(os.path.join(dir_path, hash_file_name)) | ||
| 31 | + file_size = int(uploaded_file.size / 1024) | ||
| 32 | + file = Media.objects.filter(hash=file_hash, size=file_size).first() | ||
| 33 | + if not file: | ||
| 34 | + file = Media.objects.create( | ||
| 35 | + file=uploaded_file, | ||
| 36 | + file_name=uploaded_file.name, | ||
| 37 | + hash=file_hash, | ||
| 38 | + user=user, | ||
| 39 | + size=file_size, | ||
| 40 | + extension=uploaded_file_ext | ||
| 41 | + ) | ||
| 42 | + os.remove(os.path.join(MEDIA_ROOT, file_path)) | ||
| 43 | + return file | ||
| 44 | + | ||
| 45 | + | ||
| 18 | class UploadMedia(CreateAPIView): | 46 | class UploadMedia(CreateAPIView): |
| 19 | serializer_class = MediaSerializer | 47 | serializer_class = MediaSerializer |
| 20 | permission_classes = (IsAuthenticated, ) | 48 | permission_classes = (IsAuthenticated, ) |
| @@ -30,35 +58,12 @@ class UploadMedia(CreateAPIView): | @@ -30,35 +58,12 @@ class UploadMedia(CreateAPIView): | ||
| 30 | uploaded_file_ext = uploaded_file.name[ext_pos:] | 58 | uploaded_file_ext = uploaded_file.name[ext_pos:] |
| 31 | if not self.allowed_extension(uploaded_file_ext): | 59 | if not self.allowed_extension(uploaded_file_ext): |
| 32 | return response(msg="非法文件类型", status_code=status.HTTP_400_BAD_REQUEST) | 60 | return response(msg="非法文件类型", status_code=status.HTTP_400_BAD_REQUEST) |
| 33 | - hash_file_name = uuid() + uploaded_file_ext | ||
| 34 | - time_tag = time.strftime('%Y-%m-%d') | ||
| 35 | - file_path = time_tag + os.sep + hash_file_name | ||
| 36 | - dir_path = os.path.join(MEDIA_ROOT, time_tag) | ||
| 37 | - | ||
| 38 | - if not os.path.exists(dir_path): | ||
| 39 | - os.makedirs(dir_path) | ||
| 40 | - with open(os.path.join(dir_path, hash_file_name), 'wb') as f: | ||
| 41 | - f.write(uploaded_file.read()) | ||
| 42 | - | ||
| 43 | - file_hash = get_md5_hash(os.path.join(dir_path, hash_file_name)) | ||
| 44 | - file_size = int(uploaded_file.size / 1024) | ||
| 45 | - file = Media.objects.filter(hash=file_hash, size=file_size).first() | ||
| 46 | - if not file: | ||
| 47 | - file = Media.objects.create( | ||
| 48 | - file=uploaded_file, | ||
| 49 | - file_name=uploaded_file.name, | ||
| 50 | - hash=file_hash, | ||
| 51 | - user=request.user, | ||
| 52 | - size=file_size, | ||
| 53 | - extension=uploaded_file_ext | ||
| 54 | - ) | ||
| 55 | - os.remove(os.path.join(MEDIA_ROOT, file_path)) | ||
| 56 | - # return response.Response(MediaSerializer(file, context={'request': request}).data) | 61 | + file = upload_media(uploaded_file, uploaded_file_ext, request.user) |
| 57 | return response(MediaSerializer(file, context={'request': request}).data) | 62 | return response(MediaSerializer(file, context={'request': request}).data) |
| 58 | 63 | ||
| 59 | @staticmethod | 64 | @staticmethod |
| 60 | - def allowed_extension(ext): | ||
| 61 | - choices = UPLOAD_MEDIA_CHOICES | 65 | + def allowed_extension(ext, allowed_ext=None): |
| 66 | + choices = allowed_ext if allowed_ext else UPLOAD_MEDIA_CHOICES | ||
| 62 | for allowed_ext in choices: | 67 | for allowed_ext in choices: |
| 63 | if ext == allowed_ext[0]: | 68 | if ext == allowed_ext[0]: |
| 64 | return True | 69 | return True |
| @@ -11,13 +11,17 @@ project_conf = { | @@ -11,13 +11,17 @@ project_conf = { | ||
| 11 | "CORP_ID": "ww0f3efc2873ad11c3", | 11 | "CORP_ID": "ww0f3efc2873ad11c3", |
| 12 | "APP_ID": '1000078', | 12 | "APP_ID": '1000078', |
| 13 | "APP_SECRET": "7MHpdQICiegx9rIc4iZrEPunb1aYUqdJYKSW9v7a1A8", | 13 | "APP_SECRET": "7MHpdQICiegx9rIc4iZrEPunb1aYUqdJYKSW9v7a1A8", |
| 14 | + "wx_authorize": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww0f3efc2873ad11c3&redirect_uri=REDIRECT_URL&response_type=code&scope=snsapi_base&state=1000078#wechat_redirect", | ||
| 15 | + "flow_detail": "http://project.tacklifetools.com/product/audit/PK" | ||
| 14 | } | 16 | } |
| 15 | 17 | ||
| 16 | sku_conf = { | 18 | sku_conf = { |
| 17 | - "title": "sku条目审批应用", | 19 | + "title": "返单特采", |
| 18 | "CORP_ID": "ww0f3efc2873ad11c3", | 20 | "CORP_ID": "ww0f3efc2873ad11c3", |
| 19 | "APP_ID": '1000081', | 21 | "APP_ID": '1000081', |
| 20 | "APP_SECRET": "_O_MrxbQO1vojzNBPAiaF_MdzikHRbnVfFc3v8iOtKo", | 22 | "APP_SECRET": "_O_MrxbQO1vojzNBPAiaF_MdzikHRbnVfFc3v8iOtKo", |
| 23 | + "wx_authorize": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww0f3efc2873ad11c3&redirect_uri=REDIRECT_URL&response_type=code&scope=snsapi_base&state=1000081#wechat_redirect", | ||
| 24 | + "flow_detail": "http://project.tacklifetools.com/sku/audit/PK" | ||
| 21 | } | 25 | } |
| 22 | 26 | ||
| 23 | 27 | ||
| @@ -25,3 +29,4 @@ Conf = { | @@ -25,3 +29,4 @@ Conf = { | ||
| 25 | "1000078": project_conf, | 29 | "1000078": project_conf, |
| 26 | "1000081": sku_conf | 30 | "1000081": sku_conf |
| 27 | } | 31 | } |
| 32 | + |
| @@ -177,7 +177,3 @@ SIMPLE_JWT = { | @@ -177,7 +177,3 @@ SIMPLE_JWT = { | ||
| 177 | 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), | 177 | 'SLIDING_TOKEN_REFRESH_LIFETIME': timedelta(days=1), |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | -FRONT_URL = { | ||
| 181 | - "wx_authorize": "https://open.weixin.qq.com/connect/oauth2/authorize?appid=ww0f3efc2873ad11c3&redirect_uri=REDIRECT_URL&response_type=code&scope=snsapi_base#wechat_redirect", | ||
| 182 | - "flow_detail": "http://project.tacklifetools.com/product/audit/PK" | ||
| 183 | -} |
| @@ -18,6 +18,7 @@ urlpatterns = [ | @@ -18,6 +18,7 @@ urlpatterns = [ | ||
| 18 | path(api_version + 'auth/', include('usercenter.urls', namespace='usercenter')), | 18 | path(api_version + 'auth/', include('usercenter.urls', namespace='usercenter')), |
| 19 | path(api_version + 'upload/', UploadMedia.as_view()), | 19 | path(api_version + 'upload/', UploadMedia.as_view()), |
| 20 | path(api_version + 'project/', include('project.urls', namespace="project")), | 20 | path(api_version + 'project/', include('project.urls', namespace="project")), |
| 21 | + path(api_version + 'sku/', include('sku.urls', namespace="sku")), | ||
| 21 | path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), | 22 | path('api-auth/', include('rest_framework.urls', namespace='rest_framework')), |
| 22 | re_path(r'api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), | 23 | re_path(r'api/token/refresh/', TokenRefreshView.as_view(), name='token_refresh'), |
| 23 | re_path(r'api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'), | 24 | re_path(r'api/token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'), |
-
请 注册 或 登录 后发表评论