Big Data project for centralized procurement using Hadoop, Presto, and Apache Airflow
A production-ready data pipeline that processes Point-of-Sale (POS) orders and warehouse stock data to generate optimized supplier orders. Built with Hadoop HDFS for distributed storage, Presto for federated queries, PostgreSQL for master data, and Apache Airflow for orchestration.
- Features
- Architecture
- Technologies
- Project Structure
- Quick Start
- Usage Guide
- Data Flow
- Pipeline Details
- Monitoring & Access
- Analysis Tools
- Troubleshooting
- Contributing
- π Centralized Procurement: Single replenishment rule per SKU across all warehouses
- π Big Data Storage: HDFS-based data lake for scalable storage
- π Federated Queries: Presto joins HDFS data with PostgreSQL master data
- β° Batch Orchestration: Apache Airflow DAG scheduling (daily at 22:00)
- β Data Quality: Automated validation checks (supplier mapping, demand spikes, duplicates)
- π Exception Logging: Comprehensive fault tracking and reporting
- π³ Fully Dockerized: One-command deployment with 9 containerized services
- π Historical Audit: Date-partitioned data preservation
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β DATA SOURCES β
βββββββββββββββββββ¬ββββββββββββββββββββ¬βββββββββββββββββββββββββββββββ€
β POS Systems β Warehouse Stock β PostgreSQL Master Data β
β (5 stores) β (3 warehouses) β β’ Products (100 SKUs) β
β Daily Orders β Daily Snapshots β β’ Suppliers (10) β
ββββββββββ¬βββββββββ΄βββββββββ¬βββββββββββ΄βββββββββββ¬ββββββββββββββββββββ
β β β
βΌ βΌ βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β STORAGE LAYER β
ββββββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ€
β HDFS Data Lake β PostgreSQL OLTP β
β β’ /raw/orders/YYYY-MM-DD/ β β’ products β
β β’ /raw/stock/YYYY-MM-DD/ β β’ suppliers β
β β’ /processed/ β β’ warehouses β
β β’ /output/ β β’ replenishment_rules β
β β’ /logs/ β β’ supplier_products β
ββββββββββββββ¬ββββββββββββββββββββ΄ββββββββββββββββ¬βββββββββββββββββββββ
β β
ββββββββββββββββββ¬ββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β QUERY ENGINE β
β Presto (Distributed SQL) β
β β’ Hive Connector β HDFS β
β β’ PostgreSQL Connector β Master Data β
β β’ Federated JOIN across data sources β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ORCHESTRATION LAYER β
β Apache Airflow β
β β’ Scheduled DAG (daily 22:00) β
β β’ 6 Task Pipeline β
β β’ Retries & Alerts β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββ
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β OUTPUT β
β Supplier Orders (CSV) β
β β’ /data/output/supplier_orders/ β
β β’ HDFS: /procurement/output/supplier_orders/ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
| Service | Container | Port | Description |
|---|---|---|---|
| PostgreSQL | procurement_postgres |
5433 | Master data (products, suppliers, rules) |
| HDFS NameNode | namenode |
9870, 9000 | HDFS metadata & coordination |
| HDFS DataNode | datanode |
- | HDFS block storage |
| HDFS Client | hadoop_client |
- | CLI access with volume mounts |
| Presto | presto |
8080 | Distributed SQL query engine |
| Airflow DB | airflow_postgres |
5434 | Airflow metadata storage |
| Airflow Webserver | airflow_webserver |
8081 | Web UI (admin/admin) |
| Airflow Scheduler | airflow_scheduler |
- | Task scheduling & execution |
| Airflow Init | airflow_init |
- | One-time DB setup (exits) |
- Hadoop HDFS 3.2.1 - Distributed file system for raw/processed data
- Presto - Federated SQL query engine (Hive + PostgreSQL connectors)
- PostgreSQL 15 - OLTP database for master data
- PostgreSQL 13 - Airflow metadata storage
- Apache Airflow 2.x - Workflow orchestration with Web UI
- Docker Compose - Multi-container deployment
- Python 3.9+ - Data generation, pipeline scripts
- psycopg2 - PostgreSQL adapter
- hdfs dfs - Hadoop CLI commands
procurement-pipeline/
βββ π airflow/ # Apache Airflow orchestration
β βββ dags/
β β βββ procurement_pipeline_dag.py # Main DAG (7 tasks, daily @ 22:00)
β βββ logs/ # Task execution logs
β βββ plugins/ # Custom Airflow plugins
β
βββ π scripts/ # Utility scripts
β βββ data_generation/ # Test data generators
β β βββ generate_all_data.py # Master script (--date param)
β β βββ generate_suppliers.py # 10 suppliers
β β βββ generate_products.py # 100 products
β β βββ generate_warehouses.py # 3 warehouses
β β βββ generate_orders.py # POS orders (5 stores)
β β βββ generate_stock.py # Warehouse stock snapshots
β β βββ generate_replenishment_rules.py # 100 centralized rules
β βββ upload_to_hdfs.py # HDFS upload automation
β βββ analyze_data.py # Data overview & testing tool
β βββ setup_hdfs.sh # HDFS directory initialization
β βββ setup_hdfs.ps1 # Windows version
β
βββ π docker/ # Docker infrastructure
β βββ docker-compose.yml # All 9 services in one file
β βββ presto/
β βββ catalog/
β βββ hive.properties # HDFS connector config
β βββ postgresql.properties # PostgreSQL connector config
β
βββ π database/ # Database schemas
β βββ schema.sql # PostgreSQL tables DDL
β βββ db_connection.py # Connection utilities
β
βββ π config/ # Configuration
β βββ config.py # Database & HDFS configs
β βββ .env.example # Environment variables template
β
βββ π data/ # Local data directory (gitignored)
β βββ raw/
β β βββ orders/YYYY-MM-DD/ # POS order JSONL files
β β βββ stock/YYYY-MM-DD/ # Stock snapshot JSONL files
β βββ processed/ # Intermediate results
β βββ output/
β β βββ supplier_orders/ # Final CSV outputs
β βββ logs/ # Pipeline execution logs
β
βββ π sql/ # SQL queries
β βββ analytics_queries.sql # Sample analytical queries
β
βββ π requirements.txt # Python dependencies
βββ π .gitignore # Git exclusions
βββ π README.md # This file
- Docker and Docker Compose installed
- Python 3.9+ installed
- 8GB RAM minimum (recommended: 16GB)
- 10GB disk space for Docker volumes
-
Clone the repository
git clone https://github.com/yourusername/procurement-pipeline.git cd procurement-pipeline -
Install Python dependencies
pip install -r requirements.txt
-
Configure environment variables
# Copy the example file cp .env.example .env # For Windows PowerShell: Copy-Item .env.example .env
Note: Default values work for local development. For production, update passwords in
.env -
Start all services
cd docker docker-compose up -d -
Wait for services to be ready (~2 minutes)
docker-compose ps # All services should show "healthy" or "Up" -
Initialize HDFS directories
cd .. # Linux/Mac: bash scripts/setup_hdfs.sh # Windows PowerShell (if script execution disabled): docker exec hadoop_client hdfs dfs -mkdir -p /procurement/raw/orders /procurement/raw/stock /procurement/processed/aggregated_orders /procurement/processed/net_demand /procurement/output/supplier_orders /procurement/logs/exceptions
β Your environment is ready!
Generate operational data for a specific date:
# Generate for today
python scripts/data_generation/generate_all_data.py
# Generate for specific date
python scripts/data_generation/generate_all_data.py --date 2026-01-14Output:
data/raw/orders/2026-01-14/- 5 POS store order files (JSONL)data/raw/stock/2026-01-14/- 3 warehouse stock snapshots (JSONL)
# Upload today's data
python scripts/upload_to_hdfs.py
# Upload specific date
python scripts/upload_to_hdfs.py --date 2026-01-14HDFS Structure Created:
/procurement/
βββ raw/
β βββ orders/2026-01-14/
β β βββ orders_store_001.json
β β βββ orders_store_002.json
β β βββ ...
β βββ stock/2026-01-14/
β βββ stock_WH001.json
β βββ ...
βββ processed/
β βββ aggregated_orders/
β βββ net_demand/
βββ output/
β βββ supplier_orders/
βββ logs/
βββ exceptions/
Option A: Apache Airflow (Recommended for production)
- Access Airflow UI: http://localhost:8081
- Login:
admin/admin - Enable the
procurement_pipelineDAG - Trigger manually or wait for scheduled run (22:00 daily)
Option B: Python Script (Quick testing)
python airflow/dags/procurement_pipeline_dag.py# Use built-in analysis tool
python scripts/analyze_data.pyOutput displays:
- β PostgreSQL master data summary
- β HDFS data overview (orders & stock)
- β Combined analysis (top products with supplier info)
# Local output
cat data/output/supplier_orders/supplier_orders_20260114.csv
# HDFS output
docker exec hadoop_client hdfs dfs -cat /procurement/output/supplier_orders/supplier_orders_20260114.csvCSV Format:
supplier_code,supplier_name,sku,product_name,net_demand,case_size,order_quantity
SUP001,Tech Supplies Inc,SKU00001,Product A,45,12,48
SUP002,Office Goods Ltd,SKU00015,Product B,23,6,24The complete procurement pipeline with 7 tasks: initialize_presto_schema β check_data_availability β create_hive_tables β validate_data_quality β calculate_net_demand β generate_supplier_orders β cleanup_temp_tables
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 1: INITIALIZE PRESTO SCHEMA β
β β’ CREATE SCHEMA IF NOT EXISTS hive.default β
β β’ Verify schema creation (idempotent setup) β
β β’ Ensures Presto can create tables on first run β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 2: CHECK DATA AVAILABILITY β
β β’ Verify HDFS files exist for execution date β
β β’ Count POS order files (expect 5) β
β β’ Count warehouse stock files (expect 3) β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 3: CREATE HIVE TABLES β
β β’ CREATE EXTERNAL TABLE orders (location: HDFS /raw/orders/) β
β β’ CREATE EXTERNAL TABLE stock (location: HDFS /raw/stock/) β
β β’ Format: JSON β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 4: VALIDATE DATA QUALITY β
β β’ Check: All products have primary supplier mapping β
β β’ Check: No demand spikes >500% vs safety stock β
β β’ Check: No zero available stock with positive reserved β
β β’ Check: No duplicate SKU records per warehouse β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 5: CALCULATE NET DEMAND β
β β’ Aggregate orders by SKU across all stores β
β β’ Join with stock levels by SKU (sum across warehouses) β
β β’ Formula: max(0, orders + safety_stock - free_stock) β
β β’ Export: aggregated_orders & net_demand to HDFS /processed/ β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 6: GENERATE SUPPLIER ORDERS β
β β’ Join net_demand with replenishment_rules β
β β’ Apply case rounding: CEIL(net_demand / case_size) * case_sizeβ
β β’ Enforce MOQ: max(order_qty, min_order_quantity) β
β β’ Filter: order_quantity > 0 β
β β’ Export: CSV to /data/output/ and HDFS /output/ β
βββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββββββββ
βΌ
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Step 7: CLEANUP TEMP TABLES β
β β’ DROP TABLE IF EXISTS hive.default.orders β
β β’ DROP TABLE IF EXISTS hive.default.stock β
β β’ Log execution metrics β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
for each SKU:
# Aggregate demand
total_orders = SUM(quantity) FROM orders WHERE sku = ?
# Aggregate stock
total_available = SUM(available_stock) FROM stock WHERE sku = ?
total_reserved = SUM(reserved_stock) FROM stock WHERE sku = ?
free_stock = total_available - total_reserved
# Get safety stock from replenishment rules
safety_stock = SELECT safety_stock FROM rules WHERE sku = ?
# Calculate net demand
net_demand = MAX(0, total_orders + safety_stock - free_stock)
# Apply case rounding
case_size = SELECT case_size FROM rules WHERE sku = ?
order_quantity = CEIL(net_demand / case_size) * case_size
# Enforce MOQ
min_order_qty = SELECT min_order_quantity FROM rules WHERE sku = ?
final_order = MAX(order_quantity, min_order_qty) IF net_demand > 0Schedule: 0 22 * * * (Daily at 22:00 UTC)
Catchup: False (no backfilling)
Retries: 2 per task
Retry Delay: 5 minutes
Task Dependencies:
check_data_availability
β
create_hive_tables
β
validate_data_quality
β
calculate_net_demand
β
generate_supplier_orders
β
cleanup_temp_tables
| Check | Description | Threshold |
|---|---|---|
| Supplier Mapping | All ordered products must have primary supplier | 0 unmapped |
| Demand Spike | Orders shouldn't exceed 5x safety stock | < 5% violations |
| Stock Consistency | No reserved stock when available = 0 | 0 violations |
| Duplicate SKUs | Each SKU appears once per warehouse snapshot | 0 duplicates |
| Service | URL | Credentials | Purpose |
|---|---|---|---|
| Airflow UI | http://localhost:8081 | admin / admin | DAG monitoring, logs, task execution |
| Presto UI | http://localhost:8080 | - | Query monitoring, cluster status |
| HDFS NameNode | http://localhost:9870 | - | HDFS browser, cluster health |
# PostgreSQL (Master Data)
docker exec -it procurement_postgres psql -U procurement -d procurement_db
# OR: localhost:5433 / procurement / procurement123
# PostgreSQL (Airflow Metadata)
docker exec -it airflow_postgres psql -U airflow -d airflow_db
# OR: localhost:5434 / airflow / airflow
# Presto CLI
docker exec -it presto presto-cli
# HDFS CLI
docker exec -it hadoop_client hdfs dfs -ls /procurement/# View all containers
docker-compose ps
# View Airflow logs
docker-compose logs -f airflow_scheduler
# Check HDFS usage
docker exec hadoop_client hdfs dfs -du -h /procurement/
# Run Presto query
docker exec presto presto-cli --execute "SELECT COUNT(*) FROM hive.default.orders"
# View DAG execution history
docker exec airflow_webserver airflow dags list-runs -d procurement_pipeline
# Clear DAG run history
docker exec airflow_webserver airflow dags delete procurement_pipelineQuick data overview and system testing:
python scripts/analyze_data.pyOutput includes:
-
Master Data Summary
- Product, supplier, warehouse, rules counts
-
HDFS Data Overview
- Latest data date available
- Order items count & unique products
- Stock records & availability
-
Combined Analysis
- Top 10 products ordered (from HDFS)
- Product details with suppliers (from PostgreSQL)
Sample queries in sql/analytics_queries.sql:
-- Top products by order volume
SELECT sku, SUM(quantity) as total_qty
FROM hive.default.orders
GROUP BY sku
ORDER BY total_qty DESC
LIMIT 10;
-- Products with low stock
SELECT s.sku, s.available_stock, r.safety_stock
FROM hive.default.stock s
JOIN postgresql.public.replenishment_rules r ON s.sku = r.sku
WHERE s.available_stock < r.safety_stock;
-- Supplier order summary
SELECT supplier_code, COUNT(*) as products, SUM(order_quantity) as total_qty
FROM supplier_orders
GROUP BY supplier_code;Symptom: Container exits immediately or shows unhealthy
Solution:
# Check logs
docker-compose logs namenode
docker-compose logs presto
# Restart specific service
docker-compose restart namenode
# Full reset
docker-compose down -v
docker-compose up -dSymptom: psycopg2.OperationalError: could not connect
Solution:
# Verify PostgreSQL is running
docker ps | grep postgres
# Test connection
docker exec procurement_postgres psql -U procurement -d procurement_db -c "SELECT 1"
# Check if port 5433 is available
netstat -an | grep 5433Symptom: hdfs: command not found or No such file or directory
Solution:
# Check Hadoop containers
docker ps | grep hadoop
# Verify namenode is accessible
curl http://localhost:9870
# Check HDFS safemode
docker exec namenode hdfs dfsadmin -safemode get
# Leave safemode if stuck
docker exec namenode hdfs dfsadmin -safemode leaveSymptom: Query exceeded maximum time limit
Solution:
# Check Presto is running
docker exec presto presto-cli --execute "SELECT 1"
# Verify Hive connector
docker exec presto cat /opt/presto-server/etc/catalog/hive.properties
# Restart Presto
docker-compose restart prestoSymptom: DAG not visible in UI
Solution:
# Check DAG file syntax
python airflow/dags/procurement_pipeline_dag.py
# Refresh DAGs
docker exec airflow_scheduler airflow dags list
# Check scheduler logs
docker-compose logs -f airflow_scheduler# Increase Docker memory limit (Docker Desktop)
# Settings β Resources β Memory: 8GB minimum
# Increase Presto memory
# Edit docker/presto/config.properties:
# query.max-memory=2GB
# query.max-memory-per-node=1GB
# HDFS replication factor (single-node setup)
docker exec namenode hdfs dfs -setrep -w 1 /procurement/Contributions and suggestions are welcome!
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Commit:
git commit -m 'feat: add your feature' - Push:
git push origin feature/your-feature - Open a Pull Request
Academic project - Fondements Big Data
Academic Year: 2025-2026
For questions or suggestions, open an issue on GitHub.
- Distributed Storage with Hadoop HDFS
- Federated Queries with Presto (cross-system JOINs)
- Workflow Orchestration with Apache Airflow
- Data Quality Validation in production pipelines
- Batch Processing patterns for Big Data
- Containerization with Docker Compose
- Data Lake Architecture (raw/processed/output zones)
- OLTP + OLAP hybrid systems
# Start everything
cd docker && docker-compose up -d
# Generate & upload data
python scripts/data_generation/generate_all_data.py --date 2026-01-14
python scripts/upload_to_hdfs.py --date 2026-01-14
# Analyze results
python scripts/analyze_data.py
# Check HDFS
docker exec hadoop_client hdfs dfs -ls -R /procurement/
# Run Presto query
docker exec presto presto-cli --execute 'SELECT COUNT(*) FROM hive.default.orders'
# View Airflow logs
docker-compose -f docker/docker-compose.yml logs -f airflow_scheduler
# Stop everything
cd docker && docker-compose down- Docker Containers: 9
- Python Files: ~15
- SQL Queries: ~20
- Data Generators: 6
- HDFS Directories: 7
- PostgreSQL Tables: 5
- Airflow Tasks: 7
- Lines of Code: ~2000+
- ENSA Al-Hoceima for the Big Data curriculum
- Apache Software Foundation for Hadoop, Presto, and Airflow
- PostgreSQL Global Development Group
- Docker Community
Last Updated: January 14, 2026
