diff --git a/config/bundles.php b/config/bundles.php index 19b2cda..9dbe7c2 100644 --- a/config/bundles.php +++ b/config/bundles.php @@ -13,4 +13,5 @@ Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], Ambta\DoctrineEncryptBundle\AmbtaDoctrineEncryptBundle::class => ['all' => true], + AutoMapper\Symfony\Bundle\AutoMapperBundle::class => ['all' => true], ]; diff --git a/src/ApiResource/Project/ProjectApiResource.php b/src/ApiResource/Project/ProjectApiResource.php index f8cf273..235bb21 100644 --- a/src/ApiResource/Project/ProjectApiResource.php +++ b/src/ApiResource/Project/ProjectApiResource.php @@ -57,4 +57,11 @@ class ProjectApiResource #[API\ApiFilter(filterClass: SearchFilter::class, strategy: 'exact')] #[API\ApiProperty(securityPostDenormalize: 'is_granted("PROJECT_EDIT")')] public ProjectStatus $status = ProjectStatus::InEditing; + + /** + * List of the ProjectRewards this Project offers. + * + * @var array + */ + public array $rewards; } diff --git a/src/ApiResource/Project/RewardApiResource.php b/src/ApiResource/Project/RewardApiResource.php new file mode 100644 index 0000000..bf34027 --- /dev/null +++ b/src/ApiResource/Project/RewardApiResource.php @@ -0,0 +1,73 @@ +setOwner($owner); + + return $accounting; + } + public function __construct() { /* diff --git a/src/Entity/Interface/UserOwnedInterface.php b/src/Entity/Interface/UserOwnedInterface.php index c615e78..e2d7408 100644 --- a/src/Entity/Interface/UserOwnedInterface.php +++ b/src/Entity/Interface/UserOwnedInterface.php @@ -9,4 +9,6 @@ interface UserOwnedInterface public function getOwner(): ?User; public function isOwnedBy(User $user): bool; + + public function setOwner(User $user): static; } diff --git a/src/Entity/Project/Project.php b/src/Entity/Project/Project.php index c358896..d91b71a 100644 --- a/src/Entity/Project/Project.php +++ b/src/Entity/Project/Project.php @@ -4,15 +4,18 @@ use App\Entity\Accounting\Accounting; use App\Entity\Interface\AccountingOwnerInterface; +use App\Entity\Interface\UserOwnedInterface; use App\Entity\Trait\MigratedEntity; use App\Entity\Trait\TimestampedCreationEntity; use App\Entity\Trait\TimestampedUpdationEntity; use App\Entity\User\User; use App\Repository\Project\ProjectRepository; +use Doctrine\Common\Collections\ArrayCollection; +use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; #[ORM\Entity(repositoryClass: ProjectRepository::class)] -class Project implements AccountingOwnerInterface +class Project implements UserOwnedInterface, AccountingOwnerInterface { use MigratedEntity; use TimestampedCreationEntity; @@ -50,12 +53,16 @@ class Project implements AccountingOwnerInterface #[ORM\Column(type: 'string', enumType: ProjectStatus::class)] private ProjectStatus $status; + /** + * @var Collection + */ + #[ORM\OneToMany(mappedBy: 'project', targetEntity: Reward::class)] + private Collection $rewards; + public function __construct() { - $accounting = new Accounting(); - $accounting->setOwner($this); - - $this->accounting = $accounting; + $this->accounting = Accounting::of($this); + $this->rewards = new ArrayCollection(); } public function getId(): ?int @@ -63,6 +70,13 @@ public function getId(): ?int return $this->id; } + public function setId(int $id): static + { + $this->id = $id; + + return $this; + } + public function getTitle(): ?string { return $this->title; @@ -92,6 +106,11 @@ public function getOwner(): ?User return $this->owner; } + public function isOwnedBy(User $user): bool + { + return $user->getId() === $this->owner->getId(); + } + public function setOwner(?User $owner): static { $this->owner = $owner; @@ -110,4 +129,34 @@ public function setStatus(ProjectStatus $status): static return $this; } + + /** + * @return Collection + */ + public function getRewards(): Collection + { + return $this->rewards; + } + + public function addReward(Reward $reward): static + { + if (!$this->rewards->contains($reward)) { + $this->rewards->add($reward); + $reward->setProject($this); + } + + return $this; + } + + public function removeReward(Reward $reward): static + { + if ($this->rewards->removeElement($reward)) { + // set the owning side to null (unless already changed) + if ($reward->getProject() === $this) { + $reward->setProject(null); + } + } + + return $this; + } } diff --git a/src/Entity/Project/Reward.php b/src/Entity/Project/Reward.php new file mode 100644 index 0000000..7d9e4e1 --- /dev/null +++ b/src/Entity/Project/Reward.php @@ -0,0 +1,186 @@ + + */ + #[ORM\OneToMany(mappedBy: 'reward', targetEntity: RewardClaim::class)] + private Collection $claims; + + public function __construct() + { + $this->claims = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getProject(): ?Project + { + return $this->project; + } + + public function setProject(?Project $project): static + { + $this->project = $project; + + return $this; + } + + public function getTitle(): ?string + { + return $this->title; + } + + public function setTitle(string $title): static + { + $this->title = $title; + + return $this; + } + + public function getDescription(): ?string + { + return $this->description; + } + + public function setDescription(?string $description): static + { + $this->description = $description; + + return $this; + } + + public function getMoney(): ?Money + { + return $this->money; + } + + public function setMoney(Money $money): static + { + $this->money = $money; + + return $this; + } + + public function hasUnits(): bool + { + return $this->hasUnits; + } + + public function setHasUnits(bool $hasUnits): static + { + $this->hasUnits = $hasUnits; + + return $this; + } + + public function getUnitsTotal(): ?int + { + return $this->unitsTotal; + } + + public function setUnitsTotal(int $unitsTotal): static + { + $this->unitsTotal = $unitsTotal; + + return $this; + } + + public function getUnitsAvailable(): ?int + { + return $this->unitsAvailable; + } + + public function setUnitsAvailable(int $unitsAvailable): static + { + $this->unitsAvailable = $unitsAvailable; + + return $this; + } + + /** + * @return Collection + */ + public function getClaims(): Collection + { + return $this->claims; + } + + public function addClaim(RewardClaim $claim): static + { + if (!$this->claims->contains($claim)) { + $this->claims->add($claim); + $claim->setReward($this); + } + + return $this; + } + + public function removeClaim(RewardClaim $claim): static + { + if ($this->claims->removeElement($claim)) { + // set the owning side to null (unless already changed) + if ($claim->getReward() === $this) { + $claim->setReward(null); + } + } + + return $this; + } +} diff --git a/src/Entity/Project/RewardClaim.php b/src/Entity/Project/RewardClaim.php new file mode 100644 index 0000000..4dc14fd --- /dev/null +++ b/src/Entity/Project/RewardClaim.php @@ -0,0 +1,59 @@ +id; + } + + public function getReward(): ?Reward + { + return $this->reward; + } + + public function setReward(?Reward $reward): static + { + $this->reward = $reward; + + return $this; + } + + public function getOwner(): ?User + { + return $this->owner; + } + + public function isOwnedBy(User $user): bool + { + return $this->owner->getId() === $user->getId(); + } + + public function setOwner(?User $owner): static + { + $this->owner = $owner; + + return $this; + } +} diff --git a/src/Entity/Tipjar.php b/src/Entity/Tipjar.php index 621bd84..8a177e7 100644 --- a/src/Entity/Tipjar.php +++ b/src/Entity/Tipjar.php @@ -40,10 +40,7 @@ class Tipjar implements AccountingOwnerInterface public function __construct() { - $accounting = new Accounting(); - $accounting->setOwner($this); - - $this->accounting = $accounting; + $this->accounting = Accounting::of($this); } public function getId(): ?int diff --git a/src/Entity/Trait/MigratedEntity.php b/src/Entity/Trait/MigratedEntity.php index 07a3135..e8bd672 100644 --- a/src/Entity/Trait/MigratedEntity.php +++ b/src/Entity/Trait/MigratedEntity.php @@ -3,6 +3,7 @@ namespace App\Entity\Trait; use ApiPlatform\Metadata as API; +use AutoMapper\Attribute\MapFrom; use Doctrine\ORM\Mapping as ORM; trait MigratedEntity @@ -18,6 +19,7 @@ trait MigratedEntity * Previous ID of the entity in the Goteo v3 platform. */ #[API\ApiProperty(writable: false)] + #[MapFrom(if: 'isMigrated')] #[ORM\Column(length: 255, nullable: true)] protected ?string $migratedId = null; diff --git a/src/Entity/User/User.php b/src/Entity/User/User.php index 20bdc8a..d913e88 100644 --- a/src/Entity/User/User.php +++ b/src/Entity/User/User.php @@ -21,7 +21,7 @@ * Users represent people who interact with the platform.\ * \ * Users are the usual issuers of funding, however an User's Accounting can still be a Transaction recipient. - * This allows to keep an User's "wallet", witholding their non-raised fundings into their Accounting. + * This allows to keep an User's "wallet", withholding their non-raised fundings into their Accounting. */ #[Gedmo\Loggable()] #[UniqueEntity(fields: ['username'], message: 'This usernames already exists.')] @@ -106,10 +106,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface, Account public function __construct() { - $accounting = new Accounting(); - $accounting->setOwner($this); - - $this->accounting = $accounting; + $this->accounting = Accounting::of($this); $this->emailConfirmed = false; $this->active = false; diff --git a/src/Library/Benzina/Pump/ProjectsPump.php b/src/Library/Benzina/Pump/ProjectsPump.php index 1b6b78d..dbf609d 100644 --- a/src/Library/Benzina/Pump/ProjectsPump.php +++ b/src/Library/Benzina/Pump/ProjectsPump.php @@ -159,20 +159,20 @@ private function getOwners(array $record): array private function getProjectStatus(int $status): ProjectStatus { switch ($status) { - case 0: - return ProjectStatus::Rejected; case 1: return ProjectStatus::InEditing; case 2: return ProjectStatus::InReview; + case 0: + return ProjectStatus::Rejected; case 3: return ProjectStatus::InCampaign; + case 6: + return ProjectStatus::Unfunded; case 4: return ProjectStatus::InFunding; case 5: return ProjectStatus::Fulfilled; - case 6: - return ProjectStatus::Unfunded; } } diff --git a/src/Repository/Project/RewardClaimRepository.php b/src/Repository/Project/RewardClaimRepository.php new file mode 100644 index 0000000..a4d9222 --- /dev/null +++ b/src/Repository/Project/RewardClaimRepository.php @@ -0,0 +1,43 @@ + + */ +class RewardClaimRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, RewardClaim::class); + } + + // /** + // * @return RewardClaim[] Returns an array of RewardClaim 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): ?RewardClaim + // { + // return $this->createQueryBuilder('r') + // ->andWhere('r.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/Project/RewardRepository.php b/src/Repository/Project/RewardRepository.php new file mode 100644 index 0000000..2bbd296 --- /dev/null +++ b/src/Repository/Project/RewardRepository.php @@ -0,0 +1,43 @@ + + */ +class RewardRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, Reward::class); + } + + // /** + // * @return Reward[] Returns an array of Reward objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('p.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?Reward + // { + // return $this->createQueryBuilder('p') + // ->andWhere('p.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/tests/Entity/ProjectApiTest.php b/tests/Entity/ProjectApiTest.php index b3a16cc..278ad27 100644 --- a/tests/Entity/ProjectApiTest.php +++ b/tests/Entity/ProjectApiTest.php @@ -55,6 +55,7 @@ public function testGetCollection(): void [ 'title' => 'Test Project', 'status' => ProjectStatus::InEditing->value, + 'rewards' => [], ], ]]); }