PROJECT 03HANZ

HANZ.

A hotel rate and availability sync pipeline between an internal pricing engine and a Channex-compatible channel manager — the data backbone I own, plus the dashboard I helped build on top of it.

at NEWDEVowned the pipelineetl · bulk operationslive · hanz.com.vn
HANZ logo
01overview

HANZ keeps a hotel chain's room rates and availability in sync — flowing between its internal pricing engine and a Channex-compatible channel manager that pushes to the booking platforms.

I own the heart of it: a five-stage ETL pipeline in Laravel 8 and PostgreSQL that extracts, transforms, and reconciles pricing in bulk — chunked, idempotent, and audited at every stage. On top of it, I contributed to the React inventory dashboard the hotel team uses day to day.

It runs on an hourly full-sync and a five-minute webhook selective-sync, with a collision guard so the two never fight. The hard part of a pipeline like this isn't moving data — it's moving a lot of it, correctly, without stepping on itself.

02architecture

A five-stage pipeline, built to move pricing in bulk.

Here is how rates actually move. A Laravel pipeline extracts pricing in chunks, explodes date ranges, computes the final numbers in PostgreSQL itself, and pushes back to the channel manager — every stage chunked and logged. The React dashboard reads the same data for the hotel team.

tier 01
dashboard
RC
ts · react 18
Inventory dashboard

14-day rolling rate/availability grid · drag-to-select · bulk-update modal

rolecontributed
Ant Designreact-beautiful-dnd
JSON:API
tier 02
pipeline
LV
php · laravel 8
Laravel ETL pipeline

5-stage flow · chunked extract · CarbonPeriod explosion · bulk upsert via mavinoo/laravel-batch

roleowned end to end
PG
sql · postgres
PostgreSQL store

6,000-row chunk upserts · VIEW-based pricing math (last-minute discount)

roledata + business logic
REST · webhook
tier 03
endpoints
PE
source
HANZ pricing engine

internal rate plans + property data

CM
channel manager
Channex-compatible API

pushes rates out to the booking platforms

infraScheduled sync · cron + webhook
Hourly full-sync5-min webhook syncCollision guard3 audit-log tablesTelegram alerts
03engineering

Four pieces I'd hold up as proof.

A pricing pipeline has one job: be right, at volume, every time. These four are the engineering that earns that trust.

A · pipeline
6,000rows per chunked Postgres upsert

Moving a hotel's pricing without moving it twice.

The pipeline upserts in 6,000-row chunks via mavinoo/laravel-batch and pushes back in 10-row chunks, sized to the channel manager's limits. Extraction is chunked too — 50 properties and 15 rate plans per call — and CarbonPeriod explodes every date range so a price exists for every night.

upsert
6,000-row
push
10-row
extract
50 props
B · data
in-DBpricing math as a Postgres VIEW

The discount math lives in the database.

Final rates — including last-minute discounts — are computed by a PostgreSQL VIEW rather than in PHP. The pipeline reads numbers that are already correct; the business rule has exactly one home, and it's the one closest to the data.

engine
Postgres VIEW
rule
last-minute
C · sync
2 clockshourly full-sync + 5-min webhook

Two sync clocks that never collide.

An hourly cron runs a full reconciliation; a five-minute webhook handles selective updates. A collision guard keeps the two from touching the same property at once — so a fast webhook never races a slow full-sync into an inconsistent state.

full
hourly
selective
5-min
guard
collision lock
D · ops
3 logsaudit tables + Telegram alerts

Every stage leaves a trace.

The pipeline writes to three audit-log tables and posts a Telegram alert per stage — so when a sync goes wrong, the failure is already located and timestamped before anyone goes looking for it.

tables
3
alerts
Telegram
scope
per stage
integrated & in production
Channex APImavinoo/laravel-batchPostgreSQL VIEWCarbonPeriodJSON:APIAnt Designreact-beautiful-dndTelegram Bot
04impact

The pipeline, in numbers.

5
pipeline stages
extract → push
6,000
rows / upsert
chunked bulk write
50 / 15
props · rate plans
per extract pull
2
sync modes
cron + webhook
3
audit logs
+ Telegram alerts
14-day
rate grid
dashboard
7
restriction types
bulk-update modal
2
codebases
pipeline + dashboard

Reported from the HANZ codebases at NEWDEV — pipeline stage, chunk-size, and dashboard figures taken from the Laravel and React projects. Snapshot taken May 2026.