tum 1 gadu atpakaļ
vecāks
revīzija
f526bca111

+ 1 - 1
app/coi/settings.py

@@ -172,7 +172,7 @@ AUTH_PASSWORD_VALIDATORS = [
172 172
 
173 173
 LANGUAGE_CODE = "en-us"
174 174
 
175
-TIME_ZONE = "UTC"
175
+TIME_ZONE = "Asia/Bangkok"
176 176
 
177 177
 USE_I18N = True
178 178
 

+ 1 - 0
app/package.json

@@ -1,6 +1,7 @@
1 1
 {
2 2
   "dependencies": {
3 3
     "alpinejs": "^3.14.7",
4
+    "axios": "^1.7.9",
4 5
     "font-awesome": "^4.7.0",
5 6
     "heroicons": "^2.2.0",
6 7
     "tailwindcss": "^3.4.17",

BIN
app/report/coi_templates.xlsx


+ 58 - 3
app/report/templates/report/coi.html

@@ -3,7 +3,7 @@
3 3
 {% block title %}Report Dashboard{% endblock %}
4 4
 
5 5
 {% block content %}
6
-<div class="container mx-auto px-4 py-8">
6
+<div class="container mx-auto px-4 py-8" x-data="COIReport">
7 7
 
8 8
   <h1 class="text-2xl font-bold text-gray-800">Export Center</h1>
9 9
   <form method='post'>
@@ -16,7 +16,7 @@
16 16
     </div>
17 17
     <div class="flex items-center gap-2 mb-4">
18 18
       <label for="lot-number" class="text-gray-700 font-medium">Lot No. :</label>
19
-      <input id="lot-number" type="text" class="border border-gray-300 rounded px-4 py-2 focus:outline-blue-500" placeholder="Enter Lot No." name='lot_no' required>
19
+      <input id="lot-number" type="text" class="border border-gray-300 rounded px-4 py-2 focus:outline-blue-500" placeholder="Enter Lot No." name='lot_no' required x-model="lot_no">
20 20
       <button class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" type="submit" name="search_lot">
21 21
         🔍
22 22
       </button>
@@ -59,9 +59,16 @@
59 59
           <span>Final Judge</span>
60 60
         </label>
61 61
       </div>
62
-      <button class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" type='submit' name='export'>
62
+      <button  type='button' class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600" 
63
+        @click="exportCOI">
63 64
         Export Excel
64 65
       </button>
66
+      <!-- TODO: add download here -->
67
+      <div class=" text-center" x-show="downloadUrl">
68
+        <a :href="downloadUrl"  class="px-4 py-2 bg-green-600 text-white font-medium rounded-md hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-green-500 focus:ring-offset-2" download>
69
+          Download Report
70
+        </a>
71
+      </div>
65 72
     </div>
66 73
   </form>
67 74
   {{ result }}
@@ -130,3 +137,51 @@
130 137
 <div class="border-t border-gray-300 my-4"></div>
131 138
 {% include "report/_cen.html" %}
132 139
 {% endblock %}
140
+{% block footer_script %}
141
+<script type="text/javascript">
142
+  function COIReport() {
143
+    return {
144
+      lot_no: '', // Bind this to the input value
145
+      gen_report_url: '{% url "report:gen_report" %}', 
146
+      downloadUrl: null, // Stores the download link after export success
147
+      init() {
148
+        //alert("COI Report");
149
+      },
150
+      async exportCOI() {
151
+              if (!this.lot_no) {
152
+                  alert("Please enter a Lot No.");
153
+                  return;
154
+              }
155
+
156
+              try {
157
+                  // Make POST request using Axios
158
+                  const response = await axios.post(this.gen_report_url, {
159
+                      lot_no: this.lot_no,
160
+                  });
161
+
162
+                  if (response.status === 200) {
163
+                      const result = response.data;
164
+                      alert(`Report generated successfully: ${result.file_url}`);
165
+                      console.log('File URL:', result.file_url);
166
+                      this.downloadUrl = result.file_url; // Set the download URL
167
+                  }
168
+              } catch (error) {
169
+                  if (error.response) {
170
+                      // Server responded with a status other than 2xx
171
+                      alert(`Error: ${error.response.data.message || 'Failed to generate report'}`);
172
+                      console.error('Error response:', error.response);
173
+                  } else if (error.request) {
174
+                      // Request was made but no response received
175
+                      alert('No response from server.');
176
+                      console.error('Request error:', error.request);
177
+                  } else {
178
+                      // Something else caused the error
179
+                      alert('An unexpected error occurred.');
180
+                      console.error('Unexpected error:', error.message);
181
+                  }
182
+              }
183
+          },
184
+    };
185
+  }
186
+</script>
187
+{% endblock %}

+ 2 - 0
app/report/urls.py

@@ -14,6 +14,8 @@ urlpatterns = [
14 14
     path('report/<int:pk>/update/', report_crud.get_update_view().as_view(), name='report-update'),
15 15
     path('report/<int:pk>/delete/', report_crud.get_delete_view().as_view(), name='report-delete'),
16 16
     path('coi/', views.coi_view, name='coi-view'),
17
+    path('report/generate/', views.gen_report_view, name='gen_report'),
18
+
17 19
     # path('create/', views.create_report, name='create'),  # Create a new report
18 20
     # path('<int:pk>/', views.detail_report, name='detail'),  # View details of a specific report
19 21
     # path('<int:pk>/update/', views.update_report, name='update'),  # Update a specific report

+ 89 - 7
app/report/views.py

@@ -11,7 +11,10 @@ from pprint import pprint
11 11
 from .gen_report import gen_xlsx
12 12
 from django.core.files.base import File
13 13
 from pathlib import Path
14
-
14
+from django.views.decorators.csrf import csrf_exempt
15
+from django.http import JsonResponse, HttpResponseBadRequest
16
+import json
17
+from django.contrib.auth.decorators import login_required
15 18
 
16 19
 def index(request):
17 20
     reports = Report.objects.all()
@@ -62,6 +65,52 @@ class ReportCRUDView(ConfigurableCRUDView):
62 65
     # config_edit_fields = ["lot_no", "code"]
63 66
     ordering = ["-created_at", "-id",]
64 67
 
68
+def create_coi_file(lot_no, user):
69
+
70
+    data = {
71
+        "customer": "Tum Coder",
72
+        "inspect_date": "2025-01-15",
73
+        "lot_no": "12345",
74
+        "staff_name":  "Tum 8888",
75
+        "man_name":  "Tum 999",
76
+        "size": "Large",
77
+        "pcs": "10 pcs",
78
+        "spec": "Spec-A",
79
+        "hardness_out.d1_act": "10",
80
+        "hardness_out.d2_act": "0[24:28]",  # Hide rows 24 to 28 if the prefix is "0"
81
+        "hardness_out.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
82
+        "hardness_out.spe_acc": False,  # Hide rows 24 to 28 if the prefix is "0"
83
+        "hardness_out.qa1": "Hello world",
84
+        "hardness_out.qa2": "Unknow person",
85
+        "hardness_out.v11": 5,
86
+        "hardness_out.v12": 15,
87
+        "hardness_out.v13": 10,
88
+        "hardness_out.v21": 9,
89
+        "hardness_out.v22": 8,
90
+        "hardness_out.v23": 7,
91
+        "dimension_app.d1_act": "33",
92
+        "dimension_app.d2_act": "0[26:32]",  # Hide rows 24 to 28 if the prefix is "0"
93
+        "dimension_app.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
94
+        "dimension_app.spe_acc": True,  # Hide rows 24 to 28 if the prefix is "0"
95
+    }
96
+    output_file = gen_xlsx(
97
+        template_file="/app/report/coi_templates.xlsx",
98
+        selected_sheets=["hardness_out", "dimension_app"],  # Replace with your actual sheet names
99
+        prefix_filename="/app/media/coi",
100
+        data=data
101
+    )
102
+    report = Report.objects.create(
103
+        name=lot_no,
104
+        created_by=user,
105
+        file=None  # Leave this as None or assign a file if required
106
+    )
107
+    output_file_path = Path(output_file)  # Convert to a Path object for convenience
108
+    with open(output_file_path, "rb") as f:
109
+        report.file.save(output_file_path.name, File(f), save=True)
110
+
111
+    pprint(f"outputfile = {output_file}")
112
+    return report
113
+
65 114
 def coi_view(request):
66 115
     pprint(f"xxxx method = xxx {request.method}")
67 116
     if request.method == "POST":
@@ -75,12 +124,12 @@ def coi_view(request):
75 124
                 "staff_name":  "Tum 8888",
76 125
                 "man_name":  "Tum 999",
77 126
                 "size": "Large",
78
-                "pcs": "10 pcs",
127
+                "lot_size": "10 pcs",
79 128
                 "spec": "Spec-A",
80
-                "hardness.d1_act": "10",
81
-                "hardness.d2_act": "0[24:28]",  # Hide rows 24 to 28 if the prefix is "0"
82
-                "hardness.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
83
-                "hardness.spe_acc": False,  # Hide rows 24 to 28 if the prefix is "0"
129
+                "hardness_out.d1_act": "10",
130
+                "hardness_out.d2_act": "0[24:28]",  # Hide rows 24 to 28 if the prefix is "0"
131
+                "hardness_out.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
132
+                "hardness_out.spe_acc": False,  # Hide rows 24 to 28 if the prefix is "0"
84 133
                 "dimension_app.d1_act": "33",
85 134
                 "dimension_app.d2_act": "0[26:32]",  # Hide rows 24 to 28 if the prefix is "0"
86 135
                 "dimension_app.acc": True,  # Hide rows 24 to 28 if the prefix is "0"
@@ -88,7 +137,7 @@ def coi_view(request):
88 137
             }
89 138
             output_file = gen_xlsx(
90 139
                 template_file="/app/report/coi_templates.xlsx",
91
-                selected_sheets=["hardness", "dimension_app"],  # Replace with your actual sheet names
140
+                selected_sheets=["hardness_out", "dimension_app"],  # Replace with your actual sheet names
92 141
                 prefix_filename="/app/media/coi",
93 142
                 data=data
94 143
             )
@@ -124,3 +173,36 @@ def coi_view(request):
124 173
         messages.success(request, "Request Sent")
125 174
         return redirect(request.path_info)
126 175
     return render(request, 'report/coi.html')
176
+
177
+@csrf_exempt  # Disable CSRF for API requests (ensure this is secure in production)
178
+@login_required
179
+def gen_report_view(request):
180
+    if request.method == "POST":
181
+        try:
182
+            # Parse JSON data from the request body
183
+            data = json.loads(request.body)
184
+            lot_no = data.get("lot_no")
185
+
186
+            if not lot_no:
187
+                return HttpResponseBadRequest("Missing 'lot_no' in request data")
188
+
189
+            # Call the `create_coi_file` function with the provided lot_no
190
+            report = create_coi_file(lot_no, request.user)
191
+
192
+            # Return a success response with the report details
193
+            return JsonResponse({
194
+                "message": "Report generated successfully",
195
+                "report_id": report.id,
196
+                "file_url": report.file.url if report.file else None,
197
+            })
198
+
199
+        except json.JSONDecodeError:
200
+            return HttpResponseBadRequest("Invalid JSON data")
201
+        except Exception as e:
202
+            pprint(e)
203
+            return JsonResponse({"error": str(e)}, status=500)
204
+    else:
205
+        return HttpResponseBadRequest("Only POST requests are allowed")
206
+
207
+
208
+

BIN
app/report/~$coi_templates.xlsx


+ 9 - 6
app/templates/base.html

@@ -16,6 +16,7 @@
16 16
     <link href="{% static "font-awesome/css/font-awesome.css" %}" rel="stylesheet" />
17 17
     <script type="text/javascript" defer src="{% static "alpinejs/dist/cdn.min.js" %}"></script>
18 18
     <link href="https://cdn.jsdelivr.net/npm/flowbite@2.5.2/dist/flowbite.min.css" rel="stylesheet" />
19
+    <script type="text/javascript"  src="{% static "axios/dist/axios.js" %}"></script>
19 20
     <script type="text/javascript"  src="{% static "js/main.js" %}"></script>
20 21
 </head>
21 22
 <body class="bg-gray-100 text-gray-800">
@@ -144,14 +145,16 @@
144 145
 
145 146
     {% django_browser_reload_script %}
146 147
     <script>
147
-    // Auto-hide the message after 5 seconds
148
-    setTimeout(() => {
148
+      // Auto-hide the message after 5 seconds
149
+      setTimeout(() => {
149 150
         const alert = document.getElementById('message-alert');
150 151
         if (alert) {
151
-            alert.style.opacity = '0'; // Fade out
152
-            setTimeout(() => alert.remove(), 500); // Remove after fade-out
152
+          alert.style.opacity = '0'; // Fade out
153
+          setTimeout(() => alert.remove(), 500); // Remove after fade-out
153 154
         }
154
-    }, 5000); // 5 seconds
155
-</script>
155
+      }, 5000); // 5 seconds
156
+    </script>
157
+    {% block footer_script %}
158
+    {% endblock %}
156 159
 </body>
157 160
 </html>