@@ -834,144 +834,87 @@ def ysws_programs_hcb_stats(
834834 log = context .log
835835 input_df = ysws_programs_hcb_candidates
836836
837+ total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
838+
837839 if input_df .height == 0 :
838840 log .info ("No HCB candidates to process." )
839- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
840- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
841841 return Output (
842842 pl .DataFrame (schema = {
843843 "id" : pl .Utf8 ,
844844 total_spent_field_id : pl .Float64 ,
845- hcb_field_id : pl .Utf8
846845 }),
847846 metadata = {"num_processed" : 0 , "num_successful" : 0 , "num_failed" : 0 }
848847 )
849-
848+
850849 log .info (f"Processing HCB data for { input_df .height } programs" )
851-
852- all_records = [] # Changed from successful_records to include both success and error records
853- failed_count = 0
854-
850+
851+ successful_records = []
852+ failures = []
853+
855854 for row in input_df .iter_rows (named = True ):
856855 program_id = row .get ("id" )
857856 hcb_id = row .get ("hcb_id" )
858857 hcb_url = row .get ("hcb" )
859-
858+
860859 if not hcb_id :
861- log .warning (f"No HCB ID for program { program_id } " )
862- # Create error record
863- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
864- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
865- all_records .append ({
866- "id" : program_id ,
867- total_spent_field_id : None ,
868- hcb_field_id : f'ERROR: "No HCB ID extracted" | { hcb_url or "Unknown URL" } '
869- })
870- failed_count += 1
860+ log .warning (f"No HCB ID for program { program_id } (url={ hcb_url !r} )" )
861+ failures .append ({"id" : program_id , "hcb_url" : hcb_url , "reason" : "No HCB ID extracted" })
871862 continue
872-
863+
873864 try :
874- # Make API request to HCB
875865 api_url = f"https://hcb.hackclub.com/api/v3/organizations/{ hcb_id } "
876866 log .debug (f"Fetching HCB data for { hcb_id } : { api_url } " )
877-
867+
878868 response = requests .get (
879869 api_url ,
880870 headers = {"Accept" : "application/json" },
881871 timeout = 30
882872 )
883-
873+
884874 if response .status_code != 200 :
885- # Try to extract message from JSON response
886875 try :
887876 error_data = response .json ()
888877 error_message = error_data .get ("message" , f"HTTP { response .status_code } " )
889- except :
878+ except Exception :
890879 error_message = f"HTTP { response .status_code } "
891-
880+
892881 log .warning (f"HCB API returned { response .status_code } for { hcb_id } : { response .text } " )
893- # Create error record
894- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
895- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
896- all_records .append ({
897- "id" : program_id ,
898- total_spent_field_id : None ,
899- hcb_field_id : f'ERROR: "{ error_message } " | { hcb_url } '
900- })
901- failed_count += 1
882+ failures .append ({"id" : program_id , "hcb_url" : hcb_url , "reason" : error_message })
902883 continue
903-
884+
904885 data = response .json ()
905-
906- # Extract balance information
907886 balances = data .get ("balances" , {})
908887 total_raised = balances .get ("total_raised" , 0 )
909888 balance_cents = balances .get ("balance_cents" , 0 )
910-
911- # Calculate total spent: total_raised - balance_cents (convert from cents to dollars)
912889 total_spent_dollars = (total_raised - balance_cents ) / 100.0
913-
914- # Get Airtable field IDs
915- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
916- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
917-
918- # Add successful record
919- all_records .append ({
890+
891+ successful_records .append ({
920892 "id" : program_id ,
921893 total_spent_field_id : total_spent_dollars ,
922- hcb_field_id : None # No error, so empty
923894 })
924-
895+
925896 log .info (f"Successfully processed { hcb_id } : total_raised={ total_raised } , balance_cents={ balance_cents } , total_spent=${ total_spent_dollars :.2f} " )
926-
897+
927898 except requests .exceptions .RequestException as e :
928899 log .error (f"Request failed for HCB ID { hcb_id } : { e } " )
929- # Create error record
930- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
931- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
932- all_records .append ({
933- "id" : program_id ,
934- total_spent_field_id : None ,
935- hcb_field_id : f'ERROR: "Request failed: { str (e )} " | { hcb_url } '
936- })
937- failed_count += 1
900+ failures .append ({"id" : program_id , "hcb_url" : hcb_url , "reason" : f"Request failed: { e } " })
938901 except (KeyError , ValueError , TypeError ) as e :
939902 log .error (f"Error parsing HCB data for { hcb_id } : { e } " )
940- # Create error record
941- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
942- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
943- all_records .append ({
944- "id" : program_id ,
945- total_spent_field_id : None ,
946- hcb_field_id : f'ERROR: "Data parsing error: { str (e )} " | { hcb_url } '
947- })
948- failed_count += 1
903+ failures .append ({"id" : program_id , "hcb_url" : hcb_url , "reason" : f"Data parsing error: { e } " })
949904 except Exception as e :
950905 log .error (f"Unexpected error processing HCB ID { hcb_id } : { e } " )
951- # Create error record
952- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
953- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
954- all_records .append ({
955- "id" : program_id ,
956- total_spent_field_id : None ,
957- hcb_field_id : f'ERROR: "Unexpected error: { str (e )} " | { hcb_url } '
958- })
959- failed_count += 1
960-
961- # Create output DataFrame
962- total_spent_field_id = UnifiedYSWS .ysws_programs .total_spent_from_hcb_fund
963- hcb_field_id = UnifiedYSWS .ysws_programs .hcb
964-
965- if all_records :
966- output_df = pl .DataFrame (all_records )
906+ failures .append ({"id" : program_id , "hcb_url" : hcb_url , "reason" : f"Unexpected error: { e } " })
907+
908+ if successful_records :
909+ output_df = pl .DataFrame (successful_records )
967910 else :
968911 output_df = pl .DataFrame (schema = {
969912 "id" : pl .Utf8 ,
970913 total_spent_field_id : pl .Float64 ,
971- hcb_field_id : pl .Utf8
972914 })
973-
974- successful_count = len ([r for r in all_records if r [total_spent_field_id ] is not None ])
915+
916+ successful_count = len (successful_records )
917+ failed_count = len (failures )
975918 log .info (f"HCB processing completed. Successful: { successful_count } , Failed: { failed_count } " )
976919
977920 # Generate preview metadata
@@ -983,16 +926,22 @@ def ysws_programs_hcb_stats(
983926 else :
984927 preview_metadata = MetadataValue .text ("No HCB data processed successfully" )
985928
986- return Output (
987- output_df ,
988- metadata = {
989- "num_processed" : input_df .height ,
990- "num_successful" : successful_count ,
991- "num_failed" : failed_count ,
992- "success_rate" : round ((successful_count / max (input_df .height , 1 )) * 100 , 2 ),
993- "preview" : preview_metadata
994- }
995- )
929+ metadata = {
930+ "num_processed" : input_df .height ,
931+ "num_successful" : successful_count ,
932+ "num_failed" : failed_count ,
933+ "success_rate" : round ((successful_count / max (input_df .height , 1 )) * 100 , 2 ),
934+ "preview" : preview_metadata ,
935+ }
936+ if failures :
937+ try :
938+ metadata ["failures" ] = MetadataValue .md (
939+ pl .DataFrame (failures ).to_pandas ().to_markdown (index = False )
940+ )
941+ except Exception :
942+ metadata ["failures" ] = MetadataValue .text (str (failures ))
943+
944+ return Output (output_df , metadata = metadata )
996945
997946
998947def _get_signup_analysis_data (search_terms : List [str ]) -> pl .DataFrame :
0 commit comments