@@ -1,4 +1,5 @@ |
||
| 1 | 1 |
*.db |
| 2 |
+*.rdb |
|
| 2 | 3 |
*.swp |
| 3 | 4 |
*.idea |
| 4 | 5 |
*.sqlite3 |
@@ -0,0 +1,33 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.conf import settings |
|
| 4 |
+from django.contrib import admin |
|
| 5 |
+from django.contrib.auth.hashers import make_password |
|
| 6 |
+from pysnippets.strsnippets import strip |
|
| 7 |
+ |
|
| 8 |
+from account.models import AdministratorInfo |
|
| 9 |
+from equipment.models import IsolationPointInfo |
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+class AdministratorInfoAdmin(admin.ModelAdmin): |
|
| 13 |
+ list_display = ('admin_id', 'phone', 'password', 'encryption', 'name', 'point_id', 'point_name', 'user_status', 'status', 'created_at', 'updated_at')
|
|
| 14 |
+ list_filter = ('user_status', 'status', 'point_name')
|
|
| 15 |
+ readonly_fields = ('encryption', 'point_name')
|
|
| 16 |
+ |
|
| 17 |
+ def save_model(self, request, obj, form, change): |
|
| 18 |
+ obj.phone = strip(obj.phone) |
|
| 19 |
+ obj.password = strip(obj.password) |
|
| 20 |
+ if obj.password: |
|
| 21 |
+ obj.encryption = make_password(obj.password, settings.MAKE_PASSWORD_SALT, settings.MAKE_PASSWORD_HASHER) |
|
| 22 |
+ obj.password = '' |
|
| 23 |
+ |
|
| 24 |
+ obj.point_id = strip(obj.point_id) |
|
| 25 |
+ try: |
|
| 26 |
+ obj.point_name = IsolationPointInfo.objects.get(point_id=obj.point_id).point_name |
|
| 27 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 28 |
+ obj.point_name = '' |
|
| 29 |
+ |
|
| 30 |
+ obj.save() |
|
| 31 |
+ |
|
| 32 |
+ |
|
| 33 |
+admin.site.register(AdministratorInfo, AdministratorInfoAdmin) |
@@ -0,0 +1,5 @@ |
||
| 1 |
+from django.apps import AppConfig |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+class AccountConfig(AppConfig): |
|
| 5 |
+ name = 'account' |
@@ -0,0 +1,36 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 01:41 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+import shortuuidfield.fields |
|
| 5 |
+ |
|
| 6 |
+ |
|
| 7 |
+class Migration(migrations.Migration): |
|
| 8 |
+ |
|
| 9 |
+ initial = True |
|
| 10 |
+ |
|
| 11 |
+ dependencies = [ |
|
| 12 |
+ ] |
|
| 13 |
+ |
|
| 14 |
+ operations = [ |
|
| 15 |
+ migrations.CreateModel( |
|
| 16 |
+ name='AdministratorInfo', |
|
| 17 |
+ fields=[ |
|
| 18 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 19 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 20 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 21 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 22 |
+ ('admin_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='管理员唯一标识', max_length=22, null=True, unique=True)),
|
|
| 23 |
+ ('phone', models.CharField(blank=True, db_index=True, help_text='管理员电话', max_length=11, null=True, verbose_name='phone')),
|
|
| 24 |
+ ('password', models.CharField(blank=True, help_text='管理员密码', max_length=255, null=True, verbose_name='password')),
|
|
| 25 |
+ ('encryption', models.CharField(blank=True, help_text='管理员密码', max_length=255, null=True, verbose_name='encryption')),
|
|
| 26 |
+ ('name', models.CharField(blank=True, help_text='管理员姓名', max_length=255, null=True, verbose_name='name')),
|
|
| 27 |
+ ('point_id', models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id')),
|
|
| 28 |
+ ('point_name', models.CharField(blank=True, help_text='隔离点名称', max_length=255, null=True, verbose_name='point_name')),
|
|
| 29 |
+ ('user_status', models.IntegerField(choices=[(1, '已激活'), (2, '已禁用'), (3, '已删除')], db_index=True, default=1, help_text='管理员状态', verbose_name='user_status')),
|
|
| 30 |
+ ], |
|
| 31 |
+ options={
|
|
| 32 |
+ 'verbose_name': '管理员信息', |
|
| 33 |
+ 'verbose_name_plural': '管理员信息', |
|
| 34 |
+ }, |
|
| 35 |
+ ), |
|
| 36 |
+ ] |
@@ -0,0 +1,49 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.db import models |
|
| 4 |
+from django.utils.translation import ugettext_lazy as _ |
|
| 5 |
+from django_models_ext import BaseModelMixin |
|
| 6 |
+from shortuuidfield import ShortUUIDField |
|
| 7 |
+ |
|
| 8 |
+from equipment.models import IsolationPointInfo |
|
| 9 |
+ |
|
| 10 |
+ |
|
| 11 |
+class AdministratorInfo(BaseModelMixin): |
|
| 12 |
+ ACTIVATED = 1 |
|
| 13 |
+ DISABLED = 2 |
|
| 14 |
+ DELETED = 3 |
|
| 15 |
+ |
|
| 16 |
+ USER_STATUS_TUPLE = ( |
|
| 17 |
+ (ACTIVATED, '已激活'), |
|
| 18 |
+ (DISABLED, '已禁用'), |
|
| 19 |
+ (DELETED, '已删除'), |
|
| 20 |
+ ) |
|
| 21 |
+ |
|
| 22 |
+ admin_id = ShortUUIDField(_('admin_id'), max_length=32, blank=True, null=True, help_text='管理员唯一标识', db_index=True, unique=True)
|
|
| 23 |
+ |
|
| 24 |
+ phone = models.CharField(_('phone'), max_length=11, blank=True, null=True, help_text='管理员电话', db_index=True)
|
|
| 25 |
+ password = models.CharField(_('password'), max_length=255, blank=True, null=True, help_text='管理员密码')
|
|
| 26 |
+ encryption = models.CharField(_('encryption'), max_length=255, blank=True, null=True, help_text='管理员密码')
|
|
| 27 |
+ |
|
| 28 |
+ name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='管理员姓名')
|
|
| 29 |
+ |
|
| 30 |
+ point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
|
|
| 31 |
+ point_name = models.CharField(_('point_name'), max_length=255, blank=True, null=True, help_text='隔离点名称')
|
|
| 32 |
+ |
|
| 33 |
+ user_status = models.IntegerField(_('user_status'), choices=USER_STATUS_TUPLE, default=ACTIVATED, help_text='管理员状态', db_index=True)
|
|
| 34 |
+ |
|
| 35 |
+ class Meta: |
|
| 36 |
+ verbose_name = _('管理员信息')
|
|
| 37 |
+ verbose_name_plural = _('管理员信息')
|
|
| 38 |
+ |
|
| 39 |
+ def __unicode__(self): |
|
| 40 |
+ return '{}-{}'.format(self.name, self.phone)
|
|
| 41 |
+ |
|
| 42 |
+ @property |
|
| 43 |
+ def data(self): |
|
| 44 |
+ return {
|
|
| 45 |
+ 'admin_id': self.admin_id, |
|
| 46 |
+ 'name': self.name, |
|
| 47 |
+ 'point_id': self.point_id, |
|
| 48 |
+ 'point_name': self.point_name, |
|
| 49 |
+ } |
@@ -0,0 +1,4 @@ |
||
| 1 |
+from django.test import TestCase |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+# Create your tests here. |
@@ -0,0 +1,4 @@ |
||
| 1 |
+from django.shortcuts import render |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+# Create your views here. |
@@ -0,0 +1,41 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+from django.conf import settings |
|
| 6 |
+from django.contrib.auth.hashers import check_password |
|
| 7 |
+from django_logit import logit |
|
| 8 |
+from django_response import response |
|
| 9 |
+ |
|
| 10 |
+from account.models import AdministratorInfo |
|
| 11 |
+from equipment.models import IsolationPointInfo |
|
| 12 |
+from utils.error.errno_utils import AdministratorStatusCode, IsolationPointStatusCode |
|
| 13 |
+ |
|
| 14 |
+ |
|
| 15 |
+WECHAT = settings.WECHAT |
|
| 16 |
+ |
|
| 17 |
+ |
|
| 18 |
+@logit |
|
| 19 |
+def admin_login(request): |
|
| 20 |
+ phone = request.POST.get('phone', '')
|
|
| 21 |
+ password = request.POST.get('password', '')
|
|
| 22 |
+ |
|
| 23 |
+ try: |
|
| 24 |
+ administrator = AdministratorInfo.objects.get(phone=phone, status=True) |
|
| 25 |
+ except AdministratorInfo.DoesNotExist: |
|
| 26 |
+ return response(AdministratorStatusCode.ADMINISTRATOR_NOT_FOUND) |
|
| 27 |
+ |
|
| 28 |
+ if administrator.user_status == AdministratorInfo.DISABLED: |
|
| 29 |
+ return response(AdministratorStatusCode.ADMINISTRATOR_NOT_ACTIVATED) |
|
| 30 |
+ elif administrator.user_status == AdministratorInfo.DELETED: |
|
| 31 |
+ return response(AdministratorStatusCode.ADMINISTRATOR_HAS_DELETED) |
|
| 32 |
+ |
|
| 33 |
+ if not check_password(password, administrator.encryption): |
|
| 34 |
+ return response(AdministratorStatusCode.ADMINISTRATOR_PASSWORD_ERROR) |
|
| 35 |
+ |
|
| 36 |
+ try: |
|
| 37 |
+ point = IsolationPointInfo.objects.get(point_id=administrator.point_id, status=True) |
|
| 38 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 39 |
+ return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND) |
|
| 40 |
+ |
|
| 41 |
+ return response(200, 'Admin Login Success', '管理员登录成功', data={**administrator.data, **point.data})
|
@@ -0,0 +1,121 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+from django.db.models import Q |
|
| 6 |
+from django_logit import logit |
|
| 7 |
+from django_response import response |
|
| 8 |
+from TimeConvert import TimeConvert as tc |
|
| 9 |
+ |
|
| 10 |
+from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo, |
|
| 11 |
+ ThermometerMeasureLogInfo) |
|
| 12 |
+from utils.error.errno_utils import IsolationPointStatusCode, ThermometerEquipmentStatusCode |
|
| 13 |
+ |
|
| 14 |
+ |
|
| 15 |
+@logit |
|
| 16 |
+def eqpt_bind(request): |
|
| 17 |
+ point_id = request.POST.get('point_id', '')
|
|
| 18 |
+ macid = request.POST.get('macid', '')
|
|
| 19 |
+ sn = request.POST.get('sn', '')
|
|
| 20 |
+ |
|
| 21 |
+ ThermometerEquipmentInfo.objects.update_or_create(macid=macid, defaults={
|
|
| 22 |
+ 'point_id': point_id, |
|
| 23 |
+ 'sn': sn, |
|
| 24 |
+ }) |
|
| 25 |
+ |
|
| 26 |
+ return response() |
|
| 27 |
+ |
|
| 28 |
+ |
|
| 29 |
+@logit |
|
| 30 |
+def eqpt_onoff(request): |
|
| 31 |
+ macid = request.POST.get('macid', '')
|
|
| 32 |
+ active = request.POST.get('active', 0)
|
|
| 33 |
+ |
|
| 34 |
+ ThermometerEquipmentInfo.objects.update_or_create(macid=macid, defaults={
|
|
| 35 |
+ 'active_status': active, |
|
| 36 |
+ 'active_at': tc.utc_datetime(), |
|
| 37 |
+ }) |
|
| 38 |
+ |
|
| 39 |
+ return response() |
|
| 40 |
+ |
|
| 41 |
+ |
|
| 42 |
+@logit |
|
| 43 |
+def eqpt_list(request): |
|
| 44 |
+ point_id = request.POST.get('point_id', '')
|
|
| 45 |
+ macid = request.POST.get('macid', '')
|
|
| 46 |
+ |
|
| 47 |
+ eqpts = ThermometerEquipmentInfo.objects.filter(point_id=point_id, status=True) |
|
| 48 |
+ if macid: |
|
| 49 |
+ eqpts = eqpts.filter(macid=macid) |
|
| 50 |
+ eqpts = [eqpt.data for eqpt in eqpts] |
|
| 51 |
+ |
|
| 52 |
+ total_num = len(eqpts) |
|
| 53 |
+ active_num = len([1 for eqpt in eqpts if eqpt.get('active_status') == ThermometerEquipmentInfo.ONLINE])
|
|
| 54 |
+ |
|
| 55 |
+ return response(data={
|
|
| 56 |
+ 'eqpts': eqpts, |
|
| 57 |
+ 'total_num': total_num, |
|
| 58 |
+ 'active_num': active_num, |
|
| 59 |
+ 'unactive_num': total_num - active_num, |
|
| 60 |
+ }) |
|
| 61 |
+ |
|
| 62 |
+ |
|
| 63 |
+@logit |
|
| 64 |
+def eqpt_result(request): |
|
| 65 |
+ point_id = request.POST.get('point_id', '')
|
|
| 66 |
+ kw = request.POST.get('kw', '')
|
|
| 67 |
+ |
|
| 68 |
+ try: |
|
| 69 |
+ point = IsolationPointInfo.objects.get(point_id=point_id, status=True) |
|
| 70 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 71 |
+ return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND) |
|
| 72 |
+ |
|
| 73 |
+ logs = ThermometerMeasureInfo.objects.filter(point_id=point_id, point_measure_ymd=tc.local_string(format='%Y-%m-%d'), point_measure_window=point.point_measure_window, status=True).order_by('-pk')
|
|
| 74 |
+ |
|
| 75 |
+ eqpts = ThermometerEquipmentInfo.objects.filter(point_id=point_id, active_status=ThermometerEquipmentInfo.ONLINE, status=True) |
|
| 76 |
+ if kw: |
|
| 77 |
+ eqpts = eqpts.filter(Q(name__icontains=kw) | Q(phone__icontains=kw)) |
|
| 78 |
+ eqpts = [eqpt.data for eqpt in eqpts] |
|
| 79 |
+ |
|
| 80 |
+ return response(data={
|
|
| 81 |
+ 'eqpts': eqpts, |
|
| 82 |
+ }) |
|
| 83 |
+ |
|
| 84 |
+ |
|
| 85 |
+@logit |
|
| 86 |
+def upload_temperature(request): |
|
| 87 |
+ macid = request.POST.get('macid', '')
|
|
| 88 |
+ name = request.POST.get('name', '')
|
|
| 89 |
+ sex = request.POST.get('sex', 0)
|
|
| 90 |
+ age = request.POST.get('age', 0)
|
|
| 91 |
+ phone = request.POST.get('phone', '')
|
|
| 92 |
+ temperature = request.POST.get('temperature', 0)
|
|
| 93 |
+ |
|
| 94 |
+ try: |
|
| 95 |
+ eqpt = ThermometerEquipmentInfo.objects.get(macid=macid, status=True) |
|
| 96 |
+ except ThermometerEquipmentInfo.DoesNotExist: |
|
| 97 |
+ return response(ThermometerEquipmentStatusCode.THERMOMETER_EQUIPMENT_NOT_FOUND) |
|
| 98 |
+ |
|
| 99 |
+ try: |
|
| 100 |
+ point = IsolationPointInfo.objects.get(point_id=eqpt.point_id, status=True) |
|
| 101 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 102 |
+ return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND) |
|
| 103 |
+ |
|
| 104 |
+ point_measure_ymd = tc.local_string(format='%Y-%m-%d') |
|
| 105 |
+ point_measure_window = point.current_measure_window |
|
| 106 |
+ |
|
| 107 |
+ eqpt.name = name |
|
| 108 |
+ eqpt.sex = sex |
|
| 109 |
+ eqpt.age = age |
|
| 110 |
+ eqpt.phone = phone |
|
| 111 |
+ eqpt.last_submit_at = tc.utc_datetime() |
|
| 112 |
+ eqpt.save() |
|
| 113 |
+ |
|
| 114 |
+ ThermometerMeasureLogInfo.objects.create(point_id=eqpt.point_id, macid=macid, temperature=temperature) |
|
| 115 |
+ |
|
| 116 |
+ if point_measure_window: |
|
| 117 |
+ ThermometerMeasureInfo.objects.update_or_create(point_id=eqpt.point_id, point_measure_ymd=point_measure_ymd, point_measure_window=point_measure_window, macid=macid, defaults={
|
|
| 118 |
+ 'temperature': temperature, |
|
| 119 |
+ }) |
|
| 120 |
+ |
|
| 121 |
+ return response() |
@@ -0,0 +1,25 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from __future__ import division |
|
| 4 |
+ |
|
| 5 |
+from django_logit import logit |
|
| 6 |
+from django_response import response |
|
| 7 |
+ |
|
| 8 |
+from equipment.models import IsolationPointInfo |
|
| 9 |
+from utils.error.errno_utils import IsolationPointStatusCode |
|
| 10 |
+ |
|
| 11 |
+ |
|
| 12 |
+@logit |
|
| 13 |
+def measure_window(request): |
|
| 14 |
+ point_id = request.POST.get('point_id', '')
|
|
| 15 |
+ point_measure_window = request.POST.get('point_measure_window', '')
|
|
| 16 |
+ |
|
| 17 |
+ try: |
|
| 18 |
+ point = IsolationPointInfo.objects.get(point_id=point_id, status=True) |
|
| 19 |
+ except IsolationPointInfo.DoesNotExist: |
|
| 20 |
+ return response(IsolationPointStatusCode.ISOLATIONPOINT_NOT_FOUND) |
|
| 21 |
+ |
|
| 22 |
+ point.point_measure_window = point_measure_window |
|
| 23 |
+ point.save() |
|
| 24 |
+ |
|
| 25 |
+ return response() |
@@ -2,7 +2,7 @@ |
||
| 2 | 2 |
|
| 3 | 3 |
from django.conf.urls import url |
| 4 | 4 |
|
| 5 |
-from api import oauth_views |
|
| 5 |
+from api import admin_views, eqpt_views, oauth_views, point_views |
|
| 6 | 6 |
|
| 7 | 7 |
|
| 8 | 8 |
urlpatterns = [ |
@@ -12,3 +12,22 @@ urlpatterns += [ |
||
| 12 | 12 |
url(r'^3rd/or$', oauth_views.oauth_redirect, name='3rd_or'), |
| 13 | 13 |
url(r'^3rd/oauth_redirect$', oauth_views.oauth_redirect, name='3rd_oauth_redirect'), |
| 14 | 14 |
] |
| 15 |
+ |
|
| 16 |
+urlpatterns += [ |
|
| 17 |
+ url(r'^admin/login$', admin_views.admin_login, name='admin_login'), |
|
| 18 |
+] |
|
| 19 |
+ |
|
| 20 |
+urlpatterns += [ |
|
| 21 |
+ url(r'^point/measure_window$', point_views.measure_window, name='measure_window'), |
|
| 22 |
+] |
|
| 23 |
+ |
|
| 24 |
+urlpatterns += [ |
|
| 25 |
+ url(r'^eqpt/bind$', eqpt_views.eqpt_bind, name='eqpt_bind'), |
|
| 26 |
+ url(r'^eqpt/onoff$', eqpt_views.eqpt_onoff, name='eqpt_onoff'), |
|
| 27 |
+ url(r'^eqpt/list$', eqpt_views.eqpt_list, name='eqpt_list'), |
|
| 28 |
+ url(r'^eqpt/result$', eqpt_views.eqpt_result, name='eqpt_result'), |
|
| 29 |
+] |
|
| 30 |
+ |
|
| 31 |
+urlpatterns += [ |
|
| 32 |
+ url(r'^upload/temperature$', eqpt_views.upload_temperature, name='upload_temperature'), |
|
| 33 |
+] |
@@ -0,0 +1,31 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.contrib import admin |
|
| 4 |
+ |
|
| 5 |
+from equipment.models import (IsolationPointInfo, ThermometerEquipmentInfo, ThermometerMeasureInfo, |
|
| 6 |
+ ThermometerMeasureLogInfo) |
|
| 7 |
+ |
|
| 8 |
+ |
|
| 9 |
+class IsolationPointInfoAdmin(admin.ModelAdmin): |
|
| 10 |
+ list_display = ('point_id', 'point_name', 'point_measure_window', 'status', 'updated_at', 'created_at')
|
|
| 11 |
+ |
|
| 12 |
+ |
|
| 13 |
+class ThermometerEquipmentInfoAdmin(admin.ModelAdmin): |
|
| 14 |
+ list_display = ('eqpt_id', 'point_id', 'macid', 'sn', 'active_status', 'active_at', 'name', 'sex', 'age', 'phone', 'remark', 'last_submit_at', 'status', 'updated_at', 'created_at')
|
|
| 15 |
+ list_filter = ('point_id', 'status')
|
|
| 16 |
+ |
|
| 17 |
+ |
|
| 18 |
+class ThermometerMeasureInfoAdmin(admin.ModelAdmin): |
|
| 19 |
+ list_display = ('point_id', 'point_measure_ymd', 'point_measure_window', 'macid', 'sn', 'temperature', 'status', 'updated_at', 'created_at')
|
|
| 20 |
+ list_filter = ('point_id', 'status')
|
|
| 21 |
+ |
|
| 22 |
+ |
|
| 23 |
+class ThermometerMeasureLogInfoAdmin(admin.ModelAdmin): |
|
| 24 |
+ list_display = ('point_id', 'macid', 'sn', 'temperature', 'status', 'updated_at', 'created_at')
|
|
| 25 |
+ list_filter = ('point_id', 'status')
|
|
| 26 |
+ |
|
| 27 |
+ |
|
| 28 |
+admin.site.register(IsolationPointInfo, IsolationPointInfoAdmin) |
|
| 29 |
+admin.site.register(ThermometerEquipmentInfo, ThermometerEquipmentInfoAdmin) |
|
| 30 |
+admin.site.register(ThermometerMeasureInfo, ThermometerMeasureInfoAdmin) |
|
| 31 |
+admin.site.register(ThermometerMeasureLogInfo, ThermometerMeasureLogInfoAdmin) |
@@ -0,0 +1,5 @@ |
||
| 1 |
+from django.apps import AppConfig |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+class AccountConfig(AppConfig): |
|
| 5 |
+ name = 'equipment' |
@@ -0,0 +1,72 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 01:41 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+import jsonfield.fields |
|
| 5 |
+import shortuuidfield.fields |
|
| 6 |
+ |
|
| 7 |
+ |
|
| 8 |
+class Migration(migrations.Migration): |
|
| 9 |
+ |
|
| 10 |
+ initial = True |
|
| 11 |
+ |
|
| 12 |
+ dependencies = [ |
|
| 13 |
+ ] |
|
| 14 |
+ |
|
| 15 |
+ operations = [ |
|
| 16 |
+ migrations.CreateModel( |
|
| 17 |
+ name='IsolationPointInfo', |
|
| 18 |
+ fields=[ |
|
| 19 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 20 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 21 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 22 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 23 |
+ ('point_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='隔离点唯一标识', max_length=22, null=True, unique=True)),
|
|
| 24 |
+ ('point_name', models.CharField(blank=True, help_text='隔离点名称', max_length=255, null=True, verbose_name='point_name')),
|
|
| 25 |
+ ('point_measure_window', jsonfield.fields.JSONField(blank=True, default=[], help_text='隔离点测温时间段', null=True, verbose_name='point_measure_window')),
|
|
| 26 |
+ ], |
|
| 27 |
+ options={
|
|
| 28 |
+ 'verbose_name': '隔离点信息', |
|
| 29 |
+ 'verbose_name_plural': '隔离点信息', |
|
| 30 |
+ }, |
|
| 31 |
+ ), |
|
| 32 |
+ migrations.CreateModel( |
|
| 33 |
+ name='ThermometerEquipmentInfo', |
|
| 34 |
+ fields=[ |
|
| 35 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 36 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 37 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 38 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 39 |
+ ('eqpt_id', shortuuidfield.fields.ShortUUIDField(blank=True, db_index=True, editable=False, help_text='设备唯一标识', max_length=22, null=True, unique=True)),
|
|
| 40 |
+ ('point_id', models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id')),
|
|
| 41 |
+ ('macid', models.CharField(blank=True, help_text='设备号', max_length=255, null=True, verbose_name='macid')),
|
|
| 42 |
+ ('sn', models.CharField(blank=True, help_text='序列号', max_length=255, null=True, verbose_name='sn')),
|
|
| 43 |
+ ('active_status', models.IntegerField(choices=[(1, '已激活'), (0, '已离线')], default=0, help_text='激活状态', verbose_name='active_status')),
|
|
| 44 |
+ ('active_at', models.DateTimeField(blank=True, help_text='激活时间', null=True, verbose_name='active_at')),
|
|
| 45 |
+ ('name', models.CharField(blank=True, help_text='用户姓名', max_length=255, null=True, verbose_name='name')),
|
|
| 46 |
+ ('sex', models.IntegerField(choices=[(0, '未知'), (1, '男'), (2, '女')], default=0, help_text='用户性别', verbose_name='sex')),
|
|
| 47 |
+ ('age', models.IntegerField(default=0, help_text='用户年龄', verbose_name='age')),
|
|
| 48 |
+ ('phone', models.CharField(blank=True, db_index=True, help_text='用户电话', max_length=11, null=True, verbose_name='phone')),
|
|
| 49 |
+ ('remark', models.CharField(blank=True, help_text='备注', max_length=255, null=True, verbose_name='remark')),
|
|
| 50 |
+ ], |
|
| 51 |
+ options={
|
|
| 52 |
+ 'verbose_name': '测温设备信息', |
|
| 53 |
+ 'verbose_name_plural': '测温设备信息', |
|
| 54 |
+ }, |
|
| 55 |
+ ), |
|
| 56 |
+ migrations.CreateModel( |
|
| 57 |
+ name='ThermometerMeasureInfo', |
|
| 58 |
+ fields=[ |
|
| 59 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 60 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 61 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 62 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 63 |
+ ('macid', models.CharField(blank=True, help_text='设备号', max_length=255, null=True, verbose_name='macid')),
|
|
| 64 |
+ ('sn', models.CharField(blank=True, help_text='序列号', max_length=255, null=True, verbose_name='sn')),
|
|
| 65 |
+ ('temperature', models.FloatField(default=0, help_text='用户体温', verbose_name='temperature')),
|
|
| 66 |
+ ], |
|
| 67 |
+ options={
|
|
| 68 |
+ 'verbose_name': '测温记录信息', |
|
| 69 |
+ 'verbose_name_plural': '测温记录信息', |
|
| 70 |
+ }, |
|
| 71 |
+ ), |
|
| 72 |
+ ] |
@@ -0,0 +1,18 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 04:54 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+ |
|
| 5 |
+ |
|
| 6 |
+class Migration(migrations.Migration): |
|
| 7 |
+ |
|
| 8 |
+ dependencies = [ |
|
| 9 |
+ ('equipment', '0001_initial'),
|
|
| 10 |
+ ] |
|
| 11 |
+ |
|
| 12 |
+ operations = [ |
|
| 13 |
+ migrations.AddField( |
|
| 14 |
+ model_name='thermometermeasureinfo', |
|
| 15 |
+ name='point_id', |
|
| 16 |
+ field=models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id'), |
|
| 17 |
+ ), |
|
| 18 |
+ ] |
@@ -0,0 +1,43 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 05:32 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+ |
|
| 5 |
+ |
|
| 6 |
+class Migration(migrations.Migration): |
|
| 7 |
+ |
|
| 8 |
+ dependencies = [ |
|
| 9 |
+ ('equipment', '0002_thermometermeasureinfo_point_id'),
|
|
| 10 |
+ ] |
|
| 11 |
+ |
|
| 12 |
+ operations = [ |
|
| 13 |
+ migrations.CreateModel( |
|
| 14 |
+ name='ThermometerMeasureLogInfo', |
|
| 15 |
+ fields=[ |
|
| 16 |
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
| 17 |
+ ('status', models.BooleanField(default=True, help_text='Status', verbose_name='status')),
|
|
| 18 |
+ ('created_at', models.DateTimeField(auto_now_add=True, help_text='Create Time', verbose_name='created_at')),
|
|
| 19 |
+ ('updated_at', models.DateTimeField(auto_now=True, help_text='Update Time', verbose_name='updated_at')),
|
|
| 20 |
+ ('point_id', models.CharField(blank=True, db_index=True, help_text='隔离点唯一标识', max_length=32, null=True, verbose_name='point_id')),
|
|
| 21 |
+ ('macid', models.CharField(blank=True, help_text='设备号', max_length=255, null=True, verbose_name='macid')),
|
|
| 22 |
+ ('sn', models.CharField(blank=True, help_text='序列号', max_length=255, null=True, verbose_name='sn')),
|
|
| 23 |
+ ('temperature', models.FloatField(default=0, help_text='用户体温', verbose_name='temperature')),
|
|
| 24 |
+ ], |
|
| 25 |
+ options={
|
|
| 26 |
+ 'verbose_name': '测温记录信息', |
|
| 27 |
+ 'verbose_name_plural': '测温记录信息', |
|
| 28 |
+ }, |
|
| 29 |
+ ), |
|
| 30 |
+ migrations.AlterModelOptions( |
|
| 31 |
+ name='thermometermeasureinfo', |
|
| 32 |
+ options={'verbose_name': '测温信息', 'verbose_name_plural': '测温信息'},
|
|
| 33 |
+ ), |
|
| 34 |
+ migrations.AddField( |
|
| 35 |
+ model_name='thermometermeasureinfo', |
|
| 36 |
+ name='point_measure_window', |
|
| 37 |
+ field=models.CharField(blank=True, db_index=True, help_text='隔离点测温时间段', max_length=16, null=True, verbose_name='point_measure_window'), |
|
| 38 |
+ ), |
|
| 39 |
+ migrations.AlterUniqueTogether( |
|
| 40 |
+ name='thermometermeasureinfo', |
|
| 41 |
+ unique_together={('point_id', 'point_measure_window')},
|
|
| 42 |
+ ), |
|
| 43 |
+ ] |
@@ -0,0 +1,17 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 05:34 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations |
|
| 4 |
+ |
|
| 5 |
+ |
|
| 6 |
+class Migration(migrations.Migration): |
|
| 7 |
+ |
|
| 8 |
+ dependencies = [ |
|
| 9 |
+ ('equipment', '0003_auto_20210709_1332'),
|
|
| 10 |
+ ] |
|
| 11 |
+ |
|
| 12 |
+ operations = [ |
|
| 13 |
+ migrations.AlterUniqueTogether( |
|
| 14 |
+ name='thermometermeasureinfo', |
|
| 15 |
+ unique_together={('point_id', 'point_measure_window', 'macid')},
|
|
| 16 |
+ ), |
|
| 17 |
+ ] |
@@ -0,0 +1,18 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 05:42 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+ |
|
| 5 |
+ |
|
| 6 |
+class Migration(migrations.Migration): |
|
| 7 |
+ |
|
| 8 |
+ dependencies = [ |
|
| 9 |
+ ('equipment', '0004_alter_thermometermeasureinfo_unique_together'),
|
|
| 10 |
+ ] |
|
| 11 |
+ |
|
| 12 |
+ operations = [ |
|
| 13 |
+ migrations.AddField( |
|
| 14 |
+ model_name='thermometerequipmentinfo', |
|
| 15 |
+ name='last_submit_at', |
|
| 16 |
+ field=models.DateTimeField(blank=True, help_text='上一次上报时间', null=True, verbose_name='last_submit_at'), |
|
| 17 |
+ ), |
|
| 18 |
+ ] |
@@ -0,0 +1,22 @@ |
||
| 1 |
+# Generated by Django 3.2.4 on 2021-07-09 05:46 |
|
| 2 |
+ |
|
| 3 |
+from django.db import migrations, models |
|
| 4 |
+ |
|
| 5 |
+ |
|
| 6 |
+class Migration(migrations.Migration): |
|
| 7 |
+ |
|
| 8 |
+ dependencies = [ |
|
| 9 |
+ ('equipment', '0005_thermometerequipmentinfo_last_submit_at'),
|
|
| 10 |
+ ] |
|
| 11 |
+ |
|
| 12 |
+ operations = [ |
|
| 13 |
+ migrations.AddField( |
|
| 14 |
+ model_name='thermometermeasureinfo', |
|
| 15 |
+ name='point_measure_ymd', |
|
| 16 |
+ field=models.CharField(blank=True, db_index=True, help_text='隔离点测温日期', max_length=10, null=True, verbose_name='point_measure_ymd'), |
|
| 17 |
+ ), |
|
| 18 |
+ migrations.AlterUniqueTogether( |
|
| 19 |
+ name='thermometermeasureinfo', |
|
| 20 |
+ unique_together={('point_id', 'point_measure_ymd', 'point_measure_window', 'macid')},
|
|
| 21 |
+ ), |
|
| 22 |
+ ] |
@@ -0,0 +1,157 @@ |
||
| 1 |
+# -*- coding: utf-8 -*- |
|
| 2 |
+ |
|
| 3 |
+from django.db import models |
|
| 4 |
+from django.utils.translation import ugettext_lazy as _ |
|
| 5 |
+from django_models_ext import BaseModelMixin, SexModelMixin |
|
| 6 |
+from jsonfield import JSONField |
|
| 7 |
+from shortuuidfield import ShortUUIDField |
|
| 8 |
+from TimeConvert import TimeConvert as tc |
|
| 9 |
+ |
|
| 10 |
+ |
|
| 11 |
+class IsolationPointInfo(BaseModelMixin): |
|
| 12 |
+ point_id = ShortUUIDField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True, unique=True)
|
|
| 13 |
+ point_name = models.CharField(_('point_name'), max_length=255, blank=True, null=True, help_text='隔离点名称')
|
|
| 14 |
+ # [{"start": "8:00", "end": "9:00"}, {"start": "12:00", "end": "14:00"}]
|
|
| 15 |
+ point_measure_window = JSONField(_('point_measure_window'), default=[], blank=True, null=True, help_text='隔离点测温时间段')
|
|
| 16 |
+ |
|
| 17 |
+ class Meta: |
|
| 18 |
+ verbose_name = _('隔离点信息')
|
|
| 19 |
+ verbose_name_plural = _('隔离点信息')
|
|
| 20 |
+ |
|
| 21 |
+ def __unicode__(self): |
|
| 22 |
+ return '%d' % self.pk |
|
| 23 |
+ |
|
| 24 |
+ @property |
|
| 25 |
+ def data(self): |
|
| 26 |
+ return {
|
|
| 27 |
+ 'point_id': self.point_id, |
|
| 28 |
+ 'point_name': self.point_name, |
|
| 29 |
+ 'point_measure_window': self.point_measure_window, |
|
| 30 |
+ } |
|
| 31 |
+ |
|
| 32 |
+ @property |
|
| 33 |
+ def current_measure_window(self): |
|
| 34 |
+ current_ymd = tc.local_string(format='%Y-%m-%d') |
|
| 35 |
+ current_dt = tc.utc_datetime() |
|
| 36 |
+ for window in self.point_measure_window: |
|
| 37 |
+ start_t, end_t = window.get('start'), window.get('end')
|
|
| 38 |
+ start_dt = tc.string_to_utc_datetime(f'{current_ymd} {start_t}:00')
|
|
| 39 |
+ end_dt = tc.string_to_utc_datetime(f'{current_ymd} {end_t}:00')
|
|
| 40 |
+ if start_dt < current_dt < end_dt: |
|
| 41 |
+ return f'{start_t}-{end_t}'
|
|
| 42 |
+ return '' |
|
| 43 |
+ |
|
| 44 |
+ |
|
| 45 |
+class ThermometerEquipmentInfo(BaseModelMixin): |
|
| 46 |
+ ONLINE = 1 |
|
| 47 |
+ OFFLINE = 0 |
|
| 48 |
+ |
|
| 49 |
+ ACTIVE_STATUE_TUPLE = ( |
|
| 50 |
+ (ONLINE, '已激活'), |
|
| 51 |
+ (OFFLINE, '已离线'), |
|
| 52 |
+ ) |
|
| 53 |
+ |
|
| 54 |
+ eqpt_id = ShortUUIDField(_('eqpt_id'), max_length=32, blank=True, null=True, help_text='设备唯一标识', db_index=True, unique=True)
|
|
| 55 |
+ |
|
| 56 |
+ point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
|
|
| 57 |
+ |
|
| 58 |
+ macid = models.CharField(_('macid'), max_length=255, blank=True, null=True, help_text='设备号')
|
|
| 59 |
+ sn = models.CharField(_('sn'), max_length=255, blank=True, null=True, help_text='序列号')
|
|
| 60 |
+ |
|
| 61 |
+ active_status = models.IntegerField(_('active_status'), choices=ACTIVE_STATUE_TUPLE, default=OFFLINE, help_text='激活状态')
|
|
| 62 |
+ active_at = models.DateTimeField(_('active_at'), blank=True, null=True, help_text=_('激活时间'))
|
|
| 63 |
+ |
|
| 64 |
+ # 用户基本信息 |
|
| 65 |
+ name = models.CharField(_('name'), max_length=255, blank=True, null=True, help_text='用户姓名')
|
|
| 66 |
+ sex = models.IntegerField(_('sex'), choices=SexModelMixin.SEX_TUPLE, default=SexModelMixin.UNKNOWN, help_text='用户性别')
|
|
| 67 |
+ age = models.IntegerField(_('age'), default=0, help_text='用户年龄')
|
|
| 68 |
+ phone = models.CharField(_('phone'), max_length=11, blank=True, null=True, help_text='用户电话', db_index=True)
|
|
| 69 |
+ |
|
| 70 |
+ remark = models.CharField(_('remark'), max_length=255, blank=True, null=True, help_text='备注')
|
|
| 71 |
+ |
|
| 72 |
+ last_submit_at = models.DateTimeField(_('last_submit_at'), blank=True, null=True, help_text=_('上一次上报时间'))
|
|
| 73 |
+ |
|
| 74 |
+ class Meta: |
|
| 75 |
+ verbose_name = _('测温设备信息')
|
|
| 76 |
+ verbose_name_plural = _('测温设备信息')
|
|
| 77 |
+ |
|
| 78 |
+ def __unicode__(self): |
|
| 79 |
+ return '%d' % self.pk |
|
| 80 |
+ |
|
| 81 |
+ @property |
|
| 82 |
+ def data(self): |
|
| 83 |
+ return {
|
|
| 84 |
+ 'eqpt_id': self.eqpt_id, |
|
| 85 |
+ 'point_id': self.point_id, |
|
| 86 |
+ 'macid': self.macid, |
|
| 87 |
+ 'sn': self.sn, |
|
| 88 |
+ 'active_status': self.active_status, |
|
| 89 |
+ 'active_status_str': dict(self.ACTIVE_STATUE_TUPLE).get(self.active_status, ''), |
|
| 90 |
+ 'active_at': tc.local_string(utc_dt=self.active_at), |
|
| 91 |
+ 'name': self.name or '', |
|
| 92 |
+ 'sex': self.sex, |
|
| 93 |
+ 'sex_str': dict(SexModelMixin.SEX_TUPLE).get(self.sex, ''), |
|
| 94 |
+ 'age': self.age or '', |
|
| 95 |
+ 'phone': self.phone or '', |
|
| 96 |
+ 'remark': self.remark or '', |
|
| 97 |
+ 'last_submit_at': tc.local_string(utc_dt=self.last_submit_at), |
|
| 98 |
+ 'created_at': tc.local_string(utc_dt=self.created_at), |
|
| 99 |
+ } |
|
| 100 |
+ |
|
| 101 |
+ |
|
| 102 |
+class ThermometerMeasureInfo(BaseModelMixin): |
|
| 103 |
+ point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
|
|
| 104 |
+ |
|
| 105 |
+ point_measure_ymd = models.CharField(_('point_measure_ymd'), max_length=10, blank=True, null=True, help_text='隔离点测温日期', db_index=True)
|
|
| 106 |
+ point_measure_window = models.CharField(_('point_measure_window'), max_length=16, blank=True, null=True, help_text='隔离点测温时间段', db_index=True)
|
|
| 107 |
+ |
|
| 108 |
+ macid = models.CharField(_('macid'), max_length=255, blank=True, null=True, help_text='设备号')
|
|
| 109 |
+ sn = models.CharField(_('sn'), max_length=255, blank=True, null=True, help_text='序列号')
|
|
| 110 |
+ |
|
| 111 |
+ temperature = models.FloatField(_('temperature'), default=0, help_text='用户体温')
|
|
| 112 |
+ |
|
| 113 |
+ class Meta: |
|
| 114 |
+ verbose_name = _('测温信息')
|
|
| 115 |
+ verbose_name_plural = _('测温信息')
|
|
| 116 |
+ |
|
| 117 |
+ unique_together = ( |
|
| 118 |
+ ('point_id', 'point_measure_ymd', 'point_measure_window', 'macid')
|
|
| 119 |
+ ) |
|
| 120 |
+ |
|
| 121 |
+ def __unicode__(self): |
|
| 122 |
+ return '%d' % self.pk |
|
| 123 |
+ |
|
| 124 |
+ @property |
|
| 125 |
+ def data(self): |
|
| 126 |
+ return {
|
|
| 127 |
+ 'point_id': self.point_id, |
|
| 128 |
+ 'point_measure_window': self.point_measure_window, |
|
| 129 |
+ 'macid': self.macid, |
|
| 130 |
+ 'sn': self.sn, |
|
| 131 |
+ 'temperature': self.temperature, |
|
| 132 |
+ } |
|
| 133 |
+ |
|
| 134 |
+ |
|
| 135 |
+class ThermometerMeasureLogInfo(BaseModelMixin): |
|
| 136 |
+ point_id = models.CharField(_('point_id'), max_length=32, blank=True, null=True, help_text='隔离点唯一标识', db_index=True)
|
|
| 137 |
+ |
|
| 138 |
+ macid = models.CharField(_('macid'), max_length=255, blank=True, null=True, help_text='设备号')
|
|
| 139 |
+ sn = models.CharField(_('sn'), max_length=255, blank=True, null=True, help_text='序列号')
|
|
| 140 |
+ |
|
| 141 |
+ temperature = models.FloatField(_('temperature'), default=0, help_text='用户体温')
|
|
| 142 |
+ |
|
| 143 |
+ class Meta: |
|
| 144 |
+ verbose_name = _('测温记录信息')
|
|
| 145 |
+ verbose_name_plural = _('测温记录信息')
|
|
| 146 |
+ |
|
| 147 |
+ def __unicode__(self): |
|
| 148 |
+ return '%d' % self.pk |
|
| 149 |
+ |
|
| 150 |
+ @property |
|
| 151 |
+ def data(self): |
|
| 152 |
+ return {
|
|
| 153 |
+ 'point_id': self.point_id, |
|
| 154 |
+ 'macid': self.macid, |
|
| 155 |
+ 'sn': self.sn, |
|
| 156 |
+ 'temperature': self.temperature, |
|
| 157 |
+ } |
@@ -0,0 +1,4 @@ |
||
| 1 |
+from django.test import TestCase |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+# Create your tests here. |
@@ -0,0 +1,4 @@ |
||
| 1 |
+from django.shortcuts import render |
|
| 2 |
+ |
|
| 3 |
+ |
|
| 4 |
+# Create your views here. |
@@ -5,21 +5,23 @@ from django.utils.translation import ugettext_lazy as _ |
||
| 5 | 5 |
|
| 6 | 6 |
|
| 7 | 7 |
class BaseModelMixin(models.Model): |
| 8 |
- status = models.BooleanField(_(u'status'), default=True, help_text=_(u'状态')) |
|
| 9 |
- created_at = models.DateTimeField(_(u'created_at'), auto_now_add=True, editable=True, help_text=_(u'创建时间')) |
|
| 10 |
- updated_at = models.DateTimeField(_(u'updated_at'), auto_now=True, editable=True, help_text=_(u'更新时间')) |
|
| 8 |
+ status = models.BooleanField(_('status'), default=True, help_text=_('状态'), db_index=True)
|
|
| 9 |
+ created_at = models.DateTimeField(_('created_at'), auto_now_add=True, editable=True, help_text=_('创建时间'))
|
|
| 10 |
+ updated_at = models.DateTimeField(_('updated_at'), auto_now=True, editable=True, help_text=_('更新时间'))
|
|
| 11 | 11 |
|
| 12 | 12 |
class Meta: |
| 13 | 13 |
abstract = True |
| 14 | 14 |
|
| 15 | 15 |
|
| 16 | 16 |
class SexChoicesMixin(models.Model): |
| 17 |
+ UNKNOWN = 0 |
|
| 17 | 18 |
MALE = 1 |
| 18 |
- FEMALE = 0 |
|
| 19 |
+ FEMALE = 2 |
|
| 19 | 20 |
|
| 20 |
- SEX_TYPE = ( |
|
| 21 |
- (MALE, u'男'), |
|
| 22 |
- (FEMALE, u'女'), |
|
| 21 |
+ SEX_TUPLE = ( |
|
| 22 |
+ (UNKNOWN, '未知'), |
|
| 23 |
+ (MALE, '男'), |
|
| 24 |
+ (FEMALE, '女'), |
|
| 23 | 25 |
) |
| 24 | 26 |
|
| 25 | 27 |
class Meta: |
@@ -14,4 +14,4 @@ EMAIL_HOST_USER = 'error.notify@exmail.com' |
||
| 14 | 14 |
EMAIL_HOST_PASSWORD = '<^_^>pwd<^_^>' |
| 15 | 15 |
DEFAULT_FROM_EMAIL = 'error.notify <error.notify@exmail.com>' |
| 16 | 16 |
ADMINS = [('Zhang San', 'san.zhang@exmail.com'), ('Li Si', 'si.li@exmail.com')]
|
| 17 |
-EMAIL_SUBJECT_PREFIX = u'[Thermometer] ' |
|
| 17 |
+EMAIL_SUBJECT_PREFIX = '[Thermometer] ' |
@@ -55,6 +55,8 @@ INSTALLED_APPS = [ |
||
| 55 | 55 |
'django_we', |
| 56 | 56 |
'commands', |
| 57 | 57 |
'api', |
| 58 |
+ 'account', |
|
| 59 |
+ 'equipment', |
|
| 58 | 60 |
] |
| 59 | 61 |
|
| 60 | 62 |
MIDDLEWARE = [ |
@@ -278,7 +280,7 @@ ADMINS = [] |
||
| 278 | 280 |
MANAGERS = ADMINS |
| 279 | 281 |
# Subject-line prefix for email messages send with django.core.mail.mail_admins |
| 280 | 282 |
# or ...mail_managers. Make sure to include the trailing space. |
| 281 |
-EMAIL_SUBJECT_PREFIX = u'[Thermometer] ' |
|
| 283 |
+EMAIL_SUBJECT_PREFIX = '[Thermometer] ' |
|
| 282 | 284 |
|
| 283 | 285 |
# Django-Admin Settings |
| 284 | 286 |
DJANGO_ADMIN_DISABLE_DELETE_SELECTED = False |
@@ -310,6 +312,10 @@ DJANGO_WE_MODEL_DISPLAY_OR_NOT = True |
||
| 310 | 312 |
DJANGO_WE_COOKIE_MAX_AGE = COOKIE_MAX_AGE |
| 311 | 313 |
DJANGO_WE_COOKIE_SALT = COOKIE_SALT |
| 312 | 314 |
|
| 315 |
+# 密码设置 |
|
| 316 |
+MAKE_PASSWORD_SALT = '' |
|
| 317 |
+MAKE_PASSWORD_HASHER = 'pbkdf2_sha256' |
|
| 318 |
+ |
|
| 313 | 319 |
# 开发调试相关配置 |
| 314 | 320 |
if DEBUG: |
| 315 | 321 |
try: |
@@ -5,32 +5,55 @@ from StatusCode import BaseStatusCode, StatusCodeField |
||
| 5 | 5 |
|
| 6 | 6 |
class ParamStatusCode(BaseStatusCode): |
| 7 | 7 |
""" 4000xx 参数相关错误码 """ |
| 8 |
- PARAM_NOT_FOUND = StatusCodeField(400000, 'Param Not Found', description=u'参数不存在') |
|
| 8 |
+ PARAM_NOT_FOUND = StatusCodeField(400000, 'Param Not Found', description='参数不存在') |
|
| 9 | 9 |
|
| 10 | 10 |
|
| 11 | 11 |
class ProfileStatusCode(BaseStatusCode): |
| 12 | 12 |
""" 4001xx 用户相关错误码 """ |
| 13 |
- PROFILE_NOT_FOUND = StatusCodeField(400101, 'Profile Not Found', description=u'用户不存在') |
|
| 13 |
+ PROFILE_NOT_FOUND = StatusCodeField(400101, 'Profile Not Found', description='用户不存在') |
|
| 14 | 14 |
|
| 15 | 15 |
|
| 16 | 16 |
class PhoneStatusCode(BaseStatusCode): |
| 17 | 17 |
""" 4002xx 手机相关错误码 """ |
| 18 |
- INVALID_PHONE = StatusCodeField(400200, 'Invalid Phone', description=u'非法手机号') |
|
| 19 |
- PHONE_NOT_FOUND = StatusCodeField(400201, 'Phone Not Found', description=u'手机号不存在') |
|
| 20 |
- PHONE_ALREADY_EXISTS = StatusCodeField(400202, 'Phone Already Exists', description=u'手机号已存在') |
|
| 18 |
+ INVALID_PHONE = StatusCodeField(400200, 'Invalid Phone', description='非法手机号') |
|
| 19 |
+ PHONE_NOT_FOUND = StatusCodeField(400201, 'Phone Not Found', description='手机号不存在') |
|
| 20 |
+ PHONE_ALREADY_EXISTS = StatusCodeField(400202, 'Phone Already Exists', description='手机号已存在') |
|
| 21 |
+ |
|
| 22 |
+ |
|
| 23 |
+class AdministratorStatusCode(BaseStatusCode): |
|
| 24 |
+ """ 操作员相关错误码 4010xx """ |
|
| 25 |
+ ADMINISTRATOR_NOT_FOUND = StatusCodeField(401001, 'Administrator Not Found', description='管理员不存在') |
|
| 26 |
+ # 密码 |
|
| 27 |
+ ADMINISTRATOR_PASSWORD_ERROR = StatusCodeField(401002, 'Administrator Password Error', description='管理员密码错误') |
|
| 28 |
+ # 手机号 |
|
| 29 |
+ ADMINISTRATOR_PHONE_ALREADY_EXISTS = StatusCodeField(401005, 'Administrator Phone Already Exists', description='管理员手机号已经存在') |
|
| 30 |
+ # 状态 |
|
| 31 |
+ ADMINISTRATOR_NOT_ACTIVATED = StatusCodeField(401015, 'Administrator Not Activated', description='管理员未激活') |
|
| 32 |
+ ADMINISTRATOR_HAS_DISABLED = StatusCodeField(401016, 'Administrator Has Disabled', description='管理员已禁用') |
|
| 33 |
+ ADMINISTRATOR_HAS_DELETED = StatusCodeField(401017, 'Administrator Has Deleted', description='管理员已删除') |
|
| 34 |
+ |
|
| 35 |
+ |
|
| 36 |
+class IsolationPointStatusCode(BaseStatusCode): |
|
| 37 |
+ """ 操作员相关错误码 4020xx """ |
|
| 38 |
+ ISOLATIONPOINT_NOT_FOUND = StatusCodeField(402001, 'IsolationPoint Not Found', description='隔离点不存在') |
|
| 39 |
+ |
|
| 40 |
+ |
|
| 41 |
+class ThermometerEquipmentStatusCode(BaseStatusCode): |
|
| 42 |
+ """ 操作员相关错误码 4030xx """ |
|
| 43 |
+ THERMOMETER_EQUIPMENT_NOT_FOUND = StatusCodeField(403001, 'Thermometer Equipment Not Found', description='测温设备不存在') |
|
| 21 | 44 |
|
| 22 | 45 |
|
| 23 | 46 |
class OrderStatusCode(BaseStatusCode): |
| 24 | 47 |
""" 4040xx 订单/支付相关错误码 """ |
| 25 |
- UNIFIED_ORDER_FAIL = StatusCodeField(404000, 'Unified Order Fail', description=u'统一下单失败') |
|
| 26 |
- ORDER_NOT_FOUND = StatusCodeField(404001, 'Order Not Found', description=u'订单不存在') |
|
| 48 |
+ UNIFIED_ORDER_FAIL = StatusCodeField(404000, 'Unified Order Fail', description='统一下单失败') |
|
| 49 |
+ ORDER_NOT_FOUND = StatusCodeField(404001, 'Order Not Found', description='订单不存在') |
|
| 27 | 50 |
# 订单支付状态 |
| 28 |
- ORDER_NOT_PAY = StatusCodeField(404011, 'Order Not Pay', description=u'订单未支付') |
|
| 29 |
- ORDER_PAYING = StatusCodeField(404012, 'Order Paying', description=u'订单支付中') |
|
| 30 |
- ORDER_PAY_FAIL = StatusCodeField(404013, 'Order Pay Fail', description=u'微信支付失败') |
|
| 51 |
+ ORDER_NOT_PAY = StatusCodeField(404011, 'Order Not Pay', description='订单未支付') |
|
| 52 |
+ ORDER_PAYING = StatusCodeField(404012, 'Order Paying', description='订单支付中') |
|
| 53 |
+ ORDER_PAY_FAIL = StatusCodeField(404013, 'Order Pay Fail', description='微信支付失败') |
|
| 31 | 54 |
# 通知校验状态 |
| 32 |
- SIGN_CHECK_FAIL = StatusCodeField(404090, 'Sign Check Fail', description=u'签名校验失败') |
|
| 33 |
- FEE_CHECK_FAIL = StatusCodeField(404091, 'FEE Check Fail', description=u'金额校验失败') |
|
| 55 |
+ SIGN_CHECK_FAIL = StatusCodeField(404090, 'Sign Check Fail', description='签名校验失败') |
|
| 56 |
+ FEE_CHECK_FAIL = StatusCodeField(404091, 'FEE Check Fail', description='金额校验失败') |
|
| 34 | 57 |
|
| 35 | 58 |
|
| 36 | 59 |
class PayStatusCode(BaseStatusCode): |
@@ -39,39 +62,39 @@ class PayStatusCode(BaseStatusCode): |
||
| 39 | 62 |
|
| 40 | 63 |
class WithdrawStatusCode(BaseStatusCode): |
| 41 | 64 |
""" 4042xx 提现相关错误码 """ |
| 42 |
- BALANCE_INSUFFICIENT = StatusCodeField(404200, 'Balance Insufficient', description=u'提现金额不足') |
|
| 65 |
+ BALANCE_INSUFFICIENT = StatusCodeField(404200, 'Balance Insufficient', description='提现金额不足') |
|
| 43 | 66 |
|
| 44 | 67 |
|
| 45 | 68 |
class TokenStatusCode(BaseStatusCode): |
| 46 | 69 |
""" 4090xx 票据相关错误码 """ |
| 47 |
- TOKEN_NOT_FOUND = StatusCodeField(409001, 'Token Not Found', description=u'票据不存在') |
|
| 70 |
+ TOKEN_NOT_FOUND = StatusCodeField(409001, 'Token Not Found', description='票据不存在') |
|
| 48 | 71 |
|
| 49 | 72 |
|
| 50 | 73 |
class SignatureStatusCode(BaseStatusCode): |
| 51 | 74 |
""" 4091xx 签名校验错误 """ |
| 52 |
- SIGNATURE_ERROR = StatusCodeField(409101, 'Signature Error', description=u'签名错误') |
|
| 75 |
+ SIGNATURE_ERROR = StatusCodeField(409101, 'Signature Error', description='签名错误') |
|
| 53 | 76 |
|
| 54 | 77 |
|
| 55 | 78 |
class GVCodeStatusCode(BaseStatusCode): |
| 56 | 79 |
""" 4092xx 图形验证码相关错误码 """ |
| 57 |
- GRAPHIC_VCODE_ERROR = StatusCodeField(409201, 'Graphic VCode Error', description=u'图形验证码错误') |
|
| 80 |
+ GRAPHIC_VCODE_ERROR = StatusCodeField(409201, 'Graphic VCode Error', description='图形验证码错误') |
|
| 58 | 81 |
|
| 59 | 82 |
|
| 60 | 83 |
class SVCodeStatusCode(BaseStatusCode): |
| 61 | 84 |
""" 4093xx 短信验证码相关错误码 """ |
| 62 |
- SMS_QUOTA_LIMIT = StatusCodeField(409300, 'SMS Quota Limit', description=u'短信次数超限') |
|
| 63 |
- SMS_VCODE_ERROR = StatusCodeField(409301, 'SMS VCode Error', description=u'验证码错误,请稍后重试') |
|
| 64 |
- SMS_VCODE_HAS_SEND = StatusCodeField(409302, 'SMS VCode Has Send', description=u'验证码已发送,请勿重复获取') |
|
| 85 |
+ SMS_QUOTA_LIMIT = StatusCodeField(409300, 'SMS Quota Limit', description='短信次数超限') |
|
| 86 |
+ SMS_VCODE_ERROR = StatusCodeField(409301, 'SMS VCode Error', description='验证码错误,请稍后重试') |
|
| 87 |
+ SMS_VCODE_HAS_SEND = StatusCodeField(409302, 'SMS VCode Has Send', description='验证码已发送,请勿重复获取') |
|
| 65 | 88 |
|
| 66 | 89 |
|
| 67 | 90 |
class InsufficientStatusCode(BaseStatusCode): |
| 68 | 91 |
""" 4095xx 不足相关错误码 """ |
| 69 |
- BALANCE_INSUFFICIENT = StatusCodeField(409501, 'Balance Insufficient', description=u'余额不足') |
|
| 70 |
- INTEGRAL_INSUFFICIENT = StatusCodeField(409502, 'Integral Insufficient', description=u'积分不足') |
|
| 92 |
+ BALANCE_INSUFFICIENT = StatusCodeField(409501, 'Balance Insufficient', description='余额不足') |
|
| 93 |
+ INTEGRAL_INSUFFICIENT = StatusCodeField(409502, 'Integral Insufficient', description='积分不足') |
|
| 71 | 94 |
|
| 72 | 95 |
|
| 73 | 96 |
class PermissionStatusCode(BaseStatusCode): |
| 74 | 97 |
""" 4099xx 权限相关错误码 """ |
| 75 |
- PERMISSION_DENIED = StatusCodeField(409900, 'Permission Denied', description=u'权限不足') |
|
| 76 |
- UPLOAD_PERMISSION_DENIED = StatusCodeField(409910, 'Upload Permission Denied', description=u'上传权限不足') |
|
| 77 |
- UPDATE_PERMISSION_DENIED = StatusCodeField(409930, 'Update Permission Denied', description=u'更新权限不足') |
|
| 98 |
+ PERMISSION_DENIED = StatusCodeField(409900, 'Permission Denied', description='权限不足') |
|
| 99 |
+ UPLOAD_PERMISSION_DENIED = StatusCodeField(409910, 'Upload Permission Denied', description='上传权限不足') |
|
| 100 |
+ UPDATE_PERMISSION_DENIED = StatusCodeField(409930, 'Update Permission Denied', description='更新权限不足') |