From 9d40be9cb7f8ddd3c28733c43c441c5e9a9bcfb9 Mon Sep 17 00:00:00 2001 From: bunnyguy <67383454+autowattage@users.noreply.github.com> Date: Tue, 25 Aug 2026 14:40:55 -0400 Subject: [PATCH] Add wrangler airtable sync via dashbored --- orpheus_engine/defs/airtable/definitions.py | 19 +++- orpheus_engine/defs/airtable/generated_ids.py | 90 +++++++++++++++++++ orpheus_engine/defs/dlt/assets.py | 6 ++ orpheus_engine_dbt/models/sources.yml | 15 ++++ .../summer_unified_time_log.sql | 21 ++++- 5 files changed, 149 insertions(+), 2 deletions(-) diff --git a/orpheus_engine/defs/airtable/definitions.py b/orpheus_engine/defs/airtable/definitions.py index 66de4d3..63f06ff 100644 --- a/orpheus_engine/defs/airtable/definitions.py +++ b/orpheus_engine/defs/airtable/definitions.py @@ -407,7 +407,24 @@ def sanitize_name(name: str) -> str: table_id="tblNzmIj9lzOF8rst" ) } - ) + ), + "wrangler": AirtableBaseConfig( + base_id="appznGjUoC1o6jLZd", + tables={ + "ysws_project_submission": AirtableTableConfig( + table_id="tblAv8vzzQClBi5xR" + ), + "shop_queue": AirtableTableConfig( + table_id="tblb4ioz8nOlk9NEJ" + ), + "currency": AirtableTableConfig( + table_id="tblhrthkzWrvLNg39" + ), + "ysws_config": AirtableTableConfig( + table_id="tbls0agmh7GVPnlhK" + ), + } + ), } ) diff --git a/orpheus_engine/defs/airtable/generated_ids.py b/orpheus_engine/defs/airtable/generated_ids.py index 08099c4..ea37f5e 100644 --- a/orpheus_engine/defs/airtable/generated_ids.py +++ b/orpheus_engine/defs/airtable/generated_ids.py @@ -3090,4 +3090,94 @@ class videos: ai_screenplay_error = "fldXsSqMNpcz1aCEL" # Name: AI - Screenplay Error + class wrangler: + """IDs for Base 'wrangler' (ID: appznGjUoC1o6jLZd)""" + BASE_ID = "appznGjUoC1o6jLZd" + + class ysws_project_submission: + """IDs for Table 'ysws_project_submission' (ID: tblAv8vzzQClBi5xR)""" + TABLE_ID = "tblAv8vzzQClBi5xR" + + code_url = "fldzfiDez5YPeGCuC" # Name: Code URL + playable_url = "fldGrp8IDHny71VGW" # Name: Playable URL + how_did_you_hear_about_this = "fldf5uEkUU0liAZ0H" # Name: How did you hear about this? + what_are_we_doing_well = "fld13s9c5Dae7Mrco" # Name: What are we doing well? + how_can_we_improve = "fldb8Y1ysHEEes39l" # Name: How can we improve? + first_name = "fldif0TQkq3aWdJ9b" # Name: First Name + last_name = "fld3rdb40cgCkjtz5" # Name: Last Name + email = "fldexMLda66MbQuTf" # Name: Email + phone = "fldAAXPoGOkzoaX5d" # Name: Phone + screenshot = "fldfrDLbu4MtznQUu" # Name: Screenshot + description = "fldVOT6IT4q5kqjeY" # Name: Description + git_hub_username = "fld5PDzo9R4IWqMQg" # Name: GitHub Username + shipping_first_name = "fldA9U9JClGLMjGRE" # Name: Shipping First Name + shipping_last_name = "fldKnIGAQwMBRhhFa" # Name: Shipping Last Name + address_line_1 = "fld2YEcMnMtS7fXmA" # Name: Address (Line 1) + address_line_2 = "fldSGl7fG9dc9ovql" # Name: Address (Line 2) + city = "fldZ0szHx38mYum0x" # Name: City + state_province = "fld4vRJLJtcxCaFG9" # Name: State / Province + country = "fldqdA0rPO2LAow3T" # Name: Country + zip_postal_code = "fldbrhEnaZajRCoOY" # Name: ZIP / Postal Code + birthday = "fldTJGyCHumdkg19N" # Name: Birthday + linked_lapse_lookout_hackatime_links = "fldb1ZC2rnxUGe8Nn" # Name: Linked lapse/lookout/hackatime links + ai_usage_disclaimer = "fldX30uQp3bxWglaT" # Name: AI usage disclaimer + hours_claimed = "fldKdjdbD1JKDvPYi" # Name: Hours claimed + optional_override_hours_spent = "fldvVS8bt2FBQf8m9" # Name: Optional - Override Hours Spent + optional_override_hours_spent_justification = "fldqBWaZaAXIW2HCX" # Name: Optional - Override Hours Spent Justification + automation_unified_justification = "fldq0fSVuGsIOGCF1" # Name: Automation - Unified Justification + justification_hackatime_project_name_s_date_range_s = "fldE1oolMJwLAQ3HA" # Name: Justification - Hackatime Project Name(s) + Date Range(s) + justification_submitter_hackatime_id = "fldfxRTCYGJCajVzo" # Name: Justification - Submitter Hackatime ID + justification_lapse_links_comma_separated = "fldmbmsSsbiBdypl6" # Name: Justification - Lapse Links, comma-separated + justification_specific_technical_features = "fld6qk67nNnYH3dCF" # Name: Justification - Specific Technical Features + justification_deflation_justification = "fldSz5Ex5cYzAptGi" # Name: Justification - Deflation Justification + justification_alternate_tracking_method = "fldZWkFIsrHNkLo5w" # Name: Justification - Alternate Tracking Method + justification_additional_justification = "fldQW1HY50t9zIA7K" # Name: Justification - Additional Justification + optional_override_duplicate_justification = "fldwtmsBpysJqsjwA" # Name: Optional - Override Duplicate Justification + optional_override_age_justification = "fldKKaSeYlLzXQ8Oe" # Name: Optional - Override Age Justification + automation_submit_to_unified_ysws = "fld2HOwglKY4FR31N" # Name: Automation - Submit to Unified YSWS + automation_error = "fldgtvRggjo9LSzxI" # Name: Automation - Error + automation_first_submitted_at = "fldx5r3R6U0JBBmNc" # Name: Automation - First Submitted At + automation_last_updated_at = "fldduS82Ib3onJlhR" # Name: Automation - Last Updated At + automation_ysws_record_id = "fldnv9yi061JyDRFr" # Name: Automation - YSWS Record ID + loops_special_set_full_name = "fldW49rQug6OUesx2" # Name: Loops - Special - setFullName + loops_birthday = "fldGkQFiaT70raplK" # Name: Loops - birthday + loops_special_set_full_address = "fld4rj0adG8IGen2f" # Name: Loops - Special - setFullAddress + automation_status = "fldvya1GU1tyf7cAA" # Name: Automation - Status + review_status = "fldTizXoFOyq70FMP" # Name: Review status + + class shop_queue: + """IDs for Table 'shop_queue' (ID: tblb4ioz8nOlk9NEJ)""" + TABLE_ID = "tblb4ioz8nOlk9NEJ" + + item = "flduxJRxLyr4ndyfI" # Name: Item + cost = "fldgTITd5sCfN7tFx" # Name: Cost + email = "fldNzl71hmFmlkO4b" # Name: Email + shop_hours_from_currency = "fldvHiAxXxGSF3gMA" # Name: Shop hours (from currency) + currency = "fldNsznCZ8Zzyn0eC" # Name: currency + status = "fldamNCOdH8vFC9tV" # Name: status + + class currency: + """IDs for Table 'currency' (ID: tblhrthkzWrvLNg39)""" + TABLE_ID = "tblhrthkzWrvLNg39" + + email = "fld2yqfS9d0o2criQ" # Name: Email + accepted_hours = "fldL4gY7mr7xvWWTe" # Name: Accepted hours + rejected_hours = "fldc7oKPbdoi3TZ9E" # Name: Rejected hours + pending_hours = "fld7raQR7LdpT4uXZ" # Name: Pending hours + manual_hours_added = "fldOozFXzdgPrMocM" # Name: Manual hours added + shop_hours = "fldJWi3OgWSf0Abfh" # Name: Shop hours + spent_hours = "fldDGjbjlSYbkOkl6" # Name: Spent hours + loops_wrangler_sign_up_at = "fld32R7IzjdgroPa4" # Name: Loops - wranglerSignUpAt + loops_wrangler_shopped_at = "fldbHd7ReZUgUbET1" # Name: Loops - wranglerShoppedAt + loops_list_wrangler = "fldGXVfqYk5u0a3N4" # Name: Loops List - Wrangler + shop_queue = "fldifnCxEte5VNKvi" # Name: shop queue + + class ysws_config: + """IDs for Table 'ysws_config' (ID: tbls0agmh7GVPnlhK)""" + TABLE_ID = "tbls0agmh7GVPnlhK" + + key = "fldKYQXqaxsukzgFj" # Name: Key + value = "fld0p2vciXHyUrYQF" # Name: Value + + # fmt: on diff --git a/orpheus_engine/defs/dlt/assets.py b/orpheus_engine/defs/dlt/assets.py index 5bcbd3a..9813bea 100644 --- a/orpheus_engine/defs/dlt/assets.py +++ b/orpheus_engine/defs/dlt/assets.py @@ -698,6 +698,12 @@ def _run_load(active_dir: str): description="Loads daydream_ops data into the warehouse.airtable_daydream_ops schema." ) +wrangler_assets = create_airtable_sync_assets( + base_name="wrangler", + tables=["ysws_project_submission", "shop_queue", "currency", "ysws_config"], + description="Loads wrangler data into the warehouse.airtable_wrangler schema." +) + # --- DLT Asset: Loads Data into Warehouse using DLT --- @asset( compute_kind="dlt", # Tagging the compute type for UI clarity diff --git a/orpheus_engine_dbt/models/sources.yml b/orpheus_engine_dbt/models/sources.yml index e6f60ca..74cfec3 100644 --- a/orpheus_engine_dbt/models/sources.yml +++ b/orpheus_engine_dbt/models/sources.yml @@ -632,3 +632,18 @@ sources: - name: repos description: "One row per scraped repo with scrape_status (ok/not_found/empty/error) and commit_count." meta: { dagster: { deps: ['highway_github_commits'] } } + - name: airtable_wrangler + schema: airtable_wrangler + tables: + - name: ysws_project_submission + description: "Wrangler ysws_project_submission table." + meta: {dagster: {deps: [wrangler_ysws_project_submission_warehouse]}} + - name: shop_queue + description: "Wrangler shop_queue table." + meta: {dagster: {deps: [wrangler_shop_queue_warehouse]}} + - name: currency + description: "Wrangler currency table." + meta: {dagster: {deps: [wrangler_currency_warehouse]}} + - name: ysws_config + description: "Wrangler ysws_config table." + meta: {dagster: {deps: [wrangler_ysws_config_warehouse]}} diff --git a/orpheus_engine_dbt/models/summer_2026_analytics/summer_unified_time_log.sql b/orpheus_engine_dbt/models/summer_2026_analytics/summer_unified_time_log.sql index 8d6c017..d0ac57e 100644 --- a/orpheus_engine_dbt/models/summer_2026_analytics/summer_unified_time_log.sql +++ b/orpheus_engine_dbt/models/summer_2026_analytics/summer_unified_time_log.sql @@ -228,7 +228,7 @@ WITH program_windows AS ( -- Juice has no Hackatime alias so it shares only same-repo-same-day URL -- dedup, which is negligible across these distinct programs. ('juice', TIMESTAMP WITH TIME ZONE '2025-01-24 00:00:00+00', - TIMESTAMP WITH TIME ZONE '2025-05-12 00:00:00+00') + TIMESTAMP WITH TIME ZONE '2025-05-12 00:00:00+00'), -- Hackatime + custom devlog/journal time for coding programs is the -- credited-hours core of this model, but it is now the SINGLE activity -- log for ALL Summer 2026 programs: the daily-grain and activity-only @@ -241,6 +241,9 @@ WITH program_windows AS ( -- switches to app-native user_daily_activity (section 6b) from -- 2026-04-22 onward; the run window below closes the Hackatime path at -- the handoff so the two never overlap. + ('wrangler', TIMESTAMP WITH TIME ZONE '2026-08-10 00:00:00+00', + TIMESTAMP WITH TIME ZONE '2026-09-30 00:00:00+00') + ) AS t(program_name, start_at, end_at_exclusive) ), @@ -1516,6 +1519,21 @@ high_seas_ht_claims AS ( -- ============================================================ -- 4. MERGE CLAIMS & FILTER BAD ALIASES -- ============================================================ +wrangler_ht_claims AS ( + SELECT 'wrangler'::text AS program_name, + CASE WHEN POSITION('@' IN LOWER(BTRIM(hp."email"))) > 0 + THEN SPLIT_PART(SPLIT_PART(LOWER(BTRIM(hp."email")), '@', 1), '+', 1) + || '@' || SPLIT_PART(LOWER(BTRIM(hp."email")), '@', 2) + ELSE SPLIT_PART(LOWER(BTRIM(hp."email")), '+', 1) + END AS user_email, + LOWER(BTRIM(hp."linked_lapse_lookout_hackatime_links")) AS hackatime_alias, + NULL::text AS project_name, + NULL::text AS code_url, + TIMESTAMP WITH TIME ZONE '2026-08-10 00:00:00+00' AS claim_start_ts + FROM {{ source('airtable_wrangler', 'ysws_project_submission') }} hp + WHERE hp."linked_lapse_lookout_hackatime_links" IS NOT NULL AND hp."linked_lapse_lookout_hackatime_links" <> '' +), + all_claims_raw AS ( SELECT * FROM stardance_ht_claims UNION ALL SELECT * FROM flavortown_ht_claims @@ -1534,6 +1552,7 @@ all_claims_raw AS ( UNION ALL SELECT * FROM carnival_ht_claims UNION ALL SELECT * FROM moonshot_ht_claims UNION ALL SELECT * FROM high_seas_ht_claims + UNION ALL SELECT * FROM wrangler_ht_claims ), all_claims AS (