diff --git a/migrations/Version20240328150920.php b/migrations/Version20240404115740.php similarity index 87% rename from migrations/Version20240328150920.php rename to migrations/Version20240404115740.php index 2b5d0e8..505c886 100644 --- a/migrations/Version20240328150920.php +++ b/migrations/Version20240404115740.php @@ -10,7 +10,7 @@ use Doctrine\Migrations\AbstractMigration; /** * Auto-generated Migration: Please modify to your needs! */ -final class Version20240328150920 extends AbstractMigration +final class Version20240404115740 extends AbstractMigration { public function getDescription(): string { @@ -22,11 +22,13 @@ final class Version20240328150920 extends AbstractMigration // this up() migration is auto-generated, please modify it to your needs $this->addSql('CREATE TABLE comment (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, posting_id INT NOT NULL, message LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_9474526C7E3C61F9 (owner_id), INDEX IDX_9474526C9AE985F6 (posting_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE contact (id INT AUTO_INCREMENT NOT NULL, partner_id INT NOT NULL, image_id INT DEFAULT NULL, created_by_id INT NOT NULL, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, birthday DATETIME DEFAULT NULL COMMENT \'(DC2Type:datetime_immutable)\', position VARCHAR(255) DEFAULT NULL, phone VARCHAR(255) DEFAULT NULL, email VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_4C62E6389393F8FE (partner_id), INDEX IDX_4C62E6383DA5256D (image_id), INDEX IDX_4C62E638B03A8386 (created_by_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE contact_partner_product (id INT AUTO_INCREMENT NOT NULL, contact_id INT NOT NULL, partner_product_id INT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_8FB7588EE7A1254A (contact_id), INDEX IDX_8FB7588E5F7565BC (partner_product_id), UNIQUE INDEX unique_contact_partner_product (contact_id, partner_product_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE document (id INT AUTO_INCREMENT NOT NULL, created_by_id INT NOT NULL, partner_id INT DEFAULT NULL, product_id INT DEFAULT NULL, document_object_id INT NOT NULL, name VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_D8698A76B03A8386 (created_by_id), INDEX IDX_D8698A769393F8FE (partner_id), INDEX IDX_D8698A764584665A (product_id), INDEX IDX_D8698A7631157E8A (document_object_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE document_object (id INT AUTO_INCREMENT NOT NULL, created_by_id INT NOT NULL, file_path VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_16CF1A8AB03A8386 (created_by_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE media_object (id INT AUTO_INCREMENT NOT NULL, created_by_id INT NOT NULL, file_path VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_14D43132B03A8386 (created_by_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE partner (id INT AUTO_INCREMENT NOT NULL, logo_id INT DEFAULT NULL, created_by_id INT NOT NULL, navision_id INT UNSIGNED DEFAULT NULL, name VARCHAR(255) NOT NULL, type VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, street VARCHAR(255) DEFAULT NULL, street_no VARCHAR(255) DEFAULT NULL, zip VARCHAR(255) DEFAULT NULL, city VARCHAR(255) DEFAULT NULL, country VARCHAR(255) DEFAULT NULL, website VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', UNIQUE INDEX UNIQ_312B3E16B0FD8AF9 (navision_id), INDEX IDX_312B3E16F98F144A (logo_id), INDEX IDX_312B3E16B03A8386 (created_by_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE partner_follow (id INT AUTO_INCREMENT NOT NULL, user_id INT NOT NULL, partner_id INT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_55FFED0BA76ED395 (user_id), INDEX IDX_55FFED0B9393F8FE (partner_id), UNIQUE INDEX unique_follow (user_id, partner_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); + $this->addSql('CREATE TABLE partner_product (id INT AUTO_INCREMENT NOT NULL, partner_id INT NOT NULL, product_id INT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_14A067B09393F8FE (partner_id), INDEX IDX_14A067B04584665A (product_id), UNIQUE INDEX unique_partner_product (partner_id, product_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE posting (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, partner_id INT NOT NULL, contact_id INT DEFAULT NULL, sale_id INT DEFAULT NULL, product_id INT NOT NULL, headline VARCHAR(255) NOT NULL, message LONGTEXT NOT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_BD275D737E3C61F9 (owner_id), INDEX IDX_BD275D739393F8FE (partner_id), INDEX IDX_BD275D73E7A1254A (contact_id), INDEX IDX_BD275D734A7E4868 (sale_id), INDEX IDX_BD275D734584665A (product_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE product (id INT AUTO_INCREMENT NOT NULL, image_id INT DEFAULT NULL, created_by_id INT NOT NULL, name VARCHAR(255) NOT NULL, description LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_D34A04AD3DA5256D (image_id), INDEX IDX_D34A04ADB03A8386 (created_by_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); $this->addSql('CREATE TABLE sale (id INT AUTO_INCREMENT NOT NULL, owner_id INT NOT NULL, partner_id INT NOT NULL, product_id INT NOT NULL, turnover INT NOT NULL, profit INT DEFAULT NULL, quantity INT UNSIGNED NOT NULL, comment LONGTEXT DEFAULT NULL, created_at DATETIME NOT NULL COMMENT \'(DC2Type:datetime_immutable)\', INDEX IDX_E54BC0057E3C61F9 (owner_id), INDEX IDX_E54BC0059393F8FE (partner_id), INDEX IDX_E54BC0054584665A (product_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB'); @@ -38,6 +40,8 @@ final class Version20240328150920 extends AbstractMigration $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6389393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E6383DA5256D FOREIGN KEY (image_id) REFERENCES media_object (id) ON DELETE SET NULL'); $this->addSql('ALTER TABLE contact ADD CONSTRAINT FK_4C62E638B03A8386 FOREIGN KEY (created_by_id) REFERENCES `user` (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE contact_partner_product ADD CONSTRAINT FK_8FB7588EE7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE contact_partner_product ADD CONSTRAINT FK_8FB7588E5F7565BC FOREIGN KEY (partner_product_id) REFERENCES partner_product (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE document ADD CONSTRAINT FK_D8698A76B03A8386 FOREIGN KEY (created_by_id) REFERENCES `user` (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE document ADD CONSTRAINT FK_D8698A769393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id)'); $this->addSql('ALTER TABLE document ADD CONSTRAINT FK_D8698A764584665A FOREIGN KEY (product_id) REFERENCES product (id)'); @@ -48,6 +52,8 @@ final class Version20240328150920 extends AbstractMigration $this->addSql('ALTER TABLE partner ADD CONSTRAINT FK_312B3E16B03A8386 FOREIGN KEY (created_by_id) REFERENCES `user` (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE partner_follow ADD CONSTRAINT FK_55FFED0BA76ED395 FOREIGN KEY (user_id) REFERENCES `user` (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE partner_follow ADD CONSTRAINT FK_55FFED0B9393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE partner_product ADD CONSTRAINT FK_14A067B09393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); + $this->addSql('ALTER TABLE partner_product ADD CONSTRAINT FK_14A067B04584665A FOREIGN KEY (product_id) REFERENCES product (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D737E3C61F9 FOREIGN KEY (owner_id) REFERENCES `user` (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D739393F8FE FOREIGN KEY (partner_id) REFERENCES partner (id) ON DELETE CASCADE'); $this->addSql('ALTER TABLE posting ADD CONSTRAINT FK_BD275D73E7A1254A FOREIGN KEY (contact_id) REFERENCES contact (id) ON DELETE CASCADE'); @@ -75,6 +81,8 @@ final class Version20240328150920 extends AbstractMigration $this->addSql('ALTER TABLE contact DROP FOREIGN KEY FK_4C62E6389393F8FE'); $this->addSql('ALTER TABLE contact DROP FOREIGN KEY FK_4C62E6383DA5256D'); $this->addSql('ALTER TABLE contact DROP FOREIGN KEY FK_4C62E638B03A8386'); + $this->addSql('ALTER TABLE contact_partner_product DROP FOREIGN KEY FK_8FB7588EE7A1254A'); + $this->addSql('ALTER TABLE contact_partner_product DROP FOREIGN KEY FK_8FB7588E5F7565BC'); $this->addSql('ALTER TABLE document DROP FOREIGN KEY FK_D8698A76B03A8386'); $this->addSql('ALTER TABLE document DROP FOREIGN KEY FK_D8698A769393F8FE'); $this->addSql('ALTER TABLE document DROP FOREIGN KEY FK_D8698A764584665A'); @@ -85,6 +93,8 @@ final class Version20240328150920 extends AbstractMigration $this->addSql('ALTER TABLE partner DROP FOREIGN KEY FK_312B3E16B03A8386'); $this->addSql('ALTER TABLE partner_follow DROP FOREIGN KEY FK_55FFED0BA76ED395'); $this->addSql('ALTER TABLE partner_follow DROP FOREIGN KEY FK_55FFED0B9393F8FE'); + $this->addSql('ALTER TABLE partner_product DROP FOREIGN KEY FK_14A067B09393F8FE'); + $this->addSql('ALTER TABLE partner_product DROP FOREIGN KEY FK_14A067B04584665A'); $this->addSql('ALTER TABLE posting DROP FOREIGN KEY FK_BD275D737E3C61F9'); $this->addSql('ALTER TABLE posting DROP FOREIGN KEY FK_BD275D739393F8FE'); $this->addSql('ALTER TABLE posting DROP FOREIGN KEY FK_BD275D73E7A1254A'); @@ -104,11 +114,13 @@ final class Version20240328150920 extends AbstractMigration $this->addSql('ALTER TABLE `user` DROP FOREIGN KEY FK_8D93D6493DA5256D'); $this->addSql('DROP TABLE comment'); $this->addSql('DROP TABLE contact'); + $this->addSql('DROP TABLE contact_partner_product'); $this->addSql('DROP TABLE document'); $this->addSql('DROP TABLE document_object'); $this->addSql('DROP TABLE media_object'); $this->addSql('DROP TABLE partner'); $this->addSql('DROP TABLE partner_follow'); + $this->addSql('DROP TABLE partner_product'); $this->addSql('DROP TABLE posting'); $this->addSql('DROP TABLE product'); $this->addSql('DROP TABLE sale'); diff --git a/src/ApiResource/ContactPartnerProductApi.php b/src/ApiResource/ContactPartnerProductApi.php new file mode 100644 index 0000000..c6ba179 --- /dev/null +++ b/src/ApiResource/ContactPartnerProductApi.php @@ -0,0 +1,65 @@ + + * @date 12.12.23 + */ + + +namespace App\ApiResource; + +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\State\Options; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use App\Entity\Partner; +use App\Entity\PartnerFollow; +use App\Entity\User; +use App\State\EntityClassDtoStateProcessor; +use App\State\EntityToDtoStateProvider; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use Symfony\Component\Serializer\Attribute\Groups; +use Symfony\Component\Validator\Constraints\NotBlank; + +#[ApiResource( + shortName: 'PartnerFollow', + operations: [ + new Get( + security: 'is_granted("ROLE_USER")' + ), + new GetCollection( + security: 'is_granted("ROLE_USER")', + ), + new Post( + security: 'is_granted("ROLE_USER")', + ), + new Delete( + security: 'is_granted("ROLE_USER")', + ) + ], + security: 'is_granted("ROLE_USER")', + provider: EntityToDtoStateProvider::class, + processor: EntityClassDtoStateProcessor::class, + stateOptions: new Options(entityClass: PartnerFollow::class), +)] +#[ApiFilter(SearchFilter::class, properties: ['contact' => 'exact'])] +class ContactPartnerProductApi +{ + #[ApiProperty(readable: false, writable: false, identifier: true)] + public ?int $id = null; + + #[NotBlank] + public ?ContactApi $contact = null; + + #[NotBlank] + public ?PartnerProductApi $partnerProduct = null; + + #[ApiProperty(writable: false)] + public ?string $productName = null; + + #[ApiProperty(writable: false)] + public ?\DateTimeImmutable $createdAt = null; +} \ No newline at end of file diff --git a/src/ApiResource/PartnerProductApi.php b/src/ApiResource/PartnerProductApi.php new file mode 100644 index 0000000..1564676 --- /dev/null +++ b/src/ApiResource/PartnerProductApi.php @@ -0,0 +1,68 @@ + + * @date 12.12.23 + */ + + +namespace App\ApiResource; + +use ApiPlatform\Doctrine\Orm\Filter\SearchFilter; +use ApiPlatform\Doctrine\Orm\State\Options; +use ApiPlatform\Metadata\ApiFilter; +use ApiPlatform\Metadata\ApiProperty; +use ApiPlatform\Metadata\ApiResource; +use App\Entity\Partner; +use App\Entity\PartnerFollow; +use App\Entity\User; +use App\State\EntityClassDtoStateProcessor; +use App\State\EntityToDtoStateProvider; +use ApiPlatform\Metadata\Delete; +use ApiPlatform\Metadata\Get; +use ApiPlatform\Metadata\GetCollection; +use ApiPlatform\Metadata\Post; +use Symfony\Component\Serializer\Attribute\Groups; +use Symfony\Component\Validator\Constraints\NotBlank; + +#[ApiResource( + shortName: 'PartnerFollow', + operations: [ + new Get( + security: 'is_granted("ROLE_USER")' + ), + new GetCollection( + security: 'is_granted("ROLE_USER")', + ), + new Post( + security: 'is_granted("ROLE_USER")', + ), + new Delete( + security: 'is_granted("ROLE_USER")', + ) + ], + security: 'is_granted("ROLE_USER")', + provider: EntityToDtoStateProvider::class, + processor: EntityClassDtoStateProcessor::class, + stateOptions: new Options(entityClass: PartnerFollow::class), +)] +#[ApiFilter(SearchFilter::class, properties: ['partner' => 'exact', 'product' => 'exact'])] +class PartnerProductApi +{ + #[ApiProperty(readable: false, writable: false, identifier: true)] + public ?int $id = null; + + #[NotBlank] + public ?PartnerApi $partner = null; + + #[ApiProperty(writable: false)] + public ?string $partnerName = null; + + #[NotBlank] + public ?ProductApi $product = null; + + #[ApiProperty(writable: false)] + public ?string $productName = null; + + #[ApiProperty(writable: false)] + public ?\DateTimeImmutable $createdAt = null; +} \ No newline at end of file diff --git a/src/ApiResource/TaskApi.php b/src/ApiResource/TaskApi.php index 5f7cdbb..10501fc 100644 --- a/src/ApiResource/TaskApi.php +++ b/src/ApiResource/TaskApi.php @@ -18,6 +18,7 @@ use ApiPlatform\Metadata\GetCollection; use ApiPlatform\Metadata\Patch; use ApiPlatform\Metadata\Post; use App\Entity\Task; +use App\Enum\PartnerType; use App\Enum\PrioType; use App\State\EntityClassDtoStateProcessor; use App\State\EntityToDtoStateProvider; @@ -86,6 +87,9 @@ class TaskApi #[ApiProperty(writable: false)] public ?string $partnerName = null; + #[ApiProperty(writable: false)] + public ?PartnerType $partnerType = null; + public ?ContactApi $contact = null; #[ApiProperty(writable: false)] diff --git a/src/DataFixtures/AppFixtures.php b/src/DataFixtures/AppFixtures.php index 54db5d2..81215cb 100644 --- a/src/DataFixtures/AppFixtures.php +++ b/src/DataFixtures/AppFixtures.php @@ -2,9 +2,11 @@ namespace App\DataFixtures; +use App\Entity\ContactPartnerProduct; use App\Entity\Document; use App\Factory\CommentFactory; use App\Factory\ContactFactory; +use App\Factory\ContactPartnerProductFactory; use App\Factory\DocumentFactory; use App\Factory\DocumentObjectFactory; use App\Factory\MediaObjectLogoFactory; @@ -13,6 +15,7 @@ use App\Factory\MediaObjectContactFactory; use App\Factory\MediaObjectUserFactory; use App\Factory\PartnerFactory; use App\Factory\PartnerFollowFactory; +use App\Factory\PartnerProductFactory; use App\Factory\PostingFactory; use App\Factory\ProductFactory; use App\Factory\SaleFactory; @@ -140,5 +143,52 @@ class AppFixtures extends Fixture TaskNoteFactory::createMany(100); PartnerFollowFactory::createMany(100); DocumentFactory::createMany(50); + + $products = ProductFactory::all(); + $partners = PartnerFactory::all(); + foreach ($partners as $partner) { + $productsPicked = []; + for ($i = 0; $i < 3; $i++) { + $product = $products[array_rand($products)]; + $productsPicked[$product->getId()] = $product; + } + + foreach ($productsPicked as $item) { + PartnerProductFactory::createOne( + [ + 'partner' => $partner, + 'product' => $item + ] + ); + } + } + + $partnerProducts = PartnerProductFactory::all(); + foreach($partnerProducts as $partnerProduct) { + $partner = $partnerProduct->getPartner(); + $contacts = $partner?->getContacts()->toArray(); + if (count($contacts) > 0) { + $randomKeys = array_rand($contacts, random_int(1, count($contacts))); + if (is_array($randomKeys)) { + foreach ($randomKeys as $key) { + ContactPartnerProductFactory::createOne( + [ + 'contact' => $contacts[$key], + 'partnerProduct' => $partnerProduct, + ] + ); + } + } else { + ContactPartnerProductFactory::createOne( + [ + 'contact' => $contacts[$randomKeys], + 'partnerProduct' => $partnerProduct, + ] + ); + } + } + } + + } } diff --git a/src/Entity/Contact.php b/src/Entity/Contact.php index ddd4b88..c457163 100644 --- a/src/Entity/Contact.php +++ b/src/Entity/Contact.php @@ -51,12 +51,16 @@ class Contact #[ORM\OneToMany(mappedBy: 'contact', targetEntity: Posting::class)] private Collection $posts; + #[ORM\OneToMany(mappedBy: 'contact', targetEntity: ContactPartnerProduct::class)] + private Collection $contactPartnerProducts; + public function __construct(Partner $partner, User $createdBy) { $this->partner = $partner; $this->createdBy = $createdBy; $this->createdAt = new \DateTimeImmutable(); $this->posts = new ArrayCollection(); + $this->contactPartnerProducts = new ArrayCollection(); } public function getId(): ?int @@ -207,4 +211,34 @@ class Contact return $this; } + + /** + * @return Collection + */ + public function getContactPartnerProducts(): Collection + { + return $this->contactPartnerProducts; + } + + public function addContactPartnerProduct(ContactPartnerProduct $contactPartnerProduct): static + { + if (!$this->contactPartnerProducts->contains($contactPartnerProduct)) { + $this->contactPartnerProducts->add($contactPartnerProduct); + $contactPartnerProduct->setContact($this); + } + + return $this; + } + + public function removeContactPartnerProduct(ContactPartnerProduct $contactPartnerProduct): static + { + if ($this->contactPartnerProducts->removeElement($contactPartnerProduct)) { + // set the owning side to null (unless already changed) + if ($contactPartnerProduct->getContact() === $this) { + $contactPartnerProduct->setContact(null); + } + } + + return $this; + } } diff --git a/src/Entity/ContactPartnerProduct.php b/src/Entity/ContactPartnerProduct.php new file mode 100644 index 0000000..f8c2e96 --- /dev/null +++ b/src/Entity/ContactPartnerProduct.php @@ -0,0 +1,80 @@ +getPartner()?->getId() !== $partnerProduct->getPartner()?->getId()) { + throw new \Exception('Contact Partner and ProductPartner Partner do not match!'); + } + + $this->contact = $contact; + $this->partnerProduct = $partnerProduct; + + $this->createdAt = new \DateTimeImmutable(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getContact(): ?Contact + { + return $this->contact; + } + + public function setContact(?Contact $contact): static + { + $this->contact = $contact; + + return $this; + } + + public function getPartnerProduct(): ?PartnerProduct + { + return $this->partnerProduct; + } + + public function setPartnerProduct(?PartnerProduct $partnerProduct): static + { + $this->partnerProduct = $partnerProduct; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeImmutable + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTimeImmutable $createdAt): static + { + $this->createdAt = $createdAt; + + return $this; + } +} diff --git a/src/Entity/Partner.php b/src/Entity/Partner.php index af74a12..9ef4b9c 100644 --- a/src/Entity/Partner.php +++ b/src/Entity/Partner.php @@ -73,6 +73,9 @@ class Partner #[ORM\OneToMany(mappedBy: 'partner', targetEntity: PartnerFollow::class)] private Collection $partnerFollows; + #[ORM\OneToMany(mappedBy: 'partner', targetEntity: PartnerProduct::class)] + private Collection $partnerProducts; + public function __construct(User $createdBy) { $this->createdBy = $createdBy; @@ -82,6 +85,7 @@ class Partner $this->sales = new ArrayCollection(); $this->documentObjects = new ArrayCollection(); $this->partnerFollows = new ArrayCollection(); + $this->partnerProducts = new ArrayCollection(); } public function getId(): ?int @@ -334,4 +338,34 @@ class Partner return $this; } + /** + * @return Collection + */ + public function getPartnerProducts(): Collection + { + return $this->partnerProducts; + } + + public function addPartnerProduct(PartnerProduct $partnerProduct): static + { + if (!$this->partnerProducts->contains($partnerProduct)) { + $this->partnerProducts->add($partnerProduct); + $partnerProduct->setPartner($this); + } + + return $this; + } + + public function removePartnerProduct(PartnerProduct $partnerProduct): static + { + if ($this->partnerProducts->removeElement($partnerProduct)) { + // set the owning side to null (unless already changed) + if ($partnerProduct->getPartner() === $this) { + $partnerProduct->setPartner(null); + } + } + + return $this; + } + } diff --git a/src/Entity/PartnerFollow.php b/src/Entity/PartnerFollow.php index 69eb33f..934321c 100644 --- a/src/Entity/PartnerFollow.php +++ b/src/Entity/PartnerFollow.php @@ -65,13 +65,9 @@ class PartnerFollow { return $this->createdAt; } - public function setCreatedAt(\DateTimeImmutable $createdAt): static { $this->createdAt = $createdAt; - return $this; } -} -///api/users/155 -///api/partners/289 \ No newline at end of file +} \ No newline at end of file diff --git a/src/Entity/PartnerProduct.php b/src/Entity/PartnerProduct.php new file mode 100644 index 0000000..dc9b42a --- /dev/null +++ b/src/Entity/PartnerProduct.php @@ -0,0 +1,110 @@ +partner = $partner; + $this->product = $product; + $this->createdAt = new \DateTimeImmutable(); + $this->contactPartnerProducts = new ArrayCollection(); + } + + public function getId(): ?int + { + return $this->id; + } + + public function getPartner(): ?Partner + { + return $this->partner; + } + + public function setPartner(?Partner $partner): static + { + $this->partner = $partner; + + return $this; + } + + public function getProduct(): ?Product + { + return $this->product; + } + + public function setProduct(?Product $product): static + { + $this->product = $product; + + return $this; + } + + public function getCreatedAt(): ?\DateTimeImmutable + { + return $this->createdAt; + } + + public function setCreatedAt(?\DateTimeImmutable $createdAt): void + { + $this->createdAt = $createdAt; + } + + /** + * @return Collection + */ + public function getContactPartnerProducts(): Collection + { + return $this->contactPartnerProducts; + } + + public function addContactPartnerProduct(ContactPartnerProduct $contactPartnerProduct): static + { + if (!$this->contactPartnerProducts->contains($contactPartnerProduct)) { + $this->contactPartnerProducts->add($contactPartnerProduct); + $contactPartnerProduct->setPartnerProduct($this); + } + + return $this; + } + + public function removeContactPartnerProduct(ContactPartnerProduct $contactPartnerProduct): static + { + if ($this->contactPartnerProducts->removeElement($contactPartnerProduct)) { + // set the owning side to null (unless already changed) + if ($contactPartnerProduct->getPartnerProduct() === $this) { + $contactPartnerProduct->setPartnerProduct(null); + } + } + + return $this; + } + +} diff --git a/src/Entity/Product.php b/src/Entity/Product.php index d33be2e..6bfec2d 100644 --- a/src/Entity/Product.php +++ b/src/Entity/Product.php @@ -42,6 +42,9 @@ class Product #[ORM\OneToMany(mappedBy: 'product', targetEntity: Posting::class)] private Collection $postings; + #[ORM\OneToMany(mappedBy: 'product', targetEntity: PartnerProduct::class)] + private Collection $partnerProducts; + public function __construct(User $createdBy) { $this->createdBy = $createdBy; @@ -49,6 +52,7 @@ class Product $this->sales = new ArrayCollection(); $this->documentObjects = new ArrayCollection(); $this->postings = new ArrayCollection(); + $this->partnerProducts = new ArrayCollection(); } public function getId(): ?int @@ -191,4 +195,34 @@ class Product return $this; } + + /** + * @return Collection + */ + public function getPartnerProducts(): Collection + { + return $this->partnerProducts; + } + + public function addPartnerProduct(PartnerProduct $partnerProduct): static + { + if (!$this->partnerProducts->contains($partnerProduct)) { + $this->partnerProducts->add($partnerProduct); + $partnerProduct->setProduct($this); + } + + return $this; + } + + public function removePartnerProduct(PartnerProduct $partnerProduct): static + { + if ($this->partnerProducts->removeElement($partnerProduct)) { + // set the owning side to null (unless already changed) + if ($partnerProduct->getProduct() === $this) { + $partnerProduct->setProduct(null); + } + } + + return $this; + } } diff --git a/src/Factory/ContactPartnerProductFactory.php b/src/Factory/ContactPartnerProductFactory.php new file mode 100644 index 0000000..2f33536 --- /dev/null +++ b/src/Factory/ContactPartnerProductFactory.php @@ -0,0 +1,71 @@ + + * + * @method ContactPartnerProduct|Proxy create(array|callable $attributes = []) + * @method static ContactPartnerProduct|Proxy createOne(array $attributes = []) + * @method static ContactPartnerProduct|Proxy find(object|array|mixed $criteria) + * @method static ContactPartnerProduct|Proxy findOrCreate(array $attributes) + * @method static ContactPartnerProduct|Proxy first(string $sortedField = 'id') + * @method static ContactPartnerProduct|Proxy last(string $sortedField = 'id') + * @method static ContactPartnerProduct|Proxy random(array $attributes = []) + * @method static ContactPartnerProduct|Proxy randomOrCreate(array $attributes = []) + * @method static ContactPartnerProductRepository|RepositoryProxy repository() + * @method static ContactPartnerProduct[]|Proxy[] all() + * @method static ContactPartnerProduct[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static ContactPartnerProduct[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static ContactPartnerProduct[]|Proxy[] findBy(array $attributes) + * @method static ContactPartnerProduct[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static ContactPartnerProduct[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class ContactPartnerProductFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'contact' => ContactFactory::new(), + 'createdAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime()), + 'partnerProduct' => PartnerProductFactory::new(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(ContactPartnerProduct $contactPartnerProduct): void {}) + ; + } + + protected static function getClass(): string + { + return ContactPartnerProduct::class; + } +} diff --git a/src/Factory/PartnerProductFactory.php b/src/Factory/PartnerProductFactory.php new file mode 100644 index 0000000..06165a9 --- /dev/null +++ b/src/Factory/PartnerProductFactory.php @@ -0,0 +1,70 @@ + + * + * @method PartnerProduct|Proxy create(array|callable $attributes = []) + * @method static PartnerProduct|Proxy createOne(array $attributes = []) + * @method static PartnerProduct|Proxy find(object|array|mixed $criteria) + * @method static PartnerProduct|Proxy findOrCreate(array $attributes) + * @method static PartnerProduct|Proxy first(string $sortedField = 'id') + * @method static PartnerProduct|Proxy last(string $sortedField = 'id') + * @method static PartnerProduct|Proxy random(array $attributes = []) + * @method static PartnerProduct|Proxy randomOrCreate(array $attributes = []) + * @method static PartnerProductRepository|RepositoryProxy repository() + * @method static PartnerProduct[]|Proxy[] all() + * @method static PartnerProduct[]|Proxy[] createMany(int $number, array|callable $attributes = []) + * @method static PartnerProduct[]|Proxy[] createSequence(iterable|callable $sequence) + * @method static PartnerProduct[]|Proxy[] findBy(array $attributes) + * @method static PartnerProduct[]|Proxy[] randomRange(int $min, int $max, array $attributes = []) + * @method static PartnerProduct[]|Proxy[] randomSet(int $number, array $attributes = []) + */ +final class PartnerProductFactory extends ModelFactory +{ + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services + * + * @todo inject services if required + */ + public function __construct() + { + parent::__construct(); + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories + * + * @todo add your default values here + */ + protected function getDefaults(): array + { + return [ + 'createdAt' => \DateTimeImmutable::createFromMutable(self::faker()->dateTime()), + 'partner' => PartnerFactory::new(), + 'product' => ProductFactory::new(), + ]; + } + + /** + * @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization + */ + protected function initialize(): self + { + return $this + // ->afterInstantiate(function(PartnerProduct $partnerProduct): void {}) + ; + } + + protected static function getClass(): string + { + return PartnerProduct::class; + } +} diff --git a/src/Mapper/ContactPartnerProductApiToEntityMapper.php b/src/Mapper/ContactPartnerProductApiToEntityMapper.php new file mode 100644 index 0000000..ddc4813 --- /dev/null +++ b/src/Mapper/ContactPartnerProductApiToEntityMapper.php @@ -0,0 +1,74 @@ +id) { + $entity = $this->repository->find($dto->id); + } else { + if ($dto->contact === null) { + throw new \Exception('Contact missing'); + } + $contact = $this->microMapper->map($dto->contact, Contact::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + + if ($dto->partnerProduct === null) { + throw new \Exception('PartnerProduct missing'); + } + $partnerProduct = $this->microMapper->map($dto->partnerProduct, PartnerProduct::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + + if ($contact->getPartner() !== $partnerProduct->getPartner()) { + throw new \Exception('Contact Partner and ProductPartner Partner do not match!'); + } + + assert($contact instanceof Contact); + assert($partnerProduct instanceof PartnerProduct); + $entity = new PartnerProduct($contact, $partnerProduct); + } + + if (!$entity) { + throw new \Exception('PartnerFollow not found'); + } + + return $entity; + } + + public function populate(object $from, object $to, array $context): object + { + $dto = $from; + assert($dto instanceof PartnerProductApi); + $entity = $to; + assert($entity instanceof PartnerProduct); + return $entity; + } +} diff --git a/src/Mapper/ContactPartnerProductEntityToApiMapper.php b/src/Mapper/ContactPartnerProductEntityToApiMapper.php new file mode 100644 index 0000000..f8cdb86 --- /dev/null +++ b/src/Mapper/ContactPartnerProductEntityToApiMapper.php @@ -0,0 +1,53 @@ +id = $entity->getId(); + + return $dto; + } + + public function populate(object $from, object $to, array $context): object + { + $entity = $from; + $dto = $to; + assert($entity instanceof ContactPartnerProduct); + assert($dto instanceof ContactPartnerProductApi); + + $dto->contact = $this->microMapper->map($entity->getContact(), ContactApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + + $dto->partnerProduct = $this->microMapper->map($entity->getPartnerProduct(), PartnerProductApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + $dto->productName = $entity->getPartnerProduct()?->getProduct()?->getName(); + + $dto->createdAt = $entity->getCreatedAt(); + + return $dto; + } +} diff --git a/src/Mapper/PartnerProductApiToEntityMapper.php b/src/Mapper/PartnerProductApiToEntityMapper.php new file mode 100644 index 0000000..1586793 --- /dev/null +++ b/src/Mapper/PartnerProductApiToEntityMapper.php @@ -0,0 +1,71 @@ +id) { + $entity = $this->repository->find($dto->id); + } else { + if ($dto->partner === null) { + throw new \Exception('Partner missing'); + } + $partner = $this->microMapper->map($dto->partner, Partner::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + + if ($dto->product === null) { + throw new \Exception('Product missing'); + } + $product = $this->microMapper->map($dto->product, Product::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + assert($partner instanceof Partner); + assert($product instanceof Product); + $entity = new PartnerProduct($partner, $product); + } + + if (!$entity) { + throw new \Exception('PartnerFollow not found'); + } + + return $entity; + } + + public function populate(object $from, object $to, array $context): object + { + $dto = $from; + assert($dto instanceof PartnerProductApi); + $entity = $to; + assert($entity instanceof PartnerProduct); + return $entity; + } +} diff --git a/src/Mapper/PartnerProductEntityToApiMapper.php b/src/Mapper/PartnerProductEntityToApiMapper.php new file mode 100644 index 0000000..d8affdd --- /dev/null +++ b/src/Mapper/PartnerProductEntityToApiMapper.php @@ -0,0 +1,57 @@ +id = $entity->getId(); + + return $dto; + } + + public function populate(object $from, object $to, array $context): object + { + $entity = $from; + $dto = $to; + assert($entity instanceof PartnerProduct); + assert($dto instanceof PartnerProductApi); + + $dto->partner = $this->microMapper->map($entity->getPartner(), PartnerApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + $dto->partnerName = $entity->getPartner()?->getName(); + + $dto->product = $this->microMapper->map($entity->getProduct(), ProductApi::class, [ + MicroMapperInterface::MAX_DEPTH => 1, + ]); + $dto->productName = $entity->getProduct()?->getName(); + + $dto->createdAt = $entity->getCreatedAt(); + + return $dto; + } +} diff --git a/src/Mapper/TaskEntityToApiMapper.php b/src/Mapper/TaskEntityToApiMapper.php index 2263589..b182686 100644 --- a/src/Mapper/TaskEntityToApiMapper.php +++ b/src/Mapper/TaskEntityToApiMapper.php @@ -61,6 +61,7 @@ class TaskEntityToApiMapper implements MapperInterface MicroMapperInterface::MAX_DEPTH => 1, ]); $dto->partnerName = $entity->getPartner()?->getName(); + $dto->partnerType = $entity->getPartner()?->getType(); } if ($entity->getContact() !== null) { diff --git a/src/Repository/ContactPartnerProductRepository.php b/src/Repository/ContactPartnerProductRepository.php new file mode 100644 index 0000000..65f0a6e --- /dev/null +++ b/src/Repository/ContactPartnerProductRepository.php @@ -0,0 +1,48 @@ + + * + * @method ContactPartnerProduct|null find($id, $lockMode = null, $lockVersion = null) + * @method ContactPartnerProduct|null findOneBy(array $criteria, array $orderBy = null) + * @method ContactPartnerProduct[] findAll() + * @method ContactPartnerProduct[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class ContactPartnerProductRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, ContactPartnerProduct::class); + } + + // /** + // * @return ContactPartnerProduct[] Returns an array of ContactPartnerProduct objects + // */ + // public function findByExampleField($value): array + // { + // return $this->createQueryBuilder('c') + // ->andWhere('c.exampleField = :val') + // ->setParameter('val', $value) + // ->orderBy('c.id', 'ASC') + // ->setMaxResults(10) + // ->getQuery() + // ->getResult() + // ; + // } + + // public function findOneBySomeField($value): ?ContactPartnerProduct + // { + // return $this->createQueryBuilder('c') + // ->andWhere('c.exampleField = :val') + // ->setParameter('val', $value) + // ->getQuery() + // ->getOneOrNullResult() + // ; + // } +} diff --git a/src/Repository/PartnerProductRepository.php b/src/Repository/PartnerProductRepository.php new file mode 100644 index 0000000..29f937a --- /dev/null +++ b/src/Repository/PartnerProductRepository.php @@ -0,0 +1,48 @@ + + * + * @method PartnerProduct|null find($id, $lockMode = null, $lockVersion = null) + * @method PartnerProduct|null findOneBy(array $criteria, array $orderBy = null) + * @method PartnerProduct[] findAll() + * @method PartnerProduct[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null) + */ +class PartnerProductRepository extends ServiceEntityRepository +{ + public function __construct(ManagerRegistry $registry) + { + parent::__construct($registry, PartnerProduct::class); + } + +// /** +// * @return PartnerProduct[] Returns an array of PartnerProduct 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): ?PartnerProduct +// { +// return $this->createQueryBuilder('p') +// ->andWhere('p.exampleField = :val') +// ->setParameter('val', $value) +// ->getQuery() +// ->getOneOrNullResult() +// ; +// } +}