# milosmrsovic/competitor-price-automation architecture

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

- Interactive diagram: https://gitdiagram.com/milosmrsovic/competitor-price-automation
- Repository: https://github.com/milosmrsovic/competitor-price-automation

## Overview

This repository demonstrates scheduled competitor-price monitoring and automated product repricing. The principal workflow collects regional market offers, filters and records them, computes a median, then lets n8n compare it with the current price and either request an update or notify that no change is needed. A Flask page demonstrates the resulting price. The README documents the n8n stages and email integration; the workflow JSON is present in the tree, but its contents were not sampled, so those stages are represented only as documented.

Main entry points: [`main.py`](https://github.com/milosmrsovic/competitor-price-automation/blob/main/main.py) (FastAPI service), [`CompetitionWorkflown8n.json`](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json) (5% decision), [`check_competiton.py`](https://github.com/milosmrsovic/competitor-price-automation/blob/main/check_competiton.py) (Competitor collector), [`Web_Example/product_data.json`](https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/product_data.json) (Product data JSON)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_orchestration["Workflow orchestration"]
  node_scheduler(("Schedule trigger"))
  node_normalize["Normalize values"]
  node_difference["Calculate difference"]
  node_threshold{{"5% decision"}}
  node_update_notice["Update email"]
  node_aligned_notice["Aligned email"]
end

subgraph group_market["Market data collection"]
  node_collector["Competitor collector"]
  node_filter["Offer filtering"]
  node_prices_csv[("Price results CSV")]
end

subgraph group_pricing["Price service and state"]
  node_api["FastAPI service<br/>[main.py]"]
  node_product_json[("Product data JSON<br/>[product_data.json]")]
  node_median["Median calculation<br/>[main.py]"]
end

subgraph group_display["Product display"]
  node_flask["Flask product page<br/>[app.py]"]
  node_template["Product view<br/>[product.html]"]
end

node_serpapi["SerpAPI Shopping"]
node_browser(("Store visitor"))
node_email["Email provider"]

node_scheduler -->|"requests GET"| node_api
node_api -->|"runs script"| node_collector
node_collector -->|"reads product"| node_product_json
node_collector -->|"searches regions"| node_serpapi
node_collector -->|"validates offers"| node_filter
node_filter -->|"writes offers"| node_prices_csv
node_api -->|"reads prices"| node_prices_csv
node_api -->|"calculates median"| node_median
node_api -->|"reads current price"| node_product_json
node_api -->|"returns price data"| node_normalize
node_normalize -->|"passes numbers"| node_difference
node_difference -->|"passes difference"| node_threshold
node_threshold -->|"requests POST update"| node_api
node_api -->|"saves new price"| node_product_json
node_threshold -->|"above threshold"| node_update_notice
node_threshold -->|"at or below"| node_aligned_notice
node_update_notice -->|"sends update"| node_email
node_aligned_notice -->|"sends status"| node_email
node_browser -->|"requests page"| node_flask
node_flask -->|"reads product"| node_product_json
node_flask -->|"renders page"| node_template

click node_scheduler "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_normalize "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_difference "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_threshold "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_update_notice "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_aligned_notice "https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json"
click node_api "https://github.com/milosmrsovic/competitor-price-automation/blob/main/main.py"
click node_collector "https://github.com/milosmrsovic/competitor-price-automation/blob/main/check_competiton.py"
click node_filter "https://github.com/milosmrsovic/competitor-price-automation/blob/main/check_competiton.py"
click node_product_json "https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/product_data.json"
click node_median "https://github.com/milosmrsovic/competitor-price-automation/blob/main/main.py"
click node_flask "https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/app.py"
click node_template "https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/templates/product.html"

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_scheduler,node_normalize,node_difference,node_threshold,node_update_notice,node_aligned_notice toneBlue
class node_collector,node_filter,node_prices_csv toneAmber
class node_api,node_product_json,node_median,node_serpapi toneMint
class node_flask,node_template toneRose
class node_browser,node_email toneIndigo
```

## Components

### Workflow orchestration

- [Schedule trigger](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`
- [Normalize values](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`
- [Calculate difference](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`
- [5% decision](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`
- [Update email](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`
- [Aligned email](https://github.com/milosmrsovic/competitor-price-automation/blob/main/CompetitionWorkflown8n.json): `CompetitionWorkflown8n.json`

### Market data collection

- [Competitor collector](https://github.com/milosmrsovic/competitor-price-automation/blob/main/check_competiton.py): `check_competiton.py`
- [Offer filtering](https://github.com/milosmrsovic/competitor-price-automation/blob/main/check_competiton.py): `check_competiton.py`
- **Price results CSV**

### Price service and state

- [FastAPI service](https://github.com/milosmrsovic/competitor-price-automation/blob/main/main.py): `main.py`
- [Product data JSON](https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/product_data.json): `Web_Example/product_data.json`
- [Median calculation](https://github.com/milosmrsovic/competitor-price-automation/blob/main/main.py): `main.py`

### Product display

- [Flask product page](https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/app.py): `Web_Example/app.py`
- [Product view](https://github.com/milosmrsovic/competitor-price-automation/blob/main/Web_Example/templates/product.html): `Web_Example/templates/product.html`

### Other components

- **SerpAPI Shopping**
- **Store visitor**
- **Email provider**

## Connections

- Schedule trigger → FastAPI service: requests GET
- FastAPI service → Competitor collector: runs script
- Competitor collector → Product data JSON: reads product
- Competitor collector → SerpAPI Shopping: searches regions
- Competitor collector → Offer filtering: validates offers
- Offer filtering → Price results CSV: writes offers
- FastAPI service → Price results CSV: reads prices
- FastAPI service → Median calculation: calculates median
- FastAPI service → Product data JSON: reads current price
- FastAPI service → Normalize values: returns price data
- Normalize values → Calculate difference: passes numbers
- Calculate difference → 5% decision: passes difference
- 5% decision → FastAPI service: requests POST update
- FastAPI service → Product data JSON: saves new price
- 5% decision → Update email: above threshold
- 5% decision → Aligned email: at or below
- Update email → Email provider: sends update
- Aligned email → Email provider: sends status
- Store visitor → Flask product page: requests page
- Flask product page → Product data JSON: reads product
- Flask product page → Product view: renders page
