tum 11 ay önce
ebeveyn
işleme
2ff5179c56

+ 1 - 1
app/core/utils.py

@@ -20,7 +20,7 @@ class ConfigurableCRUDView:
20 20
     form_template_name = None
21 21
     confirm_delete_template_name = None
22 22
     fields = '__all__'  # Default to all fields
23
-    paginate_by = 10
23
+    paginate_by = 50
24 24
     filterset_class = None
25 25
     page_title = "Page Title"
26 26
     create_url_name = None

+ 8 - 1
app/legacy/filters.py

@@ -1,6 +1,6 @@
1 1
 import django_filters
2 2
 from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary, DataRl, DataWb, \
3
-        LotSummaryRl, LotSummaryWb
3
+        LotSummaryRl, LotSummaryWb, RotateData
4 4
 
5 5
 class DataFilter(django_filters.FilterSet):
6 6
     lot_no = django_filters.CharFilter(field_name='lot_no', lookup_expr='icontains')
@@ -78,3 +78,10 @@ class LotSummaryWbFilter(django_filters.FilterSet):
78 78
         model = LotSummaryWb
79 79
         fields = ['lot_no', 'code']  # Add fields you want to filter
80 80
 
81
+class RotateDataFilter(django_filters.FilterSet):
82
+    lot_no = django_filters.CharFilter(field_name='lot_no', lookup_expr='icontains')
83
+    code = django_filters.CharFilter(field_name='code', lookup_expr='icontains')
84
+
85
+    class Meta:
86
+        model = RotateData
87
+        fields = ['lot_no', 'code']  # Add fields you want to filter

+ 8 - 1
app/legacy/urls.py

@@ -1,7 +1,8 @@
1 1
 from django.urls import path
2 2
 from .views import DataListView, DataDetailView, DataCreateView, DataUpdateView, DataDeleteView,\
3 3
 DataMsCRUDView, TbFgPressInfoLotListCRUDView, LotSummaryCRUDView, VMasterViewCRUDView, MgMasterViewCRUDView,\
4
-BelMasterViewCRUDView, EMasterViewCRUDView, DataRLCRUDView, DataWbCRUDView, LotSummaryRlCRUDView, LotSummaryWbCRUDView
4
+BelMasterViewCRUDView, EMasterViewCRUDView, DataRLCRUDView, DataWbCRUDView, LotSummaryRlCRUDView, \
5
+LotSummaryWbCRUDView, RotateDataCRUDView
5 6
 
6 7
 app_name = 'legacy'  # Namespace for this app
7 8
 
@@ -16,6 +17,7 @@ datarl_crud = DataRLCRUDView()
16 17
 datawb_crud = DataWbCRUDView()
17 18
 lsrl_crud = LotSummaryRlCRUDView()
18 19
 lswb_crud = LotSummaryWbCRUDView()
20
+rotate_crud = RotateDataCRUDView()
19 21
 
