models.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. # coding=utf-8
  2. from django.utils import timezone
  3. from django.conf import settings
  4. from django.db import models
  5. from apps.log.models import BizLog
  6. from apps.tenant import tenant_log
  7. from apps.tenant.models import Tenant
  8. from apps.upload.models import Upload
  9. from utils.exceptions import CustomError
  10. from apps.tenant.option.models import Option
  11. from utils.format import strftime, strfsecond
  12. from apps.account.models import User
  13. from apps.tenant.device.models import DeviceModel
  14. class RepairOrder(models.Model):
  15. REPAIR_ORDER = 1
  16. INSPECTION_ORDER = 2
  17. ORDER_TYPE = (
  18. (REPAIR_ORDER, '报修工单'),
  19. (INSPECTION_ORDER, '巡检转报修工单')
  20. )
  21. NOT_CHECKED = 1
  22. CHECKED = 2
  23. DISPATCH = 3
  24. HANG_UP = 4
  25. TURN_EMPLOYEE = 5
  26. FINISH = 6
  27. APPRAISE = 7
  28. CANCEL_HANG_UP = 8
  29. INVALID = 9
  30. REPAIR_STATUS_CHOICES = (
  31. (NOT_CHECKED, '待审核'),
  32. (CHECKED, '已审核,待派单'),
  33. (DISPATCH, '已派单'),
  34. (HANG_UP, '已挂起'),
  35. (TURN_EMPLOYEE, '转单'),
  36. (FINISH, '已完工,待评价'),
  37. (APPRAISE, '已评价'),
  38. (CANCEL_HANG_UP, '取消挂起,维修中'),
  39. (INVALID, '作废'),
  40. )
  41. no = models.CharField(max_length=50, verbose_name='单号', blank=True)
  42. tenant = models.ForeignKey(Tenant, verbose_name=u'企业', on_delete=models.PROTECT, blank=True)
  43. device = models.ForeignKey(DeviceModel, verbose_name='设备', on_delete=models.PROTECT, blank=True, null=True)
  44. device_name = models.CharField(max_length=100, verbose_name='设备名称')
  45. device_address = models.CharField(max_length=200, verbose_name='设备地址')
  46. fault_des = models.CharField(max_length=200, verbose_name='故障描述')
  47. repair_type = models.ForeignKey(Option, verbose_name='报修类型', on_delete=models.PROTECT)
  48. user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"报修人员", on_delete=models.PROTECT,
  49. editable=False)
  50. name = models.CharField(max_length=11, verbose_name='报修人员')
  51. tel = models.CharField(max_length=11, verbose_name='报修电话')
  52. repair_users = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='维修人员', related_name='repair_users',on_delete=models.PROTECT,)
  53. status = models.PositiveSmallIntegerField(choices=settings.REPAIR_STATUS_CHOICES, verbose_name=u'状态',
  54. default=settings.NOT_CHECKED)
  55. order_type = models.PositiveSmallIntegerField(choices=ORDER_TYPE, verbose_name=u'工单类型',
  56. default=REPAIR_ORDER)
  57. create_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
  58. delete = models.BooleanField(verbose_name='删除', default=False)
  59. images = models.ManyToManyField(Upload, verbose_name='图片', blank=True, related_name='images_id')
  60. class Meta:
  61. db_table = 'repair_order'
  62. verbose_name = '报修工单'
  63. ordering = ['-create_time']
  64. index_together = (
  65. 'status',
  66. 'create_time',
  67. )
  68. default_permissions = ()
  69. permissions = [
  70. ('browse_repair_order', u'查看'),
  71. ('add_repair_order', u'添加'),
  72. ('delete_repair_order', u'删除'),
  73. ('check_repair_order', u'审核'),
  74. ('invalid_repair_order', u'作废'),
  75. ('dispatch_repair_order', u'派工'),
  76. ('rob_repair_order', u'抢单'),
  77. ('finish_repair_order', u'完工'),
  78. ]
  79. def get_no(self):
  80. now = timezone.now()
  81. no = '%s%d-%s' % ('BX', self.tenant.id, now.strftime('%Y%m%d%H%M%S'))
  82. return no
  83. @staticmethod
  84. def get_instance_by_id(id, tenant):
  85. try:
  86. id = int(id)
  87. except:
  88. raise CustomError('无效的报修单ID')
  89. instance = RepairOrder.objects.filter(pk=id, tenant=tenant, delete=False).first()
  90. if not instance:
  91. raise CustomError('未找到对应的报修工单')
  92. return instance
  93. def hange_up_repair_order(self, user, reason):
  94. # 挂起
  95. if not self.status == settings.DISPATCH:
  96. raise CustomError('当前报修工单不允许挂起!')
  97. if user != self.repair_users:
  98. raise CustomError('非主修人员操作,禁止操作!')
  99. self.status = settings.HANG_UP
  100. self.save()
  101. RepairOrderRecord.objects.create(repair_order=self, status=settings.HANG_UP, user=user, notes=reason)
  102. tenant_log(user.employee, BizLog.INSERT, u'挂起报修工单[%s],id=%d' % (self.no, self.id))
  103. def cancel_hange_up_repair_order(self, user):
  104. # 取消挂起
  105. if not self.status == settings.HANG_UP:
  106. raise CustomError('当前报修工单非挂起状态!')
  107. if user != self.repair_users:
  108. raise CustomError('非主修人员操作,禁止操作!')
  109. self.status = settings.DISPATCH
  110. self.save()
  111. RepairOrderRecord.objects.create(repair_order=self, status=settings.CANCEL_HANG_UP, user=user)
  112. tenant_log(user.employee, BizLog.INSERT, u'取消挂起报修工单[%s],id=%d' % (self.no, self.id))
  113. def check_repair_order(self, user):
  114. # 审核
  115. if self.status > settings.NOT_CHECKED:
  116. raise CustomError('当前报修工单状态已审核!')
  117. self.status = settings.CHECKED
  118. self.save()
  119. self.user.employee.baoxiu_count += 1
  120. self.user.employee.save()
  121. if self.device:
  122. self.device.repair_count += 1
  123. self.device.status = DeviceModel.BAD
  124. self.device.save()
  125. RepairOrderRecord.objects.create(repair_order=self, status=settings.CHECKED, user=user)
  126. tenant_log(user.employee, BizLog.INSERT, u'审核报修工单[%s],id=%d' % (self.no, self.id))
  127. def dispatch_repair_order(self, user, dispacth_users):
  128. self.status = settings.DISPATCH
  129. self.repair_users_id = dispacth_users
  130. self.save()
  131. # 记录操作
  132. RepairOrderRecord.objects.create(repair_order=self, status=settings.DISPATCH, user=user,
  133. repair_users=dispacth_users)
  134. def invalid(self, user):
  135. # 作废
  136. if self.status == settings.NOT_CHECKED:
  137. raise CustomError('当前报修工单状态未审核,不能进行作废!')
  138. if self.status > settings.APPRAISE:
  139. raise CustomError('该报修单已作废!')
  140. self.status = settings.INVALID
  141. self.save()
  142. if self.device:
  143. self.device.status = DeviceModel.FINE
  144. self.device.save()
  145. # 记录操作
  146. RepairOrderRecord.objects.create(repair_order=self, status=settings.INVALID, user=user)
  147. tenant_log(user.employee, BizLog.UPDATE, u'作废报修工单[%s],id=%d' % (self.no, self.id))
  148. class RepairOrderRecord(models.Model):
  149. repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT,
  150. related_name='repair_order_record')
  151. status = models.PositiveSmallIntegerField(choices=settings.REPAIR_STATUS_CHOICES, verbose_name=u'状态',
  152. default=settings.NOT_CHECKED)
  153. user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"操作人", on_delete=models.PROTECT,
  154. editable=False)
  155. notes = models.CharField(max_length=500, verbose_name='备注', null=True)
  156. repair_users = models.CharField(max_length=500, verbose_name='维修人员', null=True)
  157. operation_time = models.DateTimeField(verbose_name='操作时间', auto_now_add=True)
  158. class Meta:
  159. db_table = 'repair_order_record'
  160. verbose_name = '维修工单记录'
  161. ordering = ['operation_time']
  162. default_permissions = ()
  163. def get_records(self, order_id):
  164. dict = {
  165. 'status': self.status,
  166. 'status_text': settings.REPAIR_STATUS_CHOICES[self.status - 1][1],
  167. 'operation_time': strftime(self.operation_time),
  168. 'images': [],
  169. }
  170. user_name = self.user.employee.name
  171. if self.status == settings.NOT_CHECKED:
  172. dict['no'] = self.repair_order.no
  173. dict['desc'] = u'下单人:{}-{}'.format(self.repair_order.name, self.repair_order.tel)
  174. dict['tel'] = self.repair_order.tel
  175. # images = self.repair_order.images.all()
  176. # for img in images:
  177. # if img.type != Upload.REPAIR_VOICE:
  178. # dict['images'].append(
  179. # {
  180. # 'url': img.picture
  181. # }
  182. # )
  183. elif self.status == settings.CHECKED:
  184. dict['desc'] = u'审核人:{}'.format(user_name)
  185. elif self.status == settings.DISPATCH:
  186. repair_users = User.objects.filter(id=self.repair_users).values('employee__name', 'employee__tel', )
  187. e_name = [u'{0}-{1}'.format(e['employee__name'], e['employee__tel']) for e in repair_users]
  188. if str(self.user.id) == self.repair_users:
  189. desc = u'维修工【{0}】接单'.format(','.join(e_name))
  190. if self.repair_order.order_type == RepairOrder.INSPECTION_ORDER:
  191. desc = u'维修工【{0}】巡检转维修接单'.format(','.join(e_name))
  192. else:
  193. desc = u'【{0}】派单给维修工【{1}】'.format(user_name, ','.join(e_name))
  194. dict['desc'] = desc
  195. dict['employees'] = [{'name': e['employee__name'], 'tel': e['employee__tel']} for e in repair_users]
  196. elif self.status == settings.HANG_UP:
  197. dict['desc'] = u'挂起原因:{}'.format(self.notes)
  198. elif self.status == settings.FINISH:
  199. dispatch_time = RepairOrderRecord.objects.filter(repair_order_id=order_id,
  200. status=settings.DISPATCH).order_by('operation_time').first()
  201. diff_time = self.operation_time - dispatch_time.operation_time
  202. hang_up = RepairOrderRecord.objects.filter(repair_order_id=order_id, status=settings.HANG_UP).first()
  203. if hang_up:
  204. cancel_hang_up = RepairOrderRecord.objects.filter(repair_order_id=order_id,
  205. status=settings.CANCEL_HANG_UP).first()
  206. if cancel_hang_up:
  207. # 挂起时间
  208. hang_up_time = cancel_hang_up.operation_time - hang_up.operation_time
  209. diff_time = diff_time - hang_up_time
  210. desc = u'维修工【{0}】完工,共用时:{1}天{2}'.format(user_name, diff_time.days, strfsecond(diff_time.seconds))
  211. dict['desc'] = desc
  212. order_finish = RepairOrderFinish.objects.filter(repair_order=order_id).first()
  213. dict['fault_cause'] = order_finish.fault_cause.name
  214. dict['content'] = order_finish.content
  215. dict['images'] = []
  216. images = order_finish.images.all()
  217. for img in images:
  218. if img.type != Upload.REPAIR_VOICE:
  219. dict['images'].append(
  220. {
  221. 'url': img.picture
  222. }
  223. )
  224. elif self.status == settings.TURN_EMPLOYEE:
  225. e_name = User.objects.filter(id=self.repair_users).values('employee__name', 'employee__tel', )
  226. e_name = [e['employee__name'] + '-' + e['employee__tel'] for e in e_name]
  227. desc = u'【{0}】转单给维修工【{1}】'.format(user_name, ','.join(e_name))
  228. dict['desc'] = desc
  229. elif self.status == settings.APPRAISE:
  230. comment = RepairOrderComment.objects.filter(repair_order_id=order_id).first()
  231. if comment:
  232. dict['desc'] = u'评价内容:{0}'.format(comment.content)
  233. dict['start'] = comment.start
  234. else:
  235. dict['desc'] = ''
  236. return dict
  237. class RepairOrderComment(models.Model):
  238. repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT,
  239. related_name='repair_order_comment')
  240. content = models.CharField(max_length=200, verbose_name='评价内容')
  241. user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"评价人", on_delete=models.PROTECT,
  242. related_name='comment_user', editable=False)
  243. repair_user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=u"维修人", on_delete=models.PROTECT,
  244. related_name='comment_repair_user',editable=False)
  245. start = models.PositiveSmallIntegerField(verbose_name='评分', default=5)
  246. create_time = models.DateTimeField(verbose_name='评价时间', auto_now_add=True)
  247. class Meta:
  248. db_table = 'repair_order_comment'
  249. verbose_name = '维修工单评价'
  250. default_permissions = ()
  251. class RepairOrderFinish(models.Model):
  252. repair_order = models.ForeignKey(RepairOrder, verbose_name='报修工单', on_delete=models.PROTECT)
  253. fault_cause = models.ForeignKey(Option, verbose_name=u'故障原因', on_delete=models.PROTECT)
  254. quality_date = models.DateField(verbose_name=u'质保到期', null=True)
  255. content = models.CharField(verbose_name=u'完工内容', max_length=500, null=True)
  256. images = models.ManyToManyField(Upload, verbose_name='图片', blank=True)
  257. class Meta:
  258. db_table = 'repair_order_finish'
  259. verbose_name = '维修完工'
  260. ordering = ['-id']
  261. default_permissions = ()