Data Analyst / Engineer · Projects
Project 2: A warehouse with personal data protected
Marking guide version 1 · Lessons: DT5 lessons 2 and 5, DT6 lessons 1–5, DT7 lessons 1–5, DT10 lesson 3
The problem and who it's for
SabziSathi's dbt project builds, but it passes customers' names, phone numbers and emails into the marts, keys customers by an unsalted MD5 of their phone number, gives every order the area from the September export even after customers moved, counts cancelled and refunded lines as revenue, has no tests or freshness checks, and is almost undocumented. The analysts who use it can't tell which numbers to trust, and any one of them can read every customer's phone number.
Scope
- Stop personal data in staging; build
dim_customerswith a salted SHA-256 key fromSABZI_KEY_SALTandsignup_month. - Build
dim_customer_area_history(type 2, half-open periods) and give each order the area at the time it was placed. - Put
net_amount_paisein the fact and net revenue and delivered orders inmart_daily_sales; addmart_area_moves. - Add tests (grain, keys, accepted values, relationships, a reconciliation), sources with freshness, and descriptions for every mart column.
- Make
fct_order_linesincremental with a unique key and a look-back.
Not included
- A cloud warehouse (the capstone's design notes cover it).
- dbt Cloud or a semantic layer.
- Real customer data of any kind.
Before you start
-
Core: Module 53 (Relationships and ER Diagrams), Module 54 (Normalisation), Module 56 (Advanced Queries), Module 79 (Privacy and Data Protection).
-
Path: DT5, DT6 and DT7 complete, and Project 1 finished (the warehouse's numbers depend on the pipeline).
pytest tests/test_warehouse.pyrunning (8 of its 10 tests fail at first).
Starter files
sabzisathi/warehouse/models/staging/stg_customers.sql: passes every column of the customer export on.sabzisathi/warehouse/models/marts/dim_customers.sql:md5(phone)as the key, with names, phones and emails.sabzisathi/warehouse/models/marts/fct_order_lines.sql: a full rebuild, the export's area, and every line counted as revenue.sabzisathi/warehouse/models/marts/mart_daily_sales.sql: revenue including cancellations, and an average per day and store.sabzisathi/warehouse/models/staging/sources.ymlandsabzisathi/warehouse/models/marts/schema.yml: no tests, freshness or descriptions.sabzisathi/tests/test_warehouse.py: the 10 acceptance tests for this project.
Download everything at once: starter/data-starter.zip.
Milestones
- Run
pytest tests/test_warehouse.pyand note which of the 10 tests fail and why. - Fix staging and the customer key (tests 3 and 4).
- Build the area history and join it on the order time (test 6).
- Fix the measures and marts (test 7), and add tests and the reconciliation (test 2).
- Add sources with freshness, the incremental fact and descriptions (tests 8 to 10).
- Run all 10 tests twice in a row.
Expected outputs
- 10 of 10 warehouse tests passing, twice in a row.
dbt buildpassing every test, and the docs site generated.docs/model.mdwith the grain, the star schema and how to total each measure.
Acceptance tests
| # | Input | Expected result |
|---|---|---|
| 1 | pytest tests/test_warehouse.py |
10 of 10 pass, twice in a row |
| 2 | dbt build --profiles-dir . with SABZI_KEY_SALT set |
Every model and test passes (test 1) |
| 3 | Every column and value in the marts schema |
No name, phone or email; customer keys are 64-character salted hashes (tests 3 and 4) |
| 4 | marts.dim_customer_area_history and marts.fct_order_lines |
640 history rows, 600 current; 10,181 lines, each with an area its store serves (tests 2 and 6) |
| 5 | marts.mart_daily_sales |
3,411 orders, 2,918 delivered, 196,576,400 paise net revenue (test 7) |
| 6 | Reload 30 October and rebuild | The same 10,181 lines and net revenue (test 9) |
Failure and recovery exercises
- Write the salt into
dbt_project.ymlas a variable and run test 4. Explain the failure, then move it back to the environment. - Join the fact to the history on the customer key only and count the rows. Explain the difference, then restore the time condition.
- Remove
unique_keyfrom the incremental fact, reload a day and rebuild. Describe what happens to the totals, then restore it.
Evidence to submit
- The deliverable link to your repository or folder with the warehouse changes.
- The output of
pytest tests/test_warehouse.pyshowing 10 passed, pasted into test evidence. - The
dbt buildsummary and a screenshot of the lineage graph fromdbt docs. - Your explanation: where personal data stops, how the customer key is made and kept safe, and how an order gets the right area.
Marking guide and self-check
Pass rule: every Safety-critical (S) and Mandatory (M) item must be met. A single unmet safety item means the project is not complete, whatever else is done. Quality items are for your own improvement.
Your answers are saved in this browser on this device. Self-checked means you checked your own work against this guide; it is not a reviewer's approval. Never paste passwords, keys, tokens or real customer data here.
