Initial commit

This commit is contained in:
2026-04-23 21:38:24 -04:00
commit 63e12a9636
1762 changed files with 1672620 additions and 0 deletions
@@ -0,0 +1,197 @@
@{
ViewData["Title"] = "Accounting Export";
ViewData["PageIcon"] = "bi-box-arrow-up";
}
<div class="row justify-content-center">
<div class="col-lg-7">
<form asp-action="Export" method="post" id="exportForm">
@Html.AntiForgeryToken()
<!-- Date Range -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-0 py-3">
<h5 class="mb-0 fw-semibold"><i class="bi bi-calendar-range me-2 text-primary"></i>Date Range</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<label class="form-label fw-semibold">Start Date <span class="text-danger">*</span></label>
<input type="date" name="startDate" class="form-control" value="@ViewBag.DefaultStart" required>
</div>
<div class="col-md-6">
<label class="form-label fw-semibold">End Date <span class="text-danger">*</span></label>
<input type="date" name="endDate" class="form-control" value="@ViewBag.DefaultEnd" required>
</div>
</div>
<div class="mt-3 d-flex flex-wrap gap-2" id="quickRanges">
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('this-month')">This Month</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('last-month')">Last Month</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('this-quarter')">This Quarter</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('last-quarter')">Last Quarter</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('this-year')">This Year</button>
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="setRange('last-year')">Last Year</button>
</div>
</div>
</div>
<!-- Format -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-0 py-3">
<h5 class="mb-0 fw-semibold"><i class="bi bi-file-earmark-zip me-2 text-primary"></i>Export Format</h5>
</div>
<div class="card-body">
<div class="row g-3">
<div class="col-md-6">
<label class="format-card d-block border rounded p-3 cursor-pointer @("quickbooks" == "quickbooks" ? "" : "")" id="card-quickbooks">
<input type="radio" name="format" value="quickbooks" class="d-none format-radio" id="fmt-quickbooks">
<div class="d-flex align-items-start gap-3">
<div class="mt-1 text-success" style="font-size:1.6rem;"><i class="bi bi-building"></i></div>
<div>
<div class="fw-semibold">QuickBooks Desktop</div>
<div class="text-muted small">IIF files — import directly via File &gt; Utilities &gt; Import</div>
<div class="mt-2">
<span class="badge bg-light text-dark border me-1">customers.iif</span>
<span class="badge bg-light text-dark border me-1">invoices_payments.iif</span>
<span class="badge bg-light text-dark border">expenses_bills.iif</span>
</div>
</div>
</div>
</label>
</div>
<div class="col-md-6">
<label class="format-card d-block border rounded p-3 cursor-pointer" id="card-csv">
<input type="radio" name="format" value="csv" class="d-none format-radio" id="fmt-csv" checked>
<div class="d-flex align-items-start gap-3">
<div class="mt-1 text-primary" style="font-size:1.6rem;"><i class="bi bi-filetype-csv"></i></div>
<div>
<div class="fw-semibold">CSV (Universal)</div>
<div class="text-muted small">Works with QuickBooks Online, Xero, Wave, Excel, and more</div>
<div class="mt-2">
<span class="badge bg-light text-dark border me-1">invoices.csv</span>
<span class="badge bg-light text-dark border me-1">payments.csv</span>
<span class="badge bg-light text-dark border">+5 more</span>
</div>
</div>
</div>
</label>
</div>
</div>
</div>
</div>
<!-- What's Included -->
<div class="card border-0 shadow-sm mb-4">
<div class="card-header bg-white border-0 py-3">
<h5 class="mb-0 fw-semibold"><i class="bi bi-list-check me-2 text-primary"></i>What's Included</h5>
</div>
<div class="card-body">
<div class="row g-2">
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Customer list
</div>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Invoices &amp; line items
</div>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Payments received
</div>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Direct expenses
</div>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Vendor bills (AP)
</div>
</div>
<div class="col-sm-6">
<div class="d-flex align-items-center gap-2 text-muted small">
<i class="bi bi-check-circle-fill text-success"></i> Bill payments
</div>
</div>
</div>
</div>
</div>
<div class="d-flex gap-2">
<button type="submit" class="btn btn-primary px-4" id="exportBtn">
<i class="bi bi-download me-2"></i>Download Export Package
</button>
<a asp-controller="Reports" asp-action="Index" class="btn btn-outline-secondary">Cancel</a>
</div>
</form>
</div>
</div>
@section Scripts {
<script>
// Format card selection
document.querySelectorAll('.format-radio').forEach(function(radio) {
radio.addEventListener('change', updateFormatCards);
});
function updateFormatCards() {
document.querySelectorAll('.format-card').forEach(function(card) {
const radio = card.querySelector('.format-radio');
card.classList.toggle('border-primary', radio.checked);
card.classList.toggle('bg-primary-subtle', radio.checked);
});
}
// Init — mark CSV as selected by default
document.getElementById('fmt-csv').checked = true;
updateFormatCards();
// Prevent double-submit
document.getElementById('exportForm').addEventListener('submit', function() {
const btn = document.getElementById('exportBtn');
btn.disabled = true;
btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Generating…';
setTimeout(function() { btn.disabled = false; btn.innerHTML = '<i class="bi bi-download me-2"></i>Download Export Package'; }, 8000);
});
// Quick date range shortcuts
function setRange(range) {
const now = new Date();
const y = now.getFullYear();
const m = now.getMonth(); // 0-indexed
let start, end;
if (range === 'this-month') {
start = new Date(y, m, 1);
end = new Date(y, m + 1, 0);
} else if (range === 'last-month') {
start = new Date(y, m - 1, 1);
end = new Date(y, m, 0);
} else if (range === 'this-quarter') {
const q = Math.floor(m / 3);
start = new Date(y, q * 3, 1);
end = new Date(y, q * 3 + 3, 0);
} else if (range === 'last-quarter') {
const q = Math.floor(m / 3) - 1;
const qy = q < 0 ? y - 1 : y;
const qq = q < 0 ? 3 : q;
start = new Date(qy, qq * 3, 1);
end = new Date(qy, qq * 3 + 3, 0);
} else if (range === 'this-year') {
start = new Date(y, 0, 1);
end = new Date(y, 11, 31);
} else if (range === 'last-year') {
start = new Date(y - 1, 0, 1);
end = new Date(y - 1, 11, 31);
}
const fmt = d => d.toISOString().slice(0, 10);
document.querySelector('[name="startDate"]').value = fmt(start);
document.querySelector('[name="endDate"]').value = fmt(end);
}
</script>
}