245 lines
9.1 KiB
Python
245 lines
9.1 KiB
Python
import json
|
|
import datetime
|
|
from reportlab.lib.pagesizes import letter
|
|
from reportlab.lib import colors
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, PageBreak, Image
|
|
from reportlab.platypus import Frame, PageTemplate, NextPageTemplate
|
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
|
from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY, TA_LEFT, TA_RIGHT
|
|
from reportlab.lib.units import inch, cm
|
|
from reportlab.pdfgen import canvas
|
|
|
|
def header_footer(canvas, doc):
|
|
"""Add the header and footer to each page"""
|
|
canvas.saveState()
|
|
|
|
# Header
|
|
header_text = "Standard Operating Procedures"
|
|
canvas.setFont('Helvetica-Bold', 10)
|
|
canvas.drawString(72, letter[1] - 40, header_text)
|
|
|
|
# Add a line below the header
|
|
canvas.setStrokeColor(colors.lightgrey)
|
|
canvas.line(72, letter[1] - 50, letter[0] - 72, letter[1] - 50)
|
|
|
|
# Footer with page number and date
|
|
current_date = datetime.datetime.now().strftime("%B %d, %Y")
|
|
page_num = f"Page {doc.page} | {current_date}"
|
|
canvas.setFont('Helvetica', 8)
|
|
canvas.drawString(letter[0] - 150, 40, page_num)
|
|
|
|
# Add a line above the footer
|
|
canvas.line(72, 50, letter[0] - 72, 50)
|
|
|
|
canvas.restoreState()
|
|
|
|
def convert_sop_to_pdf(sop_data, output_pdf="sop_document.pdf", company_name="Company Name"):
|
|
"""
|
|
Convert SOP data to a well-formatted PDF document
|
|
|
|
Args:
|
|
sop_data (dict or str): SOP data in dictionary format or JSON string
|
|
output_pdf (str): Output PDF filename
|
|
company_name (str): Name of the company to display on the cover page
|
|
"""
|
|
# Parse JSON string if needed
|
|
if isinstance(sop_data, str):
|
|
sop_data = json.loads(sop_data)
|
|
|
|
# Extract SOP details
|
|
sop_details = sop_data.get("sop_details", [])
|
|
|
|
# Create PDF document
|
|
doc = SimpleDocTemplate(output_pdf, pagesize=letter,
|
|
rightMargin=72, leftMargin=72,
|
|
topMargin=90, bottomMargin=72)
|
|
|
|
# Container for PDF elements
|
|
elements = []
|
|
|
|
# Get styles
|
|
styles = getSampleStyleSheet()
|
|
|
|
# Define custom styles
|
|
title_style = ParagraphStyle(
|
|
'TitleStyle',
|
|
parent=styles['Heading1'],
|
|
fontSize=24,
|
|
alignment=TA_CENTER,
|
|
spaceAfter=12,
|
|
fontName='Helvetica-Bold',
|
|
textColor=colors.darkblue
|
|
)
|
|
|
|
subtitle_style = ParagraphStyle(
|
|
'SubtitleStyle',
|
|
parent=styles['Heading2'],
|
|
fontSize=16,
|
|
alignment=TA_CENTER,
|
|
spaceAfter=36,
|
|
fontName='Helvetica-Bold',
|
|
textColor=colors.darkblue
|
|
)
|
|
|
|
heading2_style = ParagraphStyle(
|
|
'Heading2Style',
|
|
parent=styles['Heading2'],
|
|
fontSize=16,
|
|
spaceBefore=12,
|
|
spaceAfter=6,
|
|
fontName='Helvetica-Bold',
|
|
textColor=colors.darkblue,
|
|
borderWidth=0,
|
|
borderColor=colors.lightgrey,
|
|
borderPadding=5,
|
|
borderRadius=5
|
|
)
|
|
|
|
heading3_style = ParagraphStyle(
|
|
'Heading3Style',
|
|
parent=styles['Heading3'],
|
|
fontSize=12,
|
|
spaceBefore=6,
|
|
spaceAfter=3,
|
|
fontName='Helvetica-Bold',
|
|
textColor=colors.darkslategray
|
|
)
|
|
|
|
normal_style = ParagraphStyle(
|
|
'NormalStyle',
|
|
parent=styles['Normal'],
|
|
fontSize=10,
|
|
alignment=TA_JUSTIFY,
|
|
leading=14,
|
|
fontName='Helvetica'
|
|
)
|
|
|
|
bullet_style = ParagraphStyle(
|
|
'BulletStyle',
|
|
parent=normal_style,
|
|
leftIndent=20,
|
|
firstLineIndent=-15,
|
|
spaceBefore=2,
|
|
spaceAfter=2
|
|
)
|
|
|
|
# Create cover page
|
|
elements.append(Spacer(1, 2*inch))
|
|
elements.append(Paragraph("Standard Operating Procedures", title_style))
|
|
elements.append(Spacer(1, 0.5*inch))
|
|
#elements.append(Paragraph(company_name, subtitle_style))
|
|
elements.append(Spacer(1, 2*inch))
|
|
|
|
# Add current date
|
|
current_date = datetime.datetime.now().strftime("%B %d, %Y")
|
|
date_style = ParagraphStyle(
|
|
'DateStyle',
|
|
parent=styles['Normal'],
|
|
fontSize=12,
|
|
alignment=TA_CENTER,
|
|
fontName='Helvetica'
|
|
)
|
|
elements.append(Paragraph(f"Generated on: {current_date}", date_style))
|
|
|
|
# Add a page break after the cover page
|
|
elements.append(PageBreak())
|
|
|
|
|
|
# Process each role
|
|
for role_data in sop_details:
|
|
role_name = role_data.get("role", "Unnamed Role")
|
|
sops = role_data.get("sops", {})
|
|
narrative = role_data.get("narrative")
|
|
|
|
# Add role header with decorative element
|
|
elements.append(Paragraph(role_name, heading2_style))
|
|
|
|
# Add horizontal rule after heading
|
|
elements.append(Spacer(1, 0.05*inch))
|
|
|
|
# Add narrative if available
|
|
if narrative and narrative != "Narrative" and narrative is not None:
|
|
elements.append(Paragraph("Narrative:", heading3_style))
|
|
elements.append(Paragraph(narrative, normal_style))
|
|
elements.append(Spacer(1, 0.2*inch))
|
|
|
|
# Process SOPs
|
|
for sop_type in ["must", "shall", "will"]:
|
|
sop_items = sops.get(sop_type, [])
|
|
|
|
if sop_items:
|
|
# Capitalize the first letter of SOP type and make it bold
|
|
sop_type_title = sop_type.capitalize()
|
|
elements.append(Paragraph(f"{sop_type_title}:", heading3_style))
|
|
|
|
# Create bullet points for each SOP item with better formatting
|
|
for item in sop_items:
|
|
elements.append(Paragraph(f"• {item}", bullet_style))
|
|
|
|
elements.append(Spacer(1, 0.15*inch))
|
|
|
|
# Add a page break between roles for cleaner separation
|
|
elements.append(PageBreak())
|
|
|
|
# Build the PDF document with header and footer
|
|
doc.build(elements, onFirstPage=header_footer, onLaterPages=header_footer)
|
|
|
|
return output_pdf
|
|
|
|
def main():
|
|
# Example usage
|
|
sop_json = """
|
|
{
|
|
"sop_details": [
|
|
{
|
|
"role": "Sales Manager",
|
|
"role_id": 140,
|
|
"sops": {
|
|
"must": [],
|
|
"shall": [
|
|
"Shall develop and implement sales strategies to achieve company targets.",
|
|
"Shall conduct regular performance reviews with the sales team to ensure targets are met.",
|
|
"Shall provide training and support to sales staff to enhance their skills and performance.",
|
|
"Shall analyze market trends and adjust sales strategies accordingly.",
|
|
"Shall maintain accurate records of sales activities and customer interactions."
|
|
],
|
|
"will": [
|
|
"Will lead the sales team to achieve monthly and quarterly sales goals.",
|
|
"Will collaborate with marketing to align sales strategies with promotional campaigns.",
|
|
"Will report sales performance to upper management on a regular basis.",
|
|
"Will identify potential new markets and customer segments for growth.",
|
|
"Will foster a positive team environment to motivate sales staff."
|
|
]
|
|
},
|
|
"areas": [],
|
|
"narrative": "The Sales Manager is responsible for leading and developing the sales team to achieve business targets and growth objectives. They will implement effective sales strategies, provide coaching to team members, and maintain strong customer relationships while ensuring all sales activities align with the company's overall goals."
|
|
},
|
|
{
|
|
"role": "Campaign Manager",
|
|
"role_id": 141,
|
|
"sops": {
|
|
"must": [],
|
|
"shall": [],
|
|
"will": [
|
|
"Will develop and execute marketing campaigns to promote products and services.",
|
|
"Will analyze campaign performance metrics to optimize future campaigns.",
|
|
"Will collaborate with cross-functional teams to ensure campaign alignment with business objectives.",
|
|
"Will manage campaign budgets and ensure effective allocation of resources.",
|
|
"Will stay updated on industry trends to inform campaign strategies."
|
|
]
|
|
},
|
|
"areas": [],
|
|
"narrative": "The Campaign Manager oversees the planning, execution, and analysis of marketing campaigns across various channels to drive brand awareness and customer acquisition. They work closely with creative teams, external vendors, and stakeholders to ensure campaigns are effective, on-brand, and deliver measurable results."
|
|
}
|
|
]
|
|
}
|
|
"""
|
|
|
|
# You can replace the company name with your own
|
|
output_file = convert_sop_to_pdf(sop_json, company_name="Strategic Business Solutions, Inc.")
|
|
print(f"PDF successfully generated: {output_file}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|