tum 11 mēneši atpakaļ
vecāks
revīzija
2ff5179c56

+ 1 - 1
app/core/utils.py

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

+ 8 - 1
app/legacy/filters.py

1
 import django_filters
1
 import django_filters
2
 from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary, DataRl, DataWb, \
2
 from .models import Data, DataMs, TbFgPressinfoLotlist, LotSummary, DataRl, DataWb, \
3
-        LotSummaryRl, LotSummaryWb
3
+        LotSummaryRl, LotSummaryWb, RotateData
4
 
4
 
5
 class DataFilter(django_filters.FilterSet):
5
 class DataFilter(django_filters.FilterSet):
6
     lot_no = django_filters.CharFilter(field_name='lot_no', lookup_expr='icontains')
6
     lot_no = django_filters.CharFilter(field_name='lot_no', lookup_expr='icontains')
78
         model = LotSummaryWb
78
         model = LotSummaryWb
79
         fields = ['lot_no', 'code']  # Add fields you want to filter
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
 from django.urls import path
1
 from django.urls import path
2
 from .views import DataListView, DataDetailView, DataCreateView, DataUpdateView, DataDeleteView,\
2
 from .views import DataListView, DataDetailView, DataCreateView, DataUpdateView, DataDeleteView,\
3
 DataMsCRUDView, TbFgPressInfoLotListCRUDView, LotSummaryCRUDView, VMasterViewCRUDView, MgMasterViewCRUDView,\
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
 app_name = 'legacy'  # Namespace for this app
7
 app_name = 'legacy'  # Namespace for this app
7
 
8
 
16
 datawb_crud = DataWbCRUDView()
17
 datawb_crud = DataWbCRUDView()
17
 lsrl_crud = LotSummaryRlCRUDView()
18
 lsrl_crud = LotSummaryRlCRUDView()
18
 lswb_crud = LotSummaryWbCRUDView()
19
 lswb_crud = LotSummaryWbCRUDView()
20
+rotate_crud = RotateDataCRUDView()
19
 
21
 
20
 urlpatterns = [
22
 urlpatterns = [
21
     path('data/', DataListView.as_view(), name='data-list'),            # data/
23
     path('data/', DataListView.as_view(), name='data-list'),            # data/
79
     path('lswb/create/', lswb_crud.get_create_view().as_view(), name='lswb-create'),
81
     path('lswb/create/', lswb_crud.get_create_view().as_view(), name='lswb-create'),
80
     path('lswb/<int:pk>/update/', lswb_crud.get_update_view().as_view(), name='lswb-update'),
82
     path('lswb/<int:pk>/update/', lswb_crud.get_update_view().as_view(), name='lswb-update'),
81
     path('lswb/<int:pk>/delete/', lswb_crud.get_delete_view().as_view(), name='lswb-delete'),
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
     DeleteView,
11
     DeleteView,
12
 )
12
 )
13
 from django.core.paginator import Paginator
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
 from .filters import DataFilter, DataMsFilter, TbFgPressFilter, LotSummaryFilter, \
16
 from .filters import DataFilter, DataMsFilter, TbFgPressFilter, LotSummaryFilter, \
16
-        DataRlFilter, DataWbFilter, LotSummaryRlFilter, LotSummaryWbFilter
17
+        DataRlFilter, DataWbFilter, LotSummaryRlFilter, LotSummaryWbFilter, RotateDataFilter
17
 from django.urls import reverse
18
 from django.urls import reverse
18
 from django.contrib import messages
19
 from django.contrib import messages
19
 from pprint import pprint
20
 from pprint import pprint
374
     delete_url_name = 'legacy:lswb-delete'
375
     delete_url_name = 'legacy:lswb-delete'
375
     # excludes = ["splitdata"]
376
     # excludes = ["splitdata"]
376
     config_field_orders = ["id", "lot_no", "code"]  # Display these fields first
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
         <div class="grid grid-cols-4 gap-4">
24
         <div class="grid grid-cols-4 gap-4">
25
         {% for key,value in SHEET_NAMES.items %}
25
         {% for key,value in SHEET_NAMES.items %}
26
         <label class="flex items-center space-x-1">
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
           <span>{{ value }}</span>
28
           <span>{{ value }}</span>
29
         </label>
29
         </label>
30
         {% endfor %}
30
         {% endfor %}
32
         <div class="grid grid-cols-2 gap-4">
32
         <div class="grid grid-cols-2 gap-4">
33
           <div class="my-4">
33
           <div class="my-4">
34
             <label for="qa1" class="block mb-2 text-sm font-medium text-gray-900">Select QA.1</label>
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
               <option value="" disabled selected>Choose a user</option>
36
               <option value="" disabled selected>Choose a user</option>
37
               {% for user in users %}
37
               {% for user in users %}
38
               <option value="{{ user.id }}">{{ user.profile }}</option>
38
               <option value="{{ user.id }}">{{ user.profile }}</option>
41
           </div>
41
           </div>
