feat: 修改考试和 新增证书字段
This commit is contained in:
parent
779855ea62
commit
5638574339
|
|
@ -69,6 +69,8 @@ class CompanyInfo(CommonModel):
|
|||
edu_points = models.FloatField('教育积分', null=True, blank=True)
|
||||
co_sponsor_points = models.FloatField('协办大赛积分', null=True, blank=True)
|
||||
sum_points = models.FloatField('总积分', null=True, blank=True)
|
||||
photo = models.ImageField('公司图片', upload_to='photo', null=True, blank=True)
|
||||
remark = models.TextField('备注', null=True, blank=True, max_length=500)
|
||||
|
||||
def __str__(self):
|
||||
return self.company_name
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ from .models import Candidate, Company, Consumer, PaySubject, ConsumerPerm, Cons
|
|||
from question.models import Question, Questioncat
|
||||
from .permission import get_consumerperm_list
|
||||
from rbac.serializers.user_serializer import UserListSerializer
|
||||
|
||||
from examtest.services import make_img
|
||||
from server import settings
|
||||
|
||||
class ConsumerPermSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
|
|
@ -43,7 +44,7 @@ class ConsumerSerializer(serializers.ModelSerializer):
|
|||
create_admin_name = serializers.StringRelatedField(source='create_admin', read_only=True)
|
||||
class Meta:
|
||||
model = Consumer
|
||||
exclude = ('avatar','collects', 'process')
|
||||
exclude = ('collects', 'process')
|
||||
|
||||
@staticmethod
|
||||
def setup_eager_loading(queryset):
|
||||
|
|
@ -83,6 +84,7 @@ class ConsumerDetailSerializer(serializers.ModelSerializer):
|
|||
|
||||
class CandidateSerializer(serializers.ModelSerializer):
|
||||
create_admin_username = serializers.StringRelatedField(source='create_admin', read_only=True)
|
||||
cert_template = serializers.StringRelatedField(source='examtest.exam.cert_template', read_only=True)
|
||||
class Meta:
|
||||
model = Candidate
|
||||
fields = '__all__'
|
||||
|
|
@ -97,6 +99,16 @@ class CandidateCreateSerializer(serializers.ModelSerializer):
|
|||
validated_data['create_admin'] = self.context['request'].user
|
||||
return super().create(validated_data)
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
validated_data['is_manual'] = True
|
||||
validated_data['create_admin'] = self.context['request'].user
|
||||
issue_date = validated_data.get('issue_date', None)
|
||||
exp_date = validated_data.get('end_date', None)
|
||||
header_photo = settings.BASE_DIR + validated_data.get('photo', None)
|
||||
path = make_img(validated_data["consumer_name"], str(issue_date.year), str(issue_date.month), str(exp_date.year), str(exp_date.month), str(exp_date.day), validated_data["number"], header_photo)
|
||||
validated_data['path'] = path
|
||||
return super().update(instance,validated_data)
|
||||
|
||||
class MsgSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = SendCode
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ class Exam(CommonModel):
|
|||
qdimgs = JSONField('签到图片', default=list)
|
||||
xcimgs = JSONField('现场图片', default=list)
|
||||
only_vip = models.BooleanField('仅允许培训班学员', default=False)
|
||||
cert_template = models.PositiveSmallIntegerField('证书模板', null=True, blank=True, help_text='1,2')
|
||||
cert_template = models.PositiveSmallIntegerField('证书模板', null=True, blank=True, help_text='1,2,3')
|
||||
auto_issue = models.BooleanField('是否自动发证', default=False)
|
||||
|
||||
def __str__(self):
|
||||
|
|
|
|||
|
|
@ -4,6 +4,10 @@ from django.utils import timezone
|
|||
from datetime import timedelta
|
||||
from rest_framework.exceptions import ParseError
|
||||
from rbac.models import UserProfile
|
||||
from PIL import Image, ImageDraw, ImageFont
|
||||
import settings, datetime
|
||||
from server import settings
|
||||
|
||||
def issue(obj: ExamTest, create_admin: UserProfile = None):
|
||||
if create_admin is None:
|
||||
create_admin = obj.exam.create_admin
|
||||
|
|
@ -35,8 +39,124 @@ def issue(obj: ExamTest, create_admin: UserProfile = None):
|
|||
if cert_template == 2:
|
||||
count = Candidate.objects.filter(create_admin=create_admin, issue_date__year=now.year, issue_date__month=now.month).count()
|
||||
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
|
||||
elif cert_template == 3:
|
||||
cer_path = make_img(candidate.consumer_name, str(candidate.start_date.year), str(candidate.start_date.month), str(candidate.end_date.year), str(candidate.end_date.month), str(candidate.end_date.day), candidate.number, header_path=candidate.photo, mode=True)
|
||||
candidate.path = cer_path
|
||||
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
|
||||
elif cert_template == 4:
|
||||
cer_path = make_img(candidate.consumer_name, str(candidate.start_date.year), str(candidate.start_date.month), str(candidate.end_date.year), str(candidate.end_date.month), str(candidate.end_date.day), candidate.number, header_path=candidate.photo, mode=False)
|
||||
candidate.path = cer_path
|
||||
candidate.number='HNHK'+ str(now.year) + str(now.month).zfill(2) + str(count+1).zfill(4)
|
||||
else:
|
||||
candidate.number='SL'+ str(now.year)[-2:] + str(candidate.pk).zfill(6)
|
||||
|
||||
candidate.create_admin = create_admin
|
||||
candidate.save()
|
||||
return {"id":candidate.pk, "number":candidate.number, "path":None}
|
||||
|
||||
|
||||
def make_img(name:str, year:str, month:str, expiry_year:str, expiry_month:str, expiry_day:str, certificate_number:str, header_path=None, mode=None):
|
||||
now = datetime.datetime.now()
|
||||
font_path = settings.BASE_DIR + "/media/cert/template/STKAITI.TTF"
|
||||
if mode:
|
||||
demo_image_path = settings.BASE_DIR + "/media/cert/template/assess.png"
|
||||
# demo_image_path = r"C:\code\cma_search\server\media\test.png"
|
||||
img = Image.open(demo_image_path)
|
||||
if img.mode == 'RGBA':
|
||||
img = img.convert('RGB')
|
||||
# Initialize ImageDraw
|
||||
draw = ImageDraw.Draw(img)
|
||||
|
||||
# Set font paths and sizes
|
||||
# font_path = r"C:/code/cma_search/server/media/font/SIMLI.TTF" # Update this to the correct font path
|
||||
font_name = ImageFont.truetype(font_path, 20) # Font size for the name
|
||||
font_text = ImageFont.truetype(font_path, 20) # Font size for the other text
|
||||
font_number = ImageFont.truetype(font_path, 15) # Font size for the other text
|
||||
|
||||
# uoload header image
|
||||
# header_path = "C:\code\cma_search\server\media\OIP.jpg"
|
||||
if header_path:
|
||||
header_img = Image.open(header_path)
|
||||
# 指定粘贴的位置
|
||||
header_position = (210, 235) # 粘贴图像的左上角位置
|
||||
header_img = header_img.resize((140, 150))
|
||||
img.paste(header_img, header_position)
|
||||
if len(name) <= 3:
|
||||
position_name = (105, 395)
|
||||
else:
|
||||
position_name = (100, 395)
|
||||
position_year = (220, 395)
|
||||
position_month = (280, 395)
|
||||
|
||||
position_exp_day = (310, 490)
|
||||
position_exp_month = (270, 490)
|
||||
position_exp_year = (210, 490)
|
||||
position_cert_number = (180, 530)
|
||||
|
||||
# Define colors
|
||||
color = (0, 0, 0) # Black color
|
||||
|
||||
# Draw the text on the image
|
||||
draw.text(position_name, name, fill=color, font=font_name)
|
||||
draw.text(position_year, year, fill=color, font=font_text)
|
||||
draw.text(position_month, month, fill=color, font=font_text)
|
||||
|
||||
draw.text(position_exp_year, expiry_year, fill=color, font=font_text)
|
||||
draw.text(position_exp_month, expiry_month, fill=color, font=font_text)
|
||||
draw.text(position_exp_day, expiry_day, fill=color, font=font_text)
|
||||
|
||||
draw.text(position_cert_number, certificate_number, fill=color, font=font_number)
|
||||
# Save the edited image
|
||||
output_path = f"/media/cert/template/certificate/{now}.jpg"# Update this to the desired output path
|
||||
img.save(settings.BASE_DIR + output_path, format='JPEG')
|
||||
else:
|
||||
demo_image_path = settings.BASE_DIR + "/media/cert/template/inspect.jpg"
|
||||
# font_path = r"C:/code/cma_search/server/media/font/SIMLI.TTF" # Update this to the correct font path
|
||||
img = Image.open(demo_image_path)
|
||||
if img.mode == 'RGBA':
|
||||
img = img.convert('RGB')
|
||||
# Initialize ImageDraw
|
||||
draw = ImageDraw.Draw(img)
|
||||
# Set font paths and sizes
|
||||
font_name = ImageFont.truetype(font_path, 20) # Font size for the name
|
||||
font_text = ImageFont.truetype(font_path, 20) # Font size for the other text
|
||||
font_number = ImageFont.truetype(font_path, 15) # Font size for the other text
|
||||
|
||||
# uoload header image
|
||||
if header_path:
|
||||
header_img = Image.open(header_path)
|
||||
# 指定粘贴的位置
|
||||
header_position = (240, 250) # 粘贴图像的左上角位置
|
||||
header_img = header_img.resize((120, 150))
|
||||
img.paste(header_img, header_position)
|
||||
|
||||
# Define text positions (X, Y) based on your image
|
||||
if len(name) <= 3:
|
||||
position_name = (130, 430)
|
||||
else:
|
||||
position_name = (140, 430)
|
||||
position_year = (245, 430)
|
||||
position_month = (308, 430)
|
||||
|
||||
position_exp_day = (430, 525)
|
||||
position_exp_month = (390, 525)
|
||||
position_exp_year = (330, 525)
|
||||
position_cert_number = (200, 565)
|
||||
|
||||
# Define colors
|
||||
color = (0, 0, 0) # Black color
|
||||
|
||||
# Draw the text on the image
|
||||
draw.text(position_name, name, fill=color, font=font_name)
|
||||
draw.text(position_year, year, fill=color, font=font_text)
|
||||
draw.text(position_month, month, fill=color, font=font_text)
|
||||
|
||||
draw.text(position_exp_year, expiry_year, fill=color, font=font_text)
|
||||
draw.text(position_exp_month, expiry_month, fill=color, font=font_text)
|
||||
draw.text(position_exp_day, expiry_day, fill=color, font=font_text)
|
||||
|
||||
draw.text(position_cert_number, certificate_number, fill=color, font=font_number)
|
||||
# Save the edited image
|
||||
output_path = f"/media/cert/template/certificate/{now}.jpg"# Update this to the desired output path # Update this to the desired output path
|
||||
img.save(settings.BASE_DIR + output_path, format='JPEG')
|
||||
return output_path
|
||||
Loading…
Reference in New Issue