From eebc286c784524e78247c0b108b6ab1672275dda Mon Sep 17 00:00:00 2001 From: Mantas Muliarcikas Date: Wed, 28 Aug 2024 18:32:02 +0300 Subject: [PATCH] Added MerchantProductImport functionality cleaned up from redundant logic --- config/Zed/navigation.xml | 20 +- .../MerchantProductImportConstants.php | 13 ++ .../merchant_product_import.transfer.xml | 54 +++++ ...ct_import_merchant_portal_gui.transfer.xml | 16 ++ .../AclMerchantPortalDependencyProvider.php | 10 +- .../Business/FileUploadBusinessFactory.php | 9 + .../Business/Writer/FileUploadWriter.php | 35 +++- .../Controller/UploadController.php | 191 ------------------ .../FileUploadCommunicationFactory.php | 54 ----- .../DataProvider/FileUploadDataProvider.php | 38 ---- .../FileUploadDataProviderInterface.php | 20 -- .../Communication/Form/FileUploadForm.php | 142 ------------- ...adAclEntityConfigurationExpanderPlugin.php | 1 + .../FileUploadPostSavePluginInterface.php | 22 ++ src/Pyz/Zed/FileUpload/FileUploadConfig.php | 6 + .../FileUploadDependencyProvider.php | 28 ++- .../Persistence/FileUploadEntityManager.php | 8 +- .../FileUploadEntityManagerInterface.php | 4 +- .../Propel/Schema/pyz_file_upload.schema.xml | 2 +- .../Controller/UploadController.php | 16 +- ...PortalGuiMerchantAclRuleExpanderPlugin.php | 2 +- .../MerchantProductImportBusinessFactory.php | 44 ++++ .../Business/MerchantProductImportFacade.php | 46 +++++ .../MerchantProductImportFacadeInterface.php | 34 ++++ .../Business/Reader/ImportUploadReader.php | 65 ++++++ .../Reader/ImportUploadReaderInterface.php | 21 ++ .../Business/Writer/ImportUploadWriter.php | 119 +++++++++++ .../Writer/ImportUploadWriterInterface.php | 31 +++ ...adAclEntityConfigurationExpanderPlugin.php | 41 ++++ ...oadMerchantAclEntityRuleExpanderPlugin.php | 48 +++++ .../MerchantProductImpostPostSavePlugin.php | 33 +++ .../MerchantProductImportConfig.php | 71 +++++++ ...erchantProductImportDependencyProvider.php | 14 ++ .../MerchantProductImportEntityManager.php | 59 ++++++ ...antProductImportEntityManagerInterface.php | 23 +++ ...erchantProductImportPersistenceFactory.php | 36 ++++ .../MerchantProductImportRepository.php | 126 ++++++++++++ ...rchantProductImportRepositoryInterface.php | 21 ++ .../Propel/Mapper/ImportUploadMapper.php | 118 +++++++++++ .../Schema/pyz_import_upload.schema.xml | 37 ++++ .../Controller/ImportsController.php | 59 ++++++ ...ortUploadGuiTableConfigurationProvider.php | 124 ++++++++++++ ...GuiTableConfigurationProviderInterface.php | 15 ++ .../ImportUploadGuiTableDataProvider.php | 114 +++++++++++ ...tMerchantPortalGuiCommunicationFactory.php | 56 +++++ ...uctImportMerchantAclRuleExpanderPlugin.php | 47 +++++ ...ntProductImportMerchantPortalGuiConfig.php | 111 ++++++++++ ...ortMerchantPortalGuiDependencyProvider.php | 94 +++++++++ .../Mapper/ImportUploadTableDataMapper.php | 88 ++++++++ .../ImportUploadTableDataMapperInterface.php | 43 ++++ ...ortMerchantPortalGuiPersistenceFactory.php | 31 +++ ...oductImportMerchantPortalGuiRepository.php | 121 +++++++++++ ...rtMerchantPortalGuiRepositoryInterface.php | 18 ++ .../Components/app/components.module.ts | 12 ++ .../import-upload-table.component.html | 1 + .../import-upload-table.component.less | 30 +++ .../import-upload-table.component.ts | 40 ++++ .../import-upload-table.module.ts | 12 ++ .../Presentation/Components/entry.ts | 5 + .../Presentation/Imports/index.twig | 19 ++ .../Presentation/Products/index.twig | 3 - 61 files changed, 2254 insertions(+), 467 deletions(-) create mode 100644 src/Pyz/Shared/MerchantProductImport/MerchantProductImportConstants.php create mode 100644 src/Pyz/Shared/MerchantProductImport/Transfer/merchant_product_import.transfer.xml create mode 100644 src/Pyz/Shared/MerchantProductImportMerchantPortalGui/Transfer/merchant_product_import_merchant_portal_gui.transfer.xml delete mode 100644 src/Pyz/Zed/FileUpload/Communication/Controller/UploadController.php delete mode 100644 src/Pyz/Zed/FileUpload/Communication/FileUploadCommunicationFactory.php delete mode 100644 src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProvider.php delete mode 100644 src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProviderInterface.php delete mode 100644 src/Pyz/Zed/FileUpload/Communication/Form/FileUploadForm.php create mode 100644 src/Pyz/Zed/FileUpload/Dependency/Plugin/FileUploadPostSavePluginInterface.php rename src/Pyz/Zed/{FileUpload => FileUploadMerchantPortalGui}/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php (93%) create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportBusinessFactory.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacade.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacadeInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/Reader/ImportUploadReader.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/Reader/ImportUploadReaderInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/Writer/ImportUploadWriter.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Business/Writer/ImportUploadWriterInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Communication/Plugin/AclMerchantPortal/ImportUploadAclEntityConfigurationExpanderPlugin.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Communication/Plugin/AclMerchantPortal/ImportUploadMerchantAclEntityRuleExpanderPlugin.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Communication/Plugin/FileUpload/MerchantProductImpostPostSavePlugin.php create mode 100644 src/Pyz/Zed/MerchantProductImport/MerchantProductImportConfig.php create mode 100644 src/Pyz/Zed/MerchantProductImport/MerchantProductImportDependencyProvider.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportEntityManager.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportEntityManagerInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportPersistenceFactory.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportRepository.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportRepositoryInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/Propel/Mapper/ImportUploadMapper.php create mode 100644 src/Pyz/Zed/MerchantProductImport/Persistence/Propel/Schema/pyz_import_upload.schema.xml create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Controller/ImportsController.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProvider.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProviderInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/DataProvider/ImportUploadGuiTableDataProvider.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/MerchantProductImportMerchantPortalGuiCommunicationFactory.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Plugin/AclMerchantPortal/MerchantProductImportMerchantAclRuleExpanderPlugin.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiConfig.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiDependencyProvider.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapper.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapperInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiPersistenceFactory.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepository.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepositoryInterface.php create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/components.module.ts create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.html create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.less create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.ts create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.module.ts create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/entry.ts create mode 100644 src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Imports/index.twig diff --git a/config/Zed/navigation.xml b/config/Zed/navigation.xml index ad8ee89f6..509845934 100644 --- a/config/Zed/navigation.xml +++ b/config/Zed/navigation.xml @@ -640,10 +640,28 @@ Products - products + offers product-merchant-portal-gui products index + + + + Products + product-merchant-portal-gui + products + index + 1 + + + + Import History + merchant-product-import-merchant-portal-gui + imports + index + 1 + + diff --git a/src/Pyz/Shared/MerchantProductImport/MerchantProductImportConstants.php b/src/Pyz/Shared/MerchantProductImport/MerchantProductImportConstants.php new file mode 100644 index 000000000..25e6aa563 --- /dev/null +++ b/src/Pyz/Shared/MerchantProductImport/MerchantProductImportConstants.php @@ -0,0 +1,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Pyz/Shared/MerchantProductImportMerchantPortalGui/Transfer/merchant_product_import_merchant_portal_gui.transfer.xml b/src/Pyz/Shared/MerchantProductImportMerchantPortalGui/Transfer/merchant_product_import_merchant_portal_gui.transfer.xml new file mode 100644 index 000000000..11ca77b16 --- /dev/null +++ b/src/Pyz/Shared/MerchantProductImportMerchantPortalGui/Transfer/merchant_product_import_merchant_portal_gui.transfer.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php b/src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php index 6988fba5e..feb2e62e1 100644 --- a/src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php +++ b/src/Pyz/Zed/AclMerchantPortal/AclMerchantPortalDependencyProvider.php @@ -9,7 +9,10 @@ use Pyz\Zed\FileUpload\Communication\Plugin\AclMerchantPortal\FileUploadAclEntityConfigurationExpanderPlugin; use Pyz\Zed\FileUpload\Communication\Plugin\AclMerchantPortal\FileUploadMerchantAclEntityRuleExpanderPlugin; -use Pyz\Zed\FileUpload\Communication\Plugin\AclMerchantPortal\FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin; +use Pyz\Zed\FileUploadMerchantPortalGui\Communication\Plugin\AclMerchantPortal\FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin; +use Pyz\Zed\MerchantProductImport\Communication\Plugin\AclMerchantPortal\ImportUploadAclEntityConfigurationExpanderPlugin; +use Pyz\Zed\MerchantProductImport\Communication\Plugin\AclMerchantPortal\ImportUploadMerchantAclEntityRuleExpanderPlugin; +use Pyz\Zed\MerchantProductImportMerchantPortalGui\Communication\Plugin\AclMerchantPortal\MerchantProductImportMerchantAclRuleExpanderPlugin; use Spryker\Zed\Acl\Communication\Plugin\AclMerchantPortal\AclEntityConfigurationExpanderPlugin; use Spryker\Zed\AclEntity\Communication\Plugin\AclMerchantPortal\AclEntityAclEntityConfigurationExpanderPlugin; use Spryker\Zed\AclMerchantPortal\AclMerchantPortalDependencyProvider as SprykerAclMerchantPortalDependencyProvider; @@ -114,6 +117,7 @@ protected function getMerchantAclRuleExpanderPlugins(): array new ProductOfferServicePointMerchantPortalGuiMerchantAclRuleExpanderPlugin(), new MerchantAppMerchantPortalGuiMerchantAclRuleExpanderPlugin(), new FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin(), + new MerchantProductImportMerchantAclRuleExpanderPlugin(), ]; } @@ -143,6 +147,8 @@ protected function getMerchantAclEntityRuleExpanderPlugins(): array new DiscountMerchantAclEntityRuleExpanderPlugin(), new DiscountPromotionMerchantAclEntityRuleExpanderPlugin(), new SalesMerchantCommissionMerchantAclEntityRuleExpanderPlugin(), + new FileUploadMerchantAclEntityRuleExpanderPlugin(), + new ImportUploadMerchantAclEntityRuleExpanderPlugin(), ]; } @@ -164,7 +170,6 @@ protected function getMerchantUserAclEntityRuleExpanderPlugins(): array { return [ new MerchantUserMerchantUserAclEntityRuleExpanderPlugin(), - new FileUploadMerchantAclEntityRuleExpanderPlugin(), ]; } @@ -231,6 +236,7 @@ protected function getAclEntityConfigurationExpanderPlugins(): array new MerchantAppAclEntityConfigurationExpanderPlugin(), new SalesMerchantCommissionAclEntityConfigurationExpanderPlugin(), new FileUploadAclEntityConfigurationExpanderPlugin(), + new ImportUploadAclEntityConfigurationExpanderPlugin(), ]; } } diff --git a/src/Pyz/Zed/FileUpload/Business/FileUploadBusinessFactory.php b/src/Pyz/Zed/FileUpload/Business/FileUploadBusinessFactory.php index 75df7e7d5..5856eba1d 100644 --- a/src/Pyz/Zed/FileUpload/Business/FileUploadBusinessFactory.php +++ b/src/Pyz/Zed/FileUpload/Business/FileUploadBusinessFactory.php @@ -53,6 +53,7 @@ public function createFileUploadWriter(): FileUploadWriterInterface $this->getEntityManager(), $this->getMerchantUserFacade(), $this->getAwsS3Service(), + $this->getFileUploadPostSavePlugins(), ); } @@ -77,4 +78,12 @@ private function getAwsS3Service(): AwsS3ServiceInterface { return $this->getProvidedDependency(FileUploadDependencyProvider::SERVICE_AWS_S3); } + + /** + * @return array<\Pyz\Zed\FileUpload\Dependency\Plugin\FileUploadPostSavePluginInterface> + */ + private function getFileUploadPostSavePlugins(): array + { + return $this->getProvidedDependency(FileUploadDependencyProvider::PLUGINS_FILE_UPLOAD_POST_SAVE); + } } diff --git a/src/Pyz/Zed/FileUpload/Business/Writer/FileUploadWriter.php b/src/Pyz/Zed/FileUpload/Business/Writer/FileUploadWriter.php index 620a0f29a..492ed1915 100644 --- a/src/Pyz/Zed/FileUpload/Business/Writer/FileUploadWriter.php +++ b/src/Pyz/Zed/FileUpload/Business/Writer/FileUploadWriter.php @@ -11,6 +11,7 @@ use Generated\Shared\Transfer\FileUploadTransfer; use Pyz\Service\AwsS3\AwsS3ServiceInterface; +use Pyz\Service\AwsS3\Exception\S3BucketConfigurationNotFoundException; use Pyz\Zed\FileUpload\Persistence\FileUploadEntityManagerInterface; use Spryker\Zed\MerchantUser\Business\MerchantUserFacadeInterface; @@ -22,14 +23,21 @@ class FileUploadWriter implements FileUploadWriterInterface private AwsS3ServiceInterface $awsS3Service; + /** + * @return array<\Pyz\Zed\FileUpload\Dependency\Plugin\FileUploadPostSavePluginInterface> + */ + private array $fileUploadPostSavePlugins; + public function __construct( FileUploadEntityManagerInterface $entityManager, MerchantUserFacadeInterface $merchantUserFacade, AwsS3ServiceInterface $awsS3Service, + array $fileUploadPostSavePlugins, ) { $this->entityManager = $entityManager; $this->merchantUserFacade = $merchantUserFacade; $this->awsS3Service = $awsS3Service; + $this->fileUploadPostSavePlugins = $fileUploadPostSavePlugins; } public function createFileUpload(FileUploadTransfer $fileUploadTransfer): FileUploadTransfer @@ -45,7 +53,9 @@ public function createFileUpload(FileUploadTransfer $fileUploadTransfer): FileUp $this->setFileUploadS3Url($fileUploadTransfer); $this->setFileUploadCdnUrl($fileUploadTransfer); - $this->entityManager->createFileUpload($fileUploadTransfer); + $fileUploadTransfer = $this->entityManager->createFileUpload($fileUploadTransfer); + + $this->executePostSavePlugins($fileUploadTransfer); return $fileUploadTransfer; } @@ -57,12 +67,16 @@ public function createFileUpload(FileUploadTransfer $fileUploadTransfer): FileUp */ private function setFileUploadCdnUrl(FileUploadTransfer $fileUploadTransfer): void { - $cdnUrl = $this->awsS3Service->getCdnUrl( - $fileUploadTransfer->getFileName(), - $fileUploadTransfer->getObjectType(), - ); - - $fileUploadTransfer->setCdnUrl($cdnUrl); + try { + $cdnUrl = $this->awsS3Service->getCdnUrl( + $fileUploadTransfer->getFileName(), + $fileUploadTransfer->getObjectType(), + ); + + $fileUploadTransfer->setCdnUrl($cdnUrl); + } catch (S3BucketConfigurationNotFoundException) { + return; + } } /** @@ -96,4 +110,11 @@ private function setFileUploadOwner(FileUploadTransfer $fileUploadTransfer): voi ->setFkMerchant($merchantUserTransfer->getIdMerchant()) ->setFkUser($merchantUserTransfer->getIdUser()); } + + private function executePostSavePlugins(FileUploadTransfer $fileUploadTransfer): void + { + foreach ($this->fileUploadPostSavePlugins as $fileUploadPostSavePlugin) { + $fileUploadPostSavePlugin->execute($fileUploadTransfer); + } + } } diff --git a/src/Pyz/Zed/FileUpload/Communication/Controller/UploadController.php b/src/Pyz/Zed/FileUpload/Communication/Controller/UploadController.php deleted file mode 100644 index 0695a2b49..000000000 --- a/src/Pyz/Zed/FileUpload/Communication/Controller/UploadController.php +++ /dev/null @@ -1,191 +0,0 @@ -getFileUploadForm(SharedFileUploadConfig::ACCEPTED_IMAGE_CONTENT_TYPES); - - return [ - 'form' => $fileUploadForm->createView(), - ]; - } - - public function getImageUploadUrlAction(Request $request): JsonResponse - { - $formOptions = $this->getFactory() - ->createFileUploadDataProvider() - ->getOptions(SharedFileUploadConfig::ACCEPTED_IMAGE_CONTENT_TYPES); - $fileUploadForm = $this->getFactory() - ->createFileUploadForm($formOptions) - ->handleRequest($request); - - if (!$fileUploadForm->isSubmitted()) { - return $this->getJsonErrorResponse([self::ERROR_FORM_NOT_SUBMITTED]); - } - - if (!$fileUploadForm->isValid()) { - $errorMessages = $this->getFormErrorMessages($fileUploadForm); - - return $this->getJsonErrorResponse($errorMessages); - } - - /** @var \Generated\Shared\Transfer\FileUploadTransfer $formUploadTransfer */ - $formUploadTransfer = $fileUploadForm->getData(); - $merchantTransfer = $this->findMerchantById($formUploadTransfer->getFkMerchant()); - if (!$merchantTransfer) { - return $this->getJsonErrorResponse([self::ERROR_MERCHANT_NOT_FOUND]); - } - - $uploadFileName = $this->getFacade()->buildUploadFileNameForMerchant( - $formUploadTransfer->getOriginalFileName(), - $formUploadTransfer->getContentType(), - $merchantTransfer->getMerchantReference(), - ); - - $preSignedUrl = $this->getFactory() - ->getAwsS3Service() - ->getPresignedUrl($uploadFileName, SharedAwsS3Config::OBJECT_TYPE_ADDITIONAL_MEDIA); - - return $this->jsonResponse([ - self::PARAM_FILE_URL => $preSignedUrl, - self::PARAM_FILE_NAME => $uploadFileName, - self::PARAM_ID_MERCHANT => $merchantTransfer->getIdMerchant(), - ]); - } - - /** - * @param \Symfony\Component\HttpFoundation\Request $request - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - */ - public function saveImageUploadDataAction(Request $request): JsonResponse - { - $fileUploadTransfer = $this->createHydratedFileUploadTransferForImage($request); - - $fileUploadTransfer = $this->getFacade() - ->createFileUpload($fileUploadTransfer); - - return $this->jsonResponse([ - 'success' => true, - 'cdnUrl' => $fileUploadTransfer->getCdnUrl(), - ]); - } - - /** - * @param array $acceptedContentType - * - * @return \Symfony\Component\Form\FormInterface - */ - private function getFileUploadForm(array $acceptedContentType): FormInterface - { - $formOptions = $this->getFactory() - ->createFileUploadDataProvider() - ->getOptions($acceptedContentType); - - return $this->getFactory() - ->createFileUploadForm($formOptions); - } - - /** - * @param array $errorMessages - * - * @return \Symfony\Component\HttpFoundation\JsonResponse - */ - private function getJsonErrorResponse(array $errorMessages): JsonResponse - { - return $this->jsonResponse( - [ - 'errors' => $errorMessages, - ], - JsonResponse::HTTP_UNPROCESSABLE_ENTITY, - ); - } - - private function createHydratedFileUploadTransferForImage(Request $request): FileUploadTransfer - { - $fileName = $request->get(self::PARAM_FILE_NAME); - $size = $request->get(self::PARAM_FILE_SIZE); - $type = $request->get(self::PARAM_FILE_TYPE); - $originalName = $request->get(self::PARAM_ORIGINAL_FILE_NAME); - $idMerchant = $request->get(self::PARAM_ID_MERCHANT); - $idUser = $this->getFactory()->getUserFacade()->getCurrentUser()->getIdUser(); - - return (new FileUploadTransfer()) - ->setOriginalFileName($originalName) - ->setFileName($fileName) - ->setContentType($type) - ->setSize($size) - ->setFkMerchant($idMerchant) - ->setFkUser($idUser) - ->setObjectType(SharedAwsS3Config::OBJECT_TYPE_ADDITIONAL_MEDIA); - } - - /** - * @param \Symfony\Component\Form\FormInterface $form - * - * @return array - */ - private function getFormErrorMessages(FormInterface $form): array - { - $formErrorIterator = $form->getErrors(true); - $errorMessages = []; - foreach ($formErrorIterator as $formError) { - $errorMessages[] = $formError->getMessage(); - } - - return $errorMessages; - } - - private function findMerchantById(int $idMerchant): ?MerchantTransfer - { - $merchantCriteriaTransfer = $this->createMerchantCriteriaTransfer()->setIdMerchant($idMerchant); - - return $this->getFactory()->getMerchantFacade()->findOne($merchantCriteriaTransfer); - } - - private function createMerchantCriteriaTransfer(): MerchantCriteriaTransfer - { - return new MerchantCriteriaTransfer(); - } -} diff --git a/src/Pyz/Zed/FileUpload/Communication/FileUploadCommunicationFactory.php b/src/Pyz/Zed/FileUpload/Communication/FileUploadCommunicationFactory.php deleted file mode 100644 index 10f8faff5..000000000 --- a/src/Pyz/Zed/FileUpload/Communication/FileUploadCommunicationFactory.php +++ /dev/null @@ -1,54 +0,0 @@ -getFormFactory()->create(FileUploadForm::class, null, $options); - } - - public function createFileUploadDataProvider(): FileUploadDataProviderInterface - { - return new FileUploadDataProvider($this->getMerchantFacade()); - } - - public function getUserFacade(): UserFacadeInterface - { - return $this->getProvidedDependency(FileUploadDependencyProvider::FACADE_USER); - } - - public function getMerchantFacade(): MerchantFacadeInterface - { - return $this->getProvidedDependency(FileUploadDependencyProvider::FACADE_MERCHANT); - } - - public function getAwsS3Service(): AwsS3ServiceInterface - { - return $this->getProvidedDependency(FileUploadDependencyProvider::SERVICE_AWS_S3); - } -} diff --git a/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProvider.php b/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProvider.php deleted file mode 100644 index 139529f59..000000000 --- a/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProvider.php +++ /dev/null @@ -1,38 +0,0 @@ -merchantFacade = $merchantFacade; - } - - public function getOptions(array $acceptedContentTypes): array - { - return [ - FileUploadForm::OPTION_MERCHANT_CHOICES => $this->getMerchantChoices(), - FileUploadForm::OPTION_ACCEPTED_CONTENT_TYPE => $acceptedContentTypes, - ]; - } - - private function getMerchantChoices(): array - { - $activeMerchantNames = $this->merchantFacade->getActiveMerchantNamesWithIds(); - - return array_flip($activeMerchantNames); - } -} diff --git a/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProviderInterface.php b/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProviderInterface.php deleted file mode 100644 index f67a6dee4..000000000 --- a/src/Pyz/Zed/FileUpload/Communication/Form/DataProvider/FileUploadDataProviderInterface.php +++ /dev/null @@ -1,20 +0,0 @@ - $acceptedContentTypes - * - * @return array - */ - public function getOptions(array $acceptedContentTypes): array; -} diff --git a/src/Pyz/Zed/FileUpload/Communication/Form/FileUploadForm.php b/src/Pyz/Zed/FileUpload/Communication/Form/FileUploadForm.php deleted file mode 100644 index 7e607f47f..000000000 --- a/src/Pyz/Zed/FileUpload/Communication/Form/FileUploadForm.php +++ /dev/null @@ -1,142 +0,0 @@ -addFileNameField($builder); - $this->addContentTypeField($builder); - $this->addMerchantField($builder, $options); - - $builder->setAction(FileUploadConfig::URL_GET_IMAGE_UPLOAD_URL); - } - - /** - * @param \Symfony\Component\OptionsResolver\OptionsResolver $resolver - * - * @return void - */ - public function configureOptions(OptionsResolver $resolver): void - { - parent::configureOptions($resolver); - - $resolver->setDefaults([ - 'data_class' => FileUploadTransfer::class, - ]); - - $resolver->setRequired([ - self::OPTION_ACCEPTED_CONTENT_TYPE, - self::OPTION_MERCHANT_CHOICES, - ]); - } - - /** - * @param \Symfony\Component\Form\FormView $view - * @param \Symfony\Component\Form\FormInterface $form - * @param array $options - * - * @return void - */ - public function finishView(FormView $view, FormInterface $form, array $options): void - { - parent::finishView($view, $form, $options); - - $view->vars[self::OPTION_ACCEPTED_CONTENT_TYPE] = $options[self::OPTION_ACCEPTED_CONTENT_TYPE]; - } - - /** - * @param \Symfony\Component\Form\FormBuilderInterface $builder - * - * @return void - */ - private function addFileNameField(FormBuilderInterface $builder): void - { - $builder->add(self::FIELD_FILE_NAME, HiddenType::class, [ - 'constraints' => [ - new NotBlank(['message' => self::ERROR_FILE_NAME_NOT_PROVIDED]), - ], - ]); - } - - /** - * @param \Symfony\Component\Form\FormBuilderInterface $builder - * - * @return void - */ - private function addContentTypeField(FormBuilderInterface $builder): void - { - $builder->add(self::FIELD_CONTENT_TYPE, HiddenType::class, [ - 'constraints' => [ - new NotBlank(['message' => self::ERROR_CONTENT_TYPE_NOT_PROVIDED]), - ], - ]); - } - - /** - * @param \Symfony\Component\Form\FormBuilderInterface $builder - * @param array $options - * - * @return void - */ - private function addMerchantField(FormBuilderInterface $builder, array $options): void - { - $builder->add(self::FIELD_MERCHANT, ChoiceType::class, [ - 'required' => true, - 'label' => 'Merchant', - 'choices' => $options[self::OPTION_MERCHANT_CHOICES], - 'constraints' => [ - new NotBlank(['message' => self::ERROR_MERCHANT_NOT_SELECTED]), - ], - ]); - } -} diff --git a/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadAclEntityConfigurationExpanderPlugin.php b/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadAclEntityConfigurationExpanderPlugin.php index 2a8646e3c..e5cf2922b 100644 --- a/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadAclEntityConfigurationExpanderPlugin.php +++ b/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadAclEntityConfigurationExpanderPlugin.php @@ -30,6 +30,7 @@ public function expand(AclEntityMetadataConfigTransfer $aclEntityMetadataConfigT 'Orm\Zed\FileUpload\Persistence\PyzFileUpload', (new AclEntityMetadataTransfer()) ->setEntityName('Orm\Zed\FileUpload\Persistence\PyzFileUpload') + ->setIsSubEntity(true) ->setParent((new AclEntityParentMetadataTransfer()) ->setEntityName('Orm\Zed\Merchant\Persistence\SpyMerchant')), ); diff --git a/src/Pyz/Zed/FileUpload/Dependency/Plugin/FileUploadPostSavePluginInterface.php b/src/Pyz/Zed/FileUpload/Dependency/Plugin/FileUploadPostSavePluginInterface.php new file mode 100644 index 000000000..0a56e8775 --- /dev/null +++ b/src/Pyz/Zed/FileUpload/Dependency/Plugin/FileUploadPostSavePluginInterface.php @@ -0,0 +1,22 @@ + SharedFileUploadConfig::ACCEPTED_IMAGE_CONTENT_TYPES, self::FILE_TYPE_VIDEO => SharedFileUploadConfig::ACCEPTED_VIDEO_CONTENT_TYPES, self::FILE_TYPE_DOCUMENT => SharedFileUploadConfig::ACCEPTED_DOCUMENT_CONTENT_TYPES, + self::FILE_TYPE_IMPORT_CSV => ['text/csv'], ]; /** @@ -50,6 +53,7 @@ class FileUploadConfig extends AbstractBundleConfig self::FILE_TYPE_IMAGE => self::IMAGE_FILE_NAME_PATTERN, self::FILE_TYPE_VIDEO => self::VIDEO_FILE_NAME_PATTERN, self::FILE_TYPE_DOCUMENT => self::DOCUMENT_FILE_NAME_PATTERN, + self::FILE_TYPE_IMPORT_CSV => self::IMPORT_CSV_FILE_NAME_PATTERN, ]; private const FILE_TYPE_IMAGE = 'image'; @@ -58,6 +62,8 @@ class FileUploadConfig extends AbstractBundleConfig private const FILE_TYPE_DOCUMENT = 'document'; + private const FILE_TYPE_IMPORT_CSV = 'import_csv'; + /** * @return array> */ diff --git a/src/Pyz/Zed/FileUpload/FileUploadDependencyProvider.php b/src/Pyz/Zed/FileUpload/FileUploadDependencyProvider.php index dff326b8d..960a8ee3c 100644 --- a/src/Pyz/Zed/FileUpload/FileUploadDependencyProvider.php +++ b/src/Pyz/Zed/FileUpload/FileUploadDependencyProvider.php @@ -10,8 +10,9 @@ namespace Pyz\Zed\FileUpload; use Pyz\Service\AwsS3\AwsS3ServiceInterface; -use Pyz\Zed\Merchant\Business\MerchantFacadeInterface; -use Pyz\Zed\User\Business\UserFacadeInterface; +use Pyz\Zed\MerchantProductImport\Communication\Plugin\FileUpload\MerchantProductImpostPostSavePlugin; +use Spryker\Zed\Merchant\Business\MerchantFacadeInterface; +use Spryker\Zed\User\Business\UserFacadeInterface; use Spryker\Zed\Kernel\AbstractBundleDependencyProvider; use Spryker\Zed\Kernel\Container; use Spryker\Zed\MerchantUser\Business\MerchantUserFacadeInterface; @@ -26,12 +27,15 @@ class FileUploadDependencyProvider extends AbstractBundleDependencyProvider public const SERVICE_AWS_S3 = 'SERVICE_AWS_S3'; + public const PLUGINS_FILE_UPLOAD_POST_SAVE = 'PLUGINS_FILE_UPLOAD_POST_SAVE'; + public function provideBusinessLayerDependencies(Container $container): Container { $container = parent::provideBusinessLayerDependencies($container); $this->addMerchantUserFacade($container); $this->addAwsS3Service($container); + $this->addFileUploadPostSavePlugins($container); return $container; } @@ -106,4 +110,24 @@ static function (Container $container): UserFacadeInterface { }, ); } + + private function addFileUploadPostSavePlugins(Container $container): void + { + $container->set( + self::PLUGINS_FILE_UPLOAD_POST_SAVE, + function (): array { + return $this->getFileUploadPostSavePlugins(); + } + ); + } + + /** + * @return array<\Pyz\Zed\FileUpload\Dependency\Plugin\FileUploadPostSavePluginInterface> + */ + private function getFileUploadPostSavePlugins(): array + { + return [ + new MerchantProductImpostPostSavePlugin(), + ]; + } } diff --git a/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManager.php b/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManager.php index 5daebcef5..d39c78323 100644 --- a/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManager.php +++ b/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManager.php @@ -21,15 +21,19 @@ class FileUploadEntityManager extends AbstractEntityManager implements FileUploa /** * @param \Generated\Shared\Transfer\FileUploadTransfer $fileUploadTransfer * - * @return void + * @return \Generated\Shared\Transfer\FileUploadTransfer */ - public function createFileUpload(FileUploadTransfer $fileUploadTransfer): void + public function createFileUpload(FileUploadTransfer $fileUploadTransfer): FileUploadTransfer { $pyzFileUpload = $this->getFactory() ->createFileUploadMapper() ->mapTransferToEntity($fileUploadTransfer, new PyzFileUpload()); $pyzFileUpload->save(); + + $fileUploadTransfer->setIdFileUpload($pyzFileUpload->getIdFileUpload()); + + return $fileUploadTransfer; } public function deleteFileUpload(FileUploadTransfer $fileUploadTransfer): bool diff --git a/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManagerInterface.php b/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManagerInterface.php index 0942b5d3a..2dea39950 100644 --- a/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManagerInterface.php +++ b/src/Pyz/Zed/FileUpload/Persistence/FileUploadEntityManagerInterface.php @@ -17,9 +17,9 @@ interface FileUploadEntityManagerInterface extends EntityManagerInterface /** * @param \Generated\Shared\Transfer\FileUploadTransfer $fileUploadTransfer * - * @return void + * @return \Generated\Shared\Transfer\FileUploadTransfer */ - public function createFileUpload(FileUploadTransfer $fileUploadTransfer): void; + public function createFileUpload(FileUploadTransfer $fileUploadTransfer): FileUploadTransfer; public function deleteFileUpload(FileUploadTransfer $fileUploadTransfer): bool; } diff --git a/src/Pyz/Zed/FileUpload/Persistence/Propel/Schema/pyz_file_upload.schema.xml b/src/Pyz/Zed/FileUpload/Persistence/Propel/Schema/pyz_file_upload.schema.xml index 9191fdded..b4198059f 100644 --- a/src/Pyz/Zed/FileUpload/Persistence/Propel/Schema/pyz_file_upload.schema.xml +++ b/src/Pyz/Zed/FileUpload/Persistence/Propel/Schema/pyz_file_upload.schema.xml @@ -8,7 +8,7 @@ - + diff --git a/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Controller/UploadController.php b/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Controller/UploadController.php index d5e68cc7a..f429e28a6 100644 --- a/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Controller/UploadController.php +++ b/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Controller/UploadController.php @@ -11,6 +11,7 @@ use Generated\Shared\Transfer\FileUploadTransfer; use Pyz\Shared\AwsS3\AwsS3Config as SharedAwsS3Config; +use Pyz\Shared\FileUpload\FileUploadConfig; use Spryker\Zed\Kernel\Communication\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; @@ -70,6 +71,19 @@ public function saveUploadDataAction(Request $request): JsonResponse ]); } + private function resolveResourceObjectType(string $contentType): string + { + if (in_array($contentType, array_merge( + FileUploadConfig::ACCEPTED_DOCUMENT_CONTENT_TYPES, + FileUploadConfig::ACCEPTED_IMAGE_CONTENT_TYPES, + FileUploadConfig::ACCEPTED_VIDEO_CONTENT_TYPES, + ))) { + return SharedAwsS3Config::OBJECT_TYPE_ADDITIONAL_MEDIA; + } + + return SharedAwsS3Config::OBJECT_TYPE_CVS_IMPORT; + } + private function createHydratedFileUploadTransfer(Request $request): FileUploadTransfer { $fileName = $request->get(self::PARAM_FILE_NAME); @@ -82,7 +96,7 @@ private function createHydratedFileUploadTransfer(Request $request): FileUploadT ->setFileName($fileName) ->setContentType($type) ->setSize($size) - ->setObjectType(SharedAwsS3Config::OBJECT_TYPE_ADDITIONAL_MEDIA); + ->setObjectType($this->resolveResourceObjectType($type)); } private function createErrorJsonResponse(string $message): JsonResponse diff --git a/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php b/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php similarity index 93% rename from src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php rename to src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php index c657380a2..e3d82ef8c 100644 --- a/src/Pyz/Zed/FileUpload/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php +++ b/src/Pyz/Zed/FileUploadMerchantPortalGui/Communication/Plugin/AclMerchantPortal/FileUploadMerchantPortalGuiMerchantAclRuleExpanderPlugin.php @@ -2,7 +2,7 @@ declare(strict_types=1); -namespace Pyz\Zed\FileUpload\Communication\Plugin\AclMerchantPortal; +namespace Pyz\Zed\FileUploadMerchantPortalGui\Communication\Plugin\AclMerchantPortal; use Generated\Shared\Transfer\RuleTransfer; use Spryker\Zed\AclMerchantPortalExtension\Dependency\Plugin\MerchantAclRuleExpanderPluginInterface; diff --git a/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportBusinessFactory.php b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportBusinessFactory.php new file mode 100644 index 000000000..d432f7bbb --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportBusinessFactory.php @@ -0,0 +1,44 @@ +getConfig(), + $this->getRepository(), + ); + } + + /** + * @return \Pyz\Zed\MerchantProductImport\Business\Writer\ImportUploadWriterInterface + */ + public function createImportUploadWriter(): ImportUploadWriterInterface + { + return new ImportUploadWriter( + $this->getConfig(), + $this->getEntityManager(), + ); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacade.php b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacade.php new file mode 100644 index 000000000..53e70afeb --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacade.php @@ -0,0 +1,46 @@ +getFactory() + ->createImportUploadWriter() + ->createImportUpload($fileUploadTransfer); + } + + public function updateImportUpload(ImportUploadTransfer $importUploadTransfer): ImportUploadResponseTransfer + { + return $this->getFactory() + ->createImportUploadWriter() + ->updateImportUpload($importUploadTransfer); + } + + public function getImportUploads( + ImportUploadCriteriaTransfer $importUploadCriteriaTransfer, + ): ImportUploadCollectionTransfer { + return $this->getFactory() + ->createImportUploadReader() + ->get($importUploadCriteriaTransfer); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacadeInterface.php b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacadeInterface.php new file mode 100644 index 000000000..d0762abf8 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Business/MerchantProductImportFacadeInterface.php @@ -0,0 +1,34 @@ +merchantProductImportConfig = $merchantProductImportConfig; + $this->merchantProductImportRepository = $merchantProductImportRepository; + } + + public function get(ImportUploadCriteriaTransfer $importUploadCriteriaTransfer): ImportUploadCollectionTransfer + { + return $this->merchantProductImportRepository->get($importUploadCriteriaTransfer); + } + + /** + * @return \Generated\Shared\Transfer\ImportUploadCollectionTransfer + */ + public function getLatestPendingImportUploads(): ImportUploadCollectionTransfer + { + $sortCollection = new ArrayObject(); + $sortCollection + ->append( + (new SortTransfer()) + ->setField(PyzImportUploadTableMap::COL_CREATED_AT) + ->setIsAscending(true), + ); + + $importUploadCriteriaTransfer = (new ImportUploadCriteriaTransfer()) + ->setImportUploadConditions( + (new ImportUploadConditionsTransfer()) + ->setStatus(MerchantProductImportConfig::STATUS_PENDING), + ) + ->setPagination( + (new PaginationTransfer()) + ->setLimit($this->merchantProductImportConfig->getImportUploadReadLimit()), + ) + ->setSortCollection($sortCollection); + + return $this->merchantProductImportRepository->get($importUploadCriteriaTransfer); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Business/Reader/ImportUploadReaderInterface.php b/src/Pyz/Zed/MerchantProductImport/Business/Reader/ImportUploadReaderInterface.php new file mode 100644 index 000000000..efcca6a80 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Business/Reader/ImportUploadReaderInterface.php @@ -0,0 +1,21 @@ +merchantImportUploadConfig = $merchantImportUploadConfig; + $this->merchantProductImportEntityManager = $merchantProductImportEntityManager; + } + + public function createImportUpload(FileUploadTransfer $fileUploadTransfer): ImportUploadResponseTransfer + { + $importUploadTransfer = $this->createImportUploadTransfer($fileUploadTransfer); + $importUploadResponseTransfer = (new ImportUploadResponseTransfer())->setIsSuccessful(true); + + $importUploadCollectionTransfer = $this->merchantProductImportEntityManager->saveImportUploadCollection( + (new ImportUploadCollectionTransfer())->addImportUpload($importUploadTransfer), + ); + + if ($importUploadCollectionTransfer->getImportUploads()->count() === 0) { + $importUploadResponseTransfer->setIsSuccessful(false); + $importUploadResponseTransfer->setMessage('Failed to create import upload'); + } + + $importUploadResponseTransfer->setImportUpload($importUploadCollectionTransfer->getImportUploads()->offsetGet(0)); + + return $importUploadResponseTransfer; + } + + public function updateImportUpload(ImportUploadTransfer $importUploadTransfer): ImportUploadResponseTransfer + { + $importUploadResponseTransfer = (new ImportUploadResponseTransfer())->setIsSuccessful(true); + + if ($importUploadTransfer->getIdImportUpload() === null) { + $importUploadResponseTransfer->setIsSuccessful(false); + $importUploadResponseTransfer->setMessage('Upload ID is missing'); + + return $importUploadResponseTransfer; + } + + try { + $this->merchantProductImportEntityManager->updateImportUpload($importUploadTransfer); + } catch (EntityNotFoundException) { + $importUploadResponseTransfer->setIsSuccessful(false); + $importUploadResponseTransfer->setMessage('Failed to update import upload. Wrong ID provided.'); + + return $importUploadResponseTransfer; + } + + return $importUploadResponseTransfer->setImportUpload($importUploadTransfer); + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadCollectionTransfer $importUploadCollectionTransfer + * @param string $status + * + * @throws \RuntimeException + * + * @return \Generated\Shared\Transfer\ImportUploadCollectionTransfer + */ + public function updateImportUploadsCollectionStatus( + ImportUploadCollectionTransfer $importUploadCollectionTransfer, + string $status, + ): ImportUploadCollectionTransfer { + if (!in_array($status, $this->merchantImportUploadConfig->getImportUploadStatues())) { + throw new RuntimeException(sprintf("Merchant import upload status '%s' is not allowed.", $status)); + } + + foreach ($importUploadCollectionTransfer->getImportUploads() as $importUploadTransfer) { + if ($importUploadTransfer->getStatus() === $status) { + continue; + } + + $currentTime = (new DateTime())->format(DateTimeInterface::ATOM); + $importUploadTransfer + ->setStatus($status) + ->setStartedAt($currentTime) + ->setStatusUpdatedAt($currentTime); + } + + return $this->merchantProductImportEntityManager->saveImportUploadCollection($importUploadCollectionTransfer); + } + + private function createImportUploadTransfer( + FileUploadTransfer $fileUploadTransfer, + ): ImportUploadTransfer { + return (new ImportUploadTransfer()) + ->setFileUpload($fileUploadTransfer) + ->setFkMerchant($fileUploadTransfer->getFkMerchant()) + ->setFkUser($fileUploadTransfer->getFkUser()) + ->setStatus(MerchantProductImportConfig::STATUS_PENDING) + ->setCreatedAt((new DateTime())->format(DateTimeInterface::ATOM)); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Business/Writer/ImportUploadWriterInterface.php b/src/Pyz/Zed/MerchantProductImport/Business/Writer/ImportUploadWriterInterface.php new file mode 100644 index 000000000..8040d7816 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Business/Writer/ImportUploadWriterInterface.php @@ -0,0 +1,31 @@ +getAclEntityMetadataCollectionOrFail() + ->addAclEntityMetadata( + 'Orm\Zed\MerchantProductImport\Persistence\PyzImportUpload', + (new AclEntityMetadataTransfer()) + ->setEntityName('Orm\Zed\MerchantProductImport\Persistence\PyzImportUpload') + ->setParent( + (new AclEntityParentMetadataTransfer()) + ->setEntityName('Orm\Zed\Merchant\Persistence\SpyMerchant'), + ), + ); + + return $aclEntityMetadataConfigTransfer; + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/AclMerchantPortal/ImportUploadMerchantAclEntityRuleExpanderPlugin.php b/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/AclMerchantPortal/ImportUploadMerchantAclEntityRuleExpanderPlugin.php new file mode 100644 index 000000000..23f5ee918 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/AclMerchantPortal/ImportUploadMerchantAclEntityRuleExpanderPlugin.php @@ -0,0 +1,48 @@ +setEntity('Orm\Zed\MerchantProductImport\Persistence\PyzImportUpload') + ->setScope(self::SCOPE_INHERITED) + ->setPermissionMask(self::OPERATION_MASK_READ | self::OPERATION_MASK_CREATE); + + return $aclEntityRuleTransfers; + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/FileUpload/MerchantProductImpostPostSavePlugin.php b/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/FileUpload/MerchantProductImpostPostSavePlugin.php new file mode 100644 index 000000000..ea7dbc9ba --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Communication/Plugin/FileUpload/MerchantProductImpostPostSavePlugin.php @@ -0,0 +1,33 @@ +getObjectType() !== self::FILE_TYPE_IMPORT_CSV) { + return; + } + + $this->getFacade()->createImportUpload($fileUploadTransfer); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/MerchantProductImportConfig.php b/src/Pyz/Zed/MerchantProductImport/MerchantProductImportConfig.php new file mode 100644 index 000000000..3ad22835d --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/MerchantProductImportConfig.php @@ -0,0 +1,71 @@ +get(MerchantProductImportConstants::IMPORT_UPLOAD_READ_LIMIT); + } + + /** + * @return array + */ + public function getImportUploadStatues(): array + { + return [ + self::STATUS_PENDING, + self::STATUS_IN_PROGRESS, + self::STATUS_FAILED, + self::STATUS_PARTIALLY_FAILED, + self::STATUS_SUCCESSFUL, + ]; + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/MerchantProductImportDependencyProvider.php b/src/Pyz/Zed/MerchantProductImport/MerchantProductImportDependencyProvider.php new file mode 100644 index 000000000..7f22b3105 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/MerchantProductImportDependencyProvider.php @@ -0,0 +1,14 @@ +getFactory()->createImportUploadMapper(); + + $pyzImportUploadEntityCollection = $importUploadMapper->mapImportUploadCollectionTransferToImportUploadEntityCollection($importUploadCollectionTransfer); + $pyzImportUploadEntityCollection->save(); + + return $importUploadMapper->mapImportUploadEntityCollectionToImportUploadCollectionTransfer($pyzImportUploadEntityCollection); + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadTransfer $importUploadTransfer + * + * @throws \Propel\Runtime\Exception\EntityNotFoundException + * + * @return void + */ + public function updateImportUpload(ImportUploadTransfer $importUploadTransfer): void + { + $pyzImportUploadEntity = $this->getFactory() + ->createImportUploadPropelQuery() + ->filterByIdImportUpload($importUploadTransfer->getIdImportUpload()) + ->findOne(); + + if (!$pyzImportUploadEntity) { + throw new EntityNotFoundException( + sprintf('Import upload entity with id "%s" not found', $importUploadTransfer->getIdImportUpload()), + ); + } + + $pyzImportUploadEntity->fromArray($importUploadTransfer->modifiedToArray()); + + $pyzImportUploadEntity->save(); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportEntityManagerInterface.php b/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportEntityManagerInterface.php new file mode 100644 index 000000000..8f17b61c0 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportEntityManagerInterface.php @@ -0,0 +1,23 @@ +getFactory()->createImportUploadPropelQuery(); + + $importUploadQuery = $this->applyCriteria($importUploadCriteriaTransfer, $importUploadQuery); + $importUploadQuery = $this->applySortings($importUploadCriteriaTransfer, $importUploadQuery); + $importUploadQuery = $this->applyPagination($importUploadCriteriaTransfer, $importUploadQuery); + + /** @var \Propel\Runtime\Collection\ObjectCollection<\Orm\Zed\MerchantProductImport\Persistence\Base\PyzImportUpload> $pyzImportUploadEntityCollection */ + $pyzImportUploadEntityCollection = $importUploadQuery->find(); + + return $this->getFactory()->createImportUploadMapper() + ->mapImportUploadEntityCollectionToImportUploadCollectionTransfer($pyzImportUploadEntityCollection); + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadCriteriaTransfer $importUploadCriteriaTransfer + * @param \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery $importUploadQuery + * + * @return \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery + */ + private function applyCriteria( + ImportUploadCriteriaTransfer $importUploadCriteriaTransfer, + PyzImportUploadQuery $importUploadQuery, + ): PyzImportUploadQuery { + $importUploadConditionsTransfer = $importUploadCriteriaTransfer->getImportUploadConditions(); + + if ($importUploadConditionsTransfer === null) { + return $importUploadQuery; + } + + if ($importUploadConditionsTransfer->getIdImportUpload() !== null) { + $importUploadQuery->filterByIdImportUpload($importUploadConditionsTransfer->getIdImportUpload()); + } + + if ($importUploadConditionsTransfer->getIdMerchant() !== null) { + $importUploadQuery->filterByFkMerchant($importUploadConditionsTransfer->getIdMerchant()); + } + + if ($importUploadConditionsTransfer->getIdUser() !== null) { + $importUploadQuery->filterByFkUser($importUploadConditionsTransfer->getIdUser()); + } + + if ($importUploadConditionsTransfer->getStatus() !== null) { + $importUploadQuery->filterByStatus($importUploadConditionsTransfer->getStatus()); + } + + return $importUploadQuery; + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadCriteriaTransfer $importUploadCriteriaTransfer + * @param \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery $pyzImportUploadQuery + * + * @return \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery + */ + private function applySortings( + ImportUploadCriteriaTransfer $importUploadCriteriaTransfer, + PyzImportUploadQuery $pyzImportUploadQuery, + ): PyzImportUploadQuery { + foreach ($importUploadCriteriaTransfer->getSortCollection() as $sortTransfer) { + $pyzImportUploadQuery->orderBy( + $sortTransfer->getField(), + $sortTransfer->getIsAscending() ? Criteria::ASC : Criteria::DESC, + ); + } + + return $pyzImportUploadQuery; + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadCriteriaTransfer $importUploadCriteriaTransfer + * @param \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery $pyzImportUploadQuery + * + * @return \Orm\Zed\MerchantProductImport\Persistence\PyzImportUploadQuery + */ + private function applyPagination( + ImportUploadCriteriaTransfer $importUploadCriteriaTransfer, + PyzImportUploadQuery $pyzImportUploadQuery, + ): PyzImportUploadQuery { + $paginationTransfer = $importUploadCriteriaTransfer->getPagination(); + + if ($paginationTransfer === null) { + return $pyzImportUploadQuery; + } + + $paginationTransfer->setNbResults($pyzImportUploadQuery->count()); + + if ($paginationTransfer->getLimit() !== null) { + $pyzImportUploadQuery + ->setLimit($paginationTransfer->getLimit()); + } + + if ($paginationTransfer->getOffset() !== null) { + $pyzImportUploadQuery + ->setOffset($paginationTransfer->getOffset()); + } + + return $pyzImportUploadQuery; + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportRepositoryInterface.php b/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportRepositoryInterface.php new file mode 100644 index 000000000..4098036c4 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Persistence/MerchantProductImportRepositoryInterface.php @@ -0,0 +1,21 @@ +fromArray($pyzImportUploadEntity->toArray(), true) + ->setFileUpload($this->mapFileUploadEntityToTransfer($pyzImportUploadEntity->getPyzFileUpload())); + + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadTransfer $importUploadTransfer + * + * @return \Orm\Zed\MerchantProductImport\Persistence\PyzImportUpload + */ + public function mapImportUploadTransferToImportUploadEntity(ImportUploadTransfer $importUploadTransfer): PyzImportUpload + { + $pyzImportUploadEntity = (new PyzImportUpload()) + ->fromArray($importUploadTransfer->toArray()) + ->setFkFileUpload($importUploadTransfer->getFileUpload()->getIdFileUpload()); + + $pyzImportUploadEntity->setNew($importUploadTransfer->getIdImportUpload() ? false : true); + + return $pyzImportUploadEntity; + } + + /** + * @param \Orm\Zed\Merchant\Persistence\SpyMerchant $spyMerchantEntity + * + * @return \Generated\Shared\Transfer\MerchantTransfer + */ + private function mapMerchantEntityToMerchantTransfer(SpyMerchant $spyMerchantEntity): MerchantTransfer + { + return (new MerchantTransfer()) + ->fromArray($spyMerchantEntity->toArray(), true); + } + + /** + * @param \Orm\Zed\User\Persistence\SpyUser $spyUserEntity + * + * @return \Generated\Shared\Transfer\UserTransfer + */ + private function mapUserEntityToUserTransfer(SpyUser $spyUserEntity): UserTransfer + { + return (new UserTransfer()) + ->fromArray($spyUserEntity->toArray(), true); + } + + /** + * @param \Propel\Runtime\Collection\ObjectCollection $pyzImportUploadEntityCollection + * + * @return \Generated\Shared\Transfer\ImportUploadCollectionTransfer + */ + public function mapImportUploadEntityCollectionToImportUploadCollectionTransfer( + ObjectCollection $pyzImportUploadEntityCollection, + ): ImportUploadCollectionTransfer { + $importUploadCollectionTransfer = new ImportUploadCollectionTransfer(); + + foreach ($pyzImportUploadEntityCollection as $pyzImportUploadEntity) { + $importUploadCollectionTransfer->addImportUpload( + $this->mapImportUploadEntityToImportUploadTransfer($pyzImportUploadEntity), + ); + } + + return $importUploadCollectionTransfer; + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadCollectionTransfer $importUploadCollectionTransfer + * + * @return \Propel\Runtime\Collection\ObjectCollection<\Orm\Zed\MerchantProductImport\Persistence\Base\PyzImportUpload> + */ + public function mapImportUploadCollectionTransferToImportUploadEntityCollection( + ImportUploadCollectionTransfer $importUploadCollectionTransfer, + ): ObjectCollection { + $pyzImportUploadEntityCollection = new ObjectCollection(); + $pyzImportUploadEntityCollection->setModel(PyzImportUpload::class); + + foreach ($importUploadCollectionTransfer->getImportUploads() as $importUploadTransfer) { + $pyzImportUploadEntityCollection->append( + $this->mapImportUploadTransferToImportUploadEntity($importUploadTransfer), + ); + } + + return $pyzImportUploadEntityCollection; + } + + private function mapFileUploadEntityToTransfer(PyzFileUpload $fileUpload): FileUploadTransfer + { + return (new FileUploadTransfer()) + ->fromArray($fileUpload->toArray(), true); + } +} diff --git a/src/Pyz/Zed/MerchantProductImport/Persistence/Propel/Schema/pyz_import_upload.schema.xml b/src/Pyz/Zed/MerchantProductImport/Persistence/Propel/Schema/pyz_import_upload.schema.xml new file mode 100644 index 000000000..d2e80a788 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImport/Persistence/Propel/Schema/pyz_import_upload.schema.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Controller/ImportsController.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Controller/ImportsController.php new file mode 100644 index 000000000..9ef94da07 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Controller/ImportsController.php @@ -0,0 +1,59 @@ + + */ + public function indexAction(): array + { + $viewData = $this->prepareViewData(); + + return $this->viewResponse($viewData); + } + + public function tableDataAction(Request $request): Response + { + return $this->getFactory()->getGuiTableHttpDataRequestExecutor()->execute( + $request, + $this->getFactory()->createImportUploadGuiTableDataProvider(), + $this->getFactory()->createImportUploadGuiTableConfigurationProvider()->getConfiguration(), + ); + } + + /** + * @SuppressWarnings(PHPMD.LongVariable) + * + * @return array + */ + private function prepareViewData(): array + { + $importUploadGuiTableConfigurationProvider = $this->getFactory() + ->createImportUploadGuiTableConfigurationProvider(); + + return [ + 'idTableProductImport' => self::TABLE_ID_PRODUCT_IMPORT, + 'tableConfiguration' => $importUploadGuiTableConfigurationProvider->getConfiguration(), + ]; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProvider.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProvider.php new file mode 100644 index 000000000..b97c02da7 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProvider.php @@ -0,0 +1,124 @@ +guiTableFactory = $guiTableFactory; + $this->config = $config; + } + + public function getConfiguration(): GuiTableConfigurationTransfer + { + $guiTableConfigurationBuilder = $this->guiTableFactory->createConfigurationBuilder() + ->setDataSourceUrl(self::DATA_URL) + ->isSearchEnabled(false); + + $guiTableConfigurationBuilder = $this->addColumns($guiTableConfigurationBuilder); + $guiTableConfigurationBuilder = $this->addFilters($guiTableConfigurationBuilder); + + return $guiTableConfigurationBuilder->createConfiguration(); + } + + private function addColumns( + GuiTableConfigurationBuilderInterface $guiTableConfigurationBuilder, + ): GuiTableConfigurationBuilderInterface { + $guiTableConfigurationBuilder + ->addColumnText(self::COL_ID_OWNER, self::TITLE_COLUMN_OWNER, false, false) + ->addColumnText(self::COL_ID_ORIGINAL_FILE_NAME, self::TITLE_COLUMN_ORIGINAL_FILE_NAME, false, false) + ->addColumnText(self::COL_ID_UPLOAD_TIME, self::TITLE_COLUMN_UPLOAD_TIME, false, false) + ->addColumnText(self::COL_ID_PROCESSING_START_TIME, self::TITLE_COLUMN_PROCESSING_START_TIME, false, false) + ->addColumnText(self::COL_ID_PROCESSING_FINISH_TIME, self::TITLE_COLUMN_PROCESSING_FINISH_TIME, false, false) + ->addColumnText(self::COL_ID_TOTAL_NUMBER_OF_PRODUCTS, self::TITLE_COLUMN_TOTAL_NUMBER_OF_PRODUCTS, false, false) + ->addColumnText(self::COL_ID_NUMBER_OF_PRODUCTS_UPLOADED, self::TITLE_COLUMN_NUMBER_OF_PRODUCTS_UPLOADED, false, false) + ->addColumnText(self::COL_ID_NUMBER_OF_PRODUCTS_FAILED, self::TITLE_COLUMN_NUMBER_OF_PRODUCTS_FAILED, false, false) + ->addColumnChip(self::COL_ID_STATUS, self::TITLE_COLUMN_STATUS, false, false, self::COLOR_GREY, $this->config->getStatusChipColorMapping()) + ->addColumnText(self::COL_ID_STATUS_UPDATED_TIME, self::TITLE_COLUMN_STATUS_UPDATED_TIME, false, false) + ->addColumnText(self::COL_ID_ERRORS, self::TITLE_COLUMN_ERRORS, false, false, 1, 'gray'); + + return $guiTableConfigurationBuilder; + } + + private function addFilters( + GuiTableConfigurationBuilderInterface $guiTableConfigurationBuilder, + ): GuiTableConfigurationBuilderInterface { + $guiTableConfigurationBuilder->addFilterSelect( + self::FILTER_ID_STATUS, + self::TITLE_FILTER_STATUS, + false, + $this->config->getStatusEnumValueToLabelMap(), + ); + + return $guiTableConfigurationBuilder; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProviderInterface.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProviderInterface.php new file mode 100644 index 000000000..e5635a842 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/GuiTable/ConfigurationProvider/ImportUploadGuiTableConfigurationProviderInterface.php @@ -0,0 +1,15 @@ +productImportMerchantPortalGuiRepository = $productImportMerchantPortalGuiRepository; + $this->merchantUserFacade = $merchantUserFacade; + } + + /** + * @inheritDoc + */ + protected function createCriteria(GuiTableDataRequestTransfer $guiTableDataRequestTransfer): AbstractTransfer + { + return (new ProductImportGuiTableCriteriaTransfer()) + ->setFkMerchant($this->merchantUserFacade->getCurrentMerchantUser()->getIdMerchant()); + } + + /** + * @inheritDoc + * + * @param \Generated\Shared\Transfer\ProductImportGuiTableCriteriaTransfer $criteriaTransfer + */ + protected function fetchData(AbstractTransfer $criteriaTransfer): GuiTableDataResponseTransfer + { + $importUploadCollectionTransfer = $this->productImportMerchantPortalGuiRepository + ->getImportUploadTableData($criteriaTransfer); + + $guiTableDataResponseTransfer = new GuiTableDataResponseTransfer(); + foreach ($importUploadCollectionTransfer->getImportUploads() as $importUploadTransfer) { + $guiTableDataResponseTransfer->addRow($this->createGuiTableRowDataResponseTransfer($importUploadTransfer)); + } + + $guiTableDataResponseTransfer = $this->setPaginationData( + $guiTableDataResponseTransfer, + $importUploadCollectionTransfer->getPagination(), + ); + + return $guiTableDataResponseTransfer; + } + + private function createGuiTableRowDataResponseTransfer( + ImportUploadTransfer $importUploadTransfer, + ): GuiTableRowDataResponseTransfer { + return (new GuiTableRowDataResponseTransfer())->setResponseData([ + ImportUploadGuiTableConfigurationProvider::COL_ID_OWNER => $this->getOwnerColumnData($importUploadTransfer), + ImportUploadGuiTableConfigurationProvider::COL_ID_ORIGINAL_FILE_NAME => $importUploadTransfer->getOriginalFileName(), + ImportUploadGuiTableConfigurationProvider::COL_ID_UPLOAD_TIME => $importUploadTransfer->getCreatedAt(), + ImportUploadGuiTableConfigurationProvider::COL_ID_PROCESSING_START_TIME => $importUploadTransfer->getStartedAt(), + ImportUploadGuiTableConfigurationProvider::COL_ID_PROCESSING_FINISH_TIME => $importUploadTransfer->getFinishedAt(), + ImportUploadGuiTableConfigurationProvider::COL_ID_TOTAL_NUMBER_OF_PRODUCTS => $importUploadTransfer->getTotalNumberOfProducts(), + ImportUploadGuiTableConfigurationProvider::COL_ID_NUMBER_OF_PRODUCTS_UPLOADED => $importUploadTransfer->getNumberOfProductsUploaded(), + ImportUploadGuiTableConfigurationProvider::COL_ID_NUMBER_OF_PRODUCTS_FAILED => $importUploadTransfer->getNumberOfProductsFailed(), + ImportUploadGuiTableConfigurationProvider::COL_ID_STATUS => $importUploadTransfer->getStatus(), + ImportUploadGuiTableConfigurationProvider::COL_ID_STATUS_UPDATED_TIME => $importUploadTransfer->getStatusUpdatedAt(), + ImportUploadGuiTableConfigurationProvider::COL_ID_ERRORS => $this->getErrorsColumnData($importUploadTransfer), + ]); + } + + private function setPaginationData( + GuiTableDataResponseTransfer $guiTableDataResponseTransfer, + PaginationTransfer $paginationTransfer, + ): GuiTableDataResponseTransfer { + return $guiTableDataResponseTransfer + ->setPage($paginationTransfer->getPageOrFail()) + ->setPageSize($paginationTransfer->getMaxPerPageOrFail()) + ->setTotal($paginationTransfer->getNbResultsOrFail()); + } + + private function getOwnerColumnData(ImportUploadTransfer $importUploadTransfer): string + { + return sprintf( + '%s %s', + $importUploadTransfer->getUser()->getFirstName(), + $importUploadTransfer->getUser()->getLastName(), + ); + } + + /** + * @param \Generated\Shared\Transfer\ImportUploadTransfer $importUploadTransfer + * + * @return array + */ + private function getErrorsColumnData(ImportUploadTransfer $importUploadTransfer): array + { + return explode("\n", $importUploadTransfer->getErrors()); + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/MerchantProductImportMerchantPortalGuiCommunicationFactory.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/MerchantProductImportMerchantPortalGuiCommunicationFactory.php new file mode 100644 index 000000000..74063bfe7 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/MerchantProductImportMerchantPortalGuiCommunicationFactory.php @@ -0,0 +1,56 @@ +getGuiTableFactory(), + $this->getConfig(), + ); + } + + public function createImportUploadGuiTableDataProvider(): AbstractGuiTableDataProvider + { + return new ImportUploadGuiTableDataProvider( + $this->getRepository(), + $this->getMerchantUserFacade(), + ); + } + + public function getGuiTableFactory(): GuiTableFactoryInterface + { + return $this->getProvidedDependency(MerchantProductImportMerchantPortalGuiDependencyProvider::SERVICE_GUI_TABLE_FACTORY); + } + + public function getGuiTableHttpDataRequestExecutor(): GuiTableDataRequestExecutorInterface + { + return $this->getProvidedDependency(MerchantProductImportMerchantPortalGuiDependencyProvider::SERVICE_GUI_TABLE_HTTP_DATA_REQUEST_EXECUTOR); + } + + public function getMerchantUserFacade(): MerchantUserFacadeInterface + { + return $this->getProvidedDependency(MerchantProductImportMerchantPortalGuiDependencyProvider::FACADE_MERCHANT_USER); + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Plugin/AclMerchantPortal/MerchantProductImportMerchantAclRuleExpanderPlugin.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Plugin/AclMerchantPortal/MerchantProductImportMerchantAclRuleExpanderPlugin.php new file mode 100644 index 000000000..93054a64a --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Communication/Plugin/AclMerchantPortal/MerchantProductImportMerchantAclRuleExpanderPlugin.php @@ -0,0 +1,47 @@ + $ruleTransfers + * + * @return list<\Generated\Shared\Transfer\RuleTransfer> + */ + public function expand(array $ruleTransfers): array + { + $ruleTransfers[] = (new RuleTransfer()) + ->setBundle('merchant-product-import-merchant-portal-gui') + ->setController(static::RULE_VALIDATOR_WILDCARD) + ->setAction(static::RULE_VALIDATOR_WILDCARD) + ->setType(static::RULE_TYPE_ALLOW); + + return $ruleTransfers; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiConfig.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiConfig.php new file mode 100644 index 000000000..34c615832 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiConfig.php @@ -0,0 +1,111 @@ + + */ + public const MAP_STATUS_ENUM_TO_LABEL = [ + self::STATUS_PENDING => self::LABEL_STATUS_PENDING, + self::STATUS_IN_PROGRESS => self::LABEL_STATUS_IN_PROGRESS, + self::STATUS_FAILED => self::LABEL_STATUS_FAILED, + self::STATUS_PARTIALLY_FAILED => self::LABEL_STATUS_PARTIALLY_FAILED, + self::STATUS_SUCCESSFUL => self::LABEL_STATUS_SUCCESSFUL, + ]; + + /** + * @var array + */ + public const MAP_STATUS_CHIP_TO_COLOR = [ + self::LABEL_STATUS_PENDING => 'gray', + self::LABEL_STATUS_IN_PROGRESS => 'blue', + self::LABEL_STATUS_FAILED => 'red', + self::LABEL_STATUS_PARTIALLY_FAILED => 'orange', + self::LABEL_STATUS_SUCCESSFUL => 'green', + ]; + + /** + * @return array + */ + public function getStatusEnumValueToLabelMap(): array + { + return self::MAP_STATUS_ENUM_TO_LABEL; + } + + /** + * @return array + */ + public function getStatusChipColorMapping(): array + { + return self::MAP_STATUS_CHIP_TO_COLOR; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiDependencyProvider.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiDependencyProvider.php new file mode 100644 index 000000000..a46308091 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/MerchantProductImportMerchantPortalGuiDependencyProvider.php @@ -0,0 +1,94 @@ +addMerchantUserFacade($container); + $container = $this->addGuiTableFactory($container); + $container = $this->addGuiTableHttpDataRequestExecutor($container); + + return $container; + } + + public function providePersistenceLayerDependencies(Container $container): Container + { + $container = parent::providePersistenceLayerDependencies($container); + $container = $this->addImportUploadQuery($container); + + return $container; + } + + private function addGuiTableFactory(Container $container): Container + { + $container->set(static::SERVICE_GUI_TABLE_FACTORY, static function (Container $container) { + return $container->getApplicationService(static::SERVICE_GUI_TABLE_FACTORY); + }); + + return $container; + } + + private function addGuiTableHttpDataRequestExecutor(Container $container): Container + { + $container->set(static::SERVICE_GUI_TABLE_HTTP_DATA_REQUEST_EXECUTOR, static function (Container $container) { + return $container->getApplicationService(static::SERVICE_GUI_TABLE_HTTP_DATA_REQUEST_EXECUTOR); + }); + + return $container; + } + + private function addMerchantUserFacade(Container $container): Container + { + $container->set(static::FACADE_MERCHANT_USER, static function (Container $container) { + return $container->getLocator()->merchantUser()->facade(); + }); + + return $container; + } + + private function addImportUploadQuery(Container $container): Container + { + $container->set(static::QUERY_IMPORT_UPLOAD, $container->factory(static function () { + return PyzImportUploadQuery::create(); + })); + + return $container; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapper.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapper.php new file mode 100644 index 000000000..d842a1516 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapper.php @@ -0,0 +1,88 @@ +config = $config; + } + + /** + * @inheritDoc + */ + public function mapImportUploadTableDataToImportUploadCollectionTransfer( + array $importUploadTableData, + ImportUploadCollectionTransfer $importUploadCollectionTransfer, + ): ImportUploadCollectionTransfer { + foreach ($importUploadTableData as $importUpload) { + $importUploadTransfer = $this->mapImportUploadArrayToImportUploadTransfer( + $importUpload, + new ImportUploadTransfer(), + ); + + $importUploadCollectionTransfer->addImportUpload($importUploadTransfer); + } + + return $importUploadCollectionTransfer; + } + + /** + * @inheritDoc + */ + public function mapImportUploadArrayToImportUploadTransfer( + array $importUpload, + ImportUploadTransfer $importUploadTransfer, + ): ImportUploadTransfer { + $importUploadTransfer = $importUploadTransfer->fromArray($importUpload, true); + $importUploadTransfer->setStatus($this->mapStatusRawToLabel($importUpload[PyzImportUploadTableMap::COL_STATUS])); + + $userTransfer = (new UserTransfer())->fromArray($importUpload, true); + + $importUploadTransfer->setUser($userTransfer); + + return $importUploadTransfer; + } + + public function mapPropelModelPagerToPaginationTransfer( + PropelModelPager $propelModelPager, + PaginationTransfer $paginationTransfer, + ): PaginationTransfer { + return $paginationTransfer + ->setNbResults($propelModelPager->getNbResults()) + ->setPage($propelModelPager->getPage()) + ->setMaxPerPage($propelModelPager->getMaxPerPage()) + ->setFirstIndex($propelModelPager->getFirstIndex()) + ->setFirstIndex($propelModelPager->getFirstIndex()) + ->setLastIndex($propelModelPager->getLastIndex()) + ->setFirstPage($propelModelPager->getFirstPage()) + ->setLastPage($propelModelPager->getLastPage()) + ->setNextPage($propelModelPager->getNextPage()) + ->setPreviousPage($propelModelPager->getPreviousPage()); + } + + private function mapStatusRawToLabel(string $statusRaw): ?string + { + $valueSet = PyzImportUploadTableMap::getValueSet(PyzImportUploadTableMap::COL_STATUS); + $status = $valueSet[array_search($statusRaw, array_keys($valueSet))]; + $statusEnumToLabelMap = $this->config->getStatusEnumValueToLabelMap(); + + return $statusEnumToLabelMap[$status] ?? null; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapperInterface.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapperInterface.php new file mode 100644 index 000000000..af3797d06 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/Mapper/ImportUploadTableDataMapperInterface.php @@ -0,0 +1,43 @@ +> $importUploadTableData + * @param \Generated\Shared\Transfer\ImportUploadCollectionTransfer $importUploadCollectionTransfer + * + * @return \Generated\Shared\Transfer\ImportUploadCollectionTransfer + */ + public function mapImportUploadTableDataToImportUploadCollectionTransfer( + array $importUploadTableData, + ImportUploadCollectionTransfer $importUploadCollectionTransfer, + ): ImportUploadCollectionTransfer; + + /** + * @param array $importUpload + * @param \Generated\Shared\Transfer\ImportUploadTransfer $importUploadTransfer + * + * @return \Generated\Shared\Transfer\ImportUploadTransfer + */ + public function mapImportUploadArrayToImportUploadTransfer( + array $importUpload, + ImportUploadTransfer $importUploadTransfer, + ): ImportUploadTransfer; + + public function mapPropelModelPagerToPaginationTransfer( + PropelModelPager $propelModelPager, + PaginationTransfer $paginationTransfer, + ): PaginationTransfer; +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiPersistenceFactory.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiPersistenceFactory.php new file mode 100644 index 000000000..639e3f394 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiPersistenceFactory.php @@ -0,0 +1,31 @@ +getConfig()); + } + + public function getImportUploadQuery(): PyzImportUploadQuery + { + return $this->getProvidedDependency(MerchantProductImportMerchantPortalGuiDependencyProvider::QUERY_IMPORT_UPLOAD); + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepository.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepository.php new file mode 100644 index 000000000..55cc08277 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepository.php @@ -0,0 +1,121 @@ +buildBaseImportUploadQuery($productImportGuiTableCriteriaTransfer); + $pyzImportUploadQuery = $this->addImportUploadFilters($pyzImportUploadQuery, $productImportGuiTableCriteriaTransfer); + + $propelModelPager = $pyzImportUploadQuery->paginate( + $productImportGuiTableCriteriaTransfer->getPageOrFail(), + $productImportGuiTableCriteriaTransfer->getPageSizeOrFail(), + ); + + $productImportTableDataMapper = $this->getFactory()->createImportUploadTableDataMapper(); + + $importUploadCollectionTransfer = $productImportTableDataMapper + ->mapImportUploadTableDataToImportUploadCollectionTransfer( + $propelModelPager->getResults()->getData(), + new ImportUploadCollectionTransfer(), + ); + + $paginationTransfer = $productImportTableDataMapper->mapPropelModelPagerToPaginationTransfer( + $propelModelPager, + new PaginationTransfer(), + ); + + $importUploadCollectionTransfer->setPagination($paginationTransfer); + + return $importUploadCollectionTransfer; + } + + private function buildBaseImportUploadQuery( + ProductImportGuiTableCriteriaTransfer $productImportGuiTableCriteriaTransfer, + ): PyzImportUploadQuery { + $pyzImportUploadQuery = $this->getFactory()->getImportUploadQuery(); + + $pyzImportUploadQuery + ->filterByFkMerchant($productImportGuiTableCriteriaTransfer->getFkMerchant()) + ->joinUser(null, Criteria::LEFT_JOIN) + ->joinWithPyzFileUpload() + ->select([ + PyzImportUploadTableMap::COL_ID_IMPORT_UPLOAD, + PyzImportUploadTableMap::COL_STATUS, + PyzImportUploadTableMap::COL_STATUS_UPDATED_AT, + PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_UPLOADED, + PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_FAILED, + PyzImportUploadTableMap::COL_ERRORS, + PyzImportUploadTableMap::COL_CREATED_AT, + PyzImportUploadTableMap::COL_STARTED_AT, + PyzImportUploadTableMap::COL_FINISHED_AT, + SpyUserTableMap::COL_FIRST_NAME, + SpyUserTableMap::COL_LAST_NAME, + ]) + ->orderByIdImportUpload(Criteria::DESC); + + $pyzImportUploadQuery = $this->addColumnToTransferMappings($pyzImportUploadQuery); + + return $pyzImportUploadQuery; + } + + private function addColumnToTransferMappings( + PyzImportUploadQuery $pyzImportUploadQuery, + ): PyzImportUploadQuery { + $totalNumberOfProductsClause = sprintf( + '(%s + %s)', + PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_UPLOADED, + PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_FAILED, + ); + + return $pyzImportUploadQuery + ->addAsColumn(ImportUploadTransfer::ID_IMPORT_UPLOAD, PyzImportUploadTableMap::COL_ID_IMPORT_UPLOAD) + ->addAsColumn(ImportUploadTransfer::STATUS, PyzImportUploadTableMap::COL_STATUS) + ->addAsColumn(ImportUploadTransfer::STATUS_UPDATED_AT, PyzImportUploadTableMap::COL_STATUS_UPDATED_AT) + ->addAsColumn(ImportUploadTransfer::NUMBER_OF_PRODUCTS_UPLOADED, PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_UPLOADED) + ->addAsColumn(ImportUploadTransfer::NUMBER_OF_PRODUCTS_FAILED, PyzImportUploadTableMap::COL_NUMBER_OF_PRODUCTS_FAILED) + ->addAsColumn(ImportUploadTransfer::TOTAL_NUMBER_OF_PRODUCTS, $totalNumberOfProductsClause) + ->addAsColumn(ImportUploadTransfer::ORIGINAL_FILE_NAME, PyzFileUploadTableMap::COL_ORIGINAL_FILE_NAME) + ->addAsColumn(ImportUploadTransfer::ERRORS, PyzImportUploadTableMap::COL_ERRORS) + ->addAsColumn(ImportUploadTransfer::CREATED_AT, PyzImportUploadTableMap::COL_CREATED_AT) + ->addAsColumn(ImportUploadTransfer::STARTED_AT, PyzImportUploadTableMap::COL_STARTED_AT) + ->addAsColumn(ImportUploadTransfer::FINISHED_AT, PyzImportUploadTableMap::COL_FINISHED_AT) + ->addAsColumn(UserTransfer::FIRST_NAME, SpyUserTableMap::COL_FIRST_NAME) + ->addAsColumn(UserTransfer::LAST_NAME, SpyUserTableMap::COL_LAST_NAME); + } + + private function addImportUploadFilters( + PyzImportUploadQuery $pyzImportUploadQuery, + ProductImportGuiTableCriteriaTransfer $productImportGuiTableCriteriaTransfer, + ): PyzImportUploadQuery { + if ($productImportGuiTableCriteriaTransfer->getFilterStatus() !== null) { + $pyzImportUploadQuery->filterByStatus($productImportGuiTableCriteriaTransfer->getFilterStatus()); + } + + return $pyzImportUploadQuery; + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepositoryInterface.php b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepositoryInterface.php new file mode 100644 index 000000000..2f2b0a141 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Persistence/MerchantProductImportMerchantPortalGuiRepositoryInterface.php @@ -0,0 +1,18 @@ + diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.less b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.less new file mode 100644 index 000000000..d858c2205 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.less @@ -0,0 +1,30 @@ +@import '~@spryker/styles/src/lib/themes/default/variables/index.less'; + +.mp-import-upload-table { + &--inner { + background: @gray-lighter; + padding: var(--spy-order-import-upload-table-padding, 20px); + display: block; + } + + &--order-items { + .spy-table-search-feature, + .ant-table-features--top .spy-table-features-renderer__content { + width: 100%; + } + + .spy-table-filters-feature__item { + flex: 1; + } + } + + &--file-upload { + .spy-table-column-list:has(.spy-table-column-text) { + flex-wrap: nowrap; + + .spy-table-column-text { + white-space: normal; + } + } + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.ts b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.ts new file mode 100644 index 000000000..6f9397076 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.component.ts @@ -0,0 +1,40 @@ +import { + booleanAttribute, + ChangeDetectionStrategy, + Component, + HostBinding, + Input, + OnInit, + ViewEncapsulation, +} from '@angular/core'; +import { TableConfig } from '@spryker/table'; +import { TableRowActionBase } from '@spryker/table.feature.row-actions'; +import { ToJson } from '@spryker/utils'; + +@Component({ + selector: 'mp-import-upload-table', + templateUrl: './import-upload-table.component.html', + styleUrls: ['./import-upload-table.component.less'], + changeDetection: ChangeDetectionStrategy.OnPush, + encapsulation: ViewEncapsulation.None, +}) +export class ImportUploadTableComponent implements OnInit { + @Input() @ToJson() config: TableConfig; + @Input() @ToJson() action: TableRowActionBase; + @Input() tableId?: string; + + @HostBinding('class.mp-import-upload-table') mainClass = true; + @HostBinding('class.mp-import-upload-table--inner') + @Input({ transform: booleanAttribute }) + inner = true; + + protected _config: TableConfig; + + ngOnInit(): void { + if (this.config?.rowActions && this.action) { + this.config.rowActions.click = this.action.id; + this.config.rowActions.actions.push(this.action); + this.config = { ...this.config }; + } + } +} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.module.ts b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.module.ts new file mode 100644 index 000000000..6217ba4b5 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/app/import-upload-table/import-upload-table.module.ts @@ -0,0 +1,12 @@ +import { CommonModule } from '@angular/common'; +import { NgModule } from '@angular/core'; +import { TableModule } from '@spryker/table'; + +import { ImportUploadTableComponent } from './import-upload-table.component'; + +@NgModule({ + imports: [CommonModule, TableModule], + declarations: [ImportUploadTableComponent], + exports: [ImportUploadTableComponent], +}) +export class ImportUploadTableModule {} diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/entry.ts b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/entry.ts new file mode 100644 index 000000000..6e4c69b30 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Components/entry.ts @@ -0,0 +1,5 @@ +// spy/merchant-portal:single-entry-marker +import { registerNgModule } from '@mp/zed-ui'; +import { ComponentsModule } from './app/components.module'; + +registerNgModule(ComponentsModule); diff --git a/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Imports/index.twig b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Imports/index.twig new file mode 100644 index 000000000..6b733c988 --- /dev/null +++ b/src/Pyz/Zed/MerchantProductImportMerchantPortalGui/Presentation/Imports/index.twig @@ -0,0 +1,19 @@ +{% extends '@ZedUi/Layout/merchant-layout-main.twig' %} +{% import _self as view %} + +{% block headTitle %} + {{ 'Import History' | trans }} +{% endblock %} + +{% block content %} + +

{{ 'Import History' | trans }}

+ + + +
+{% endblock %} diff --git a/src/Pyz/Zed/ProductMerchantPortalGui/Presentation/Products/index.twig b/src/Pyz/Zed/ProductMerchantPortalGui/Presentation/Products/index.twig index a6663b566..6b21c09c3 100644 --- a/src/Pyz/Zed/ProductMerchantPortalGui/Presentation/Products/index.twig +++ b/src/Pyz/Zed/ProductMerchantPortalGui/Presentation/Products/index.twig @@ -42,9 +42,6 @@ errorType: 'Only %types% file formats are allowed' | trans({ '%types%': 'text/csv' }), - noCDNPreview: true, - import: '/product-merchant-portal-gui/products/get-import-url', - hook: '/product-merchant-portal-gui/products/save-import-url', download: '/import_template.csv', fileData: mediaData, }