作者 vanwhebin

update

  1 +# Generated by Django 3.1.1 on 2020-10-21 11:40
  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 + dependencies = [
  11 + migrations.swappable_dependency(settings.AUTH_USER_MODEL),
  12 + ('project', '0004_auto_20201014_1513'),
  13 + ]
  14 +
  15 + operations = [
  16 + migrations.AddField(
  17 + model_name='auditor',
  18 + name='type',
  19 + field=models.PositiveSmallIntegerField(choices=[(1, '市场容量小于300万美金'), (2, '市场容量大于等于300万美金')], default=1, verbose_name='项目类型'),
  20 + ),
  21 + migrations.AddField(
  22 + model_name='project',
  23 + name='first_orders',
  24 + field=models.PositiveIntegerField(default=0, verbose_name='首单数量'),
  25 + ),
  26 + migrations.AddField(
  27 + model_name='project',
  28 + name='orders_estimate',
  29 + field=models.CharField(default='', max_length=255, verbose_name='月销量预估'),
  30 + ),
  31 + migrations.AddField(
  32 + model_name='project',
  33 + name='roi_report',
  34 + field=models.CharField(default='', max_length=255, verbose_name='ROI报告'),
  35 + ),
  36 + migrations.AddField(
  37 + model_name='project',
  38 + name='type',
  39 + field=models.PositiveSmallIntegerField(choices=[(1, '市场容量小于300万美金'), (2, '市场容量大于等于300万美金')], default=1, verbose_name='项目类型'),
  40 + ),
  41 + migrations.AlterField(
  42 + model_name='auditor',
  43 + name='user',
  44 + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='aud', to=settings.AUTH_USER_MODEL, verbose_name='审批人员'),
  45 + ),
  46 + ]
1 from django.db import models 1 from django.db import models
2 from usercenter.models import User 2 from usercenter.models import User
3 3
4 -# users = User.objects.filter(is_active=True).values('username', 'id').all()  
5 -# AUDITOR_CHOICE = [(i['id'], i['username']) for i in users]  
6 -AUDITOR_CHOICE = [(2, '邓望明'), (3, '杜波')] 4 +PROJECT_TYPE = (
  5 + (1, u"市场容量小于300万美金"),
  6 + (2, u"市场容量大于等于300万美金"),
  7 + )
7 8
8 9
9 class Auditor(models.Model): 10 class Auditor(models.Model):
@@ -12,7 +13,6 @@ class Auditor(models.Model): @@ -12,7 +13,6 @@ class Auditor(models.Model):
12 User, 13 User,
13 on_delete=models.CASCADE, 14 on_delete=models.CASCADE,
14 related_name="aud", 15 related_name="aud",
15 - choices=AUDITOR_CHOICE,  
16 verbose_name="审批人员") 16 verbose_name="审批人员")
17 leader = models.ForeignKey( 17 leader = models.ForeignKey(
18 'self', 18 'self',
@@ -21,6 +21,7 @@ class Auditor(models.Model): @@ -21,6 +21,7 @@ class Auditor(models.Model):
21 null=True, 21 null=True,
22 blank=True, 22 blank=True,
23 verbose_name="上级领导") 23 verbose_name="上级领导")
  24 + type = models.PositiveSmallIntegerField(default=1, choices=PROJECT_TYPE, verbose_name="项目类型")
24 order = models.PositiveSmallIntegerField(default=0, null=True, blank=True, verbose_name="排序") 25 order = models.PositiveSmallIntegerField(default=0, null=True, blank=True, verbose_name="排序")
25 26
26 def __str__(self): 27 def __str__(self):
@@ -31,13 +32,17 @@ class Auditor(models.Model): @@ -31,13 +32,17 @@ class Auditor(models.Model):
31 32
32 33
33 class Project(models.Model): 34 class Project(models.Model):
  35 +
34 category = models.CharField(max_length=100, default="", verbose_name="产品类目") 36 category = models.CharField(max_length=100, default="", verbose_name="产品类目")
35 model_type = models.CharField(max_length=50, default="", verbose_name="产品型号") 37 model_type = models.CharField(max_length=50, default="", verbose_name="产品型号")
36 market_share_analysis = models.TextField(default="", verbose_name="产品市场占有率分析") 38 market_share_analysis = models.TextField(default="", verbose_name="产品市场占有率分析")
37 context_analysis = models.TextField(default="", verbose_name="产品场景分析") 39 context_analysis = models.TextField(default="", verbose_name="产品场景分析")
38 attachments = models.CharField(max_length=800, default="", verbose_name="附件地址") 40 attachments = models.CharField(max_length=800, default="", verbose_name="附件地址")
  41 + first_orders = models.PositiveIntegerField(default=0, verbose_name="首单数量")
  42 + orders_estimate = models.CharField(default="", max_length=255, verbose_name="月销量预估")
39 auditor = models.ManyToManyField(Auditor, related_name="project_auditor", blank=True, verbose_name="审核人员") 43 auditor = models.ManyToManyField(Auditor, related_name="project_auditor", blank=True, verbose_name="审核人员")
40 is_done = models.BooleanField(default=False, blank=True, verbose_name="是否完成") 44 is_done = models.BooleanField(default=False, blank=True, verbose_name="是否完成")
  45 + type = models.PositiveSmallIntegerField(default=1, choices=PROJECT_TYPE, verbose_name="项目类型")
41 is_pass = models.BooleanField(null=True, blank=True, verbose_name="是否通过") 46 is_pass = models.BooleanField(null=True, blank=True, verbose_name="是否通过")
42 create_time = models.DateTimeField(auto_now_add=True) 47 create_time = models.DateTimeField(auto_now_add=True)
43 creator = models.ForeignKey(User, related_name="project_creator", on_delete=models.CASCADE, verbose_name="创建人员") 48 creator = models.ForeignKey(User, related_name="project_creator", on_delete=models.CASCADE, verbose_name="创建人员")
@@ -23,7 +23,7 @@ class ProjectSerializer(serializers.ModelSerializer): @@ -23,7 +23,7 @@ class ProjectSerializer(serializers.ModelSerializer):
23 model = Project 23 model = Project
24 fields = ( 24 fields = (
25 'id', 'result', 'creator_name', 'category', 'model_type', 'market_share_analysis', 'context_analysis', 25 'id', 'result', 'creator_name', 'category', 'model_type', 'market_share_analysis', 'context_analysis',
26 - 'attachments', 'create_time', "is_done", "is_pass" 26 + 'attachments', 'create_time', "is_done", "is_pass", "type", "orders_estimate", "first_orders"
27 ) 27 )
28 depth = 1 28 depth = 1
29 29
@@ -35,17 +35,18 @@ class CreateProject(CreateAPIView): @@ -35,17 +35,18 @@ class CreateProject(CreateAPIView):
35 if not serializer.is_valid(): 35 if not serializer.is_valid():
36 raise ValidationError(serializer.errors) 36 raise ValidationError(serializer.errors)
37 else: 37 else:
38 - serializer.save(creator=request.user, auditor=Auditor.objects.order_by('-order').all())  
39 - # 企业微信推送  
40 obj_dict = serializer.data 38 obj_dict = serializer.data
41 - for i in AUDITORS: 39 + auditors = Auditor.objects.filter(type=obj_dict['type']).order_by('order')
  40 + serializer.save(creator=request.user, auditor=auditors)
  41 + # 企业微信推送
  42 + for i in auditors:
