views.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. from rest_framework import viewsets
  2. from utils.page import MyPageNumberPagination
  3. from utils.datasolve import sumOfList, transportation_calculate
  4. from utils.md5 import Md5
  5. from rest_framework.filters import OrderingFilter
  6. from django_filters.rest_framework import DjangoFilterBackend
  7. from rest_framework.response import Response
  8. from rest_framework.exceptions import APIException
  9. from django.utils import timezone
  10. from .models import BoundListModel, BoundDetailModel,BoundBatchModel, BatchLogModel, OutBatchModel,OutBoundDetailModel
  11. # from .files import FileListRenderCN, FileDetailRenderCN
  12. from .serializers import BoundListGetSerializer,BoundListPostSerializer,BoundBatchGetSerializer,BoundBatchPostSerializer,BoundDetailGetSerializer,BoundDetailPostSerializer
  13. from .serializers import OutBoundDetailGetSerializer,OutBoundDetailPostSerializer,OutBatchGetSerializer,OutBatchPostSerializer,BatchLogGetSerializer
  14. from .filter import BoundListFilter, BoundDetailFilter,BoundBatchFilter
  15. from .filter import OutBatchFilter,OutBoundDetailFilter,BatchlogFilter
  16. # 以后添加模块检验
  17. from warehouse.models import ListModel as warehouse
  18. from staff.models import ListModel as staff
  19. from rest_framework.permissions import AllowAny
  20. class BoundListViewSet(viewsets.ModelViewSet):
  21. """
  22. retrieve:
  23. Response a data list(get)
  24. list:
  25. Response a data list(all)
  26. create:
  27. Create a data line(post)
  28. delete:
  29. Delete a data line(delete)
  30. """
  31. # authentication_classes = [] # 禁用所有认证类
  32. # permission_classes = [AllowAny] # 允许任意访问
  33. pagination_class = MyPageNumberPagination
  34. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  35. ordering_fields = ['id', "create_time", "update_time", ]
  36. filter_class = BoundListFilter
  37. def get_project(self):
  38. try:
  39. id = self.kwargs.get('pk')
  40. return id
  41. except:
  42. return None
  43. def get_queryset(self):
  44. id = self.get_project()
  45. if self.request.user:
  46. if id is None:
  47. return BoundListModel.objects.filter( is_delete=False)
  48. else:
  49. return BoundListModel.objects.filter( id=id, is_delete=False)
  50. else:
  51. return BoundListModel.objects.none()
  52. def get_serializer_class(self):
  53. if self.action in ['list', 'destroy','retrieve']:
  54. return BoundListGetSerializer
  55. elif self.action in ['create', 'update']:
  56. return BoundListPostSerializer
  57. else:
  58. return self.http_method_not_allowed(request=self.request)
  59. def create(self, request, *args, **kwargs):
  60. data = self.request.data
  61. # if BoundListModel.objects.filter(code=data['code'], is_delete=False).exists():
  62. # raise APIException({"detail": "Data exists"})
  63. # else:
  64. data['openid'] = self.request.auth.openid
  65. data['bound_date'] =str(timezone.now().strftime('%Y-%m-%d'))
  66. order_day=str(timezone.now().strftime('%Y-%m-'))
  67. data['bound_month'] =str(timezone.now().strftime('%Y%m'))
  68. if data['bound_type'] == 'in':
  69. data['bound_status'] = '100'
  70. else:
  71. data['bound_status'] = '200'
  72. qs_set = BoundListModel.objects.filter(bound_month=data['bound_month'], bound_code_type=data['bound_code_type'], is_delete=False)
  73. print('qs_set是:', len(qs_set))
  74. if len(qs_set) > 0:
  75. bound_last_code = qs_set.order_by('-id').first().bound_code
  76. data['bound_code'] = data['bound_code_type'] +'-'+ order_day + str(int(bound_last_code.split('-')[-1])+1).zfill(4)
  77. else:
  78. data['bound_code'] = data['bound_code_type'] +'-'+ order_day + '0001'
  79. serializer = self.get_serializer(data=data)
  80. serializer.is_valid(raise_exception=True)
  81. serializer.save()
  82. headers = self.get_success_headers(serializer.data)
  83. return Response(serializer.data, status=200, headers=headers)
  84. def update(self, request, pk):
  85. qs = self.get_object()
  86. data = self.request.data
  87. serializer = self.get_serializer(qs, data=data)
  88. serializer.is_valid(raise_exception=True)
  89. serializer.save()
  90. headers = self.get_success_headers(serializer.data)
  91. return Response(serializer.data, status=200, headers=headers)
  92. def destroy(self, request, pk):
  93. qs = self.get_object()
  94. if qs.openid != self.request.auth.openid:
  95. raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
  96. else:
  97. qs.is_delete = True
  98. qs.bound_code =qs.bound_code+'-delete'+str(timezone.now().strftime('%Y%m%d%H%M%S'))
  99. qs.save()
  100. serializer = self.get_serializer(qs, many=False)
  101. headers = self.get_success_headers(serializer.data)
  102. return Response(serializer.data, status=200, headers=headers)
  103. class BoundBatchViewSet(viewsets.ModelViewSet):
  104. """
  105. retrieve:
  106. Response a data list(get)
  107. list:
  108. Response a data list(all)
  109. create:
  110. Create a data line(post)
  111. delete:
  112. Delete a data line(delete)
  113. """
  114. # authentication_classes = [] # 禁用所有认证类
  115. # permission_classes = [AllowAny] # 允许任意访问
  116. pagination_class = MyPageNumberPagination
  117. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  118. ordering_fields = ['id', "create_time", "update_time", ]
  119. filter_class = BoundBatchFilter
  120. def get_project(self):
  121. try:
  122. id = self.kwargs.get('pk')
  123. return id
  124. except:
  125. return None
  126. def get_queryset(self):
  127. id = self.get_project()
  128. if self.request.user:
  129. if id is None:
  130. return BoundBatchModel.objects.filter( is_delete=False)
  131. else:
  132. return BoundBatchModel.objects.filter( id=id, is_delete=False)
  133. else:
  134. return BoundBatchModel.objects.none()
  135. def get_serializer_class(self):
  136. if self.action in ['list', 'destroy','retrieve']:
  137. return BoundBatchGetSerializer
  138. elif self.action in ['create', 'update']:
  139. return BoundBatchPostSerializer
  140. else:
  141. return self.http_method_not_allowed(request=self.request)
  142. def create(self, request, *args, **kwargs):
  143. data = self.request.data
  144. try:
  145. data['openid'] = self.request.auth.openid
  146. data['goods_total_weight'] = data['goods_weight']*data['goods_qty']
  147. order_day=str(timezone.now().strftime('-%Y%m'))
  148. order_month=str(timezone.now().strftime('%Y%m'))
  149. data['bound_month'] =str(timezone.now().strftime('%Y%m'))
  150. print(data['order'])
  151. if data['order'] == 'true':
  152. qs_set = BoundBatchModel.objects.filter( goods_code=data['goods_code'], bound_month=order_month, is_delete=False)
  153. print('qs_set是:', len(qs_set))
  154. if len(qs_set) > 0:
  155. bound_last_code = qs_set.order_by('-id').first().bound_number
  156. data['bound_batch_order'] = int(bound_last_code.split('-')[-1])+1
  157. data['bound_number'] = data['goods_code'] + '-' + str(int(bound_last_code.split('-')[-1])+1)
  158. else:
  159. data['bound_batch_order'] = int(order_day.split('-')[-1])*100 +1
  160. data['bound_number'] = data['goods_code'] + order_day + '01'
  161. else:
  162. data['bound_number'] = data['goods_code'] + '-' + str(data['bound_batch_order'])
  163. serializer = self.get_serializer(data=data)
  164. serializer.is_valid(raise_exception=True)
  165. serializer.save()
  166. headers = self.get_success_headers(serializer.data)
  167. self.add_batch_log(serializer.data, 0, data['goods_qty'])
  168. return Response(serializer.data, status=200, headers=headers)
  169. except Exception as e:
  170. print(e)
  171. raise APIException({"detail": "{}".format(e)})
  172. def add_batch_log(self, data, log_type, goods_qty):
  173. choices_dict = dict(BatchLogModel.BATCH_LOG_TYPE)
  174. log_type_name = choices_dict.get(log_type, "未知类型")
  175. try:
  176. # 获取 BoundBatchModel 实例
  177. batch_obj = BoundBatchModel.objects.get(id=data['id'])
  178. except BoundBatchModel.DoesNotExist:
  179. return False
  180. log_data = {
  181. 'batch_id': batch_obj,
  182. 'log_type': log_type,
  183. 'log_date': timezone.now().strftime('%Y-%m-%d-%H:%M'), # 直接格式化时间,无需转字符串
  184. 'goods_code': data['goods_code'],
  185. 'goods_desc': data['goods_desc'],
  186. 'goods_qty': data['goods_qty'],
  187. 'log_content': f"{log_type_name} {data['goods_qty']}件",
  188. 'creater': data['creater'],
  189. 'openid': data['openid'],
  190. 'is_delete': False,
  191. }
  192. # 创建日志记录
  193. BatchLogModel.objects.create(**log_data)
  194. return True
  195. def update(self, request, pk):
  196. qs = self.get_object()
  197. data = self.request.data
  198. serializer = self.get_serializer(qs, data=data)
  199. serializer.is_valid(raise_exception=True)
  200. serializer.save()
  201. headers = self.get_success_headers(serializer.data)
  202. return Response(serializer.data, status=200, headers=headers)
  203. def destroy(self, request, pk):
  204. qs = self.get_object()
  205. if qs.openid != self.request.auth.openid:
  206. raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
  207. else:
  208. qs.is_delete = True
  209. qs.save()
  210. serializer = self.get_serializer(qs, many=False)
  211. headers = self.get_success_headers(serializer.data)
  212. return Response(serializer.data, status=200, headers=headers)
  213. class BoundDetailViewSet(viewsets.ModelViewSet):
  214. """
  215. retrieve:
  216. Response a data list(get)
  217. list:
  218. Response a data list(all)
  219. create:
  220. Create a data line(post)
  221. delete:
  222. Delete a data line(delete)
  223. """
  224. # authentication_classes = [] # 禁用所有认证类
  225. # permission_classes = [AllowAny] # 允许任意访问
  226. pagination_class = MyPageNumberPagination
  227. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  228. ordering_fields = ['id', "create_time", "update_time", ]
  229. filter_class = BoundDetailFilter
  230. def get_project(self):
  231. try:
  232. id = self.kwargs.get('pk')
  233. return id
  234. except:
  235. return None
  236. def get_queryset(self):
  237. id = self.get_project()
  238. if self.request.user:
  239. if id is None:
  240. return BoundDetailModel.objects.filter( is_delete=False)
  241. else:
  242. return BoundDetailModel.objects.filter( id=id, is_delete=False)
  243. else:
  244. return BoundDetailModel.objects.none()
  245. def get_serializer_class(self):
  246. if self.action in ['list', 'destroy','retrieve']:
  247. return BoundDetailGetSerializer
  248. elif self.action in ['create', 'update']:
  249. return BoundDetailPostSerializer
  250. else:
  251. return self.http_method_not_allowed(request=self.request)
  252. def create(self, request, *args, **kwargs):
  253. data = self.request.data
  254. data['openid'] = self.request.auth.openid
  255. data.setdefault('is_delete', False)
  256. # 验证并保存数据
  257. data['detail_code'] = f"DC-{data['bound_list']:02}{data['bound_batch']:02}"
  258. print(data['detail_code'])
  259. if BoundDetailModel.objects.filter(detail_code=data['detail_code'], is_delete=False).exists():
  260. raise APIException({"detail": "Data exists"})
  261. else:
  262. serializer = self.get_serializer(data=data)
  263. serializer.is_valid(raise_exception=True)
  264. serializer.save()
  265. # 返回响应
  266. headers = self.get_success_headers(serializer.data)
  267. return Response(serializer.data, status=200, headers=headers)
  268. def update(self, request, pk):
  269. qs = self.get_object()
  270. data = self.request.data
  271. serializer = self.get_serializer(qs, data=data)
  272. serializer.is_valid(raise_exception=True)
  273. serializer.save()
  274. headers = self.get_success_headers(serializer.data)
  275. return Response(serializer.data, status=200, headers=headers)
  276. def destroy(self, request, pk):
  277. qs = self.get_object()
  278. if qs.openid != self.request.auth.openid:
  279. raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
  280. else:
  281. qs.is_delete = True
  282. qs.save()
  283. serializer = self.get_serializer(qs, many=False)
  284. headers = self.get_success_headers(serializer.data)
  285. return Response(serializer.data, status=200, headers=headers)
  286. class OutBoundDetailViewSet(viewsets.ModelViewSet):
  287. """
  288. retrieve:
  289. Response a data list(get)
  290. list: Response a data list(all)
  291. create:
  292. Create a data line(post)
  293. delete:
  294. Delete a data line(delete)
  295. """
  296. # authentication_classes = [] # 禁用所有认证类
  297. # permission_classes = [AllowAny] # 允许任意访问
  298. pagination_class = MyPageNumberPagination
  299. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  300. ordering_fields = ['id', "create_time", "update_time", ]
  301. filter_class = OutBoundDetailFilter
  302. def get_project(self):
  303. try:
  304. id = self.kwargs.get('pk')
  305. return id
  306. except:
  307. return None
  308. def get_queryset(self):
  309. id = self.get_project()
  310. if self.request.user:
  311. if id is None:
  312. return OutBoundDetailModel.objects.filter( is_delete=False)
  313. else:
  314. return OutBoundDetailModel.objects.filter( id=id, is_delete=False)
  315. else:
  316. return OutBoundDetailModel.objects.none()
  317. def get_serializer_class(self):
  318. if self.action in ['list', 'destroy','retrieve']:
  319. return OutBoundDetailGetSerializer
  320. elif self.action in ['create', 'update']:
  321. return OutBoundDetailPostSerializer
  322. else:
  323. return self.http_method_not_allowed(request=self.request)
  324. def create(self, request, *args, **kwargs):
  325. data = self.request.data
  326. data['openid'] = self.request.auth.openid
  327. data.setdefault('is_delete', False)
  328. data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
  329. # 验证并保存数据
  330. data['detail_code'] = f"DC-{data['bound_list']:02}{data['bound_batch']:02}"
  331. print(data['detail_code'])
  332. if OutBoundDetailModel.objects.filter(detail_code=data['detail_code'], is_delete=False).exists():
  333. raise APIException({"detail": "Data exists"})
  334. else:
  335. serializer = self.get_serializer(data=data)
  336. serializer.is_valid(raise_exception=True)
  337. serializer.save()
  338. # 返回响应
  339. headers = self.get_success_headers(serializer.data)
  340. return Response(serializer.data, status=200, headers=headers)
  341. def update(self, request, pk):
  342. qs = self.get_object()
  343. data = self.request.data
  344. serializer = self.get_serializer(qs, data=data)
  345. serializer.is_valid(raise_exception=True)
  346. serializer.save()
  347. headers = self.get_success_headers(serializer.data)
  348. return Response(serializer.data, status=200, headers=headers)
  349. def destroy(self, request, pk):
  350. qs = self.get_object()
  351. if qs.openid != self.request.auth.openid:
  352. raise APIException({"detail": "该入库非您所属,禁止删除,您可以进行编辑"})
  353. else:
  354. qs.is_delete = True
  355. qs.save()
  356. serializer = self.get_serializer(qs, many=False)
  357. headers = self.get_success_headers(serializer.data)
  358. return Response(serializer.data, status=200, headers=headers)
  359. class OutBoundBatchViewSet(viewsets.ModelViewSet):
  360. """
  361. retrieve:
  362. Response a data list(get)
  363. list:
  364. Response a data list(all)
  365. create:
  366. Create a data line(post)
  367. delete:
  368. Delete a data line(delete)
  369. """
  370. # authentication_classes = [] # 禁用所有认证类
  371. # permission_classes = [AllowAny] # 允许任意访问
  372. pagination_class = MyPageNumberPagination
  373. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  374. ordering_fields = ['id', "create_time", "update_time", ]
  375. filter_class = OutBatchFilter
  376. def get_project(self):
  377. try:
  378. id = self.kwargs.get('pk')
  379. return id
  380. except:
  381. return None
  382. def get_queryset(self):
  383. id = self.get_project()
  384. if self.request.user:
  385. if id is None:
  386. return OutBatchModel.objects.filter( is_delete=False)
  387. else:
  388. return OutBatchModel.objects.filter( id=id, is_delete=False)
  389. else:
  390. return OutBatchModel.objects.none()
  391. def get_serializer_class(self):
  392. if self.action in ['list', 'destroy','retrieve']:
  393. return OutBatchGetSerializer
  394. elif self.action in ['create', 'update']:
  395. return OutBatchPostSerializer
  396. else:
  397. return self.http_method_not_allowed(request=self.request)
  398. def create(self, request, *args, **kwargs):
  399. data = self.request.data
  400. batch_obj = BoundBatchModel.objects.get(bound_number=data['out_number'])
  401. if batch_obj is None:
  402. raise APIException({"detail": "批次不存在"})
  403. data['batch_number'] = batch_obj.id
  404. data['out_date'] = str(timezone.now().strftime('%Y-%m-%d %H:%M:%S'))
  405. data['openid'] = self.request.auth.openid
  406. data.setdefault('is_delete', False)
  407. data['goods_total_weight'] = data['goods_weight']*data['goods_out_qty']
  408. data['goods_qty'] = batch_obj.goods_qty -batch_obj.goods_out_qty - data['goods_out_qty']
  409. batch_obj.goods_out_qty += data['goods_out_qty']
  410. if batch_obj.goods_out_qty > batch_obj.goods_in_qty:
  411. raise APIException({"detail": "出库数量大于批次数量"})
  412. batch_obj.goods_qty -= data['goods_out_qty']
  413. batch_obj.save()
  414. data['status'] = 0 #现在处于出库申请状态
  415. serializer = self.get_serializer(data=data)
  416. serializer.is_valid(raise_exception=True)
  417. serializer.save()
  418. headers = self.get_success_headers(serializer.data)
  419. self.add_batch_log(serializer.data, 1, data['goods_out_qty'])
  420. return Response(serializer.data, status=200, headers=headers)
  421. def update(self, request, pk):
  422. qs = self.get_object()
  423. data = self.request.data
  424. data['openid'] = self.request.auth.openid
  425. data.setdefault('is_delete', False)
  426. data['goods_total_weight'] = data['goods_weight']*data['goods_qty']
  427. serializer = self.get_serializer(qs, data=data)
  428. serializer.is_valid(raise_exception=True)
  429. serializer.save()
  430. headers = self.get_success_headers(serializer.data)
  431. self.add_batch_log(serializer.data, 1, data['goods_qty'])
  432. return Response(serializer.data, status=200, headers=headers)
  433. def destroy(self, request, pk):
  434. qs = self.get_object()
  435. if qs.openid != self.request.auth.openid:
  436. raise APIException({"detail": "该出库非您所属,禁止删除,您可以进行编辑"})
  437. else:
  438. qs.is_delete = True
  439. qs.save()
  440. serializer = self.get_serializer(qs, many=False)
  441. headers = self.get_success_headers(serializer.data)
  442. return Response(serializer.data, status=200, headers=headers)
  443. def add_batch_log(self, data, log_type, goods_qty):
  444. choices_dict = dict(BatchLogModel.BATCH_LOG_TYPE)
  445. log_type_name = choices_dict.get(log_type, "未知类型")
  446. try:
  447. # 获取 BoundBatchModel 实例
  448. batch_obj = BoundBatchModel.objects.get(id=data['batch_number'])
  449. except BoundBatchModel.DoesNotExist:
  450. # 处理批次不存在的情况(如记录日志或抛出异常)
  451. return False
  452. log_data = {
  453. 'batch_id': batch_obj, # 关键修复:传入实例对象,而不是 batch_obj.id
  454. 'log_type': log_type,
  455. 'log_date': timezone.now().strftime('%Y-%m-%d-%H:%M'), # 直接格式化时间,无需转字符串
  456. 'goods_code': data['goods_code'],
  457. 'goods_desc': data['goods_desc'],
  458. 'goods_qty': data['goods_qty'],
  459. 'log_content': f"{log_type_name} {goods_qty}件",
  460. 'creater': data['creater'],
  461. 'openid': data['openid'],
  462. 'is_delete': False,
  463. # 注意:create_time 和 update_time 由模型的 auto_now_add 和 auto_now 自动处理,无需手动赋值
  464. }
  465. # 创建日志记录
  466. BatchLogModel.objects.create(**log_data)
  467. return True
  468. class BoundBatchLogViewSet(viewsets.ModelViewSet):
  469. """
  470. retrieve:
  471. Response a data list(get)
  472. list:
  473. Response a data list(all)
  474. delete:
  475. Delete a data line(delete)
  476. """
  477. # authentication_classes = [] # 禁用所有认证类
  478. # permission_classes = [AllowAny] # 允许任意访问
  479. pagination_class = MyPageNumberPagination
  480. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  481. ordering_fields = ['id', "create_time", "update_time", ]
  482. filter_class = BatchlogFilter
  483. def get_queryset(self):
  484. return BatchLogModel.objects.filter( is_delete=False)
  485. def get_serializer_class(self):
  486. if self.action in ['list', 'destroy','retrieve']:
  487. return BatchLogGetSerializer
  488. else:
  489. return self.http_method_not_allowed(request=self.request)
  490. def destroy(self, request, pk):
  491. qs = self.get_object()
  492. qs.is_delete = True
  493. qs.save()
  494. serializer = self.get_serializer(qs, many=False)
  495. headers = self.get_success_headers(serializer.data)
  496. return Response(serializer.data, status=200, headers=headers)