Business Membership & Networking Cost Tracker

General Settings

Manage Categories

No categories added. E.g., Industry Body, Local Chamber, Conference.

Manage Internal Association (Optional)

No internal associations added. E.g., Sales Dept, CEO Office.

Memberships & Recurring Subscriptions

No memberships or subscriptions added yet.

Networking Events & One-Time Costs

No networking events added yet.

Cost Summary

Enter data in previous tabs to see the summary.

Total Annual Recurring: ${currency}${totalAnnualRecurring.toFixed(2)}

Total For Entered Events: ${currency}${totalEventCosts.toFixed(2)}

Overall Total (Annual Recurring + Events): ${currency}${(totalAnnualRecurring + totalEventCosts).toFixed(2)}


`; html += '

Memberships & Recurring Subscriptions

'; html += ''; if (memberships.length === 0) html += ''; memberships.forEach(m => { html += ``; }); html += '
NameCycle CostCategoryAssoc.MonthlyAnnual
No recurring items.
${m.name}${m.tier ? ' ('+m.tier+')':''}${currency}${m.cycleCost.toFixed(2)} (${m.billingCycle})${m.category||'-'}${m.association||'-'}${currency}${m.monthlyCost.toFixed(2)}${currency}${m.annualCost.toFixed(2)}
'; html += '

Networking Events & One-Time Costs

'; html += ''; if (events.length === 0) html += ''; events.forEach(e => { html += ``; }); html += '
Event NameDate(s)CategoryAssoc.Total Cost
No event items.
${e.name}${e.organizer ? ' ('+e.organizer+')':''}${e.date||'-'}${e.category||'-'}${e.association||'-'}${currency}${e.totalCost.toFixed(2)}
'; const grandTotalForBreakdown = totalAnnualRecurring + totalEventCosts; html += '

Cost Breakdown by Category (Annual Recurring + Events)

'; if (Object.keys(costsByCategory).length > 0) { html += '
'; Object.entries(costsByCategory).sort(([,a],[,b]) => b-a).forEach(([cat, cost]) => { const percentage = grandTotalForBreakdown > 0 ? (cost / grandTotalForBreakdown * 100) : 0; html += `
${cat}
${currency}${cost.toFixed(2)}
`; }); html += '
'; } else { html += '

No costs assigned to categories.

'; } html += '

Cost Breakdown by Internal Association (Annual Recurring + Events)

'; if (Object.keys(costsByAssociation).length > 0) { html += '
'; Object.entries(costsByAssociation).sort(([,a],[,b]) => b-a).forEach(([assoc, cost]) => { const percentage = grandTotalForBreakdown > 0 ? (cost / grandTotalForBreakdown * 100) : 0; html += `
${assoc}
${currency}${cost.toFixed(2)}
`; }); html += '
'; } else { html += '

No costs assigned to internal depts/employees.

'; } summaryOutput.innerHTML = html; downloadPdfButton.disabled = memberships.length === 0 && events.length === 0; } // PDF Download downloadPdfButton.addEventListener('click', function () { if (typeof jspdf === 'undefined' || typeof jspdf.jsPDF === 'undefined') { alert('Error: jsPDF library is not loaded.'); return; } const { jsPDF } = jspdf; const doc = new jsPDF('p'); const currency = currencySymbolInput.value || '$'; const reportingPeriod = document.getElementById('bmnc-reporting-period').value; const primaryColor = getComputedStyle(document.documentElement).getPropertyValue('--bmnc-primary-color').trim(); const secondaryColor = getComputedStyle(document.documentElement).getPropertyValue('--bmnc-secondary-color').trim(); const textColor = getComputedStyle(document.documentElement).getPropertyValue('--bmnc-text-color').trim(); const buttonTextColor = getComputedStyle(document.documentElement).getPropertyValue('--bmnc-button-text-color').trim(); doc.setFontSize(18); doc.setTextColor(primaryColor); doc.text('Membership & Networking Cost Summary', doc.internal.pageSize.getWidth() / 2, 20, { align: 'center' }); doc.setFontSize(12); doc.setTextColor(textColor); let lastY = 30; doc.text(`Business Name: ${document.getElementById('bmnc-business-name').value || 'N/A'}`, 14, lastY); lastY += 7; doc.text(`Currency: ${currency}`, 14, lastY); lastY += 7; doc.text(`Reporting View: ${reportingPeriod}`, 14, lastY); lastY += 10; let totalMonthlyRecurringPdf = 0; let totalAnnualRecurringPdf = 0; const costsByCategoryPdf = {}; const costsByAssociationPdf = {}; const membershipsPdfData = []; const eventsPdfData = []; let totalEventCostsPdf = 0; // Collect Membership Data for PDF document.querySelectorAll('.bmnc-membership-item').forEach(item => { const name = item.querySelector('.bmnc-ms-name').value || 'N/A'; const cycleCost = getNum(item.querySelector('.bmnc-ms-cost')); const billingCycle = item.querySelector('.bmnc-ms-cycle').value; const annualCost = calculateAnnualizedCost(cycleCost, billingCycle); totalAnnualRecurringPdf += annualCost; totalMonthlyRecurringPdf += annualCost / 12; const category = item.querySelector('.bmnc-item-category').value; const association = item.querySelector('.bmnc-item-association').value; if(category) costsByCategoryPdf[category] = (costsByCategoryPdf[category] || 0) + annualCost; if(association) costsByAssociationPdf[association] = (costsByAssociationPdf[association] || 0) + annualCost; membershipsPdfData.push([ name, item.querySelector('.bmnc-ms-tier').value || '-', `${currency}${cycleCost.toFixed(2)} (${billingCycle})`, category || '-', association || '-', `${currency}${(annualCost/12).toFixed(2)}`, `${currency}${annualCost.toFixed(2)}` ]); }); // Collect Event Data for PDF document.querySelectorAll('.bmnc-event-item').forEach(item => { const name = item.querySelector('.bmnc-ev-name').value || 'N/A'; const regFee = getNum(item.querySelector('.bmnc-ev-regfee')); const attendees = getNum(item.querySelector('.bmnc-ev-attendees')); const sponsorship = getNum(item.querySelector('.bmnc-ev-sponsorship')); const travel = getNum(item.querySelector('.bmnc-ev-travel')); const other = getNum(item.querySelector('.bmnc-ev-other')); const totalEventCost = (regFee * attendees) + sponsorship + travel + other; totalEventCostsPdf += totalEventCost; const category = item.querySelector('.bmnc-item-category').value; const association = item.querySelector('.bmnc-item-association').value; if(category) costsByCategoryPdf[category] = (costsByCategoryPdf[category] || 0) + totalEventCost; if(association) costsByAssociationPdf[association] = (costsByAssociationPdf[association] || 0) + totalEventCost; eventsPdfData.push([ name, item.querySelector('.bmnc-ev-date').value || '-', category || '-', association || '-', `${currency}${totalEventCost.toFixed(2)}` ]); }); doc.setFontSize(10); doc.text(`Total Monthly Recurring: ${currency}${totalMonthlyRecurringPdf.toFixed(2)}`, 14, lastY); lastY += 7; doc.text(`Total Annual Recurring: ${currency}${totalAnnualRecurringPdf.toFixed(2)}`, 14, lastY); lastY += 7; doc.text(`Total For Entered Events: ${currency}${totalEventCostsPdf.toFixed(2)}`, 14, lastY); lastY += 7; doc.text(`Overall Total (Annual Recurring + Events): ${currency}${(totalAnnualRecurringPdf + totalEventCostsPdf).toFixed(2)}`, 14, lastY); lastY += 10; if (membershipsPdfData.length > 0) { doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text('Memberships & Recurring Subscriptions:', 14, lastY); lastY += 7; doc.autoTable({ startY: lastY, theme: 'grid', head: [['Name', 'Tier', 'Cycle Cost', 'Category', 'Assoc.', 'Monthly', 'Annual']], body: membershipsPdfData, headStyles: { fillColor: secondaryColor, textColor: buttonTextColor, fontSize: 8 }, styles: { fontSize: 7, cellPadding: 1.5 }, columnStyles: { 2:{halign:'right'}, 5:{halign:'right'}, 6:{halign:'right'} } }); lastY = doc.lastAutoTable.finalY + 10; } if (eventsPdfData.length > 0) { if (lastY > 260) { doc.addPage(); lastY = 20; } doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text('Networking Events & One-Time Costs:', 14, lastY); lastY += 7; doc.autoTable({ startY: lastY, theme: 'grid', head: [['Event Name', 'Date(s)', 'Category', 'Assoc.', 'Total Cost']], body: eventsPdfData, headStyles: { fillColor: secondaryColor, textColor: buttonTextColor, fontSize: 8 }, styles: { fontSize: 7, cellPadding: 1.5 }, columnStyles: { 4:{halign:'right'} } }); lastY = doc.lastAutoTable.finalY + 10; } const grandTotalForBreakdownPdf = totalAnnualRecurringPdf + totalEventCostsPdf; if (Object.keys(costsByCategoryPdf).length > 0) { if (lastY > 250) { doc.addPage(); lastY = 20; } doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text('Cost Breakdown by Category (Annual Recurring + Events):', 14, lastY); lastY += 7; const catBody = []; Object.entries(costsByCategoryPdf).sort(([,a],[,b]) => b-a).forEach(([cat, cost]) => { catBody.push([cat, `${currency}${cost.toFixed(2)}`, `${grandTotalForBreakdownPdf > 0 ? (cost / grandTotalForBreakdownPdf * 100).toFixed(1) : '0.0'}%`]); }); doc.autoTable({ startY: lastY, head: [['Category', 'Total Cost', '% of Total']], body: catBody, headStyles: {fillColor: secondaryColor, textColor:buttonTextColor, fontSize:9}, styles:{fontSize:8, cellPadding:1.5}, columnStyles:{1:{halign:'right'}, 2:{halign:'right'}}}); lastY = doc.lastAutoTable.finalY + 10; } if (Object.keys(costsByAssociationPdf).length > 0) { if (lastY > 250) { doc.addPage(); lastY = 20; } doc.setFontSize(12); doc.setTextColor(primaryColor); doc.text('Cost Breakdown by Internal Association (Annual Recurring + Events):', 14, lastY); lastY += 7; const assocBody = []; Object.entries(costsByAssociationPdf).sort(([,a],[,b]) => b-a).forEach(([assoc, cost]) => { assocBody.push([assoc, `${currency}${cost.toFixed(2)}`, `${grandTotalForBreakdownPdf > 0 ? (cost / grandTotalForBreakdownPdf * 100).toFixed(1) : '0.0'}%`]); }); doc.autoTable({ startY: lastY, head: [['Department/Employee', 'Total Cost', '% of Total']], body: assocBody, headStyles: {fillColor: secondaryColor, textColor:buttonTextColor, fontSize:9}, styles:{fontSize:8, cellPadding:1.5}, columnStyles:{1:{halign:'right'}, 2:{halign:'right'}}}); } doc.save(`Membership_Networking_Costs_${document.getElementById('bmnc-business-name').value.replace(/\s+/g, '_') || 'Report'}.pdf`); }); // Initial setup checkEmptyState('#bmnc-categories-container'); checkEmptyState('#bmnc-associations-container'); checkEmptyState('#bmnc-memberships-list-container'); checkEmptyState('#bmnc-events-list-container'); showTab(0); updateAllCurrencyPrefixes(); });
Scroll to Top