42 Result.objects.create( 43 Result.objects.create(
43 - auditor_id=i[0], 44 + auditor_id=i.pk,
44 project_id=obj_dict['id'] 45 project_id=obj_dict['id']
45 ) 46 )
46 url = re.sub("PK", str(obj_dict['id']), FRONT_URL['flow_detail']) 47 url = re.sub("PK", str(obj_dict['id']), FRONT_URL['flow_detail'])
47 url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), FRONT_URL['wx_authorize']) 48 url = re.sub("REDIRECT_URL", parse.quote(url, safe=''), FRONT_URL['wx_authorize'])
48 - first_auditor = Auditor.objects.filter(pk=AUDITORS[0][0]).first() 49 + first_auditor = auditors[0]
49 50
50 wx_client.push_card(first_auditor.user.wx_token, url, f"{request.user.username}提交了一个产品立项申请") 51 wx_client.push_card(first_auditor.user.wx_token, url, f"{request.user.username}提交了一个产品立项申请")
51 wx_client.push_card(request.user.wx_token, url, u"流程创建成功") 52 wx_client.push_card(request.user.wx_token, url, u"流程创建成功")
@@ -61,8 +62,7 @@ class ProjectDetail(RetrieveAPIView): @@ -61,8 +62,7 @@ class ProjectDetail(RetrieveAPIView):
61 obj = self.get_object() 62 obj = self.get_object()
62 obj.creator_name = obj.creator.username 63 obj.creator_name = obj.creator.username
63 obj.result = [] 64 obj.result = []
64 - auditors = Auditor.objects.all()  
65 - # result = Result.objects.filter(project=obj) 65 + auditors = Auditor.objects.filter(type=obj.type)
66 for i in auditors: 66 for i in auditors:
67 res = i.result_auditor.filter(project=obj).values('is_accept', 'memo').first() 67 res = i.result_auditor.filter(project=obj).values('is_accept', 'memo').first()
68 obj.result.append({ 68 obj.result.append({
@@ -94,12 +94,14 @@ class AuditProject(UpdateAPIView): @@ -94,12 +94,14 @@ class AuditProject(UpdateAPIView):
94 ('reject', '否决') 94 ('reject', '否决')
95 ) 95 )
96 accept_param = accept_choices[0][0] if request.data.get('is_accept') else accept_choices[1][0] 96 accept_param = accept_choices[0][0] if request.data.get('is_accept') else accept_choices[1][0]
97 - target = Project.objects.filter(auditor__user_id=request.user.id, pk=obj.id)  
98 - if not target: 97 + # target = Project.objects.filter(auditor__user_id=request.user.id, pk=obj.id)
  98 + if not obj:
99 raise PermissionError 99 raise PermissionError
100 else: 100 else:
101 auditor = Auditor.objects.get(user=request.user) 101 auditor = Auditor.objects.get(user=request.user)
102 - result = Result.objects.filter(auditor=auditor, project=obj).first() 102 + result = Result.objects.filter(auditor=auditor, project=obj, is_accept__isnull=True).order_by('pk').first()
  103 + if not result:
  104 + raise PermissionError("不允许修改已审核的项目")
103 result.is_accept = accept_param 105 result.is_accept = accept_param
104 result.memo = request.data.get('memo', '') 106 result.memo = request.data.get('memo', '')
105 result.save() 107 result.save()
@@ -117,7 +119,9 @@ class AuditProject(UpdateAPIView): @@ -117,7 +119,9 @@ class AuditProject(UpdateAPIView):
117 obj.is_done = True 119 obj.is_done = True
118 obj.is_pass = False 120 obj.is_pass = False
119 else: 121 else:
120 - second_auditor = Auditor.objects.filter(pk=AUDITORS[1][0]).first() 122 + next_auditor_id = Result.objects.filter(project=obj, is_accept__isnull=True)\
  123 + .values_list('auditor_id', flat=True).order_by('pk').first()
  124 + second_auditor = Auditor.objects.filter(pk=next_auditor_id).first()
121 wx_client.push_card(second_auditor.user.wx_token, url, f"{request.user.username}已审核了一个产品立项申请") 125 wx_client.push_card(second_auditor.user.wx_token, url, f"{request.user.username}已审核了一个产品立项申请")
122 obj.save() 126 obj.save()
123 wx_client.push_card(obj.creator.wx_token, url, desc) 127 wx_client.push_card(obj.creator.wx_token, url, desc)
  1 +# Generated by Django 3.1.1 on 2020-10-21 13:10
  2 +
  3 +from django.db import migrations, models
  4 +
  5 +
  6 +class Migration(migrations.Migration):
  7 +
  8 + dependencies = [
  9 + ('usercenter', '0001_initial'),
  10 + ]
  11 +
  12 + operations = [
  13 + migrations.AddField(
  14 + model_name='media',
  15 + name='file_name',
  16 + field=models.CharField(default='', max_length=100, verbose_name='文件名'),
  17 + ),
  18 + ]
@@ -108,6 +108,7 @@ class Media(models.Model): @@ -108,6 +108,7 @@ class Media(models.Model):
108 file = models.FileField(max_length=200, upload_to="%Y-%m-%d", verbose_name="文件地址") 108 file = models.FileField(max_length=200, upload_to="%Y-%m-%d", verbose_name="文件地址")
109 size = models.PositiveIntegerField(verbose_name="文件大小", null=True, blank=True) 109 size = models.PositiveIntegerField(verbose_name="文件大小", null=True, blank=True)
110 user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="uploader", verbose_name="上传用户") 110 user = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=True, related_name="uploader", verbose_name="上传用户")
  111 + file_name = models.CharField(max_length=100, default="", verbose_name="文件名")
111 extension = models.CharField(max_length=10, verbose_name="文件扩展名", choices=UPLOAD_MEDIA_CHOICES) 112 extension = models.CharField(max_length=10, verbose_name="文件扩展名", choices=UPLOAD_MEDIA_CHOICES)
112 create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间") 113 create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
113 hash = models.CharField(max_length=200, verbose_name="文件哈希", null=True, blank=True) 114 hash = models.CharField(max_length=200, verbose_name="文件哈希", null=True, blank=True)
@@ -54,7 +54,7 @@ class GroupSerializer(serializers.ModelSerializer): @@ -54,7 +54,7 @@ class GroupSerializer(serializers.ModelSerializer):
54 class MediaSerializer(serializers.ModelSerializer): 54 class MediaSerializer(serializers.ModelSerializer):
55 class Meta: 55 class Meta:
56 model = Media 56 model = Media
57 - fields = ('file', 'size', 'create_time') 57 + fields = ('file', 'size', 'create_time', 'file_name')
58 58
59 59
60 60
@@ -46,6 +46,7 @@ class UploadMedia(CreateAPIView): @@ -46,6 +46,7 @@ class UploadMedia(CreateAPIView):
46 if not file: 46 if not file:
47 file = Media.objects.create( 47 file = Media.objects.create(
48 file=uploaded_file, 48 file=uploaded_file,
  49 + file_name=uploaded_file.name,
49 hash=file_hash, 50 hash=file_hash,
50 user=request.user, 51 user=request.user,
51 size=file_size, 52 size=file_size,