From 55c74e64b2292c83bf27314f81d009cbac97234d Mon Sep 17 00:00:00 2001 From: indigane <indigane@users.noreply.github.com> Date: Tue, 28 May 2024 09:45:22 +0300 Subject: [PATCH] Add regulated half hitas housing companies report --- backend/hitas/services/housing_company.py | 30 +++++++++ backend/hitas/tests/apis/test_api_reports.py | 68 ++++++++++++++++++++ backend/hitas/urls.py | 9 ++- backend/hitas/views/__init__.py | 3 +- backend/hitas/views/reports.py | 13 +++- backend/openapi.yaml | 21 ++++++ 6 files changed, 141 insertions(+), 3 deletions(-) diff --git a/backend/hitas/services/housing_company.py b/backend/hitas/services/housing_company.py index e2862906a..a2deaa0ea 100644 --- a/backend/hitas/services/housing_company.py +++ b/backend/hitas/services/housing_company.py @@ -340,6 +340,36 @@ def find_regulated_housing_companies_for_reporting() -> list[HousingCompanyWithR ) +def find_regulated_half_hitas_housing_companies_for_reporting() -> list[HousingCompanyWithRegulatedReportAnnotations]: + return list( + HousingCompany.objects.select_related("postal_code") + .prefetch_related( + "real_estates__buildings__apartments", + ) + .filter( + regulation_status=RegulationStatus.REGULATED, + hitas_type=HitasType.HALF_HITAS, + ) + .alias( + _acquisition_price=get_first_sale_acquisition_price("real_estates__buildings__apartments__id"), + ) + .annotate( + _completion_date=max_date_if_all_not_null("real_estates__buildings__apartments__completion_date"), + surface_area=Round(Sum("real_estates__buildings__apartments__surface_area")), + realized_acquisition_price=Sum("_acquisition_price"), + avg_price_per_square_meter=Round( + F("realized_acquisition_price") / F("surface_area"), + precision=2, + ), + apartment_count=Count("real_estates__buildings__apartments"), + ) + .order_by( + "postal_code__value", + "_completion_date", + ) + ) + + def find_unregulated_housing_companies_for_reporting() -> list[HousingCompanyWithUnregulatedReportAnnotations]: return list( HousingCompany.objects.select_related("postal_code") diff --git a/backend/hitas/tests/apis/test_api_reports.py b/backend/hitas/tests/apis/test_api_reports.py index 225b1d30b..b46be09d4 100644 --- a/backend/hitas/tests/apis/test_api_reports.py +++ b/backend/hitas/tests/apis/test_api_reports.py @@ -539,6 +539,74 @@ def test__api__regulated_housing_companies_report__multiple_housing_companies(ap ] +@pytest.mark.django_db +def test__api__regulated_half_hitas_housing_companies_report__multiple_housing_companies(api_client: HitasAPIClient): + housing_company_1: HousingCompany = HousingCompanyFactory.create( + postal_code__value="00001", + postal_code__cost_area=1, + hitas_type=HitasType.HALF_HITAS, + ) + sale_1: ApartmentSale = ApartmentSaleFactory.create( + purchase_date=datetime.date(2020, 1, 1), + purchase_price=50_000, + apartment_share_of_housing_company_loans=10_000, + apartment__surface_area=100, + apartment__completion_date=datetime.date(2020, 1, 1), + apartment__building__real_estate__housing_company=housing_company_1, + ) + + housing_company_2: HousingCompany = HousingCompanyFactory.create( + postal_code__value="00002", + postal_code__cost_area=1, + hitas_type=HitasType.HALF_HITAS, + ) + sale_2: ApartmentSale = ApartmentSaleFactory.create( + purchase_date=datetime.date(2021, 1, 1), + purchase_price=100_000, + apartment_share_of_housing_company_loans=44_000, + apartment__surface_area=50, + apartment__completion_date=datetime.date(2021, 1, 1), + apartment__building__real_estate__housing_company=housing_company_2, + ) + + url = reverse("hitas:regulated-half-hitas-housing-companies-report-list") + response: HttpResponse = api_client.get(url) + + workbook: Workbook = load_workbook(BytesIO(response.content), data_only=False) + worksheet: Worksheet = workbook.worksheets[0] + + assert list(worksheet.values) == [ + ( + "Kalleusalue", + "Postinumero", + "Yhtiö", + "Osoite", + "Valmistumispäivä", + "Asuntojen lukumäärä", + "Keskineliöhinta", + ), + ( + housing_company_1.postal_code.cost_area, + housing_company_1.postal_code.value, + housing_company_1.display_name, + housing_company_1.street_address, + datetime.datetime.fromisoformat(sale_1.apartment.completion_date.isoformat()), + 1, + int(sale_1.total_price / sale_1.apartment.surface_area), + ), + ( + housing_company_2.postal_code.cost_area, + housing_company_2.postal_code.value, + housing_company_2.display_name, + housing_company_2.street_address, + datetime.datetime.fromisoformat(sale_2.apartment.completion_date.isoformat()), + 1, + int(sale_2.total_price / sale_2.apartment.surface_area), + ), + (None, None, None, None, None, None, None), # Empty row at the bottom for filtering and sorting + ] + + @pytest.mark.django_db def test__api__regulated_housing_companies_report__unregulated_not_included(api_client: HitasAPIClient): housing_company_1: HousingCompany = HousingCompanyFactory.create( diff --git a/backend/hitas/urls.py b/backend/hitas/urls.py index 59e98666d..6108ba2f7 100644 --- a/backend/hitas/urls.py +++ b/backend/hitas/urls.py @@ -81,10 +81,17 @@ # /api/v1/reports/download-regulated-housing-companies-report router.register( r"reports/download-regulated-housing-companies-report", - views.RegulateHousingCompaniesReportView, + views.RegulatedHousingCompaniesReportView, basename="regulated-housing-companies-report", ) +# /api/v1/reports/download-regulated-half-hitas-housing-companies-report +router.register( + r"reports/download-regulated-half-hitas-housing-companies-report", + views.RegulatedHalfHitasHousingCompaniesReportView, + basename="regulated-half-hitas-housing-companies-report", +) + # /api/v1/reports/download-unregulated-housing-companies-report router.register( r"reports/download-unregulated-housing-companies-report", diff --git a/backend/hitas/views/__init__.py b/backend/hitas/views/__init__.py index ce5295af9..d899b436d 100644 --- a/backend/hitas/views/__init__.py +++ b/backend/hitas/views/__init__.py @@ -34,7 +34,8 @@ MultipleOwnershipsReportView, OwnershipsByCompanyJSONReportView, OwnershipsByHousingCompanyReport, - RegulateHousingCompaniesReportView, + RegulatedHalfHitasHousingCompaniesReportView, + RegulatedHousingCompaniesReportView, SalesByPostalCodeAndAreaReportView, SalesReportView, UnregulatedHousingCompaniesReportView, diff --git a/backend/hitas/views/reports.py b/backend/hitas/views/reports.py index 7092a35b9..b45fc2799 100644 --- a/backend/hitas/views/reports.py +++ b/backend/hitas/views/reports.py @@ -11,6 +11,7 @@ from hitas.services.apartment_sale import find_sales_on_interval_for_reporting from hitas.services.housing_company import ( find_housing_companies_for_state_reporting, + find_regulated_half_hitas_housing_companies_for_reporting, find_regulated_housing_companies_for_reporting, find_unregulated_housing_companies_for_reporting, ) @@ -57,7 +58,7 @@ def list(self, request: Request, *args, **kwargs) -> HttpResponse: return get_excel_response(filename=filename, excel=workbook) -class RegulateHousingCompaniesReportView(ViewSet): +class RegulatedHousingCompaniesReportView(ViewSet): renderer_classes = [HitasJSONRenderer, ExcelRenderer] def list(self, request: Request, *args, **kwargs) -> HttpResponse: @@ -67,6 +68,16 @@ def list(self, request: Request, *args, **kwargs) -> HttpResponse: return get_excel_response(filename=filename, excel=workbook) +class RegulatedHalfHitasHousingCompaniesReportView(ViewSet): + renderer_classes = [HitasJSONRenderer, ExcelRenderer] + + def list(self, request: Request, *args, **kwargs) -> HttpResponse: + housing_companies = find_regulated_half_hitas_housing_companies_for_reporting() + workbook = build_regulated_housing_companies_report_excel(housing_companies) + filename = "Valvonnan piirissä olevat puolihitas-yhtiöt.xlsx" + return get_excel_response(filename=filename, excel=workbook) + + class UnregulatedHousingCompaniesReportView(ViewSet): renderer_classes = [HitasJSONRenderer, ExcelRenderer] diff --git a/backend/openapi.yaml b/backend/openapi.yaml index 62d9ce12b..bfa122aa2 100644 --- a/backend/openapi.yaml +++ b/backend/openapi.yaml @@ -4008,6 +4008,27 @@ paths: "500": $ref: "#/components/responses/InternalServerError" + /api/v1/reports/download-regulated-half-hitas-housing-companies-report: + get: + description: Download an Excel report of half hitas regulated housing companies + operationId: fetch-regulated-half-hitas-housing-companies-report-excel + tags: + - Reports + responses: + "200": + description: Successfully downloaded a regulated half hitas housing company report + content: + application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: + schema: + type: string + format: binary + "400": + $ref: "#/components/responses/BadRequest" + "404": + $ref: "#/components/responses/NotFound" + "500": + $ref: "#/components/responses/InternalServerError" + /api/v1/reports/download-unregulated-housing-companies-report: get: description: Download an Excel report of housing companies released from regulation