The repository, how to run CloudPay locally, how a change reaches production, the tests, and the traps.
src/web (Next.js) and src/api (.NET). main is production; development is the development environment.Azure DevOpsdocumentation/marketing.PowerPointaz login with access to the development Key Vault, which the API reads. dotnet-ef only if you add migrations.npm i at the root installs only concurrently; npm run setup runs npm ci in src/web.src/web/.env.example to src/web/.env.local, set NEXT_PUBLIC_BACKEND_URL=http://localhost:5085, and fill in the Clerk, Clover and DMS values from the team. Use the NEXT_PUBLIC_ names for the Clover domain and remote app id.npm run dev starts the web app on http://localhost:3000 and the API on http://localhost:5085 (HTTPS on 7291 with --launch-profile https). Swagger is at /swagger.Migrations apply when the API starts, and the Development settings point at the shared development database. Running a branch with a new migration changes that database for everyone.
npm i && npm run setup
npm run dev # web :3000 + api :5085
npm run dev:web # or one side only: npm run dev:api
cd src/api && dotnet test CloudPayClover.slnx
cd src/web && npm run typecheck && npm testdotnet ef migrations add <Name> --project src/CloudPayClover.Infrastructure --startup-project src/CloudPayClover.Api
dotnet ef database update --project src/CloudPayClover.Infrastructure --startup-project src/CloudPayClover.Apidevelopment, named after the story: us/{story}/….dotnet test and npm run typecheck && npm test yourself.src/web and src/api) and deploys it to the development environment.development into main, with 2 reviewers.production environment until someone approves it in Azure DevOps./health and the web pipeline checks that / does not answer 5xx. Then take a sale and send an invoice.There are no version numbers or tags: src/web/package.json has said 0.1.0 since the first commit. Releases go by date and PR.
| Class | Tests | Covers |
|---|---|---|
ReceiptServiceTests | 21 | Validation, merchant checks, Clover lookups, email and SMS, partial delivery, refund receipts |
MerchantUserServiceTests | 15 | Users list filters and sorting; update rules and the Clerk sync |
ContactServiceTests | 13 | Demo-request validation, the honeypot, delivery failures, the disabled form |
InvoiceTemplateTests | 12 | Invoice emails and texts: DMS and plain, logo, encoding, subjects, truncation |
PaymentServiceRefundTests | 12 | Refund webhooks: invoice refunded, partially refunded or voided; idempotency |
InvoiceCommandServiceTests | 9 | Create and resend: contact rules, the DMS snapshot, the pay link |
PaymentServiceInvoiceLinkTests | 9 | Matching payments to invoices, paid emails, no resend on a replay |
UserServiceTests | 9 | Preference defaults, saving and validation |
MerchantUsersEndpointTests | 8 | /merchant/users: auth, scoping, role validation, domain errors |
PaymentServiceLookupTests | 7 | Lookups by reference, single and batch |
AdminMerchantUsersEndpointTests | 6 | Admin users routes: 401, 403 for merchant admins, route scoping, role validation |
MerchantServiceSettingsTests | 6 | Saving settings, time zone, display groups, older JSON |
PaymentServiceRefundNoteTests | 6 | Refund notes: create, update, scoping, keys |
UserPreferencesEndpointTests | 6 | Preferences GET and PUT: auth, scoping, 404, a bad time zone |
ClerkSessionContextResolverTests | 5 | Clerk user to merchant and role, deactivated merchants, caching |
ContactEndpointTests | 5 | Demo request: 202, 400, 503, 429 past the limit |
DemoRequestTemplateTests | 5 | The demo-request email |
HostedCheckoutEndpointTests | 4 | Redirect to Clover; the paid, missing and failing pages |
MerchantLogoServiceTests | 4 | Logo sync from Clover |
WireEnumExtensionsTests | 4 | Clover's transaction type and result strings |
| Seven more classes | 19 | Admin settings, the Clover checkout request, hosted checkout, invoice stats SQL, receipt logos, webhook routing, Data Protection keys |
185 test methods in 27 classes; five theories bring it to 194 cases. Tests use EF Core's in-memory provider, so SQL Server behaviour is not exercised (the invoice-stats test only checks the generated SQL). Nothing covers the Clover OAuth exchange or the token refresh.
| Area | Files | Tests |
|---|---|---|
| DMS | DmsService, dmsTableQuery, dmsServer, useDmsOrders, PaymentHistoryCell, SendDialog | 47 |
| Helpers | time zones, payment reference, percent input, card brands, contact validators, Clarity | 35 |
| Payment details | PaymentDetailsService | 28 |
| Invoices | InvoiceSubmit, createInvoice, lookupInvoiceByPayment | 15 |
| Devices | DeviceStatusPanel, useFavoriteDevice | 15 |
| Marketing | DemoRequestForm, MarketingFooter, the demo-request schema | 13 |
| Transactions export | exportCsv | 8 |
| Tables | CustomTableActions | 2 |
163 it declarations in 23 files; it.each rows bring it to about 204 cases. The Sales Terminal (PaymentInput, CloverService), the admin pages, Settings, Preferences and the route handlers other than the DMS client have no tests, and no pipeline runs the suite.
| Folder | What is in it |
|---|---|
src/web/app/(root) | The merchant app behind CloverOnboardingGuard: Sales (page.tsx), dashboard, inventory, dms, payment-details/[id], settings, preferences |
src/web/app/(admin), (auth), (marketing) | The admin pages behind AdminGuard; sign-in, sign-up, connect-clover and callback; /home and the legal pages |
src/web/app/api | The route handlers: Clover relays, the DMS proxy, the Clerk webhook, CSP reports |
src/web/services | Plain modules the hooks call: api/backendClient, auth (session and token store), clover (SDK and token), dms, invoices, payments, receipts, user |
src/web/components | By feature, plus ui/ (shadcn) and shared/ (CustomTable, SendDialog, DeviceStatusPanel, NumericKeypad) |
src/web/proxy.ts | The Next.js 16 middleware: Clerk, the public routes, the CSP |
src/api/src/CloudPayClover.Api | Program.cs (auth schemes, policies, OData, the rate limit), the controllers and the error middleware |
…Application, …Domain | Interfaces, DTOs and commands; entities, enums and exceptions (no dependencies) |
…Infrastructure | CloudPayDbContext, configurations and migrations; the services; the Clover, Clerk, Twilio and SMTP2GO clients; email and SMS templates; background services; DependencyInjection.cs |
| Table | Holds | Since |
|---|---|---|
Merchants | The business, its Clover id (unique), the active flag and the Settings JSON | 2026-01-27; settings 2026-02-12 |
MerchantTokens | Encrypted Clover access and refresh tokens, their expiries and status (Active, Expired, Revoked, RefreshFailed) | 2026-01-27 |
Payments | Clover payments and refunds from webhooks: cents, card, type, result, external reference, and for refunds the source payment | 2026-01-27; refund link 2026-06-10 |
WebhookLogs | Every Clover webhook, its processing state and its retries | 2026-01-27 |
Invoices | Invoices, their contacts and status, and the DmsSnapshot JSON | 2026-04-15; both channels 2026-05-13; snapshot 2026-07-31 |
DataProtectionKeys | The key ring that encrypts the Clover tokens, shared by every instance | 2026-05-28 |
Users | Clerk id, merchant, role, department, name, email and the Preferences JSON | 2026-06-23; profile fields 2026-08-12 |
Invitations | Clerk invitations with their role and status | 2026-06-23 |
RefundNotes | Refund reasons, unique per merchant and source payment | 2026-06-26 |
Payments amounts are cents; Invoices amounts are dollars. The invoice matcher divides by 100 before comparing.merchant-settings-changed, cloudpay-timezone-changed), not React context. Dispatch them when you change either.enabled) on Reynolds and the department toggle, or they fail with not_provisioned (409).totalCount. Passing the full list pages it twice.middleware.ts.server.js exists only in the standalone build. npm run lint runs next lint, which Next.js 16 removed, so it probably fails.git log src/api starts on 2026-09-28. Older API history is in the read-only Clover-CloudPayService repository. git log --follow does work for src/web.services/mockUpData, the mocks in lib/index.ts, services/pdf/GeneratePDF.ts, lib/oauth-session, several unused components, and the unused nodemailer, ssh2-sftp-client and jszip packages. Email and SMS are sent by the API only.GET /weatherforecast).