Explorar el Código

[#1] Fix page 2 text loss, scale header logos, add DOPRO1 to footer, purge hardcoded secrets, and add header/footer guidelines

Lange François hace 2 semanas
padre
commit
e47fdcbae4

+ 9 - 8
INSTALL_WSL.md

@@ -59,16 +59,17 @@ DB_APP_AUTH_PASS=your_secure_auth_password
 MYSQL_ZABBIX_PASSWORD=your_secure_zabbix_password
 
 # ZABBIX & SNMP CREDENTIALS
-ZABBIX_USER=Admin
-ZABBIX_PASS=zabbix
-ZABBIX_SNMP_USER=zabbix_snmp
-ZABBIX_SNMP_AUTHKEY=authkey123
-ZABBIX_SNMP_PRIVKEY=privkey123
-DISCORD_WEBHOOK=https://discord.com/api/webhooks/your_webhook_id
+ZABBIX_URL=your_zabbix_url
+ZABBIX_USER=your_zabbix_user
+ZABBIX_PASS=your_zabbix_pass
+ZABBIX_SNMP_USER=your_snmp_user
+ZABBIX_SNMP_AUTHKEY=your_snmp_authkey
+ZABBIX_SNMP_PRIVKEY=your_snmp_privkey
+DISCORD_WEBHOOK=your_discord_webhook
 
 # EMAIL ALERTS CONFIGURATION
-EMAIL_USER=your_email@gmail.com
-EMAIL_PASS=your_email_app_password
+EMAIL_USER=your_email_user
+EMAIL_PASS=your_email_pass
 
 # TAIGA CREDENTIALS
 TAIGA_URL=https://192.168.130.161/taiga

BIN
Project.pdf


BIN
Retro Planning.pdf


+ 3 - 3
configure_zabbix_alerts.py

@@ -4,11 +4,11 @@ import json
 import urllib.request
 import os
 
-ZABBIX_URL = os.environ.get('ZABBIX_URL', 'http://192.168.130.170:8081/api_jsonrpc.php')
-ZABBIX_USER = os.environ.get('ZABBIX_USER', 'Admin')
+ZABBIX_URL = os.environ.get('ZABBIX_URL', '')
+ZABBIX_USER = os.environ.get('ZABBIX_USER', '')
 ZABBIX_PASS = os.environ.get('ZABBIX_PASS', '')
 DISCORD_WEBHOOK = os.environ.get('DISCORD_WEBHOOK', '')
-EMAIL_USER = os.environ.get('EMAIL_USER', 'lanfr144@gmail.com')
+EMAIL_USER = os.environ.get('EMAIL_USER', '')
 EMAIL_PASS = os.environ.get('EMAIL_PASS', '')
 
 def zabbix_request(method, params, auth=None):

BIN
delivery.zip


BIN
docs/Backup_Procedure.pdf


BIN
docs/Bts.png


BIN
docs/Data_Ingestion.pdf


BIN
docs/Final_Report.pdf


+ 45 - 0
docs/Header_Footer_Antigravity.md

@@ -0,0 +1,45 @@
+The current version is #ident "@(#)$Format:LocalFoodAI_lanfr144:Header_Footer_Antigravity.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+
+# PDF Header and Footer Generation Guidelines (Antigravity Standard)
+
+This document provides guidelines on how to programmatically inject institutional headers and footers into compiled PDF documents using Python and PyMuPDF (`fitz`). 
+
+## 1. Concept
+
+Instead of relying on fragile HTML/CSS page rendering contexts that vary across layout engines, the Antigravity approach compiles standard Markdown to a clean, margin-compliant intermediate PDF. We then perform a post-processing pass using PyMuPDF to draw vector logos, document title headers, and footer blocks on every page at absolute coordinates.
+
+## 2. Layout Structure
+
+The layout bounds on a standard A4 page (595 x 842 points) are mapped as follows:
+
+```mermaid
+graph TD
+    subgraph A4 Page Boundary [A4 Page Layout: 595 x 842 pt]
+        subgraph Top Margin Area [Top Margin: Y=0 to Y=54]
+            L_Logo["Left Logo: am.png<br/>X=48, Y=12<br/>(146.5 x 24.5 pt)"]
+            M_Title["Middle Title: Document Title<br/>X=Centered, Y=26"]
+            R_Logo["Right Logo: Bts.png<br/>X=479.9, Y=8<br/>(67.1 x 36.8 pt)"]
+        end
+        
+        subgraph Content Area [Main Document Context: Y=54 to Y=788]
+            Content["HTML/CSS Layout Story Flow"]
+        end
+        
+        subgraph Bottom Margin Area [Bottom Margin: Y=788 to Y=842]
+            L_Foot["Left Footer: lanfr144<br/>X=48, Y=820"]
+            M_Foot["Middle Footer: Page X of Y<br/>X=Centered, Y=820"]
+            R_Foot["Right Footer: DOPRO1<br/>X=width-48-width, Y=820"]
+        end
+    end
+```
+
+## 3. High-Quality Scaled Drawing
+
+To ensure maximum visual fidelity when zoomed, follow these steps:
+1. **Load PNGs as Pixmaps**: Read the image size using PyMuPDF `fitz.Pixmap`.
+2. **Compute 10% Bounds**: Scale the pixel width and height to 10% for layout dimensions in points.
+3. **Draw Bounds**: Insert the image using `page.insert_image(rect, filename)`. The full resolution is embedded in the PDF, keeping quality high when zoomed.
+4. **Optimized Saving**: Always save the PDF with deflate compression, garbage collection, and linearization:
+   ```python
+   doc.save(pdf_file, clean=True, garbage=3, deflate=True)
+   ```

BIN
docs/Header_Footer_Antigravity.pdf


+ 93 - 0
docs/Header_Footer_Gemini.md

@@ -0,0 +1,93 @@
+The current version is #ident "@(#)$Format:LocalFoodAI_lanfr144:Header_Footer_Gemini.md:%an:%ae:%ad:%cn:%ce:%cd:%H:%D:%N$"
+
+# PDF Header and Footer Generation Guidelines (Gemini Standard)
+
+This document describes how to implement standard headers and footers using the Gemini declarative styling approach. This model uses CSS Paged Media specifications to design page layouts directly during HTML-to-PDF compilation.
+
+## 1. Concept
+
+Unlike programmatic post-processing, the Gemini approach relies on standard CSS Page Margin Boxes defined within the `@page` context. The layout engine allocates page margin spaces and positions the logos, titles, and page numbers based on CSS property rules.
+
+## 2. Page Margin Box Layout Model
+
+The CSS Paged Media margin boxes are structured as follows around the main page area:
+
+```mermaid
+graph TD
+    subgraph Page Box [W3C Page Margin Box Grid]
+        subgraph Top Margin Boxes
+            TopLeft["@top-left Box<br/>(am.png Logo<br/>max-height: 24.5pt)"]
+            TopCenter["@top-center Box<br/>(Centered Document Title)"]
+            TopRight["@top-right Box<br/>(Bts.png Logo<br/>max-height: 36.8pt)"]
+        end
+        
+        subgraph Middle Box
+            MainPage["Page Content Area<br/>(Markdown Flowables)"]
+        end
+        
+        subgraph Bottom Margin Boxes
+            BottomLeft["@bottom-left Box<br/>(User ID: lanfr144)"]
+            BottomCenter["@bottom-center Box<br/>(Page X of Y)"]
+            BottomRight["@bottom-right Box<br/>(Project: DOPRO1)"]
+        end
+    end
+    
+    TopLeft -.-> MainPage
+    TopCenter -.-> MainPage
+    TopRight -.-> MainPage
+    MainPage -.-> BottomLeft
+    MainPage -.-> BottomCenter
+    MainPage -.-> BottomRight
+```
+
+## 3. CSS Declaration Example
+
+To implement the Gemini standard paged layout, include the following CSS rules inside the stylesheet used by the PDF engine:
+
+```css
+@page {
+    size: A4;
+    margin: 54pt 48pt 54pt 48pt;
+    
+    @top-left {
+        content: url("am.png");
+        image-resolution: 300dpi;
+        vertical-align: middle;
+    }
+    
+    @top-center {
+        content: "Document Title";
+        font-family: 'Helvetica', sans-serif;
+        font-size: 8pt;
+        color: #808080;
+        vertical-align: middle;
+    }
+    
+    @top-right {
+        content: url("Bts.png");
+        image-resolution: 300dpi;
+        vertical-align: middle;
+    }
+    
+    @bottom-left {
+        content: "lanfr144";
+        font-family: 'Helvetica', sans-serif;
+        font-size: 8pt;
+        color: #808080;
+    }
+    
+    @bottom-center {
+        content: "Page " counter(page) " of " counter(pages);
+        font-family: 'Helvetica', sans-serif;
+        font-size: 8pt;
+        color: #808080;
+    }
+    
+    @bottom-right {
+        content: "DOPRO1";
+        font-family: 'Helvetica', sans-serif;
+        font-size: 8pt;
+        color: #808080;
+    }
+}
+```

BIN
docs/Header_Footer_Gemini.pdf


BIN
docs/Installation_Guide.pdf


BIN
docs/Operator_Installation_Guide.pdf


BIN
docs/Recommendations.pdf


BIN
docs/Scrum_Artifacts.pdf


BIN
docs/Scrum_Daily.pdf


BIN
docs/Scrum_Plan.pdf


BIN
docs/Scrum_Retro.pdf


BIN
docs/Scrum_Review.pdf


BIN
docs/Scrum_Wiki.pdf


BIN
docs/Start_Stop_Procedures.pdf


BIN
docs/Technical_Document.pdf


BIN
docs/Test_Cases_Sprint8.pdf


BIN
docs/URL_Formats.pdf


BIN
docs/Uninstall_Guide.pdf


BIN
docs/User_Description.pdf


BIN
docs/User_Guide.pdf


BIN
docs/WSL_Deployment.pdf


BIN
docs/Wiki_Home.pdf


BIN
docs/am.png


BIN
docs/architecture.pdf


BIN
docs/disaster_recovery_plan.pdf


BIN
docs/distributed_deployment.pdf


BIN
docs/docker_connection.pdf


BIN
docs/project_report.pdf


BIN
docs/retro_planning.pdf


BIN
docs/taiga_audit_report.pdf


BIN
docs/zabbix_monitoring.pdf


+ 4 - 4
scratch/zabbix_airflow_monitor.py

@@ -7,10 +7,10 @@ from dotenv import load_dotenv
 load_dotenv()
 urllib3.disable_warnings()
 
-# Zabbix Server credentials
-ZABBIX_URL = 'http://192.168.130.170:8081/api_jsonrpc.php'
-ZABBIX_USER = 'Admin'
-ZABBIX_PASS = 'zabbix'
+# Zabbix Server credentials loaded from environment
+ZABBIX_URL = os.environ.get('ZABBIX_URL', '')
+ZABBIX_USER = os.environ.get('ZABBIX_USER', '')
+ZABBIX_PASS = os.environ.get('ZABBIX_PASS', '')
 
 def zabbix_rpc(method, params, auth=None):
     payload = {

+ 5 - 4
scripts/create_delivery_zip.py

@@ -56,9 +56,10 @@ MYSQL_ZABBIX_PASSWORD=your_mysql_zabbix_pass
 # ------------------------------------------
 # 3. ZABBIX & SNMP CREDENTIALS
 # ------------------------------------------
-ZABBIX_USER=Admin
+ZABBIX_URL=your_zabbix_url
+ZABBIX_USER=your_zabbix_user
 ZABBIX_PASS=your_zabbix_pass
-ZABBIX_SNMP_USER=zabbix_snmp
+ZABBIX_SNMP_USER=your_snmp_user
 ZABBIX_SNMP_AUTHKEY=your_snmp_authkey
 ZABBIX_SNMP_PRIVKEY=your_snmp_privkey
 DISCORD_WEBHOOK=your_discord_webhook
@@ -66,8 +67,8 @@ DISCORD_WEBHOOK=your_discord_webhook
 # ------------------------------------------
 # 4. EMAIL ALERTS CONFIGURATION
 # ------------------------------------------
-EMAIL_USER=your_email@gmail.com
-EMAIL_PASS=your_email_app_password
+EMAIL_USER=your_email_user
+EMAIL_PASS=your_email_pass
 
 # ------------------------------------------
 # 5. TAIGA PROJECT MANAGEMENT CREDENTIALS

+ 44 - 20
scripts/generate_pdfs.py

@@ -135,8 +135,8 @@ def main():
         md_content = re.sub(r'file:///.*?/docs/([a-zA-Z0-9_-]+)\.md', r'\1.pdf', md_content, flags=re.IGNORECASE)
         md_content = re.sub(r'file:///.*?/Food/([a-zA-Z0-9_.-]+)', r'../\1', md_content, flags=re.IGNORECASE)
         
-        # Add <br/> after code blocks to force copy-paste blank line
-        md_content = re.sub(r'(```[a-zA-Z0-9_-]*\n[\s\S]*?\n```)', r'\1\n<br/>', md_content)
+        # Add a blank line after code blocks to force copy-paste blank line
+        md_content = re.sub(r'(```[a-zA-Z0-9_-]*\n[\s\S]*?\n```)', r'\1\n\n', md_content)
         
         # Convert any relative markdown links in standard format [text](filename.md) or [text](./filename.md) to point to .pdf
         md_content = re.sub(r'\]\((?!http|https)([a-zA-Z0-9_./-]+)\.md(#[a-zA-Z0-9_-]+)?\)', r'](\1.pdf\2)', md_content, flags=re.IGNORECASE)
@@ -180,7 +180,27 @@ def main():
             else:
                 doc_title = os.path.basename(pdf_file).replace('.pdf', '').replace('_', ' ')
             
-            image_path = os.path.join(docs_dir, 'am.png')
+            am_path = os.path.join(docs_dir, 'am.png')
+            bts_path = os.path.join(docs_dir, 'Bts.png')
+            
+            # Read real sizes for scaling to 10%
+            width_am, height_am = 146.5, 24.5 # Fallback defaults
+            if os.path.exists(am_path):
+                try:
+                    pix_am = fitz.Pixmap(am_path)
+                    width_am = pix_am.width * 0.1
+                    height_am = pix_am.height * 0.1
+                except Exception:
+                    pass
+            
+            width_bts, height_bts = 67.1, 36.8 # Fallback defaults
+            if os.path.exists(bts_path):
+                try:
+                    pix_bts = fitz.Pixmap(bts_path)
+                    width_bts = pix_bts.width * 0.1
+                    height_bts = pix_bts.height * 0.1
+                except Exception:
+                    pass
             
             for page_idx in range(total_pages):
                 page = doc[page_idx]
@@ -188,39 +208,33 @@ def main():
                 height = page.rect.height
                 
                 # Header layout
-                # Left: am.png picture (if exists)
-                if os.path.exists(image_path):
-                    image_rect = fitz.Rect(48, 12, 48 + 16, 12 + 16)
-                    page.insert_image(image_rect, filename=image_path)
+                # Left: am.png picture (if exists) at 10% size
+                if os.path.exists(am_path):
+                    image_rect = fitz.Rect(48, 12, 48 + width_am, 12 + height_am)
+                    page.insert_image(image_rect, filename=am_path)
+                
+                # Right: Bts.png logo (if exists) at 10% size
+                if os.path.exists(bts_path):
+                    bts_rect = fitz.Rect(width - 48 - width_bts, 8, width - 48, 8 + height_bts)
+                    page.insert_image(bts_rect, filename=bts_path)
                 
                 # Middle: document title (centered)
-                # Right: "DOPRO1"
-                r_text = "DOPRO1"
                 fontsize = 8
                 fontname = "helv"
-                
                 m_width = fitz.get_text_length(doc_title, fontname=fontname, fontsize=fontsize)
-                r_width = fitz.get_text_length(r_text, fontname=fontname, fontsize=fontsize)
                 
                 page.insert_text(
-                    fitz.Point((width - m_width) / 2, 22),
+                    fitz.Point((width - m_width) / 2, 26),
                     doc_title,
                     fontname=fontname,
                     fontsize=fontsize,
                     color=(0.5, 0.5, 0.5)
                 )
                 
-                page.insert_text(
-                    fitz.Point(width - 48 - r_width, 22),
-                    r_text,
-                    fontname=fontname,
-                    fontsize=fontsize,
-                    color=(0.5, 0.5, 0.5)
-                )
-                
                 # Footer layout
                 # Left: "lanfr144"
                 # Middle: "Page X of Y"
+                # Right: "DOPRO1"
                 l_footer = "lanfr144"
                 footer_text = f"Page {page_idx + 1} of {total_pages}"
                 f_width = fitz.get_text_length(footer_text, fontname=fontname, fontsize=fontsize)
@@ -241,6 +255,16 @@ def main():
                     color=(0.5, 0.5, 0.5)
                 )
                 
+                r_footer = "DOPRO1"
+                r_footer_width = fitz.get_text_length(r_footer, fontname=fontname, fontsize=fontsize)
+                page.insert_text(
+                    fitz.Point(width - 48 - r_footer_width, height - 22),
+                    r_footer,
+                    fontname=fontname,
+                    fontsize=fontsize,
+                    color=(0.5, 0.5, 0.5)
+                )
+                
             # Deflate, clean, garbage collect and linearize the document
             # to fix Acrobat encoding and save prompts
             doc.save(pdf_file, clean=True, garbage=3, deflate=True)