richardchanjr90-cpu/ddd-by-example
57.2
Adequate · 21 September 2026
17.6k
lines of production code
C#
primary language
4
measurements over time
What this system is
This system is a loyalty program management platform built on Azure Functions, designed to handle the full lifecycle of venues, products, orders, and user interactions. It implements a CQRS architecture using MediatR to process commands for creating, updating, and archiving entities like loyalty programs, product groups, and orders. The system manages complex domain events to trigger notifications for order status changes, user interactions, and worker invites, while also handling purchase redemption and user profile management.
How it got here
2025 — Loyalty program domain implementation
46 changes.
This period focused on building the core domain and infrastructure for a new loyalty program feature, introducing entities, commands, and queries for managing venues, products, and purchases. The work established the application layer with MediatR handlers, AutoMapper mappings, and database access patterns, while also setting up the Azure Functions infrastructure and test coverage for the new services.
2026 — Loyalty domain implementation
42 changes.
This period focused on implementing the core loyalty domain, introducing comprehensive CRUD operations, queries, and commands for entities such as orders, products, venues, and user profiles. The work established the internal event-driven architecture by adding domain events, outbox-based persistence, and notification handlers to ensure reliable state management and integration.
Features
Add write API endpoints for venue, product, and order management
New HTTP functions have been added to the Write service to handle administrative and operational write operations. This includes venue approval and rejection, creating and managing loyalty programs and product groups, managing products and their images, handling order status updates and ratings, processing purchases, and managing worker invites. These endpoints expose the backend services for creating, updating, archiving, and deleting resources across the loyalty program system.
src/LoyaltyProgram/Http/Write · high confidence
Added Firebase query handlers for client info, current user, and email verification
Implemented three new query handlers in the Firebase infrastructure layer: GetClientInfoFirebaseQueryHandler, GetCurrentUserQueryHandler, and GetVerificationLinkQueryHandler. These handlers enable retrieving client information and current user details from Firebase, as well as generating email verification links for users.
src/Loyalty.Infrastructure.Firebase.Handlers/Queries · high confidence
Added Firebase token and email update handlers
New command handlers were added to manage Firebase authentication state. The SetupFirebaseTokenCommandHandler now processes user claims and roles to set custom Firebase user claims, while the UpdateUserEmailCommandHandler allows users to update their email address in Firebase, including handling verification status.
src/Loyalty.Infrastructure.Firebase.Handlers/Commands · high confidence
Added GetUserInfoByCodeQuery for retrieving user information by code
A new query class, GetUserInfoByCodeQuery, has been introduced in the Loyalty domain handlers. This class implements the MediatR IRequest interface to request user information associated with a specific code, establishing the structure for this new lookup capability.
src/Loyalty.Domain.Handlers.Queries/Queries/Code · high confidence
Added GetUserInfoByCodeQueryResult for code-based user lookups
A new query result class, GetUserInfoByCodeQueryResult, has been introduced in the Loyalty.Domain.Handlers.Queries.QueryResults.Code namespace. This class defines the structure for user information retrieved via a code, specifically exposing a UserId property for downstream processing.
src/Loyalty.Domain.Handlers.Queries/QueryResults/Code · high confidence
Added HTTP read endpoints for the Loyalty Program
Introduced a comprehensive set of new HTTP read functions across the Loyalty Program module, exposing RESTful endpoints for retrieving venues, products, product groups, loyalty programs, orders, purchases, and user profiles. These endpoints facilitate read-only access to core business entities, enabling clients to fetch detailed information about the loyalty ecosystem.
src/LoyaltyProgram/Http/Read · high confidence
Added SelfWarmer timer function to pre-warm database contexts
A new Azure Functions timer job named 'SelfWarmer' has been added to the LoyaltyProgram.Timer module. Executed every five minutes, this function initializes the LoyaltyDbContext and IntegrationEventsContext to warm up the database models, ensuring faster subsequent access.
src/LoyaltyProgram/Timer · high confidence
Added Service Bus function to process client events and order notifications
A new Azure Functions class, ClientEventsFunction, was added to the LoyaltyProgram.ServiceBus project. This function listens to Service Bus topics for code generation, new order, and order update notifications. It processes these events by updating user codes in the database and handling order creation and status updates, subsequently pushing new or declined order notifications to Azure Queues for downstream processing.
src/LoyaltyProgram/ServiceBus · high confidence
Added UserProfile query result model
A new C\# class, GetUserProfileByIdQueryResult, was added to the domain handlers. This model defines the structure for user profile data, including name, last name, phone, city, and photo URI, with corresponding JSON property names for serialization.
src/Loyalty.Domain.Handlers.Queries/QueryResults/UserProfile · high confidence
Added client notification types and Azure publish profiles for the Loyalty Program
The Loyalty.Client.Notifications library now includes a new IClientStatisticsNotification interface and an InteractionNotification class that carries user interaction data (userId, interactionType, timestamp, and venueId) for integration events. Additionally, new Azure Web App publish profiles (Web Deploy and Zip Deploy) have been added for the LoyaltyProgram service, configuring deployment to the 'loyaltyprogram-dev' Azure site.
common/Loyalty.Client.Notifications, src/LoyaltyProgram/Properties · high confidence
Added command definitions for creating and updating loyalty rules
New command classes have been introduced in the domain handlers to support creating and updating loyalty rules. Specifically, the system now includes CreateRuleCommand and CreateSingleRuleCommand to handle the creation of single or multiple rules, and UpdateRuleCommand and UpdateSingleRuleCommand to handle updates. These commands define the structure for rule data, including rule type, version, and the rule object itself, enabling the backend to process these specific operations.
src/Loyalty.Domain.Handlers.Queries/Commands/Rules · high confidence
Added command definitions for loyalty program lifecycle
Introduced new MediatR command classes to support creating, updating, and archiving loyalty programs. The diff adds \CreateLoyaltyProgramCommand\ (accepting name, description, dates, venue, and external URI), \UpdateLoyaltyProgramCommand\ (for modifying existing programs with similar fields plus a publish status), and \ArchiveLoyaltyProgramCommand\ (identifying the program by ID and user). These commands enable the backend to process loyalty program creation, modification, and archival requests.
src/Loyalty.Domain.Handlers.Queries/Commands/LoyaltyPrograms · high confidence
Added command definitions for managing loyalty product groups
New command classes (ArchiveLoyaltyProductGroupCommand, CreateLoyaltyProductGroupCommand, UpdateLoyaltyProductGroupCommand) were added to the LoyaltyProductGroup namespace. These commands define the input structures for archiving, creating, and updating loyalty product groups, each inheriting from MediatR's IRequest interface and containing relevant properties such as user ID, loyalty program ID, name, description, and rule configurations.
src/Loyalty.Domain.Handlers.Queries/Commands/LoyaltyProductGroup · high confidence
Added command handlers for managing loyalty programs, product groups, products, orders, purchases, user profiles, and venues
Implemented command handlers for creating, updating, archiving, and patching loyalty programs, product groups, products, orders, purchases, user profiles, and venues. These handlers process commands to create new entities (e.g., CreateLoyaltyProgramCommandHandler, CreateProductGroupCommandHandler), update existing ones (e.g., UpdateLoyaltyProgramCommandHandler, PatchProductCommandHandler), archive or reject them (e.g., ArchiveLoyaltyProgramCommandHandler, RejectVenueCommandHandler), and perform specific actions like burning or creating purchases (e.g., BurnPurchaseCommandHandler, CreateAndBurnPurchaseCommandHandler). The changes also include handlers for managing venue details, images, and order acceptance status.
src/Loyalty.Infrastructure.Handlers.Commands/Commands · high confidence
Added command models for creating and updating venue invites
Introduced new command classes, CreateInviteCommand and UpdateInviteCommand, within the Invites directory. These define the data structures for creating and updating venue invites, including fields for venue ID, user role, phone number, name, and position name.
src/Loyalty.Domain.Handlers.Queries/Commands/Workers/Invites · high confidence
Added core domain model base classes and interfaces
The codebase now includes foundational domain-driven design primitives in the \Loyalty.Core.Entities.SeedWork\ namespace. This includes an \Entity\ base class managing domain events and identity-based equality, an \Enumeration\ abstract class for strongly-typed enums with lookup capabilities, a \ValueObject\ base class for value-type equality semantics, and interfaces for \IAggregateRoot\, \IRepository\, and \IUnitOfWork\ to support repository and unit-of-work patterns.
src/Loyalty.Core.Entities/SeedWork · high confidence
Added data access infrastructure components
The Loyalty.Infrastructure.DataAccess module now includes three new classes: a factory for creating the EF Core DbContext for design-time operations, an extension method to dispatch domain events via MediatR, and a provider to extract tenant identifiers from the current HTTP context.
src/Loyalty.Infrastructure.DataAccess · high confidence
Added database context and migrations for integration event logging
Introduced the \IntegrationEventsContext\ and its corresponding interface \IIntegrationEventsContext\ to manage the persistence of integration events. This includes the entity configuration for \IntegrationEventLogEntry\, a database migration script to create the \IntegrationEvents\ table in the \events\ schema, and a design-time context factory to support database migrations.
src/Loyalty.Infrastructure.Events.DataAccess · high confidence
Added domain event handlers for loyalty programs, orders, and purchases
New domain event handlers have been introduced to process events for loyalty programs (creation, update, and archival), orders (status changes and user ratings), and purchases (creation and redemption). Each handler listens for specific domain events and persists corresponding notifications to the event bus, ensuring that downstream systems are notified of these key business actions.
src/Loyalty.Application.DomainEvents.Handlers/LoyaltyPrograms, src/Loyalty.Application.DomainEvents.Handlers/Orders, src/Loyalty.Application.DomainEvents.Handlers/Purchases · high confidence
Added domain event handlers for worker lifecycle and profile updates
New domain event handlers were added to the application layer to process worker-related events, including creation, archiving, patching, and updates. These handlers persist notifications such as UpdatedWorkerNotification, SetupFirebaseTokenNotification, ArchiveWorkerNotification, PatchWorkerNotification, and UpdateWorkerProfileNotification to the event bus. In the infrastructure layer, corresponding notification handlers were introduced to update Firebase user claims with worker details (name, surname, city, roles) and manage token setup, ensuring that Firebase authentication claims are synchronized with the worker's profile and venue roles.
src/Loyalty.Application.DomainEvents.Handlers/Workers, src/Loyalty.Infrastructure.Firebase.Handlers/Notifications · high confidence
Added domain events for all core entities
A comprehensive set of domain events has been added to the \Loyalty.Core.Entities\ module, covering lifecycle and state changes for Loyalty Programs, Product Groups, Products, Orders, Purchases, Venues, and Workers. Each entity now exposes specific events (such as \LoyaltyProgramCreatedDomainEvent\, \ProductArchivedDomainEvent\, and \VenueApprovedDomainEvent\) to support internal event-driven workflows.
src/Loyalty.Core.Entities/Events · high confidence
Added email confirmation link sending functionality
A new Azure Function, SendEmailConfirmationLinkFunction, has been introduced to process email invitations. This function listens to a queue for invitation data and uses SendGrid to send confirmation emails with verification links, supporting dynamic template data for the link.
src/LoyaltyProgram/SendGrid · high confidence
Added exception handling and transactional notification decorators
Introduced a new HandlerWrapper class in the IoC infrastructure layer that standardizes HTTP error responses by catching AuthenticationException to return 401 Unauthorized, and other exceptions to return 400 Bad Request with error details. Additionally, added a TransactionalNotificationDecorator for MediatR notifications, which wraps notification handling to ensure transactional behavior (though the current implementation appears to be a placeholder or minimal wrapper).
src/Loyalty.Infrastructure.IoC · high confidence
Added integration event notifications for domain entities
Added a comprehensive set of MediatR notification classes to the \Loyalty.Domain.Handlers.Notifications\ module, establishing the messaging contracts for domain events. This includes base interfaces (\IIntegrationEventsNotification\, \IUserEventsNotification\, \IVenueIntegrationEventsNotification\) and specific event payloads for Loyalty Programs, Product Groups, Products, Orders, Purchases, Ratings, Venues, Visits, and Workers. These notifications carry the necessary data (such as IDs, status changes, and metadata) to trigger downstream processing or user notifications.
common/Loyalty.Domain.Handlers.Notifications · high confidence
Added new DTOs for order lifecycle events
Three new data transfer objects have been introduced to represent order state changes: NewOrderDto for creating orders, OrderChangedDto for tracking status updates, and OrderDeclinedDto for declined orders. These DTOs expose specific fields such as venue ID, user ID, order status, and reason for decline, enabling the application to handle these distinct order events.
src/Loyalty.Application.Storage.Dto/Orders · high confidence
Added new Firebase command models for user management
Three new command models have been introduced to support user-related Firebase operations: AddUserToVenueFirebaseCommand for associating users with venues, SetupFirebaseTokenCommand for configuring user tokens and profile details, and UpdateUserEmailCommand for modifying user email addresses.
src/Loyalty.Domain.Handlers.Firebase.Queries/Commands · medium confidence
Added new query classes for retrieving orders by venue, user, and ID
Three new MediatR query classes have been introduced in the Orders module: GetAllOrdersByVenueIdQuery, GetOrderByIdQuery, and GetOrdersByUserIdQuery. These additions provide the application with the ability to fetch order data filtered by venue ID, specific order ID, and user ID respectively, expanding the available data retrieval capabilities for the loyalty domain.
src/Loyalty.Domain.Handlers.Queries/Queries/Orders · high confidence
Added new query result models for active purchases
New result classes have been introduced to support querying active purchases. The changes add GetActivePurchaseResult, which includes loyalty program details and a list of group purchases; GetActivePurchasesResult, which wraps a list of these results; GroupPurchaseResult, which captures group-level purchase data including rules and associated products; and ProductPurchaseResult, which details individual product information such as name, icon, image URL, and price. These models enable the system to return structured data about active purchases and their associated products and groups.
src/Loyalty.Domain.Handlers.Queries/QueryResults/Purchase · high confidence
Added notification functions for order lifecycle and invite SMS
Added new Azure Functions to handle push notifications for order status changes (new, changed, declined) and purchase confirmations, as well as an SMS notification for worker invites. These functions listen to specific message queues and send targeted notifications to Android and Apple devices or via SMS, improving user awareness of order updates and invite status.
src/LoyaltyProgram/Storage · high confidence
Added order patching commands for status and rating updates
New command classes, PatchOrderCommand and PatchRateOrderCommand, have been introduced in the Orders directory. PatchOrderCommand enables updating an order's status and adding a venue comment, while PatchRateOrderCommand allows updating an order's venue rating and associated comment. These commands facilitate the modification of existing orders through the MediatR pipeline.
src/Loyalty.Domain.Handlers.Queries/Commands/Orders · high confidence
Added order query result models for user and venue lookups
Introduced new C\# classes to represent order data for queries by user ID and venue ID. The changes add GetOrderByUserIdQueryResult, GetOrderByVenueIdQueryResult, and GetOrderItemByVenueIdQueryResult, which define the structure for order details including items, status, dates, and comments. These models support retrieving order lists via GetOrdersByUserIdQueryResult and GetOrdersByVenueIdQueryResult, enabling the system to return structured order information for both individual users and specific venues.
src/Loyalty.Domain.Handlers.Queries/QueryResults/Orders · high confidence
Added outbox-based event persistence and publishing service
Introduced a new outbox implementation in the Loyalty.Infrastructure.Outbox module, featuring an EventBusPublishingService that retrieves unprocessed integration events from a persistent store, publishes them via MediatR, and updates their status (published or failed) in the database. The change also includes the underlying PersistentIntegrationEventService for database operations and a LoggingIntegrationEventService that adds logging around event saving and retrieval.
src/Loyalty.Infrastructure.Outbox · high confidence
Added product domain event handlers to propagate product lifecycle changes
New domain event handlers have been added for product lifecycle events, including creation, updates, image changes, availability changes, and archiving. Each handler listens for its respective domain event and persists corresponding notifications (e.g., CreateProductNotification, UpdateProductNotification, PatchProductNotification, ArchiveProductNotification) to the event bus, ensuring downstream systems are notified of product state changes.
src/Loyalty.Application.DomainEvents.Handlers/Product · high confidence
Added product group command models
New command classes for managing product groups have been introduced, enabling users to create, update, patch, and archive product groups. Specifically, the system now supports creating a product group with a name, icon, and associated products; updating an existing group's details and products; patching availability status; and archiving a group.
src/Loyalty.Domain.Handlers.Queries/Commands/ProductGroups · high confidence
Added product group query result models and validation exception
Introduced a new exception type, LoyaltyValidationException, which carries a list of error codes alongside the standard exception message. Additionally, added query result models for product groups: GetProductGroupByIdQueryResult, which includes fields for id, venueId, name, icon, availability status, and a list of products; and corresponding wrapper results for retrieving product groups by user or generally.
src/Loyalty.Common.Shared/Exceptions, src/Loyalty.Domain.Handlers.Queries/QueryResults/ProductGroup · high confidence
Added purchase command models for the loyalty domain
Three new command classes were added to the purchase handling layer: BurnPurchaseCommand, CreateAndBurnCommand, and CreatePurchaseCommand. These define the data structures used to process purchase-related actions, including fields for loyalty product groups, user and worker identifiers, venue, and monetary values.
src/Loyalty.Domain.Handlers.Queries/Commands/Purchase · medium confidence
Added queries to retrieve client, current user, and email verification link data from Firebase
New MediatR query classes and their corresponding result models have been introduced in the Firebase domain handlers. Specifically, the system now supports fetching detailed client information (including name, city, phone, and photo), retrieving the current user's profile and email verification status, and generating an email verification link. These additions enable the application to query and display user profile data and email verification states directly from Firebase.
src/Loyalty.Domain.Handlers.Firebase.Queries/Queries · high confidence
Added query and command definitions for location, product, and purchase domains
This change introduces a new set of MediatR command and query classes to support location, product, and purchase domain operations. Specifically, it adds \CreateLocationCommand\ and \UpdateLocationCommand\ for managing location data, alongside several new queries for retrieving loyalty programs, product groups, and active purchases. These additions establish the request structures needed for the application's internal handlers to process these specific domain events and data retrieval requests.
(repo-wide) · high confidence
Added query for retrieving user profile by ID
A new query class, GetUserProfileByIdQuery, has been introduced to the UserProfile query namespace. This change adds the capability to fetch a user's profile data using a specific user identifier, supporting the existing MediatR-based request/response pattern.
src/Loyalty.Domain.Handlers.Queries/Queries/UserProfile · high confidence
Added query handlers for loyalty system data access
The system now includes a suite of new query handlers in the infrastructure layer that retrieve data from the database using Dapper. These include handlers for fetching user codes, loyalty programs, product groups, products, orders, and venue details, as well as a base handler for database access. Additionally, new entity classes and an event bus service interface were added to support the outbox pattern for integration events.
src/Loyalty.Infrastructure.Handlers · high confidence
Added query result models and build configuration files
The codebase now includes new query result models for retrieving loyalty product groups and rules, specifically GetLoyaltyProductGroupByIdQueryResult, GetLoyaltyProductGroupsQueryResult, GetRuleByIdQueryResult, and GetSingleRuleByIdQueryResult. Additionally, the project has been equipped with a new solution file (LoyaltyProgram.sln) and configuration files for NuGet package management (nuget.config) and code style enforcement (StyleCop.ruleset, stylecop.json).
src · high confidence
Added query result models for loyalty program data
Three new C\# classes have been introduced to structure loyalty program data for queries: GetLoyaltyProgramByIdQueryResult, which exposes program details like name, description, and publication status; and the collection wrappers GetLoyaltyProgramsQueryResult and GetLoyaltyProgramsByUserIdQueryResult, which return lists of these program objects. These models enable the application to retrieve and display loyalty program information to users.
src/Loyalty.Domain.Handlers.Queries/QueryResults/LoyaltyProgram · high confidence
Added repository implementations for core domain entities
The Loyalty.Infrastructure.Commands.Repository project now includes new repository classes for managing Loyalty Programs, Orders, Product Groups, Products, Purchases, Venues, and Workers. Each repository implements its corresponding interface and provides data access methods (such as GetAsync, AddAsync, and Update) backed by Entity Framework Core, enabling the application to persist and retrieve these domain aggregates.
src/Loyalty.Infrastructure.Commands.Repository · high confidence
Added shared contract enums for orders, venues, and user claims
The common contracts library now includes a new set of enumerations that define the structure for order processing, venue management, and user identity. Specifically, the change introduces \CustomClaimsConstants\ for user profile data, and a suite of enums including \LoyaltyRuleType\, \OrderPaymentType\, \OrderPickupType\, \OrderStatus\, \OrderVenueRate\, \ProductGroupIconType\, \ProductIconType\, \UserInteractionType\, \VenueApprovalStatus\, \VenueCategoryType\, \VenueType\, and \VenueUserRole\. These definitions provide the shared data types required for order and venue operations across the system.
common/Loyalty.Shared.Contracts · medium confidence
Added venue and order status domain models
Introduced new entity classes for the loyalty system: \LoyaltyGroupRule\ for managing loyalty program rules, a set of \OrderStatus\ classes (e.g., \PlacedOrder\, \ReadyOrder\, \FinishedOrder\) to define order lifecycle states, and several value objects for venues including \ContactInfo\, \Location\, \SocialNetworks\, and \VenueDetails\.
src/Loyalty.Core.Entities/Aggregates · high confidence
Added venue domain event handlers for lifecycle and update notifications
New domain event handlers have been introduced for the Venue aggregate, ensuring that key venue lifecycle events—creation, approval, acceptance changes, archiving, and updates to images, logos, and general details—are properly processed. Each handler listens for its respective domain event and publishes corresponding outbox notifications (e.g., WorkerAddedToVenueNotification, CreateVenueNotification, UpdateVenueNotification, PatchVenueApproveNotification, etc.) to the event bus, enabling downstream systems to react to venue state changes.
src/Loyalty.Application.DomainEvents.Handlers/Venues · high confidence
Added venue management commands
Introduced a new set of commands for managing venue data, including creating, updating, and patching venue details such as name, description, location, working hours, and social network links. The update also includes commands for approving, rejecting, archiving, and modifying venue images and logos, as well as handling order acceptance status for venues.
src/Loyalty.Domain.Handlers.Queries/Commands/Venue · high confidence
Added venue query models for admin and user retrieval
Three new query models were added to the venue domain: GetVenueByIdQuery for retrieving a single venue by ID, GetVenuesForAdminQuery for admin-level venue access, and GetVenuesQuery for retrieving venues associated with a specific user ID. These changes introduce the request side of the CQRS pattern for venue data access.
src/Loyalty.Domain.Handlers.Queries/Queries/Venue · high confidence
Added venue query result models
Introduced new C\# classes that define the structure of venue-related query results, including GetVenueByIdQueryResult, GetVenuesQueryResult, GetVenuesByUserIdQueryResult, GetSocialNetworksResult, GetVenueWorkingHoursQueryResult, and GetLocationQueryResult. These models represent the data returned by venue queries, containing fields such as name, description, location, social network links, and working hours.
src/Loyalty.Domain.Handlers.Queries/QueryResults/Product, src/Loyalty.Domain.Handlers.Queries/QueryResults/Venue · high confidence
Added view models and validators for the loyalty application
Introduced a comprehensive set of data transfer objects and validation rules for the loyalty system. New view models were added to represent core entities including clients, locations, products, purchases, and venues, alongside their corresponding FluentValidation validators to enforce data integrity.
src/Loyalty.Application.ViewModels · high confidence
Added worker management commands
New MediatR command classes have been introduced to support worker lifecycle operations, including creating workers (with and without venue association), updating worker details, archiving workers by UID or ID, and updating worker photos. These commands provide the necessary data structures for handling worker-related requests within the loyalty domain.
src/Loyalty.Domain.Handlers.Queries/Commands/Workers · high confidence
Added worker query handlers for retrieving worker data
Introduced new MediatR query classes for fetching worker information, including lookups by email, ID, phone, and user ID, as well as a general query to list workers by venue. These additions provide the underlying data access methods for worker-related operations.
src/Loyalty.Domain.Handlers.Queries/Queries/Worker · high confidence
Added worker query result models for loyalty system
New C\# classes have been introduced to represent worker data in the loyalty domain, including GetWorkerByIdQueryResult, GetWorkersQueryResult, GetWorkersByUserIdQueryResult, GetInviteByEmailQueryResult, GetInviteByPhoneQueryResult, and GetVenueWorkerResult. These models define the structure for retrieving worker information, including fields like ID, name, phone, email, photo URI, and associated venue roles, enabling the system to query and return worker details.
src/Loyalty.Domain.Handlers.Queries/QueryResults/Worker · high confidence
Adds shared extension methods for claims, HTTP requests, and environment detection
New extension methods are introduced in the shared library to simplify common operations. ClaimsPrincipal is extended with helpers to extract user identity, phone number, email, name, surname, city, avatar, and venue roles/IDs from security claims. HttpRequest gains a method to validate an admin secret header and a generic deserializer for request bodies. Environment detection is added to identify local, stage, or production deployments. Additional utilities include string splitting with quote unwrapping, enumerable-to-JSON serialization for service bus messages, and a helper to join strings with commas.
src/Loyalty.Common.Shared/Extensions · high confidence
Initial AutoMapper configuration for domain entities
The application introduces a new AutoMapper profile that establishes mapping rules for a wide range of domain entities, including venues, workers, products, loyalty programs, and purchases. This configuration bridges the gap between internal query results and external view models, enabling seamless data transformation for the loyalty system.
src/Loyalty.Application.AutoMapper · high confidence
Initial setup of the Loyalty Program Azure Function
The Loyalty Program service is introduced as a new Azure Function application. This includes the core startup configuration for dependency injection and Swagger documentation, along with WebJobs startup logic for Azure token validation and Application Insights telemetry processing. The service is configured with an 'api' route prefix, structured logging, and sampling for Application Insights. A .gitignore file is added to exclude build artifacts and sensitive local settings, while a local.settings.example.json template provides the necessary configuration keys for local development.
src/LoyaltyProgram · high confidence
Introduce command result abstractions and handler interfaces for loyalty products and programs
Added new domain contract classes (CommandResult, CommandNotificationResult) and their corresponding interfaces to standardize command execution outcomes and notification handling. Additionally, introduced interface definitions for command handlers managing the creation, update, and archiving of loyalty product groups and loyalty programs, establishing the contract layer for these specific operations.
src/Loyalty.Domain.Contracts, src/Loyalty.Domain.Handlers.Contracts · high confidence
Introduce new application services and DTOs for venue management and user interactions
Added a suite of new application services in the Venue module to handle core business logic for venues, products, orders, purchases, and users. This includes \LoyaltyVenueAppService\ for venue CRUD and image patching, \ProductAppService\ and \ProductGroupAppService\ for product management, \OrderAppService\ for order status updates, and \PurchaseAppService\ for handling purchase and burn operations. Additionally, \ClientInfoAppService\ and \CodeAppService\ provide user and purchase retrieval by code, while \LoyaltyProgramAppService\ manages loyalty programs. Supporting DTOs like \EmailInvitationDto\ and \PurchaseNotificationDto\ were added to the storage layer, and new interfaces \IDbContext\ and \ITenantProvider\ were introduced to support database and tenant context access.
src/Loyalty.Application.Venue · high confidence
Introduce new loyalty rule entity models
Added new entity classes for loyalty rules, including a base rule class and specific implementations for percentage-based calculations (fixed and range-based) and stamp-based rewards. These new models define the structure for different types of loyalty rules, each specifying compatible rule types and specific configuration properties.
src/Loyalty.Core.Entities/Rules · high confidence
Introduce notification handlers for product and worker events
Added new notification handlers to process specific domain events: a handler for product acceptance changes that updates venue order availability, and a handler for worker venue assignments that updates worker-venue relationships. These handlers utilize a new base notification handler and service bus topic interfaces to send messages via Azure Service Bus.
src/Loyalty.Infrastructure.Handlers.Notifications · high confidence
Introduced centralized dependency injection setup for database, service bus, and application services
The application now registers all core infrastructure services through a new set of extension methods in the DI layer. This includes configuring SQL connection strings and repository mappings for the database context, setting up Azure Service Bus clients for integration and user topics, binding configuration sections for settings like SMS and email, and registering application-level services such as venue, product, and order handlers. Additionally, third-party integrations including MediatR, AutoMapper, and logging are wired up, with a transactional behavior pipeline added for commands.
src/Loyalty.Infrastructure.IoC/DI · high confidence
Introduces core domain entities for the loyalty system
Adds new entity classes for managing loyalty programs, product groups, orders, purchases, venues, and workers. These include LoyaltyProgram, LoyaltyProductGroup, Order, OrderItem, Product, Purchase, Venue, and Worker aggregates, each with their respective domain events and validation logic.
Loyalty.Core.Entities · high confidence
Introduces scoped DbContext lifecycle and transactional context management
The data access layer now implements a custom scoped lifecycle for database contexts, ensuring that each HTTP request or function invocation receives a dedicated, reusable DbContext instance via a new \DbContextScoped\ wrapper and \ObjectStore\ cache. This change introduces \TransactionalContext\ to manage explicit database transactions and adds an \EmptyMediator\ stub, while defining the \ILoyaltyDbContext\ and \ILoyaltyTenantDbContext\ interfaces that map to specific entity sets for the loyalty system.
src/Loyalty.Infrastructure.DataAccess/Context · high confidence
New base interfaces for entity lifecycle and auditing
The codebase introduces four new base interfaces in the entity model: IArchivableEntity (with an IsArchived flag), IAuditableEntity (tracking Created/Modified timestamps and user IDs), IOrderable (an IsAvailableForOrder flag), and ITenantEntity (a TenantId). These interfaces provide a standardized contract for archiving, auditing, ordering, and multi-tenancy across entities.
src/Loyalty.Core.Entities/Base · high confidence
New commands for updating user profile and email
Added new MediatR command classes for updating a user's profile information and email address. The \UpdateUserProfileCommand\ allows updating a user's name and last name, while the \UpdateEmailCommand\ enables updating the email address and its verification status.
src/Loyalty.Domain.Handlers.Queries/Commands/UserProfile · high confidence
New configuration settings for image, email, and messaging services
Added new settings classes to the application's configuration layer, introducing structured options for database connections, email templates and domains, Google authentication, image storage and dimensions, Service Bus queues, SMS host and tokens, Swagger endpoints, and venue limits. These changes allow the system to externalize and manage configuration for these specific services.
src/Loyalty.Common.Shared/Settings · high confidence
New notification types for orders, interactions, and codes
The system now supports new notification events for order lifecycle changes (creation and updates), user interactions, and generated codes. Users will receive notifications when an order is created or modified, when a user interaction occurs, and when a code is generated, enabling real-time updates for these specific events.
common/LoyaltyClient.Domain.Handlers.Notifications · medium confidence
New repository interfaces for domain aggregates
Added repository interfaces for LoyaltyProgram, Order, ProductGroup, Product, Purchase, VenueAdmin, Venue, and Worker aggregates. These interfaces define the data access contracts for each entity, enabling the implementation of persistence logic for these core business objects.
src/Loyalty.Core.Entities/Interfaces · high confidence
Architecture
Added solution file for common project
A new solution file, Loyalty.Venue.Common.sln, has been added to the common directory. This file defines the build configuration for three specific projects: Loyalty.Shared.Contracts, Loyalty.Domain.Handlers.Notifications, and LoyaltyClient.Domain.Handlers.Notifications.
common · high confidence
Behavioural changes
Added database entity configurations for loyalty domain aggregates
The data access layer now includes Entity Framework Core configuration classes for a new set of loyalty domain entities. New mappings have been added for LoyaltyGroupRule, LoyaltyProductGroup, LoyaltyProgram, Order, OrderItem, Product, ProductGroup, Purchase, Venue, VenueWorker, and Worker. These configurations define table names within the 'Loyalty' schema, primary keys, unique indexes, and relationships such as the one-to-many between Venue and its ProductGroups and LoyaltyPrograms.
src/Loyalty.Infrastructure.DataAccess/EntityConfigurations · high confidence
Added domain event handlers for loyalty product group lifecycle events
Implemented new domain event handlers for the LoyaltyProductGroups module, enabling the system to react to the creation, update, and archival of loyalty product groups. These handlers listen for corresponding domain events and persist notifications to the event bus, ensuring that external systems are notified of these state changes.
src/Loyalty.Application.DomainEvents.Handlers/LoyaltyProductGroups · high confidence
Added error code and claim constants for validation and state management
The application now defines a centralized set of error codes and claim identifiers to standardize error handling and state management across the loyalty system. New constants include specific error codes for scenarios such as limit reached, duplicated entities, incorrect product or loyalty group references, and venue-related states (e.g., approval, publishing, and order states). Additionally, new claim constants for 'venues' and 'new\_venue' are introduced to support identity or permission checks. These changes ensure consistent error messaging and state validation throughout the shared components.
src/Loyalty.Common.Shared/Constants · high confidence
Added image validation logic for various entity types
The system now enforces image validation rules for product photos, venue images, venue logos, and worker photos. This includes checks for file size (up to 1 MB), format (PNG or JPG), and specific width/height constraints for each entity type, ensuring uploaded images meet the required specifications.
src/Loyalty.Application.Storage.Dto/Validators · high confidence
Added product command DTOs for the MediatR pipeline
New command classes have been introduced in the product domain to handle product lifecycle operations via the MediatR framework. Specifically, ArchiveProductCommand, CreateProductCommand, PatchProductCommand, PatchProductImageCommand, and UpdateProductCommand have been added. These DTOs define the input contracts for creating, updating, patching, archiving, and updating product images, enabling the application to process these product management requests through the existing command handler pipeline.
src/Loyalty.Domain.Handlers.Queries/Commands/Products · high confidence
Added product group domain event handlers
New domain event handlers have been added for product group lifecycle events: archiving a product group now archives all associated products; changing a product group's visibility state now updates the visibility of all associated products; and updating a product group now publishes notifications to update each associated product's icon and name.
src/Loyalty.Application.DomainEvents.Handlers/ProductGroup · high confidence
Added script to clear all application data
A new SQL script, delete\_all\_data.sql, has been added to the scripts directory. This script executes DELETE statements against multiple tables across the client and loyalty schemas, including Card, ProductGroup, Venue, Worker, UserProfile, and UserCode, effectively clearing all stored data.
scripts · high confidence
Added transactional command handling with automatic commit/rollback
A new base handler and a MediatR pipeline behavior were added to the command handling layer. The \BaseHandler\ provides a shared interface for command handlers, injecting the database context and HTTP principal. The \TransactionBehaviour\ pipeline behavior wraps each command in a database transaction, automatically committing on success or rolling back on failure, and publishes outbox events after a successful transaction. This ensures that command execution is atomic and consistent with the application's event-driven architecture.
src/Loyalty.Infrastructure.Handlers.Commands/Pipelines · medium confidence
Custom App Insights telemetry processing and user context enrichment
The application now filters out low-latency dependency telemetry and enriches request telemetry with user identity and profile data. A new MyTelemetryProcessor is introduced to discard DependencyTelemetry items with a duration under 200ms, reducing noise in Application Insights. Additionally, a TelemetryInitializer adds user-specific properties (City, Phone, Role) to request telemetry when available from the HTTP context, enabling better tracking of user attributes in logs.
src/Loyalty.Infrastructure.Logging.AppInsights · medium confidence
Initial database schema for the loyalty platform
The database schema is initialized with tables for venues, workers, orders, and loyalty programs, establishing the core data model for the loyalty system.
src/Loyalty.Infrastructure.DataAccess/Migrations · high confidence
Test coverage
Added AuthUser test helper for Firebase authentication; Added availability tests for the loyalty program API; Added functional tests for venue and worker management; Added test data factories for loyalty program entities; Added test data factories for the loyalty program; Added test fixtures and integration tests for the Loyalty Program; Added test infrastructure and configuration; Added tests for Loyalty, Product, and ProductGroup management.
Dependencies
Updated .NET and NuGet dependencies across the solution
The project files have been updated to use .NET Standard 2.1 and .NET Core 3.1 as the target frameworks. Key package references have been upgraded, including MediatR to 8.0.1, AutoMapper to 10.0.0, and Microsoft.EntityFrameworkCore to 3.1.8. Additional dependencies such as FirebaseAdmin, Serilog, and various Azure SDKs have also been updated to their latest compatible versions.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 60 → 57 (-2.9)
- Rubric changed (rubric-2026.08.18 → rubric-2026.09.15) — scores are not directly comparable.
Lenses
- Code Health 59 → 53 (-5.8)
- Architecture 84 → 84 (-0.0)
- Maturity 77 → 77 (+0.0)
- Readiness 75 → 75 (-0.1)
- Security 86 → 79 (-6.3)
- Domain Modelling 50 → 46 (-3.8)
- Event-Driven 100 (new)
Resolved (16)
- Bounded contexts not declared
- Build status unknown
- Duplicated block (11 lines × 2) (src/Loyalty.Application.ViewModels/Validators/Venue/CreateVenueValidator.cs)
- Duplicated block (11 lines × 2) (src/LoyaltyProgram/Http/Write/Admin/VenueApprovePatchFunction.cs)
- Duplicated block (13 lines × 3) (src/Loyalty.Application.Storage.Dto/Validators/VenueImageValidator.cs)
- Duplicated block (19 lines × 2) (src/Loyalty.Application.Storage.Dto/Validators/VenueLogoValidator.cs)
- Duplicated block (8 lines × 2) (src/Loyalty.Application.ViewModels/Validators/Venue/CreateVenueValidator.cs)
- Duplicated block (9 lines × 2) (src/LoyaltyProgram/Http/Write/VenueImages/VenueCreateImageFunction.cs)
- Inconsistent Naming and Structure: ICommandNotificationResult is an interface that duplicates the structure of CommandResult but with different naming conventions (e.g., OnSuccessNotifications, OnFailNotifications). This suggests a lack of clear distinction between the result of a command and the notification of its outcome.
- LLM evaluation failed
- Low cohesion: LoyaltyVenueImageAppService (LCOM4 5) (src/Loyalty.Application.Venue/LoyaltyVenueImageAppService.cs)
- Monorepo: only 1 of 2 solutions was scored
- Redundant/Overlapping Types: CommandNotificationResult appears to be a wrapper around CommandResult (it has a CommandResult property) but also duplicates the Success, Message, and Result properties directly. This creates confusion about whether consumers should use CommandResult or CommandNotificationResult, and why both exist.
- Tests co-located / outside the solution
- redundant comment (src/Loyalty.Infrastructure.DataAccess/Context/Scoped/ObjectStore.cs)
- single-maintainer — knowledge-concentration (bus factor) risk
New (77)
- Boundary-crossing change coupling: AutoMapperProfile.cs ↔ UpdateVenueCommandHandler.cs (src/Loyalty.Application.AutoMapper/AutoMapperProfile.cs)
- Boundary-crossing change coupling: CreateVenueViewModel.cs ↔ UpdateVenueCommandHandler.cs (src/Loyalty.Application.ViewModels/Venue/CreateVenueViewModel.cs)
- Change coupling: CreateLoyaltyProgramCommandHandler.cs ↔ UpdateLoyaltyProgramCommandHandler.cs (src/Loyalty.Infrastructure.Handlers.Commands/Commands/LoyaltyPrograms/CreateLoyaltyProgramCommandHandler.cs)
- Change-coupling hub: VenueGetAllFunction.cs → VenueGetFunction.cs, VenueDeleteFunction.cs, VenuePostFunction.cs, VenuePutFunction.cs (src/LoyaltyProgram/Http/Read/Venue/VenueGetAllFunction.cs)
- Change-coupling hub: VenueGetFunction.cs → VenueDeleteFunction.cs, VenuePostFunction.cs, VenuePutFunction.cs (src/LoyaltyProgram/Http/Read/Venue/VenueGetFunction.cs)
- CommentedOutCode (src/Loyalty.Core.Entities/Aggregates/ProductGroups/ProductGroup.cs)
- CommentedOutCode (src/LoyaltyProgram/Startup.cs)
- Documentation: no installation or build instructions (README.md)
- Documentation: no licence statement (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (10 lines × 2) (src/LoyaltyProgram/Http/Write/VenueImages/VenueCreateImageFunction.cs)
- Duplicated block (11 lines × 2) (src/LoyaltyProgram/Http/Write/Admin/VenueApprovePatchFunction.cs)
- Duplicated block (11 lines × 3) (src/Loyalty.Application.Storage.Dto/Validators/VenueImageValidator.cs)
- Duplicated block (13 lines × 2) (src/Loyalty.Domain.Handlers.Queries/QueryResults/Orders/GetOrderByUserIdQueryResult.cs)
- Duplicated block (13 lines × 3) (src/Loyalty.Application.Storage.Dto/Validators/VenueImageValidator.cs)
- Duplicated block (14 lines × 3) (src/Loyalty.Application.ViewModels/Venue/CreateVenueViewModel.cs)
- Duplicated block (16 lines × 2) (src/Loyalty.Application.ViewModels/Product/CreateProductViewModel.cs)
- Duplicated block (17 lines × 2) (src/Loyalty.Application.ViewModels/LoyaltyProductGroup/LoyaltyProductGroupGetViewModel.cs)
- Duplicated block (18 lines × 2) (src/Loyalty.Application.ViewModels/Venue/CreateVenueViewModel.cs)
- Duplicated block (18–21 lines × 2) (src/Loyalty.Infrastructure.Firebase.Handlers/Notifications/SetupFirebaseTokenNotificationHandler.cs)
- …and 57 more
Architecture
- Unchanged — 1 containers · 1 contexts · 0 edges
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
richardchanjr90-cpu/ddd-by-example was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 21 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit 495458f3b45146be55076fadaf329257a1ea0bab — the exact code this score is about.
- Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-28e75b8e3254.