QA LOG ============================================================ [ok] spend: 1104 row(s) loaded, schema 'spend' validated against 5 required column(s). [ok] conversions: 1104 row(s) loaded and validated. [ok] google_spend.csv: ignored unmapped column(s): Internal note. [ok] source google_spend.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source google_spend.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Cost (USD) -> spend, Impressions -> impressions, Link clicks -> clicks [ok] source meta_spend.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source meta_spend.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Cost (USD) -> spend, Impressions -> impressions, Link clicks -> clicks [ok] source linkedin_spend.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source linkedin_spend.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Cost (USD) -> spend, Impressions -> impressions, Link clicks -> clicks [ok] source tiktok_spend.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source tiktok_spend.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Cost (USD) -> spend, Impressions -> impressions, Link clicks -> clicks [ok] consolidation: 4 source files into 1104 unique date/campaign row(s). [ok] fixed delimiter: google_spend.csv: read google_spend.csv as ';'-separated detected from column consistency [ok] fixed blank_column: google_spend.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 9 [ok] fixed exact_duplicate_row: google_spend.csv: removed 1 row(s) that were byte-identical to a row already present (1 cell) A verbatim copy-paste repeat. Rows sharing a key but differing in value are NOT removed - those are reported instead. [ok] fixed date_format: google_spend.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: google_spend.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: meta_spend.csv: read meta_spend.csv as ';'-separated detected from column consistency [ok] fixed blank_column: meta_spend.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 9 [ok] fixed exact_duplicate_row: meta_spend.csv: removed 1 row(s) that were byte-identical to a row already present (1 cell) A verbatim copy-paste repeat. Rows sharing a key but differing in value are NOT removed - those are reported instead. [ok] fixed date_format: meta_spend.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: meta_spend.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: linkedin_spend.csv: read linkedin_spend.csv as ';'-separated detected from column consistency [ok] fixed blank_column: linkedin_spend.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 9 [ok] fixed date_format: linkedin_spend.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: linkedin_spend.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: tiktok_spend.csv: read tiktok_spend.csv as ';'-separated detected from column consistency [ok] fixed blank_column: tiktok_spend.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 9 [ok] fixed date_format: tiktok_spend.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: tiktok_spend.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] google_spend.csv: read as delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] google_conversions.csv: ignored unmapped column(s): Attribution model. [ok] source google_conversions.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source google_conversions.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Conversions -> conversions, Conversion value (USD) -> revenue [ok] source meta_conversions.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source meta_conversions.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Conversions -> conversions, Conversion value (USD) -> revenue [ok] source linkedin_conversions.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source linkedin_conversions.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Conversions -> conversions, Conversion value (USD) -> revenue [ok] source tiktok_conversions.csv: 276 validated row(s); delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] source tiktok_conversions.csv field mapping: Report Date -> date, Campaign ID -> campaign_id, Campaign Name -> campaign_name, Platform -> channel, Conversions -> conversions, Conversion value (USD) -> revenue [ok] consolidation: 4 source files into 1104 unique date/campaign row(s). [ok] fixed delimiter: google_conversions.csv: read google_conversions.csv as ';'-separated detected from column consistency [ok] fixed blank_column: google_conversions.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 8 [ok] fixed date_format: google_conversions.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: google_conversions.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: meta_conversions.csv: read meta_conversions.csv as ';'-separated detected from column consistency [ok] fixed blank_column: meta_conversions.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 8 [ok] fixed date_format: meta_conversions.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: meta_conversions.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: linkedin_conversions.csv: read linkedin_conversions.csv as ';'-separated detected from column consistency [ok] fixed blank_column: linkedin_conversions.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 8 [ok] fixed date_format: linkedin_conversions.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: linkedin_conversions.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] fixed delimiter: tiktok_conversions.csv: read tiktok_conversions.csv as ';'-separated detected from column consistency [ok] fixed blank_column: tiktok_conversions.csv: dropped 1 empty column(s) with no header and no data (1 cell) column position(s): 8 [ok] fixed date_format: tiktok_conversions.csv: read dates as %d/%m/%Y all 200 sampled values match %d/%m/%Y [ok] fixed decimal_separator: tiktok_conversions.csv: read numbers as ','-decimal unambiguous numeric grouping and decimal marks indicate ',' [ok] google_conversions.csv: read as delimiter=';', date_format=%d/%m/%Y, decimal_separator=','. [ok] join coverage: 1104 matched key(s) across 1104 spend row(s) and 1104 conversion row(s); 0 spend row(s) and 0 conversion row(s) unmatched. [ok] totals recomputed independently of the row-level table: spend=167262.30.