Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automatically calculate total number of plants and seeds #274

Merged
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we beware of the migration?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This migration should work as-is. No loss of data because now its calculated.
django also tells you when you have migrations to run

Original file line number Diff line number Diff line change
@@ -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",
),
]
13 changes: 10 additions & 3 deletions canopeum_backend/canopeum_backend/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand All @@ -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)

Expand Down
35 changes: 23 additions & 12 deletions canopeum_backend/canopeum_backend/serializers.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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


Expand Down Expand Up @@ -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):
Expand Down Expand Up @@ -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):
Expand Down
2 changes: 0 additions & 2 deletions canopeum_backend/canopeum_backend/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"}},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

const fetchBatch = useCallback(
async (siteId: number) => {
// TODO: Use endpoint to get specific batch directly instead of refetching site summary

Check warning on line 30 in canopeum_frontend/src/components/analytics/BatchTable.tsx

View workflow job for this annotation

GitHub Actions / Lint

Unexpected 'TODO' comment: 'TODO: Use endpoint to get specific batch...'
// Also only update required batch, not the entire array
const siteSummary = await getApiClient().siteClient.summary(siteId)
setBatches(siteSummary.batches)
Expand Down Expand Up @@ -281,7 +281,7 @@
key={`batch-${batch.id}-seedCollectedCount`}
style={{ borderColor: cellBorderColor }}
>
{batch.totalNumberSeed}
{batch.totalNumberSeeds}
</td>
))}
</tr>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {
Expand Down Expand Up @@ -144,13 +145,23 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => {
setBatch(current => ({
...current,
species,
plantCount: mapSum(species, 'quantity'),
})),
[],
)}
species={batch.species}
/>
</div>

<div>
<label className='form-label text-capitalize' htmlFor='total-number-of-plants'>
{t('analyticsSite.batch-modal.total-number-of-plants-label')}:&nbsp;
</label>
<span id='total-number-of-plants'>
{batch.plantCount}
</span>
</div>

<div>
<label className='form-label' htmlFor='soil-condition'>
{t('analyticsSite.batch-modal.soil-condition-label')}
Expand Down Expand Up @@ -200,23 +211,6 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => {
species={batch.supportedSpecies}
/>

<div>
<label className='form-label text-capitalize' htmlFor='total-number-of-plants'>
{t('analyticsSite.batch-modal.total-number-of-plants-label')}
</label>
<input
className='form-control'
id='total-number-of-plants'
onChange={event =>
setBatch(value => ({
...value,
plantCount: Number.parseInt(event.target.value, 10),
}))}
type='number'
value={floorNumberValue(batch.plantCount)}
/>
</div>

<div>
<label className='form-label text-capitalize' htmlFor='survived'>
{t('analyticsSite.batch-modal.survived-label')}
Expand Down Expand Up @@ -259,6 +253,7 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => {
setBatch(current => ({
...current,
seeds: species,
totalNumberSeeds: mapSum(species, 'quantity'),
})),
[],
)}
Expand All @@ -267,20 +262,12 @@ const BatchForm = ({ handleBatchChange, initialBatch }: Props) => {
</div>

<div>
<label className='form-label text-capitalize' htmlFor='totalNumberSeed'>
{t('analyticsSite.batch-modal.total-seeds-label')}
<label className='form-label text-capitalize' htmlFor='total-number-seeds'>
{t('analyticsSite.batch-modal.total-seeds-label')}:&nbsp;
</label>
<input
className='form-control'
id='totalNumberSeed'
onChange={event =>
setBatch(value => ({
...value,
totalNumberSeed: Number.parseInt(event.target.value, 10),
}))}
type='number'
value={floorNumberValue(batch.totalNumberSeed)}
/>
<span id='total-number-seeds'>
{batch.totalNumberSeeds}
</span>
</div>

<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,8 @@ const CreateBatchModal = ({ open, site, handleClose }: Props) => {
fertilizers,
mulchLayers,
supportedSpecies,
plantCount,
survivedCount,
replaceCount,
totalNumberSeed,
totalPropagation,
seeds,
species,
Expand All @@ -60,10 +58,8 @@ const CreateBatchModal = ({ open, site, handleClose }: Props) => {
sponsorLogoImage,
size,
soilCondition,
plantCount,
survivedCount,
replaceCount,
totalNumberSeed,
totalPropagation,
batchImage,
fertilizers.map(fertilizer => fertilizer.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@ const BatchModal = ({ batchToEdit, handleClose }: Props) => {
fertilizers,
mulchLayers,
supportedSpecies,
plantCount,
survivedCount,
replaceCount,
totalNumberSeed,
totalPropagation,
seeds,
species,
Expand All @@ -55,10 +53,8 @@ const BatchModal = ({ batchToEdit, handleClose }: Props) => {
sponsorLogoImage,
size,
soilCondition,
plantCount,
survivedCount,
replaceCount,
totalNumberSeed,
totalPropagation,
fertilizers.map(fertilizer => fertilizer.id),
mulchLayers.map(layer => layer.id),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ export type BatchFormDto = {
},
size?: number,
soilCondition?: string,
plantCount?: number,
plantCount: number,
survivedCount?: number,
replaceCount?: number,
totalNumberSeed?: number,
totalNumberSeeds: number,
totalPropagation?: number,
image?: File,
fertilizers: FertilizerType[],
Expand All @@ -34,10 +34,10 @@ export const DEFAULT_BATCH_FORM_DTO: BatchFormDto = {
logo: undefined,
},
supportedSpecies: [],
plantCount: undefined,
plantCount: -1,
survivedCount: undefined,
replaceCount: undefined,
totalNumberSeed: undefined,
totalNumberSeeds: -1,
totalPropagation: undefined,
image: undefined,
fertilizers: [],
Expand Down
Loading
Loading