Customers Management
Relevant source files
The following files were used as context for generating this wiki page:
- packages/api/Modules/Customers/CustomerService.cs
- packages/api/Modules/Customers/CustomerEndpoints.cs
- packages/web/src/features/customers/customers.server.ts
- packages/api/Modules/Customers/Customer.cs
- packages/api/Modules/Customers/CustomersModule.cs
- packages/web/src/features/customers/customers.functions.ts
- packages/web/src/api/schema.ts
- packages/api/Migrations/AppDb/20260513112353_AddUsers.Designer.cs
Introduction
Customers Management is a core module within the project responsible for handling the lifecycle of customer entities, including their registration, modification, search, and archival. It serves as a foundational administrative slice, providing the necessary data structures and services to manage organizational clients who interact with other systems such as Contracts Management.
The system architecture follows a modular approach, separating concerns between a .NET-based REST API backend and a Tanstack-powered React frontend. The backend utilizes Entity Framework Core for data persistence in a SQLite database, while the frontend leverages server functions and Zod-validated schemas to ensure type-safe data handling.
Sources: packages/api/Modules/Customers/CustomersModule.cs, packages/web/src/features/customers/customers.functions.ts, CHANGELOG.md:46-47
Architecture and Data Flow
The module is organized into distinct layers across the monorepo:
- API Layer: Defines RESTful endpoints and request validation.
- Service Layer: Encapsulates business logic, including sequential number generation.
- Data Layer: Manages persistence via
AppDbContext. - Web Layer: Provides UI components, server functions, and API client integration.
Component Relationship
The following diagram illustrates the high-level relationship between the different components involved in customer operations.
The flow initiates from the React UI, passing through Tanstack server functions to reach the backend service, which interacts with the database and a sequential counter service for customer numbering.
Sources: packages/api/Modules/Customers/CustomerService.cs:11-15, packages/web/src/features/customers/customers.functions.ts, packages/api/Modules/Customers/CustomersModule.cs:12-16
Backend Implementation
Data Model
The Customer entity represents a business client. It includes unique identification, contact details, and status flags. Database constraints ensure that customer numbers are unique.
| Field | Type | Description | Constraints |
|---|---|---|---|
Id | Guid | Primary unique identifier | Generated on Add |
Number | int | Sequential customer number | Unique Index |
Name | string | Organization name | Max Length 200 |
Street | string | Street address | Max Length 200 |
Zip | string | Postal code | Max Length 20 |
City | string | City location | Max Length 100 |
Country | string | Country name | Max Length 100 |
ContactName | string | Primary contact person | Max Length 200 |
ContactEmail | string | Primary contact email | Max Length 254 |
IsArchived | bool | Soft-delete status flag | Default: false |
Sources: packages/api/Modules/Customers/Customer.cs:5-16, packages/api/Migrations/AppDb/20260513112353_AddUsers.Designer.cs:33-85
Service Logic
The CustomerService handles CRUD operations and complex querying. A notable feature is the GetAllAsync method, which implements filtering for active (non-archived) customers, keyword search across names, and dynamic sorting.
public async Task<PagedCustomers> GetAllAsync(
string? search,
CustomerSort sort,
SortDirection sortDirection,
int page,
int pageSize,
CancellationToken cancellationToken = default)
{
var query = _dbContext.Customers.Where(customer => !customer.IsArchived);
// ... filtering and sorting logic ...
var total = await query.CountAsync(cancellationToken);
var items = await query.Skip((page - 1) * pageSize).Take(pageSize).ToListAsync(cancellationToken);
return new PagedCustomers(items, total);
}
Sources: packages/api/Modules/Customers/CustomerService.cs:20-51
API Endpoints
The module exposes several endpoints under the /api/customers prefix. Request validation is enforced via ValidationFilter<CustomerRequest>.
| Method | Path | Description | Response |
|---|---|---|---|
| GET | /api/customers | List customers with search/sort/pagination | PagedCustomers |
| GET | /api/customers/{id} | Retrieve specific customer details | Customer or 404 |
| POST | /api/customers | Create a new customer | 201 Created |
| PUT | /api/customers/{id} | Update existing customer details | 200 OK or 404 |
| PATCH | /api/customers/{id}/archive | Soft-delete a customer | 204 No Content |
| PATCH | /api/customers/{id}/unarchive | Restore a customer | 204 No Content |
Sources: packages/api/Modules/Customers/CustomerEndpoints.cs:13-88, packages/web/src/api/schema.ts:51-180
Frontend Integration
Server Functions
The web application uses @tanstack/react-start server functions to bridge the UI and the API. These functions include input validation using Zod schemas.
Customer List UI
The administrative list view (CustomerList) implements:
- Debounced Search: Filtering by name or contact with a 300ms delay.
- Sortable Headers: Column-based sorting for Number, Name, Contact, and City.
- Pagination: Navigation between results sets (default 25 per page).
- Archival Flow: An
AlertDialogconfirmation before triggering the archive operation.
Sources: packages/web/src/routes/_authed/admin/customers/index.tsx:29-75
Conclusion
The Customers Management module provides a robust framework for handling client data with a strong emphasis on data integrity through server-side validation and sequential ID generation. Its integration with standardized API patterns and Tanstack-based frontend utilities ensures a consistent experience for administrators and maintainable code for developers.
Sources: REVIEW.md:21-25, packages/api/Modules/Customers/CustomerService.cs:55-60