From 3ecd0e1361316802b454d46e8cc09e35647857ab Mon Sep 17 00:00:00 2001 From: ske087 Date: Wed, 23 Apr 2025 16:34:42 +0300 Subject: [PATCH] created quality page --- py_app/app/__pycache__/routes.cpython-311.pyc | Bin 15785 -> 16455 bytes py_app/app/routes.py | 17 +- py_app/app/static/script.js | 76 +++++++ py_app/app/static/style.css | 83 ++++++++ py_app/app/templates/dashboard.html | 20 +- py_app/app/templates/quality.html | 34 ++- py_app/documentation.md | 198 ++++++++++++++++++ 7 files changed, 421 insertions(+), 7 deletions(-) create mode 100644 py_app/documentation.md diff --git a/py_app/app/__pycache__/routes.cpython-311.pyc b/py_app/app/__pycache__/routes.cpython-311.pyc index b39d66d2f84bfd6fe90b1f0dd12617e16314525e..4f6e790dd07f8a11c9c5da0dc2c3c76f1a7c0ea4 100644 GIT binary patch delta 2408 zcmbtVU2GIp6rMY?GrQZ}+5YTqyRExrC@pm8AKR9+&=yJok?^CUK&-}f%S?Bd?(Wn( zTMI>OV@QYz50d*JiGQdG1WAm^8iVmgpM263#b_q+=fx<>Lyb`r9?)}UmnmDzlask$ z&Ufy)_nv#^oHJKWeYQXXmu0z%gJ;VvPx^({^MMGNKEGjTH0K-l5l#~{SJt1C$7Nd< zvw>Xocs1d8P8T#uuero?+*KH*XS`N(pW(*q^xBI-wxgl`{0FKSDw8nFMyi=af@0Xw z^pO^^-eCr?28Ue*7IE0mWTV*VunxXOY;stNZx zuv}@wEYOB`Zc2po6n}L`glHV}G=zW_D!(k#M%L^*rpmZbe0D~sCoS(}CR@;HV&bGF zPG%_VWv}$&@_zQNuc_79i8g}L6aW-Oq22Z-StFIn)1l%ozFmYgvMzbBei)b9vtBJ} zrYDRf)#xZYC2uFg#gFCVJn3iaYvSR}Xjh9+hY&>Yvuw@odGwDC0$4&ao25~tF@$CW z%p1A}K|yFiSclMx-~v$HbQj9I5!w+pB6J{hB6I<{ zH^z)$oNQ)q1-sU4M+4`2^dY1OdtjK4a4azxW_)NH8D={|UoCGC4R7wj%gzO6lT=R| zGp631F66RwFK)16(|xGh#}>j*L$rPf|0ON&^Ifzq&Qw30UVs1jvViS4A1qlN33kk@a8m9k%%xuGtB2Th1jj z`EFA$6f*ggxtx|Np&>S+MtvbP#iWJQ)6}5^-i|uiK(`>>iVy&Rp^;Op8BgKw_%l}_RbZrmb~(P)^x*R_9Q zg*!*Vr0gw9=+j+yrYfiG!m0Gct81A;$&VZue+a|;8&hbEz0rLQoI2XGhi_WNDQfSX zW!K_E`&Vn+unN%j_vIGLg-%Y*m}HD140C0 z`BT-h_JPauwk!9mRLhe~PQit#X}JOO$((N2ttHOVOhJcwz3=W$`TnO~tr|1=oSx86 zz&-Qq;GjfK6b}#nL+a*gdY~W@RG&5=&$VPB$)54ni|4@YSJ)0$go&>3m_{la@o6r_ zY5dzn6Q1W@U6_h{afkm9wf*Z9+<;AXcrHO)h(_8qjO(pjo7=hGrbk8ysCHQD%)sYDeKE?%B)Z2 zEq7W^YES@{iyE^glnC}a%ax>1d3NUdfJ1|uv(*?S^WNmBUJ*jN0Csm^n3#VH+)r}o z+*9Ao%ds!z*oE|UdBY8P!@`405*Hd=3=Y8iquhP*$fDd`dfyLx5?J&<{OxMWB~hrY zS`sC{w8Q}{?D{jn`GYU_zcg}gWYHC|JFcpfegkcAIQ*!xNpp(ApNLIuZJnoh6HCe& zkk6*wF068g@FWtLYl(!#PfXJudo6`7rPCph=_rET_3c)^52@YqG?X$3SetYj;RM10 zLS^T>9r6sr(KA_n8$Aot_-i+>vB*$#G{4CGueX>V>f#4_Io@?P@?vDMDtev7Zjjg# VUqu?1IDp>;j&H8e*lIgs{{q?wH|+ob delta 1830 zcmbW1U1%It6oBW>?Cfs3Kizb9lQqr8%@0W@+ia6;)5LDt(ApAPV%3&t3Ftb>T(X z+Sgo_8?nv|$AsK!pHqlmsg~n=&q1%;t zOJ@d~;-AN+NXZSvmt<1pR$?T581)i}R>VF;gnyJcy&A>gIKWeM(`5Tm>_lV{_|{n$ z;$cKLq6g875Kf2Kqc}c=7(i%x6t(1Aq?+&d_`xpVlCUWP;qJ|dknYScg$Iw zJIlXJKL`0a(DrArc}{;e9~5aCcAv?Hl=d-HJp%BQMe2C!Wmc^_tiYFZeWZ`y$aM}r zjvD6>PavK|JcT%qxB&113s$|(F7lsp>HI8A*qCmShAlL*F@qZrLgx>KzucO3$GX1? zL^8M{3g#H!)8CQV8IKo)ny{7~w!kO*&p=48_WvNC7wRW)<4M3~tfp7%1)DlfwZ3RK zOH3nTd_6U5Qd+c9E`L; z(*!H>>|lFRly77K3^=q5?}xF9J3ZJ#z~QC5C3o#~m{B}0gnH$w!BYIMp_z;K8Gjn> zV!JhRgC1-fU)s5Z3AC|LG2vUSLXE1^@WXW9Dg@Avn}??5j$Qm<;5q*YryeBeT5_u&&pr=v+@-VO57}A@;!2{RaL|$9f4{ze3COD#Te2>1NrOXDja8 z6MvHyt*i0b=;NPFj;?yangyZSqEx)C>Ij$1=tjBh$@7<40iy9#28B!6QH*Q~AwCJB z&qbGto>;(z3c^HKh!w=nKG+OTg3)D@9%s+L1j_^-`*q0vJ%tdmA+@ZDdqaw^iF-q$ W-~Qj9`^&K*IWD!6!aaoeM*RcZ36f6$ diff --git a/py_app/app/routes.py b/py_app/app/routes.py index 598019d..93ce422 100644 --- a/py_app/app/routes.py +++ b/py_app/app/routes.py @@ -1,6 +1,6 @@ import os import mariadb -from flask import Blueprint, render_template, redirect, url_for, request, flash, session, current_app +from flask import Blueprint, render_template, redirect, url_for, request, flash, session, current_app, jsonify from .models import User from . import db @@ -249,4 +249,17 @@ def save_external_db(): f.write(f"password={password}\n") flash('External database settings saved/updated successfully.') - return redirect(url_for('main.settings')) \ No newline at end of file + return redirect(url_for('main.settings')) + +@bp.route('/get_report_data') +def get_report_data(): + report = request.args.get('report') + # Mock data for demonstration + data = { + "headers": ["Column 1", "Column 2", "Column 3"], + "rows": [ + [f"Row 1, Col 1 (Report {report})", "Row 1, Col 2", "Row 1, Col 3"], + [f"Row 2, Col 1 (Report {report})", "Row 2, Col 2", "Row 2, Col 3"], + ], + } + return jsonify(data) \ No newline at end of file diff --git a/py_app/app/static/script.js b/py_app/app/static/script.js index d3ad383..2c18792 100644 --- a/py_app/app/static/script.js +++ b/py_app/app/static/script.js @@ -120,4 +120,80 @@ document.addEventListener('DOMContentLoaded', () => { deleteUserPopup.style.display = 'none'; } }); + + const reportButtons = document.querySelectorAll('.report-btn'); + const reportTitle = document.getElementById('report-title'); + const reportTable = document.getElementById('report-table'); + + // Handle report button clicks + reportButtons.forEach((button) => { + button.addEventListener('click', () => { + const reportNumber = button.dataset.report; + + // Update the title dynamically + reportTitle.textContent = `Data for "Report ${reportNumber}"`; + + // Fetch data for the selected report (mocked for now) + fetch(`/get_report_data?report=${reportNumber}`) + .then((response) => response.json()) + .then((data) => { + populateTable(data); + }) + .catch((error) => { + console.error('Error fetching report data:', error); + }); + }); + }); + + // Populate the table with data + function populateTable(data) { + const tableHead = reportTable.querySelector('thead tr'); + const tableBody = reportTable.querySelector('tbody'); + + // Clear existing table content + tableHead.innerHTML = ''; + tableBody.innerHTML = ''; + + if (data.headers && data.rows) { + // Populate table headers + data.headers.forEach((header) => { + const th = document.createElement('th'); + th.textContent = header; + tableHead.appendChild(th); + }); + + // Populate table rows + data.rows.forEach((row) => { + const tr = document.createElement('tr'); + row.forEach((cell) => { + const td = document.createElement('td'); + td.textContent = cell; + tr.appendChild(td); + }); + tableBody.appendChild(tr); + }); + } else { + // No data available + const tr = document.createElement('tr'); + const td = document.createElement('td'); + td.textContent = 'No data available.'; + td.colSpan = data.headers ? data.headers.length : 1; + tr.appendChild(td); + tableBody.appendChild(tr); + } + } + + // Export buttons + const exportCsvButton = document.getElementById('export-csv'); + const exportPdfButton = document.getElementById('export-pdf'); + + exportCsvButton.addEventListener('click', () => { + alert('Exporting current report as CSV...'); + // Add logic to export the current report as CSV + }); + + exportPdfButton.addEventListener('click', () => { + alert('Exporting current report as PDF...'); + // Add logic to export the current report as PDF + }); }); \ No newline at end of file diff --git a/py_app/app/static/style.css b/py_app/app/static/style.css index 601dd3f..38dc348 100644 --- a/py_app/app/static/style.css +++ b/py_app/app/static/style.css @@ -556,4 +556,87 @@ body.dark-mode .scan-table tr:nth-child(odd) { .scan-form-card, .scan-table-card { width: 100%; /* Make both cards take full width */ } +} + +/* Dashboard container */ +.dashboard-container { + display: flex; + flex-wrap: wrap; /* Allow wrapping to the next row if needed */ + justify-content: space-between; /* Distribute cards evenly */ + gap: 20px; /* Add spacing between the cards */ + margin: 20px auto; /* Center the container */ + max-width: 1200px; /* Optional: Limit the maximum width of the container */ +} + +/* Full-width card for the dashboard */ +.dashboard-full-width-card { + flex: 0 0 100%; /* Take up the full width of the container */ + text-align: center; + padding: 20px; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + transition: background-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease; +} + +/* Individual cards for the dashboard */ +.dashboard-card { + flex: 1 1 calc(25% - 20px); /* Ensure cards are evenly distributed */ + padding: 20px; + border-radius: 5px; + box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); + text-align: center; + transition: background-color 0.3s ease, color 0.3s ease, box-shadow 0.3s ease; +} + +/* Light mode styles for dashboard cards */ +body.light-mode .dashboard-card, +body.light-mode .dashboard-full-width-card { + background: #fff; + color: #000; + border: 1px solid #ddd; +} + +/* Dark mode styles for dashboard cards */ +body.dark-mode .dashboard-card, +body.dark-mode .dashboard-full-width-card { + background: #1e1e1e; + color: #fff; + border: 1px solid #444; +} + +/* Ensure cards have consistent height */ +.dashboard-card h3 { + margin-bottom: 15px; + font-size: 1.5em; +} + +.dashboard-card p { + margin-bottom: 20px; + color: inherit; /* Inherit text color from the card */ +} + +.dashboard-card .btn { + display: inline-block; + padding: 10px 20px; + font-size: 1em; + color: #fff; + background-color: #007bff; + text-decoration: none; + border-radius: 5px; + transition: background-color 0.3s ease; +} + +.dashboard-card .btn:hover { + background-color: #0056b3; +} + +/* Responsive design for smaller screens */ +@media (max-width: 768px) { + .dashboard-card { + flex: 1 1 100%; /* Stack cards vertically on smaller screens */ + } + + .dashboard-full-width-card { + flex: 1 1 100%; /* Ensure the full-width card spans the entire width */ + } } \ No newline at end of file diff --git a/py_app/app/templates/dashboard.html b/py_app/app/templates/dashboard.html index 8d36521..abf56d4 100644 --- a/py_app/app/templates/dashboard.html +++ b/py_app/app/templates/dashboard.html @@ -3,14 +3,28 @@ {% block title %}Dashboard{% endblock %} {% block content %} -
-
+
+ + + -
+
+

Accesare modul calitate

+

Modul de verificare si configurare setari calitate.

+ Lansare modul calitate +
+ +
+

Accesare modul magazie

+

Modul pentru managementul magaziei

+ Lansare modul Magazie +
+ +

Manage Settings

Access and manage application settings.

Access Settings Page diff --git a/py_app/app/templates/quality.html b/py_app/app/templates/quality.html index a06480a..4cad439 100644 --- a/py_app/app/templates/quality.html +++ b/py_app/app/templates/quality.html @@ -1,6 +1,36 @@ {% extends "base.html" %} {% block title %}Quality Module{% endblock %} {% block content %} -

Quality Module

-

Welcome to the Quality Module.

+
+ +
+

Rapoarte

+
+ + + + + +
+
+ + +
+
+ + +
+

No data to display, please select a report.

+ + + + + + + + + +
+
+
{% endblock %} \ No newline at end of file diff --git a/py_app/documentation.md b/py_app/documentation.md new file mode 100644 index 0000000..4398313 --- /dev/null +++ b/py_app/documentation.md @@ -0,0 +1,198 @@ +Here is the content for the `documentation.md` file that explains the functionality of the application: + +--- + +### Documentation for Quality Recticel Application + +--- + +#### **Overview** +The Quality Recticel application is a web-based system designed to manage and monitor quality control processes, user roles, and database interactions. It includes modules for scanning, quality assurance, warehouse management, and administrative settings. + +--- + +### **Features** + +#### 1. **User Management** +- **Roles**: + - `superadmin`: Full access to all features and settings. + - `administrator`: Limited administrative access. + - `quality`: Access to quality assurance features. + - `warehouse`: Access to warehouse management features. + - `scan`: Access to scanning features. +- **Functionalities**: + - Create, edit, and delete users. + - Assign roles to users. + - Manage user credentials. + +#### 2. **Scan Module** +- **Input Form**: + - Allows users to input scan data, including: + - Operator Code + - CP Code + - OC1 Code + - OC2 Code + - Defect Code + - Date and Time +- **Latest Scans Table**: + - Displays the last 15 scans with details such as: + - Approved Quantity + - Rejected Quantity + - Data is dynamically fetched from the database. + +#### 3. **Quality Module** +- Provides tools for quality assurance personnel to monitor and manage quality-related data. + +#### 4. **Warehouse Module** +- Enables warehouse personnel to manage inventory and related processes. + +#### 5. **Settings Module** +- **External Database Configuration**: + - Allows the `superadmin` to configure external database settings, including: + - Server Domain/IP + - Port + - Database Name + - Username and Password +- **User Management**: + - Provides an interface to manage users and their roles. + +--- + +### **Database Structure** + +#### **Table: `scan1_orders`** +- **Columns**: + - `Id`: Auto-incremented primary key. + - `operator_code`: Operator code (4 characters). + - `CP_full_code`: Full CP code (15 characters, unique). + - `OC1_code`: OC1 code (4 characters). + - `OC2_code`: OC2 code (4 characters). + - `CP_base_code`: Auto-generated base code (first 10 characters of `CP_full_code`). + - `quality_code`: Quality code (3 digits). + - `date`: Date in `yyyy-mm-dd` format. + - `time`: Time in `hh:mm:ss` format. + - `approved_quantity`: Number of approved items (calculated dynamically). + - `rejected_quantity`: Number of rejected items (calculated dynamically). + +#### **Triggers** +- **`increment_approved_quantity`**: + - Updates `approved_quantity` based on the number of rows with the same `CP_base_code` and `quality_code = 000`. +- **`increment_rejected_quantity`**: + - Updates `rejected_quantity` based on the number of rows with the same `CP_base_code` and `quality_code != 000`. + +--- + +### **Key Files** + +#### 1. **`run.py`** +- Entry point for the application. +- Starts the Flask server. + +#### 2. **`routes.py`** +- Defines the routes and logic for the application. +- Handles user authentication, form submissions, and database interactions. + +#### 3. **`models.py`** +- Defines the `User` model for managing user data. + +#### 4. **`create_scan_1db.py`** +- Script to create the `scan1_orders` table in the database. + +#### 5. **`create_triggers.py`** +- Script to create database triggers for dynamically updating `approved_quantity` and `rejected_quantity`. + +#### 6. **`seed.py`** +- Seeds the database with default users. + +#### 7. **Templates** +- **`scan.html`**: + - Interface for the Scan Module. +- **`settings.html`**: + - Interface for managing users and external database settings. + +--- + +### **How to Run the Application** + +1. **Set Up the Environment**: + - Install dependencies: + ```bash + pip install flask mariadb + ``` + +2. **Configure the Database**: + - Update the `external_server.conf` file with the correct database credentials. + +3. **Create the Database and Triggers**: + - Run the create_scan_1db.py script: + ```bash + python py_app/app/db_create_scripts/create_scan_1db.py + ``` + - Run the create_triggers.py script: + ```bash + python py_app/app/db_create_scripts/create_triggers.py + ``` + +4. **Seed the Database**: + - Run the seed.py script: + ```bash + python py_app/seed.py + ``` + +5. **Start the Application**: + - Run the run.py file: + ```bash + python py_app/run.py + ``` + +6. **Access the Application**: + - Open a browser and navigate to: + ``` + http://127.0.0.1:5000 + ``` + +--- + +### **Troubleshooting** + +1. **Database Connection Issues**: + - Ensure the `external_server.conf` file is correctly configured. + - Verify that the database server is running. + +2. **Trigger Errors**: + - Check the trigger definitions in the database using: + ```sql + SHOW TRIGGERS; + ``` + +3. **Form Submission Errors**: + - Verify that all required fields in the form are filled out. + +4. **Permission Issues**: + - Ensure the user has the correct role for accessing specific modules. + +--- + +### **Future Enhancements** +- Add detailed logging for debugging. +- Implement role-based access control for more granular permissions. +- Add support for exporting scan data to CSV or Excel. + +--- + +Save this content as `documentation.md` in the root directory of your project.3. **Form Submission Errors**: + - Verify that all required fields in the form are filled out. + +4. **Permission Issues**: + - Ensure the user has the correct role for accessing specific modules. + +--- + +### **Future Enhancements** +- Add detailed logging for debugging. +- Implement role-based access control for more granular permissions. +- Add support for exporting scan data to CSV or Excel. + +--- + +Save this content as `documentation.md` in the root directory of your project. \ No newline at end of file