Fixing bug with gbis remaining counts

This commit is contained in:
Khalim Conn-Kowlessar 2024-03-06 10:24:42 +00:00
parent f8948ff60f
commit abe0e627db

View file

@ -424,6 +424,12 @@ class DataLoader:
def load_asset_list(self, filepath, ha_name):
workbook = openpyxl.load_workbook(filepath)
asset_sheetname = self.get_asset_sheetname(workbook)
# TODO: TEMP
sheetnames_lower = [x.lower() for x in workbook.sheetnames]
if any("eco3" in x for x in sheetnames_lower):
raise Exception("REMOVE ME")
asset_sheet = workbook[asset_sheetname]
asset_sheet_colnames = [cell.value for cell in asset_sheet[1]]
if ha_name == "HA25":
@ -569,6 +575,34 @@ class DataLoader:
)
return asset_list
@staticmethod
def correct_ha38_asset_list(asset_list):
# For Kingsford court, the house number is at the end of the address
def rearrange_address_if_flat(address):
if '/flat' in address.lower():
parts = address.split('/flat', 1)
return f"FLAT{parts[1]}, {parts[0]}"
return address
def extract_house_no_if_flat(address):
if '/flat' in address.lower():
# Attempt to extract the house number following "/flat"
try:
house_no = address.split('/flat ')[1].split(' ')[0]
# Remove trailing comma
house_no = house_no.replace(",", "")
except IndexError:
house_no = None
return house_no
return None
asset_list['ExtractedHouseNo'] = asset_list['matching_address'].apply(extract_house_no_if_flat)
asset_list.loc[asset_list['ExtractedHouseNo'].notnull(), 'HouseNo'] = asset_list['ExtractedHouseNo']
asset_list['matching_address'] = asset_list['matching_address'].apply(rearrange_address_if_flat)
# We then need to
return asset_list
@staticmethod
def correct_ha6_survey_list(survey_list):
@ -925,6 +959,11 @@ class DataLoader:
def correct_ha38_survey_list(survey_list):
# Rename the "No" column to "No." to align with the other survey sheets
survey_list = survey_list.rename(columns={"NO ": "NO."})
survey_list["Street / Block Name"] = survey_list["Street / Block Name"].str.replace(
'Kingsford Court, Coombe Valley Road', 'Kingsford Court'
)
return survey_list
@staticmethod
@ -1345,6 +1384,7 @@ class DataLoader:
"eco4 (subject to ciga/archetype check": "eco4 (subject to ciga)",
"eco4 (subject to archetype check)": "eco4",
"eco4 (subject to ciga/archetype)": "eco4 (subject to ciga)",
"eco4 (subject to ciga)": "eco4 (subject to ciga)"
}
ha_facts_and_figures = []
@ -2943,8 +2983,8 @@ def forecast_remaining_sales(loader):
median_ciga_success_rate = ciga_passrates["# CIGA passed"].sum() / ciga_passrates["# CIGA dependent"].sum()
# 3) Calculate the conversion rate of an ECO4 and a GBISjob, that doesn't need ciga, to install
eco4_ciga_independent_passrates = []
gbis_ciga_independent_passrates = []
eco4_ciga_independent_to_install = []
gbis_to_install = []
for ha_name, input_data in loader.data.items():
asset_list = input_data["asset_list"].copy()
survey_list = input_data["survey_list"].copy()
@ -2973,7 +3013,7 @@ def forecast_remaining_sales(loader):
)
]
eco4_ciga_independent_passrates.append(
eco4_ciga_independent_to_install.append(
{
"Ha Name": ha_name,
"# ECO4 at install stage": typical_eco4_installed.shape[0],
@ -2993,7 +3033,7 @@ def forecast_remaining_sales(loader):
)
]
gbis_ciga_independent_passrates.append(
gbis_to_install.append(
{
"Ha Name": ha_name,
"# GBIS at install stage": typical_gbis_installed.shape[0],
@ -3001,33 +3041,33 @@ def forecast_remaining_sales(loader):
}
)
eco4_ciga_independent_passrates = pd.DataFrame(eco4_ciga_independent_passrates)
gbis_ciga_independent_passrates = pd.DataFrame(gbis_ciga_independent_passrates)
eco4_ciga_independent_to_install = pd.DataFrame(eco4_ciga_independent_to_install)
gbis_to_install = pd.DataFrame(gbis_to_install)
eco4_ciga_independent_passrates["conversion"] = (
eco4_ciga_independent_passrates["# ECO4 successfully installed"] /
eco4_ciga_independent_passrates["# ECO4 at install stage"]
eco4_ciga_independent_to_install["conversion"] = (
eco4_ciga_independent_to_install["# ECO4 successfully installed"] /
eco4_ciga_independent_to_install["# ECO4 at install stage"]
)
eco4_ciga_independent_passrates_clipped = eco4_ciga_independent_passrates[
eco4_ciga_independent_passrates["conversion"] >= sales_conversion_lower_bound
eco4_ciga_independent_to_install_clipped = eco4_ciga_independent_to_install[
eco4_ciga_independent_to_install["conversion"] >= sales_conversion_lower_bound
]
gbis_ciga_independent_passrates["conversion"] = (
gbis_ciga_independent_passrates["# GBIS successfully installed"] /
gbis_ciga_independent_passrates["# GBIS at install stage"]
gbis_to_install["conversion"] = (
gbis_to_install["# GBIS successfully installed"] /
gbis_to_install["# GBIS at install stage"]
)
gbis_ciga_independent_passrates_clipped = gbis_ciga_independent_passrates[
gbis_ciga_independent_passrates["conversion"] >= sales_conversion_lower_bound
gbis_to_install_clipped = gbis_to_install[
gbis_to_install["conversion"] >= sales_conversion_lower_bound
]
median_eco4_to_install = (
eco4_ciga_independent_passrates_clipped["# ECO4 successfully installed"].sum() /
eco4_ciga_independent_passrates_clipped["# ECO4 at install stage"].sum()
eco4_ciga_independent_to_install_clipped["# ECO4 successfully installed"].sum() /
eco4_ciga_independent_to_install_clipped["# ECO4 at install stage"].sum()
)
median_gbis_to_install = (
gbis_ciga_independent_passrates_clipped["# GBIS successfully installed"].sum() /
gbis_ciga_independent_passrates_clipped["# GBIS at install stage"].sum()
gbis_to_install_clipped["# GBIS successfully installed"].sum() /
gbis_to_install_clipped["# GBIS at install stage"].sum()
)
# Produce the final output
@ -3044,29 +3084,26 @@ def forecast_remaining_sales(loader):
results = []
for ha_name, input_data in loader.data.items():
# Original warmfront figures - ECO4
original_warmfront_estimates = december_figures[december_figures["HA Name"] == ha_name]
original_warmfront_eco4 = original_warmfront_estimates["ECO4"].values[0]
original_warmfront_remaining_eco4 = original_warmfront_estimates["ECO4 remaining"].values[0]
original_warmfront_sold_eco4 = (
original_warmfront_estimates["No. of Tech surveys complete - Eco 4"].values[0] * eco4_rate
)
# original_warmfront_eco4_revenue = (
# original_warmfront_remaining_eco4 * eco4_rate +
# (original_warmfront_eco4 - original_warmfront_remaining_eco4) * old_eco4_rate
# )
original_warmfront_eco4_revenue = original_warmfront_eco4 * eco4_rate
original_warmfront_remaining_eco4_revenue = original_warmfront_remaining_eco4 * eco4_rate
original_warmfront_sold_gbis = (
original_warmfront_estimates["No. of Tech surveys complete - GBIS"].values[0] * gbis_rate
)
# Original warmfront figures - GBIS
original_warmfront_gbis = original_warmfront_estimates["GBIS"].values[0]
original_warmfront_remaining_gbis = original_warmfront_estimates["GBIS remaining"].values[0]
# original_warmfront_gbis_revenue = (
# original_warmfront_remaining_gbis * gbis_rate +
# (original_warmfront_gbis - original_warmfront_remaining_gbis) * old_gbis_rate
# )
original_warmfront_gbis_revenue = (
original_warmfront_gbis * gbis_rate
)
@ -3123,7 +3160,7 @@ def forecast_remaining_sales(loader):
# We also need the ha ciga passed to install success rate
ha_ciga_pass_to_sale = converted_ciga_jobs[converted_ciga_jobs["HA Name"] == ha_name]
if not ha_ciga_pass_to_sale.empty:
if not ha_ciga_pass_to_sale.empty and ha_ciga_pass_to_sale["# Ciga dependent at installation"].values[0] != 0:
ha_ciga_pass_to_sale_rate = (
ha_ciga_pass_to_sale["# Ciga dependent successfully installed"].values[0] /
ha_ciga_pass_to_sale["# Ciga dependent at installation"].values[0]
@ -3131,7 +3168,9 @@ def forecast_remaining_sales(loader):
else:
ha_ciga_pass_to_sale_rate = median_ciga_pass_to_install
ha_eco4_to_sale = eco4_ciga_independent_passrates[eco4_ciga_independent_passrates["Ha Name"] == ha_name]
ha_eco4_to_sale = eco4_ciga_independent_to_install_clipped[
eco4_ciga_independent_to_install_clipped["Ha Name"] == ha_name
]
if not ha_eco4_to_sale.empty:
ha_eco4_to_sale_rate = (
ha_eco4_to_sale['# ECO4 successfully installed'].values[0] /
@ -3149,12 +3188,6 @@ def forecast_remaining_sales(loader):
eco4_rate=eco4_rate
)
# Calculate the delta compared to Warmfront's original estimate
eco4_delta_vs_original_estimate = (
eco4_post_ciga_total_results[
"ECO4 - post CIGA - #"] - original_warmfront_eco4
) / original_warmfront_eco4
eco4_post_ciga_remaining_results = calculate_eco4_post_ciga(
eligiblity_counts=eligiblity_counts_remaining,
input_data=input_data,
@ -3164,10 +3197,18 @@ def forecast_remaining_sales(loader):
eco4_rate=eco4_rate
)
# Calculate the delta compared to Warmfront's original remaining
if original_warmfront_remaining_eco4 == 0:
eco4_delta_vs_original_estimate_remaining = eco4_post_ciga_remaining_results["ECO4 - post CIGA - #"]
else:
eco4_delta_vs_original_estimate_remaining = ((eco4_post_ciga_remaining_results["ECO4 - post CIGA - #"] -
original_warmfront_remaining_eco4) /
original_warmfront_remaining_eco4)
# GBIS Figures
# Estimate the GBIS conversion rate
ha_gbis_sale_conversion = gbis_ciga_independent_passrates[
gbis_ciga_independent_passrates["Ha Name"] == ha_name
ha_gbis_sale_conversion = gbis_to_install_clipped[
gbis_to_install_clipped["Ha Name"] == ha_name
]
if not ha_gbis_sale_conversion.empty:
@ -3178,6 +3219,9 @@ def forecast_remaining_sales(loader):
else:
ha_gbis_sale_conversion = median_gbis_to_install
asset_list["ECO Eligibility"].value_counts()
asset_list_remaining["ECO Eligibility"].value_counts()
gbis_total = eligiblity_counts[
eligiblity_counts["ECO Eligibility"] == "gbis"
]["count"].sum()
@ -3185,18 +3229,59 @@ def forecast_remaining_sales(loader):
gbis_total_revenue = int(gbis_total * gbis_rate)
gbis_remaining = eligiblity_counts_remaining[
eligiblity_counts["ECO Eligibility"] == "gbis"
eligiblity_counts_remaining["ECO Eligibility"] == "gbis"
]["count"].sum()
gbis_remaining = int(np.round(gbis_remaining * ha_gbis_sale_conversion))
gbis_remaining_revenue = int(gbis_remaining * gbis_rate)
# GBIS delta
if original_warmfront_gbis == 0:
gbis_delta_vs_original_estimate = gbis_total
if original_warmfront_remaining_gbis == 0:
gbis_delta_vs_original_estimate_remaining = gbis_remaining
else:
gbis_delta_vs_original_estimate = (
gbis_total - original_warmfront_gbis
) / original_warmfront_gbis
gbis_delta_vs_original_estimate_remaining = (
(gbis_remaining - original_warmfront_remaining_gbis) / original_warmfront_remaining_gbis
)
# Current sales figures
# For any sales surveys that are complete, that could still cancel, we apply a conversion rate
eco4_actually_sold = 0
gbis_actually_sold = 0
if not survey_list.empty:
surveys_with_eligibility = survey_list.merge(
asset_list[["asset_list_row_id", "ECO Eligibility"]],
how="left", on="asset_list_row_id"
)
completed_eco4_sales = surveys_with_eligibility[
surveys_with_eligibility["installation_status"] == "ECO4 - installed"
]
incomplete_eco4_sales = surveys_with_eligibility[
(surveys_with_eligibility["installation_status"] == "ECO4 - in progress") &
(~surveys_with_eligibility["ECO Eligibility"].isin(
["eco4 - passed ciga"])
)
]
incomplete_eco4_sales_ciga = surveys_with_eligibility[
(surveys_with_eligibility["installation_status"] == "ECO4 - in progress") &
(surveys_with_eligibility["ECO Eligibility"].isin(
["eco4 - passed ciga"])
)
]
eco4_actually_sold = (completed_eco4_sales.shape[0] * eco4_rate) + (
incomplete_eco4_sales.shape[0] * ha_eco4_to_sale_rate +
incomplete_eco4_sales_ciga.shape[0] * ha_ciga_pass_to_sale_rate
) * eco4_rate
completed_gbis_sales = surveys_with_eligibility[
surveys_with_eligibility["installation_status"] == "GBIS - installed"
]
incomplete_gbis_sales = surveys_with_eligibility[
(surveys_with_eligibility["installation_status"] == "GBIS - in progress")
]
gbis_actually_sold = completed_gbis_sales.shape[0] * gbis_rate + (
incomplete_gbis_sales.shape[0] * ha_gbis_sale_conversion * gbis_rate
)
to_append = {
("", "", "", "HA Name"): ha_name,
@ -3204,29 +3289,33 @@ def forecast_remaining_sales(loader):
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): original_warmfront_eco4,
("ECO4 original", "", "Remaining - #", ""): original_warmfront_remaining_eco4,
("ECO4 original", "", "Total - £", ""): original_warmfront_eco4_revenue,
("ECO4 original", "", "Sold - £", ""): original_warmfront_sold_eco4,
("ECO4 original", "", "Remaining - £", ""): original_warmfront_remaining_eco4_revenue,
# GBIS - original warmfront figures
("", "Original Warmfront estimate", "Total - #", "GBIS - November"): original_warmfront_gbis,
("GBIS original", "", "Remaining - #", ""): original_warmfront_gbis,
("GBIS original", "", "Total - £", ""): original_warmfront_gbis_revenue,
("GBIS original", "", "Sold - £", ""): original_warmfront_sold_gbis,
("GBIS original", "", "Remaining - £", ""): original_warmfront_remaining_gbis_revenue,
# ECO4 - asset list, pre-ciga
("", "Warmfront post code list", "Total #", "ECO4 total (pre-ciga)"): eco4_pre_ciga,
("ECO4 pre-ciga", "", "Remaining - #", ""): eco4_pre_ciga_remaining,
("ECO4 pre-ciga", "", "Total - £", ""): eco4_pre_ciga_revenue,
("ECO4 pre-ciga", "", "Sold - £", ""): eco4_actually_sold,
("ECO4 pre-ciga", "", "Remaining - £", ""): eco4_pre_ciga_remaining_revenue,
# ECO4 - asset list, post ciga, total
("ECO4 post-ciga", "", "Estimated total eligible - #", "ECO4 total (post-ciga)"):
("ECO4 post-ciga", "", "Estimated total eligible - #", "ECO4 total"):
eco4_post_ciga_total_results[
"ECO4 - post CIGA - #"],
("ECO4 post-ciga", "", "Estimated total eligible - £", ""): eco4_post_ciga_total_results[
"ECO4 - post CIGA - £"],
("ECO4 post-ciga", "", "Delta vs original estimate - %", ""): eco4_delta_vs_original_estimate,
# ECO4 - asset list, post ciga, remaining
("ECO4 post-ciga", "", "Estimated remaining eligible - #", ""): eco4_post_ciga_remaining_results[
"ECO4 - post CIGA - #"],
("ECO4 post-ciga", "", "Estimated remaining eligible - £", ""): eco4_post_ciga_remaining_results[
"ECO4 - post CIGA - £"],
("ECO4 post-ciga", "", "Delta vs original estimate, remaining - %",
""): eco4_delta_vs_original_estimate_remaining,
("ECO4 post-ciga", "", "Of which - confirmed (post CIGA or no CIGA required) - #", ""):
eco4_post_ciga_remaining_results["Of which confirmed - #"],
("ECO4 post-ciga", "", "Of which - confirmed (post CIGA or no CIGA required) - £", ""):
@ -3257,13 +3346,15 @@ def forecast_remaining_sales(loader):
# GBIS postcode list
("GBIS Postcode list", "Warmfront post code list", "Total - #", "GBIS total"): gbis_total,
("GBIS Postcode list", "Warmfront post code list", "Total - £", "GBIS total"): gbis_total_revenue,
("GBIS Postcode list", "", "Delta vs original estimate - %", ""): gbis_delta_vs_original_estimate,
("GBIS Postcode list", "Warmfront post code list", "Sold - £", "GBIS total"): gbis_actually_sold,
("GBIS Postcode list", "Warmfront post code list", "Remaining - #", "GBIS total"): gbis_remaining,
("GBIS Postcode list", "Warmfront post code list", "Remaining - £", "GBIS total"): gbis_remaining_revenue,
("GBIS Postcode list", "", "Delta vs original estimate, remaining - %", ""):
gbis_delta_vs_original_estimate_remaining,
}
# Make sure nothing is forgotten due to duplicate multi-index keys
if len(to_append) != 33:
if len(to_append) != 37:
raise ValueError("Something went wrong")
results.append(to_append)
@ -3275,26 +3366,26 @@ def forecast_remaining_sales(loader):
if col == ('', '', '', 'HA Name'):
totals_row[col] = "Total"
elif col in [
("ECO4 post-ciga", "", "Delta vs original estimate - %", ""),
("GBIS Postcode list", "", "Delta vs original estimate - %", "")
("ECO4 post-ciga", "", "Delta vs original estimate, remaining - %", ""),
("GBIS Postcode list", "", "Delta vs original estimate, remaining - %", "")
]:
totals_row[col] = None
else:
totals_row[col] = results[col].sum()
# For the delta columns, we calculate the delta on the totals
totals_row[("ECO4 post-ciga", "", "Delta vs original estimate - %", "")] = (
totals_row[("ECO4 post-ciga", "", "Delta vs original estimate, remaining - %", "")] = (
(
totals_row[("ECO4 post-ciga", "", "Estimated total eligible - #", "ECO4 total (post-ciga)")] -
totals_row[("", "Original Warmfront estimate", "Total - #", "ECO4 - November")]
) / totals_row[("", "Original Warmfront estimate", "Total - #", "ECO4 - November")]
totals_row[("ECO4 post-ciga", "", "Estimated remaining eligible - #", "")] -
totals_row[("ECO4 original", "", "Remaining - #", "")]
) / totals_row[("ECO4 original", "", "Remaining - #", "")]
)
totals_row[("GBIS Postcode list", "", "Delta vs original estimate - %", "")] = (
totals_row[("GBIS Postcode list", "", "Delta vs original estimate, remaining - %", "")] = (
(
totals_row[("GBIS Postcode list", "Warmfront post code list", "Total - #", "GBIS total")] -
totals_row[("", "Original Warmfront estimate", "Total - #", "GBIS - November")]
) / totals_row[("", "Original Warmfront estimate", "Total - #", "GBIS - November")]
totals_row[("GBIS Postcode list", "Warmfront post code list", "Remaining - #", "GBIS total")] -
totals_row[("GBIS original", "", "Remaining - #", "")]
) / totals_row[("GBIS original", "", "Remaining - #", "")]
)
blank_row = pd.DataFrame([{col: "" for col in results.columns}])
@ -3342,6 +3433,15 @@ def forecast_remaining_sales(loader):
)
headline_total_delta = round(headline_total_delta, 1)
headline_eco4_sold_since_november = (
totals_row[('ECO4 pre-ciga', '', 'Sold - £', '')] - totals_row[('ECO4 original', '', 'Sold - £', '')]
)
headline_gbis_sold_since_november = (
totals_row[("GBIS Postcode list", "Warmfront post code list", "Sold - £", "GBIS total")] -
totals_row[('GBIS original', '', 'Sold - £', '')]
)
headlines = [
{
("", "", "", "HA Name"): "Headlines",
@ -3358,16 +3458,22 @@ def forecast_remaining_sales(loader):
"ECO4 - November"): headline_eco4_original_remaining_revenue
},
{
("", "", "", "HA Name"): "ECO4 Remaining - postcode list - #",
("", "", "", "HA Name"): "ECO4 Sold since November - £",
(
"", "Original Warmfront estimate", "Total - #",
"ECO4 - November"): headline_eco4_sold_since_november
},
{
("", "", "", "HA Name"): "ECO4 Remaining - postcode list (post CIGA) - #",
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): headline_eco4_postcode_list_remaining
},
{
("", "", "", "HA Name"): "ECO4 Remaining - postcode list - £",
("", "", "", "HA Name"): "ECO4 Remaining - postcode list (post CIGA) - £",
("", "Original Warmfront estimate", "Total - #",
"ECO4 - November"): headline_eco4_postcode_list_remaining_revenue
},
{
("", "", "", "HA Name"): "ECO4 delta %",
("", "", "", "HA Name"): "ECO4 £ remaining delta - %",
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): str(headline_eco4_delta) + "%"
},
{
@ -3380,6 +3486,12 @@ def forecast_remaining_sales(loader):
"", "Original Warmfront estimate", "Total - #",
"ECO4 - November"): headline_gbis_original_remaining_revenue
},
{
("", "", "", "HA Name"): "GBIS Sold since November - £",
(
"", "Original Warmfront estimate", "Total - #",
"ECO4 - November"): headline_gbis_sold_since_november
},
{
("", "", "", "HA Name"): "GBIS Remaining - post code list - #",
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): headline_gbis_postcode_list_remaining
@ -3400,7 +3512,7 @@ def forecast_remaining_sales(loader):
"ECO4 - November"): headline_original_total_revenue_remaining
},
{
("", "", "", "HA Name"): "Total Remaining - post code list - £",
("", "", "", "HA Name"): "Total Remaining - post code list (post CIGA) - £",
("", "Original Warmfront estimate", "Total - #",
"ECO4 - November"): headline_postcode_list_total_revenue_remaining
},
@ -3440,14 +3552,16 @@ def forecast_remaining_sales(loader):
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): str(
round(median_eco4_to_install * 100, 1)) + "%",
("ECO4 original", "", "Remaining - #",
""): " - Sales conversion rate for a ECO4 property that didn't need a CIGA check. Job must not cancel"
""): " - Sales conversion rate for a ECO4 property that didn't need a CIGA check. Surveys that resulted "
"in cancelled install are excluded."
},
{
("", "", "", "HA Name"): "Median ECO4 (subect to CIGA) sales conversion rate",
("", "Original Warmfront estimate", "Total - #", "ECO4 - November"): str(
round(median_ciga_pass_to_install * 100, 1)) + "%",
("ECO4 original", "", "Remaining - #",
""): " - Sales conversion rate for a ECO4 property that passed a CIGA check. Job must not cancel"
""): " - Sales conversion rate for a ECO4 property that passed a CIGA check. Surveys that resulted in "
"cancelled installs are excluded."
}
]
@ -3462,23 +3576,7 @@ def forecast_remaining_sales(loader):
pd.DataFrame(assumptions)
]
)
# header_rows = [
# [name[0] for name in results.columns.values],
# [name[1] for name in results.columns.values],
# [name[2] for name in results.columns.values],
# [name[3] for name in results.columns.values]
# ]
# Step 2: Write the transformed header and DataFrame data to CSV.
# Open the file in write mode.
import csv
with open("HA Remaining Analysis.csv", "w", newline="") as file:
# writer = csv.writer(file)
# Write the header rows.
# writer.writerows(header_rows)
# Write the DataFrame data without the index (adjust if you want the index).
results.to_csv(file, header=True, index=False)
@ -3504,8 +3602,12 @@ def app():
# Grab the December HA figures filepath
december_figures_filepath = "local_data/ha_data/HA_December_figures.csv"
# priority_has = [
# "HA1", "HA6", "HA7", "HA14", "HA15", "HA16", "HA24", "HA25", "HA28", "HA32", "HA38", "HA39", "HA107",
# ]
# TODO: Remove ECO3 sales from HA25
priority_has = [
"HA1", "HA6", "HA7", "HA14", "HA15", "HA16", "HA24", "HA25", "HA28", "HA32", "HA38", "HA39", "HA107",
"HA1", "HA6", "HA7", "HA14", "HA15", "HA16", "HA24", "HA28", "HA32", "HA39", "HA107",
]
# Next HAs to do: 15[DONE], 32 [DONE], 33 [Input format is 4 parts and no eco4 jobs identified - come back on this],
# Then: 28 [DONE],