# levhryhoriev/prostor-test architecture

> Architecture diagram of the GitHub repository levhryhoriev/prostor-test, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-09-27). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/levhryhoriev/prostor-test
- Repository: https://github.com/levhryhoriev/prostor-test

## Overview

Prostor_CumDiscount is a Magento 2 module that applies a separate cumulative cart discount to eligible products for signed-in customers. During quote-total collection, it reads website configuration, gets the customer’s 90-day loyalty spend (using a cache before the API), selects a threshold, excludes marked products, and calculates the total. Magento then exposes that total to the cart display. The README documents graceful no-discount behavior on failures. The graph uses sampled collector/client code and README-described caching; unsampled module links are limited to supported roles and paths.

Main entry points: [`src/app/code/Prostor/CumDiscount/Model/Quote/Address/Total/Cumulative.php`](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Quote/Address/Total/Cumulative.php) (Cumulative collector), [`src/app/code/Prostor/CumDiscount/Model/Loyalty/CacheBackedLoyaltySnapshotProvider.php`](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/CacheBackedLoyaltySnapshotProvider.php) (Snapshot provider), [`src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltyHttpClient.php`](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltyHttpClient.php) (Loyalty HTTP client), [`src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfig.php`](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfig.php) (Loyalty configuration)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_discount["Cart discount"]
  node_collector["Cumulative collector<br/>[Cumulative.php]"]
  node_thresholds["Threshold table<br/>[ThresholdTable.php]"]
  node_calculator["Discount calculator"]
end

subgraph group_loyalty["Loyalty spend"]
  node_snapshot_provider["Snapshot provider"]
  node_cache[("Loyalty cache<br/>[Type.php]")]
  node_http_client["Loyalty HTTP client"]
  node_parser["Snapshot parser"]
end

subgraph group_settings["Configuration"]
  node_config["Loyalty configuration<br/>[LoyaltyConfig.php]"]
  node_config_mapper["Configuration mapper"]
  node_admin["Admin settings<br/>[system.xml]"]
end

subgraph group_product["Product eligibility"]
  node_excluded["Excluded product lookup"]
  node_attribute["Exclusion attribute setup"]
end

subgraph group_presentation["Cart presentation"]
  node_cart_ui["Cart total display<br/>[cumulative.js]"]
  node_cart_template["Cart total template<br/>[cumulative.html]"]
end

node_shopper(("Signed-in shopper"))
node_magento["Magento quote totals"]
node_loyalty_api["Loyalty API"]
node_products[("Magento product catalog")]
node_loyalty_mock["Local loyalty mock<br/>[server.php]"]

node_shopper -->|"updates cart"| node_magento
node_magento -->|"collects totals"| node_collector
node_collector -->|"reads settings"| node_config
node_collector -->|"requests spend"| node_snapshot_provider
node_collector -->|"checks products"| node_excluded
node_collector -->|"selects rate"| node_thresholds
node_collector -->|"calculates discount"| node_calculator
node_collector -->|"adds cart total"| node_magento
node_config -->|"maps settings"| node_config_mapper
node_admin -->|"sets options"| node_config
node_snapshot_provider -->|"reads and writes"| node_cache
node_snapshot_provider -->|"fetches on miss"| node_http_client
node_http_client -->|"parses response"| node_parser
node_http_client -->|"requests spend"| node_loyalty_api
node_loyalty_api -->|"returns snapshot"| node_snapshot_provider
node_loyalty_mock -.->|"serves locally"| node_loyalty_api
node_excluded -->|"reads attribute"| node_products
node_attribute -->|"defines attribute"| node_products
node_magento -->|"provides total"| node_cart_ui
node_cart_ui -->|"renders total"| node_cart_template

