// Tools Import/Export Wizard (function () { 'use strict'; // ── Anti-forgery token ──────────────────────────────────────────────────── const tokenInput = document.querySelector('input[name="__RequestVerificationToken"]'); if (!tokenInput) { console.error('[Tools] Anti-forgery token not found'); return; } const token = tokenInput.value; // ── Account select data (embedded by Razor as JSON) ─────────────────────── let accountData = { revenueAccounts: [], cogsAccounts: [], inventoryAccounts: [] }; try { const el = document.getElementById('toolsAccountData'); if (el) accountData = JSON.parse(el.textContent); } catch (e) { console.warn('[Tools] Could not parse account data'); } // ── Wizard state ────────────────────────────────────────────────────────── let wDir = null; // 'import' | 'export' let wFmt = null; // 'csv' | 'qb-desktop' | 'qb-online' let wItem = null; // selected item object let wStep = 1; // ── Item catalog ────────────────────────────────────────────────────────── const ITEMS = [ // ── CSV Import ────────────────────────────────────────────────────── { key: 'csv-customers', label: 'Customers', icon: 'bi-people', color: '#2563eb', desc: 'Contact info, addresses, and balances', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportCustomers', accept: '.csv', template: '/Tools/DownloadCustomerTemplate', tips: ['Download the CSV template to see the expected columns', 'One customer per row — existing records matched by company name are updated'] }, { key: 'csv-vendors', label: 'Vendors', icon: 'bi-truck', color: '#d97706', desc: 'Supplier records and contact info', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportVendors', accept: '.csv', template: '/Tools/DownloadVendorTemplate', tips: ['Download the CSV template to see the expected columns', 'One vendor per row — existing records matched by company name are updated'] }, { key: 'csv-catalog', label: 'Catalog Items', icon: 'bi-box-seam', color: '#059669', desc: 'Pre-priced service catalog entries', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportCatalogItems', accept: '.csv', template: '/Tools/DownloadCatalogTemplate', extraFields: [ { name: 'revenueAccountId', label: 'Revenue Account', hint: 'Optional', accountKey: 'revenueAccounts' }, { name: 'cogsAccountId', label: 'COGS Account', hint: 'Optional', accountKey: 'cogsAccounts' }, ], tips: ['Download the CSV template', 'Optionally map to GL accounts before uploading'] }, { key: 'csv-inventory', label: 'Inventory', icon: 'bi-boxes', color: '#0891b2', desc: 'Stock items, quantities, and unit costs', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportInventoryItems', accept: '.csv', template: '/Tools/DownloadInventoryTemplate', extraFields: [ { name: 'inventoryAccountId', label: 'Inventory Asset Account', hint: 'Optional', accountKey: 'inventoryAccounts' }, { name: 'cogsAccountId', label: 'COGS Account', hint: 'Optional', accountKey: 'cogsAccounts' }, ], tips: ['Download the CSV template', 'Optionally map to GL accounts before uploading'] }, { key: 'csv-quotes', label: 'Quotes', icon: 'bi-file-earmark-text', color: '#d97706', desc: 'Quote records with statuses and totals', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportQuotes', accept: '.csv', template: '/Tools/DownloadQuoteTemplate', tips: ['Download the CSV template', 'One quote per row'] }, { key: 'csv-jobs', label: 'Jobs', icon: 'bi-briefcase', color: '#059669', desc: 'Job records with statuses and priorities', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportJobs', accept: '.csv', template: '/Tools/DownloadJobTemplate', tips: ['Download the CSV template', 'One job per row'] }, { key: 'csv-appointments', label: 'Appointments', icon: 'bi-calendar-check', color: '#2563eb', desc: 'Scheduled customer appointments', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportAppointments', accept: '.csv', template: '/Tools/DownloadAppointmentTemplate', tips: ['Download the CSV template', 'One appointment per row'] }, { key: 'csv-equipment', label: 'Equipment', icon: 'bi-tools', color: '#dc2626', desc: 'Equipment records and status', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportEquipment', accept: '.csv', template: '/Tools/DownloadEquipmentTemplate', tips: ['Download the CSV template', 'One equipment item per row'] }, { key: 'csv-maintenance', label: 'Maintenance Records', icon: 'bi-wrench', color: '#6b7280', desc: 'Scheduled and completed maintenance', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportMaintenance', accept: '.csv', template: '/Tools/DownloadMaintenanceTemplate', tips: ['Download the CSV template', 'One maintenance record per row'] }, { key: 'csv-prepservices', label: 'Prep Services', icon: 'bi-hammer', color: '#7c3aed', desc: 'Sandblasting, masking, and prep options', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportPrepServices', accept: '.csv', template: '/Tools/DownloadPrepServiceTemplate', tips: ['Existing services matched by name are updated'] }, { key: 'csv-coa', label: 'Chart of Accounts', icon: 'bi-journal-text', color: '#374151', desc: 'GL accounts — import first (required for expenses and bills)', badge: 'Import first', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportChartOfAccounts', accept: '.csv', template: '/Tools/DownloadChartOfAccountsTemplate', tips: ['Download the CSV template to see required columns', 'Valid AccountType values: Asset, Liability, Equity, Revenue, CostOfGoods, Expense', 'Existing accounts matched by AccountNumber are updated; system accounts are never modified'] }, { key: 'csv-expenses', label: 'Expenses', icon: 'bi-receipt-cutoff', color: '#dc2626', desc: 'Direct expenses with account, vendor, and job links', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportExpenses', accept: '.csv', template: '/Tools/DownloadExpenseTemplate', tips: ['Download the CSV template to see required columns', 'ExpenseAccountNumber and PaymentAccountNumber must match account numbers in your Chart of Accounts', 'VendorName and JobNumber are optional — leave blank if not applicable', 'Valid PaymentMethod values: Cash, Check, CreditDebitCard, BankTransferACH, DigitalPayment'] }, { key: 'csv-settings', label: 'Company Settings', icon: 'bi-gear', color: '#d97706', desc: 'Operating costs and configuration', dir: ['import'], fmt: ['csv'], endpoint: '/Tools/CsvImportCompanySettings', accept: '.csv', template: '/Tools/DownloadCompanySettingsTemplate', warning: 'This will overwrite your current company settings. Download a backup first.', tips: ['Download a backup of your current settings first', 'Modify the CSV, then upload it below'] }, // ── CSV Export ────────────────────────────────────────────────────── { key: 'exp-customers', label: 'Customers', icon: 'bi-people', color: '#2563eb', desc: 'Contact info, addresses, and balances', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportCustomersCsv' }, { key: 'exp-vendors', label: 'Vendors', icon: 'bi-truck', color: '#d97706', desc: 'Supplier records, contact info, and payment terms', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportVendorsCsv' }, { key: 'exp-quotes', label: 'Quotes', icon: 'bi-file-earmark-text', color: '#0891b2', desc: 'Status, dates, totals, and customer info', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportQuotesCsv' }, { key: 'exp-jobs', label: 'Jobs', icon: 'bi-briefcase', color: '#059669', desc: 'Status, priority, dates, and completion data', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportJobsCsv' }, { key: 'exp-appointments', label: 'Appointments', icon: 'bi-calendar-check', color: '#d97706', desc: 'Customer, type, status, and scheduling details', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportAppointmentsCsv' }, { key: 'exp-catalog', label: 'Catalog Items', icon: 'bi-box-seam', color: '#6b7280', desc: 'SKU, pricing, categories, and descriptions', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportCatalogCsv' }, { key: 'exp-inventory', label: 'Inventory', icon: 'bi-boxes', color: '#1f2937', desc: 'Quantities, costs, and location details', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportInventoryCsv' }, { key: 'exp-equipment', label: 'Equipment', icon: 'bi-tools', color: '#dc2626', desc: 'Details, purchase info, and current status', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportEquipmentCsv' }, { key: 'exp-maintenance', label: 'Maintenance Records', icon: 'bi-wrench', color: '#6b7280', desc: 'Scheduled and completed maintenance with equipment and costs', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportMaintenanceCsv' }, { key: 'exp-prepservices', label: 'Prep Services', icon: 'bi-tools', color: '#7c3aed', desc: 'Preparation service catalog (sandblasting, stripping, etc.)', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportPrepServicesCsv' }, { key: 'exp-purchaseorders', label: 'Purchase Orders', icon: 'bi-cart', color: '#6b7280', desc: 'Vendor, status, dates, and totals', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportPurchaseOrdersCsv' }, { key: 'exp-coa', label: 'Chart of Accounts', icon: 'bi-journal-text', color: '#374151', desc: 'Full GL account list with types, balances, and account numbers', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportChartOfAccountsCsv' }, { key: 'exp-expenses', label: 'Expenses', icon: 'bi-receipt-cutoff', color: '#dc2626', desc: 'Direct expenses with dates, accounts, vendors, and amounts', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportExpensesCsv' }, { key: 'exp-settings', label: 'Company Settings', icon: 'bi-gear-fill', color: '#d97706', desc: 'Company info, operating costs, and preferences', dir: ['export'], fmt: ['csv'], exportUrl: '/Tools/ExportCompanySettingsCsv' }, // ── QB Desktop Import ─────────────────────────────────────────────── { key: 'qbd-coa', label: 'Chart of Accounts', icon: 'bi-journal-text', color: '#374151', desc: 'Account list — import this first (required for bills)', badge: 'Import first', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportChartOfAccounts', accept: '.iif,.txt', tips: ['Lists → Chart of Accounts → right-click → Export → save as .iif', 'Upload the .iif file below'] }, { key: 'qbd-customers', label: 'Customers', icon: 'bi-people', color: '#2563eb', desc: 'Customer list from QB Desktop', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportCustomers', accept: '.iif,.txt', tips: ['File → Utilities → Export → Lists to IIF Files → select Customers', 'Upload the .iif file below'] }, { key: 'qbd-vendors', label: 'Vendors', icon: 'bi-truck', color: '#d97706', desc: 'Vendor list from QB Desktop', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportVendors', accept: '.iif,.txt', tips: ['File → Utilities → Export → Lists to IIF Files → select Vendors', 'Upload the .iif file below'] }, { key: 'qbd-catalog', label: 'Catalog Items', icon: 'bi-box-seam', color: '#059669', desc: 'Service items from QB Desktop', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportCatalogItems', accept: '.iif,.txt', tips: ['File → Utilities → Export → Lists to IIF Files → select Items', 'Upload the .iif file below'] }, { key: 'qbd-inventory', label: 'Inventory Stock', icon: 'bi-boxes', color: '#0891b2', desc: 'Inventory Valuation Summary — include Pref Vendor column', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportQbInventoryValuation', accept: '.csv', tips: [ 'Reports → Inventory → Inventory Valuation Summary', 'Customize Report → Display tab → check Pref Vendor', 'Excel → Create New Worksheet → Comma Separated Values (.csv)', 'Upload the saved .csv file below' ] }, { key: 'qbd-invoices', label: 'Invoices', icon: 'bi-receipt', color: '#2563eb', desc: 'Customer Balance Detail report', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportQbInvoices', accept: '.csv', tips: ['Reports → Customers & Receivables → Customer Balance Detail', 'Set date range to All', 'Excel → Create New Worksheet → Comma Separated Values (.csv)', 'Upload the saved .csv file below'] }, { key: 'qbd-transactions', label: 'Transactions', icon: 'bi-arrow-left-right', color: '#059669', desc: 'Transaction List by Customer report', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportQbTransactions', accept: '.csv', tips: ['Reports → Customers & Receivables → Transaction List by Customer', 'Set date range to All', 'Excel → Create New Worksheet → Comma Separated Values (.csv)', 'Upload the saved .csv file below'] }, { key: 'qbd-bills', label: 'Bills & Payments', icon: 'bi-file-earmark-minus', color: '#dc2626', desc: 'Vendor Balance Detail report — imports bills and payments in one pass', dir: ['import'], fmt: ['qb-desktop'], endpoint: '/Tools/ImportQbBillsAndPayments', accept: '.csv', tips: [ 'Reports → Vendors & Payables → Vendor Balance Detail', 'Set date range to All', 'Click Customize Report → Display tab → check Memo to include bill and payment descriptions', 'Excel → Create New Worksheet → Comma Separated Values (.csv)', 'Upload the file — bills are imported first, then payments are matched against them automatically' ] }, // ── QB Online Import ──────────────────────────────────────────────── { key: 'qbo-coa', label: 'Chart of Accounts', icon: 'bi-journal-text', color: '#374151', desc: 'Account List — import this first (required for invoices)', badge: 'Import first', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboChartOfAccounts', accept: '.xlsx,.xls', tips: [ 'Accounting (left nav) → Chart of Accounts → Download/Export button', 'Or: Reports → search "Account List" → Export to Excel', 'Upload the .xlsx file below' ] }, { key: 'qbo-customers', label: 'Customers', icon: 'bi-people', color: '#2563eb', desc: 'Customer Contact List from QuickBooks Online', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboCustomers', accept: '.xlsx,.xls', tips: [ 'Reports → search "Customer Contact List" → Customize → add all desired columns → Export to Excel', 'Tip: Add Billing Street, City, State, Zip columns via Customize → Rows/Columns for best results', 'Upload the .xlsx file below' ] }, { key: 'qbo-vendors', label: 'Vendors', icon: 'bi-truck', color: '#d97706', desc: 'Vendor Contact List from QuickBooks Online', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboVendors', accept: '.xlsx,.xls', tips: [ 'Reports → search "Vendor Contact List" → Customize → add all desired columns → Export to Excel', 'Or: Expenses → Vendors → Export icon (box with arrow) → Export to Excel', 'Upload the .xlsx file below' ] }, { key: 'qbo-products', label: 'Products & Services', icon: 'bi-box-seam', color: '#059669', desc: 'Product/service catalog from QuickBooks Online', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboCatalogItems', accept: '.xlsx,.xls', tips: [ 'Sales → Products and Services → Export to Excel icon (top right)', 'Inventory-type items are imported as Inventory; all others as Catalog Items', 'Items named Category:Item Name will have the category prefix stripped automatically', 'Upload the .xlsx file below' ] }, { key: 'qbo-invoices', label: 'Invoices', icon: 'bi-receipt', color: '#2563eb', desc: 'Invoice List report from QuickBooks Online', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboInvoices', accept: '.xlsx,.xls', tips: [ 'Reports → search "Invoice List" → set your date range → Export to Excel', 'Customers must be imported first so invoices can be linked', 'Invoice totals and open balances are imported; line item detail is not available in this report', 'Upload the .xlsx file below' ] }, { key: 'qbo-transactions', label: 'Transactions', icon: 'bi-arrow-left-right', color: '#059669', desc: 'Transaction List — applies payments to imported invoices', dir: ['import'], fmt: ['qb-online'], endpoint: '/Tools/ImportQboTransactions', accept: '.xlsx,.xls', tips: [ 'Reports → search "Transaction List by Date" → set All Dates → Export to Excel', 'Only Payment/Receipt rows are processed; Invoice rows are skipped', 'Invoices must be imported first so payments can be matched by reference number', 'Upload the .xlsx file below' ] }, // ── QB Export ─────────────────────────────────────────────────────── { key: 'qb-exp-customers', label: 'Customers', icon: 'bi-people', color: '#2563eb', desc: 'Export all active customers', dir: ['export'], fmt: ['qb-desktop', 'qb-online'], exportUrlDesktop: '/Tools/ExportCustomers?format=desktop', exportUrlOnline: '/Tools/ExportCustomers?format=online' }, { key: 'qb-exp-vendors', label: 'Vendors', icon: 'bi-truck', color: '#d97706', desc: 'Export all active vendors to IIF format', dir: ['export'], fmt: ['qb-desktop'], exportUrl: '/Tools/ExportVendors' }, { key: 'qb-exp-catalog', label: 'Catalog Items', icon: 'bi-box-seam', color: '#059669', desc: 'Export active catalog items as service items', dir: ['export'], fmt: ['qb-desktop', 'qb-online'], exportUrlDesktop: '/Tools/ExportCatalogItems?format=desktop', exportUrlOnline: '/Tools/ExportCatalogItems?format=online' }, ]; // ── Helpers ─────────────────────────────────────────────────────────────── function getExportUrl(item) { if (item.exportUrl) return item.exportUrl; if (wFmt === 'qb-online' && item.exportUrlOnline) return item.exportUrlOnline; if (item.exportUrlDesktop) return item.exportUrlDesktop; return '#'; } function filteredItems() { return ITEMS.filter(it => it.dir.includes(wDir) && it.fmt.includes(wFmt)); } // ── Wizard Navigation ───────────────────────────────────────────────────── window.wizardSetDirection = function (dir) { wDir = dir; wStep = 2; setBreadcrumb(2, dir === 'import' ? 'Import' : 'Export'); document.getElementById('step2-heading').textContent = dir === 'import' ? 'Import from which format?' : 'Export to which format?'; showStep(2); document.getElementById('wizardBackBtn').classList.remove('d-none'); }; window.wizardSetFormat = function (fmt) { wFmt = fmt; wStep = 3; const labels = { csv: 'CSV', 'qb-desktop': 'QB Desktop', 'qb-online': 'QB Online' }; setBreadcrumb(3, labels[fmt] || fmt); renderStep3(); showStep(3); }; window.wizardBack = function () { if (wStep === 4) { wItem = null; wStep = 3; resetBreadcrumb(4, wDir === 'import' ? 'Import' : 'Export'); renderStep3(); showStep(3); } else if (wStep === 3) { wFmt = null; wStep = 2; resetBreadcrumb(3, 'Select'); showStep(2); } else if (wStep === 2) { wDir = null; wStep = 1; resetBreadcrumb(2, 'Format'); resetBreadcrumb(1, 'Direction'); showStep(1); document.getElementById('wizardBackBtn').classList.add('d-none'); } }; window.wizardSelectItem = function (key) { wItem = ITEMS.find(it => it.key === key); if (!wItem) return; wStep = 4; setBreadcrumb(4, wItem.label); renderStep4(); showStep(4); }; function showStep(n) { [1, 2, 3, 4].forEach(function (s) { const el = document.getElementById('wizard-step-' + s); if (el) el.classList.toggle('d-none', s !== n); }); updateBreadcrumbActive(n); } function setBreadcrumb(step, label) { const lbl = document.getElementById('bc-' + step + '-label'); const bdg = document.getElementById('bc-' + step + '-badge'); if (lbl) { lbl.textContent = label; lbl.className = 'small fw-semibold'; } if (bdg) bdg.className = 'badge rounded-pill bg-primary'; } function resetBreadcrumb(step, label) { const lbl = document.getElementById('bc-' + step + '-label'); const bdg = document.getElementById('bc-' + step + '-badge'); if (lbl) { lbl.textContent = label; lbl.className = 'small text-muted'; } if (bdg) bdg.className = 'badge rounded-pill bg-secondary'; } function updateBreadcrumbActive(currentStep) { for (let s = 1; s <= 4; s++) { const badge = document.getElementById('bc-' + s + '-badge'); if (badge && s < currentStep && badge.className.includes('primary')) { badge.className = 'badge rounded-pill bg-success'; } } } // ── Step 3: item selection grid ─────────────────────────────────────────── function renderStep3() { const heading = document.getElementById('step3-heading'); const grid = document.getElementById('step3-grid'); if (!heading || !grid) return; heading.textContent = wDir === 'import' ? 'What would you like to import?' : 'What would you like to export?'; let html = ''; // CSV Export: "Export All" shortcut if (wDir === 'export' && wFmt === 'csv') { html += `
Or pick a specific data set below.
No options available for this selection.
${detail}