views.py 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. from rest_framework import viewsets
  2. from utils.page import MyPageNumberPagination
  3. from utils.md5 import Md5
  4. from rest_framework.filters import OrderingFilter
  5. from django_filters.rest_framework import DjangoFilterBackend
  6. from rest_framework.response import Response
  7. from rest_framework.exceptions import APIException
  8. from django.http import StreamingHttpResponse
  9. from rest_framework.settings import api_settings
  10. from django.db import transaction
  11. from rest_framework import status
  12. from reportcenter.models import flowModel as flowlist
  13. from .models import bigScreenModel
  14. from . import serializers
  15. from .filter import FlowFilter, MaterialChangeHistoryFilter, batchLogFilter, ContainerDetailLogFilter,bigScreenFilter
  16. from .files import FileFlowListRenderCN, MaterialChangeHistoryRenderCN, batchLogRenderCN, ContainerDetailLogRenderCN
  17. from container.models import MaterialChangeHistory,batchLogModel,ContainerDetailLogModel
  18. """
  19. path(r'MaterialChangeHistory/', views.MaterialChangeHistoryViewSet.as_view({"get": "list", }), name="management"),
  20. path(r'MaterialChangeHistory/file/', views.MaterialChangeHistoryDownloadView.as_view({"get": "list"}), name="flowfile"),
  21. path(r'batchLog/', views.batchLogViewSet.as_view({"get": "list", }), name="management"),
  22. path(r'batchLog/file/', views.batchLogDownloadView.as_view({"get": "list"}), name="flowfile"),
  23. path(r'ContainerDetailLog/', views.ContainerDetailLogViewSet.as_view({"get": "list", }), name="management"),
  24. path(r'ContainerDetailLog/file/', views.ContainerDetailLogDownloadView.as_view({"get": "list"}), name="flowfile"),
  25. """
  26. from django.utils import timezone
  27. from datetime import datetime, timedelta
  28. from rest_framework.decorators import action
  29. from rest_framework.response import Response
  30. from django.db.models import Q, Max, Min
  31. from decimal import Decimal
  32. from django.db.models import Sum
  33. from django.db.models import OuterRef, Subquery
  34. def format_decimal(value):
  35. """格式化Decimal值为字符串,避免科学计数法"""
  36. if isinstance(value, Decimal):
  37. # 格式化为字符串,保留小数点后6位,但去除尾部多余的0
  38. return format(value.normalize(), 'f')
  39. return str(value)
  40. class MaterialChangeHistoryViewSet(viewsets.ModelViewSet):
  41. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  42. ordering_fields = ['id', "change_time", "create_time", "update_time", ]
  43. filter_class = MaterialChangeHistoryFilter
  44. pagination_class = MyPageNumberPagination
  45. def get_queryset(self):
  46. return MaterialChangeHistory.objects.all()
  47. def get_serializer_class(self):
  48. if self.action in ['list', 'create']:
  49. return serializers.MaterialChangeHistorySerializer
  50. else:
  51. return self.http_method_not_allowed(request=self.request)
  52. def summary_complex(self, request):
  53. """
  54. 获取物料库存变动汇总数据(支持分页)
  55. 请求参数路由上提供:
  56. - start_time: 开始时间(可选)
  57. - end_time: 结束时间(可选)
  58. - material_ids: 物料ID列表(可选)
  59. - page: 页码(可选)
  60. - page_size: 每页数量(可选)
  61. """
  62. # 获取请求参数 "POST /reportcenter/MaterialChangeHistory/?page=1&page_size=11&goods_code__icontains=UZ
  63. start_time = request.query_params.get('start_time') if request.query_params.get('start_time') else None
  64. end_time = request.quary_params.get('end_time') if request.query_params.get('end_time') else None
  65. material_ids_code = request.query_params.get('goods_code__icontains') if request.query_params.get('goods_code__icontains') else None
  66. # 记录查询时间范围
  67. query_time_range = {}
  68. # 如果没有提供时间段,使用当前月份
  69. if not start_time or not end_time:
  70. today = timezone.now().date()
  71. start_time = datetime(today.year, today.month, 1)
  72. end_time = start_time + timedelta(days=32)
  73. end_time = datetime(end_time.year, end_time.month, 1) - timedelta(days=1)
  74. end_time = datetime.combine(end_time, datetime.max.time())
  75. query_time_range['default_time_range'] = True
  76. else:
  77. query_time_range['default_time_range'] = False
  78. # 转换为datetime对象
  79. if isinstance(start_time, str):
  80. start_time = datetime.fromisoformat(start_time)
  81. if isinstance(end_time, str):
  82. end_time = datetime.fromisoformat(end_time)
  83. # 存储查询时间范围用于返回
  84. query_time_range['start_time'] = start_time.isoformat()
  85. query_time_range['end_time'] = end_time.isoformat()
  86. # 创建基础查询集
  87. queryset = MaterialChangeHistory.objects.filter(
  88. change_time__gte=start_time,
  89. change_time__lte=end_time
  90. )
  91. # 如果有物料ID过滤
  92. if material_ids_code:
  93. queryset = queryset.filter(goods_code__icontains=material_ids_code)
  94. print(f"过滤物料编码包含: {material_ids_code},剩余条目数: {queryset.count()}")
  95. # 获取期初数量(时间段开始时的库存)
  96. opening_subquery = MaterialChangeHistory.objects.filter(
  97. goods_code=OuterRef('goods_code'),
  98. change_time__lt=start_time
  99. ).order_by('-change_time').values('closing_quantity')[:1]
  100. opening_data = MaterialChangeHistory.objects.filter(
  101. change_time__lt=start_time
  102. )
  103. if material_ids_code:
  104. opening_data = opening_data.filter(goods_code__icontains=material_ids_code)
  105. opening_data = opening_data.values('goods_code').annotate(
  106. opening_quantity=Subquery(opening_subquery)
  107. )
  108. # 获取期末数量(时间段结束时的库存)
  109. closing_subquery = MaterialChangeHistory.objects.filter(
  110. goods_code=OuterRef('goods_code'),
  111. change_time__lte=end_time
  112. ).order_by('-change_time').values('closing_quantity')[:1]
  113. closing_data = MaterialChangeHistory.objects.filter(
  114. change_time__lte=end_time
  115. )
  116. if material_ids_code:
  117. closing_data = closing_data.filter(goods_code__icontains=material_ids_code)
  118. closing_data = closing_data.values('goods_code').annotate(
  119. closing_quantity=Subquery(closing_subquery)
  120. )
  121. # 计算期间出入库总量
  122. period_data = queryset.values('goods_code').annotate(
  123. total_in=Sum('in_quantity'),
  124. total_out=Sum('out_quantity')
  125. )
  126. # 构建结果字典
  127. result = {}
  128. for item in opening_data:
  129. material_code = item['goods_code']
  130. goods=MaterialChangeHistory.objects.filter(goods_code=material_code).first()
  131. result.setdefault(material_code, {
  132. 'material_code': material_code,
  133. 'goods_code': goods.goods_code if goods else 'N/A',
  134. 'goods_desc': goods.goods_desc if goods else 'N/A',
  135. 'goods_unit': goods.goods_unit if goods else 'N/A',
  136. 'opening_quantity': item['opening_quantity'] or Decimal('0'),
  137. 'closing_quantity': Decimal('0'),
  138. 'total_in': Decimal('0'),
  139. 'total_out': Decimal('0'),
  140. 'net_change': Decimal('0'), # 新增:净含量变化
  141. 'theoretical_change': Decimal('0'), # 新增:理论变化量
  142. 'is_consistent': True # 新增:一致性校验
  143. })
  144. for item in closing_data:
  145. material_code = item['goods_code']
  146. goods=MaterialChangeHistory.objects.filter(goods_code=material_code).first()
  147. if material_code in result:
  148. result[material_code]['closing_quantity'] = item['closing_quantity'] or Decimal('0')
  149. else:
  150. result[material_code] = {
  151. 'material_code': material_code,
  152. 'goods_code': goods.goods_code if goods else 'N/A',
  153. 'goods_desc': goods.goods_desc if goods else 'N/A',
  154. 'goods_unit': goods.goods_unit if goods else 'N/A',
  155. 'opening_quantity': Decimal('0'),
  156. 'closing_quantity': item['closing_quantity'] or Decimal('0'),
  157. 'total_in': Decimal('0'),
  158. 'total_out': Decimal('0'),
  159. 'net_change': Decimal('0'),
  160. 'theoretical_change': Decimal('0'),
  161. 'is_consistent': True
  162. }
  163. for item in period_data:
  164. material_code = item['goods_code']
  165. goods=MaterialChangeHistory.objects.filter(goods_code=material_code).first()
  166. if material_code in result:
  167. result[material_code]['total_in'] = item['total_in'] or Decimal('0')
  168. result[material_code]['total_out'] = item['total_out'] or Decimal('0')
  169. else:
  170. result[material_code] = {
  171. 'material_code': material_code,
  172. 'goods_code': goods.goods_code if goods else 'N/A',
  173. 'goods_desc': goods.goods_desc if goods else 'N/A',
  174. 'goods_unit': goods.goods_unit if goods else 'N/A',
  175. 'opening_quantity': Decimal('0'),
  176. 'closing_quantity': Decimal('0'),
  177. 'total_in': item['total_in'] or Decimal('0'),
  178. 'total_out': item['total_out'] or Decimal('0'),
  179. 'net_change': Decimal('0'),
  180. 'theoretical_change': Decimal('0'),
  181. 'is_consistent': True
  182. }
  183. # 计算净含量变化和理论变化量,并进行一致性校验
  184. for material_code, data in result.items():
  185. # 计算净含量变化(期末 - 期初)
  186. net_change = data['closing_quantity'] - data['opening_quantity']
  187. data['net_change'] = net_change
  188. # 计算理论变化量(入库 - 出库)
  189. theoretical_change = data['total_in'] - data['total_out']
  190. data['theoretical_change'] = theoretical_change
  191. # 检查是否一致(允许小数点后3位的差异)
  192. tolerance = Decimal('0.001')
  193. is_consistent = abs(net_change - theoretical_change) <= tolerance
  194. data['is_consistent'] = is_consistent
  195. # 转换为列表格式
  196. result_list = list(result.values())
  197. # 应用分页
  198. paginator = MyPageNumberPagination()
  199. page = paginator.paginate_queryset(result_list, request)
  200. # 构建响应数据
  201. response_data = {
  202. 'query_time_range': query_time_range,
  203. 'count': len(result_list),
  204. 'next': paginator.get_next_link(),
  205. 'previous': paginator.get_previous_link(),
  206. 'results': page
  207. }
  208. return Response(response_data)
  209. def export_summary(self, request):
  210. """
  211. 导出物料库存变动汇总数据为CSV
  212. """
  213. # 重用summary方法获取数据
  214. start_time = request.query_params.get('start_time') or None
  215. end_time = request.query_params.get('end_time') or None
  216. material_ids_code = request.query_params.get('goods_code__icontains') or None
  217. response = self.summary_all( start_time=start_time, end_time=end_time, material_ids_code=material_ids_code)
  218. data = response.data
  219. query_time_range = data['query_time_range']
  220. # 创建CSV响应
  221. from django.http import HttpResponse
  222. import csv
  223. response = HttpResponse(content_type='text/csv')
  224. response['Content-Disposition'] = 'attachment; filename="material_change_summary.csv"'
  225. # 创建CSV写入器
  226. csv_writer = csv.writer(response)
  227. # 写入表头
  228. headers = [
  229. '开始时间','结束时间',
  230. '存货编码', '存货名称', '计量单位',
  231. '期初数量', '期末数量', '期间变化',
  232. '入库数量', '出库数量', '出入库差异',
  233. '对比结果'
  234. ]
  235. csv_writer.writerow(headers)
  236. # 写入数据行
  237. for item in data['results']:
  238. # 处理对比结果的显示
  239. is_consistent = "一致" if item['is_consistent'] else "不一致"
  240. row = [
  241. query_time_range.get('start_time', ''),
  242. query_time_range.get('end_time', ''),
  243. item['goods_code'],
  244. item['goods_desc'],
  245. item['goods_unit'],
  246. # 数量字段格式化为字符串,避免科学计数法
  247. format_decimal(item['opening_quantity']),
  248. format_decimal(item['closing_quantity']),
  249. format_decimal(item['net_change']),
  250. format_decimal(item['total_in']),
  251. format_decimal(item['total_out']),
  252. format_decimal(item['theoretical_change']),
  253. is_consistent
  254. ]
  255. csv_writer.writerow(row)
  256. return response
  257. def summary_all(self, start_time=None, end_time=None, material_ids_code=None):
  258. """
  259. 获取物料库存变动汇总数据(支持分页)
  260. """
  261. # 获取请求参数
  262. # 记录查询时间范围
  263. query_time_range = {}
  264. # 如果没有提供时间段,使用当前月份
  265. if not start_time or not end_time:
  266. today = timezone.now().date()
  267. start_time = datetime(today.year, today.month, 1)
  268. end_time = start_time + timedelta(days=32)
  269. end_time = datetime(end_time.year, end_time.month, 1) - timedelta(days=1)
  270. end_time = datetime.combine(end_time, datetime.max.time())
  271. query_time_range['default_time_range'] = True
  272. else:
  273. query_time_range['default_time_range'] = False
  274. # 转换为datetime对象
  275. if isinstance(start_time, str):
  276. start_time = datetime.fromisoformat(start_time)
  277. if isinstance(end_time, str):
  278. end_time = datetime.fromisoformat(end_time)
  279. # 存储查询时间范围用于返回
  280. query_time_range['start_time'] = start_time.isoformat()
  281. query_time_range['end_time'] = end_time.isoformat()
  282. # 创建基础查询集
  283. queryset = MaterialChangeHistory.objects.filter(
  284. change_time__gte=start_time,
  285. change_time__lte=end_time
  286. )
  287. # 如果有物料ID过滤
  288. if material_ids_code:
  289. queryset = queryset.filter(goods_code__icontains=material_ids_code)
  290. # 获取每个物料的期初和期末数量(直接从过滤集中获取)
  291. material_codes = queryset.values_list('goods_code', flat=True).distinct()
  292. opening_closing_data = {}
  293. for code in material_codes:
  294. # 获取该物料在时间段内的第一条记录(最早记录)
  295. first_record = queryset.filter(goods_code=code).order_by('change_time').first()
  296. # 获取该物料在时间段内的最后一条记录(最晚记录)
  297. last_record = queryset.filter(goods_code=code).order_by('-change_time').first()
  298. # 期初数量 = 第一条记录的期初数量
  299. # 期末数量 = 最后一条记录的期末数量
  300. opening_closing_data[code] = {
  301. 'opening_quantity': first_record.opening_quantity,
  302. 'closing_quantity': last_record.closing_quantity
  303. }
  304. # 计算期间出入库总量
  305. period_data = queryset.values('goods_code').annotate(
  306. total_in=Sum('in_quantity'),
  307. total_out=Sum('out_quantity')
  308. )
  309. # 构建结果字典
  310. result = {}
  311. for item in period_data:
  312. material_code = item['goods_code']
  313. goods = MaterialChangeHistory.objects.filter(goods_code=material_code).first()
  314. # 获取该物料的期初和期末数量
  315. oc_data = opening_closing_data.get(material_code, {
  316. 'opening_quantity': Decimal('0'),
  317. 'closing_quantity': Decimal('0')
  318. })
  319. result[material_code] = {
  320. 'material_code': material_code,
  321. 'goods_code': goods.goods_code if goods else 'N/A',
  322. 'goods_desc': goods.goods_desc if goods else 'N/A',
  323. 'goods_unit': goods.goods_unit if goods else 'N/A',
  324. 'opening_quantity': oc_data['opening_quantity'],
  325. 'closing_quantity': oc_data['closing_quantity'],
  326. 'total_in': item['total_in'] or Decimal('0'),
  327. 'total_out': item['total_out'] or Decimal('0'),
  328. 'net_change': Decimal('0'), # 后面计算
  329. 'theoretical_change': Decimal('0'), # 后面计算
  330. 'is_consistent': True
  331. }
  332. # 计算净含量变化和理论变化量,并进行一致性校验
  333. for material_code, data in result.items():
  334. # 净含量变化 = 期末 - 期初
  335. net_change = data['closing_quantity'] - data['opening_quantity']
  336. data['net_change'] = net_change
  337. # 理论变化量 = 入库 - 出库
  338. theoretical_change = data['total_in'] - data['total_out']
  339. data['theoretical_change'] = theoretical_change
  340. # 检查是否一致(允许小数点后3位的差异)
  341. tolerance = Decimal('0.001')
  342. data['is_consistent'] = abs(net_change - theoretical_change) <= tolerance
  343. # 转换为列表格式
  344. result_list = list(result.values())
  345. # 应用分页
  346. response_data = {
  347. 'query_time_range': query_time_range,
  348. 'count': len(result_list),
  349. 'results': result_list # 返回所有结果,不分页
  350. }
  351. return Response(response_data)
  352. def summary(self, request):
  353. """
  354. 获取物料库存变动汇总数据(支持分页)
  355. """
  356. # 获取请求参数
  357. start_time = request.query_params.get('start_time') or None
  358. end_time = request.query_params.get('end_time') or None
  359. material_ids_code = request.query_params.get('goods_code__icontains') or None
  360. # 记录查询时间范围
  361. query_time_range = {}
  362. # 如果没有提供时间段,使用当前月份
  363. if not start_time or not end_time:
  364. today = timezone.now().date()
  365. start_time = datetime(today.year, today.month, 1)
  366. end_time = start_time + timedelta(days=32)
  367. end_time = datetime(end_time.year, end_time.month, 1) - timedelta(days=1)
  368. end_time = datetime.combine(end_time, datetime.max.time())
  369. query_time_range['default_time_range'] = True
  370. else:
  371. query_time_range['default_time_range'] = False
  372. # 转换为datetime对象
  373. if isinstance(start_time, str):
  374. start_time = datetime.fromisoformat(start_time)
  375. if isinstance(end_time, str):
  376. end_time = datetime.fromisoformat(end_time)
  377. # 存储查询时间范围用于返回
  378. query_time_range['start_time'] = start_time.isoformat()
  379. query_time_range['end_time'] = end_time.isoformat()
  380. # 创建基础查询集
  381. queryset = MaterialChangeHistory.objects.filter(
  382. change_time__gte=start_time,
  383. change_time__lte=end_time
  384. )
  385. # 如果有物料ID过滤
  386. if material_ids_code:
  387. queryset = queryset.filter(goods_code__icontains=material_ids_code)
  388. # 获取每个物料的期初和期末数量(直接从过滤集中获取)
  389. material_codes = queryset.values_list('goods_code', flat=True).distinct()
  390. opening_closing_data = {}
  391. for code in material_codes:
  392. # 获取该物料在时间段内的第一条记录(最早记录)
  393. first_record = queryset.filter(goods_code=code).order_by('change_time').first()
  394. # 获取该物料在时间段内的最后一条记录(最晚记录)
  395. last_record = queryset.filter(goods_code=code).order_by('-change_time').first()
  396. # 期初数量 = 第一条记录的期初数量
  397. # 期末数量 = 最后一条记录的期末数量
  398. opening_closing_data[code] = {
  399. 'opening_quantity': first_record.opening_quantity,
  400. 'closing_quantity': last_record.closing_quantity
  401. }
  402. # 计算期间出入库总量
  403. period_data = queryset.values('goods_code').annotate(
  404. total_in=Sum('in_quantity'),
  405. total_out=Sum('out_quantity')
  406. )
  407. # 构建结果字典
  408. result = {}
  409. for item in period_data:
  410. material_code = item['goods_code']
  411. goods = MaterialChangeHistory.objects.filter(goods_code=material_code).first()
  412. # 获取该物料的期初和期末数量
  413. oc_data = opening_closing_data.get(material_code, {
  414. 'opening_quantity': Decimal('0'),
  415. 'closing_quantity': Decimal('0')
  416. })
  417. result[material_code] = {
  418. 'material_code': material_code,
  419. 'goods_code': goods.goods_code if goods else 'N/A',
  420. 'goods_desc': goods.goods_desc if goods else 'N/A',
  421. 'goods_unit': goods.goods_unit if goods else 'N/A',
  422. 'opening_quantity': oc_data['opening_quantity'],
  423. 'closing_quantity': oc_data['closing_quantity'],
  424. 'total_in': item['total_in'] or Decimal('0'),
  425. 'total_out': item['total_out'] or Decimal('0'),
  426. 'net_change': Decimal('0'), # 后面计算
  427. 'theoretical_change': Decimal('0'), # 后面计算
  428. 'is_consistent': True
  429. }
  430. # 计算净含量变化和理论变化量,并进行一致性校验
  431. for material_code, data in result.items():
  432. # 净含量变化 = 期末 - 期初
  433. net_change = data['closing_quantity'] - data['opening_quantity']
  434. data['net_change'] = net_change
  435. # 理论变化量 = 入库 - 出库
  436. theoretical_change = data['total_in'] - data['total_out']
  437. data['theoretical_change'] = theoretical_change
  438. # 检查是否一致(允许小数点后3位的差异)
  439. tolerance = Decimal('0.001')
  440. data['is_consistent'] = abs(net_change - theoretical_change) <= tolerance
  441. # 转换为列表格式
  442. result_list = list(result.values())
  443. # 应用分页
  444. paginator = MyPageNumberPagination()
  445. page = paginator.paginate_queryset(result_list, request)
  446. # 构建响应数据
  447. response_data = {
  448. 'query_time_range': query_time_range,
  449. 'count': len(result_list),
  450. 'next': paginator.get_next_link(),
  451. 'previous': paginator.get_previous_link(),
  452. 'results': page
  453. }
  454. return Response(response_data)
  455. class MaterialChangeHistoryDownloadView(viewsets.ModelViewSet):
  456. renderer_classes = (MaterialChangeHistoryRenderCN, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)
  457. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  458. ordering_fields = ['id', "change_time", "create_time", "update_time", ]
  459. filter_class = MaterialChangeHistoryFilter
  460. def get_project(self):
  461. try:
  462. id = self.kwargs.get('pk')
  463. return id
  464. except:
  465. return None
  466. def get_queryset(self):
  467. id = self.get_project()
  468. if self.request.user:
  469. if id is None:
  470. return MaterialChangeHistory.objects.filter()
  471. else:
  472. return MaterialChangeHistory.objects.filter(id=id)
  473. else:
  474. return MaterialChangeHistory.objects.none()
  475. def get_serializer_class(self):
  476. if self.action in ['list']:
  477. return serializers.MaterialChangeHistorySerializer
  478. else:
  479. return self.http_method_not_allowed(request=self.request)
  480. def get_render(self, data):
  481. # lang = self.request.META.get('HTTP_LANGUAGE')
  482. # if lang:
  483. # if lang == 'zh-hans':
  484. # return FileListRenderCN().render(data)
  485. # else:
  486. # return FileListRenderEN().render(data)
  487. # else:
  488. # return FileListRenderEN().render(data)
  489. return MaterialChangeHistoryRenderCN().render(data)
  490. def list(self, request, *args, **kwargs):
  491. from datetime import datetime
  492. dt = datetime.now()
  493. data = (
  494. serializers.MaterialChangeHistorySerializer(instance).data
  495. for instance in self.filter_queryset(self.get_queryset())
  496. )
  497. renderer = self.get_render(data)
  498. response = StreamingHttpResponse(
  499. renderer,
  500. content_type="text/csv"
  501. )
  502. response['Content-Disposition'] = "attachment; filename='MaterialChangeHistory_{}.csv'".format(str(dt.strftime('%Y%m%d%H%M%S%f')))
  503. return response
  504. class batchLogViewSet(viewsets.ModelViewSet):
  505. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  506. ordering_fields = ['id', "create_time", "update_time", ]
  507. filter_class = batchLogFilter
  508. pagination_class = MyPageNumberPagination
  509. def get_queryset(self):
  510. return batchLogModel.objects.all()
  511. def get_serializer_class(self):
  512. if self.action in ['list', 'create']:
  513. return serializers.batchLogSerializer
  514. else:
  515. return self.http_method_not_allowed(request=self.request)
  516. class batchLogDownloadView(viewsets.ModelViewSet):
  517. renderer_classes = (batchLogRenderCN, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)
  518. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  519. ordering_fields = ['id', "create_time", "update_time", ]
  520. filter_class = batchLogFilter
  521. def get_project(self):
  522. try:
  523. id = self.kwargs.get('pk')
  524. return id
  525. except:
  526. return None
  527. def get_queryset(self):
  528. id = self.get_project()
  529. if self.request.user:
  530. if id is None:
  531. return batchLogModel.objects.filter()
  532. else:
  533. return batchLogModel.objects.filter(id=id)
  534. else:
  535. return batchLogModel.objects.none()
  536. def get_serializer_class(self):
  537. if self.action in ['list']:
  538. return serializers.batchLogSerializer
  539. else:
  540. return self.http_method_not_allowed(request=self.request)
  541. def get_render(self, data):
  542. # lang = self.request.META.get('HTTP_LANGUAGE')
  543. # if lang:
  544. # if lang == 'zh-hans':
  545. # return FileListRenderCN().render(data)
  546. # else:
  547. # return FileListRenderEN().render(data)
  548. # else:
  549. # return FileListRenderEN().render(data)
  550. return batchLogRenderCN().render(data)
  551. def list(self, request, *args, **kwargs):
  552. from datetime import datetime
  553. dt = datetime.now()
  554. data = (
  555. serializers.batchLogSerializer(instance).data
  556. for instance in self.filter_queryset(self.get_queryset()))
  557. renderer = self.get_render(data)
  558. response = StreamingHttpResponse(
  559. renderer,
  560. content_type="text/csv"
  561. )
  562. response['Content-Disposition'] = "attachment; filename='batchLog_{}.csv'".format(str(dt.strftime('%Y%m%d%H%M%S%f')))
  563. return response
  564. class ContainerDetailLogViewSet(viewsets.ModelViewSet):
  565. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  566. ordering_fields = ['id', "create_time", "update_time", ]
  567. filter_class = ContainerDetailLogFilter
  568. pagination_class = MyPageNumberPagination
  569. def get_queryset(self):
  570. return ContainerDetailLogModel.objects.all()
  571. def get_serializer_class(self):
  572. if self.action in ['list', 'create']:
  573. return serializers.ContainerDetailLogSerializer
  574. else:
  575. return self.http_method_not_allowed(request=self.request)
  576. class ContainerDetailLogDownloadView(viewsets.ModelViewSet):
  577. renderer_classes = (ContainerDetailLogRenderCN, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)
  578. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  579. ordering_fields = ['id', "create_time", "update_time", ]
  580. filter_class = ContainerDetailLogFilter
  581. def get_project(self):
  582. try:
  583. id = self.kwargs.get('pk')
  584. return id
  585. except:
  586. return None
  587. def get_queryset(self):
  588. id = self.get_project()
  589. if self.request.user:
  590. if id is None:
  591. return ContainerDetailLogModel.objects.filter()
  592. else:
  593. return ContainerDetailLogModel.objects.filter(id=id)
  594. else:
  595. return ContainerDetailLogModel.objects.none()
  596. def get_serializer_class(self):
  597. if self.action in ['list']:
  598. return serializers.ContainerDetailLogSerializer
  599. else:
  600. return self.http_method_not_allowed(request=self.request)
  601. def get_render(self, data):
  602. # lang = self.request.META.get('HTTP_LANGUAGE')
  603. # if lang:
  604. # if lang == 'zh-hans':
  605. # return FileListRenderCN().render(data)
  606. # else:
  607. # return FileListRenderEN().render(data)
  608. # else:
  609. # return FileListRenderEN().render(data)
  610. return ContainerDetailLogRenderCN().render(data)
  611. def list(self, request, *args, **kwargs):
  612. from datetime import datetime
  613. dt = datetime.now()
  614. data = (
  615. serializers.ContainerDetailLogSerializer(instance).data
  616. for instance in self.filter_queryset(self.get_queryset()))
  617. renderer = self.get_render(data)
  618. response = StreamingHttpResponse(
  619. renderer,
  620. content_type="text/csv"
  621. )
  622. response['Content-Disposition'] = "attachment; filename='ContainerDetailLog_{}.csv'".format(str(dt.strftime('%Y%m%d%H%M%S%f')))
  623. return response
  624. class FileListDownloadView(viewsets.ModelViewSet):
  625. renderer_classes = (FileFlowListRenderCN, ) + tuple(api_settings.DEFAULT_RENDERER_CLASSES)
  626. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  627. ordering_fields = ['id', "document_date" ]
  628. filter_class = FlowFilter
  629. def get_project(self):
  630. try:
  631. id = self.kwargs.get('pk')
  632. return id
  633. except:
  634. return None
  635. def get_queryset(self):
  636. id = self.get_project()
  637. if self.request.user:
  638. if id is None:
  639. return flowlist.objects.filter()
  640. else:
  641. return flowlist.objects.filter(id=id)
  642. else:
  643. return flowlist.objects.none()
  644. def get_serializer_class(self):
  645. if self.action in ['list']:
  646. return serializers.flowSerializer
  647. else:
  648. return self.http_method_not_allowed(request=self.request)
  649. def get_render(self, data):
  650. # lang = self.request.META.get('HTTP_LANGUAGE')
  651. # if lang:
  652. # if lang == 'zh-hans':
  653. # return FileListRenderCN().render(data)
  654. # else:
  655. # return FileListRenderEN().render(data)
  656. # else:
  657. # return FileListRenderEN().render(data)
  658. return FileFlowListRenderCN().render(data)
  659. def list(self, request, *args, **kwargs):
  660. from datetime import datetime
  661. dt = datetime.now()
  662. data = (
  663. serializers.flowSerializer(instance).data
  664. for instance in self.filter_queryset(self.get_queryset())
  665. )
  666. renderer = self.get_render(data)
  667. response = StreamingHttpResponse(
  668. renderer,
  669. content_type="text/csv"
  670. )
  671. response['Content-Disposition'] = "attachment; filename='stocklist_{}.csv'".format(str(dt.strftime('%Y%m%d%H%M%S%f')))
  672. return response
  673. class FlowsStatsViewSet(viewsets.ModelViewSet):
  674. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  675. ordering_fields = ['id', "create_time", "update_time", ]
  676. filter_class = FlowFilter
  677. pagination_class = MyPageNumberPagination
  678. """
  679. list:
  680. Response a data list(all)
  681. post:
  682. Create a new data(create)
  683. """
  684. def get_project(self):
  685. try:
  686. id = self.kwargs.get('pk')
  687. return id
  688. except:
  689. return None
  690. def get_queryset(self):
  691. id = self.get_project()
  692. if self.request.user:
  693. if id is None:
  694. return flowlist.objects.filter()
  695. else:
  696. return flowlist.objects.filter(id=id)
  697. else:
  698. return flowlist.objects.none()
  699. def get_serializer_class(self):
  700. if self.action in ['list', 'create', ]:
  701. return serializers.flowSerializer
  702. # elif self.action in ['retrieve','update',]:
  703. # return serializers.stocklistpartialSerializer
  704. else:
  705. return self.http_method_not_allowed(request=self.request)
  706. # def create(self, request, *args, **kwargs):
  707. # data = request.data.copy()
  708. # warehouse_code = data.get('warehouse_code')
  709. # warehouse_name = data.get('warehouse_name')
  710. # shelf_type = data.get('shelf_type')
  711. # shelf_name = data.get('shelf_name')
  712. # rows = int(data.get('rows', 0))
  713. # cols = int(data.get('cols', 0))
  714. # layers = int(data.get('layers', 0))
  715. # existing_positions = flowlist.get_existing_positions(warehouse_code,shelf_name, rows, cols, layers)
  716. # # 生成所有可能的坐标
  717. # instances = []
  718. # for r in range(1, rows+1):
  719. # for c in range(1, cols+1):
  720. # for l in range(1, layers+1):
  721. # if (r, c, l) not in existing_positions :
  722. # instances.append(flowlist(
  723. # warehouse_code=warehouse_code,
  724. # warehouse_name=warehouse_name,
  725. # shelf_type=shelf_type,
  726. # shelf_name=shelf_name,
  727. # row=r,
  728. # col=c,
  729. # layer=l,
  730. # ))
  731. # try:
  732. # with transaction.atomic():
  733. # flowlist.objects.bulk_create(instances, batch_size=1000)
  734. # except Exception as e:
  735. # return Response(
  736. # {"error": str(e)},
  737. # status=status.HTTP_500_INTERNAL_SERVER_ERROR
  738. # )
  739. # return Response({
  740. # "created": len(instances),
  741. # "skipped": (rows*cols*layers) - len(instances)
  742. # }, status=status.HTTP_201_CREATED)
  743. # def update(self, request, pk):
  744. # qs = self.get_object()
  745. # print(qs.id)
  746. # # return Response({"detail": "暂不支持修改"}, status=status.HTTP_400_BAD_REQUEST)
  747. # data = self.request.data
  748. # print(data)
  749. # serializer = self.get_serializer(qs, data=data)
  750. # serializer.is_valid(raise_exception=True)
  751. # serializer.save()
  752. # headers = self.get_success_headers(serializer.data)
  753. # return Response(serializer.data, status=200, headers=headers)
  754. # def retrieve(self, request, pk):
  755. # qs = self.get_object()
  756. # serializer = self.get_serializer(qs)
  757. # return Response(serializer.data)
  758. class bigScreenModelViewSet(viewsets.ModelViewSet):
  759. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  760. ordering_fields = ['id', "create_time", "update_time", ]
  761. filter_class = bigScreenFilter
  762. pagination_class = MyPageNumberPagination
  763. def get_project(self):
  764. try:
  765. id = self.kwargs.get('pk')
  766. return id
  767. except:
  768. return None
  769. def get_queryset(self):
  770. id = self.get_project()
  771. if self.request.user:
  772. if id is None:
  773. return bigScreenModel.objects.filter()
  774. else:
  775. return bigScreenModel.objects.filter(id=id)
  776. else:
  777. return bigScreenModel.objects.none()
  778. def get_serializer_class(self):
  779. if self.action in ['list', 'create', ]:
  780. return serializers.bigScreenSerializer
  781. # elif self.action in ['retrieve','update',]:
  782. # return serializers.stocklistpartialSerializer
  783. else:
  784. return self.http_method_not_allowed(request=self.request)