tum преди 11 месеца
родител
ревизия
837370063b
променени са 4 файла, в които са добавени 197 реда и са изтрити 25 реда
  1. BIN
      app/report/coi_templates.xlsx
  2. 4 2
      app/report/gen_report.py
  3. 9 5
      app/report/templates/report/coi.html
  4. 184 18
      app/report/views.py

BIN
app/report/coi_templates.xlsx


+ 4 - 2
app/report/gen_report.py

@@ -242,13 +242,15 @@ def gen_xlsx(template_file, selected_sheets, prefix_filename, data):
242 242
                             cell.value = value
243 243
 
244 244
         for key, value in data.items():
245
-            if isinstance(value, str) and re.match(r"^\d+\[\d+:\d+\]$", value):
245
+            # if isinstance(value, str) and re.match(r"^\d+\[\d+:\d+\]$", value):
246
+            if isinstance(value, str) and re.match(r"^[0-9\s]+\[\d+:\d+\]$", value):
246 247
                 # Parse the prefix and row range
247 248
                 prefix, row_range = value.split("[")
248 249
                 row_start, row_end = map(int, row_range[:-1].split(":"))
249 250
                 
250 251
                 # Hide rows if the prefix matches the condition
251
-                if prefix == "0":  # Adjust the condition as needed
252
+                # if prefix == "0":  # Adjust the condition as needed
253
+                if " " in prefix or prefix.strip() == "0":
252 254
                     sheet.row_dimensions.group(row_start, row_end, hidden=True)
253 255
         
254 256
 

+ 9 - 5
app/report/templates/report/coi.html

@@ -18,6 +18,7 @@
18 18
         🔍
19 19
       </button>
20 20
     </div>
21
+  </form>
21 22
       <button class="bg-blue-100 text-blue-700 px-4 py-2 rounded hover:bg-blue-200">
22 23
         Option for Export :
23 24
       </button>
@@ -73,12 +74,10 @@
73 74
           </div>
74 75
           <!-- TODO: add download here -->
75 76
           <div class=" text-center" x-show="downloadUrl">
76
-            <a :href="downloadUrl"  class="block px-4 py-2 bg-green-600 text-white  rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2" download>
77
-              Download Report
77
+            <a :href="downloadUrl"  class="block px-4 py-2 bg-green-600 text-white  rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2" download x-text="downText">
78 78
             </a>
79 79
           </div>
80 80
         </div>
81
-  </form>
82 81
   {{ result }}
83 82
   
84 83
   <div class="bg-white shadow-md rounded-md p-4">
