Project 05 · CRM + ERP Integration

Connect business data with confidence.

Integrate customer and operational records into reliable sales reporting.

The business question
Follow extraction reconciliation, authoritative integration, date quarantine, quality gates, stable keys, replay-safe loads, and atomic promotion. Finish with a customer-grain capstone and field-level lineage.
What you’ll deliver
Reconciled source data, stable keys, historical versions and a validated reporting refresh.
Skills
Integration · Incremental loading · Data quality
Scope
Advanced level · 12 milestones · 16 tables

Fictional extracts, load counts, invalid dates, versioned dimensions, refresh staging and a data catalog. The foundation project is latest-state; separate history and incremental labs demonstrate extensions.

crm_people
  • source_rowintegerPK
  • customer_idtext
  • nametext
  • gendertext
  • updated_attext
#source_rowcustomer_idnamegenderupdated_at
11 C001 AliceF2025-01-01
22C001Alice NguyenF2025-01-05
33C002Benn/a2025-01-02
44C003CaraF2025-01-03
55C004DevNULL2025-01-04
erp_people
  • erp_idtext
  • gendertext
  • birth_datetext
#erp_idgenderbirth_date
1NASC001Male1990-05-12
2NASC002Male1988-02-29
3NASC003Female2028-01-01
4NASC004Other1995-06-20
5NASC999Female1980-01-01
erp_locations
  • erp_idtext
  • country_codetext
#erp_idcountry_code
1C-001USA
2C-002GB
3C-003UK
4C-004IND
load_manifest
  • source_nametextPK
  • expected_rowsinteger
#source_nameexpected_rows
1CRM6
2ERP5
product_versions
  • version_idintegerPK
  • product_idtext
  • nametext
  • costreal
  • valid_fromtext
#version_idproduct_idnamecostvalid_from
11P01Notebook82024-01-01
22P01Notebook92025-02-01
33P02Desk lamp302024-01-01
44P02Desk lamp322025-03-01
raw_dates
  • row_idintegerPK
  • raw_datetext
#row_idraw_date
1120250115
2220250230
330
4420240229
5520251301
dq_sales
  • line_idinteger
  • customer_keyinteger
  • product_keyinteger
  • quantityinteger
  • salesreal
#line_idcustomer_keyproduct_keyquantitysales
1111224
229991112
332999180
442300
5111224
customer_history
  • version_keyintegerPK
  • customer_idtext
  • countrytext
  • valid_fromtext
  • valid_totext
#version_keycustomer_idcountryvalid_fromvalid_to
1101C001United States2024-01-012025-02-01
2102C001Canada2025-02-01NULL
3103C002United Kingdom2024-01-01NULL
incoming_people
  • customer_idtextPK
  • nametext
  • updated_attext
#customer_idnameupdated_at
1C001Alice New2025-02-01
2C002Ben stale2024-01-01
3C006Finn2025-02-02
current_people
  • customer_keyintegerPK
  • customer_idtext
  • nametext
  • updated_attext
#customer_keycustomer_idnameupdated_at
11C001Alice Nguyen2025-01-05
22C002Ben2025-01-02
published_totals
  • customer_idtextPK
  • total_salesreal
#customer_idtotal_sales
1C001289
2C002116
refresh_stage
  • customer_idtext
  • total_salesreal
#customer_idtotal_sales
1C001300
2C002120
warehouse_catalog
  • object_nametext
  • column_nametext
  • meaningtext
  • source_objecttext
  • ruletext
#object_namecolumn_namemeaningsource_objectrule
1integrated_customerscustomer_idNormalized natural customer identifiercrm_people.customer_idTrim; latest updated_at then source_row
2integrated_customersgenderCustomer gender under agreed source authoritycrm_people.gender + erp_people.genderMeaningful CRM first, ERP fallback, otherwise Unknown
3integrated_customerscountryCountry display nameerp_locations.country_codeNormalize ERP key and map codes
4integrated_customersbirth_dateValidated birth dateerp_people.birth_dateValid calendar date; no future dates at 2025-04-01
5built_salessale_keyOne source sales linebronze_sales.row_idUnique and not null
bronze_sales
  • row_idintegerPK
  • customer_idtext
  • product_idtext
  • quantitytext
  • salestext
  • order_datetext
#row_idcustomer_idproduct_idquantitysalesorder_date
11C001P012242025-01-01
22 C002 P031802025-01-02
33C001P021452025-01-15
44C003P0422402025-02-01
55C004P0321602025-02-05
dim_customer
  • customer_keyintegerPK
  • customer_idtext
  • nametext
  • countrytext
#customer_keycustomer_idnamecountry
11C001Alice NguyenUnited States
22C002BenUnited Kingdom
33C003CaraUnited Kingdom
44C004DevIndia
55C005ElenaCanada
dim_product
  • product_keyintegerPK
  • product_idtext
  • nametext
  • categorytext
  • pricereal
#product_keyproduct_idnamecategoryprice
11P01NotebookStationery12
22P02Desk lampHome45
33P03KeyboardTech80
44P04HeadphonesTech120
Start

1 · Land the sources

This project follows the standard layers: understand source data → load raw records (Bronze) → clean and validate (Silver) → build reporting tables (Gold) → produce reports.

sources

Source contract

Structured fictional CRM, ERP and sales extracts. The foundation keeps latest state. Confirm source ownership, extraction counts, key formats, grain and refresh expectations before choosing architecture.

bronze

Bronze · preserve evidence

Raw source-shaped records retain spaces, sentinels, duplicates and malformed values. Compare extraction counts, inspect column alignment, and retain source row identity for replay and diagnosis.

silver

Silver · standardize with explicit rules

Latest CRM row wins with a deterministic source_row tie-breaker. Normalize ERP keys under its format contract. Validate calendar dates, quarantine failures and reconcile every source row.

gold

Gold · integrate business entities

CRM owns meaningful gender; ERP supplies fallback and country. Stable dimension keys link each validated sales line. Choose current-state or effective-time semantics before reporting. Views or stored tables are workload choices.

report

Reports · declare the metric

Customer totals use one row per customer and preserve zero-activity entities. Northstar sales means positive quantity × catalog price under a stated teaching rule, not an automatic accounting correction.

Runtime — Learn it. Run it. Understand it.