WAVit Dashboard is the web portal for merchants who take payments with the WAVit app on Clover. It reads the payments every terminal reports to MiCamp's MiPoint database and turns them into a daily balance, a filterable transaction list with CSV export, and charts. Merchants also use it to change a few terminal settings, send pay-by-link invoices, invite their staff and send feedback. It is an ASP.NET Core 8 MVC app with server-rendered Razor views, hosted on Azure App Service. Production runs version 2.1.0, released on 2026-08-17.
The dashboard owns very little data. It mostly reads what the WAVit app and MiCamp's back office have already written.
| Piece | What it does for the dashboard |
|---|---|
| WAVit Payments (Clover app) | Writes every payment, refund and void to MiPoint, and reads the terminal settings the dashboard edits. See the WAVit project. |
| MiPoint database | The system of record. The dashboard queries it directly with EF Core (no API in between) for transactions, units, MIDs, devices, settings and invoices. It writes a few of these tables too. |
| Identity database | ASP.NET Core Identity's AspNet* tables: logins, passwords, 2FA. This is a separate SQL database from MiPoint. |
| MiPoint API | Used for one thing only: creating and cancelling pay-by-link invoices. MiPoint sends the email or text. |
| Configurator | Where MiCamp sets up merchants and most terminal settings. The dashboard edits only the tax rate, tips and unlock PIN. |
| Clover | Fallback receipts: when the receipt page has no record of a payment, it redirects to Clover's web receipt. |
| Azure | App Service hosting, Key Vault for secrets, Application Insights for telemetry. |
| Others | SMTP2GO for email, a Slack webhook for survey responses, and Microsoft Clarity session replay on signed-in pages. |
| Area | Choice |
|---|---|
| Framework | ASP.NET Core 8 MVC with Razor views, plus Razor Pages for Identity and the public pages. Project WAVitDashboard/WAvitDashboardWeb.csproj. |
| Auth | ASP.NET Core Identity 8.0.11 (default UI, mostly restyled), with confirmed email required |
| Data | EF Core 9.0 on SQL Server, database-first with no migrations. Two class libraries: MiCamp.Models (scaffolded MiPoint entities) and MiCamp.DataAccess (unit of work and a generic repository). |
| Front end | Bootstrap 5.3.8, jQuery, Chart.js, and per-page scripts under wwwroot/js/pages. The tables are server-rendered partials driven by OData-style query strings. |
| Secrets | Azure Key Vault through DefaultAzureCredential. The vault is chosen by KeyVault:Uri. |
| Observability | Application Insights (server SDK and browser snippet, through ILogger<T>), Microsoft Clarity, an audit table, and GET /health |
| Other libraries | MailKit (SMTP), CsvHelper,RestSharp, Newtonsoft.Json |
| Tests | xUnit with EF Core InMemory and Moq. A Playwright end-to-end suite exists on a branch. See Resources. |
| Hosting | Windows Azure App Service, one site for DEV and one for PROD, deployed by Azure Pipelines |
Three MiPoint records sit between a login and the merchants it can see.
| Record | What it is |
|---|---|
Unit (OrganizationUnit) | One merchant location. MiPoint's hierarchy has Enterprise, Organization, Merchant and Revenue Center levels. The dashboard works with the unit's GUID, which it calls the MerchantId. Transactions, devices, settings and invoices all hang off it. |
MID (OrganizationUnitMID) | A processor merchant id mapped to a unit |
Master MID (OrganizationUnitMasterMID) | A dashboard-only record keyed by email. It stores the account's MIDs as a JSON list and a Hidden flag. A hidden record cannot sign in ("User temporarily disabled"). |
Preferences (DashboardPreferences) | Per-user JSON: MerchantToShow (the units shown on Home), InvitationsLeft (50 to start), and the unused EnableDailyEmails and Emails |
/Dashboard/Portal/Home.MerchantToShow decides both what Home shows and which merchants the merchant-scoped pages accept. Unticking a unit under Preferences hides it everywhere.| Screen | What it is for | Shown when |
|---|---|---|
| Home | Today's balance across all units, a 10-day chart, unit cards, the latest transactions and shortcuts | Always; where sign-in lands |
| Transactions | Summary totals, a filterable table with a Quick View panel, and CSV export | Always |
| Transaction detail | Every field of one payment, the card, the receipt, and Resend Receipt | From Transactions |
| Report (legacy) | The older transactions page built on DataTables. It is still linked from Home's "View all transactions" button and the mobile shortcut. | Home |
| Analytics | Volume, amount, average and frequency, with two daily charts | Always |
| Invoices | Pay-by-link ("Text to Pay") invoices: totals, list, CSV export, a New Invoice wizard and cancel | Any of the user's units has an invoice tender |
| Devices | Terminals per unit, with Settings and Change PIN for each unit | Always |
| Feedback | Subject and comments, stored for the team | Header icon; mobile menu |
| Account settings | Profile, Preferences, Invite Users, Password, Personal Data | Header icon |
Signed-in users can switch between light and dark themes from the header. The choice is kept per browser in localStorage under the key wavit-theme, and light is the default. The landing page, sign-in pages and public receipt are always light.
The page itself is empty when it arrives. Two requests fill it: GetUnitsSummary and GetLastTenDaysChartData.
| Part | What it shows |
|---|---|
| Today's Total Balance | The total of today's sales across every unit shown: TotalAmount of transactions that are not refunds, voids or pre-transactions. It is gross, not net of refunds. Volume is the number of those transactions. |
| Chart | "Transactions amount per day (last 10 days)": the same sales total for each of the last ten days |
| Unit cards | Name, address and today's balance for each unit. "View All Transactions" opens Transactions filtered to that unit. A search box filters the cards by name. |
| Most Recent Transactions | The five newest payments from the last 30 days, with card brand (or cash), amount and date. Refunds are shown in red. |
| Shortcuts | Transactions, Analytics, Devices, Preferences |
| Filter | Options |
|---|---|
| Date | Today, Yesterday, Last 7 Days, This Month, or Custom (from/to date and time). The presets use the browser's clock. From must not be after To, and the latest allowed date is tomorrow. |
| Merchant | All Merchants, or one unit |
| Terminal | All Terminals, or one device by serial number |
| Card type | All, Card, Cash, EBT/SNAP |
WAVit Report - {merchant} - {from} to {to}.csv: a SUMMARY block (totals, card, cash, refunds, voids), then one row per transaction. The columns include date, time, unit, payment id, tenders, invoice, amounts, card type and number, auth code, terminal, service advisor, employee and the enabled custom fields. Refund rows carry a minus sign.IsTipAllowed, EnableCashDiscounts and its tender types.The detail page has a Refund panel marked "On Development". Refunds and voids are done on the terminal; the dashboard only reports them.
These rules live in Helpers/Reporting.cs and TransactionService. They are the reason two screens can disagree.
| Field and value | Treated as |
|---|---|
TransactionStatus = "9" | A pre-transaction: the record the app writes before Clover is called. Always hidden. |
TransactionTypeId = 4 | Failed. Excluded. |
TransactionTypeId = 13 | A void. The voided sale is removed from the table and the totals. The void is counted under Voids. |
IsRefund | A refund. Counted under Refunds. |
IsCashPayment | Cash rather than card |
CardTypeId = 10 | EBT/SNAP. The card brand also shows EBT for 11. |
Several rows with one PaymentId | Duplicates written by webhooks. All but one are dropped. |
| Field | Shown as |
|---|---|
Amount | Sub Total / Payment Amount |
TaxAmount | Tax |
TipAmount | Tip |
ServiceAmount | WAVit / Service Amount. On the public receipt it is "Technology Fee", hidden for dual-price merchants. It is the surcharge or non-cash adjustment. |
DiscountAmount | Cash Savings |
TotalAmount | Total. Every balance and chart sums this field. |
Time zones: transaction times are stored in UTC. Each unit's state maps to one Windows time zone (Helpers/States.cs), and lists and totals are shown in that local time. When several units are selected, the first unit's zone is used for all of them. "Today" on Home is the server's date.
TotalAmount), Average Value, and Transaction Frequency (count per day of the range).Devices lists every terminal under each unit: model image, brand and model, serial number, alternate merchant id and last update. Each unit has a Settings page and a Change PIN page.
| Field | Settings key | Rule |
|---|---|---|
| Tax Rate % | TaxRate | Required, 0–100 |
| Allow Gratuity (Tips)? | IsTipAllowed | |
| Gratuity calculated post tax? | IsTipPostTax | Saved only when tips are allowed |
| Gratuity calculated post surcharge? | IsTipPostSurcharge | Saved only when tips are allowed |
| Gratuity Percent Option 1–3 | GratuityPercent1–3 | Not negative |
OrganizationUnitProduct.Settings. They apply to every terminal of the unit. The dashboard parses it and changes only the keys above, so keys it does not know about are left alone.UnlockPIN): 4 to 6 digits. It can change the PIN (the current one is required), set one when none exists, or remove it (stored as ----, meaning disabled).Pay-by-link invoices for merchants with an invoice tender. The list reads MiPoint's Invoice table; creating and cancelling go through the MiPoint API, which sends the link and hosts the payment page.
TextToPayMerchants). The merchant's invoice-number settings (IncludeInvoice, InvoiceRequired, InvoiceCaption) come with it.CalculateBreakdown). The server works them out again when the invoice is created, and the browser only sends the amount.Outstanding.amount = round2(amount)
tax = round2(amount × TaxRate / 100)
base = SurchargePostTax ? amount + tax : amount
service = round2(base × SurchargePercent / 100)
tip = 0 // the customer tips on the payment page
total = amount + tax + service
// rounding is AwayFromZero; missing or unreadable settings mean 0 tax and 0 serviceOutstanding (or Pending) until paid, then Paid (set upstream), or Cancelled.WAVit Invoices - {from} to {to}.csv.| Page | What it is |
|---|---|
/ | The WAVit marketing page: no-fee pitch, savings calculator, clients, contact details, and links to "Become a Client" and the dashboard sign-in |
/Invoice?id={paymentId} | The virtual receipt for a payment: merchant, amounts, card brand and masked number, auth and payment ids, and a Refunded / Partially Refunded / Voided badge with the refunds. If MiPoint has no such payment, it redirects to Clover's receipt (the payment URL, then the credit URL), or to /ReceiptNotFound. |
/ReceiptNotFound | Apology and support contact |
/Survey | "WAVit Payments Feedback", an eight-step wizard: business name, star rating, impact of recent updates, biggest frustration, wished-for feature, NPS 0–10, what would help most, and an optional email. Responses are saved to MiPoint and posted to Slack. |
/health | Liveness for monitoring. |
The in-dashboard Feedback form is a separate thing. It offers eight subjects (WAVit App: features, reporting, other; WAVit Dashboard: data accuracy, features, other issue, other feedback; Other), needs at least 20 characters, and is stored in DashboardFeedback with no notification.