Ei kuvausta

views.py 39KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. from django.shortcuts import render, redirect, get_object_or_404
  2. from django.core.paginator import Paginator
  3. from django.contrib import messages
  4. from core.models import Report, AllProductDimensionForInsProcess
  5. from core.forms import ReportForm
  6. from core.utils import ConfigurableCRUDView, queryFromMaster
  7. from .filters import ReportFilter
  8. from .forms import ExportOptionsForm
  9. from pprint import pprint
  10. from legacy.models import Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData, TbFgPressinfoLotlist,\
  11. Manualsize
  12. from .gen_report import gen_xlsx
  13. from django.core.files.base import File
  14. from pathlib import Path
  15. from django.views.decorators.csrf import csrf_exempt
  16. from django.http import JsonResponse, HttpResponseBadRequest
  17. import json
  18. from django.contrib.auth.decorators import login_required
  19. from django.contrib.auth.models import User
  20. from legacy.models import Data
  21. from django.conf import settings
  22. from itertools import chain
  23. def index(request):
  24. reports = Report.objects.all()
  25. report_filter = ReportFilter(request.GET, queryset=reports)
  26. # Paginate the filtered queryset
  27. paginator = Paginator(report_filter.qs, 10) # Show 10 reports per page
  28. page_number = request.GET.get('page')
  29. page_obj = paginator.get_page(page_number)
  30. context = {
  31. 'filter': report_filter,
  32. 'page_obj': page_obj,
  33. }
  34. return render(request, 'report/index.html', context)
  35. def report_create_view(request):
  36. if request.method == "POST":
  37. form = ReportForm(request.POST)
  38. if form.is_valid():
  39. form.save()
  40. messages.success(request, "Report created successfully!")
  41. return redirect("report:report_index") # Adjust with your report list view name
  42. else:
  43. form = ReportForm()
  44. return render(request, "report/create.html", {"form": form})
  45. class ReportCRUDView(ConfigurableCRUDView):
  46. model = Report
  47. list_template_name = 'legacy/datacrud_list.html'
  48. detail_template_name = 'legacy/datacrud_detail.html'
  49. form_template_name = 'report/report_form.html'
  50. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  51. filterset_class = ReportFilter
  52. page_title = "Reports"
  53. # URL name mappings
  54. list_url_name = 'report:report-list'
  55. create_url_name = 'report:report-create'
  56. update_url_name = 'report:report-update'
  57. delete_url_name = 'report:report-delete'
  58. config_fields = ["name", "file", "created_by", "created_at"]
  59. config_field_orders = ["id", "name", "created_by"]
  60. # config_readonly_fields = ["lot_no"]
  61. # config_edit_fields = ["lot_no", "code"]
  62. ordering = ["-created_at", "-id",]
  63. def convert_sheet_data(sheet_data):
  64. """
  65. Convert sheet_data to the required form with prefixed keys.
  66. :param sheet_data: Dictionary with sheet names as keys and their data as values.
  67. :return: Dictionary in the required key-value format.
  68. """
  69. converted_data = {}
  70. for sheet_name, data in sheet_data.items():
  71. for key, value in data.items():
  72. # Prefix each key with the sheet name
  73. converted_key = f"{sheet_name}.{key}"
  74. converted_data[converted_key] = value
  75. return converted_data
  76. def hide_con(placeholders, mark_value, hide_rows):
  77. """
  78. Updates the 'placeholders' dictionary with a mark value and hide rows range.
  79. :param placeholders: The dictionary to update.
  80. :param mark_value: The key to check or update in the placeholders.
  81. :param hide_rows: The row range to append in the format '[start:end]'.
  82. """
  83. if mark_value in placeholders:
  84. placeholders[mark_value] = f"{placeholders[mark_value]}[{hide_rows}]"
  85. else:
  86. placeholders[mark_value] = f"0[{hide_rows}]"
  87. def clear_values(n, m):
  88. placeholders = {}
  89. for i in range(1, n + 1):
  90. for j in range(1, m + 1):
  91. placeholders[f'v{i}_{j}'] = " "
  92. return placeholders
  93. def generate_hardness_out_values(lot_no, code):
  94. """
  95. Generate a dictionary of placeholder values for a given lot_no.
  96. :param lot_no: The lot number to query data for.
  97. :return: A dictionary with placeholders (e.g., v1_1, v1_2, ...) as keys and their respective values.
  98. """
  99. # Query the Data model for records matching the given lot_no
  100. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  101. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  102. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  103. records = list(chain(data_h1, data_h2))
  104. # print(f"records {lot_no} = {records.values()}")
  105. # Initialize an empty dictionary to store placeholder values
  106. placeholders = clear_values(2,5)
  107. # Iterate over the records to populate placeholder values
  108. for record_idx, record in enumerate(records, start=1):
  109. placeholders[f'v{record_idx}_1'] = record.p1 # Checkpoint 1 value
  110. placeholders[f'v{record_idx}_2'] = record.p2 # Checkpoint 2 value
  111. placeholders[f'v{record_idx}_3'] = record.p3 # Checkpoint 3 value
  112. placeholders[f'v{record_idx}_4'] = record.avg # Average value
  113. placeholders[f'v{record_idx}_5'] = record.rgrade # Judgment value
  114. return placeholders
  115. def generate_hardness_out_in_values(lot_no, code):
  116. # Fetch records from the Data model
  117. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  118. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  119. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  120. records = list(chain(data_h1, data_h2))
  121. out_data = []
  122. in_data = []
  123. # Separate OUT and IN data
  124. for record in records:
  125. if record.r_type.upper() in ["OUT", "TOP", "FA1", "UPP", "UPPE", "RIM"]:
  126. out_data.append(record)
  127. elif record.r_type.upper() in ["IN", "UNDER", "UND", "FA2", "LOW", "LOWE", "BASE", "SOKO", "IN*"]:
  128. in_data.append(record)
  129. # Prepare placeholders
  130. # placeholders = {}
  131. placeholders = clear_values(4,5)
  132. for idx, record in enumerate(out_data, start=1):
  133. placeholders[f'v{idx}_1'] = record.p1
  134. placeholders[f'v{idx}_2'] = record.p2
  135. placeholders[f'v{idx}_3'] = record.p3
  136. placeholders[f'v{idx}_4'] = record.avg
  137. placeholders[f'v{idx}_5'] = record.rgrade
  138. for idx, record in enumerate(in_data, start=1):
  139. placeholders[f'v{len(out_data) + idx}_1'] = record.p1
  140. placeholders[f'v{len(out_data) + idx}_2'] = record.p2
  141. placeholders[f'v{len(out_data) + idx}_3'] = record.p3
  142. placeholders[f'v{len(out_data) + idx}_4'] = record.avg
  143. placeholders[f'v{len(out_data) + idx}_5'] = record.rgrade
  144. # if "v3_1" in placeholders:
  145. # placeholders["v3_1"] = f"{placeholders['v3_1']}[25:28]"
  146. # else:
  147. # placeholders[f"v3_1"] = "0[25:28]"
  148. hide_con(placeholders, "v3_1", "25:28")
  149. return placeholders
  150. def generate_hardness_both_size_values(lot_no, ms,code):
  151. # Fetch records from the Data model
  152. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  153. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no', 'sub_order'))
  154. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no', 'sub_order'))
  155. records = list(chain(data_h1, data_h2))
  156. out_data = []
  157. in_data = []
  158. placeholders = clear_values(20,5)
  159. # Separate OUT and IN data
  160. for idx, record in enumerate(records, start=0):
  161. if record.sub_order == 1:
  162. for i,v in enumerate(["p1", "p2", "p3", "avg", "rgrade"],start=1):
  163. placeholders[f"v{idx*2+1}_{i}"] = getattr(record,v)
  164. if record.sub_order == 2:
  165. for i,v in enumerate(["p1", "p2", "p3", "avg", "rgrade"],start=1):
  166. placeholders[f"v{idx*2+2}_{i}"] = getattr(record,v)
  167. # Prepare placeholders
  168. # placeholders = {}
  169. return placeholders
  170. # # Example usage:
  171. # placeholders_dict = clear_values(6, 3)
  172. # print(placeholders_dict)
  173. def generate_dimension_values(lot_no, code):
  174. """
  175. Fetch dimension records from manualSize and DataMs models
  176. and generate placeholder values for Standard, Actual, and Judgement.
  177. Supports two row_no entries per lot.
  178. """
  179. # Fetch standard values from manualSize (limit to 2 rows)
  180. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  181. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  182. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  183. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  184. # Prepare placeholders
  185. # placeholders = {}
  186. placeholders = clear_values(7,4)
  187. # for i in range(1,7):
  188. # for j in range(1,4):
  189. # placeholders[f'v{i}_{j}'] = 0
  190. pprint(placeholders)
  191. pprint(manual_size_records)
  192. for m in dimens:
  193. if m.Size_Name == "D":
  194. placeholders['v1_1'] = placeholders['v4_1'] = f'D{m.Std} +{m.TolUp} {m.TolUn}'
  195. if m.Size_Name == "T":
  196. placeholders['v2_1'] = placeholders['v5_1'] = f'T{m.Std} +{m.TolUp} {m.TolUn}'
  197. if m.Size_Name == "H":
  198. placeholders['v3_1'] = placeholders['v6_1'] = f'H{m.Std} +{m.TolUp} {m.TolUn}'
  199. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  200. for r in data_ms_records:
  201. if r.row_no == 1:
  202. placeholders[f'v1_2'] = r.dsize
  203. placeholders[f'v1_3'] = r.dsizeok
  204. placeholders[f'v2_2'] = r.tsize
  205. placeholders[f'v2_3'] = r.tsizeok
  206. placeholders[f'v3_2'] = r.hsize
  207. placeholders[f'v3_3'] = r.hsizeok
  208. if r.row_no == 2:
  209. placeholders[f'v4_2'] = r.dsize
  210. placeholders[f'v4_3'] = r.dsizeok
  211. placeholders[f'v5_2'] = r.tsize
  212. placeholders[f'v5_3'] = r.tsizeok
  213. placeholders[f'v6_2'] = r.hsize
  214. placeholders[f'v6_3'] = r.hsizeok
  215. hide_con(placeholders, "v4_1", "24:28")
  216. return placeholders
  217. def is_ok(instance):
  218. fields_and_values = {}
  219. for field in instance._meta.get_fields():
  220. field_name = field.name
  221. if field_name.endswith('ok'):
  222. v = getattr(instance, field_name)
  223. if v is not None and v != "OK":
  224. return False
  225. return True
  226. def generate_dimension_app_values(lot_no, code):
  227. """
  228. Fetch dimension records from manualSize and DataMs models
  229. and generate placeholder values for Standard, Actual, and Judgement.
  230. Supports two row_no entries per lot.
  231. """
  232. # Fetch standard values from manualSize (limit to 2 rows)
  233. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  234. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  235. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  236. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  237. # Prepare placeholders
  238. # placeholders = {}
  239. placeholders = clear_values(8,3)
  240. # for i in range(1,7):
  241. # for j in range(1,4):
  242. # placeholders[f'v{i}_{j}'] = 0
  243. pprint(placeholders)
  244. pprint(manual_size_records)
  245. # for m in manual_size_records:
  246. # if m.size_name == "D":
  247. # placeholders['v1_1'] = placeholders['v5_1'] = f'{m.std} +{m.tolup} {m.tolun}'
  248. # if m.size_name == "T":
  249. # placeholders['v2_1'] = placeholders['v6_1'] = f'{m.std} +{m.tolup} {m.tolun}'
  250. # if m.size_name == "H":
  251. # placeholders['v3_1'] = placeholders['v7_1'] = f'{m.std} +{m.tolup} {m.tolun}'
  252. for m in dimens: # Changed from manual_size_records to dimens
  253. if m.Size_Name == "D":
  254. placeholders['v1_1'] = placeholders['v5_1'] = f'D{m.Std} +{m.TolUp} {m.TolUn}'
  255. if m.Size_Name == "T":
  256. placeholders['v2_1'] = placeholders['v6_1'] = f'T{m.Std} +{m.TolUp} {m.TolUn}'
  257. if m.Size_Name == "H":
  258. placeholders['v3_1'] = placeholders['v7_1'] = f'H{m.Std} +{m.TolUp} {m.TolUn}'
  259. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  260. for r in data_ms_records:
  261. if r.row_no == 1:
  262. placeholders[f'v1_2'] = r.dsize
  263. placeholders[f'v1_3'] = r.dsizeok
  264. placeholders[f'v2_2'] = r.tsize
  265. placeholders[f'v2_3'] = r.tsizeok
  266. placeholders[f'v3_2'] = r.hsize
  267. placeholders[f'v3_3'] = r.hsizeok
  268. # if is_ok(r):
  269. # placeholders[f'v4_1'] = 'OK'
  270. # placeholders[f'v4_2'] = 'OK'
  271. # else:
  272. # placeholders[f'v4_1'] = 'NG'
  273. # placeholders[f'v4_2'] = 'OK'
  274. if r.row_no == 2:
  275. placeholders[f'v5_2'] = r.dsize
  276. placeholders[f'v5_3'] = r.dsizeok
  277. placeholders[f'v6_2'] = r.tsize
  278. placeholders[f'v6_3'] = r.tsizeok
  279. placeholders[f'v7_2'] = r.hsize
  280. placeholders[f'v7_3'] = r.hsizeok
  281. # if is_ok(r):
  282. # placeholders[f'v8_1'] = 'OK'
  283. # placeholders[f'v8_2'] = 'OK'
  284. # else:
  285. # placeholders[f'v8_1'] = 'NG'
  286. # placeholders[f'v8_2'] = 'NG'
  287. hide_con(placeholders, "v5_1", "26:32")
  288. return placeholders
  289. def generate_dimension_bal_weight_values(lot_no, ms, code):
  290. """
  291. Fetch dimension records from manualSize and DataMs models
  292. and generate placeholder values for Standard, Actual, and Judgement.
  293. Supports two row_no entries per lot.
  294. """
  295. # Fetch standard values from manualSize (limit to 2 rows)
  296. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  297. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  298. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  299. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  300. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  301. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  302. data_ho = list(chain(data_h1, data_h2))
  303. # Prepare placeholders
  304. # placeholders = {}
  305. placeholders = clear_values(10,3)
  306. # for i in range(1,7):
  307. # for j in range(1,4):
  308. # placeholders[f'v{i}_{j}'] = 0
  309. pprint(placeholders)
  310. pprint(manual_size_records)
  311. if ms:
  312. w = ms.PRO6
  313. placeholders['v4_1'] = placeholders['v9_1'] = w
  314. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  315. for m in dimens: # Changed from manual_size_records to dimens
  316. if m.Size_Name == "D":
  317. placeholders['v1_1'] = placeholders['v6_1'] = f'D{m.Std} +{m.TolUp} {m.TolUn}'
  318. if m.Size_Name == "T":
  319. placeholders['v2_1'] = placeholders['v7_1'] = f'T{m.Std} +{m.TolUp} {m.TolUn}'
  320. if m.Size_Name == "H":
  321. placeholders['v3_1'] = placeholders['v8_1'] = f'H{m.Std} +{m.TolUp} {m.TolUn}'
  322. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  323. for r in data_ms_records:
  324. if r.row_no == 1:
  325. placeholders[f'v1_2'] = r.dsize
  326. placeholders[f'v1_3'] = r.dsizeok
  327. placeholders[f'v2_2'] = r.tsize
  328. placeholders[f'v2_3'] = r.tsizeok
  329. placeholders[f'v3_2'] = r.hsize
  330. placeholders[f'v3_3'] = r.hsizeok
  331. # if is_ok(r):
  332. # placeholders[f'v4_1'] = 'OK'
  333. # placeholders[f'v4_2'] = 'OK'
  334. # else:
  335. # placeholders[f'v4_1'] = 'NG'
  336. # placeholders[f'v4_2'] = 'OK'
  337. if r.row_no == 2:
  338. placeholders[f'v6_2'] = r.dsize
  339. placeholders[f'v6_3'] = r.dsizeok
  340. placeholders[f'v7_2'] = r.tsize
  341. placeholders[f'v7_3'] = r.tsizeok
  342. placeholders[f'v8_2'] = r.hsize
  343. placeholders[f'v8_3'] = r.hsizeok
  344. # if is_ok(r):
  345. # placeholders[f'v8_1'] = 'OK'
  346. # placeholders[f'v8_2'] = 'OK'
  347. # else:
  348. # placeholders[f'v8_1'] = 'NG'
  349. # placeholders[f'v8_2'] = 'NG'
  350. for r in data_wb:
  351. if r.row_no == 1:
  352. placeholders["v4_2"] = r.result
  353. placeholders["v4_3"] = r.judgement
  354. placeholders["v5_2"] = r.weight
  355. placeholders["v5_3"] = r.judgement
  356. if r.row_no == 2:
  357. placeholders["v9_2"] = r.result
  358. placeholders["v9_3"] = r.judgement
  359. placeholders["v10_2"] = r.weight
  360. placeholders["v10_3"] = r.judgement
  361. # hide_con(placeholders, "v5_1", "26:32")
  362. return placeholders
  363. def generate_dim_bal_app_hard_values(lot_no, first_result, code):
  364. """
  365. Fetch dimension records from manualSize and DataMs models
  366. and generate placeholder values for Standard, Actual, and Judgement.
  367. Supports two row_no entries per lot.
  368. """
  369. # Fetch standard values from manualSize (limit to 2 rows)
  370. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  371. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  372. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  373. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  374. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  375. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  376. data_ho = list(chain(data_h1, data_h2))
  377. if first_result:
  378. out_limit = f"Out 外 ({first_result.MI18} - {first_result.MI19})"
  379. in_limit = f"In 内 ({first_result.MI22} - {first_result.MI23})"
  380. mid_limit = f"Middle 中 -"
  381. else:
  382. out_limit = f"Out 外"
  383. in_limit = f"In 内"
  384. mid_limit = f"Middle 中"
  385. # Prepare placeholders
  386. # placeholders = {}
  387. placeholders = clear_values(16,5)
  388. # for i in range(1,7):
  389. # for j in range(1,4):
  390. # placeholders[f'v{i}_{j}'] = 0
  391. placeholders['v6_0'] = placeholders['v14_0'] = out_limit
  392. placeholders['v7_0'] = placeholders['v15_0'] = mid_limit
  393. placeholders['v18_0'] = placeholders['v16_0'] = in_limit
  394. pprint(placeholders)
  395. pprint(manual_size_records)
  396. if first_result:
  397. w = first_result.PRO6
  398. placeholders['v4_1'] = placeholders['v12_1'] = w
  399. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  400. for m in dimens: # Changed from manual_size_records to dimens
  401. if m.Size_Name == "D":
  402. placeholders['v1_1'] = placeholders['v9_1'] = f'D{m.Std} +{m.TolUp} {m.TolUn}'
  403. if m.Size_Name == "T":
  404. placeholders['v2_1'] = placeholders['v10_1'] = f'T{m.Std} +{m.TolUp} {m.TolUn}'
  405. if m.Size_Name == "H":
  406. placeholders['v3_1'] = placeholders['v11_1'] = f'H{m.Std} +{m.TolUp} {m.TolUn}'
  407. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  408. for r in data_ms_records:
  409. if r.row_no == 1:
  410. placeholders[f'v1_2'] = r.dsize
  411. placeholders[f'v1_3'] = r.dsizeok
  412. placeholders[f'v2_2'] = r.tsize
  413. placeholders[f'v2_3'] = r.tsizeok
  414. placeholders[f'v3_2'] = r.hsize
  415. placeholders[f'v3_3'] = r.hsizeok
  416. # if is_ok(r):
  417. # placeholders[f'v4_1'] = 'OK'
  418. # placeholders[f'v4_2'] = 'OK'
  419. # else:
  420. # placeholders[f'v4_1'] = 'NG'
  421. # placeholders[f'v4_2'] = 'OK'
  422. if r.row_no == 2:
  423. placeholders[f'v9_2'] = r.dsize
  424. placeholders[f'v9_3'] = r.dsizeok
  425. placeholders[f'v10_2'] = r.tsize
  426. placeholders[f'v10_3'] = r.tsizeok
  427. placeholders[f'v11_2'] = r.hsize
  428. placeholders[f'v11_3'] = r.hsizeok
  429. # if is_ok(r):
  430. # placeholders[f'v8_1'] = 'OK'
  431. # placeholders[f'v8_2'] = 'OK'
  432. # else:
  433. # placeholders[f'v8_1'] = 'NG'
  434. # placeholders[f'v8_2'] = 'NG'
  435. for r in data_wb:
  436. if r.row_no == 1:
  437. placeholders["v4_2"] = r.weight
  438. placeholders["v4_3"] = r.judgement
  439. if r.row_no == 2:
  440. placeholders["v12_2"] = r.weight
  441. placeholders["v12_3"] = r.judgement
  442. for r in data_ho:
  443. if r.row_no == 1:
  444. rmap = {'OUT': 6, 'MID': 7, 'IN': 8}
  445. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  446. idx = rmap.get(r.r_type, None)
  447. if idx:
  448. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  449. if r.row_no == 2:
  450. rmap = {'OUT': 14, 'MID': 15, 'IN': 16}
  451. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  452. idx = rmap.get(r.r_type, None)
  453. if idx:
  454. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  455. # hide_con(placeholders, "v5_1", "26:32")
  456. return placeholders
  457. def generate_dim_bal_app_rot_hard_values(lot_no, first_result, code):
  458. """
  459. Fetch dimension records from manualSize and DataMs models
  460. and generate placeholder values for Standard, Actual, and Judgement.
  461. Supports two row_no entries per lot.
  462. """
  463. # Fetch standard values from manualSize (limit to 2 rows)
  464. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  465. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  466. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  467. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  468. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  469. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  470. data_ho = list(chain(data_h1, data_h2))
  471. rotates = RotateData.objects.filter(lot_no=lot_no).order_by('row_no')
  472. if first_result:
  473. out_limit = f"Out 外 ({first_result.MI18} - {first_result.MI19})"
  474. in_limit = f"In 内 ({first_result.MI22} - {first_result.MI23})"
  475. mid_limit = f"Middle 中 -"
  476. else:
  477. out_limit = f"Out 外"
  478. in_limit = f"In 内"
  479. mid_limit = f"Middle 中"
  480. # Prepare placeholders
  481. # placeholders = {}
  482. placeholders = clear_values(18,5)
  483. # for i in range(1,7):
  484. # for j in range(1,4):
  485. # placeholders[f'v{i}_{j}'] = 0
  486. placeholders['v6_0'] = placeholders['v14_0'] = out_limit
  487. placeholders['v7_0'] = placeholders['v15_0'] = mid_limit
  488. placeholders['v18_0'] = placeholders['v16_0'] = in_limit
  489. pprint(placeholders)
  490. pprint(manual_size_records)
  491. if first_result:
  492. w = first_result.PRO6
  493. placeholders['v4_1'] = placeholders['v13_1'] = w
  494. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  495. for m in dimens: # Changed from manual_size_records to dimens
  496. if m.Size_Name == "D":
  497. placeholders['v1_1'] = placeholders['v10_1'] = f'D{m.Std} +{m.TolUp} {m.TolUn}'
  498. if m.Size_Name == "T":
  499. placeholders['v2_1'] = placeholders['v11_1'] = f'T{m.Std} +{m.TolUp} {m.TolUn}'
  500. if m.Size_Name == "H":
  501. placeholders['v3_1'] = placeholders['v12_1'] = f'H{m.Std} +{m.TolUp} {m.TolUn}'
  502. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  503. for r in data_ms_records:
  504. if r.row_no == 1:
  505. placeholders[f'v1_2'] = r.dsize
  506. placeholders[f'v1_3'] = r.dsizeok
  507. placeholders[f'v2_2'] = r.tsize
  508. placeholders[f'v2_3'] = r.tsizeok
  509. placeholders[f'v3_2'] = r.hsize
  510. placeholders[f'v3_3'] = r.hsizeok
  511. # if is_ok(r):
  512. # placeholders[f'v4_1'] = 'OK'
  513. # placeholders[f'v4_2'] = 'OK'
  514. # else:
  515. # placeholders[f'v4_1'] = 'NG'
  516. # placeholders[f'v4_2'] = 'OK'
  517. if r.row_no == 2:
  518. placeholders[f'v10_2'] = r.dsize
  519. placeholders[f'v10_3'] = r.dsizeok
  520. placeholders[f'v11_2'] = r.tsize
  521. placeholders[f'v11_3'] = r.tsizeok
  522. placeholders[f'v12_2'] = r.hsize
  523. placeholders[f'v12_3'] = r.hsizeok
  524. # if is_ok(r):
  525. # placeholders[f'v8_1'] = 'OK'
  526. # placeholders[f'v8_2'] = 'OK'
  527. # else:
  528. # placeholders[f'v8_1'] = 'NG'
  529. # placeholders[f'v8_2'] = 'NG'
  530. for r in data_wb:
  531. if r.row_no == 1:
  532. placeholders["v4_2"] = r.weight
  533. placeholders["v4_3"] = r.judgement
  534. if r.row_no == 2:
  535. placeholders["v13_2"] = r.weight
  536. placeholders["v13_3"] = r.judgement
  537. for r in data_ho:
  538. if r.row_no == 1:
  539. rmap = {'OUT': 7, 'MID': 8, 'IN': 9}
  540. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  541. idx = rmap.get(r.r_type, None)
  542. if idx:
  543. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  544. if r.row_no == 2:
  545. rmap = {'OUT': 16, 'MID': 17, 'IN': 18}
  546. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  547. idx = rmap.get(r.r_type, None)
  548. if idx:
  549. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  550. for r in rotates:
  551. if r.row_no == 1:
  552. placeholders["v6_1"] = r.speed_spec
  553. placeholders["v6_2"] = r.speed_test
  554. placeholders["v6_3"] = r.speedok
  555. if r.row_no == 2:
  556. placeholders["v15_1"] = r.speed_spec
  557. placeholders["v15_2"] = r.speed_test
  558. placeholders["v15_3"] = r.speedok
  559. # hide_con(placeholders, "v5_1", "26:32")
  560. return placeholders
  561. def generate_centering_values(lot_no, code):
  562. """
  563. Fetch dimension records from manualSize and DataMs models
  564. and generate placeholder values for Standard, Actual, and Judgement.
  565. Supports two row_no entries per lot.
  566. """
  567. # Fetch standard values from manualSize (limit to 2 rows)
  568. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  569. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  570. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  571. # Prepare placeholders
  572. # placeholders = {}
  573. placeholders = clear_values(10,3)
  574. # for i in range(1,7):
  575. # for j in range(1,4):
  576. # placeholders[f'v{i}_{j}'] = 0
  577. pprint(placeholders)
  578. pprint(manual_size_records)
  579. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  580. for i,r in enumerate(data_ms_records, start=1):
  581. placeholders[f'v{i}_2'] = r.censize
  582. placeholders[f'v{i}_3'] = r.censizeok
  583. return placeholders
  584. def generate_t8_values(lot_no, code):
  585. """
  586. Fetch dimension records from manualSize and DataMs models
  587. and generate placeholder values for Standard, Actual, and Judgement.
  588. Supports two row_no entries per lot.
  589. """
  590. # Fetch standard values from manualSize (limit to 2 rows)
  591. placeholders = clear_values(8,10)
  592. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  593. # pprint(f"manual_size = {manual_size_records}")
  594. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  595. for m in dimens: # Changed from manual_size_records to dimens
  596. if m.Size_Name == "Thickness":
  597. for i in range(1, 9):
  598. placeholders[f'v{i}_1'] = f'{m.Std} +{m.TolUp} {m.TolUn}'
  599. # pprint("set std")
  600. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  601. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  602. # Prepare placeholders
  603. # placeholders = {}
  604. # for i in range(1,7):
  605. # for j in range(1,4):
  606. # placeholders[f'v{i}_{j}'] = 0
  607. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  608. for i,r in enumerate(data_ms_records, start=1):
  609. placeholders[f'v{i}_2'] = r.tpoint1
  610. placeholders[f'v{i}_3'] = r.tpoint2
  611. placeholders[f'v{i}_4'] = r.tpoint3
  612. placeholders[f'v{i}_5'] = r.tpoint4
  613. placeholders[f'v{i}_10'] = r.tdiff
  614. return placeholders
  615. def merge_sheet_data_with_data(sheet_data, data):
  616. """
  617. Merge `sheet_data` with `data`.
  618. :param sheet_data: Dictionary containing the sheet-specific data.
  619. :param data: Dictionary containing general data.
  620. :return: A merged dictionary combining both `sheet_data` and `data`.
  621. """
  622. # Merge dictionaries using unpacking
  623. merged_data = {**data, **sheet_data}
  624. return merged_data
  625. def create_coi_file(lot_no, sheets, user, md):
  626. pprint("---- create_coi_file ---")
  627. pprint(md)
  628. qa1 = User.objects.get(pk=md['qa1'])
  629. qa2 = User.objects.get(pk=md['qa2'])
  630. accept = specialAccept = False
  631. if md['acceptStatus'] == "accepted":
  632. accept = True
  633. if md['acceptStatus'] == "special_accepted":
  634. specialAccept = True
  635. pprint(qa1)
  636. pprint(qa2)
  637. results = queryFromMaster(lot_no)
  638. first_result = results[0] if results else None
  639. code = first_result.PRO1 if first_result else None
  640. sheet_data = {}
  641. for sheet_name in sheets:
  642. if sheet_name == 'hardness_out':
  643. sheet_data[sheet_name] = generate_hardness_out_values(lot_no, code)
  644. elif sheet_name == 'hardness_out_in':
  645. sheet_data[sheet_name] = generate_hardness_out_in_values(lot_no, code)
  646. elif sheet_name == 'hardness_both_size':
  647. sheet_data[sheet_name] = generate_hardness_both_size_values(lot_no, first_result, code)
  648. elif sheet_name == 'dimension':
  649. sheet_data[sheet_name] = generate_dimension_values(lot_no, code)
  650. elif sheet_name == 'dimension_app':
  651. sheet_data[sheet_name] = generate_dimension_app_values(lot_no, code)
  652. elif sheet_name == 'dimension_bal_weight':
  653. sheet_data[sheet_name] = generate_dimension_bal_weight_values(lot_no, first_result, code)
  654. elif sheet_name == 'centering':
  655. sheet_data[sheet_name] = generate_centering_values(lot_no, code)
  656. elif sheet_name == 'thickness_8_point':
  657. sheet_data[sheet_name] = generate_t8_values(lot_no, code)
  658. elif sheet_name == 'dim_bal_app_hard':
  659. sheet_data[sheet_name] = generate_dim_bal_app_hard_values(lot_no, first_result, code)
  660. elif sheet_name == 'dim_bal_app_rot_hard':
  661. sheet_data[sheet_name] = generate_dim_bal_app_rot_hard_values(lot_no, first_result, code)
  662. converted_data = convert_sheet_data(sheet_data)
  663. print(f"sheet_data \n {sheet_data}")
  664. print(f"converted_data \n {converted_data}")
  665. # results = queryFromMaster(lot_no)
  666. # first_result = results[0] if results else None
  667. try:
  668. pcs = int(first_result.PRO5) - int(first_result.PRO27)
  669. except:
  670. pcs = 0
  671. if first_result:
  672. size_str = f"{first_result.PRO10}x{first_result.PRO11}x{first_result.PRO12}";
  673. spec = f"{first_result.PRO13} {first_result.PRO14} {first_result.PRO15} {first_result.PRO16} {first_result.PRO17} {first_result.PRO18}"
  674. else:
  675. size_str = ""
  676. spec = ""
  677. data = {
  678. "code": first_result.PRO1 if first_result else "-",
  679. "customer": first_result.PRO1C if first_result else "-",
  680. "inspect_date": "2025-01-15",
  681. "lot_no": lot_no,
  682. "size": size_str,
  683. "lot_size": pcs,
  684. "spec": spec,
  685. # "hardness_out.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  686. # "hardness_out.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
  687. "acc": accept, # Hide rows 24 to 28 if the prefix is "0"
  688. "spe_acc": specialAccept, # Hide rows 24 to 28 if the prefix is "0"
  689. # "hardness_out.qa1": f"{qa1.first_name} {qa1.last_name}",
  690. # "hardness_out.qa2": f"{qa2.first_name} {qa2.last_name}",
  691. "qa1": f"{qa1.first_name} {qa1.last_name}",
  692. "qa2": f"{qa2.first_name} {qa2.last_name}",
  693. "sign1": qa1.profile.signed_picture,
  694. "sign2": qa2.profile.signed_picture,
  695. "pos1": qa1.profile.get_position_display(),
  696. "pos2": qa2.profile.get_position_display()
  697. }
  698. merged_data = merge_sheet_data_with_data(converted_data, data)
  699. pprint(f"---- merged_data ---")
  700. pprint(merged_data)
  701. output_file = gen_xlsx(
  702. template_file=f"{settings.BASE_DIR}/report/coi_templates.xlsx",
  703. selected_sheets=sheets, # Replace with your actual sheet names
  704. prefix_filename=f"{settings.BASE_DIR}/media/coi_{lot_no}_",
  705. data=merged_data
  706. )
  707. report = Report.objects.create(
  708. name=lot_no,
  709. created_by=user,
  710. file=None # Leave this as None or assign a file if required
  711. )
  712. output_file_path = Path(output_file) # Convert to a Path object for convenience
  713. with open(output_file_path, "rb") as f:
  714. report.file.save(output_file_path.name, File(f), save=True)
  715. pprint(f"outputfile = {output_file}")
  716. return report
  717. SHEET_NAMES = {
  718. 'hardness_out': 'Hardness Out',
  719. 'hardness_out_in': 'Hardness Out/In',
  720. 'hardness_both_size': 'Hardness Both Size',
  721. 'dimension': 'Dimension',
  722. 'dimension_app': 'Dimension Appearance',
  723. 'dimension_bal_weight': 'Dimension Balance/Weight',
  724. 'dim_bal_app_hard': 'Dimension Balance/Appearance/Hardness',
  725. 'dim_bal_app_rot_hard': 'Dimension Balance/Appearance/Rotation/Hardness',
  726. 'thickness_8_point': 'Thickness 8 Points',
  727. 'centering': 'Centering',
  728. }
  729. def get_fields(model):
  730. # model_fields = {f.name: f for f in model._meta.get_fields()}
  731. # fields = list(model_fields.values())
  732. # return fields
  733. fields = [f for f in model._meta.get_fields() if not f.auto_created]
  734. return fields
  735. def filter_by_lot_no(lot_no):
  736. models = [Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData ] # List of models to process
  737. results = {}
  738. fields = {}
  739. for model in models:
  740. model_fields = [f.name for f in model._meta.get_fields()]
  741. # Check if "id" and "row_no" are in the model's fields
  742. order_fields = []
  743. if "id" in model_fields:
  744. order_fields.append("id")
  745. if "row_no" in model_fields:
  746. order_fields.append("row_no")
  747. # Dynamically filter and order results
  748. model_name = model.__name__
  749. if order_fields:
  750. results[model_name] = model.objects.filter(lot_no=lot_no).order_by(*order_fields)
  751. else:
  752. results[model_name] = model.objects.filter(lot_no=lot_no) # No
  753. fields[model_name] = get_fields(model)
  754. return results, fields
  755. def coi_view(request):
  756. pprint(f"xxxx method = xxx {request.method}")
  757. users = User.objects.all()
  758. if request.method == "POST":
  759. pprint(request.POST)
  760. exports = request.POST.getlist("exports") # Retrieve the list of selected values
  761. pprint(f"Selected Export Options: {exports}")
  762. if 'export' in request.POST:
  763. data = {
  764. "customer": "Tum Coder",
  765. "inspect_date": "2025-01-15",
  766. "lot_no": "12345",
  767. "staff_name": "Tum 8888",
  768. "man_name": "Tum 999",
  769. "size": "Large",
  770. "lot_size": "10 pcs",
  771. "spec": "Spec-A",
  772. "hardness_out.d1_act": "10",
  773. "hardness_out.d2_act": "0[24:28]", # Hide rows 24 to 28 if the prefix is "0"
  774. "hardness_out.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  775. "hardness_out.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
  776. "dimension_app.d1_act": "33",
  777. "dimension_app.d2_act": "0[26:32]", # Hide rows 24 to 28 if the prefix is "0"
  778. "dimension_app.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  779. "dimension_app.spe_acc": True, # Hide rows 24 to 28 if the prefix is "0"
  780. }
  781. output_file = gen_xlsx(
  782. template_file="/app/report/coi_templates.xlsx",
  783. selected_sheets=exports, # Replace with your actual sheet names
  784. prefix_filename="/app/media/coi",
  785. data=data
  786. )
  787. report = Report.objects.create(
  788. name=request.POST.get('lot_no','Untitled'),
  789. created_by=request.user,
  790. file=None # Leave this as None or assign a file if required
  791. )
  792. output_file_path = Path(output_file) # Convert to a Path object for convenience
  793. with open(output_file_path, "rb") as f:
  794. report.file.save(output_file_path.name, File(f), save=True)
  795. pprint(f"outputfile = {output_file}")
  796. if 'search_lot' in request.POST:
  797. lot_no = request.POST.get('lot_no', None)
  798. lot_no = lot_no.strip()
  799. if lot_no:
  800. results = queryFromMaster(lot_no)
  801. first_result = results[0] if results else None
  802. try:
  803. pcs = int(first_result.PRO5) - int(first_result.PRO27)
  804. except:
  805. pcs = 0
  806. if first_result:
  807. size_str = f"{first_result.PRO10}x{first_result.PRO11}x{first_result.PRO12}";
  808. spec = f"{first_result.PRO13} {first_result.PRO14} {first_result.PRO15} {first_result.PRO16} {first_result.PRO17} {first_result.PRO18}"
  809. else:
  810. size_str = ""
  811. spec = ""
  812. results, fields = filter_by_lot_no(lot_no)
  813. # results1 = Data.objects.filter(lot_no=lot_no).order_by("id", "row_no")
  814. # fields1 = get_fields(Data)
  815. # results2 = DataMs.objects.filter(lot_no=lot_no).order_by("id", "row_no")
  816. # fields2 = get_fields(DataMs)
  817. return render(request, 'report/coi.html', {'result': first_result,
  818. 'pcs':pcs,
  819. 'size_str': size_str,
  820. 'lot_no': lot_no,
  821. 'spec': spec, 'users': users, 'SHEET_NAMES': SHEET_NAMES,
  822. 'results': results, 'fields': fields})
  823. messages.success(request, "Request Sent")
  824. return redirect(request.path_info)
  825. return render(request, 'report/coi.html', {'SHEET_NAMES': SHEET_NAMES, 'users': users})
  826. @csrf_exempt # Disable CSRF for API requests (ensure this is secure in production)
  827. @login_required
  828. def gen_report_view(request):
  829. if request.method == "POST":
  830. # try:
  831. # Parse JSON data from the request body
  832. data = json.loads(request.body)
  833. lot_no = data.get("lot_no").strip()
  834. exports = data.get("exports")
  835. qa1 = data.get('qa1')
  836. qa2 = data.get('qa2')
  837. print(f"data = {data}")
  838. if not lot_no:
  839. return HttpResponseBadRequest("Missing 'lot_no' in request data")
  840. # Call the `create_coi_file` function with the provided lot_no
  841. report = create_coi_file(lot_no, exports, request.user, {'qa1': qa1, 'qa2': qa2, \
  842. 'acceptStatus': data.get('acceptStatus')})
  843. # Return a success response with the report details
  844. return JsonResponse({
  845. "message": "Report generated successfully",
  846. "report_id": report.id,
  847. "file_url": report.file.url if report.file else None,
  848. })
  849. # except json.JSONDecodeError:
  850. # return HttpResponseBadRequest("Invalid JSON data")
  851. # except Exception as e:
  852. # pprint(e)
  853. # return JsonResponse({"error": str(e)}, status=500)
  854. else:
  855. return HttpResponseBadRequest("Only POST requests are allowed")