diff --git a/canopeum_backend/canopeum_backend/management/commands/initialize_database.py b/canopeum_backend/canopeum_backend/management/commands/initialize_database.py index 12427fba7..145b6ef7f 100644 --- a/canopeum_backend/canopeum_backend/management/commands/initialize_database.py +++ b/canopeum_backend/canopeum_backend/management/commands/initialize_database.py @@ -305,7 +305,6 @@ def create_batches_for_site(site): soil_condition="Good", survived_count=survived_count, replace_count=replace_count, - total_number_seed=number_of_seed, total_propagation=random.randint(0, number_of_seed), ) create_batch_species_for_batch(batch) diff --git a/canopeum_backend/canopeum_backend/migrations/0002_remove_batch_total_number_seed.py b/canopeum_backend/canopeum_backend/migrations/0002_remove_batch_total_number_seed.py new file mode 100644 index 000000000..c1c1cd7ed --- /dev/null +++ b/canopeum_backend/canopeum_backend/migrations/0002_remove_batch_total_number_seed.py @@ -0,0 +1,17 @@ +# Generated by Django 5.1 on 2024-10-29 19:34 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ("canopeum_backend", "0001_initial"), + ] + + operations = [ + migrations.RemoveField( + model_name="batch", + name="total_number_seed", + ), + ] diff --git a/canopeum_backend/canopeum_backend/models.py b/canopeum_backend/canopeum_backend/models.py index 53d3cf2f0..80ac06e0c 100644 --- a/canopeum_backend/canopeum_backend/models.py +++ b/canopeum_backend/canopeum_backend/models.py @@ -166,7 +166,7 @@ def get_sponsor_progress(self) -> float: return 0 batches = Batch.objects.filter(site=self) - sponsored_plant_count = sum(batch.plant_count() for batch in batches) + sponsored_plant_count = sum(batch.get_plant_count() for batch in batches) # Note: We don't cap the progress at 100% so it's obvious if there's a data issue return sponsored_plant_count / total_plant_count * 100 @@ -208,10 +208,13 @@ class Batch(models.Model): soil_condition = models.TextField(blank=True, null=True) survived_count = models.IntegerField(blank=True, null=True) replace_count = models.IntegerField(blank=True, null=True) - total_number_seed = models.IntegerField(blank=True, null=True) total_propagation = models.IntegerField(blank=True, null=True) image = models.ForeignKey(Asset, models.DO_NOTHING, blank=True, null=True) + @property + def total_number_seeds(self): + return 100 + def add_fertilizer_by_id(self, pk: int): fertilizer_type = Fertilizertype.objects.get(pk=pk) return Batchfertilizer.objects.create(fertilizer_type=fertilizer_type, batch=self) @@ -232,7 +235,11 @@ def add_supported_specie_by_id(self, pk: int): tree_type = Treetype.objects.get(pk=pk) return BatchSupportedSpecies.objects.create(tree_type=tree_type, batch=self) - def plant_count(self) -> int: + def get_total_number_seeds(self) -> int: + batch_seeds = BatchSeed.objects.filter(batch=self) + return sum(seed.quantity for seed in batch_seeds) + + def get_plant_count(self) -> int: batch_species = BatchSpecies.objects.filter(batch=self) return sum(specie.quantity for specie in batch_species) diff --git a/canopeum_backend/canopeum_backend/serializers.py b/canopeum_backend/canopeum_backend/serializers.py index e41d8da6d..8178979da 100644 --- a/canopeum_backend/canopeum_backend/serializers.py +++ b/canopeum_backend/canopeum_backend/serializers.py @@ -1,7 +1,6 @@ # Pyright does not support duck-typed Meta inner-class # pyright: reportIncompatibleVariableOverride=false -import random from collections.abc import Mapping from decimal import Decimal from typing import Any @@ -419,7 +418,9 @@ class BatchDetailSerializer(serializers.ModelSerializer[Batch]): mulch_layers = serializers.SerializerMethodField() supported_species = serializers.SerializerMethodField() seeds = serializers.SerializerMethodField() + total_number_seeds = serializers.SerializerMethodField() species = serializers.SerializerMethodField() + plant_count = serializers.SerializerMethodField() sponsor = serializers.SerializerMethodField() # HACK to allow handling the image with a AssetSerializer separately # TODO: Figure out how to feed the image directly to BatchDetailSerializer @@ -456,15 +457,21 @@ def get_supported_species(self, obj: Batch): return TreeTypeSerializer(supported_species_types, many=True).data @extend_schema_field(BatchSeedSerializer(many=True)) - def get_seeds(self, obj): + def get_seeds(self, obj: Batch): return BatchSeedSerializer(BatchSeed.objects.filter(batch=obj), many=True).data + def get_total_number_seeds(self, obj: Batch) -> int: + return obj.get_total_number_seeds() + @extend_schema_field(BatchSpeciesSerializer(many=True)) - def get_species(self, obj): + def get_species(self, obj: Batch): return BatchSpeciesSerializer(BatchSpecies.objects.filter(batch=obj), many=True).data + def get_plant_count(self, obj: Batch) -> int: + return obj.get_plant_count() + @extend_schema_field(BatchSponsorSerializer) - def get_sponsor(self, obj): + def get_sponsor(self, obj: Batch): return BatchSponsorSerializer(BatchSponsor.objects.get(batch=obj)).data @@ -551,11 +558,13 @@ def get_plant_count(self, obj: Site) -> int: def get_sponsor_progress(self, obj: Site) -> float: return obj.get_sponsor_progress() - def get_survived_count(self, obj) -> int: - return random.randint(50, 100) # noqa: S311 + def get_survived_count(self, obj: Site) -> int: + batches = Batch.objects.filter(site=obj) + return sum(batch.survived_count or 0 for batch in batches) - def get_propagation_count(self, obj) -> int: - return random.randint(5, 50) # noqa: S311 + def get_propagation_count(self, obj: Site) -> int: + batches = Batch.objects.filter(site=obj) + return sum(batch.total_propagation or 0 for batch in batches) @extend_schema_field(BatchDetailSerializer(many=True)) def get_batches(self, obj): @@ -599,11 +608,13 @@ def get_plant_count(self, obj: Site) -> int: def get_sponsor_progress(self, obj: Site) -> float: return obj.get_sponsor_progress() - def get_survived_count(self, obj) -> int: - return random.randint(50, 100) # noqa: S311 + def get_survived_count(self, obj: Site) -> int: + batches = Batch.objects.filter(site=obj) + return sum(batch.survived_count or 0 for batch in batches) - def get_propagation_count(self, obj) -> int: - return random.randint(5, 50) # noqa: S311 + def get_propagation_count(self, obj: Site) -> int: + batches = Batch.objects.filter(site=obj) + return sum(batch.total_propagation or 0 for batch in batches) @extend_schema_field(BatchSponsorSerializer(many=True)) def get_sponsors(self, obj): diff --git a/canopeum_backend/canopeum_backend/views.py b/canopeum_backend/canopeum_backend/views.py index db353e28e..bf6102695 100644 --- a/canopeum_backend/canopeum_backend/views.py +++ b/canopeum_backend/canopeum_backend/views.py @@ -842,10 +842,8 @@ def delete(self, request: Request, postId): "sponsorLogo": {"type": "string", "format": "binary", "nullable": True}, "size": {"type": "number", "nullable": True}, "soilCondition": {"type": "string", "nullable": True}, - "plantCount": {"type": "number", "nullable": True}, "survivedCount": {"type": "number", "nullable": True}, "replaceCount": {"type": "number", "nullable": True}, - "totalNumberSeed": {"type": "number", "nullable": True}, "totalPropagation": {"type": "number", "nullable": True}, "image": {"type": "string", "format": "binary", "nullable": True}, "fertilizerIds": {"type": "array", "items": {"type": "number"}}, diff --git a/canopeum_frontend/src/components/analytics/BatchTable.tsx b/canopeum_frontend/src/components/analytics/BatchTable.tsx index c91589e08..a7ed31533 100644 --- a/canopeum_frontend/src/components/analytics/BatchTable.tsx +++ b/canopeum_frontend/src/components/analytics/BatchTable.tsx @@ -281,7 +281,7 @@ const BatchTable = (props: Props) => { key={`batch-${batch.id}-seedCollectedCount`} style={{ borderColor: cellBorderColor }} > - {batch.totalNumberSeed} + {batch.totalNumberSeeds} ))} diff --git a/canopeum_frontend/src/components/analytics/batch-modal/BatchForm.tsx b/canopeum_frontend/src/components/analytics/batch-modal/BatchForm.tsx index b05d3aa7c..fe2ac7661 100644 --- a/canopeum_frontend/src/components/analytics/batch-modal/BatchForm.tsx +++ b/canopeum_frontend/src/components/analytics/batch-modal/BatchForm.tsx @@ -9,6 +9,7 @@ import SupportSpeciesSelector from '@components/analytics/SupportSpeciesSelector import TreeSpeciesSelector from '@components/analytics/TreeSpeciesSelector' import type { BatchDetail } from '@services/api' import { getApiBaseUrl } from '@services/apiSettings' +import { mapSum } from '@utils/arrayUtils' import { floorNumberValue } from '@utils/formUtils' type Props = { @@ -144,6 +145,7 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => { setBatch(current => ({ ...current, species, + plantCount: mapSum(species, 'quantity'), })), [], )} @@ -151,6 +153,15 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => { /> +