click node_collector "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Quote/Address/Total/Cumulative.php"
click node_thresholds "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Discount/ThresholdTable.php"
click node_calculator "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Discount/DiscountCalculator.php"
click node_config "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfig.php"
click node_config_mapper "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfigurationMapper.php"
click node_admin "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/etc/adminhtml/system.xml"
click node_snapshot_provider "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/CacheBackedLoyaltySnapshotProvider.php"
click node_cache "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Cache/Type.php"
click node_http_client "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltyHttpClient.php"
click node_parser "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltySnapshotPayloadParser.php"
click node_excluded "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Quote/PromoExcludedProductIds.php"
click node_attribute "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Setup/Patch/Data/AddPromoExcludedProductAttribute.php"
click node_cart_ui "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/view/frontend/web/js/view/cart/totals/cumulative.js"
click node_cart_template "https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/view/frontend/web/template/cart/totals/cumulative.html"
click node_loyalty_mock "https://github.com/levhryhoriev/prostor-test/blob/main/docker/loyalty-mock/server.php"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_collector,node_thresholds,node_calculator toneBlue
class node_snapshot_provider,node_cache,node_http_client,node_parser,node_products toneAmber
class node_config,node_config_mapper,node_admin,node_loyalty_api toneMint
class node_excluded,node_attribute toneRose
class node_cart_ui,node_cart_template,node_shopper,node_magento toneIndigo
class node_loyalty_mock toneTeal
```

## Components

### Cart discount

- [Cumulative collector](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Quote/Address/Total/Cumulative.php): `src/app/code/Prostor/CumDiscount/Model/Quote/Address/Total/Cumulative.php`
- [Threshold table](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Discount/ThresholdTable.php): `src/app/code/Prostor/CumDiscount/Model/Discount/ThresholdTable.php`
- [Discount calculator](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Discount/DiscountCalculator.php): `src/app/code/Prostor/CumDiscount/Model/Discount/DiscountCalculator.php`

### Loyalty spend

- [Snapshot provider](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/CacheBackedLoyaltySnapshotProvider.php): `src/app/code/Prostor/CumDiscount/Model/Loyalty/CacheBackedLoyaltySnapshotProvider.php`
- [Loyalty cache](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Cache/Type.php): `src/app/code/Prostor/CumDiscount/Model/Cache/Type.php`
- [Loyalty HTTP client](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltyHttpClient.php): `src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltyHttpClient.php`
- [Snapshot parser](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltySnapshotPayloadParser.php): `src/app/code/Prostor/CumDiscount/Model/Loyalty/LoyaltySnapshotPayloadParser.php`

### Configuration

- [Loyalty configuration](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfig.php): `src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfig.php`
- [Configuration mapper](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfigurationMapper.php): `src/app/code/Prostor/CumDiscount/Model/Config/LoyaltyConfigurationMapper.php`
- [Admin settings](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/etc/adminhtml/system.xml): `src/app/code/Prostor/CumDiscount/etc/adminhtml/system.xml`

### Product eligibility

- [Excluded product lookup](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Model/Quote/PromoExcludedProductIds.php): `src/app/code/Prostor/CumDiscount/Model/Quote/PromoExcludedProductIds.php`
- [Exclusion attribute setup](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/Setup/Patch/Data/AddPromoExcludedProductAttribute.php): `src/app/code/Prostor/CumDiscount/Setup/Patch/Data/AddPromoExcludedProductAttribute.php`

### Cart presentation

- [Cart total display](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/view/frontend/web/js/view/cart/totals/cumulative.js): `src/app/code/Prostor/CumDiscount/view/frontend/web/js/view/cart/totals/cumulative.js`
- [Cart total template](https://github.com/levhryhoriev/prostor-test/blob/main/src/app/code/Prostor/CumDiscount/view/frontend/web/template/cart/totals/cumulative.html): `src/app/code/Prostor/CumDiscount/view/frontend/web/template/cart/totals/cumulative.html`

### Other components

- **Signed-in shopper**
- **Magento quote totals**
- **Loyalty API**
- **Magento product catalog**
- [Local loyalty mock](https://github.com/levhryhoriev/prostor-test/blob/main/docker/loyalty-mock/server.php): `docker/loyalty-mock/server.php`

## Connections

- Signed-in shopper → Magento quote totals: updates cart
- Magento quote totals → Cumulative collector: collects totals
- Cumulative collector → Loyalty configuration: reads settings
- Cumulative collector → Snapshot provider: requests spend
- Cumulative collector → Excluded product lookup: checks products
- Cumulative collector → Threshold table: selects rate
- Cumulative collector → Discount calculator: calculates discount
- Cumulative collector → Magento quote totals: adds cart total
- Loyalty configuration → Configuration mapper: maps settings
- Admin settings → Loyalty configuration: sets options
- Snapshot provider → Loyalty cache: reads and writes
- Snapshot provider → Loyalty HTTP client: fetches on miss
- Loyalty HTTP client → Snapshot parser: parses response
- Loyalty HTTP client → Loyalty API: requests spend
- Loyalty API → Snapshot provider: returns snapshot
- Local loyalty mock → Loyalty API: serves locally
- Excluded product lookup → Magento product catalog: reads attribute
- Exclusion attribute setup → Magento product catalog: defines attribute
- Magento quote totals → Cart total display: provides total
- Cart total display → Cart total template: renders total
