Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 92354d9060 |
Generated
+2
-2
@@ -5,7 +5,7 @@
|
|||||||
<driver-ref>postgresql</driver-ref>
|
<driver-ref>postgresql</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
<jdbc-driver>org.postgresql.Driver</jdbc-driver>
|
||||||
<jdbc-url>jdbc:postgresql://localhost:5433/ferme</jdbc-url>
|
<jdbc-url>jdbc:postgresql://localhost:5432/ferme</jdbc-url>
|
||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
<data-source source="LOCAL" name="Ferme recette" uuid="ae622167-c834-4e7b-87a5-c1721036f5dc">
|
<data-source source="LOCAL" name="Ferme recette" uuid="ae622167-c834-4e7b-87a5-c1721036f5dc">
|
||||||
@@ -16,4 +16,4 @@
|
|||||||
<working-dir>$ProjectFileDir$</working-dir>
|
<working-dir>$ProjectFileDir$</working-dir>
|
||||||
</data-source>
|
</data-source>
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
||||||
Generated
+2
-6
@@ -5,18 +5,14 @@
|
|||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="feat : Ajout de la sélection des bovins étape 3 d'une réception (WIP)">
|
<list default="true" id="7c107abe-5995-4428-8429-b146aaca8386" name="Changes" comment="feat : Ajout de la sélection des bovins étape 3 d'une réception (WIP)">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/dataSources.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/dataSources.xml" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/config/reference.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/reference.php" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/config/reference.php" beforeDir="false" afterPath="$PROJECT_DIR$/config/reference.php" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-bovine-received.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-bovine-received.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-bovine-received.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-bovine-received.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-form.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-form.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-form.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-form.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-product-received.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-product-received.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/frontend/components/reception/reception-product-received.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/reception/reception-product-received.vue" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/components/ui/UiNumberInput.vue" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/components/ui/UiNumberInput.vue" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/frontend/services/dto/reception-data.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/services/dto/reception-data.ts" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/frontend/services/reception.ts" beforeDir="false" afterPath="$PROJECT_DIR$/frontend/services/reception.ts" afterDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/Entity/Reception.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Entity/Reception.php" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Entity/Reception.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Entity/Reception.php" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Repository/.gitignore" beforeDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/Entity/ReceptionBovine.php" beforeDir="false" afterPath="$PROJECT_DIR$/src/Entity/ReceptionBovine.php" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/Repository/BovineTypeRepository.php" beforeDir="false" />
|
|
||||||
<change beforePath="$PROJECT_DIR$/src/Repository/ReceptionBovineRepository.php" beforeDir="false" />
|
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type {BovineTypeData} from "~/services/dto/bovine-type-data";
|
import type {BovineTypeData} from "~/services/dto/bovine-type-data";
|
||||||
import {getBovineTypeList} from "~/services/bovine-type";
|
import {getBovineTypeList} from "~/services/bovine-type";
|
||||||
import {RECEPTION_TYPE_CODES} from "~/utils/constants";
|
import {MERCHANDISE_TYPE_CODES, RECEPTION_TYPE_CODES} from "~/utils/constants";
|
||||||
import {useReceptionStore} from '~/stores/reception'
|
import {useReceptionStore} from '~/stores/reception'
|
||||||
import {
|
import {
|
||||||
createReceptionBovine,
|
createReceptionBovine,
|
||||||
@@ -46,7 +46,6 @@ import {
|
|||||||
} from "~/services/reception-bovine";
|
} from "~/services/reception-bovine";
|
||||||
import {computed, onMounted, reactive, ref, watch} from "vue";
|
import {computed, onMounted, reactive, ref, watch} from "vue";
|
||||||
|
|
||||||
const toast = useToast()
|
|
||||||
const isLoadingBovineType = ref(false)
|
const isLoadingBovineType = ref(false)
|
||||||
const bovineType = ref<BovineTypeData[]>([])
|
const bovineType = ref<BovineTypeData[]>([])
|
||||||
const receptionStore = useReceptionStore()
|
const receptionStore = useReceptionStore()
|
||||||
@@ -56,13 +55,19 @@ const receptionId = computed(() => receptionStore.current?.id ?? null)
|
|||||||
const receptionIri = computed(() =>
|
const receptionIri = computed(() =>
|
||||||
receptionId.value ? `/api/receptions/${receptionId.value}` : null
|
receptionId.value ? `/api/receptions/${receptionId.value}` : null
|
||||||
)
|
)
|
||||||
const totalBovines = computed(() => {
|
const toast = useToast()
|
||||||
const base = Object.values(bovineQuantities).reduce((sum, value) => {
|
const nuxtApp = useNuxtApp()
|
||||||
return sum + (value ?? 0)
|
const i18n = nuxtApp.$i18n as { t: (key: string) => string } |
|
||||||
|
undefined
|
||||||
|
const t = (key: string) => (i18n?.t ? String(i18n.t(key)) : key)
|
||||||
|
const totalBovineQuantity = computed(() => {
|
||||||
|
const baseTotal = Object.values(bovineQuantities).reduce((sum, value) => {
|
||||||
|
const n = typeof value === 'number' ? value : 0
|
||||||
|
return sum + n
|
||||||
}, 0)
|
}, 0)
|
||||||
return base + (otherQuantity.value ?? 0)
|
const other = typeof otherQuantity.value === 'number' ? otherQuantity.value : 0
|
||||||
|
return baseTotal + other
|
||||||
})
|
})
|
||||||
|
|
||||||
const loadBovineType = async () => {
|
const loadBovineType = async () => {
|
||||||
isLoadingBovineType.value = true
|
isLoadingBovineType.value = true
|
||||||
try {
|
try {
|
||||||
@@ -112,7 +117,6 @@ watch(
|
|||||||
async function syncBovineSelections(receptionIri: string) {
|
async function syncBovineSelections(receptionIri: string) {
|
||||||
const existing = await getReceptionBovineList(receptionIri)
|
const existing = await getReceptionBovineList(receptionIri)
|
||||||
const existingMap = new Map<string, { id: number; quantity: number | null }>()
|
const existingMap = new Map<string, { id: number; quantity: number | null }>()
|
||||||
|
|
||||||
for (const selection of existing) {
|
for (const selection of existing) {
|
||||||
const bovineTypeId = String(selection.bovineType.id)
|
const bovineTypeId = String(selection.bovineType.id)
|
||||||
existingMap.set(bovineTypeId, {
|
existingMap.set(bovineTypeId, {
|
||||||
@@ -155,21 +159,37 @@ async function syncBovineSelections(receptionIri: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const hasNegativeQuantity = computed(() => {
|
||||||
|
const anyNegativeInTypes =
|
||||||
|
Object.values(bovineQuantities).some((value) => {
|
||||||
|
return typeof value === 'number' && value < 0
|
||||||
|
})
|
||||||
|
|
||||||
|
const otherNegative =
|
||||||
|
typeof otherQuantity.value === 'number' &&
|
||||||
|
otherQuantity.value < 0
|
||||||
|
|
||||||
|
return anyNegativeInTypes || otherNegative
|
||||||
|
})
|
||||||
async function goNext() {
|
async function goNext() {
|
||||||
if (!receptionStore.current || !receptionIri.value) {
|
if (!receptionStore.current || !receptionIri.value) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if (hasNegativeQuantity.value) {
|
||||||
// @TODO Ajouter un composable pour le toaster qui gère les key i18n
|
toast.error({
|
||||||
if (totalBovines.value > 52) {
|
title: 'Erreur',
|
||||||
|
message: ("La quantité de bovins ne peut pas être négative.")
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// Le 52 à vérifier
|
||||||
|
if (totalBovineQuantity.value > 52) {
|
||||||
toast.error({
|
toast.error({
|
||||||
title: 'Erreur',
|
title: 'Erreur',
|
||||||
message: ('Le total des bovins ne peut pas dépasser 52.')
|
message: ('Le total des bovins ne peut pas dépasser 52.')
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const nextStep = receptionStore.current.currentStep + 1
|
const nextStep = receptionStore.current.currentStep + 1
|
||||||
await syncBovineSelections(receptionIri.value)
|
await syncBovineSelections(receptionIri.value)
|
||||||
|
|
||||||
|
|||||||
@@ -222,12 +222,10 @@ const filteredVehicles = computed<VehicleData[]>(() => {
|
|||||||
(!form.truckId || String(vehicle.truck?.id) === form.truckId)
|
(!form.truckId || String(vehicle.truck?.id) === form.truckId)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
const selectedReceptionType = computed(() =>
|
const selectedReceptionType = computed(() =>
|
||||||
receptionTypes.value.find((type) => String(type.id) === form.receptionTypeId) ?? null
|
receptionTypes.value.find((type) => String(type.id) === form.receptionTypeId) ?? null
|
||||||
)
|
)
|
||||||
|
|
||||||
// Supprime les données bovines si on change de type de réception
|
|
||||||
const clearReceptionBovines = async (receptionIri: string) => {
|
const clearReceptionBovines = async (receptionIri: string) => {
|
||||||
const existing = await getReceptionBovineList(receptionIri)
|
const existing = await getReceptionBovineList(receptionIri)
|
||||||
for (const selection of existing) {
|
for (const selection of existing) {
|
||||||
@@ -473,6 +471,9 @@ async function validate() {
|
|||||||
const normalizedTruckId = form.truckId.trim()
|
const normalizedTruckId = form.truckId.trim()
|
||||||
const normalizedCarrierId = form.carrierId.trim()
|
const normalizedCarrierId = form.carrierId.trim()
|
||||||
const normalizedDriverId = form.driverId.trim()
|
const normalizedDriverId = form.driverId.trim()
|
||||||
|
const previousTypeCode = receptionStore.current.receptionType?.code ?? null
|
||||||
|
const nextTypeCode = selectedReceptionType.value?.code ?? null
|
||||||
|
const receptionIri = `/api/receptions/${receptionStore.current.id}`
|
||||||
const receptionTypeIri = normalizedReceptionTypeId
|
const receptionTypeIri = normalizedReceptionTypeId
|
||||||
? `/api/reception_types/${normalizedReceptionTypeId}`
|
? `/api/reception_types/${normalizedReceptionTypeId}`
|
||||||
: null
|
: null
|
||||||
@@ -521,11 +522,6 @@ async function validate() {
|
|||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const previousTypeCode = receptionStore.current.receptionType?.code ?? null
|
|
||||||
const nextTypeCode = selectedReceptionType.value?.code ?? null
|
|
||||||
const receptionIri = `/api/receptions/${receptionStore.current.id}`
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
previousTypeCode === RECEPTION_TYPE_CODES.BOVINS &&
|
previousTypeCode === RECEPTION_TYPE_CODES.BOVINS &&
|
||||||
nextTypeCode === RECEPTION_TYPE_CODES.MERCHANDISES
|
nextTypeCode === RECEPTION_TYPE_CODES.MERCHANDISES
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col items-center gap-16">
|
<div class="flex flex-col items-center gap-16">
|
||||||
|
<!-- @TODO voir pour séparer dans un composant au moment de l'implémentation des Bovins -->
|
||||||
<div
|
<div
|
||||||
v-if="receptionStore.current?.receptionType?.code === RECEPTION_TYPE_CODES.MERCHANDISES"
|
v-if="receptionStore.current?.receptionType?.code === RECEPTION_TYPE_CODES.MERCHANDISES"
|
||||||
class="flex flex-col gap-16 items-center w-full">
|
class="flex flex-col gap-16 items-center w-full">
|
||||||
@@ -98,6 +99,7 @@ const selectedBuildingIds = ref<string[]>([])
|
|||||||
const selectedPelletBuildingIds = ref<Record<string, string[]>>({})
|
const selectedPelletBuildingIds = ref<Record<string, string[]>>({})
|
||||||
const merchandiseDetail = ref('')
|
const merchandiseDetail = ref('')
|
||||||
|
|
||||||
|
|
||||||
// Extrait l'ID d'une relation depuis un IRI ou un objet complet.
|
// Extrait l'ID d'une relation depuis un IRI ou un objet complet.
|
||||||
const getRelationId = (value: unknown): string | null => {
|
const getRelationId = (value: unknown): string | null => {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
disabled ? 'cursor-not-allowed' : 'cursor-text',
|
disabled ? 'cursor-not-allowed' : 'cursor-text',
|
||||||
inputClass
|
inputClass
|
||||||
]"
|
]"
|
||||||
@keydown="onKeydown"
|
|
||||||
@input="onInput"
|
@input="onInput"
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -79,13 +78,7 @@ const onInput = (event: Event) => {
|
|||||||
emit('update:modelValue', null)
|
emit('update:modelValue', null)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
const numeric = Math.max(0, Number(target.value))
|
const numeric = Number(target.value)
|
||||||
emit('update:modelValue', Number.isNaN(numeric) ? null : numeric)
|
emit('update:modelValue', Number.isNaN(numeric) ? null : numeric)
|
||||||
}
|
}
|
||||||
|
|
||||||
const onKeydown = (event: KeyboardEvent) => {
|
|
||||||
if (event.key === '-' || event.key === 'e' || event.key === 'E') {
|
|
||||||
event.preventDefault()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -2,10 +2,9 @@ import {useApi} from '~/composables/useApi'
|
|||||||
import type {ReceptionData, ReceptionPayload} from '~/services/dto/reception-data'
|
import type {ReceptionData, ReceptionPayload} from '~/services/dto/reception-data'
|
||||||
import type {WeightData} from '~/services/dto/weight-data'
|
import type {WeightData} from '~/services/dto/weight-data'
|
||||||
|
|
||||||
export async function getReceptionList(isValid: boolean|null = null) {
|
export async function getReceptionList() {
|
||||||
const api = useApi()
|
const api = useApi()
|
||||||
const query = isValid !== null ? { isValid: isValid} : {}
|
return api.get<ReceptionData>(`receptions`, {}, {
|
||||||
return api.get<ReceptionData[]>('receptions', query, {
|
|
||||||
toastErrorKey: 'errors.reception.list'
|
toastErrorKey: 'errors.reception.list'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use ApiPlatform\Doctrine\Orm\Filter\BooleanFilter;
|
|
||||||
use ApiPlatform\Metadata\ApiFilter;
|
|
||||||
use ApiPlatform\Metadata\ApiProperty;
|
use ApiPlatform\Metadata\ApiProperty;
|
||||||
use ApiPlatform\Metadata\ApiResource;
|
use ApiPlatform\Metadata\ApiResource;
|
||||||
use ApiPlatform\Metadata\Get;
|
use ApiPlatform\Metadata\Get;
|
||||||
@@ -28,7 +26,6 @@ use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer;
|
|||||||
#[ORM\Entity]
|
#[ORM\Entity]
|
||||||
#[ORM\HasLifecycleCallbacks]
|
#[ORM\HasLifecycleCallbacks]
|
||||||
#[ORM\Table(name: 'reception')]
|
#[ORM\Table(name: 'reception')]
|
||||||
#[ApiFilter(BooleanFilter::class, properties: ['isValid'])]
|
|
||||||
#[ApiResource(
|
#[ApiResource(
|
||||||
operations: [
|
operations: [
|
||||||
new Get(
|
new Get(
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\BovineType;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<BovineType>
|
||||||
|
*/
|
||||||
|
class BovineTypeRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, BovineType::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return BovineType[] Returns an array of BovineType objects
|
||||||
|
// */
|
||||||
|
// public function findByExampleField($value): array
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('b')
|
||||||
|
// ->andWhere('b.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->orderBy('b.id', 'ASC')
|
||||||
|
// ->setMaxResults(10)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public function findOneBySomeField($value): ?BovineType
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('b')
|
||||||
|
// ->andWhere('b.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getOneOrNullResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\ReceptionBovine;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<ReceptionBovine>
|
||||||
|
*/
|
||||||
|
class ReceptionBovineRepository extends ServiceEntityRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, ReceptionBovine::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * @return ReceptionBovine[] Returns an array of ReceptionBovine objects
|
||||||
|
// */
|
||||||
|
// public function findByExampleField($value): array
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('r')
|
||||||
|
// ->andWhere('r.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->orderBy('r.id', 'ASC')
|
||||||
|
// ->setMaxResults(10)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// public function findOneBySomeField($value): ?ReceptionBovine
|
||||||
|
// {
|
||||||
|
// return $this->createQueryBuilder('r')
|
||||||
|
// ->andWhere('r.exampleField = :val')
|
||||||
|
// ->setParameter('val', $value)
|
||||||
|
// ->getQuery()
|
||||||
|
// ->getOneOrNullResult()
|
||||||
|
// ;
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\State;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\Operation;
|
||||||
|
use App\State\BovinIdentificationProvider;
|
||||||
|
use DateTimeImmutable;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Api\BovinApiInterface;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\AnimalFileDto;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\BovinIdentificationDto;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\BovinRef;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\DateValueDto;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\ExploitationRef;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\MovementDto;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\ParentInfoDto;
|
||||||
|
use Malio\EdnotifBundle\Bovin\Dto\PresencePeriodDto;
|
||||||
|
use Malio\EdnotifBundle\Shared\Dto\StandardResponseDto;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class BovinIdentificationProviderTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testReturnsNullWhenNumeroNationalMissing(): void
|
||||||
|
{
|
||||||
|
$api = $this->createMock(BovinApiInterface::class);
|
||||||
|
$api->expects(self::never())->method('getAnimalFile');
|
||||||
|
|
||||||
|
$provider = new BovinIdentificationProvider($api);
|
||||||
|
|
||||||
|
$result = $provider->provide($this->createStub(Operation::class), []);
|
||||||
|
|
||||||
|
self::assertNull($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testMapsIdentificationAndPresencePeriods(): void
|
||||||
|
{
|
||||||
|
$api = $this->createMock(BovinApiInterface::class);
|
||||||
|
|
||||||
|
$identification = new BovinIdentificationDto(
|
||||||
|
bovin: new BovinRef('FR', 'IGNORED'),
|
||||||
|
sex: 'F',
|
||||||
|
breedType: 'LIM',
|
||||||
|
birthDate: new DateValueDto(new DateTimeImmutable('2024-01-02'), 'Y'),
|
||||||
|
workNumber: 'W123',
|
||||||
|
isFilie: true,
|
||||||
|
motherCarrier: new ParentInfoDto(new BovinRef('FR', 'MOM1'), 'CHA'),
|
||||||
|
fatherIpg: new ParentInfoDto(new BovinRef('FR', 'DAD1'), 'BBB'),
|
||||||
|
birthExploitation: new ExploitationRef('FR', 'EXP1'),
|
||||||
|
);
|
||||||
|
|
||||||
|
$presencePeriods = [
|
||||||
|
new PresencePeriodDto(
|
||||||
|
new MovementDto(new DateTimeImmutable('2024-03-01'), 'ENTRY', null),
|
||||||
|
new MovementDto(new DateTimeImmutable('2024-03-10'), 'EXIT', null),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
|
$animalFile = new AnimalFileDto(
|
||||||
|
new StandardResponseDto(true, null),
|
||||||
|
$identification,
|
||||||
|
$presencePeriods,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
$api->expects(self::once())
|
||||||
|
->method('getAnimalFile')
|
||||||
|
->with('FR123', 'FR')
|
||||||
|
->willReturn($animalFile)
|
||||||
|
;
|
||||||
|
|
||||||
|
$provider = new BovinIdentificationProvider($api);
|
||||||
|
|
||||||
|
$result = $provider->provide(
|
||||||
|
$this->createStub(Operation::class),
|
||||||
|
['numeroNational' => 'FR123']
|
||||||
|
);
|
||||||
|
|
||||||
|
self::assertNotNull($result);
|
||||||
|
self::assertSame('FR123', $result->numeroNational);
|
||||||
|
self::assertSame('F', $result->sex);
|
||||||
|
self::assertSame('LIM', $result->breedType);
|
||||||
|
self::assertSame('W123', $result->workNumber);
|
||||||
|
self::assertSame('2024-01-02', $result->birthDate);
|
||||||
|
self::assertSame('Y', $result->birthDateCompletenessFlag);
|
||||||
|
self::assertTrue($result->isFilie);
|
||||||
|
self::assertSame('MOM1', $result->motherNationalNumber);
|
||||||
|
self::assertSame('CHA', $result->motherBreedType);
|
||||||
|
self::assertSame('DAD1', $result->fatherNationalNumber);
|
||||||
|
self::assertSame('BBB', $result->fatherBreedType);
|
||||||
|
self::assertSame('EXP1', $result->birthExploitationNumber);
|
||||||
|
|
||||||
|
self::assertCount(1, $result->presencePeriods);
|
||||||
|
self::assertSame('2024-03-01', $result->presencePeriods[0]->entryDate);
|
||||||
|
self::assertSame('ENTRY', $result->presencePeriods[0]->entryCause);
|
||||||
|
self::assertSame('2024-03-10', $result->presencePeriods[0]->exitDate);
|
||||||
|
self::assertSame('EXIT', $result->presencePeriods[0]->exitCause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace App\Tests\State;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\Operation;
|
||||||
|
use App\Entity\User;
|
||||||
|
use App\State\MeProvider;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @internal
|
||||||
|
*/
|
||||||
|
final class MeProviderTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testProvideReturnUser(): void
|
||||||
|
{
|
||||||
|
$user = new User();
|
||||||
|
|
||||||
|
$security = $this->createStub(Security::class);
|
||||||
|
$security->method('getUser')->willReturn($user);
|
||||||
|
|
||||||
|
$provider = new MeProvider($security);
|
||||||
|
|
||||||
|
$result = $provider->provide($this->createStub(Operation::class));
|
||||||
|
|
||||||
|
self::assertSame($user, $result);
|
||||||
|
self::assertInstanceOf(User::class, $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testProvideThrowAccessDeniedException(): void
|
||||||
|
{
|
||||||
|
$user = null;
|
||||||
|
|
||||||
|
$security = $this->createStub(Security::class);
|
||||||
|
$security->method('getUser')->willReturn($user);
|
||||||
|
|
||||||
|
$provider = new MeProvider($security);
|
||||||
|
|
||||||
|
$this->expectException(AccessDeniedException::class);
|
||||||
|
$this->expectExceptionMessage('User not authenticated.');
|
||||||
|
|
||||||
|
$provider->provide($this->createStub(Operation::class));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user