diff --git a/django/api/constants/constants.py b/django/api/constants/constants.py index 74da2492..28a0b442 100644 --- a/django/api/constants/constants.py +++ b/django/api/constants/constants.py @@ -11,6 +11,7 @@ from api.models.public_charging import PublicCharging from api.models.scrap_it import ScrapIt from api.models.go_electric_rebates import GoElectricRebates +from api.models.cvp_data import CVPData from api.services.spreadsheet_uploader_prep import ( prepare_arc_project_tracking, prepare_hydrogen_fleets, @@ -19,6 +20,7 @@ prepare_public_charging, prepare_scrap_it, prepare_go_electric_rebates, + prepare_cvp_data, validate_phone_numbers, typo_checker, location_checker, @@ -27,7 +29,7 @@ region_checker ) from api.services.resolvers import get_google_resolver -from api.constants.misc import GER_VALID_FIELD_VALUES, ARC_VALID_FIELD_VALUES, LOCALITY_FEATURES_MAP +from api.constants.misc import GER_VALID_FIELD_VALUES, ARC_VALID_FIELD_VALUES, LOCALITY_FEATURES_MAP, CVP_DATA_VALID_FIELD_VALUES from enum import Enum @@ -423,6 +425,99 @@ class GoElectricRebatesColumnMapping(Enum): rebate_adjustment = "Rebate adjustment (discount)" notes = "Notes" +class CVPDataColumns(Enum): + FUNDING_CALL = "FC" + PROJECT_IDENTIFIER = "Project Identifier" + APPLICANT_NAME = "Name of Applicant" + RANK = "Rank" + STATUS = "Status" + SCORE = "Score" + VEHICLE_DEPLOYED = "Vehicle Deployed" + VEHICLE_CATEGORY = "Vehicle Category" + DRIVE_TYPE = "Drive Type" + VEHICLE_TYPE = "Vehicle Type" + PORTFOLIO = "Portfolio" + MAKE_AND_MODEL = "Vehicle Make and Model" + ECONOMIC_REGION = "Economic Region" + START_DATE = "Start Date" + COMPLETION_DATE = "Completion Date" + PROJECT_TYPE = "Project Type" + CLASS_3 = "Class 3" + CLASS_4 = "Class 4" + CLASS_5 = "Class 5" + CLASS_6 = "Class 6" + CLASS_7 = "Class 7" + CLASS_8 = "Class 8" + ON_ROAD_TOTAL = "On Road Total" + OFF_ROAD = "Off-Road" + LEVEL_2_CHARGER = "Level 2 Charger (3.3 kW to 19.2 kW)" + LEVEL_3_CHARGER = "Level 3 Charger (20 kW to 49 kW)" + HIGH_LEVEL_3_CHARGER = "Level 3 Charger (50 kW to 99kW)" + LEVEL_CHARGER = "Level Charger (100 kW and above)" + OTHER_CHARGER = "Other Charger" + H2_FUELING_STATION = "H2 Fueling Station" + CHARGER_BRAND = "Charger Brand" + H2_FUELLING_STATION_DESCRIPTION = "H2 Fuelling Station Description" + GHG_EMISSION_REDUCTION = "Proponent's GHG Emission Reduction (tCO2e/yr)" + ESTIMATED_GHG_EMISSION_REDUCTION = "Le-ef Estimated GHG Reduction (tCO2e/yr)" + FUNDING_EFFICIENCY = "Funding Efficiency for Emmision Abatment ($/tCO2e)" + MARKET_EMISSION_REDUCTIONS = "Market Emission Reductions (tCO2e by 2030)" + CVP_FUNDING_REQUEST = "CVP Program Funding Request (Initial)" + CVP_FUNDING_CONTRIBUTION = "CVP Funding (approved - Contribution Agreement)" + EXTERNAL_FUNDING = "External Funding" + PROPONENT_FUNDING = "Proponent funding" + PROJECT_COST_INITIAL = "Total project cost (initial)" + PROJECT_COST_REVISED = "Total Project Cost (revised)" + FUNDING_SOURCE = "Funding Source" + NOTES = "Notes" + IMHZEV = "iMHZEV" + +class CVPDataColumnMapping(Enum): + funding_call = "FC" + project_identifier = "Project Identifier" + applicant_name = "Name of Applicant" + rank = "Rank" + status = "Status" + score = "Score" + vehicle_deployed = "Vehicle Deployed" + vehicle_category = "Vehicle Category" + drive_type = "Drive Type" + vehicle_type = "Vehicle Type" + portfolio = "Portfolio" + make_and_model = "Vehicle Make and Model" + economic_region = "Economic Region" + start_date = "Start Date" + completion_date = "Completion Date" + project_type = "Project Type" + class_3 = "Class 3" + class_4 = "Class 4" + class_5 = "Class 5" + class_6 = "Class 6" + class_7 = "Class 7" + class_8 = "Class 8" + on_road_total = "On Road Total" + off_road = "Off-Road" + level_2_charger = "Level 2 Charger (3.3 kW to 19.2 kW)" + level_3_charger = "Level 3 Charger (20 kW to 49 kW)" + high_level_3_charger = "Level 3 Charger (50 kW to 99kW)" + level_charger = "Level Charger (100 kW and above)" + other_charger = "Other Charger" + h2_fuelling_station = "H2 Fueling Station" + charger_brand = "Charger Brand" + h2_fuelling_station_description = "H2 Fuelling Station Description" + ghg_emission_reduction = "Proponent's GHG Emission Reduction (tCO2e/yr)" + estimated_ghg_emission_reduction = "Le-ef Estimated GHG Reduction (tCO2e/yr)" + funding_efficiency = "Funding Efficiency for Emmision Abatment ($/tCO2e)" + market_emission_reductions = "Market Emission Reductions (tCO2e by 2030)" + cvp_funding_request = "CVP Program Funding Request (Initial)" + cvp_funding_contribution = "CVP Funding (approved - Contribution Agreement)" + external_funding = "External Funding" + proponent_funding = "Proponent funding" + project_cost_initial = "Total project cost (initial)" + project_cost_revised = "Total Project Cost (revised)" + funding_source = "Funding Source" + notes = "Notes" + imhzev = "iMHZEV" FIELD_TYPES = { @@ -607,6 +702,54 @@ class GoElectricRebatesColumnMapping(Enum): "rebate_adjustment": str, "notes": str, }, + "CVP Data": { + "funding_call": int, + "project_identifier": int, + "applicant_name": str, + "rank": int, + "status": str, + "score": int, + "vehicle_deployed": str, + "vehicle_category": str, + "drive_type": str, + "vehicle_type": str, + "portfolio": str, + "make_and_model": str, + "economic_region": str, + "start_date": datetime.date, + "completion_date": datetime.date, + "project_type": str, + "class_3": int, + "class_4": int, + "class_5": int, + "class_6": int, + "class_7": int, + "class_8": int, + "on_road_total": int, + "off_road": int, + "level_2_charger": int, + "level_3_charger": int, + "high_level_3_charger": int, + "level_charger": int, + "other_charger": int, + "h2_fuelling_station": int, + "charger_brand": str, + "h2_fuelling_station_description": str, + "ghg_emission_reduction": int, + "estimated_ghg_emission_reduction": int, + "funding_efficiency": int, + "market_emission_reductions": int, + "cvp_funding_request": int, + "cvp_funding_contribution": int, + "external_funding": int, + "proponent_funding": int, + "project_cost_initial": int, + "project_cost_revised": int, + "funding_source": str, + "notes": str, + "imhzev": str, + }, + } @@ -685,4 +828,13 @@ class GoElectricRebatesColumnMapping(Enum): {"function": validate_field_values, "columns": [], "kwargs": {"indices_offset":2, "fields_and_values": GER_VALID_FIELD_VALUES}}, ] }, + "CVP Data": { + "model": CVPData, + "columns": CVPDataColumns, + "column_mapping": CVPDataColumnMapping, + "sheet_name": "Data", + "preparation_functions": [prepare_cvp_data], + "validation_functions": [{"function": validate_field_values, "columns": [], "kwargs": {"indices_offset":2, "fields_and_values": CVP_DATA_VALID_FIELD_VALUES}},] + }, + } diff --git a/django/api/constants/misc.py b/django/api/constants/misc.py index 18efbfc8..10dc15f5 100644 --- a/django/api/constants/misc.py +++ b/django/api/constants/misc.py @@ -87,4 +87,29 @@ ], 'Fuel Type': ['H2', 'Electric'], 'Retrofit': ['BEV Retrofit', 'Hybrid Retrofit', 'H2 Retrofit', 'N/A'] -} \ No newline at end of file +} + +CVP_DATA_VALID_FIELD_VALUES = { + 'Funding Call': ['1', '2', '3', '4', '5', '6', '7', '8', '10'], + 'Status': ['Approved', 'Completed', 'Terminated', 'Not Approved', 'Application Withdrawn'], + 'Vehicles Deployed': ['Yes', 'No'], + 'Vehicle Category': ['On-Road', 'Off-Road', 'Marine', 'Rail', 'Aviation'], + 'Portfolio': [ + 'Road - 8', 'Rail', 'Marine', 'Road - 8C', 'School Bus', + 'Loader', 'Road - 6', 'Fork Lift', 'Recreation' + ], + 'Economic Region': [ + 'Nechako', 'Northeast', 'North Coast', 'Cariboo', 'Vancouver Island/Coast', + 'Mainland/Southwest', 'Thompson/Okanagan', 'Kootenay', 'Across BC' + ], + 'Drive Type': ['BEV', 'FC', 'PHEV'], + 'Vehicle Type': [ + 'On-Road', 'Loader', 'Excavator', 'Forklift', 'Outboard Motor', + 'Tugboat', 'Passenger Ferry', 'Ice Resurfacer', 'Locomotive', + 'Rail Maintenance', 'Rubber-tired Gantry Crane', 'Terminal/Yard truck', + 'Aircraft', 'Jet Fuel Pumper', 'Train Mover' + ], + 'Project Type': [ + 'Procurement', 'New Design', 'Hybrid Retrofit', 'BEV Retrofit', 'H2 Retrofit' + ] +} diff --git a/django/api/migrations/0034_cvpdata.py b/django/api/migrations/0034_cvpdata.py new file mode 100644 index 00000000..d8218f3c --- /dev/null +++ b/django/api/migrations/0034_cvpdata.py @@ -0,0 +1,71 @@ +# Generated by Django 3.2.25 on 2024-09-10 21:38 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0033_regions'), + ] + + operations = [ + migrations.CreateModel( + name='CVPData', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('create_timestamp', models.DateTimeField(auto_now_add=True, null=True)), + ('create_user', models.CharField(default='SYSTEM', max_length=130)), + ('update_timestamp', models.DateTimeField(auto_now=True, null=True)), + ('update_user', models.CharField(max_length=130, null=True)), + ('funding_call', models.IntegerField(max_length=5)), + ('project_identifier', models.IntegerField(max_length=5)), + ('applicant_name', models.CharField(max_length=50)), + ('rank', models.IntegerField(blank=True, max_length=3, null=True)), + ('status', models.CharField(max_length=50)), + ('score', models.IntegerField(blank=True, max_length=5, null=True)), + ('vehicle_deployed', models.CharField(max_length=50)), + ('vehicle_category', models.CharField(max_length=50)), + ('drive_type', models.CharField(max_length=50)), + ('vehicle_type', models.CharField(max_length=50)), + ('portfolio', models.CharField(max_length=50)), + ('make_and_model', models.CharField(max_length=50)), + ('economic_region', models.CharField(max_length=150)), + ('start_date', models.DateField(blank=True, null=True)), + ('completion_date', models.DateField(blank=True, null=True)), + ('project_type', models.CharField(max_length=50)), + ('class_3', models.IntegerField(blank=True, max_length=3, null=True)), + ('class_4', models.IntegerField(blank=True, max_length=3, null=True)), + ('class_5', models.IntegerField(blank=True, max_length=3, null=True)), + ('class_6', models.IntegerField(blank=True, max_length=3, null=True)), + ('class_7', models.IntegerField(blank=True, max_length=3, null=True)), + ('class_8', models.IntegerField(blank=True, max_length=3, null=True)), + ('on_road_total', models.IntegerField(blank=True, max_length=5, null=True)), + ('off_road', models.IntegerField(blank=True, max_length=5, null=True)), + ('level_2_charger', models.IntegerField(blank=True, max_length=5, null=True)), + ('level_3_charger', models.IntegerField(blank=True, max_length=5, null=True)), + ('high_level_3_charger', models.IntegerField(blank=True, max_length=5, null=True)), + ('level_charger', models.IntegerField(blank=True, max_length=5, null=True)), + ('other_charger', models.IntegerField(blank=True, max_length=5, null=True)), + ('h2_fuelling_station', models.IntegerField(blank=True, max_length=5, null=True)), + ('charger_brand', models.CharField(blank=True, max_length=50, null=True)), + ('h2_fuelling_station_description', models.CharField(blank=True, max_length=500, null=True)), + ('ghg_emission_reduction', models.IntegerField(blank=True, max_length=5, null=True)), + ('estimated_ghg_emission_reduction', models.IntegerField(blank=True, max_length=5, null=True)), + ('funding_efficiency', models.IntegerField(blank=True, max_length=5, null=True)), + ('market_emission_reductions', models.IntegerField(blank=True, max_length=5, null=True)), + ('cvp_funding_request', models.IntegerField(max_length=10)), + ('cvp_funding_contribution', models.IntegerField(max_length=10)), + ('external_funding', models.IntegerField(blank=True, max_length=10, null=True)), + ('proponent_funding', models.IntegerField(blank=True, max_length=10, null=True)), + ('project_cost_initial', models.IntegerField(max_length=10)), + ('project_cost_revised', models.IntegerField(max_length=10)), + ('funding_source', models.CharField(blank=True, max_length=50, null=True)), + ('notes', models.CharField(blank=True, max_length=500, null=True)), + ('imhzev', models.CharField(blank=True, max_length=50, null=True)), + ], + options={ + 'db_table': 'cvp_data', + }, + ), + ] diff --git a/django/api/migrations/0035_auto_20240910_2143.py b/django/api/migrations/0035_auto_20240910_2143.py new file mode 100644 index 00000000..1fb18028 --- /dev/null +++ b/django/api/migrations/0035_auto_20240910_2143.py @@ -0,0 +1,165 @@ +# Generated by Django 3.2.25 on 2024-09-10 21:43 + +from django.db import migrations, models + +def add_cvp_data_to_datasets(apps, schema_editor): + + Datasets = apps.get_model('api', 'Datasets') + + Datasets.objects.get_or_create( + create_timestamp="2024-09-10 00:00:00+00", + create_user="user", + name="CVP Data" + ) + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0034_cvpdata'), + ] + + + + operations = [ + migrations.AlterField( + model_name='cvpdata', + name='class_3', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='class_4', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='class_5', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='class_6', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='class_7', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='class_8', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='cvp_funding_contribution', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='cvp_funding_request', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='estimated_ghg_emission_reduction', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='external_funding', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='funding_call', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='funding_efficiency', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='ghg_emission_reduction', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='h2_fuelling_station', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='high_level_3_charger', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='level_2_charger', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='level_3_charger', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='level_charger', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='market_emission_reductions', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='off_road', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='on_road_total', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='other_charger', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='project_cost_initial', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='project_cost_revised', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='project_identifier', + field=models.IntegerField(), + ), + migrations.AlterField( + model_name='cvpdata', + name='proponent_funding', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='rank', + field=models.IntegerField(blank=True, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='score', + field=models.IntegerField(blank=True, null=True), + ), + migrations.RunPython(add_cvp_data_to_datasets), + ] diff --git a/django/api/migrations/0036_auto_20240911_1758.py b/django/api/migrations/0036_auto_20240911_1758.py new file mode 100644 index 00000000..8441653b --- /dev/null +++ b/django/api/migrations/0036_auto_20240911_1758.py @@ -0,0 +1,73 @@ +# Generated by Django 3.2.25 on 2024-09-11 17:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0035_auto_20240910_2143'), + ] + + operations = [ + migrations.AlterField( + model_name='cvpdata', + name='applicant_name', + field=models.CharField(max_length=500), + ), + migrations.AlterField( + model_name='cvpdata', + name='charger_brand', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='drive_type', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='funding_source', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='imhzev', + field=models.CharField(blank=True, max_length=100, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='make_and_model', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='portfolio', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='project_type', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='status', + field=models.CharField(max_length=500), + ), + migrations.AlterField( + model_name='cvpdata', + name='vehicle_category', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='vehicle_deployed', + field=models.CharField(max_length=100), + ), + migrations.AlterField( + model_name='cvpdata', + name='vehicle_type', + field=models.CharField(max_length=100), + ), + ] diff --git a/django/api/migrations/0037_auto_20240911_1800.py b/django/api/migrations/0037_auto_20240911_1800.py new file mode 100644 index 00000000..b432e335 --- /dev/null +++ b/django/api/migrations/0037_auto_20240911_1800.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2.25 on 2024-09-11 18:00 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('api', '0036_auto_20240911_1758'), + ] + + operations = [ + migrations.AlterField( + model_name='cvpdata', + name='funding_source', + field=models.CharField(blank=True, max_length=500, null=True), + ), + migrations.AlterField( + model_name='cvpdata', + name='imhzev', + field=models.CharField(blank=True, max_length=500, null=True), + ), + ] diff --git a/django/api/models/__init__.py b/django/api/models/__init__.py index 1e02db9e..d1fc14cc 100644 --- a/django/api/models/__init__.py +++ b/django/api/models/__init__.py @@ -26,3 +26,4 @@ from . import uploaded_vin_record from . import decoded_vin_record from . import regions +from . import cvp_data diff --git a/django/api/models/cvp_data.py b/django/api/models/cvp_data.py new file mode 100644 index 00000000..06a007a8 --- /dev/null +++ b/django/api/models/cvp_data.py @@ -0,0 +1,188 @@ +from auditable.models import Auditable +from django.db import models + + +class CVPData(Auditable): + + funding_call = models.IntegerField( + blank=False, null=False + ) + + project_identifier = models.IntegerField( + blank=False, null=False + ) + + applicant_name = models.CharField( + blank=False, null=False, max_length=500 + ) + + rank = models.IntegerField( + blank=True, null=True + ) + + status = models.CharField( + blank=False, null=False, max_length=500 + ) + + score = models.IntegerField( + blank=True, null=True + ) + + vehicle_deployed = models.CharField( + blank=False, null=False, max_length=100 + ) + + vehicle_category = models.CharField( + blank=False, null=False, max_length=100 + ) + + drive_type = models.CharField( + blank=False, null=False, max_length=100 + ) + + vehicle_type = models.CharField( + blank=False, null=False, max_length=100 + ) + + portfolio = models.CharField( + blank=False, null=False, max_length=100 + ) + + make_and_model = models.CharField( + blank=False, null=False, max_length=100 + ) + + economic_region = models.CharField( + blank=False, null=False, max_length=150 + ) + + start_date = models.DateField( + blank=True, null=True + ) + + completion_date = models.DateField( + blank=True, null=True + ) + + project_type = models.CharField( + blank=False, null=False, max_length=100 + ) + + class_3 = models.IntegerField( + blank=True, null=True + ) + + class_4 = models.IntegerField( + blank=True, null=True + ) + + class_5 = models.IntegerField( + blank=True, null=True + ) + + class_6 = models.IntegerField( + blank=True, null=True + ) + + class_7 = models.IntegerField( + blank=True, null=True + ) + + class_8 = models.IntegerField( + blank=True, null=True + ) + + on_road_total = models.IntegerField( + blank=True, null=True + ) + + off_road = models.IntegerField( + blank=True, null=True + ) + + level_2_charger = models.IntegerField( + blank=True, null=True + ) + + level_3_charger = models.IntegerField( + blank=True, null=True + ) + + high_level_3_charger = models.IntegerField( + blank=True, null=True + ) + + level_charger = models.IntegerField( + blank=True, null=True + ) + + other_charger = models.IntegerField( + blank=True, null=True + ) + + h2_fuelling_station = models.IntegerField( + blank=True, null=True + ) + + charger_brand = models.CharField( + blank=True, null=True, max_length=100 + ) + + h2_fuelling_station_description = models.CharField( + blank=True, null=True, max_length=500 + ) + + ghg_emission_reduction = models.IntegerField( + blank=True, null=True + ) + + estimated_ghg_emission_reduction = models.IntegerField( + blank=True, null=True + ) + + funding_efficiency = models.IntegerField( + blank=True, null=True + ) + + market_emission_reductions = models.IntegerField( + blank=True, null=True + ) + + cvp_funding_request = models.IntegerField( + blank=False, null=False + ) + + cvp_funding_contribution = models.IntegerField( + blank=False, null=False + ) + + external_funding = models.IntegerField( + blank=True, null=True + ) + + proponent_funding = models.IntegerField( + blank=True, null=True + ) + + project_cost_initial = models.IntegerField( + blank=False, null=False + ) + + project_cost_revised = models.IntegerField( + blank=False, null=False + ) + + funding_source = models.CharField( + blank=True, null=True, max_length=500 + ) + + notes = models.CharField( + blank=True, null=True, max_length=500 + ) + + imhzev = models.CharField( + blank=True, null=True, max_length=500 + ) + + class Meta: + db_table = "cvp_data" diff --git a/django/api/services/spreadsheet_uploader_prep.py b/django/api/services/spreadsheet_uploader_prep.py index 9bd685f4..f85f6ceb 100644 --- a/django/api/services/spreadsheet_uploader_prep.py +++ b/django/api/services/spreadsheet_uploader_prep.py @@ -104,6 +104,12 @@ def prepare_go_electric_rebates(df): adjust_ger_manufacturer_names(df) return df +def prepare_cvp_data(df): + df = df.applymap(lambda s: s.upper() if type(s) == str else s) + df = df.apply(lambda x: x.fillna(0) if x.dtype.kind in "biufc" else x.fillna("")) + + return df + def format_case(s, case = 'skip', ignore_list = []): s[s.notna()] = ( s[s.notna()] # I am applying this function to non NaN values only. If you do not, they get converted from NaN to nan and are more annoying to work with. @@ -317,7 +323,7 @@ def validate_field_values(df, *columns, **kwargs): indices = [] series = df[column] for index, value in series.items(): - if str(value) not in allowed_values[column] and value != '' and value is not None and not pd.isna(value): + if str(value).upper() not in (item.upper() for item in allowed_values[column]) and value != '' and value is not None and not pd.isna(value): indices.append(index + kwargs.get("indices_offset", 0)) if indices: result[column] = {