# coding=utf-8 from django.utils import timezone from django.conf import settings from django.db import models from apps.log.models import BizLog from apps.tenant import tenant_log from apps.tenant.models import Tenant from apps.upload.models import Upload from utils.exceptions import CustomError from apps.tenant.option.models import Option from utils.format import strftime, strfsecond from apps.account.models import User from apps.tenant.device.models import DeviceModel class RepairOrder(models.Model): REPAIR_ORDER = 1 INSPECTION_ORDER = 2 ORDER_TYPE = ( (REPAIR_ORDER, '报修工单'), (INSPECTION_ORDER, '巡检转报修工单') ) NOT_CHECKED = 1 CHECKED = 2 DISPATCH = 3 HANG_UP = 4 TURN_EMPLOYEE = 5 FINISH = 6 APPRAISE = 7 CANCEL_HANG_UP = 8 INVALID = 9 REPAIR_STATUS_CHOICES = ( (NOT_CHECKED, '待审核'), (CHECKED, '已审核,待派单'), (DISPATCH, '已派单'), (HANG_UP, '已挂起'), (TURN_EMPLOYEE, '转单'), (FINISH, '已完工,待评价'), (APPRAISE, '已评价'), (CANCEL_HANG_UP, '取消挂起,维修中'), (INVALID, '作废'), ) no = models.CharField(max_length=50, verbose_name='单号', blank=True) tenant = models.ForeignKey(Tenant, verbose_name=u'企业', on_delete=models.PROTECT, blank=True) device = models.ForeignKey(DeviceModel, verbose_name='设备', on_delete=models.PROTECT, blank=True, null=True) device_name = models.CharField(max_length=100, verbose_name='设备名称') device_address = models.CharField(max_length=200, verbose_name='设备地址') fault_des = models.CharField(max_length=200, verbose_name='故障描述') repair_type = models.ForeignKey(Option, verbose_name='报修类型', on_delete=models.PROTECT) user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"报修人员", on_delete=models.PROTECT, editable=False) name = models.CharField(max_length=11, verbose_name='报修人员') tel = models.CharField(max_length=11, verbose_name='报修电话') repair_users = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='维修人员', related_name='repair_users',on_delete=models.PROTECT,) status = models.PositiveSmallIntegerField(choices=settings.REPAIR_STATUS_CHOICES, verbose_name=u'状态', default=settings.NOT_CHECKED) order_type = models.PositiveSmallIntegerField(choices=ORDER_TYPE, verbose_name=u'工单类型', default=REPAIR_ORDER) create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True) delete = models.BooleanField(verbose_name='删除', default=False) images = models.ManyToManyField(Upload, verbose_name='图片', blank=True, related_name='images_id') class Meta: db_table = 'repair_order' verbose_name = '报修工单' ordering = ['-create_time'] index_together = ( 'status', 'create_time', ) default_permissions = () permissions = [ ('browse_repair_order', u'查看'), ('add_repair_order', u'添加'), ('delete_repair_order', u'删除'), ('check_repair_order', u'审核'), ('invalid_repair_order', u'作废'), ('dispatch_repair_order', u'派工'), ('rob_repair_order', u'抢单'), ('finish_repair_order', u'完工'), ] def get_no(self): now = timezone.now() no = '%s%d-%s' % ('BX', self.tenant.id, now.strftime('%Y%m%d%H%M%S')) return no @staticmethod def get_instance_by_id(id, tenant): try: id = int(id) except: raise CustomError('无效的报修单ID') instance = RepairOrder.objects.filter(pk=id, tenant=tenant, delete=False).first() if not instance: raise CustomError('未找到对应的报修工单') return instance def hange_up_repair_order(self, user, reason): # 挂起 if not self.status == settings.DISPATCH: raise CustomError('当前报修工单不允许挂起!') if user != self.repair_users: raise CustomError('非主修人员操作,禁止操作!') self.status = settings.HANG_UP self.save() RepairOrderRecord.objects.create(repair_order=self, status=settings.HANG_UP, user=user, notes=reason) tenant_log(user.employee, BizLog.INSERT, u'挂起报修工单[%s],id=%d' % (self.no, self.id)) def cancel_hange_up_repair_order(self, user): # 取消挂起 if not self.status == settings.HANG_UP: raise CustomError('当前报修工单非挂起状态!') if user != self.repair_users: raise CustomError('非主修人员操作,禁止操作!') self.status = settings.DISPATCH self.save() RepairOrderRecord.objects.create(repair_order=self, status=settings.CANCEL_HANG_UP, user=user) tenant_log(user.employee, BizLog.INSERT, u'取消挂起报修工单[%s],id=%d' % (self.no, self.id)) def check_repair_order(self, user): # 审核 if self.status > settings.NOT_CHECKED: raise CustomError('当前报修工单状态已审核!') self.status = settings.CHECKED self.save() self.user.employee.baoxiu_count += 1 self.user.employee.save() if self.device: self.device.repair_count += 1 self.device.status = DeviceModel.BAD self.device.save() RepairOrderRecord.objects.create(repair_order=self, status=settings.CHECKED, user=user) tenant_log(user.employee, BizLog.INSERT, u'审核报修工单[%s],id=%d' % (self.no, self.id)) def dispatch_repair_order(self, user, dispacth_users): self.status = settings.DISPATCH self.repair_users_id = dispacth_users self.save() # 记录操作 RepairOrderRecord.objects.create(repair_order=self, status=settings.DISPATCH, user=user, repair_users=dispacth_users) def invalid(self, user): # 作废 if self.status == settings.NOT_CHECKED: raise CustomError('当前报修工单状态未审核,不能进行作废!') if self.status > settings.APPRAISE: raise CustomError('该报修单已作废!') self.status = settings.INVALID self.save() if self.device: self.device.status = DeviceModel.FINE self.device.save() # 记录操作 RepairOrderRecord.objects.create(repair_order=self, status=settings.INVALID, user=user) tenant_log(user.employee, BizLog.UPDATE, u'作废报修工单[%s],id=%d' % (self.no, self.id)) class RepairOrderRecord(models.Model): repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT, related_name='repair_order_record') status = models.PositiveSmallIntegerField(choices=settings.REPAIR_STATUS_CHOICES, verbose_name=u'状态', default=settings.NOT_CHECKED) user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"操作人", on_delete=models.PROTECT, editable=False) notes = models.CharField(max_length=500, verbose_name='备注', null=True) repair_users = models.CharField(max_length=500, verbose_name='维修人员', null=True) operation_time = models.DateTimeField(verbose_name='操作时间', auto_now_add=True) class Meta: db_table = 'repair_order_record' verbose_name = '维修工单记录' ordering = ['operation_time'] default_permissions = () def get_records(self, order_id): dict = { 'status': self.status, 'status_text': settings.REPAIR_STATUS_CHOICES[self.status - 1][1], 'operation_time': strftime(self.operation_time), 'images': [], } user_name = self.user.employee.name if self.status == settings.NOT_CHECKED: dict['no'] = self.repair_order.no dict['desc'] = u'下单人:{}-{}'.format(self.repair_order.name, self.repair_order.tel) dict['tel'] = self.repair_order.tel # images = self.repair_order.images.all() # for img in images: # if img.type != Upload.REPAIR_VOICE: # dict['images'].append( # { # 'url': img.picture # } # ) elif self.status == settings.CHECKED: dict['desc'] = u'审核人:{}'.format(user_name) elif self.status == settings.DISPATCH: repair_users = User.objects.filter(id=self.repair_users).values('employee__name', 'employee__tel', ) e_name = [u'{0}-{1}'.format(e['employee__name'], e['employee__tel']) for e in repair_users] if str(self.user.id) == self.repair_users: desc = u'维修工【{0}】接单'.format(','.join(e_name)) if self.repair_order.order_type == RepairOrder.INSPECTION_ORDER: desc = u'维修工【{0}】巡检转维修接单'.format(','.join(e_name)) else: desc = u'【{0}】派单给维修工【{1}】'.format(user_name, ','.join(e_name)) dict['desc'] = desc dict['employees'] = [{'name': e['employee__name'], 'tel': e['employee__tel']} for e in repair_users] elif self.status == settings.HANG_UP: dict['desc'] = u'挂起原因:{}'.format(self.notes) elif self.status == settings.FINISH: dispatch_time = RepairOrderRecord.objects.filter(repair_order_id=order_id, status=settings.DISPATCH).order_by('operation_time').first() diff_time = self.operation_time - dispatch_time.operation_time hang_up = RepairOrderRecord.objects.filter(repair_order_id=order_id, status=settings.HANG_UP).first() if hang_up: cancel_hang_up = RepairOrderRecord.objects.filter(repair_order_id=order_id, status=settings.CANCEL_HANG_UP).first() if cancel_hang_up: # 挂起时间 hang_up_time = cancel_hang_up.operation_time - hang_up.operation_time diff_time = diff_time - hang_up_time desc = u'维修工【{0}】完工,共用时:{1}天{2}'.format(user_name, diff_time.days, strfsecond(diff_time.seconds)) dict['desc'] = desc order_finish = RepairOrderFinish.objects.filter(repair_order=order_id).first() dict['fault_cause'] = order_finish.fault_cause.name dict['content'] = order_finish.content dict['images'] = [] images = order_finish.images.all() for img in images: if img.type != Upload.REPAIR_VOICE: dict['images'].append( { 'url': img.picture } ) elif self.status == settings.TURN_EMPLOYEE: e_name = User.objects.filter(id=self.repair_users).values('employee__name', 'employee__tel', ) e_name = [e['employee__name'] + '-' + e['employee__tel'] for e in e_name] desc = u'【{0}】转单给维修工【{1}】'.format(user_name, ','.join(e_name)) dict['desc'] = desc elif self.status == settings.APPRAISE: comment = RepairOrderComment.objects.filter(repair_order_id=order_id).first() if comment: dict['desc'] = u'评价内容:{0}'.format(comment.content) dict['start'] = comment.start else: dict['desc'] = '' return dict class RepairOrderComment(models.Model): repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT, related_name='repair_order_comment') content = models.CharField(max_length=200, verbose_name='评价内容') user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"评价人", on_delete=models.PROTECT, related_name='comment_user', editable=False) repair_user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"维修人", on_delete=models.PROTECT, related_name='comment_repair_user',editable=False) start = models.PositiveSmallIntegerField(verbose_name='评分', default=5) create_time = models.DateTimeField(verbose_name='评价时间', auto_now_add=True) class Meta: db_table = 'repair_order_comment' verbose_name = '维修工单评价' default_permissions = () class RepairOrderFinish(models.Model): repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT) fault_cause = models.ForeignKey(Option, verbose_name=u'故障原因', on_delete=models.PROTECT) quality_date = models.DateField(verbose_name=u'质保到期', null=True) content = models.CharField(verbose_name=u'完工内容', max_length=500, null=True) images = models.ManyToManyField(Upload, verbose_name='图片', blank=True) class Meta: db_table = 'repair_order_finish' verbose_name = '维修完工' ordering = ['-id'] default_permissions = ()