20 22
 urlpatterns = [
21 23
     path('data/', DataListView.as_view(), name='data-list'),            # data/
@@ -79,4 +81,9 @@ urlpatterns = [
79 81
     path('lswb/create/', lswb_crud.get_create_view().as_view(), name='lswb-create'),
80 82
     path('lswb/<int:pk>/update/', lswb_crud.get_update_view().as_view(), name='lswb-update'),
81 83
     path('lswb/<int:pk>/delete/', lswb_crud.get_delete_view().as_view(), name='lswb-delete'),
84
+
85
+    path('rotate/', rotate_crud.get_list_view().as_view(), name='rotate-list'),
86
+    path('rotate/create/', rotate_crud.get_create_view().as_view(), name='rotate-create'),
87
+    path('rotate/<int:pk>/update/', rotate_crud.get_update_view().as_view(), name='rotate-update'),
88
+    path('rotate/<int:pk>/delete/', rotate_crud.get_delete_view().as_view(), name='rotate-delete'),
82 89
 ]

+ 21 - 2
app/legacy/views.py

@@ -11,9 +11,10 @@ from django.views.generic import (
11 11
     DeleteView,
12 12
 )
13 13
 from django.core.paginator import Paginator
14
-from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary, DataRl, DataWb, LotSummaryRl, LotSummaryWb
14
+from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary, DataRl, DataWb, LotSummaryRl, \
15
+        RotateData, LotSummaryWb
15 16
 from .filters import DataFilter, DataMsFilter, TbFgPressFilter, LotSummaryFilter, \
16
-        DataRlFilter, DataWbFilter, LotSummaryRlFilter, LotSummaryWbFilter
17
+        DataRlFilter, DataWbFilter, LotSummaryRlFilter, LotSummaryWbFilter, RotateDataFilter
17 18
 from django.urls import reverse
18 19
 from django.contrib import messages
19 20
 from pprint import pprint
@@ -374,3 +375,21 @@ class LotSummaryWbCRUDView(ConfigurableCRUDView):
374 375
     delete_url_name = 'legacy:lswb-delete'
375 376
     # excludes = ["splitdata"]
376 377
     config_field_orders = ["id", "lot_no", "code"]  # Display these fields first
378
+
379
+class RotateDataCRUDView(ConfigurableCRUDView):
380
+    model = RotateData
381
+    list_template_name = 'legacy/datacrud_list.html'
382
+    detail_template_name = 'legacy/datacrud_detail.html'
383
+    form_template_name = 'legacy/datacrud_form.html'
384
+    confirm_delete_template_name = 'legacy/datacrud_confirm_delete.html'
385
+    filterset_class = RotateDataFilter
386
+
387
+    page_title = "Rotate Data"
388
+
389
+    # URL name mappings
390
+    list_url_name = 'legacy:rotate-list'
391
+    create_url_name = 'legacy:rotate-create'
392
+    update_url_name = 'legacy:rotate-update'
393
+    delete_url_name = 'legacy:rotate-delete'
394
+    # excludes = ["splitdata"]
395
+    config_field_orders = ["id", "lot_no", "code"]  # Display these fields first

+ 33 - 4
app/report/templates/report/coi.html

@@ -24,7 +24,7 @@
24 24
         <div class="grid grid-cols-4 gap-4">
25 25
         {% for key,value in SHEET_NAMES.items %}
26 26
         <label class="flex items-center space-x-1">
27
-          <input type="checkbox" class="rounded" name='exports' value='{{ key }}' x-model='exports'>
27
+          <input type="checkbox" class="rounded" name='exports' value='{{ key }}' x-model='exports' required>
28 28
           <span>{{ value }}</span>
29 29
         </label>
30 30
         {% endfor %}
@@ -32,7 +32,7 @@
32 32
         <div class="grid grid-cols-2 gap-4">
33 33
           <div class="my-4">
34 34
             <label for="qa1" class="block mb-2 text-sm font-medium text-gray-900">Select QA.1</label>
35
-            <select id="qa1" name="qa1" class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" x-model='qa1'>
35
+            <select id="qa1" name="qa1" class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" x-model='qa1' required>
36 36
               <option value="" disabled selected>Choose a user</option>
37 37
               {% for user in users %}
38 38
               <option value="{{ user.id }}">{{ user.profile }}</option>
@@ -41,7 +41,7 @@
41 41
           </div>
42 42
           <div class="my-4">
43 43
             <label for="qa2" class="block mb-2 text-sm font-medium text-gray-900">Select QA.2</label>
44
-            <select id="qa2" name="qa2" class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" x-model='qa2'>
44
+            <select id="qa2" name="qa2" class="block w-full px-3 py-2 bg-white border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500" x-model='qa2' required>
45 45
               <option value="" disabled selected>Choose a user</option>
46 46
               {% for user in users %}
47 47
               <option value="{{ user.id }}">{{ user.profile }}</option>
@@ -50,6 +50,21 @@
50 50
           </div>
51 51
         </div>
52 52
         <div class="flex justify-end my-3 space-x-4">
53
+          <div class="flex items-center space-x-4 my-4">
54
+            <!-- Radio button for 'Accepted' -->
55
+            <label class="flex items-center space-x-2">
56
+              <input type="radio" name="status" id="accepted" value="accepted" 
57
+                class="rounded" x-model="acceptStatus" />
58
+              <span>Accepted</span>
59
+            </label>
60
+
61
+            <!-- Radio button for 'Special Accepted' -->
62
+            <label class="flex items-center space-x-2">
63
+              <input type="radio" name="status" id="special_accepted" value="special_accepted" 
64
+                class="rounded" x-model="acceptStatus" />
65
+              <span>Special Accepted</span>
66
+            </label>
67
+          </div>
53 68
           <div>
54 69
             <button  type='button' class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" 
55 70
                                    @click="exportCOI">
@@ -140,6 +155,7 @@ th, td {
140 155
       qa1: null,
141 156
       qa2: null,
142 157
       gen_report_url: '{% url "report:gen_report" %}', 
158
+      acceptStatus: 'accepted', 
143 159
       downloadUrl: null, // Stores the download link after export success
144 160
       init() {
145 161
         //alert("COI Report");
@@ -151,6 +167,18 @@ th, td {
151 167
                   alert("Please enter a Lot No.");
152 168
                   return;
153 169
               }
170
+              if (!this.qa1) {
171
+                  alert("Select QA.1");
172
+                  return;
173
+              }
174
+              if (!this.qa2) {
175
+                  alert("Select QA.2");
176
+                  return;
177
+              }
178
+              if (this.exports.length == 0) {
179
+                  alert("Select Export Template");
180
+                  return;
181
+              }
154 182
 
155 183
               try {
156 184
                   // Make POST request using Axios
@@ -158,7 +186,8 @@ th, td {
158 186
                       lot_no: this.lot_no,
159 187
                       exports: this.exports,
160 188
                       qa1: this.qa1,
161
-                      qa2: this.qa2
189
+                      qa2: this.qa2,
190
+                      acceptStatus: this.acceptStatus
162 191
                   });
163 192
 
164 193
                   if (response.status === 200) {

+ 91 - 13
app/report/views.py

@@ -8,7 +8,8 @@ from .filters import ReportFilter
8 8
 from .forms import ExportOptionsForm
9 9
 from pprint import pprint
10 10
 
11
-from legacy.models import Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData, TbFgPressinfoLotlist
11
+from legacy.models import Data, DataMs, DataRl, DataWb, LotSummary, LotSummaryRl, LotSummaryWb, PressCal, RotateData, TbFgPressinfoLotlist,\
12
+        Manualsize
12 13
 
13 14
 from .gen_report import gen_xlsx
14 15
 from django.core.files.base import File
@@ -161,6 +162,62 @@ def generate_hardness_out_in_values(lot_no):
161 162
     
162 163
     return placeholders
163 164
 
165
+def generate_dimension_values(lot_no):
166
+    """
167
+    Fetch dimension records from manualSize and DataMs models
168
+    and generate placeholder values for Standard, Actual, and Judgement.
169
+    Supports two row_no entries per lot.
170
+    """
171
+    # Fetch standard values from manualSize (limit to 2 rows)
172
+    manual_size_records = Manualsize.objects.filter(lotno=lot_no)
173
+
174
+    # Fetch actual and judgement values from DataMs ordered by row_no (limit to 2 rows)
175
+    data_ms_records = DataMs.objects.filter(lot_no=lot_no).order_by('row_no')[:2]
176
+
177
+    # Prepare placeholders
178
+
179
+    placeholders = {}
180
+    for i in range(1,7):
181
+        for j in range(1,4):
182
+            placeholders[f'v{i}_{j}'] = 0
183
+    
184
+    pprint(placeholders)
185
+    pprint(manual_size_records) 
186
+    for m in manual_size_records:
187
+        if m.size_name == "D":
188
+            placeholders['v1_1'] = placeholders['v4_1'] = f'{m.std} +{m.tolup} {m.tolun}'
189
+        if m.size_name == "T":
190
+            placeholders['v2_1'] = placeholders['v5_1'] = f'{m.std} +{m.tolup} {m.tolun}'
191
+        if m.size_name == "H":
192
+            placeholders['v3_1'] = placeholders['v6_1'] = f'{m.std} +{m.tolup} {m.tolun}'
193
+
194
+
195
+
196
+    # Ensure that we map each manualSize entry to a corresponding DataMs entry
197
+    for r in data_ms_records:
198
+        if r.row_no == 1:
199
+            placeholders[f'v1_2'] = r.dsize
200
+            placeholders[f'v1_3'] = r.dsizeok
201
+            
202
+            placeholders[f'v2_2'] = r.tsize
203
+            placeholders[f'v2_3'] = r.tsizeok
204
+            
205
+            placeholders[f'v3_2'] = r.hsize
206
+            placeholders[f'v3_3'] = r.hsizeok
207
+        
208
+        if r.row_no == 2:
209
+            placeholders[f'v4_2'] = r.dsize
210
+            placeholders[f'v4_3'] = r.dsizeok
211
+            
212
+            placeholders[f'v5_2'] = r.tsize
213
+            placeholders[f'v5_3'] = r.tsizeok
214
+            
215
+            placeholders[f'v6_2'] = r.hsize
216
+            placeholders[f'v6_3'] = r.hsizeok
217
+
218
+    hide_con(placeholders, "v4_2", "24:28")
219
+    return placeholders
220
+
164 221
 def merge_sheet_data_with_data(sheet_data, data):
165 222
     """
166 223
     Merge `sheet_data` with `data`.
@@ -180,6 +237,13 @@ def create_coi_file(lot_no, sheets, user, md):
180 237
     qa1 = User.objects.get(pk=md['qa1'])
181 238
     qa2 = User.objects.get(pk=md['qa2'])
182 239
 
240
+    accept = specialAccept = False
241
+    if md['acceptStatus'] == "accepted":
242
+        accept = True
243
+    if md['acceptStatus'] == "special_accepted":
244
+        specialAccept = True
245
+
246
+
183 247
     pprint(qa1)
184 248
     pprint(qa2)
185 249
     
@@ -190,25 +254,38 @@ def create_coi_file(lot_no, sheets, user, md):
190 254
                 sheet_data[sheet_name] = generate_hardness_out_values(lot_no)
191 255
             case 'hardness_out_in':
192 256
                 sheet_data[sheet_name] = generate_hardness_out_in_values(lot_no)
257
+            case 'dimension':
258
+                sheet_data[sheet_name] = generate_dimension_values(lot_no)
193 259
     
194 260
     converted_data = convert_sheet_data(sheet_data)
195 261
 
196 262
     print(f"sheet_data \n {sheet_data}") 
197 263
     print(f"converted_data \n {converted_data}")
198 264
 
265
+    results = queryFromMaster(lot_no)
266
+    first_result = results[0] if results else None
267
+    try:
268
+        pcs = int(first_result.PRO5) - int(first_result.PRO27)
269
+    except:
270
+        pcs = 0
271
+    if first_result:
272
+        size_str = f"{first_result.PRO10}x{first_result.PRO11}x{first_result.PRO12}";
273
+        spec = f"{first_result.PRO13} {first_result.PRO14} {first_result.PRO15} {first_result.PRO16} {first_result.PRO17} {first_result.PRO18}"
274
+    else:
275
+        size_str = ""
276
+        spec = ""
277
+
199 278
     data = {
200
-        "customer": "Tum Coder",
279
+        "customer": first_result.PRO1C,
201 280
         "inspect_date": "2025-01-15",
202
-        "lot_no": "12345",
203
-        "staff_name":  "Tum 8888",
204
-        "man_name":  "Tum 999",
205
-        "size": "Large",
206
-        "pcs": "10 pcs",
207
-        "spec": "Spec-A",
208
-        "hardness_out.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
209
-        "hardness_out.spe_acc": False,  # Hide rows 24 to 28 if the prefix is "0"
210
-        "acc": True,  # Hide rows 24 to 28 if the prefix is "0"
211
-        "spe_acc": True,  # Hide rows 24 to 28 if the prefix is "0"
281
+        "lot_no": lot_no,
282
+        "size": size_str,
283
+        "pcs": pcs,
284
+        "spec": spec,
285
+        # "hardness_out.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
286
+        # "hardness_out.spe_acc": False,  # Hide rows 24 to 28 if the prefix is "0"
287
+        "acc": accept,  # Hide rows 24 to 28 if the prefix is "0"
288
+        "spe_acc": specialAccept,  # Hide rows 24 to 28 if the prefix is "0"
212 289
         # "hardness_out.qa1": f"{qa1.first_name} {qa1.last_name}",
213 290
         # "hardness_out.qa2": f"{qa2.first_name} {qa2.last_name}",
214 291
         "qa1": f"{qa1.first_name} {qa1.last_name}",
@@ -385,7 +462,8 @@ def gen_report_view(request):
385 462
                 return HttpResponseBadRequest("Missing 'lot_no' in request data")
386 463
 
387 464
             # Call the `create_coi_file` function with the provided lot_no
388
-            report = create_coi_file(lot_no, exports, request.user, {'qa1': qa1, 'qa2': qa2})
465
+            report = create_coi_file(lot_no, exports, request.user, {'qa1': qa1, 'qa2': qa2, \
466
+                    'acceptStatus': data.get('acceptStatus')})
389 467
 
390 468
             # Return a success response with the report details
391 469
             return JsonResponse({

BIN
app/report/~$coi_templates.xlsx


+ 3 - 0
app/templates/base.html

@@ -94,6 +94,9 @@
94 94
                             <a href="{% url "legacy:datams-list" %}" class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Measurement</a>
95 95
                           </li>
96 96
                           <li>
97
+                            <a href="{% url "legacy:rotate-list" %}" class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Rotate Data</a>
98
+                          </li>
99
+                          <li>
97 100
                             <a href="{% url "legacy:fg-list" %}" class="flex items-center w-full p-2 text-gray-900 transition duration-75 rounded-lg pl-11 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700">Fg Press Info</a>
98 101
                           </li>
99 102
                           <li>