42
           <div class="my-4">
42
           <div class="my-4">
43
             <label for="qa2" class="block mb-2 text-sm font-medium text-gray-900">Select QA.2</label>
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
               <option value="" disabled selected>Choose a user</option>
45
               <option value="" disabled selected>Choose a user</option>
46
               {% for user in users %}
46
               {% for user in users %}
47
               <option value="{{ user.id }}">{{ user.profile }}</option>
47
               <option value="{{ user.id }}">{{ user.profile }}</option>
50
           </div>
50
           </div>
51
         </div>
51
         </div>
52
         <div class="flex justify-end my-3 space-x-4">
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
           <div>
68
           <div>
54
             <button  type='button' class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" 
69
             <button  type='button' class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" 
55
                                    @click="exportCOI">
70
                                    @click="exportCOI">
140
       qa1: null,
155
       qa1: null,
141
       qa2: null,
156
       qa2: null,
142
       gen_report_url: '{% url "report:gen_report" %}', 
157
       gen_report_url: '{% url "report:gen_report" %}', 
158
+      acceptStatus: 'accepted', 
143
       downloadUrl: null, // Stores the download link after export success
159
       downloadUrl: null, // Stores the download link after export success
144
       init() {
160
       init() {
145
         //alert("COI Report");
161
         //alert("COI Report");
151
                   alert("Please enter a Lot No.");
167
                   alert("Please enter a Lot No.");
152
                   return;
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
               try {
183
               try {
156
                   // Make POST request using Axios
184
                   // Make POST request using Axios
158
                       lot_no: this.lot_no,
186
                       lot_no: this.lot_no,
159
                       exports: this.exports,
187
                       exports: this.exports,
160
                       qa1: this.qa1,
188
                       qa1: this.qa1,
161
-                      qa2: this.qa2
189
+                      qa2: this.qa2,
190
+                      acceptStatus: this.acceptStatus
162
                   });
191
                   });
163
 
192
 
164
                   if (response.status === 200) {
193
                   if (response.status === 200) {

+ 91 - 13
app/report/views.py

8
 from .forms import ExportOptionsForm
8
 from .forms import ExportOptionsForm
9
 from pprint import pprint
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
 from .gen_report import gen_xlsx
14
 from .gen_report import gen_xlsx
14
 from django.core.files.base import File
15
 from django.core.files.base import File
161
     
162
     
162
     return placeholders
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
 def merge_sheet_data_with_data(sheet_data, data):
221
 def merge_sheet_data_with_data(sheet_data, data):
165
     """
222
     """
166
     Merge `sheet_data` with `data`.
223
     Merge `sheet_data` with `data`.
180
     qa1 = User.objects.get(pk=md['qa1'])
237
     qa1 = User.objects.get(pk=md['qa1'])
181
     qa2 = User.objects.get(pk=md['qa2'])
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
     pprint(qa1)
247
     pprint(qa1)
184
     pprint(qa2)
248
     pprint(qa2)
185
     
249
     
190
                 sheet_data[sheet_name] = generate_hardness_out_values(lot_no)
254
                 sheet_data[sheet_name] = generate_hardness_out_values(lot_no)
191
             case 'hardness_out_in':
255
             case 'hardness_out_in':
192
                 sheet_data[sheet_name] = generate_hardness_out_in_values(lot_no)
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
     converted_data = convert_sheet_data(sheet_data)
260
     converted_data = convert_sheet_data(sheet_data)
195
 
261
 
196
     print(f"sheet_data \n {sheet_data}") 
262
     print(f"sheet_data \n {sheet_data}") 
197
     print(f"converted_data \n {converted_data}")
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
     data = {
278
     data = {
200
-        "customer": "Tum Coder",
279
+        "customer": first_result.PRO1C,
201
         "inspect_date": "2025-01-15",
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
         # "hardness_out.qa1": f"{qa1.first_name} {qa1.last_name}",
289
         # "hardness_out.qa1": f"{qa1.first_name} {qa1.last_name}",
213
         # "hardness_out.qa2": f"{qa2.first_name} {qa2.last_name}",
290
         # "hardness_out.qa2": f"{qa2.first_name} {qa2.last_name}",
214
         "qa1": f"{qa1.first_name} {qa1.last_name}",
291
         "qa1": f"{qa1.first_name} {qa1.last_name}",
385
                 return HttpResponseBadRequest("Missing 'lot_no' in request data")
462
                 return HttpResponseBadRequest("Missing 'lot_no' in request data")
386
 
463
 
387
             # Call the `create_coi_file` function with the provided lot_no
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
             # Return a success response with the report details
468
             # Return a success response with the report details
391
             return JsonResponse({
469
             return JsonResponse({

BIN
app/report/~$coi_templates.xlsx


+ 3 - 0
app/templates/base.html

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>
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
                           </li>
95
                           </li>
96
                           <li>
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
                             <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>
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
                           </li>
101
                           </li>
99
                           <li>
102
                           <li>