feat: 工单添加序号

pull/7483/head
xinwen 2022-01-10 20:14:13 +08:00 committed by Jiangjie.Bai
parent 25a2290804
commit 5cdc4c3c28
4 changed files with 105 additions and 4 deletions

View File

@ -0,0 +1,44 @@
# Generated by Django 3.1.13 on 2022-01-10 07:37
from django.db import migrations, models
from common.utils.timezone import as_current_tz
def fill_ticket_serial_number(apps, schema_editor):
Ticket = apps.get_model('tickets', 'Ticket')
tickets = Ticket.objects.all().order_by('date_created')
curr_day = '00000000'
curr_num = 1
print(f'\nFill ticket serial number ... ', end='')
for ticket in tickets:
# 跑这个脚本的时候,所有 ticket.serial_num == null
date_created = as_current_tz(ticket.date_created)
date_str = date_created.strftime('%Y%m%d')
if date_str != curr_day:
curr_day = date_str
curr_num = 1
ticket.serial_num = curr_day + '%04d' % curr_num
curr_num += 1
Ticket.objects.bulk_update(tickets, fields=('serial_num',))
print(len(tickets), end='')
class Migration(migrations.Migration):
dependencies = [
('tickets', '0012_ticketsession'),
]
operations = [
migrations.AddField(
model_name='ticket',
name='serial_num',
field=models.CharField(max_length=256, null=True, unique=True, verbose_name='Serial number'),
),
migrations.RunPython(fill_ticket_serial_number),
]

View File

@ -3,7 +3,11 @@
from django.db import models
from django.db.models import Q
from django.utils.translation import ugettext_lazy as _
from datetime import timedelta
from django.db.utils import IntegrityError
from common.exceptions import JMSException
from common.utils.timezone import as_current_tz
from common.mixins.models import CommonModelMixin
from common.db.encoder import ModelJSONFieldEncoder
from orgs.mixins.models import OrgModelMixin
@ -73,6 +77,7 @@ class Ticket(CommonModelMixin, OrgModelMixin):
'TicketFlow', related_name='tickets', on_delete=models.SET_NULL, null=True,
verbose_name=_("TicketFlow")
)
serial_num = models.CharField(max_length=256, unique=True, null=True, verbose_name=_('Serial number'))
class Meta:
ordering = ('-date_created',)
@ -245,3 +250,49 @@ class Ticket(CommonModelMixin, OrgModelMixin):
def body(self):
_body = self.handler.get_body()
return _body
def get_serial_num_date(self):
date_created = as_current_tz(self.date_created)
date = date_created.strftime('%Y%m%d')
return date
def get_last_serail_num(self):
date_created = as_current_tz(self.date_created)
date_prefix = date_created.strftime('%Y%m%d')
ticket = Ticket.objects.select_for_update().filter(
serial_num__startswith=date_prefix
).order_by('-date_created').first()
if ticket:
# 202212010001
num_str = ticket.serial_num[8:]
num = int(num_str)
return num
return None
def get_next_serail_num(self):
num = self.get_last_serail_num()
if num is None:
num = 0
return '%04d' % (num + 1)
def construct_serial_num(self):
date_prefix = self.get_serial_num_date()
num_suffix = self.get_next_serail_num()
return date_prefix + num_suffix
def update_serial_num_if_need(self):
if self.serial_num:
return
try:
self.serial_num = self.construct_serial_num()
self.save(update_fields=('serial_num',))
except IntegrityError as e:
if e.args[0] == 1062:
# 虽然做了 `select_for_update` 但是每天的第一条工单仍可能造成冲突
# 但概率小,这里只报错,用户重新提交即可
raise JMSException(detail=_('Please try again'), code='please_try_again')
raise e

View File

@ -28,7 +28,8 @@ class TicketSerializer(OrgResourceModelSerializerMixin):
fields_small = fields_mini + [
'type', 'type_display', 'meta', 'state', 'approval_step',
'status', 'status_display', 'applicant_display', 'process_map',
'date_created', 'date_updated', 'comment', 'org_id', 'org_name', 'body'
'date_created', 'date_updated', 'comment', 'org_id', 'org_name', 'body',
'serial_num',
]
fields_fk = ['applicant', ]
fields = fields_small + fields_fk

View File

@ -1,10 +1,10 @@
# -*- coding: utf-8 -*-
#
from django.dispatch import receiver
from django.db.models.signals import post_save
from common.utils import get_logger
from tickets.models import Ticket, ApprovalRule
from ..signals import post_change_ticket_action, post_or_update_change_ticket_flow_approval
from tickets.models import Ticket
from ..signals import post_change_ticket_action
logger = get_logger(__name__)
@ -12,3 +12,8 @@ logger = get_logger(__name__)
@receiver(post_change_ticket_action, sender=Ticket)
def on_post_change_ticket_action(sender, ticket, action, **kwargs):
ticket.handler.dispatch(action)
@receiver(post_save, sender=Ticket)
def on_pre_save_ensure_serial_num(sender, instance: Ticket, **kwargs):
instance.update_serial_num_if_need()