Project Overview: The Loyalty Points Program and an Architecture Overview of All 32 Areas
Project Overview: The Loyalty Points Program and an Architecture Overview of All 32 Areas
~9 Min. Lesezeit Zuletzt aktualisiert am August 9, 2026
This series has an unusual goal: not to explain a single Magento 2 feature, but literally every type of building block a custom Magento 2 module can be made of - model and resource model, EAV entities, custom attributes on product, category, customer, company, and order, observers and cron, plugins and preferences, controllers and routers, blocks and view models, widgets and Page Builder, custom payment and shipping methods, a custom product type, REST and GraphQL APIs, configuration types, translations, and unit tests. 32 areas, 106 chapters, 12 blocks - and one single, continuous example project that needs all of it without feeling contrived.
The business scenario: Mironsoft Loyalty & Rewards
The example project is called Mironsoft Loyalty & Rewards: a loyalty points and rewards program for a Magento 2 shop. Customers earn points on every purchase, at rates that vary by product, category, and - for B2B customers - company tier. They see their point balance in their customer account, redeem points for rewards (discount vouchers, free products, free shipping), or use points as partial payment at checkout. A daily cron job expires old points and recalculates loyalty tiers (bronze, silver, gold).
This single feature was chosen deliberately because it organically requires every one of the 32 requested module areas - none of them are bolted on just to check a box. A reward with variable properties needs an EAV entity. Points-per-product needs a product attribute. Point expiry needs cron. Partial payment with points needs a custom payment method. And so on - every chapter builds on the same Mironsoft\Loyalty module.
Achtung: Mironsoft\Loyalty is a pure tutorial example for this series. There is no corresponding implementation under app/code/Mironsoft/Loyalty/ in the real mironsoft project - the code in the following chapters is complete and runnable, but deliberately kept as a standalone learning project, not an extension of the production shop.
Architecture overview: all 32 areas and where they show up
The rest of this chapter maps all 32 requested module areas onto this series' twelve blocks - as a signpost, not a full explanation. Every area gets its own dedicated chapter later on.
Data, configuration, cache, and CLI (Block 1, this block)
Block 1 lays the foundation: a plain database table, on top of it a model, resource model, collection, and repository, a custom configuration page, a custom cache type, and a console command.
- Model (chapter 4): the classic model/resource model/collection trio for the points ledger.
- System/Config/Setting (chapter 7): a custom configuration page under Stores > Configuration with points-per-euro, expiry time, and tier thresholds.
- Cache (chapter 8): a custom cache type for the reward catalog, populated starting in block 2.
- Console Command (chapter 9): a CLI command for manual points recalculation and ledger auditing.
The reward entity as EAV (Block 2)
A reward has variable, extensible properties - the classic use case for a custom EAV entity, following the same pattern as catalog_product_entity.
- EAV Entity (chapters 10-18): the complete reward entity with entity and attribute tables, model, collection, and admin grid.
- EAV Attribute, custom (chapters 13-14): custom attributes such as
points_cost,discount_value, andreward_typedefined via a setup script.
Attributes on existing entities (Block 3)
Points need to attach to products, categories, customers, companies, and orders - five different attribute types on five different core entities.
- Product Attribute (chapter 19):
loyalty_points_multiplieron the product. - Category Attribute (chapter 20): a bonus multiplier per category.
- Customer Attribute (chapter 21): point balance and loyalty tier on the customer.
- Company Attribute (chapter 22): B2B special conditions on the company (
Magento_Company). - Sales Attribute (chapter 23): points earned stored on order and order item.
Events, observers, and cron (Block 4)
Points aren't awarded synchronously inside checkout code, but reactively via events - and daily expiry runs through a dedicated cron group.
- Observer/Event (chapters 29-31, 35-36): awarding points on order placement, reversing them on credit memos, and dispatching custom events for other modules.
- Crongroup (chapter 32): a dedicated
mironsoft_loyaltycron group with its own run frequency. - Cronjob (chapter 33): the daily job for point expiry and tier recalculation.
Plugins, preferences, and helpers (Block 5)
Sometimes observing events isn't enough - the checkout discount from points has to actively hook into an existing calculation.
- Plugin (chapters 38-39): an interceptor on the checkout totals collector that applies the points discount.
- Preference/Rewrite (chapters 40-42): when a preference is needed instead of a plugin, shown on a custom points calculation.
- Helper (chapter 44): when a classic helper class still makes sense despite the ViewModel preference (legacy compatibility).
Controllers, routers, and frontend display (Block 6)
Customers need a visible interface: a points history page and a reward catalog under their own, readable URL.
- Controller (chapters 45, 50): the points history page and the redeem controller for redeeming a reward.
- Router (chapter 46): a custom router for URLs under
/treuepraemien/and/rewards/respectively. - Block (chapter 47): a direct comparison of block class versus view model in practice.
- Viewmodel (chapter 48): the view model for the point balance on the account page.
Widget and Page Builder (Block 7)
- Widget (chapters 55-57): a "My Points" widget for CMS pages with admin-configurable parameters.
- PageBuilder Content Type (chapters 58-60): a custom "points banner" content type with a preview template.
Payment and shipping methods (Block 8)
- Payment Method (chapters 62-65): "Redeem points" as a custom payment method for partial payment at checkout.
- Shipping Method (chapters 66-69): "Free shipping via points" as a custom shipping method with its own rate calculation.
A custom product type (Block 9)
- Product Type (chapters 71-78): a "points package" product type that lets customers buy points directly - from
etc/product_types.xmlall the way through order processing.
API and GraphQL (Block 10)
- Api (chapters 79-81): a custom REST API for point balance and reward redemption, secured via ACL.
- GraphQl Endpoint (chapters 82-83): querying point balance and reward catalog via GraphQL, redeeming a reward via mutation.
- Customer(Section) Data (chapter 84): the point balance live in the mini cart and checkout via AJAX (customer section data).
Configuration types, translations, and tests (Block 11)
- Configuration Type (chapter 88): custom config types beyond System/Config.
- Language (chapters 89-90): custom i18n CSV files for store views and the admin interface.
- Unit Test (chapters 91-95): the
PointsCalculatorservice as the target for unit tests, mocking repositories, integration tests, coverage, and CI.
Putting it all together (Block 12)
Block 12 introduces no new areas - instead it shows how all 32 building blocks work together in a single module: module dependencies, deployment sequence, performance and security considerations, a troubleshooting guide, and a cheat sheet covering all 32 areas for quick reference.
Tipp: This overview doesn't need to stick on first read - it's meant as a map to come back to whenever a later chapter uses a term that hasn't been explained yet. Chapter 2 goes straight into the module skeleton that every following block needs.