Нема описа

views.py 59KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550
  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, CustomerTemplateMapping, \
  5. ProductDrawing, MksCodeMap
  6. from core.forms import ReportForm, CustomerTemplateMappingForm, ProductDrawingForm
  7. from core.utils import ConfigurableCRUDView, queryFromMaster, SHEET_NAMES, convert_mgt_to_mks
  8. from .filters import ReportFilter, CustomerTemplateFilter, ProductDrawingFilter, MksCodeMapFilter
  9. from .forms import ExportOptionsForm
  10. from pprint import pprint
  11. from legacy.models import Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData, TbFgPressinfoLotlist,\
  12. Manualsize
  13. from .gen_report import gen_xlsx
  14. from django.core.files.base import File
  15. from pathlib import Path
  16. from django.views.decorators.csrf import csrf_exempt
  17. from django.http import JsonResponse, HttpResponseBadRequest
  18. import json
  19. from django.contrib.auth.decorators import login_required
  20. from django.contrib.auth.models import User
  21. from sysadmin.models import UserProfile
  22. from legacy.models import Data
  23. from django.conf import settings
  24. from itertools import chain
  25. from django_filters.views import FilterView
  26. from django.db.models import Q, Func, Value, F
  27. from django.views.generic import (
  28. ListView,)
  29. COI_TEMPLATE_FILES = {
  30. "japanese": "coi_templates.xlsx",
  31. "asean": "coi_templates_en.xlsx",
  32. }
  33. def get_coi_template_file(template_name):
  34. template_key = (template_name or "japanese").lower()
  35. filename = COI_TEMPLATE_FILES.get(template_key, COI_TEMPLATE_FILES["japanese"])
  36. return f"{settings.BASE_DIR}/report/{filename}"
  37. def get_customer_template_mapping(master_row):
  38. if not master_row or not master_row.PRO1C:
  39. return None
  40. return CustomerTemplateMapping.objects.filter(
  41. customer_name__icontains=master_row.PRO1C
  42. ).first()
  43. def index(request):
  44. reports = Report.objects.all()
  45. report_filter = ReportFilter(request.GET, queryset=reports)
  46. # Paginate the filtered queryset
  47. paginator = Paginator(report_filter.qs, 10) # Show 10 reports per page
  48. page_number = request.GET.get('page')
  49. page_obj = paginator.get_page(page_number)
  50. context = {
  51. 'filter': report_filter,
  52. 'page_obj': page_obj,
  53. }
  54. return render(request, 'report/index.html', context)
  55. def report_create_view(request):
  56. if request.method == "POST":
  57. form = ReportForm(request.POST)
  58. if form.is_valid():
  59. form.save()
  60. messages.success(request, "Report created successfully!")
  61. return redirect("report:report_index") # Adjust with your report list view name
  62. else:
  63. form = ReportForm()
  64. return render(request, "report/create.html", {"form": form})
  65. class ReportCRUDView(ConfigurableCRUDView):
  66. model = Report
  67. list_template_name = 'legacy/datacrud_list.html'
  68. detail_template_name = 'legacy/datacrud_detail.html'
  69. form_template_name = 'report/report_form.html'
  70. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  71. filterset_class = ReportFilter
  72. page_title = "Reports"
  73. # URL name mappings
  74. list_url_name = 'report:report-list'
  75. create_url_name = 'report:report-create'
  76. update_url_name = 'report:report-update'
  77. delete_url_name = 'report:report-delete'
  78. config_fields = ["name", "file", "created_by", "created_at"]
  79. config_field_orders = ["id", "name", "created_by"]
  80. # config_readonly_fields = ["lot_no"]
  81. # config_edit_fields = ["lot_no", "code"]
  82. ordering = ["-created_at", "-id",]
  83. def convert_sheet_data(sheet_data):
  84. """
  85. Convert sheet_data to the required form with prefixed keys.
  86. :param sheet_data: Dictionary with sheet names as keys and their data as values.
  87. :return: Dictionary in the required key-value format.
  88. """
  89. converted_data = {}
  90. for sheet_name, data in sheet_data.items():
  91. for key, value in data.items():
  92. # Prefix each key with the sheet name
  93. converted_key = f"{sheet_name}.{key}"
  94. converted_data[converted_key] = value
  95. return converted_data
  96. def hide_con(placeholders, mark_value, hide_rows):
  97. """
  98. Updates the 'placeholders' dictionary with a mark value and hide rows range.
  99. :param placeholders: The dictionary to update.
  100. :param mark_value: The key to check or update in the placeholders.
  101. :param hide_rows: The row range to append in the format '[start:end]'.
  102. """
  103. if mark_value in placeholders:
  104. placeholders[mark_value] = f"{placeholders[mark_value]}[{hide_rows}]"
  105. else:
  106. placeholders[mark_value] = f"0[{hide_rows}]"
  107. def clear_values(n, m):
  108. placeholders = {}
  109. for i in range(1, n + 1):
  110. for j in range(1, m + 1):
  111. placeholders[f'v{i}_{j}'] = " "
  112. return placeholders
  113. def generate_hardness_out_values(lot_no, code):
  114. """
  115. Generate a dictionary of placeholder values for a given lot_no.
  116. :param lot_no: The lot number to query data for.
  117. :return: A dictionary with placeholders (e.g., v1_1, v1_2, ...) as keys and their respective values.
  118. """
  119. # Query the Data model for records matching the given lot_no
  120. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  121. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  122. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  123. records = list(chain(data_h1, data_h2))
  124. # print(f"records {lot_no} = {records.values()}")
  125. # Initialize an empty dictionary to store placeholder values
  126. placeholders = clear_values(2,5)
  127. # Iterate over the records to populate placeholder values
  128. inspect_date = None
  129. for record_idx, record in enumerate(records, start=1):
  130. if record_idx == 1:
  131. inspect_date = record.created_at
  132. placeholders[f'v{record_idx}_1'] = record.p1 # Checkpoint 1 value
  133. placeholders[f'v{record_idx}_2'] = record.p2 # Checkpoint 2 value
  134. placeholders[f'v{record_idx}_3'] = record.p3 # Checkpoint 3 value
  135. placeholders[f'v{record_idx}_4'] = record.avg # Average value
  136. placeholders[f'v{record_idx}_5'] = record.rgrade # Judgment value
  137. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  138. return placeholders
  139. def generate_hardness_out_in_values(lot_no, code):
  140. # Fetch records from the Data model
  141. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  142. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  143. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  144. records = list(chain(data_h1, data_h2))
  145. out_data = []
  146. in_data = []
  147. # Separate OUT and IN data
  148. for record in records:
  149. if record.r_type.upper() in ["OUT", "TOP", "FA1", "UPP", "UPPE", "RIM"]:
  150. out_data.append(record)
  151. elif record.r_type.upper() in ["IN", "UNDER", "UND", "FA2", "LOW", "LOWE", "BASE", "SOKO", "IN*", "INNER"]:
  152. in_data.append(record)
  153. # Prepare placeholders
  154. # placeholders = {}
  155. placeholders = clear_values(4,6)
  156. inspect_date = None
  157. for idx, record in enumerate(out_data, start=0):
  158. if idx == 1:
  159. inspect_date = record.created_at
  160. placeholders[f'v{2*idx+1}_1'] = record.p1
  161. placeholders[f'v{2*idx+1}_2'] = record.p2
  162. placeholders[f'v{2*idx+1}_3'] = record.p3
  163. placeholders[f'v{2*idx+1}_6'] = record.p4 # Checkpoint 3 value
  164. placeholders[f'v{2*idx+1}_4'] = record.avg
  165. placeholders[f'v{2*idx+1}_5'] = record.rgrade
  166. for idx, record in enumerate(in_data, start=1):
  167. placeholders[f'v{idx*2}_1'] = record.p1
  168. placeholders[f'v{idx*2}_2'] = record.p2
  169. placeholders[f'v{idx*2}_3'] = record.p3
  170. placeholders[f'v{idx*2}_6'] = record.p4
  171. placeholders[f'v{idx*2}_4'] = record.avg
  172. placeholders[f'v{idx*2}_5'] = record.rgrade
  173. # if "v3_1" in placeholders:
  174. # placeholders["v3_1"] = f"{placeholders['v3_1']}[25:28]"
  175. # else:
  176. # placeholders[f"v3_1"] = "0[25:28]"
  177. hide_con(placeholders, "v3_1", "26:29")
  178. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  179. return placeholders
  180. def generate_hardness_both_size_values(lot_no, ms,code):
  181. # Fetch records from the Data model
  182. # records = Data.objects.filter(lot_no=lot_no).order_by('row_no')
  183. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no', 'sub_order'))
  184. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no', 'sub_order'))
  185. records = list(chain(data_h1, data_h2))
  186. out_data = []
  187. in_data = []
  188. placeholders = clear_values(20,5)
  189. # Separate OUT and IN data
  190. inspect_date = None
  191. for idx, record in enumerate(records, start=0):
  192. if idx == 1:
  193. inspect_date = record.created_at
  194. if record.sub_order == 1:
  195. for i,v in enumerate(["p1", "p2", "p3", "avg", "rgrade"],start=1):
  196. placeholders[f"v{idx*2+1}_{i}"] = getattr(record,v)
  197. if record.sub_order == 2:
  198. for i,v in enumerate(["p1", "p2", "p3", "avg", "rgrade"],start=1):
  199. placeholders[f"v{idx*2+2}_{i}"] = getattr(record,v)
  200. # Prepare placeholders
  201. # placeholders = {}
  202. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  203. return placeholders
  204. # # Example usage:
  205. # placeholders_dict = clear_values(6, 3)
  206. # print(placeholders_dict)
  207. def generate_dimension_values(lot_no, code):
  208. """
  209. Fetch dimension records from manualSize and DataMs models
  210. and generate placeholder values for Standard, Actual, and Judgement.
  211. Supports two row_no entries per lot.
  212. """
  213. # Fetch standard values from manualSize (limit to 2 rows)
  214. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  215. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  216. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  217. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  218. # Prepare placeholders
  219. # placeholders = {}
  220. placeholders = clear_values(7,4)
  221. # for i in range(1,7):
  222. # for j in range(1,4):
  223. # placeholders[f'v{i}_{j}'] = 0
  224. pprint(placeholders)
  225. pprint(manual_size_records)
  226. for m in dimens:
  227. if m.Size_Name == "D":
  228. placeholders['v1_1'] = placeholders['v4_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  229. if m.Size_Name == "T":
  230. placeholders['v2_1'] = placeholders['v5_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  231. if m.Size_Name == "H":
  232. placeholders['v3_1'] = placeholders['v6_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  233. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  234. inspect_date = None
  235. for r in data_ms_records:
  236. if r.row_no == 1:
  237. placeholders[f'v1_2'] = r.dsize
  238. placeholders[f'v1_3'] = r.dsizeok
  239. placeholders[f'v2_2'] = r.tsize
  240. placeholders[f'v2_3'] = r.tsizeok
  241. placeholders[f'v3_2'] = r.hsize
  242. placeholders[f'v3_3'] = r.hsizeok
  243. inspect_date = r.created_at
  244. if r.row_no == 2:
  245. placeholders[f'v4_2'] = r.dsize
  246. placeholders[f'v4_3'] = r.dsizeok
  247. placeholders[f'v5_2'] = r.tsize
  248. placeholders[f'v5_3'] = r.tsizeok
  249. placeholders[f'v6_2'] = r.hsize
  250. placeholders[f'v6_3'] = r.hsizeok
  251. hide_con(placeholders, "v4_2", "25:29")
  252. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  253. return placeholders
  254. def generate_dimension_weight_warp_values(lot_no, code):
  255. """
  256. Fetch dimension records from manualSize and DataMs models
  257. and generate placeholder values for Standard, Actual, and Judgement.
  258. Supports two row_no entries per lot.
  259. """
  260. # Fetch standard values from manualSize (limit to 2 rows)
  261. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  262. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  263. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  264. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  265. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  266. # Prepare placeholders
  267. # placeholders = {}
  268. placeholders = clear_values(7,4)
  269. # for i in range(1,7):
  270. # for j in range(1,4):
  271. # placeholders[f'v{i}_{j}'] = 0
  272. pprint(placeholders)
  273. pprint(manual_size_records)
  274. for m in dimens:
  275. if m.Size_Name == "D":
  276. placeholders['v1_1'] = placeholders['v4_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  277. if m.Size_Name == "T":
  278. placeholders['v2_1'] = placeholders['v5_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  279. if m.Size_Name == "H":
  280. placeholders['v3_1'] = placeholders['v6_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  281. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  282. inspect_date = None
  283. for r in data_ms_records:
  284. if r.row_no == 1:
  285. placeholders[f'v1_2'] = r.dsize
  286. placeholders[f'v1_3'] = r.dsizeok
  287. placeholders[f'v2_2'] = r.tsize
  288. placeholders[f'v2_3'] = r.tsizeok
  289. placeholders[f'v3_2'] = r.hsize
  290. placeholders[f'v3_3'] = r.hsizeok
  291. inspect_date = r.created_at
  292. if r.row_no == 2:
  293. placeholders[f'v4_2'] = r.dsize
  294. placeholders[f'v4_3'] = r.dsizeok
  295. placeholders[f'v5_2'] = r.tsize
  296. placeholders[f'v5_3'] = r.tsizeok
  297. placeholders[f'v6_2'] = r.hsize
  298. placeholders[f'v6_3'] = r.hsizeok
  299. for r in data_wb:
  300. if r.row_no == 1:
  301. placeholders["v7_1"] = r.weight
  302. placeholders["v7_2"] = r.judgement
  303. if r.row_no == 2:
  304. placeholders["v8_1"] = r.weight
  305. placeholders["v8_2"] = r.judgement
  306. hide_con(placeholders, "v4_2", "29:37")
  307. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  308. return placeholders
  309. def is_ok(instance):
  310. fields_and_values = {}
  311. for field in instance._meta.get_fields():
  312. field_name = field.name
  313. if field_name.endswith('ok'):
  314. v = getattr(instance, field_name)
  315. if v is not None and v != "OK":
  316. return False
  317. return True
  318. def generate_dimension_app_values(lot_no, code):
  319. """
  320. Fetch dimension records from manualSize and DataMs models
  321. and generate placeholder values for Standard, Actual, and Judgement.
  322. Supports two row_no entries per lot.
  323. """
  324. # Fetch standard values from manualSize (limit to 2 rows)
  325. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  326. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  327. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  328. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  329. # Prepare placeholders
  330. # placeholders = {}
  331. placeholders = clear_values(8,3)
  332. # for i in range(1,7):
  333. # for j in range(1,4):
  334. # placeholders[f'v{i}_{j}'] = 0
  335. pprint(placeholders)
  336. pprint(manual_size_records)
  337. # for m in manual_size_records:
  338. # if m.size_name == "D":
  339. # placeholders['v1_1'] = placeholders['v5_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  340. # if m.size_name == "T":
  341. # placeholders['v2_1'] = placeholders['v6_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  342. # if m.size_name == "H":
  343. # placeholders['v3_1'] = placeholders['v7_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  344. for m in dimens: # Changed from manual_size_records to dimens
  345. if m.Size_Name == "D":
  346. placeholders['v1_1'] = placeholders['v5_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  347. if m.Size_Name == "T":
  348. placeholders['v2_1'] = placeholders['v6_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  349. if m.Size_Name == "H":
  350. placeholders['v3_1'] = placeholders['v7_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  351. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  352. inspect_date = None
  353. for r in data_ms_records:
  354. if r.row_no == 1:
  355. placeholders[f'v1_2'] = r.dsize
  356. placeholders[f'v1_3'] = r.dsizeok
  357. placeholders[f'v2_2'] = r.tsize
  358. placeholders[f'v2_3'] = r.tsizeok
  359. placeholders[f'v3_2'] = r.hsize
  360. placeholders[f'v3_3'] = r.hsizeok
  361. inspect_date = r.created_at
  362. # if is_ok(r):
  363. # placeholders[f'v4_1'] = 'OK'
  364. # placeholders[f'v4_2'] = 'OK'
  365. # else:
  366. # placeholders[f'v4_1'] = 'NG'
  367. # placeholders[f'v4_2'] = 'OK'
  368. if r.row_no == 2:
  369. placeholders[f'v5_2'] = r.dsize
  370. placeholders[f'v5_3'] = r.dsizeok
  371. placeholders[f'v6_2'] = r.tsize
  372. placeholders[f'v6_3'] = r.tsizeok
  373. placeholders[f'v7_2'] = r.hsize
  374. placeholders[f'v7_3'] = r.hsizeok
  375. # if is_ok(r):
  376. # placeholders[f'v8_1'] = 'OK'
  377. # placeholders[f'v8_2'] = 'OK'
  378. # else:
  379. # placeholders[f'v8_1'] = 'NG'
  380. # placeholders[f'v8_2'] = 'NG'
  381. hide_con(placeholders, "v5_1", "29:37")
  382. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  383. return placeholders
  384. def safe_strip(val):
  385. """Remove '-' or return '' if None."""
  386. return val.replace('-', '') if val else ''
  387. def generate_dimension_app_drawing_values(lot_no, code):
  388. """
  389. Fetch dimension records from manualSize and DataMs models
  390. and generate placeholder values for Standard, Actual, and Judgement.
  391. Supports two row_no entries per lot.
  392. """
  393. # Fetch standard values from manualSize (limit to 2 rows)
  394. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  395. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  396. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  397. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  398. # Prepare placeholders
  399. # placeholders = {}
  400. placeholders = clear_values(8,3)
  401. # for i in range(1,7):
  402. # for j in range(1,4):
  403. # placeholders[f'v{i}_{j}'] = 0
  404. pprint(placeholders)
  405. pprint(manual_size_records)
  406. # for m in manual_size_records:
  407. # if m.size_name == "D":
  408. # placeholders['v1_1'] = placeholders['v5_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  409. # if m.size_name == "T":
  410. # placeholders['v2_1'] = placeholders['v6_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  411. # if m.size_name == "H":
  412. # placeholders['v3_1'] = placeholders['v7_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  413. for m in dimens: # Changed from manual_size_records to dimens
  414. if m.Size_Name == "D":
  415. placeholders['v1_1'] = placeholders['v5_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  416. if m.Size_Name == "T":
  417. placeholders['v2_1'] = placeholders['v6_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  418. if m.Size_Name == "H":
  419. placeholders['v3_1'] = placeholders['v7_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  420. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  421. inspect_date = None
  422. for r in data_ms_records:
  423. if r.row_no == 1:
  424. placeholders[f'v1_2'] = r.dsize
  425. placeholders[f'v1_3'] = r.dsizeok
  426. placeholders[f'v2_2'] = r.tsize
  427. placeholders[f'v2_3'] = r.tsizeok
  428. placeholders[f'v3_2'] = r.hsize
  429. placeholders[f'v3_3'] = r.hsizeok
  430. inspect_date = r.created_at
  431. # if is_ok(r):
  432. # placeholders[f'v4_1'] = 'OK'
  433. # placeholders[f'v4_2'] = 'OK'
  434. # else:
  435. # placeholders[f'v4_1'] = 'NG'
  436. # placeholders[f'v4_2'] = 'OK'
  437. if r.row_no == 2:
  438. placeholders[f'v5_2'] = r.dsize
  439. placeholders[f'v5_3'] = r.dsizeok
  440. placeholders[f'v6_2'] = r.tsize
  441. placeholders[f'v6_3'] = r.tsizeok
  442. placeholders[f'v7_2'] = r.hsize
  443. placeholders[f'v7_3'] = r.hsizeok
  444. # if is_ok(r):
  445. # placeholders[f'v8_1'] = 'OK'
  446. # placeholders[f'v8_2'] = 'OK'
  447. # else:
  448. # placeholders[f'v8_1'] = 'NG'
  449. # placeholders[f'v8_2'] = 'NG'
  450. hide_con(placeholders, "v5_1", "27:33")
  451. norm_lot_no = safe_strip(lot_no)
  452. norm_code = safe_strip(code)
  453. drawing_qs = ProductDrawing.objects.annotate(
  454. norm_lot_no=Func(F('lot_no'), Value('-'), Value(''), function='replace'),
  455. norm_code_no=Func(F('code_no'), Value('-'), Value(''), function='replace')
  456. )
  457. query = Q()
  458. if norm_lot_no:
  459. query |= Q(norm_lot_no=norm_lot_no)
  460. if norm_code:
  461. query |= Q(norm_code_no=norm_code)
  462. drawing_data = drawing_qs.filter(query).first()
  463. pprint(f"1.1 = {drawing_data}")
  464. pprint(f"1.2 = {lot_no} {code}")
  465. if drawing_data:
  466. placeholders["drawing"] = drawing_data.drawing if drawing_data.drawing else "-"
  467. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  468. return placeholders
  469. def generate_dimension_bal_weight_values(lot_no, ms, code):
  470. """
  471. Fetch dimension records from manualSize and DataMs models
  472. and generate placeholder values for Standard, Actual, and Judgement.
  473. Supports two row_no entries per lot.
  474. """
  475. # Fetch standard values from manualSize (limit to 2 rows)
  476. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  477. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  478. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  479. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  480. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  481. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  482. data_ho = list(chain(data_h1, data_h2))
  483. # Prepare placeholders
  484. # placeholders = {}
  485. placeholders = clear_values(10,3)
  486. # for i in range(1,7):
  487. # for j in range(1,4):
  488. # placeholders[f'v{i}_{j}'] = 0
  489. pprint(placeholders)
  490. pprint(manual_size_records)
  491. if ms:
  492. try:
  493. w = ms.PRO6
  494. placeholders['v4_1'] = placeholders['v9_1'] = w
  495. except:
  496. print("no PRO6")
  497. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  498. for m in dimens: # Changed from manual_size_records to dimens
  499. if m.Size_Name == "D":
  500. placeholders['v1_1'] = placeholders['v6_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  501. if m.Size_Name == "T":
  502. placeholders['v2_1'] = placeholders['v7_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  503. if m.Size_Name == "H":
  504. placeholders['v3_1'] = placeholders['v8_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  505. inspect_date = None
  506. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  507. for r in data_ms_records:
  508. if r.row_no == 1:
  509. placeholders[f'v1_2'] = r.dsize
  510. placeholders[f'v1_3'] = r.dsizeok
  511. placeholders[f'v2_2'] = r.tsize
  512. placeholders[f'v2_3'] = r.tsizeok
  513. placeholders[f'v3_2'] = r.hsize
  514. placeholders[f'v3_3'] = r.hsizeok
  515. inspect_date = r.created_at
  516. # if is_ok(r):
  517. # placeholders[f'v4_1'] = 'OK'
  518. # placeholders[f'v4_2'] = 'OK'
  519. # else:
  520. # placeholders[f'v4_1'] = 'NG'
  521. # placeholders[f'v4_2'] = 'OK'
  522. if r.row_no == 2:
  523. placeholders[f'v6_2'] = r.dsize
  524. placeholders[f'v6_3'] = r.dsizeok
  525. placeholders[f'v7_2'] = r.tsize
  526. placeholders[f'v7_3'] = r.tsizeok
  527. placeholders[f'v8_2'] = r.hsize
  528. placeholders[f'v8_3'] = r.hsizeok
  529. # if is_ok(r):
  530. # placeholders[f'v8_1'] = 'OK'
  531. # placeholders[f'v8_2'] = 'OK'
  532. # else:
  533. # placeholders[f'v8_1'] = 'NG'
  534. # placeholders[f'v8_2'] = 'NG'
  535. for r in data_wb:
  536. if r.row_no == 1:
  537. placeholders["v4_2"] = r.result
  538. placeholders["v4_3"] = r.judgement
  539. placeholders["v5_2"] = r.weight
  540. placeholders["v5_3"] = r.judgement
  541. if r.row_no == 2:
  542. placeholders["v9_2"] = r.result
  543. placeholders["v9_3"] = r.judgement
  544. placeholders["v10_2"] = r.weight
  545. placeholders["v10_3"] = r.judgement
  546. # hide_con(placeholders, "v5_1", "26:32")
  547. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  548. return placeholders
  549. def generate_dim_bal_app_hard_values(lot_no, first_result, code):
  550. """
  551. Fetch dimension records from manualSize and DataMs models
  552. and generate placeholder values for Standard, Actual, and Judgement.
  553. Supports two row_no entries per lot.
  554. """
  555. # Fetch standard values from manualSize (limit to 2 rows)
  556. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  557. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  558. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  559. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  560. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  561. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  562. data_ho = list(chain(data_h1, data_h2))
  563. if first_result:
  564. # out_limit = f"Out 外 ({first_result.MI18} - {first_result.MI19})"
  565. # in_limit = f"In 内 ({first_result.MI22} - {first_result.MI23})"
  566. try:
  567. out_limit = f"Out 外 ({float(first_result.MI18):.2f} - {float(first_result.MI19):.2f})"
  568. except (TypeError, ValueError):
  569. out_limit = "Out 外"
  570. mi22 = getattr(first_result, "MI22", None)
  571. mi23 = getattr(first_result, "MI23", None)
  572. # If MI22 is missing, None, 0, or ""
  573. if mi22 in (None, 0, "", "0"):
  574. in_limit = "In 内: -"
  575. else:
  576. try:
  577. in_limit = f"In 内 ({float(mi22):.2f} - {float(mi23 or 0):.2f})"
  578. except (TypeError, ValueError):
  579. in_limit = "In 内: -"
  580. mid_limit = f"Middle 中 -"
  581. else:
  582. out_limit = f"Out 外"
  583. in_limit = f"In 内"
  584. mid_limit = f"Middle 中"
  585. # Prepare placeholders
  586. # placeholders = {}
  587. placeholders = clear_values(16,5)
  588. # for i in range(1,7):
  589. # for j in range(1,4):
  590. # placeholders[f'v{i}_{j}'] = 0
  591. placeholders['v6_0'] = placeholders['v14_0'] = out_limit
  592. placeholders['v7_0'] = placeholders['v15_0'] = mid_limit
  593. placeholders['v8_0'] = placeholders['v16_0'] = in_limit
  594. pprint(placeholders)
  595. pprint(manual_size_records)
  596. if first_result:
  597. try:
  598. w = first_result.MI24
  599. placeholders['v4_1'] = placeholders['v12_1'] = f"{w}"
  600. except:
  601. print("No PRO6")
  602. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  603. for m in dimens: # Changed from manual_size_records to dimens
  604. if m.Size_Name == "D":
  605. placeholders['v1_1'] = placeholders['v9_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f}/{m.TolUn:.2f}'
  606. if m.Size_Name == "T":
  607. placeholders['v2_1'] = placeholders['v10_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f}/{m.TolUn:.2f}'
  608. if m.Size_Name == "H":
  609. placeholders['v3_1'] = placeholders['v11_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f}/{m.TolUn:.2f}'
  610. inspect_date = None
  611. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  612. for r in data_ms_records:
  613. if r.row_no == 1:
  614. placeholders[f'v1_2'] = r.dsize
  615. placeholders[f'v1_3'] = r.dsizeok
  616. placeholders[f'v2_2'] = r.tsize
  617. placeholders[f'v2_3'] = r.tsizeok
  618. placeholders[f'v3_2'] = r.hsize
  619. placeholders[f'v3_3'] = r.hsizeok
  620. inspect_date = r.created_at
  621. # if is_ok(r):
  622. # placeholders[f'v4_1'] = 'OK'
  623. # placeholders[f'v4_2'] = 'OK'
  624. # else:
  625. # placeholders[f'v4_1'] = 'NG'
  626. # placeholders[f'v4_2'] = 'OK'
  627. if r.row_no == 2:
  628. placeholders[f'v9_2'] = r.dsize
  629. placeholders[f'v9_3'] = r.dsizeok
  630. placeholders[f'v10_2'] = r.tsize
  631. placeholders[f'v10_3'] = r.tsizeok
  632. placeholders[f'v11_2'] = r.hsize
  633. placeholders[f'v11_3'] = r.hsizeok
  634. # if is_ok(r):
  635. # placeholders[f'v8_1'] = 'OK'
  636. # placeholders[f'v8_2'] = 'OK'
  637. # else:
  638. # placeholders[f'v8_1'] = 'NG'
  639. # placeholders[f'v8_2'] = 'NG'
  640. for r in data_wb:
  641. if r.row_no == 1:
  642. placeholders["v4_2"] = f"{r.weight:.1f}"
  643. placeholders["v4_3"] = r.judgement
  644. if r.row_no == 2:
  645. placeholders["v12_2"] = f"{r.weight:.1f}"
  646. placeholders["v12_3"] = r.judgement
  647. for r in data_ho:
  648. if r.row_no == 1:
  649. rmap = {'OUT': 6, 'MID': 7, 'IN': 8}
  650. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  651. idx = rmap.get(r.r_type, None)
  652. if idx:
  653. placeholders[f'v{idx}_{index}'] = getattr(r, v, "-")
  654. if r.row_no == 2:
  655. rmap = {'OUT': 14, 'MID': 15, 'IN': 16}
  656. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  657. idx = rmap.get(r.r_type, None)
  658. if idx:
  659. placeholders[f'v{idx}_{index}'] = getattr(r, v, "-")
  660. # hide_con(placeholders, "v5_1", "26:32")
  661. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  662. return placeholders
  663. def generate_dim_bal_app_rot_hard_values(lot_no, first_result, code):
  664. """
  665. Fetch dimension records from manualSize and DataMs models
  666. and generate placeholder values for Standard, Actual, and Judgement.
  667. Supports two row_no entries per lot.
  668. """
  669. # Fetch standard values from manualSize (limit to 2 rows)
  670. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  671. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  672. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  673. data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')
  674. data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no'))
  675. data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no'))
  676. data_ho = list(chain(data_h1, data_h2))
  677. rotates = RotateData.objects.filter(lot_no=lot_no).order_by('row_no')
  678. if first_result:
  679. # out_limit = f"Out 外 ({first_result.MI18} - {first_result.MI19})"
  680. # in_limit = f"In 内 ({first_result.MI22} - {first_result.MI23})"
  681. try:
  682. out_limit = f"Out 外 ({float(first_result.MI18):.2f} - {float(first_result.MI19):.2f})"
  683. except (TypeError, ValueError):
  684. out_limit = "Out 外"
  685. mi22 = getattr(first_result, "MI22", None)
  686. mi23 = getattr(first_result, "MI23", None)
  687. # If MI22 is missing, None, 0, or ""
  688. if mi22 in (None, 0, "", "0"):
  689. in_limit = "In 内"
  690. else:
  691. try:
  692. in_limit = f"In 内 ({float(mi22):.2f} - {float(mi23 or 0):.2f})"
  693. except (TypeError, ValueError):
  694. in_limit = "In 内"
  695. mid_limit = f"Middle 中 -"
  696. else:
  697. out_limit = f"Out 外"
  698. in_limit = f"In 内"
  699. mid_limit = f"Middle 中"
  700. # Prepare placeholders
  701. # placeholders = {}
  702. placeholders = clear_values(18,5)
  703. # for i in range(1,7):
  704. # for j in range(1,4):
  705. # placeholders[f'v{i}_{j}'] = 0
  706. placeholders['v6_0'] = placeholders['v14_0'] = out_limit
  707. placeholders['v7_0'] = placeholders['v15_0'] = mid_limit
  708. placeholders['v18_0'] = placeholders['v16_0'] = in_limit
  709. pprint(placeholders)
  710. pprint(manual_size_records)
  711. if first_result:
  712. try:
  713. w = first_result.PRO6
  714. placeholders['v4_1'] = placeholders['v13_1'] = w
  715. except:
  716. print("no PRO6")
  717. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  718. for m in dimens: # Changed from manual_size_records to dimens
  719. if m.Size_Name == "D":
  720. placeholders['v1_1'] = placeholders['v10_1'] = f'D{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  721. if m.Size_Name == "T":
  722. placeholders['v2_1'] = placeholders['v11_1'] = f'T{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  723. if m.Size_Name == "H":
  724. placeholders['v3_1'] = placeholders['v12_1'] = f'H{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  725. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  726. inspect_date = None
  727. for r in data_ms_records:
  728. if r.row_no == 1:
  729. placeholders[f'v1_2'] = r.dsize
  730. placeholders[f'v1_3'] = r.dsizeok
  731. placeholders[f'v2_2'] = r.tsize
  732. placeholders[f'v2_3'] = r.tsizeok
  733. placeholders[f'v3_2'] = r.hsize
  734. placeholders[f'v3_3'] = r.hsizeok
  735. inspect_date = r.created_at
  736. # if is_ok(r):
  737. # placeholders[f'v4_1'] = 'OK'
  738. # placeholders[f'v4_2'] = 'OK'
  739. # else:
  740. # placeholders[f'v4_1'] = 'NG'
  741. # placeholders[f'v4_2'] = 'OK'
  742. if r.row_no == 2:
  743. placeholders[f'v10_2'] = r.dsize
  744. placeholders[f'v10_3'] = r.dsizeok
  745. placeholders[f'v11_2'] = r.tsize
  746. placeholders[f'v11_3'] = r.tsizeok
  747. placeholders[f'v12_2'] = r.hsize
  748. placeholders[f'v12_3'] = r.hsizeok
  749. # if is_ok(r):
  750. # placeholders[f'v8_1'] = 'OK'
  751. # placeholders[f'v8_2'] = 'OK'
  752. # else:
  753. # placeholders[f'v8_1'] = 'NG'
  754. # placeholders[f'v8_2'] = 'NG'
  755. for r in data_wb:
  756. if r.row_no == 1:
  757. placeholders["v4_2"] = f"{r.weight:.1f}"
  758. placeholders["v4_3"] = r.judgement
  759. if r.row_no == 2:
  760. placeholders["v13_2"] = f"{r.weight:.1f}"
  761. placeholders["v13_3"] = r.judgement
  762. for r in data_ho:
  763. if r.row_no == 1:
  764. rmap = {'OUT': 7, 'MID': 8, 'IN': 9}
  765. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  766. idx = rmap.get(r.r_type, None)
  767. if idx:
  768. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  769. if r.row_no == 2:
  770. rmap = {'OUT': 16, 'MID': 17, 'IN': 18}
  771. for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
  772. idx = rmap.get(r.r_type, None)
  773. if idx:
  774. placeholders[f'v{idx}_{index}'] = getattr(r, v)
  775. for r in rotates:
  776. if r.row_no == 1:
  777. placeholders["v6_1"] = r.speed_spec
  778. placeholders["v6_2"] = r.speed_test
  779. placeholders["v6_3"] = r.speedok
  780. if r.row_no == 2:
  781. placeholders["v15_1"] = r.speed_spec
  782. placeholders["v15_2"] = r.speed_test
  783. placeholders["v15_3"] = r.speedok
  784. # hide_con(placeholders, "v5_1", "26:32")
  785. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  786. return placeholders
  787. def generate_centering_values(lot_no, code):
  788. """
  789. Fetch dimension records from manualSize and DataMs models
  790. and generate placeholder values for Standard, Actual, and Judgement.
  791. Supports two row_no entries per lot.
  792. """
  793. # Fetch standard values from manualSize (limit to 2 rows)
  794. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  795. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  796. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  797. # Prepare placeholders
  798. # placeholders = {}
  799. placeholders = clear_values(20, 3)
  800. # for i in range(1,7):
  801. # for j in range(1,4):
  802. # placeholders[f'v{i}_{j}'] = 0
  803. pprint(placeholders)
  804. pprint(manual_size_records)
  805. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  806. inspect_date = None
  807. record_count = 0
  808. for i,r in enumerate(data_ms_records, start=1):
  809. record_count = i
  810. if i == 1:
  811. inspect_date = r.created_at
  812. placeholders[f'v{i}_2'] = r.censize
  813. placeholders[f'v{i}_3'] = r.censizeok
  814. if record_count <= 10:
  815. hide_con(placeholders, "v11_2", "47:93")
  816. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  817. return placeholders
  818. def generate_t8_values(lot_no, code):
  819. """
  820. Fetch dimension records from manualSize and DataMs models
  821. and generate placeholder values for Standard, Actual, and Judgement.
  822. Supports two row_no entries per lot.
  823. """
  824. # Fetch standard values from manualSize (limit to 2 rows)
  825. placeholders = clear_values(8,10)
  826. manual_size_records = Manualsize.objects.filter(lotno=lot_no)
  827. # pprint(f"manual_size = {manual_size_records}")
  828. dimens = AllProductDimensionForInsProcess.objects.filter(ProductCode=code)
  829. for m in dimens: # Changed from manual_size_records to dimens
  830. if m.Size_Name == "Thickness":
  831. for i in range(1, 9):
  832. placeholders[f'v{i}_1'] = f'{m.Std:.2f} +{m.TolUp:.2f} {m.TolUn:.2f}'
  833. # pprint("set std")
  834. # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
  835. data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
  836. # Prepare placeholders
  837. # placeholders = {}
  838. # for i in range(1,7):
  839. # for j in range(1,4):
  840. # placeholders[f'v{i}_{j}'] = 0
  841. # Ensure that we map each manualSize entry to a corresponding DataMs entry
  842. inspect_date = None
  843. for i,r in enumerate(data_ms_records, start=1):
  844. if i == 1:
  845. inspect_date = r.created_at
  846. placeholders[f'v{i}_2'] = r.tpoint1
  847. placeholders[f'v{i}_3'] = r.tpoint2
  848. placeholders[f'v{i}_4'] = r.tpoint3
  849. placeholders[f'v{i}_5'] = r.tpoint4
  850. placeholders[f'v{i}_10'] = r.tdiff
  851. placeholders['inspect_date'] = inspect_date.strftime('%Y/%m/%d') if inspect_date else "-"
  852. return placeholders
  853. def merge_sheet_data_with_data(sheet_data, data):
  854. """
  855. Merge `sheet_data` with `data`.
  856. :param sheet_data: Dictionary containing the sheet-specific data.
  857. :param data: Dictionary containing general data.
  858. :return: A merged dictionary combining both `sheet_data` and `data`.
  859. """
  860. # Merge dictionaries using unpacking
  861. merged_data = {**data, **sheet_data}
  862. return merged_data
  863. def create_coi_file(lot_no, sheets, user, md):
  864. pprint("---- create_coi_file ---")
  865. pprint(md)
  866. qa1 = User.objects.get(pk=md['qa1'])
  867. qa2 = User.objects.get(pk=md['qa2'])
  868. accept = specialAccept = False
  869. if md['acceptStatus'] == "accepted":
  870. accept = True
  871. if md['acceptStatus'] == "special_accepted":
  872. specialAccept = True
  873. pprint(qa1)
  874. pprint(qa2)
  875. results = queryFromMaster(lot_no)
  876. first_result = results[0] if results else None
  877. code = first_result.PRO1 if first_result else None
  878. sheet_data = {}
  879. for sheet_name in sheets:
  880. if sheet_name == 'hardness_out':
  881. sheet_data[sheet_name] = generate_hardness_out_values(lot_no, code)
  882. elif sheet_name == 'hardness_out_in':
  883. sheet_data[sheet_name] = generate_hardness_out_in_values(lot_no, code)
  884. elif sheet_name == 'hardness_out_in_4':
  885. sheet_data[sheet_name] = generate_hardness_out_in_values(lot_no, code)
  886. elif sheet_name == 'hardness_both_size':
  887. sheet_data[sheet_name] = generate_hardness_both_size_values(lot_no, first_result, code)
  888. elif sheet_name == 'dimension':
  889. sheet_data[sheet_name] = generate_dimension_values(lot_no, code)
  890. elif sheet_name == 'dimension_weight_warp':
  891. sheet_data[sheet_name] = generate_dimension_weight_warp_values(lot_no, code)
  892. elif sheet_name == 'dimension_app':
  893. sheet_data[sheet_name] = generate_dimension_app_values(lot_no, code)
  894. elif sheet_name == 'dimension_app_drawing':
  895. sheet_data[sheet_name] = generate_dimension_app_drawing_values(lot_no, code)
  896. elif sheet_name == 'dimension_bal_weight':
  897. sheet_data[sheet_name] = generate_dimension_bal_weight_values(lot_no, first_result, code)
  898. elif sheet_name == 'centering':
  899. sheet_data[sheet_name] = generate_centering_values(lot_no, code)
  900. elif sheet_name == 'thickness_8_point':
  901. sheet_data[sheet_name] = generate_t8_values(lot_no, code)
  902. elif sheet_name == 'dim_bal_app_hard':
  903. sheet_data[sheet_name] = generate_dim_bal_app_hard_values(lot_no, first_result, code)
  904. elif sheet_name == 'dim_bal_app_hard_stamp':
  905. sheet_data[sheet_name] = generate_dim_bal_app_hard_values(lot_no, first_result, code)
  906. elif sheet_name == 'dim_bal_app_rot_hard':
  907. sheet_data[sheet_name] = generate_dim_bal_app_rot_hard_values(lot_no, first_result, code)
  908. converted_data = convert_sheet_data(sheet_data)
  909. print(f"sheet_data \n {sheet_data}")
  910. print(f"converted_data \n {converted_data}")
  911. # results = queryFromMaster(lot_no)
  912. # first_result = results[0] if results else None
  913. try:
  914. pcs = int(first_result.PRO5) - int(first_result.PRO27)
  915. except:
  916. pcs = 0
  917. # first_result.PRO10 = 12321.1232
  918. # first_result.PRO11 = 1.5
  919. # first_result.PRO12 = 3.5
  920. if first_result:
  921. # size_str = f"{first_result.PRO10}x{first_result.PRO11}x{first_result.PRO12}";
  922. try:
  923. size_str = f"{float(first_result.PRO10):.2f}x{float(first_result.PRO11):.2f}x{float(first_result.PRO12):.2f}"
  924. except (ValueError, TypeError):
  925. size_str = "-"
  926. spec = f"{first_result.PRO13} {first_result.PRO14} {first_result.PRO15} {first_result.PRO16} {first_result.PRO17} {first_result.PRO18}"
  927. else:
  928. size_str = ""
  929. spec = ""
  930. mgt_code = first_result.PRO1 if first_result else "-"
  931. mks_code = convert_mgt_to_mks(mgt_code)
  932. code = f"{mks_code}(MKSコード)  {mgt_code}(参照)"
  933. '''
  934. mks_map = MksCodeMap.objects.filter(mgt_code=mgt_code).first()
  935. if mks_map:
  936. code = f"{mks_map.mks_code}(MKSコード)  {mgt_code}(参照)"
  937. else:
  938. code = f"{mgt_code}(参照)" or "-"
  939. '''
  940. # first_result.PRO_TOOL = None
  941. def get_tool_no(code_number: str) -> str:
  942. tool_map = {
  943. "547870587D": "A中 内径195",
  944. "547870585K": "仕上用",
  945. "547870586C": "粗",
  946. "547870586F": "A粗 内径195",
  947. "547870586H": "B粗",
  948. "547870587C": "チュウケンヨウ"
  949. }
  950. pprint(f"code_number {code_number}")
  951. return tool_map.get(code_number, None)
  952. tn = get_tool_no(mgt_code)
  953. if tn is None:
  954. tn = first_result.PRO_TOOL if first_result and first_result.PRO_TOOL else "-"
  955. # Helper function
  956. def safe_float(value):
  957. try:
  958. return float(value)
  959. except (TypeError, ValueError):
  960. return 0
  961. # MP45 or fallback MP34
  962. mp45_value = getattr(first_result, "MP45", None)
  963. mp45_or_34 = mp45_value if mp45_value not in (None, "") else getattr(first_result, "MP34", "")
  964. # MP49 or fallback MP39
  965. mp49_value = getattr(first_result, "MP49", None)
  966. mp49_or_39 = mp49_value if mp49_value not in (None, "") else getattr(first_result, "MP39", None)
  967. # Build first part (always present)
  968. part1 = (
  969. f"Hardness: {getattr(first_result, 'ob_Condition', '')}, "
  970. f"{mp45_or_34} "
  971. f"{safe_float(getattr(first_result, 'MI18', None)):.2f} - "
  972. f"{safe_float(getattr(first_result, 'MI19', None)):.2f} "
  973. f"({getattr(first_result, 'MI16', '')} {getattr(first_result, 'MI17', '')})"
  974. )
  975. # Build second part only if mp49_or_39 exists
  976. if mp49_or_39 not in (None, ""):
  977. part2 = (
  978. f" {mp49_or_39}: "
  979. f"{safe_float(getattr(first_result, 'MI22', None)):.2f} - "
  980. f"{safe_float(getattr(first_result, 'MI23', None)):.2f} "
  981. f"({getattr(first_result, 'MI20', '')} {getattr(first_result, 'MI21', '')})"
  982. )
  983. else:
  984. part2 = "" # exclude second part entirely
  985. std_value = part1 + part2
  986. data = {
  987. # "code": first_result.PRO1 if first_result else "-",
  988. "code": code,
  989. "customer": f"{first_result.Japanese_CustomerName + ' 御中 ' if first_result and first_result.Japanese_CustomerName != '' else ''}{first_result.PRO1C if first_result else '-'}",
  990. # "inspect_date": inspect_date.strftime('%Y/%m/%d') if inspect_date else "-",
  991. "lot_no": lot_no,
  992. "size": size_str,
  993. "lot_size": pcs,
  994. "spec": spec,
  995. "std": std_value,
  996. # "hardness_out.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  997. # "hardness_out.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
  998. "acc": accept, # Hide rows 24 to 28 if the prefix is "0"
  999. "spe_acc": specialAccept, # Hide rows 24 to 28 if the prefix is "0"
  1000. "tool": tn,
  1001. # "hardness_out.qa1": f"{qa1.first_name} {qa1.last_name}",
  1002. # "hardness_out.qa2": f"{qa2.first_name} {qa2.last_name}",
  1003. "qa1": f"{qa1.first_name} {qa1.last_name}",
  1004. "qa2": f"{qa2.first_name} {qa2.last_name}",
  1005. "sign1": qa1.profile.signed_picture,
  1006. "sign2": qa2.profile.signed_picture,
  1007. "pos1": qa1.profile.get_position_display(),
  1008. "pos2": qa2.profile.get_position_display()
  1009. }
  1010. merged_data = merge_sheet_data_with_data(converted_data, data)
  1011. pprint(f"---- merged_data ---")
  1012. pprint(merged_data)
  1013. template_file = get_coi_template_file(md.get("export_template"))
  1014. output_file = gen_xlsx(
  1015. template_file=template_file,
  1016. selected_sheets=sheets, # Replace with your actual sheet names
  1017. prefix_filename=f"{settings.BASE_DIR}/media/coi_{lot_no}_",
  1018. data=merged_data
  1019. )
  1020. report = Report.objects.create(
  1021. name=lot_no,
  1022. created_by=user,
  1023. file=None # Leave this as None or assign a file if required
  1024. )
  1025. output_file_path = Path(output_file) # Convert to a Path object for convenience
  1026. with open(output_file_path, "rb") as f:
  1027. report.file.save(output_file_path.name, File(f), save=True)
  1028. pprint(f"outputfile = {output_file}")
  1029. return report
  1030. def get_fields(model):
  1031. # model_fields = {f.name: f for f in model._meta.get_fields()}
  1032. # fields = list(model_fields.values())
  1033. # return fields
  1034. fields = [f for f in model._meta.get_fields() if not f.auto_created]
  1035. return fields
  1036. def filter_by_lot_no(lot_no):
  1037. models = [Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData ] # List of models to process
  1038. results = {}
  1039. fields = {}
  1040. for model in models:
  1041. model_fields = [f.name for f in model._meta.get_fields()]
  1042. # Check if "id" and "row_no" are in the model's fields
  1043. order_fields = []
  1044. if "id" in model_fields:
  1045. order_fields.append("id")
  1046. if "row_no" in model_fields:
  1047. order_fields.append("row_no")
  1048. # Dynamically filter and order results
  1049. model_name = model.__name__
  1050. if order_fields:
  1051. results[model_name] = model.objects.filter(lot_no=lot_no).order_by(*order_fields)
  1052. else:
  1053. results[model_name] = model.objects.filter(lot_no=lot_no) # No
  1054. fields[model_name] = get_fields(model)
  1055. return results, fields
  1056. @login_required
  1057. def coi_view(request):
  1058. pprint(f"xxxx method = xxx {request.method}")
  1059. users = User.objects.all()
  1060. export_template = "japanese"
  1061. qa2_profile = UserProfile.objects.filter(qa2_default=True).select_related('user').first()
  1062. qa2_default_user_id = qa2_profile.user.id if qa2_profile else ''
  1063. if request.method == "POST":
  1064. pprint(request.POST)
  1065. exports = request.POST.getlist("exports") # Retrieve the list of selected values
  1066. pprint(f"Selected Export Options: {exports}")
  1067. export_template = request.POST.get("export_template", "japanese")
  1068. if 'export' in request.POST:
  1069. data = {
  1070. "customer": "Tum Coder",
  1071. "inspect_date": "2025-01-15",
  1072. "lot_no": "12345",
  1073. "staff_name": "Tum 8888",
  1074. "man_name": "Tum 999",
  1075. "size": "Large",
  1076. "lot_size": "10 pcs",
  1077. "spec": "Spec-A",
  1078. "hardness_out.d1_act": "10",
  1079. "hardness_out.d2_act": "0[24:28]", # Hide rows 24 to 28 if the prefix is "0"
  1080. "hardness_out.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  1081. "hardness_out.spe_acc": False, # Hide rows 24 to 28 if the prefix is "0"
  1082. "dimension_app.d1_act": "33",
  1083. "dimension_app.d2_act": "0[26:32]", # Hide rows 24 to 28 if the prefix is "0"
  1084. "dimension_app.acc": True, # Hide rows 24 to 28 if the prefix is "0"
  1085. "dimension_app.spe_acc": True, # Hide rows 24 to 28 if the prefix is "0"
  1086. }
  1087. output_file = gen_xlsx(
  1088. template_file=get_coi_template_file(export_template),
  1089. selected_sheets=exports, # Replace with your actual sheet names
  1090. prefix_filename="/app/media/coi",
  1091. data=data
  1092. )
  1093. report = Report.objects.create(
  1094. name=request.POST.get('lot_no','Untitled'),
  1095. created_by=request.user,
  1096. file=None # Leave this as None or assign a file if required
  1097. )
  1098. output_file_path = Path(output_file) # Convert to a Path object for convenience
  1099. with open(output_file_path, "rb") as f:
  1100. report.file.save(output_file_path.name, File(f), save=True)
  1101. pprint(f"outputfile = {output_file}")
  1102. if 'search_lot' in request.POST:
  1103. lot_no = request.POST.get('lot_no', None)
  1104. lot_no = lot_no.strip()
  1105. if lot_no:
  1106. results = queryFromMaster(lot_no)
  1107. first_result = results[0] if results else None
  1108. selected_templates = None
  1109. try:
  1110. pcs = int(first_result.PRO5) - int(first_result.PRO27)
  1111. except:
  1112. pcs = 0
  1113. code = "-"
  1114. if first_result:
  1115. size_str = f"{first_result.PRO10}x{first_result.PRO11}x{first_result.PRO12}";
  1116. spec = f"{first_result.PRO13} {first_result.PRO14} {first_result.PRO15} {first_result.PRO16} {first_result.PRO17} {first_result.PRO18}"
  1117. mapping = get_customer_template_mapping(first_result)
  1118. selected_templates = mapping.template_names if mapping else []
  1119. export_template = mapping.export_template if mapping else export_template
  1120. mgt_code = first_result.PRO1 if first_result else "-"
  1121. mks_code = convert_mgt_to_mks(mgt_code)
  1122. code = f"{mks_code}(MKSコード)  {mgt_code}(参照)"
  1123. '''
  1124. mks_map = MksCodeMap.objects.filter(mgt_code=mgt_code).first()
  1125. if mks_map:
  1126. code = f"{mks_map.mks_code}(MKSコード)  {mgt_code}(参照)"
  1127. else:
  1128. code = f"{mgt_code}(参照)" or "-"
  1129. '''
  1130. else:
  1131. size_str = ""
  1132. spec = ""
  1133. results, fields = filter_by_lot_no(lot_no)
  1134. # results1 = Data.objects.filter(lot_no=lot_no).order_by("id", "row_no")
  1135. # fields1 = get_fields(Data)
  1136. # results2 = DataMs.objects.filter(lot_no=lot_no).order_by("id", "row_no")
  1137. # fields2 = get_fields(DataMs)
  1138. return render(request, 'report/coi.html', {'result': first_result,
  1139. 'pcs':pcs,
  1140. 'size_str': size_str,
  1141. 'lot_no': lot_no,
  1142. 'spec': spec, 'users': users, 'SHEET_NAMES': SHEET_NAMES,
  1143. 'results': results, 'fields': fields, 'selected_templates': selected_templates, 'code': code,
  1144. 'export_template': export_template,
  1145. 'current_user_id': request.user.id,
  1146. 'qa2_default_user_id': qa2_default_user_id})
  1147. messages.success(request, "Request Sent")
  1148. return redirect(request.path_info)
  1149. return render(request, 'report/coi.html', {'SHEET_NAMES': SHEET_NAMES, 'users': users,
  1150. 'export_template': export_template,
  1151. 'current_user_id': request.user.id,
  1152. 'qa2_default_user_id': qa2_default_user_id})
  1153. @csrf_exempt # Disable CSRF for API requests (ensure this is secure in production)
  1154. @login_required
  1155. def gen_report_view(request):
  1156. if request.method == "POST":
  1157. # try:
  1158. # Parse JSON data from the request body
  1159. data = json.loads(request.body)
  1160. lot_no = data.get("lot_no").strip()
  1161. exports = data.get("exports")
  1162. qa1 = data.get('qa1')
  1163. qa2 = data.get('qa2')
  1164. export_template = data.get("export_template")
  1165. print(f"data = {data}")
  1166. if not lot_no:
  1167. return HttpResponseBadRequest("Missing 'lot_no' in request data")
  1168. if not export_template:
  1169. results = queryFromMaster(lot_no)
  1170. first_result = results[0] if results else None
  1171. mapping = get_customer_template_mapping(first_result)
  1172. export_template = mapping.export_template if mapping else "japanese"
  1173. # Call the `create_coi_file` function with the provided lot_no
  1174. report = create_coi_file(lot_no, exports, request.user, {'qa1': qa1, 'qa2': qa2, \
  1175. 'acceptStatus': data.get('acceptStatus'), 'export_template': export_template})
  1176. # Return a success response with the report details
  1177. return JsonResponse({
  1178. "message": "Report generated successfully",
  1179. "report_id": report.id,
  1180. "file_url": report.file.url if report.file else None,
  1181. })
  1182. # except json.JSONDecodeError:
  1183. # return HttpResponseBadRequest("Invalid JSON data")
  1184. # except Exception as e:
  1185. # pprint(e)
  1186. # return JsonResponse({"error": str(e)}, status=500)
  1187. else:
  1188. return HttpResponseBadRequest("Only POST requests are allowed")
  1189. class CustomerTemplateCRUDView(ConfigurableCRUDView):
  1190. model = CustomerTemplateMapping
  1191. list_template_name = 'report/customer_template_list.html'
  1192. detail_template_name = 'legacy/datacrud_detail.html'
  1193. form_template_name = 'report/customer_template_form.html'
  1194. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  1195. filterset_class = CustomerTemplateFilter
  1196. page_title = "Customer Template Mapping"
  1197. # URL name mappings
  1198. list_url_name = 'report:customer_templates-list'
  1199. create_url_name = 'report:customer_templates-create'
  1200. update_url_name = 'report:customer_templates-update'
  1201. delete_url_name = 'report:customer_templates-delete'
  1202. config_fields = ["id", "customer_name", "export_template", "template_names", "created_at"]
  1203. config_field_orders = ["id", "customer_name", "export_template", "template_names", "created_at", "created_by"]
  1204. # config_readonly_fields = ["lot_no"]
  1205. config_edit_fields = None
  1206. ordering = ["-created_at", "-id",]
  1207. form_class = CustomerTemplateMappingForm
  1208. def get_list_view(self):
  1209. class ListViewClass(FilterView, ListView):
  1210. model = self.model
  1211. template_name = self.list_template_name
  1212. paginate_by = self.paginate_by
  1213. filterset_class = self.filterset_class
  1214. ordering = self.ordering
  1215. def get_context_data(inner_self, **kwargs):
  1216. context = super().get_context_data(**kwargs)
  1217. fields = self.get_fields()
  1218. context.update({
  1219. 'fields': [f for f in fields],
  1220. 'sheet_names': SHEET_NAMES,
  1221. # 'fields': [field for field in self.model._meta.get_fields()],
  1222. 'page_title': self.page_title,
  1223. 'list_url': self.list_url_name,
  1224. 'create_url': self.create_url_name,
  1225. 'update_url': self.update_url_name,
  1226. 'delete_url': self.delete_url_name,
  1227. 'bs': self.get_breadcrumbs('list'),
  1228. })
  1229. return context
  1230. return ListViewClass
  1231. class ProductDrawingCRUDView(ConfigurableCRUDView):
  1232. model = ProductDrawing
  1233. list_template_name = 'legacy/datacrud_list.html'
  1234. detail_template_name = 'legacy/datacrud_detail.html'
  1235. form_template_name = 'report/productdrawing_form.html'
  1236. confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
  1237. filterset_class = ProductDrawingFilter
  1238. page_title = "Product Drawing"
  1239. # URL name mappings
  1240. list_url_name = 'report:product_drawings-list'
  1241. create_url_name = 'report:product_drawings-create'
  1242. update_url_name = 'report:product_drawings-update'
  1243. delete_url_name = 'report:product_drawings-delete'
  1244. config_fields = ["id", "code_no", "code_no_mks", "lot_no", "drawing", "description", "created_at"]
  1245. #config_field_orders = ["id", "customer_name", "template_names", "created_at", "created_by"]
  1246. # config_readonly_fields = ["lot_no"]
  1247. config_edit_fields = None
  1248. ordering = ["-created_at", "-id",]
  1249. form_class = ProductDrawingForm
  1250. class MksCodeMapCRUDView(ConfigurableCRUDView):
  1251. model = MksCodeMap
  1252. page_title = "MKS Code Mapping"
  1253. filterset_class = MksCodeMapFilter
  1254. list_template_name = "legacy/datacrud_list.html"
  1255. detail_template_name = "legacy/datacrud_detail.html"
  1256. form_template_name = 'legacy/datacrud_form.html'
  1257. confirm_delete_template_name = "legacy/datacrud_confirm_delete.html"
  1258. config_fields = ["id", "mgt_code", "mks_code", "created_at"]
  1259. config_edit_fields = ["mgt_code", "mks_code"]
  1260. list_url_name = "report:code_maps-list"
  1261. create_url_name = "report:code_maps-create"
  1262. update_url_name = "report:code_maps-update"
  1263. delete_url_name = "report:code_maps-delete"
  1264. ordering = ["-created_at", "-id"]