models.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. from django.db import models
  2. from datetime import datetime, timedelta
  3. from .functions import get_level_name
  4. from django.db.models import F
  5. # Create your models here.
  6. class ServiceTimeSlot(models.Model):
  7. ID = models.AutoField(primary_key=True)
  8. date = models.DateField(null=True, blank=True)
  9. start_time = models.TimeField(null=True, blank=True)
  10. end_time = models.TimeField(null=True, blank=True)
  11. address = models.CharField(max_length=256, null=True, blank=True)
  12. service_address = models.CharField(max_length=256, null=True, blank=True)
  13. service_content = models.CharField(max_length=256, null=True, blank=True)
  14. people_count = models.IntegerField(default=2)
  15. booked_count = models.IntegerField(default=0) # 目前已经注册人数,因为以前未统计,先收集一段时间,等到数据稳定后,在去除
  16. @staticmethod
  17. def search_by_date(service_date):
  18. return ServiceTimeSlot.objects.filter(date=service_date)
  19. @staticmethod
  20. def search_future_timeslots(service_date):
  21. return ServiceTimeSlot.objects.filter(date__gt=service_date)
  22. @staticmethod
  23. def search_by_date_and_address(service_date, address):
  24. # if address in [None, 'false', 'all']:
  25. if address in [None, 'false']:
  26. return ServiceTimeSlot.objects.filter(date=service_date)
  27. else:
  28. return ServiceTimeSlot.objects.filter(date=service_date, address=address)
  29. @staticmethod
  30. def get_by_id(ts_id):
  31. return ServiceTimeSlot.objects.get(ID=ts_id)
  32. @staticmethod
  33. def search_by_year_month(year, month):
  34. return ServiceTimeSlot.objects.filter(date__year=year, date__month=month)
  35. @staticmethod
  36. def search_by_year_month_address(year, month, address):
  37. if address in ['all', 'false']:
  38. return ServiceTimeSlot.objects.filter(date__year=year, date__month=month).order_by('date')
  39. else:
  40. return ServiceTimeSlot.objects.filter(date__year=year, date__month=month, address=address).order_by('date')
  41. # 搜索目前可以报名的服务,返回结束日期小于当前日期的地址列表
  42. @staticmethod
  43. def available_address():
  44. return ServiceTimeSlot.objects.filter(date__gte=datetime.today().date()).values('address').distinct()
  45. class Volunteer(models.Model):
  46. ID = models.AutoField(primary_key=True)
  47. name = models.CharField(max_length=128) # 姓名
  48. gender = models.CharField(max_length=8) # 性别 男,女,保密
  49. mobile = models.BigIntegerField(unique=True) # 手机号码
  50. social_id = models.CharField(max_length=32) # 身份证号码
  51. political_outlook = models.CharField(max_length=32) # 政治面貌
  52. organization = models.CharField(max_length=256) # 单位或学校
  53. district_street = models.CharField(max_length=256) # 区或街道
  54. status = models.CharField(max_length=128) # 状态 active,pending
  55. wechat_id = models.CharField(null=True, max_length=128) # 微信openid
  56. total_credit = models.IntegerField(default=0)
  57. current_credit = models.IntegerField(default=0)
  58. @staticmethod
  59. def volunteer_list():
  60. return Volunteer.objects.all();
  61. @staticmethod
  62. def get_by_mobile(mobile_number):
  63. try:
  64. return Volunteer.objects.get(mobile=mobile_number)
  65. except Exception as e:
  66. print(e)
  67. return None
  68. @staticmethod
  69. def get_by_mobile_social_id(mobile_number, social_id):
  70. try:
  71. volunteer = Volunteer.objects.get(mobile=mobile_number, social_id=social_id)
  72. return volunteer
  73. except Exception as e:
  74. print(e)
  75. return None
  76. @staticmethod
  77. def get_by_id(v_id):
  78. try:
  79. volunteer = Volunteer.objects.get(ID=v_id)
  80. volunteer.level_name = get_level_name(volunteer.total_credit)
  81. return volunteer
  82. except Exception as e:
  83. print(e)
  84. return None
  85. @staticmethod
  86. def get_by_wechat_id(wechat_id):
  87. try:
  88. volunteer = Volunteer.objects.get(wechat_id=wechat_id)
  89. volunteer.level_name = get_level_name(volunteer.total_credit)
  90. return volunteer
  91. except Exception as e:
  92. print(e)
  93. return None
  94. @staticmethod
  95. def pending_list():
  96. return Volunteer.objects.filter(status='pending')
  97. @staticmethod
  98. def approve_volunteer(v_id):
  99. Volunteer.objects.filter(ID=v_id, status='pending').update(status='active')
  100. @staticmethod
  101. def reject(v_id):
  102. Volunteer.objects.filter(ID=v_id, status='pending').delete()
  103. class ServiceBooking(models.Model):
  104. ID = models.AutoField(primary_key=True)
  105. timeslot_id = models.ForeignKey(ServiceTimeSlot, on_delete=models.CASCADE, blank=True, null=True,
  106. related_name='service_booking_to_timeslot')
  107. volunteer_id = models.ForeignKey(Volunteer, on_delete=models.CASCADE, blank=True, null=True,
  108. related_name='service_booking_to_volunteer')
  109. register_time = models.DateTimeField(auto_now_add=True, null=True) # 记录创建时间
  110. counted_in_credit = models.BooleanField(default=False) # 是否已经在credit中统计过
  111. @staticmethod
  112. def get_by_ID(booking_id):
  113. try:
  114. service_booking = ServiceBooking.objects.get(ID=booking_id)
  115. return service_booking
  116. except Exception as e:
  117. print(e)
  118. return None
  119. @staticmethod
  120. def count_credit_by_yesterday():
  121. # 统计今天以前,并且没有被统计时长的活动
  122. return ServiceBooking.objects.select_related('timeslot_id') \
  123. .filter(counted_in_credit=False, timeslot_id__date__lt=datetime.now().date()).order_by('timeslot_id__date')
  124. @staticmethod
  125. def search_by_volunteer(v_id):
  126. return ServiceBooking.objects.select_related('timeslot_id').filter(volunteer_id_id=v_id,
  127. timeslot_id__date__gte=datetime.now().date()).order_by(
  128. 'timeslot_id__date')
  129. # 根据给定的time_slot查询预定状态
  130. @staticmethod
  131. def search_by_service_timeslot_list(service_list):
  132. if type(service_list) == ServiceTimeSlot:
  133. return ServiceBooking.objects.filter(timeslot_id=service_list)
  134. elif type(service_list) == models.query.QuerySet:
  135. return ServiceBooking.objects.filter(timeslot_id__in=service_list)
  136. @staticmethod
  137. def search_by_service_timeslot_list_with_volunteer_info(service_list):
  138. return ServiceBooking.objects.filter(timeslot_id__in=service_list).select_related('volunteer_id')
  139. @staticmethod
  140. def search_by_service_timeslot(service):
  141. return ServiceBooking.objects.filter(timeslot_id=service)
  142. @staticmethod
  143. def check_exist_booking(ts_id, v_id):
  144. if len(ServiceBooking.objects.filter(timeslot_id=ts_id, volunteer_id=v_id)) > 0:
  145. return True
  146. else:
  147. return False
  148. @staticmethod
  149. def add(service_booking):
  150. if ServiceBooking.check_exist_booking(service_booking.timeslot_id, service_booking.volunteer_id):
  151. return False
  152. else:
  153. service_booking.save()
  154. return True
  155. @staticmethod
  156. def delete(timeslot, volunteer):
  157. ServiceBooking.objects.filter(timeslot_id_id=timeslot, volunteer_id_id=volunteer).delete()
  158. @staticmethod
  159. def get_monthly_report(date):
  160. input_date = datetime.strptime(date, '%Y-%m-%d')
  161. first_date_of_month = datetime(year=input_date.year, month=input_date.month, day=1)
  162. month = input_date.month
  163. if month == 12:
  164. month = 1
  165. else:
  166. month += 1
  167. first_date_of_next_month = datetime(year=input_date.year, month=month, day=1)
  168. monthly_report = ServiceBooking.objects.select_related('timeslot_id', 'volunteer_id') \
  169. .filter(timeslot_id__date__gte=first_date_of_month, timeslot_id__date__lt=first_date_of_next_month) \
  170. .order_by('timeslot_id__date', 'timeslot_id__start_time') \
  171. .values('timeslot_id__date', 'timeslot_id__start_time', 'timeslot_id__end_time', 'timeslot_id__address'
  172. , 'volunteer_id__name', 'volunteer_id__gender', 'volunteer_id__mobile', 'volunteer_id__social_id',
  173. 'volunteer_id__political_outlook', 'volunteer_id__organization', 'volunteer_id__district_street')
  174. return monthly_report
  175. # 寻找是否用时间上重叠的booking
  176. @staticmethod
  177. def has_conflict_booking(volunteer: Volunteer, service_time_slot: ServiceTimeSlot) -> bool:
  178. existing_booking = ServiceBooking.objects.select_related('timeslot_id', 'volunteer_id') \
  179. .filter(timeslot_id__date=service_time_slot.date, timeslot_id__end_time__gt=service_time_slot.start_time,
  180. timeslot_id__start_time__lt=service_time_slot.end_time, volunteer_id__ID=volunteer.ID)
  181. if len(existing_booking) > 0:
  182. return True
  183. else:
  184. return False
  185. # 获取需要进行提醒的Service Booking List
  186. # 参数day表示提前n天,默认未1,表示或许下一天的所有service booking
  187. @staticmethod
  188. def service_booking_reminder_list(day: int = 1):
  189. today = datetime.today().date()
  190. check_date = today + timedelta(days=day)
  191. list = ServiceBooking.objects.select_related('timeslot_id', 'volunteer_id').filter(timeslot_id__date=check_date)
  192. return list
  193. class Admin(models.Model):
  194. id = models.AutoField(primary_key=True)
  195. name = models.CharField(max_length=128) # 姓名
  196. password = models.CharField(max_length=128) # 密码
  197. mobile = models.BigIntegerField(unique=True) # 手机号码
  198. register_date = models.DateTimeField(auto_now_add=True) # 创建日期
  199. status = models.CharField(max_length=128) # 状态 active,pending
  200. class CreditRecord(models.Model):
  201. id = models.AutoField(primary_key=True)
  202. volunteer = models.ForeignKey(Volunteer, on_delete=models.CASCADE, blank=True, null=True,
  203. related_name='credit_record_to_volunteer')
  204. admin = models.ForeignKey(Admin, on_delete=models.SET_NULL, blank=True, null=True,
  205. related_name='credit_record_to_admin')
  206. change = models.IntegerField(blank=True, null=True, default=0)
  207. reason = models.CharField(blank=True, null=True, max_length=256)
  208. record_datetime = models.DateTimeField(auto_now_add=True, name='datetime')
  209. class Bonus(models.Model):
  210. id = models.AutoField(primary_key=True)
  211. name = models.CharField(max_length=128)
  212. description = models.CharField(max_length=1024)
  213. picture = models.CharField(max_length=256, null=True, blank=True)
  214. type = models.CharField(max_length=128)
  215. total_qty = models.IntegerField()
  216. used_qty = models.IntegerField(default=0)
  217. cut_off_date = models.DateField()
  218. cost = models.DecimalField(max_digits=9999, decimal_places=2) # 兑换价格
  219. admin = models.ForeignKey(to=Admin, on_delete=models.SET_NULL, blank=True, null=True, related_name='bonus_to_admin')
  220. @staticmethod
  221. def get_by_id(bonus_id):
  222. try:
  223. bonus = Bonus.objects.get(id=bonus_id)
  224. return bonus
  225. except Exception as e:
  226. print(e)
  227. return None
  228. @staticmethod
  229. def get_bonus_list(admin: Admin = None):
  230. if admin is None:
  231. bonus_list = Bonus.objects.filter().order_by('-cut_off_date')
  232. else:
  233. bonus_list = Bonus.objects.filter(admin=admin).order_by('-cut_off_date')
  234. return bonus_list
  235. @staticmethod
  236. def get_bonus(bonus_id):
  237. try:
  238. bonus = Bonus.objects.get(id=bonus_id)
  239. return bonus
  240. except Exception as e:
  241. print(e)
  242. return None
  243. @staticmethod
  244. def all_available_bonus():
  245. bonus_list = Bonus.objects.filter(cut_off_date__gte=datetime.today().date(), used_qty__lt=F('total_qty')) \
  246. .order_by('cut_off_date')
  247. return bonus_list
  248. @staticmethod
  249. def del_bonus(bonus_id):
  250. bonus = Bonus.objects.get(id=bonus_id)
  251. if bonus.used_qty > 0:
  252. return False
  253. else:
  254. bonus.delete()
  255. return True
  256. class BonusRecord(models.Model):
  257. id = models.AutoField(primary_key=True)
  258. bonus = models.ForeignKey(to=Bonus, on_delete=models.SET_NULL, blank=True, null=True,
  259. related_name='bonus_record_to_bonus')
  260. volunteer = models.ForeignKey(to=Volunteer, on_delete=models.SET_NULL, blank=True, null=True,
  261. related_name='bonus_record_to_volunteer')
  262. register_time = models.DateTimeField(auto_now_add=True, null=True) # 记录创建时间
  263. @staticmethod
  264. def is_exist(volunteer: Volunteer, bonus: Bonus) -> bool:
  265. exist_record = BonusRecord.objects.filter(volunteer=volunteer, bonus=bonus)
  266. if len(exist_record) > 0:
  267. return True
  268. else:
  269. return False
  270. @staticmethod
  271. def search_bonus_with_volunteer(bonus):
  272. bonus_list = BonusRecord.objects.select_related('volunteer').filter(bonus=bonus). \
  273. values('volunteer__name', 'volunteer__gender', 'volunteer__mobile', 'volunteer__social_id',
  274. 'volunteer__political_outlook', 'volunteer__organization', 'volunteer__district_street')
  275. return bonus_list
  276. @staticmethod
  277. def search_by_volunteer(volunteer: Volunteer):
  278. bonus_record_list = BonusRecord.objects.select_related('bonus').filter(volunteer=volunteer)
  279. return bonus_record_list
  280. # class VolunteerCredit(models.Model):
  281. # id = models.AutoField(primary_key=True)
  282. # volunteer = models.ForeignKey(to=Volunteer, on_delete=models.SET_NULL, blank=True, null=True,
  283. # related_name='volunteer_credit_to_volunteer')
  284. # total_credit = models.IntegerField()
  285. # current_credit = models.IntegerField()
  286. #
  287. # def __init__(self, volunteer: Volunteer, credit: int):
  288. # self.volunteer = volunteer
  289. # self.total_credit = credit
  290. # self.current_credit = credit
  291. #
  292. # @staticmethod
  293. # def exist_by_volunteer(volunteer) -> bool:
  294. # return VolunteerCredit.objects.filter(volunteer=volunteer).exists()
  295. #
  296. # @staticmethod
  297. # def get_by_volunteer(volunteer):
  298. # try:
  299. # return VolunteerCredit.objects.get(volunteer=volunteer)
  300. # except Exception as e:
  301. # print(e)
  302. # # 删除数据库中可能存在的错误
  303. # VolunteerCredit.objects.filter(volunteer=volunteer).delete()
  304. # return None
  305. # class Organizer(models.Model):
  306. # id = models.AutoField(primary_key=True)
  307. # name = models.CharField(max_length=128)
  308. # password = models.CharField(max_length=128)