@@ -157,6 +156,7 @@ th, td {
157 156
       gen_report_url: '{% url "report:gen_report" %}', 
158 157
       acceptStatus: 'accepted', 
159 158
       downloadUrl: null, // Stores the download link after export success
159
+      downText: "Download Excel",
160 160
       init() {
161 161
         //alert("COI Report");
162 162
         this.qa1 = '';
@@ -189,14 +189,18 @@ th, td {
189 189
                       qa2: this.qa2,
190 190
                       acceptStatus: this.acceptStatus
191 191
                   });
192
-
192
+                  this.downText = "Processing ..."
193 193
                   if (response.status === 200) {
194 194
                       const result = response.data;
195
-                      alert(`Report generated successfully: ${result.file_url}`);
195
+                      //alert(`Report generated successfully: ${result.file_url}`);
196
+                      this.downText = "Download Excel"
196 197
                       console.log('File URL:', result.file_url);
197 198
                       this.downloadUrl = result.file_url; // Set the download URL
199
+                  }else {
200
+                      this.downText = "Error ..."
198 201
                   }
199 202
               } catch (error) {
203
+                  this.downText = "Error ..."
200 204
                   if (error.response) {
201 205
                       // Server responded with a status other than 2xx
202 206
                       alert(`Error: ${error.response.data.message || 'Failed to generate report'}`);

+ 184 - 18
app/report/views.py

@@ -22,6 +22,9 @@ from django.contrib.auth.models import User
22 22
 from legacy.models import Data
23 23
 from django.conf import settings
24 24
 
25
+from itertools import chain
26
+
27
+
25 28
 def index(request):
26 29
     reports = Report.objects.all()
27 30
     report_filter = ReportFilter(request.GET, queryset=reports)
@@ -166,7 +169,7 @@ def clear_values(n, m):
166 169
     placeholders = {}
167 170
     for i in range(1, n + 1):
168 171
         for j in range(1, m + 1):
169
-            placeholders[f'v{i}_{j}'] = 0
172
+            placeholders[f'v{i}_{j}'] = " "
170 173
     return placeholders
171 174
 
172 175
 # # Example usage:
@@ -283,12 +286,12 @@ def generate_dimension_app_values(lot_no):
283 286
             placeholders[f'v3_2'] = r.hsize
284 287
             placeholders[f'v3_3'] = r.hsizeok
285 288
 
286
-            if is_ok(r):
287
-                placeholders[f'v4_1'] = 'OK'
288
-                placeholders[f'v4_2'] = 'OK'
289
-            else:
290
-                placeholders[f'v4_1'] = 'NG'
291
-                placeholders[f'v4_2'] = 'OK'
289
+            # if is_ok(r):
290
+                # placeholders[f'v4_1'] = 'OK'
291
+                # placeholders[f'v4_2'] = 'OK'
292
+            # else:
293
+                # placeholders[f'v4_1'] = 'NG'
294
+                # placeholders[f'v4_2'] = 'OK'
292 295
         
293 296
         if r.row_no == 2:
294 297
             placeholders[f'v5_2'] = r.dsize
@@ -300,16 +303,133 @@ def generate_dimension_app_values(lot_no):
300 303
             placeholders[f'v7_2'] = r.hsize
301 304
             placeholders[f'v7_3'] = r.hsizeok
302 305
 
303
-            if is_ok(r):
304
-                placeholders[f'v8_1'] = 'OK'
305
-                placeholders[f'v8_2'] = 'OK'
306
-            else:
307
-                placeholders[f'v8_1'] = 'NG'
308
-                placeholders[f'v8_2'] = 'NG'
306
+            # if is_ok(r):
307
+                # placeholders[f'v8_1'] = 'OK'
308
+                # placeholders[f'v8_2'] = 'OK'
309
+            # else:
310
+                # placeholders[f'v8_1'] = 'NG'
311
+                # placeholders[f'v8_2'] = 'NG'
309 312
 
310 313
     hide_con(placeholders, "v5_1", "26:32")
311 314
     return placeholders
312 315
 
316
+def generate_dim_bal_app_hard_values(lot_no, first_result):
317
+    """
318
+    Fetch dimension records from manualSize and DataMs models
319
+    and generate placeholder values for Standard, Actual, and Judgement.
320
+    Supports two row_no entries per lot.
321
+    """
322
+    # Fetch standard values from manualSize (limit to 2 rows)
323
+    manual_size_records = Manualsize.objects.filter(lotno=lot_no)
324
+
325
+    # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
326
+    data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')[:2]
327
+    data_wb = DataWb.objects.filter(lot_no=lot_no).order_by('row_no')[:2]
328
+    
329
+    data_h1 = list(Data.objects.filter(lot_no=lot_no).order_by('row_no')[:2])
330
+    data_h2 = list(DataRl.objects.filter(lot_no=lot_no).order_by('row_no')[:2])
331
+
332
+    data_ho = list(chain(data_h1, data_h2))
333
+
334
+    if first_result:
335
+        out_limit = f"Out 外  ({first_result.MI18} - {first_result.MI19})"
336
+        in_limit = f"In 内 ({first_result.MI22} - {first_result.MI23})"
337
+        mid_limit = f"Middle   中  -"
338
+    else:
339
+        out_limit = f"Out 外"
340
+        in_limit = f"In 内"
341
+        mid_limit = f"Middle   中"
342
+    
343
+    
344
+
345
+    # Prepare placeholders
346
+
347
+    # placeholders = {}
348
+    placeholders = clear_values(16,5)
349
+    # for i in range(1,7):
350
+        # for j in range(1,4):
351
+            # placeholders[f'v{i}_{j}'] = 0
352
+    placeholders['v6_0'] = placeholders['v14_0'] = out_limit
353
+    placeholders['v7_0'] = placeholders['v15_0'] = mid_limit
354
+    placeholders['v18_0'] = placeholders['v16_0'] = in_limit
355
+
356
+    pprint(placeholders)
357
+    pprint(manual_size_records) 
358
+    if first_result:
359
+        w = first_result.PRO6
360
+        placeholders['v4_1'] = placeholders['v12_1'] = w
361
+
362
+    for m in manual_size_records:
363
+        if m.size_name == "D":
364
+            placeholders['v1_1'] = placeholders['v9_1'] = f'D{m.std} +{m.tolup} {m.tolun}'
365
+        if m.size_name == "T":
366
+            placeholders['v2_1'] = placeholders['v10_1'] = f'T{m.std} +{m.tolup} {m.tolun}'
367
+        if m.size_name == "H":
368
+            placeholders['v3_1'] = placeholders['v11_1'] = f'H{m.std} +{m.tolup} {m.tolun}'
369
+
370
+
371
+
372
+    # Ensure that we map each manualSize entry to a corresponding DataMs entry
373
+    for r in data_ms_records:
374
+        if r.row_no == 1:
375
+            placeholders[f'v1_2'] = r.dsize
376
+            placeholders[f'v1_3'] = r.dsizeok
377
+            
378
+            placeholders[f'v2_2'] = r.tsize
379
+            placeholders[f'v2_3'] = r.tsizeok
380
+            
381
+            placeholders[f'v3_2'] = r.hsize
382
+            placeholders[f'v3_3'] = r.hsizeok
383
+
384
+            # if is_ok(r):
385
+                # placeholders[f'v4_1'] = 'OK'
386
+                # placeholders[f'v4_2'] = 'OK'
387
+            # else:
388
+                # placeholders[f'v4_1'] = 'NG'
389
+                # placeholders[f'v4_2'] = 'OK'
390
+        
391
+        if r.row_no == 2:
392
+            placeholders[f'v9_2'] = r.dsize
393
+            placeholders[f'v9_3'] = r.dsizeok
394
+            
395
+            placeholders[f'v10_2'] = r.tsize
396
+            placeholders[f'v10_3'] = r.tsizeok
397
+            
398
+            placeholders[f'v11_2'] = r.hsize
399
+            placeholders[f'v11_3'] = r.hsizeok
400
+
401
+            # if is_ok(r):
402
+                # placeholders[f'v8_1'] = 'OK'
403
+                # placeholders[f'v8_2'] = 'OK'
404
+            # else:
405
+                # placeholders[f'v8_1'] = 'NG'
406
+                # placeholders[f'v8_2'] = 'NG'
407
+
408
+    for r in data_wb:
409
+        if r.row_no == 1:
410
+            placeholders["v4_2"] = r.weight
411
+            placeholders["v4_3"] = r.judgement
412
+        if r.row_no == 2:
413
+            placeholders["v12_2"] = r.weight
414
+            placeholders["v12_3"] = r.judgement
415
+
416
+    for r in data_ho:
417
+        if r.row_no == 1:
418
+            rmap = {'OUT': 6, 'MID': 7, 'IN': 8}
419
+            for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
420
+                idx = rmap.get(r.r_type, None)
421
+                if idx:
422
+                    placeholders[f'v{idx}_{index}']  = getattr(r, v) 
423
+        if r.row_no == 2:
424
+            rmap = {'OUT': 14, 'MID': 15, 'IN': 16}
425
+            for index, v in enumerate(["p1", "p2", "p3", "avg", "rgrade"], start=1):
426
+                idx = rmap.get(r.r_type, None)
427
+                if idx:
428
+                    placeholders[f'v{idx}_{index}']  = getattr(r, v)
429
+
430
+    # hide_con(placeholders, "v5_1", "26:32")
431
+    return placeholders
432
+
313 433
 def generate_centering_values(lot_no):
314 434
     """
315 435
     Fetch dimension records from manualSize and DataMs models
@@ -341,6 +461,43 @@ def generate_centering_values(lot_no):
341 461
 
342 462
     return placeholders
343 463
 
464
+def generate_t8_values(lot_no):
465
+    """
466
+    Fetch dimension records from manualSize and DataMs models
467
+    and generate placeholder values for Standard, Actual, and Judgement.
468
+    Supports two row_no entries per lot.
469
+    """
470
+    # Fetch standard values from manualSize (limit to 2 rows)
471
+    placeholders = clear_values(8,10)
472
+    
473
+    manual_size_records = Manualsize.objects.filter(lotno=lot_no)
474
+    # pprint(f"manual_size = {manual_size_records}")
475
+    for m in manual_size_records:
476
+        if m.size_name == "Thickness":
477
+            for i in range(1,9):
478
+                placeholders[f'v{i}_1'] = f'{m.std} +{m.tolup} {m.tolun}'
479
+                # pprint("set std")
480
+    # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
481
+    data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')
482
+
483
+    # Prepare placeholders
484
+
485
+    # placeholders = {}
486
+    # for i in range(1,7):
487
+        # for j in range(1,4):
488
+            # placeholders[f'v{i}_{j}'] = 0
489
+    
490
+
491
+    # Ensure that we map each manualSize entry to a corresponding DataMs entry
492
+    for i,r in enumerate(data_ms_records, start=1):
493
+        placeholders[f'v{i}_2'] = r.tpoint1
494
+        placeholders[f'v{i}_3'] = r.tpoint2
495
+        placeholders[f'v{i}_4'] = r.tpoint3
496
+        placeholders[f'v{i}_5'] = r.tpoint4
497
+        placeholders[f'v{i}_10'] = r.tdiff
498
+
499
+    return placeholders
500
+
344 501
 def merge_sheet_data_with_data(sheet_data, data):
345 502
     """
346 503
     Merge `sheet_data` with `data`.
@@ -370,6 +527,9 @@ def create_coi_file(lot_no, sheets, user, md):
370 527
     pprint(qa1)
371 528
     pprint(qa2)
372 529
     
530
+    results = queryFromMaster(lot_no)
531
+    first_result = results[0] if results else None
532
+    
373 533
     sheet_data = {}
374 534
     for sheet_name in sheets:
375 535
         match sheet_name:
@@ -383,14 +543,20 @@ def create_coi_file(lot_no, sheets, user, md):
383 543
                 sheet_data[sheet_name] = generate_dimension_app_values(lot_no)
384 544
             case 'centering':
385 545
                 sheet_data[sheet_name] = generate_centering_values(lot_no)
546
+            case 'centering':
547
+                sheet_data[sheet_name] = generate_centering_values(lot_no)
548
+            case 'thickness_8_point':
549
+                sheet_data[sheet_name] = generate_t8_values(lot_no)
550
+            case 'dim_bal_app_hard':
551
+                sheet_data[sheet_name] = generate_dim_bal_app_hard_values(lot_no, first_result)
386 552
     
387 553
     converted_data = convert_sheet_data(sheet_data)
388 554
 
389 555
     print(f"sheet_data \n {sheet_data}") 
390 556
     print(f"converted_data \n {converted_data}")
391 557
 
392
-    results = queryFromMaster(lot_no)
393
-    first_result = results[0] if results else None
558
+    # results = queryFromMaster(lot_no)
559
+    # first_result = results[0] if results else None
394 560
     try:
395 561
         pcs = int(first_result.PRO5) - int(first_result.PRO27)
396 562
     except:
@@ -403,8 +569,8 @@ def create_coi_file(lot_no, sheets, user, md):
403 569
         spec = ""
404 570
 
405 571
     data = {
406
-        "code": first_result.PRO1,
407
-        "customer": first_result.PRO1C,
572
+        "code": first_result.PRO1 if first_result else "-",
573
+        "customer": first_result.PRO1C if first_result else "-",
408 574
         "inspect_date": "2025-01-15",
409 575
         "lot_no": lot_no,
410 576
         "size": size_str,
@@ -430,7 +596,7 @@ def create_coi_file(lot_no, sheets, user, md):
430 596
     output_file = gen_xlsx(
431 597
         template_file=f"{settings.BASE_DIR}/report/coi_templates.xlsx",
432 598
         selected_sheets=sheets,  # Replace with your actual sheet names
433
-        prefix_filename=f"{settings.BASE_DIR}/media/coi",
599
+        prefix_filename=f"{settings.BASE_DIR}/media/coi_{lot_no}_",
434 600
         data=merged_data
435 601
     )
436 602
     report = Report.objects.create(