166 lines
7.3 KiB
Python
166 lines
7.3 KiB
Python
import frappe
|
|
from reportlab.lib.pagesizes import letter
|
|
from reportlab.lib.units import inch
|
|
from reportlab.lib.colors import HexColor, black, white, grey
|
|
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable, Image
|
|
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
|
from reportlab.lib.enums import TA_CENTER, TA_LEFT, TA_JUSTIFY
|
|
from reportlab.lib import colors
|
|
import io
|
|
import os
|
|
|
|
DARK_BLUE = HexColor('#2F5496')
|
|
LIGHT_BLUE = HexColor('#D6E4F0')
|
|
GRAY = HexColor('#666666')
|
|
|
|
@frappe.whitelist()
|
|
def generate_cor(company_name=None, weights=None, received_date=None, red_r2=None, contact_name=None, contact_number=None, address_line=None, pallet_name=None):
|
|
"""Generate Certificate of Recycling PDF from form data."""
|
|
|
|
# Format date
|
|
date_str = ''
|
|
if received_date:
|
|
from frappe.utils import formatdate
|
|
date_str = formatdate(received_date, 'MMMM d, Y')
|
|
|
|
items_recycled = 'e-waste'
|
|
if red_r2:
|
|
items_recycled += ' (' + red_r2 + ')'
|
|
|
|
output = io.BytesIO()
|
|
doc = SimpleDocTemplate(
|
|
output,
|
|
pagesize=letter,
|
|
topMargin=0.5 * inch,
|
|
bottomMargin=0.5 * inch,
|
|
leftMargin=0.75 * inch,
|
|
rightMargin=0.75 * inch
|
|
)
|
|
|
|
styles = getSampleStyleSheet()
|
|
|
|
# Custom styles matching the Electron app
|
|
date_style = ParagraphStyle('DateBlock', parent=styles['Normal'], fontSize=14, fontName='Times-Bold', alignment=TA_LEFT)
|
|
title_style = ParagraphStyle('CertTitle', parent=styles['Title'], fontSize=16, fontName='Times-Bold', textColor=black, spaceAfter=6, alignment=TA_CENTER, letterSpacing=0.05)
|
|
cert_style = ParagraphStyle('CertBody', parent=styles['Normal'], fontName='Times-Roman', fontSize=12, spaceAfter=12, alignment=TA_JUSTIFY)
|
|
body_style = ParagraphStyle('BodyText2', parent=styles['Normal'], fontName='Times-Roman', fontSize=12, spaceAfter=10, alignment=TA_JUSTIFY)
|
|
bullet_style = ParagraphStyle('BulletText', parent=styles['Normal'], fontName='Times-Roman', fontSize=10, spaceAfter=4, leftIndent=24, bulletIndent=12, alignment=TA_JUSTIFY)
|
|
optin_style = ParagraphStyle('OptIn', parent=styles['Normal'], fontName='Times-Roman', fontSize=12, spaceAfter=10, alignment=TA_JUSTIFY)
|
|
sig_style = ParagraphStyle('Signature', parent=styles['Normal'], fontName='Times-Bold', fontSize=18, spaceBefore=18)
|
|
footer_style = ParagraphStyle('Footer', parent=styles['Normal'], fontName='Times-Roman', fontSize=10, textColor=GRAY)
|
|
|
|
elements = []
|
|
|
|
# Header row: Date | Logo | Title
|
|
logo_path = os.path.join(frappe.get_app_path('westech_r2'), 'public', 'images', 'cor_logo.png')
|
|
logo_img = None
|
|
if os.path.exists(logo_path):
|
|
logo_img = Image(logo_path, width=2.45 * inch, height=0.8 * inch)
|
|
|
|
header_data = [
|
|
[Paragraph(date_str, date_style), logo_img or Paragraph('', styles['Normal']), Paragraph('CERTIFICATE OF RECYCLING', title_style)]
|
|
]
|
|
header_table = Table(header_data, colWidths=[1.8 * inch, 2.45 * inch, 2.75 * inch])
|
|
header_table.setStyle(TableStyle([
|
|
('VALIGN', (0, 0), (-1, -1), 'MIDDLE'),
|
|
('ALIGN', (0, 0), (0, 0), 'LEFT'),
|
|
('ALIGN', (1, 0), (1, 0), 'CENTER'),
|
|
('ALIGN', (2, 0), (2, 0), 'CENTER'),
|
|
]))
|
|
elements.append(header_table)
|
|
elements.append(Spacer(1, 18))
|
|
|
|
# Certification paragraph
|
|
elements.append(Paragraph(
|
|
'Full Circle Electronics AZ, LLC (dba Westech Recyclers) certifies that the '
|
|
'materials submitted for recycling are received and will be properly recycled '
|
|
'in accordance with all state and federal recycling regulations and in '
|
|
'accordance with the R2 Standard.',
|
|
cert_style
|
|
))
|
|
|
|
# Data table
|
|
data_rows = [
|
|
['Company:', company_name or 'N/A'],
|
|
['Weight:', weights or 'N/A'],
|
|
['Items Recycled:', items_recycled],
|
|
]
|
|
if contact_name:
|
|
data_rows.append(['Contact:', contact_name])
|
|
if contact_number:
|
|
data_rows.append(['Phone:', contact_number])
|
|
if address_line:
|
|
data_rows.append(['Address:', address_line])
|
|
|
|
data_table = Table(data_rows, colWidths=[3.36 * inch, 3.64 * inch])
|
|
data_table.setStyle(TableStyle([
|
|
('FONTNAME', (0, 0), (-1, -1), 'Times-Roman'),
|
|
('FONTSIZE', (0, 0), (-1, -1), 12),
|
|
('ALIGN', (0, 0), (0, -1), 'RIGHT'),
|
|
('ALIGN', (1, 0), (1, -1), 'LEFT'),
|
|
('VALIGN', (0, 0), (-1, -1), 'TOP'),
|
|
('GRID', (0, 0), (-1, -1), 0.5, HexColor('#bfbfbf')),
|
|
('TOPPADDING', (0, 0), (-1, -1), 4),
|
|
('BOTTOMPADDING', (0, 0), (-1, -1), 4),
|
|
('LEFTPADDING', (0, 0), (-1, -1), 6),
|
|
('RIGHTPADDING', (0, 0), (-1, -1), 6),
|
|
]))
|
|
elements.append(data_table)
|
|
elements.append(Spacer(1, 12))
|
|
|
|
# Body paragraphs
|
|
elements.append(Paragraph(
|
|
'Full Circle Electronics AZ, LLC further acknowledges the acceptance and '
|
|
'recycling of any material potentially containing data. Data containing '
|
|
'materials are stored in our secured facility ensuring the security of the '
|
|
'unit(s) prior to data sanitization.',
|
|
body_style
|
|
))
|
|
|
|
elements.append(Paragraph(
|
|
'Data containing materials are sanitized in compliance with NIST 800-88 '
|
|
'guidelines which is set forth by the U.S. government for a robust methodology '
|
|
'for erasing data from storage media. Depending upon the media received, the '
|
|
'data destruction methods used are as follows:',
|
|
body_style
|
|
))
|
|
|
|
# Bullet list
|
|
bullets = [
|
|
'Hard disk and solid-state drives will either be logically sanitized using professional software or physically destroyed via shredding or degaussing.',
|
|
'Media cards and small storage devices will either be degaussed / shredded at our facility or sent straight to a smelter.',
|
|
'Data tapes or reels will either be degaussed or shredded at a vetted and approved downstream service provider.',
|
|
'Electronics with embedded storage chips will either be destroyed by physical destruction at our facility or at a vetted and approved downstream service provider.',
|
|
'Small electronics containing data will either be logically sanitized using the manufacturer\'s application for destroying data or sent to a vetted and approved downstream service provider.',
|
|
]
|
|
for b in bullets:
|
|
elements.append(Paragraph('\u2022 ' + b, bullet_style))
|
|
|
|
elements.append(Spacer(1, 6))
|
|
|
|
# Opt-in
|
|
elements.append(Paragraph(
|
|
'Opt-in option. If you desire to be informed of our data destruction process '
|
|
'changes or be notified of any unlikely security breaches, please let us know.',
|
|
optin_style
|
|
))
|
|
|
|
# Signature
|
|
elements.append(Paragraph('Westech Recyclers', sig_style))
|
|
|
|
# Footer
|
|
elements.append(Spacer(1, 10))
|
|
elements.append(Paragraph(
|
|
'220 S 9th St Phoenix, AZ 85034 '
|
|
'<link href="http://www.westechrecyclers.com" color="#1155cc">www.westechrecyclers.com</link> '
|
|
'602.256.7626',
|
|
footer_style
|
|
))
|
|
|
|
doc.build(elements)
|
|
output.seek(0)
|
|
|
|
frappe.response.filename = 'COR_' + (company_name or 'document').replace(' ', '_') + '.pdf'
|
|
frappe.response.filecontent = output.getvalue()
|
|
frappe.response.type = 'download'
|
|
frappe.response.display_content_as = 'attachment' |