diff --git a/westech_r2/__pycache__/hooks.cpython-312.pyc b/westech_r2/__pycache__/hooks.cpython-312.pyc index 1438909..9a036e6 100644 Binary files a/westech_r2/__pycache__/hooks.cpython-312.pyc and b/westech_r2/__pycache__/hooks.cpython-312.pyc differ diff --git a/westech_r2/api/cor_generator.py b/westech_r2/api/cor_generator.py new file mode 100644 index 0000000..e61443a --- /dev/null +++ b/westech_r2/api/cor_generator.py @@ -0,0 +1,98 @@ +import frappe +from reportlab.lib.pagesizes import letter +from reportlab.lib.units import inch +from reportlab.lib.colors import HexColor +from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, Table, TableStyle, HRFlowable +from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle +from reportlab.lib.enums import TA_CENTER +from reportlab.lib import colors +import sqlite3 +import io + +DB_PATH = '/opt/eim/eim.db' +DARK_BLUE = HexColor('#2F5496') +LIGHT_BLUE = HexColor('#D6E4F0') +GRAY = HexColor('#666666') + +def get_device_counts(pallet_number): + conn = sqlite3.connect(DB_PATH) + conn.row_factory = sqlite3.Row + cur = conn.cursor() + cur.execute('SELECT device_type, COUNT(*) as count FROM devices WHERE pallet_number = ? GROUP BY device_type', (pallet_number,)) + counts = {row['device_type']: row['count'] for row in cur.fetchall()} + conn.close() + return counts + +@frappe.whitelist() +def generate_cor(pallet_number): + pallet = frappe.get_doc('Pallet', pallet_number) + device_counts = get_device_counts(pallet_number) + + output = io.BytesIO() + doc = SimpleDocTemplate(output, pagesize=letter, topMargin=0.75*inch, bottomMargin=0.75*inch, leftMargin=0.75*inch, rightMargin=0.75*inch) + styles = getSampleStyleSheet() + + title_style = ParagraphStyle('CertTitle', parent=styles['Title'], fontSize=20, textColor=DARK_BLUE, spaceAfter=6, alignment=TA_CENTER) + body_style = ParagraphStyle('CertBody', parent=styles['Normal'], fontSize=11, spaceAfter=4) + section_style = ParagraphStyle('SectionHeader', parent=styles['Heading2'], fontSize=14, textColor=DARK_BLUE, spaceBefore=12, spaceAfter=6) + + elements = [] + elements.append(Paragraph('CERTIFICATE OF RECYCLING', title_style)) + elements.append(Spacer(1, 6)) + + intro = '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.' + elements.append(Paragraph(intro, body_style)) + elements.append(Spacer(1, 8)) + elements.append(Paragraph('Materials Submitted by:', section_style)) + + pallet_data = [ + ['Company:', pallet.company_name or pallet.customer_number or 'N/A'], + ['Pallet Number:', pallet.pallet_number or pallet_number], + ['Date Received:', str(pallet.received_date or 'N/A')], + ['Weight:', str(pallet.inbound_weight or 'N/A') + ' lbs'], + ['Technician:', pallet.tester or 'N/A'], + ] + + pallet_table = Table(pallet_data, colWidths=[1.5*inch, 4*inch]) + pallet_table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (0, -1), LIGHT_BLUE), + ('TEXTCOLOR', (0, 0), (0, -1), DARK_BLUE), + ('FONTNAME', (0, 0), (0, -1), 'Helvetica-Bold'), + ('FONTSIZE', (0, 0), (-1, -1), 10), + ('ALIGN', (0, 0), (0, -1), 'RIGHT'), + ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), + ('TOPPADDING', (0, 0), (-1, -1), 4), + ('BOTTOMPADDING', (0, 0), (-1, -1), 4), + ])) + elements.append(pallet_table) + elements.append(Spacer(1, 12)) + + if device_counts: + elements.append(Paragraph('Device Summary:', section_style)) + device_data = [['Device Type', 'Count']] + for dtype, count in sorted(device_counts.items()): + device_data.append([dtype or 'Unknown', str(count)]) + device_table = Table(device_data, colWidths=[3*inch, 2*inch]) + device_table.setStyle(TableStyle([ + ('BACKGROUND', (0, 0), (-1, 0), DARK_BLUE), + ('TEXTCOLOR', (0, 0), (-1, 0), colors.white), + ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'), + ('GRID', (0, 0), (-1, -1), 0.5, colors.grey), + ('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, HexColor('#F2F2F2')]), + ])) + elements.append(device_table) + elements.append(Spacer(1, 12)) + + elements.append(HRFlowable(width='100%', thickness=1, color=DARK_BLUE, spaceBefore=12)) + footer = Paragraph('Full Circle Electronics AZ, LLC | 220 S 9th St Phoenix, AZ 85034 | www.westechrecyclers.com | 602.256.7626', + ParagraphStyle('Footer', parent=styles['Normal'], fontSize=9, textColor=GRAY, alignment=TA_CENTER)) + elements.append(Spacer(1, 6)) + elements.append(footer) + + doc.build(elements) + output.seek(0) + + frappe.response.filename = 'COR_' + pallet_number + '.pdf' + frappe.response.filecontent = output.getvalue() + frappe.response.type = 'download' + frappe.response.display_content_as = 'attachment' diff --git a/westech_r2/doctype/pallet/pallet.js b/westech_r2/doctype/pallet/pallet.js index 98e1e19..4a7c269 100644 --- a/westech_r2/doctype/pallet/pallet.js +++ b/westech_r2/doctype/pallet/pallet.js @@ -11,6 +11,15 @@ frappe.ui.form.on('Pallet', { 'pallet': frm.doc.pallet_number || frm.doc.name }); }, __('View')); + + frm.add_custom_button(__('Generate COR'), function() { + if (!frm.doc.pallet_number) { + frappe.msgprint('Please save the Pallet first'); + return; + } + var url = '/api/method/westech_r2.api.cor_generator.generate_cor?pallet_number=' + encodeURIComponent(frm.doc.pallet_number); + window.open(url, '_blank'); + }, __('Actions')); }, customer_number: function(frm) { diff --git a/westech_r2/doctype/scheduled_pickup/scheduled_pickup.js b/westech_r2/doctype/scheduled_pickup/scheduled_pickup.js index a017ec3..ecfd2df 100644 --- a/westech_r2/doctype/scheduled_pickup/scheduled_pickup.js +++ b/westech_r2/doctype/scheduled_pickup/scheduled_pickup.js @@ -2,7 +2,7 @@ frappe.ui.form.on('Scheduled Pickup', { customer_number: function(frm) { var customer = frm.doc.customer_number; if (!customer) { - clear_supplier_fields(frm); + clear_customer_fields(frm); return; } frappe.call({ @@ -52,7 +52,7 @@ frappe.ui.form.on('Scheduled Pickup', { } }); -function clear_supplier_fields(frm) { +function clear_customer_fields(frm) { frm.set_value('company_name', ''); frm.set_value('contact_name', ''); frm.set_value('contact_phone', ''); diff --git a/westech_r2/hooks.py b/westech_r2/hooks.py index f47ccff..d47bed1 100644 --- a/westech_r2/hooks.py +++ b/westech_r2/hooks.py @@ -31,3 +31,6 @@ doc_events = { "before_save": "westech_r2.doctype.load.load.calculate_totals", }, } + + +app_include_css = "/assets/westech_r2/css/westech_theme.css" diff --git a/westech_r2/page/intake/intake.js b/westech_r2/page/intake/intake.js index 0242040..f7742a0 100644 --- a/westech_r2/page/intake/intake.js +++ b/westech_r2/page/intake/intake.js @@ -1,11 +1,12 @@ frappe.pages['intake'].on_page_load = function(wrapper) { + try { var page = frappe.ui.make_app_page({ parent: wrapper, - title: 'Intake Station', + title: 'Customer Management', single_column: true }); - page.set_primary_action('New Intake', function() { + page.set_primary_action('New Customer', function() { show_intake_form(); }, 'add'); @@ -18,13 +19,44 @@ frappe.pages['intake'].on_page_load = function(wrapper) {