Ensure doctrine-level unicity in entities

master
Julien Rosset 2 months ago
parent 625f9fceb8
commit c30a8735b8

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250603101350 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_DA88B1375E237E06 ON recipe
SQL);
$this->addSql(<<<'SQL'
ALTER TABLE recipe DROP name
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
ALTER TABLE recipe ADD name VARCHAR(50) NOT NULL
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_DA88B1375E237E06 ON recipe (name)
SQL);
}
}

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20250606142337 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_77575DA759D8A214E308AC6F ON input_recipe_material (recipe_id, material_id)
SQL);
$this->addSql(<<<'SQL'
CREATE UNIQUE INDEX UNIQ_CB0D94B259D8A214E308AC6F ON output_recipe_material (recipe_id, material_id)
SQL);
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_77575DA759D8A214E308AC6F ON input_recipe_material
SQL);
$this->addSql(<<<'SQL'
DROP INDEX UNIQ_CB0D94B259D8A214E308AC6F ON output_recipe_material
SQL);
}
}

@ -4,6 +4,7 @@ namespace App\Entity;
use App\Repository\InputRecipeMaterialRepository;
use Doctrine\ORM\Mapping as ORM;
use Stringable;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
@ -11,14 +12,15 @@ use Symfony\Component\Validator\Constraints as Assert;
* A material consumed by a recipe
*/
#[ORM\Entity(repositoryClass: InputRecipeMaterialRepository::class)]
#[ORM\UniqueConstraint(fields: ['recipe', 'material'])]
#[UniqueEntity(fields: ['recipe', 'material'], message: 'Ce matériau est déjà consommé par cette recette')]
class InputRecipeMaterial {
class InputRecipeMaterial implements Stringable {
use TBaseEntity;
/**
* @var Recipe|null The recipe
*/
#[ORM\ManyToOne(inversedBy: 'inputMaterials')]
#[ORM\ManyToOne(inversedBy: 'consumedMaterials')]
#[ORM\JoinColumn(nullable: false, onDelete: 'CASCADE')]
#[Assert\NotNull(message: 'Veuillez sélectionner une recette')]
#[Assert\Valid]
@ -41,6 +43,13 @@ class InputRecipeMaterial {
#[Assert\Positive(message: 'La quantité consommée doit être strictement positive')]
private ?int $consumedQuantity = null;
/**
* @inheritDoc
*/
public function __toString (): string {
return $this->getMaterial()->getName() . ' x' . $this->getConsumedQuantity();
}
/**
* The recipe
*

@ -33,7 +33,6 @@ class Material implements Stringable {
*/
#[ORM\Column]
#[Assert\Type(type: 'bool', message: 'L\'indicateur de si le matériau est craftable par défaut doit être un booléen')]
#[Assert\NotNull(message: 'Veuillez indiquer si le matériau est craftable par défaut')]
private ?bool $isCraftableByDefault = true;
/**

@ -4,6 +4,7 @@ namespace App\Entity;
use App\Repository\OutputRecipeMaterialRepository;
use Doctrine\ORM\Mapping as ORM;
use Stringable;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Validator\Constraints as Assert;
@ -11,8 +12,9 @@ use Symfony\Component\Validator\Constraints as Assert;
* A material produced by a recipe
*/
#[ORM\Entity(repositoryClass: OutputRecipeMaterialRepository::class)]
#[ORM\UniqueConstraint(fields: ['recipe', 'material'])]
#[UniqueEntity(fields: ['recipe', 'material'], message: 'Ce matériau est déjà produite par cette recette')]
class OutputRecipeMaterial {
class OutputRecipeMaterial implements Stringable {
use TBaseEntity;
/**
@ -41,6 +43,13 @@ class OutputRecipeMaterial {
#[Assert\Positive(message: 'La quantité produite doit être strictement positive')]
private ?float $producedQuantity = null;
/**
* @inheritDoc
*/
public function __toString (): string {
return $this->getMaterial()->getName() . ' x' . $this->getProducedQuantity();
}
/**
* The recipe
*

@ -13,9 +13,8 @@ use Symfony\Component\Validator\Constraints as Assert;
* A crafting recipe
*/
#[ORM\Entity(repositoryClass: RecipeRepository::class)]
class Recipe implements Stringable {
class Recipe {
use TBaseEntity;
use TNamedEntity;
/**
* @var Machine|null The crafting machine
@ -49,14 +48,14 @@ class Recipe implements Stringable {
/**
* @var Collection<int, InputRecipeMaterial> The consumed materials
*/
#[ORM\OneToMany(targetEntity: InputRecipeMaterial::class, mappedBy: 'recipe', orphanRemoval: true)]
#[ORM\OneToMany(targetEntity: InputRecipeMaterial::class, mappedBy: 'recipe', cascade: ['persist'], orphanRemoval: true)]
#[Assert\Count(min: 1, minMessage: 'Veuillez ajouter au moins un matériau consommé')]
#[Assert\Valid]
private Collection $consumedMaterials;
/**
* @var Collection<int, OutputRecipeMaterial> The produced materials
*/
#[ORM\OneToMany(targetEntity: OutputRecipeMaterial::class, mappedBy: 'recipe', orphanRemoval: true)]
#[ORM\OneToMany(targetEntity: OutputRecipeMaterial::class, mappedBy: 'recipe', cascade: ['persist'], orphanRemoval: true)]
#[Assert\Count(min: 1, minMessage: 'Veuillez ajouter au moins un matériau produit')]
#[Assert\Valid]
private Collection $producedMaterials;
@ -109,6 +108,7 @@ class Recipe implements Stringable {
$this->machineExtraInfo1 = $machineExtraInfo1;
return $this;
}
/**
* The machine's second extra information
*

Loading…
Cancel
Save