diff --git a/apps/ofm/migrations/0010_auto_20250919_0921.py b/apps/ofm/migrations/0010_auto_20250919_0921.py new file mode 100644 index 00000000..528c5882 --- /dev/null +++ b/apps/ofm/migrations/0010_auto_20250919_0921.py @@ -0,0 +1,53 @@ +# Generated by Django 3.2.12 on 2025-09-19 01:21 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('system', '0006_auto_20241213_1249'), + ('ofm', '0009_borrowrecord_ticket'), + ] + + operations = [ + migrations.AddField( + model_name='lendingseal', + name='seal_other', + field=models.CharField(blank=True, max_length=50, null=True, verbose_name='其他印章'), + ), + migrations.CreateModel( + name='Publicity', + fields=[ + ('id', models.CharField(editable=False, help_text='主键ID', max_length=20, primary_key=True, serialize=False, verbose_name='主键ID')), + ('create_time', models.DateTimeField(default=django.utils.timezone.now, help_text='创建时间', verbose_name='创建时间')), + ('update_time', models.DateTimeField(auto_now=True, help_text='修改时间', verbose_name='修改时间')), + ('is_deleted', models.BooleanField(default=False, help_text='删除标记', verbose_name='删除标记')), + ('number', models.CharField(max_length=50, verbose_name='记录编号')), + ('title', models.CharField(max_length=100, verbose_name='送审稿件标题')), + ('participants', models.CharField(max_length=50, verbose_name='所有撰稿人')), + ('level', models.JSONField(default=list, help_text=['重要', '一般', '非涉密'], verbose_name='用途')), + ('content', models.JSONField(default=list, help_text=['武器装备科研生产综合事项', '其它'], verbose_name='稿件内容涉及')), + ('other_content', models.CharField(blank=True, max_length=100, null=True, verbose_name='其它内容')), + ('report_purpose', models.CharField(blank=True, max_length=100, null=True, verbose_name='宣传报道目的')), + ('channel', models.JSONField(default=list, help_text=['互联网', '信息平台', '官微', '公开发行物', '其它'], verbose_name='发布渠道')), + ('channel_other', models.CharField(blank=True, max_length=50, null=True, verbose_name='其它渠道')), + ('other_channel', models.CharField(blank=True, max_length=50, null=True, verbose_name='其它渠道')), + ('report_name', models.CharField(blank=True, max_length=50, null=True, verbose_name='报道名称')), + ('review', models.JSONField(default=list, help_text=['内容不涉及国家秘密和商业秘密,申请公开', '内容涉及国家秘密,申请按涉密渠道发布'], verbose_name='第一撰稿人自审')), + ('dept_opinion', models.JSONField(default=list, help_text=['同意', '不同意'], verbose_name='部门负责人意见')), + ('dept_opinion_review', models.CharField(blank=True, max_length=100, null=True, verbose_name='部门审查意见')), + ('publicity_opinion', models.JSONField(default=list, help_text=['同意公开宣传报道', '不同意任何渠道的宣传报道'], verbose_name='宣传统战部审查意见')), + ('belong_dept', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='publicity_belong_dept', to='system.dept', verbose_name='所属部门')), + ('create_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='publicity_create_by', to=settings.AUTH_USER_MODEL, verbose_name='创建人')), + ('update_by', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='publicity_update_by', to=settings.AUTH_USER_MODEL, verbose_name='最后编辑人')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/ofm/models.py b/apps/ofm/models.py index 1a7e219d..09aa8369 100644 --- a/apps/ofm/models.py +++ b/apps/ofm/models.py @@ -1,7 +1,8 @@ -from django.db import models +from django.db import models, transaction from apps.utils.models import CommonADModel, BaseModel, CommonBDModel from apps.system.models import User from django.core.validators import RegexValidator +from datetime import datetime # Create your models here. @@ -49,6 +50,7 @@ class LendingSeal(CommonBDModel): """TN: 印章外出用印信息""" seal = models.JSONField('印章信息',default=list ,help_text='[公章,法人章,财务章,合同章,业务章,其他章]') + seal_other = models.CharField('其他印章', max_length=50, blank=True, null=True) filename = models.TextField('文件名称') file = models.TextField('文件内容') file_count = models.PositiveIntegerField('用印份数') @@ -105,35 +107,44 @@ class BorrowRecord(CommonBDModel): on_delete=models.SET_NULL, related_name='borrow_ticket', null=True, blank=True, db_constraint=False) -# class Publicity(CommonBDModel): -# """TN: 公示栏""" -# CHANNEL_CHOICES = [ -# ('internet', '互联网'), -# ('platform', '信息平台'), -# ('official', '官微'), -# ('publication', '公开发行物'), -# ('other', '其它'), -# ] -# SECRET_LEVELS = ( -# (0, '重要'), -# (1, '一般'), -# (2, '非涉密'), -# ) -# CONTENT_CHOICES = [ -# ('device', '武器装备科研生产综合事项'), -# ('other', '其他'), -# ] -# number = models.CharField('记录编号', max_length=50) -# title = models.CharField('送审稿件标题', max_length=100) -# participants = models.CharField('所有撰稿人', max_length=50) -# level = models.PositiveBigIntegerField('涉密等级', choices=SECRET_LEVELS, default=2, help_text=str(SECRET_LEVELS)) -# content = models.CharField('稿件内容涉及', max_length=50, choices=CONTENT_CHOICES, default='device', blank=True) -# report_purpose = models.CharField('宣传报道目的', max_length=100, blank=True, null=True) -# channel = models.CharField('发布渠道', max_length=50, choices=CHANNEL_CHOICES, default='platform') -# other_channel = models.CharField('其它渠道', max_length=50, blank=True, null=True) -# review = models.CharField('第一撰稿人自审', max_length=100, blank=True, null=True) -# dept_opinion = models.CharField('部门负责人意见', max_length=100, blank=True, null=True) -# manager_opinion = models.CharField('总经理', max_length=100, blank=True, null=True) +class Publicity(CommonBDModel): + """TN: 公示栏""" + number = models.CharField('记录编号', max_length=50) + title = models.CharField('送审稿件标题', max_length=100) + participants = models.CharField('所有撰稿人', max_length=50) + level = models.JSONField('用途', default=list, help_text=['重要', '一般', '非涉密']) + content = models.JSONField('稿件内容涉及', default=list, help_text=[ + "武器装备科研生产综合事项", + "其它" + ]) + other_content = models.CharField('其它内容', max_length=100, blank=True, null=True) + report_purpose = models.CharField('宣传报道目的', max_length=100, blank=True, null=True) + channel = models.JSONField('发布渠道', default=list, help_text=['互联网', '信息平台', '官微', '公开发行物', '其它']) + channel_other = models.CharField('其它渠道', max_length=50, blank=True, null=True) + other_channel = models.CharField('其它渠道', max_length=50, blank=True, null=True) + report_name = models.CharField('报道名称', max_length=50, blank=True, null=True) + review = models.JSONField('第一撰稿人自审', default=list, help_text=['内容不涉及国家秘密和商业秘密,申请公开', '内容涉及国家秘密,申请按涉密渠道发布']) + dept_opinion = models.JSONField('部门负责人意见', default=list, help_text=['同意', '不同意']) + dept_opinion_review = models.CharField('部门审查意见', max_length=100, blank=True, null=True) + publicity_opinion = models.JSONField('宣传统战部审查意见', default=list, help_text=['同意公开宣传报道', '不同意任何渠道的宣传报道']) + + # 记录编号自动生成 + def save(self, *args, **kwargs): + if not self.number: + with transaction.atomic(): + # 加行锁,防止并发取到相同 last_number + last_number = self.__class__.objects.select_for_update(skip_locked=True).order_by('-id').first() # skip_locked 锁定行,避免并发冲突 + if last_number: + try: + last_num = int(last_number.number.split('-')[-1]) + except ValueError: + last_num = 0 + new_num= last_num + 1 + else: + new_num = 1 + # 格式化编号,带补零 + self.number = f"(GXKG-{datetime.now().year}-{new_num:02d})" + super().save(*args, **kwargs) # class PatentInfo(CommonBDModel): diff --git a/apps/ofm/serializers.py b/apps/ofm/serializers.py index 4761e17a..b3b3201f 100644 --- a/apps/ofm/serializers.py +++ b/apps/ofm/serializers.py @@ -1,5 +1,4 @@ -from .models import (Mroom, MroomBooking, MroomSlot, LendingSeal, Vehicle, FileRecord, BorrowRecord ) -# , Publicity, +from .models import (Mroom, MroomBooking, MroomSlot, LendingSeal, Vehicle, FileRecord, BorrowRecord, Publicity) # Publicity, PatentInfo, PaperOfm, Platform, Project, PatentRecord, PaperRecord, ProjectApproval, ProjectInfo) from apps.utils.serializers import CustomModelSerializer from rest_framework import serializers @@ -106,11 +105,11 @@ class BorrowRecordSerializer(CustomModelSerializer): return [file.name for file in obj.borrow_file.all()] -# class PublicitySerializer(CustomModelSerializer): -# class Meta: -# model = Publicity -# fields = '__all__' -# read_only_fields = EXCLUDE_FIELDS +class PublicitySerializer(CustomModelSerializer): + class Meta: + model = Publicity + fields = '__all__' + read_only_fields = EXCLUDE_FIELDS # class PatentInfoSerializer(CustomModelSerializer): diff --git a/apps/ofm/urls.py b/apps/ofm/urls.py index 38c1b273..812d4d94 100644 --- a/apps/ofm/urls.py +++ b/apps/ofm/urls.py @@ -1,6 +1,6 @@ from django.urls import path, include from rest_framework.routers import DefaultRouter -from apps.ofm.views import (MroomViewSet, MroomBookingViewSet, MroomSlotViewSet,LendingSealViewSet, VehicleViewSet, FilerecordViewSet, FileborrowViewSet) +from apps.ofm.views import (MroomViewSet, MroomBookingViewSet, MroomSlotViewSet,LendingSealViewSet, VehicleViewSet, FilerecordViewSet, FileborrowViewSet, PublicityViewSet) # SealModelViewSet, # , PublicityViewSet, PatentInfoViewSet, PaperViewSet, PlatformViewSet, # ProjectViewSet, PatentRecordViewSet, PaperRecordViewSet, ProjectApprovalViewSet, ProjectInfoViewSet) @@ -17,9 +17,8 @@ router.register('lendingseal', LendingSealViewSet, basename='lendingseal') router.register('vehicle', VehicleViewSet, basename='vehicle') router.register('filerecord', FilerecordViewSet, basename='filerecord') router.register('fileborrow', FileborrowViewSet, basename='fileborrow') -# router.register('publicity', PublicityViewSet, basename='publicity') +router.register('publicity', PublicityViewSet, basename='publicity') # router.register('patentinfo', PatentInfoViewSet, basename='patentinfo') - # router.register('paper', PaperViewSet, basename='paper') # router.register('platform', PlatformViewSet, basename='platform') # router.register('project', ProjectViewSet, basename='project') diff --git a/apps/ofm/views.py b/apps/ofm/views.py index 9def8c0c..9ac103a0 100644 --- a/apps/ofm/views.py +++ b/apps/ofm/views.py @@ -1,9 +1,8 @@ from django.shortcuts import render from apps.utils.viewsets import CustomModelViewSet, CustomGenericViewSet -from .models import Mroom, MroomBooking, MroomSlot, LendingSeal, Vehicle, FileRecord, BorrowRecord - # Seal +from .models import Mroom, MroomBooking, MroomSlot, LendingSeal, Vehicle, FileRecord, BorrowRecord, Publicity # Publicity, PatentInfo, PaperOfm, Platform, Project, PatentRecord, PaperRecord, ProjectApproval, ProjectInfo) -from .serializers import (MroomSerializer, MroomBookingSerializer, MroomSlotSerializer, LendingSealSerializer, VehicleSerializer, FileRecordSerializer, BorrowRecordSerializer) +from .serializers import (MroomSerializer, MroomBookingSerializer, MroomSlotSerializer, LendingSealSerializer, VehicleSerializer, FileRecordSerializer, BorrowRecordSerializer, PublicitySerializer) # ,SealSerializer, # LendingSealSerializer, FileRecordSerializer, BorrowRecordSerializer, PublicitySerializer, # PatentInfoSerializer, PaperSerializer, PlatformSerializer, ProjectSerializer, ProjectMemberSerializer, PaperRecordSerializer, ProjectApprovalSerializer, ProjectInfoSerializer) @@ -148,15 +147,15 @@ class FileborrowViewSet(CustomModelViewSet): ordering = ["create_time"] -# class PublicityViewSet(CustomModelViewSet): -# """list: 公告 +class PublicityViewSet(CustomModelViewSet): + """list: 公告 -# 公告 -# """ -# queryset = Publicity.objects.all() -# serializer_class = PublicitySerializer -# filterset_fields = ["title","number"] -# ordering = ["create_time", "number"] + 公告 + """ + queryset = Publicity.objects.all() + serializer_class = PublicitySerializer + filterset_fields = ["title","number"] + ordering = ["create_time", "number"] # class PatentInfoViewSet(CustomModelViewSet):