mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-06-30 13:10:47 +00:00
working on funding
This commit is contained in:
parent
41f3998c1d
commit
a6daeab889
4 changed files with 129 additions and 72 deletions
2
.idea/Model.iml
generated
2
.idea/Model.iml
generated
|
|
@ -7,7 +7,7 @@
|
||||||
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/open_uprn" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/recommendations" isTestSource="false" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="jdk" jdkName="Stonewater-wave-3" jdkType="Python SDK" />
|
<orderEntry type="jdk" jdkName="Fastapi-backend" jdkType="Python SDK" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
</component>
|
</component>
|
||||||
<component name="PyNamespacePackagesService">
|
<component name="PyNamespacePackagesService">
|
||||||
|
|
|
||||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
|
|
@ -3,7 +3,7 @@
|
||||||
<component name="Black">
|
<component name="Black">
|
||||||
<option name="sdkName" value="Python 3.10 (backend)" />
|
<option name="sdkName" value="Python 3.10 (backend)" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ProjectRootManager" version="2" project-jdk-name="Stonewater-wave-3" project-jdk-type="Python SDK" />
|
<component name="ProjectRootManager" version="2" project-jdk-name="Fastapi-backend" project-jdk-type="Python SDK" />
|
||||||
<component name="PyCharmProfessionalAdvertiser">
|
<component name="PyCharmProfessionalAdvertiser">
|
||||||
<option name="shown" value="true" />
|
<option name="shown" value="true" />
|
||||||
</component>
|
</component>
|
||||||
|
|
|
||||||
|
|
@ -98,11 +98,14 @@ class Funding:
|
||||||
self,
|
self,
|
||||||
scheme: str,
|
scheme: str,
|
||||||
eligible: bool,
|
eligible: bool,
|
||||||
|
types: List[str],
|
||||||
measure_types: List[str],
|
measure_types: List[str],
|
||||||
|
project_score: float,
|
||||||
estimated_funding: float,
|
estimated_funding: float,
|
||||||
notify_tenant_benefits_requirements: bool,
|
notify_tenant_benefits_requirements: bool,
|
||||||
notify_council_tax_band_requirements: bool,
|
notify_council_tax_band_requirements: bool,
|
||||||
notify_tenant_low_income_requirements: bool,
|
notify_tenant_low_income_requirements: bool,
|
||||||
|
innovation_required: bool,
|
||||||
):
|
):
|
||||||
""""
|
""""
|
||||||
"""
|
"""
|
||||||
|
|
@ -113,11 +116,14 @@ class Funding:
|
||||||
return {
|
return {
|
||||||
"scheme": scheme,
|
"scheme": scheme,
|
||||||
"eligible": eligible,
|
"eligible": eligible,
|
||||||
|
"type": types,
|
||||||
"measure_types": measure_types,
|
"measure_types": measure_types,
|
||||||
|
"project_score": project_score,
|
||||||
"estimated_funding": estimated_funding,
|
"estimated_funding": estimated_funding,
|
||||||
"requires_benefits": notify_tenant_benefits_requirements,
|
"requires_benefits": notify_tenant_benefits_requirements,
|
||||||
"requires_council_tax_band": notify_council_tax_band_requirements,
|
"requires_council_tax_band": notify_council_tax_band_requirements,
|
||||||
"requires_low_income": notify_tenant_low_income_requirements
|
"requires_low_income": notify_tenant_low_income_requirements,
|
||||||
|
"innovation_required": innovation_required,
|
||||||
}
|
}
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|
@ -140,7 +146,7 @@ class Funding:
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def find_best_gbis_measure(self, measures):
|
def find_gbis_measures(self, measures):
|
||||||
"""
|
"""
|
||||||
The best measure is one that:
|
The best measure is one that:
|
||||||
1) Creates some SAP movement, therefore enables eligiblity
|
1) Creates some SAP movement, therefore enables eligiblity
|
||||||
|
|
@ -247,21 +253,26 @@ class Funding:
|
||||||
) and
|
) and
|
||||||
(self.council_tax_band in [None, "A", "B", "C", "D"])
|
(self.council_tax_band in [None, "A", "B", "C", "D"])
|
||||||
):
|
):
|
||||||
# We find the best measure for GBIS
|
# This function pulls out the various measures that can provide funding under GBIS
|
||||||
recommended_measure = self.find_best_gbis_measure(
|
recommended_measures = self.find_gbis_measures(
|
||||||
measures=[m for m in valid_measures if m not in ["cavity_wall_insulation", "loft_insulation"]]
|
measures=[m for m in valid_measures if m not in ["cavity_wall_insulation", "loft_insulation"]]
|
||||||
)
|
)
|
||||||
# If the council tax band is missing, we nofify the customer that this is a requirement that
|
# If the council tax band is missing, we nofify the customer that this is a requirement that
|
||||||
# should be checked
|
# should be checked
|
||||||
return self.output(
|
return [
|
||||||
scheme="gbis",
|
self.output(
|
||||||
eligible=True,
|
scheme="gbis",
|
||||||
measure_types=[recommended_measure["measure_type"]],
|
eligible=True,
|
||||||
estimated_funding=recommended_measure["estimated_funding"],
|
types=[m["type"]], # This is single measure so we only have one type
|
||||||
notify_tenant_benefits_requirements=False,
|
measure_types=[m["measure_type"]],
|
||||||
notify_council_tax_band_requirements=self.council_tax_band is None,
|
project_score=m["project_score"],
|
||||||
notify_tenant_low_income_requirements=False,
|
estimated_funding=m["estimated_funding"],
|
||||||
)
|
notify_tenant_benefits_requirements=False,
|
||||||
|
notify_council_tax_band_requirements=self.council_tax_band is None,
|
||||||
|
notify_tenant_low_income_requirements=False,
|
||||||
|
innovation_required=False
|
||||||
|
) for m in recommended_measures
|
||||||
|
]
|
||||||
|
|
||||||
# Low income/flex
|
# Low income/flex
|
||||||
if (
|
if (
|
||||||
|
|
@ -271,28 +282,83 @@ class Funding:
|
||||||
# Find the best measure, and can also include CWI/LI but requires the tenant to be
|
# Find the best measure, and can also include CWI/LI but requires the tenant to be
|
||||||
# low inome or on benefits
|
# low inome or on benefits
|
||||||
# We find the best measure for GBIS
|
# We find the best measure for GBIS
|
||||||
recommended_measure = self.find_best_gbis_measure(measures=valid_measures)
|
recommended_measures = self.find_gbis_measures(measures=valid_measures)
|
||||||
return self.output(
|
return [
|
||||||
scheme="gbis",
|
self.output(
|
||||||
eligible=True,
|
scheme="gbis",
|
||||||
measure_types=[recommended_measure["measure_type"]],
|
eligible=True,
|
||||||
estimated_funding=recommended_measure["estimated_funding"],
|
types=[m["type"]], # This is single measure so we only have one type
|
||||||
notify_tenant_benefits_requirements=True,
|
measure_types=[m["measure_type"]],
|
||||||
notify_council_tax_band_requirements=False,
|
project_score=m["project_score"],
|
||||||
notify_tenant_low_income_requirements=True,
|
estimated_funding=m["estimated_funding"],
|
||||||
)
|
notify_tenant_benefits_requirements=True,
|
||||||
|
notify_council_tax_band_requirements=False,
|
||||||
|
notify_tenant_low_income_requirements=True,
|
||||||
|
innovation_required=False
|
||||||
|
) for m in recommended_measures
|
||||||
|
]
|
||||||
|
|
||||||
# Otherwise, no funding availability
|
# Otherwise, no funding availability
|
||||||
return self.output(
|
return []
|
||||||
scheme="gbis",
|
|
||||||
eligible=False,
|
def gbis_social(self):
|
||||||
measure_types=[],
|
"""
|
||||||
estimated_funding=0,
|
Because this is social housing, we have two typical means for eligibility
|
||||||
notify_tenant_benefits_requirements=False,
|
1) EPC D, where an innovation measure is required
|
||||||
notify_council_tax_band_requirements=False,
|
2) EPC G-E, where an innovation measure isn't required
|
||||||
notify_tenant_low_income_requirements=False
|
:return:
|
||||||
|
"""
|
||||||
|
valid_measures = [
|
||||||
|
"internal_wall_insulation",
|
||||||
|
"external_wall_insulation",
|
||||||
|
"flat_roof_insulation",
|
||||||
|
"suspended_floor_insulation",
|
||||||
|
"room_roof_insulation",
|
||||||
|
# Not available for every eligiblity type
|
||||||
|
"cavity_wall_insulation",
|
||||||
|
"loft_insulation",
|
||||||
|
"heating_control"
|
||||||
|
]
|
||||||
|
|
||||||
|
recommended_measures = self.find_gbis_measures(
|
||||||
|
measures=valid_measures
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# All measures are available
|
||||||
|
if self.starting_sap == "D":
|
||||||
|
return [
|
||||||
|
self.output(
|
||||||
|
scheme="gbis",
|
||||||
|
eligible=True,
|
||||||
|
types=[m["type"]], # This is single measure so we only have one type
|
||||||
|
measure_types=[m["measure_type"]],
|
||||||
|
project_score=m["project_score"],
|
||||||
|
estimated_funding=m["estimated_funding"],
|
||||||
|
notify_tenant_benefits_requirements=False,
|
||||||
|
notify_council_tax_band_requirements=False,
|
||||||
|
notify_tenant_low_income_requirements=False,
|
||||||
|
innovation_required=True
|
||||||
|
) for m in recommended_measures
|
||||||
|
]
|
||||||
|
|
||||||
|
if self.starting_sap in ["G", "F", "E"]:
|
||||||
|
return [
|
||||||
|
self.output(
|
||||||
|
scheme="gbis",
|
||||||
|
eligible=True,
|
||||||
|
types=[m["type"]], # This is single measure so we only have one type
|
||||||
|
measure_types=[m["measure_type"]],
|
||||||
|
project_score=m["project_score"],
|
||||||
|
estimated_funding=m["estimated_funding"],
|
||||||
|
notify_tenant_benefits_requirements=False,
|
||||||
|
notify_council_tax_band_requirements=False,
|
||||||
|
notify_tenant_low_income_requirements=False,
|
||||||
|
innovation_required=False
|
||||||
|
) for m in recommended_measures
|
||||||
|
]
|
||||||
|
|
||||||
|
return []
|
||||||
|
|
||||||
def gbis(self):
|
def gbis(self):
|
||||||
"""
|
"""
|
||||||
Check if a property is eligible for GBIS
|
Check if a property is eligible for GBIS
|
||||||
|
|
@ -303,24 +369,33 @@ class Funding:
|
||||||
self.gbis_eligibiltiy = self.gbis_prs()
|
self.gbis_eligibiltiy = self.gbis_prs()
|
||||||
return
|
return
|
||||||
|
|
||||||
|
if self.tenure == "Social":
|
||||||
|
self.gbis_eligibiltiy = self.gbis_social()
|
||||||
|
|
||||||
raise NotImplementedError("Implement social/oo")
|
raise NotImplementedError("Implement social/oo")
|
||||||
|
|
||||||
def whlg(self):
|
def whlg(self):
|
||||||
if self.tenure == "Social":
|
if self.tenure == "Social":
|
||||||
# We can't do anything for social housing
|
# We can't do anything for social housing
|
||||||
self.whlg_eligibility = self.output(
|
self.whlg_eligibility = []
|
||||||
scheme="whlg",
|
|
||||||
eligible=False,
|
|
||||||
measure_types=[],
|
|
||||||
estimated_funding=0,
|
|
||||||
notify_tenant_benefits_requirements=False,
|
|
||||||
notify_council_tax_band_requirements=False,
|
|
||||||
notify_tenant_low_income_requirements=False
|
|
||||||
)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.whlg_eligible_postcodes.empty:
|
if not self.whlg_eligible_postcodes.empty:
|
||||||
print("Eligible implement me!")
|
raise Exception("Implement me")
|
||||||
|
# self.whlg_eligibility = [
|
||||||
|
# self.output(
|
||||||
|
# scheme,
|
||||||
|
# eligible,
|
||||||
|
# types,
|
||||||
|
# measure_types,
|
||||||
|
# project_score: float,
|
||||||
|
# estimated_funding: float,
|
||||||
|
# notify_tenant_benefits_requirements: bool,
|
||||||
|
# notify_council_tax_band_requirements: bool,
|
||||||
|
# notify_tenant_low_income_requirements: bool,
|
||||||
|
# innovation_required: bool,
|
||||||
|
# )
|
||||||
|
# ]
|
||||||
|
|
||||||
def eco4(self):
|
def eco4(self):
|
||||||
if self.tenure == "Private":
|
if self.tenure == "Private":
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ from dotenv import load_dotenv
|
||||||
from utils.s3 import save_csv_to_s3
|
from utils.s3 import save_csv_to_s3
|
||||||
from etl.find_my_epc.AssetListEpcData import AssetListEpcData
|
from etl.find_my_epc.AssetListEpcData import AssetListEpcData
|
||||||
|
|
||||||
PORTFOLIO_ID = 134
|
PORTFOLIO_ID = 138
|
||||||
USER_ID = 8
|
USER_ID = 8
|
||||||
|
|
||||||
load_dotenv(dotenv_path="backend/.env")
|
load_dotenv(dotenv_path="backend/.env")
|
||||||
|
|
@ -19,25 +19,15 @@ def app():
|
||||||
|
|
||||||
asset_list = [
|
asset_list = [
|
||||||
{
|
{
|
||||||
"address": "Flat 2, 42 Malden Road, London NW5 3HG",
|
"address": "42 Rippolson Road",
|
||||||
"postcode": "NW5 3HG",
|
"postcode": "SE18 1NS",
|
||||||
"uprn": 5117165,
|
"uprn": 100020999275,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"address": "15 Bournville Lane",
|
"address": "66 Riverdale Road",
|
||||||
"postcode": "B30 2JY",
|
"postcode": "DA8 1PX",
|
||||||
"uprn": 100070301128
|
"uprn": 100020235516
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"address": "34 Bournville Lane",
|
|
||||||
"postcode": "B30 2LN",
|
|
||||||
"uprn": 100070301140
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"address": "36 Bournville Lane",
|
|
||||||
"postcode": "B30 2LN",
|
|
||||||
"uprn": 100070301142
|
|
||||||
}
|
|
||||||
]
|
]
|
||||||
asset_list = pd.DataFrame(asset_list)
|
asset_list = pd.DataFrame(asset_list)
|
||||||
|
|
||||||
|
|
@ -67,20 +57,12 @@ def app():
|
||||||
|
|
||||||
valuation_data = [
|
valuation_data = [
|
||||||
{
|
{
|
||||||
"uprn": 5117165,
|
"valuation": 469_000,
|
||||||
"valuation": 467_000
|
"uprn": 100020999275,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"uprn": 100070301128,
|
"valuation": 382_000,
|
||||||
"valuation": 335_000
|
"uprn": 100020235516
|
||||||
},
|
|
||||||
{
|
|
||||||
"uprn": 100070301140,
|
|
||||||
"valuation": 276_000
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"uprn": 100070301142,
|
|
||||||
"valuation": 276_000
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
# Store valuation data to s3
|
# Store valuation data to s3
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue