diff --git a/.github/actions/build-plugin/action.yml b/.github/actions/build-plugin/action.yml index a7266e16e..904df0206 100644 --- a/.github/actions/build-plugin/action.yml +++ b/.github/actions/build-plugin/action.yml @@ -8,7 +8,7 @@ runs: - name: Start Docker shell: bash run: | - docker run --rm --name shop --env NODE_VERSION=18 --env PHP_VERSION=8.1 -d dockware/dev:6.5.8.7 + docker run --rm --name shop --env NODE_VERSION=22 --env PHP_VERSION=8.3 -d dockware/shopware:6.7.3.0 sleep 20 docker logs shop @@ -23,19 +23,6 @@ runs: docker cp $(pwd)/. shop:/var/www/html/custom/plugins/MolliePayments docker exec shop bash -c 'sudo chown www-data:www-data /var/www/html/custom/plugins -R' - # -------------------------------------------------------------------------------------------------------------------------------------- - - name: Fix apt-get repo - shell: bash - run: | - docker exec -u root shop bash -c 'apt-get update --allow-releaseinfo-change' - - - name: Install Plugin - shell: bash - run: | - docker exec shop bash -c 'cd /var/www/html/custom/plugins/MolliePayments && make prod' - docker exec shop bash -c 'cd /var/www/html && php bin/console plugin:refresh' - docker exec shop bash -c 'cd /var/www/html && php bin/console plugin:install MolliePayments --activate' - docker exec shop bash -c 'cd /var/www/html && php bin/console cache:clear' - name: Build Plugin shell: bash diff --git a/.github/actions/run-e2e/action.yml b/.github/actions/run-e2e/action.yml index 7e6cafba5..0903ff8e0 100644 --- a/.github/actions/run-e2e/action.yml +++ b/.github/actions/run-e2e/action.yml @@ -1,242 +1,228 @@ -name: 'Run E2E Tests' -description: "Runs installation and Cypress tests" - - -branding: - icon: 'award' - color: 'green' - - -inputs: - # ------------------------------------------------------------------------------------ - # ENVIRONMENT SETTINGS - SHOPWARE: - description: "The Shopware version that is used to run the Cypress tests." - required: true - PHP: - description: "The PHP Version that is used for the Shopware container." - required: true - IMAGE: - description: "dockware image container." - required: true - MOLLIE_APIKEY_TEST: - description: "The Mollie Test API key. Required for the installation." - default: '' - required: true - # ------------------------------------------------------------------------------------ - # CYPRESS SETTINGS - RUN_CYPRESS: - description: "If disabled, only the plugin installation will be tested" - default: 'true' - required: false - FILTERS: - description: "An optional filter for the Cypress tests. Leave empty to run all tests" - default: '' - required: false - REMOVE_DEPRECATED_TESTS: - description: "If enabled, tests that are marked as deprecated will be removed" - default: 'false' - required: false - CYPRESS_RESULTS_SUFFIX: - description: "Additional suffix for the zip file with all Cypress results." - default: '' - required: false - # ------------------------------------------------------------------------------------ - # TESTRAIL SETTINGS - TESTRAIL: - description: "If enabled, all results will be sent to TestRail." - default: 'false' - required: false - TESTRAIL_DOMAIN: - description: "The domain for the TestRail endpoint" - default: '' - required: false - TESTRAIL_USERNAME: - description: "The username for the TestRail endpoint" - default: '' - required: false - TESTRAIL_PASSWORD: - description: "The password for the TestRail endpoint" - default: '' - required: false - # ------------------------------------------------------------------------------------ - # ------------------------------------------------------------------------------------ - # PRIVATE VARIABLES - _SHOP_DOMAIN: - description: 'This domain will be used in Cypress as BASE_URL' - default: 'cypress.github.shop' - required: false - _STORE_API_KEY: - description: 'This is the Store API Key that is used when launching our Shopware. Its not confidential, its just for here' - default: 'SWSCOVFSNKLBYUTKS1VSOEDGUQ' - required: false - _ZIP_FILE: - description: 'This is the defined filename of the ZIP file that we use for the installation of the plugin' - default: '~/.build/MolliePayments-e2e.zip' - required: false - - - -runs: - using: "composite" - steps: - - - name: Download Docker - shell: bash - run: docker pull -q ${{ inputs.IMAGE }}:${{ inputs.SHOPWARE }} - - - name: Start Docker - shell: bash - run: | - docker run -p 443:443 --name shop --env PHP_VERSION=${{ inputs.PHP }} --env SW_API_ACCESS_KEY=${{ inputs._STORE_API_KEY }} -d ${{ inputs.IMAGE }}:${{ inputs.SHOPWARE }} - sleep 15 - # now change the domain of our shop, mollie doesn't work with localhost - sudo echo "127.0.0.1 ${{ inputs._SHOP_DOMAIN }}" | sudo tee -a /etc/hosts - docker exec shop bash -c "mysql -h 127.0.0.1 -u root -proot shopware -e \"UPDATE sales_channel_domain SET url='https://${{ inputs._SHOP_DOMAIN }}' WHERE url NOT LIKE 'default.%';\"" - - - name: Update Shopware Config - shell: bash - run: | - docker exec shop bash -c 'sed -i "s/APP_ENV=dev/APP_ENV=prod/g" /var/www/html/.env' || true; - # we have to enable cypress mode in our shop, this helps us to create subscriptions without webhooks - docker exec shop bash -c "echo "MOLLIE_CYPRESS_MODE=1" >> /var/www/html/.env" || true; - docker exec shop bash -c "echo "APP_URL=https://${{ inputs._SHOP_DOMAIN }}" >> /var/www/html/.env" || true; - docker exec shop bash -c "echo "MOLLIE_PAYPAL_EXPRESS_BETA=1" >> /var/www/html/.env" || true; - docker exec shop bash -c "echo "TEST_TOKEN='none'" >> /var/www/html/.env" || true; - docker exec shop bash -c "echo "MAILER_DSN=null://null" >> /var/www/html/.env" || true; - - # -------------------------------------------------------------------------------------------------------------------------------------- - - - name: Upload ZIP File to Docker - shell: bash - run: | - docker cp ${{ inputs._ZIP_FILE }} shop:/var/www/html/custom/plugins/MolliePayments.zip - docker exec shop bash -c 'cd /var/www/html/custom/plugins && unzip -qq -o MolliePayments.zip' - - - name: Configure Shopware - shell: bash - run: | - docker exec shop bash -c 'php bin/console system:config:set core.loginRegistration.showAccountTypeSelection true' - - - name: Legacy fixes - if: ${{ startsWith(inputs.SHOPWARE,'6.4') }} - shell: bash - run: | - # latest composer has an issue with php 7.4 where the lock file is not read fully. you see error that shopware/core is not found - docker exec -u root shop bash -c 'wget https://getcomposer.org/download/2.2.9/composer.phar && chmod a+x composer.phar && mv composer.phar /usr/local/bin/composer' - docker exec shop bash -c 'mkdir -p /var/www/html/var/test/jwt && cp /var/www/html/config/jwt/*.pem /var/www/html/var/test/jwt && chmod 0660 /var/www/html/var/test/jwt/*.pem' - - - - name: Prepare Shop for e2e tests - shell: bash - run: | - docker exec shop bash -c 'composer require --dev phpunit/phpunit:9.* -W' # we need to install phpunit 9 with all dependencies, because of minimum php version 8.0 - docker exec shop bash -c 'composer config --no-plugins allow-plugins.wikimedia/composer-merge-plugin true' - docker exec shop bash -c 'composer config --no-plugins allow-plugins.php-http/discovery true' - docker exec shop bash -c 'composer config --json extra.merge-plugin "{\"include\":[\"custom/plugins/MolliePayments/composer.json\"], \"ignore-duplicates\":true}"' - docker exec shop bash -c 'composer require wikimedia/composer-merge-plugin:*' - - - name: Install Plugin - shell: bash - run: | - docker exec shop bash -c 'php bin/console plugin:refresh' - docker exec shop bash -c 'php bin/console plugin:install MolliePayments --activate' - docker exec shop bash -c 'php bin/console cache:clear' - - - name: Configure Plugin - if: ${{ inputs.MOLLIE_APIKEY_TEST != '' }} - shell: bash - run: | - docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.testMode true' - docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.debugMode true' - docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.liveApiKey ${{ inputs.MOLLIE_APIKEY_TEST }}' - docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.testApiKey ${{ inputs.MOLLIE_APIKEY_TEST }}' - docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.formatOrderNumber github_{ordernumber}' - docker exec shop bash -c 'php bin/console system:config:set core.mailerSettings.disableDelivery true' - docker exec shop bash -c 'php bin/console system:config:set core.mailerSettings.emailAgent ""' - docker exec shop bash -c 'php bin/console cache:clear' - - - name: Install Fixtures - shell: bash - run: | - docker exec shop bash -c 'php bin/console mollie:fixtures:install --force' - - # -------------------------------------------------------------------------------------------------------------------------------------- - - - name: DAL Validate - shell: bash - run: | - docker exec shop bash -c 'php bin/console dal:validate' - - # -------------------------------------------------------------------------------------------------------------------------------------- - - name: Integration analyzer - shell: bash - run: | - docker exec shop bash -c 'php vendor/bin/phpstan analyse -c ./custom/plugins/MolliePayments/config/.phpstan.neon' - - - name: Integration tests - shell: bash - run: | - docker exec shop bash -c 'cd custom/plugins/MolliePayments && make phpintegration -B' - - - name: Functional tests - shell: bash - run: | - docker exec shop bash -c 'cd custom/plugins/MolliePayments && make behat -B' - - - name: Install Cypress - if: ${{ inputs.RUN_CYPRESS == 'true' }} - shell: bash - run: cd tests/Cypress && make install -B - - - name: Remove deprecated Cypress Tests - if: ${{ inputs.RUN_CYPRESS == 'true' && inputs.REMOVE_DEPRECATED_TESTS == 'true' }} - shell: bash - run: | - # SEPA Direct Debit has been completely removed from Mollie. We have to remove that entry from the tests in old Cypress versions - sed -i "/key: 'directdebit'/g" $(pwd)/tests/Cypress/cypress/e2e/storefront/checkout/checkout-success.cy.js || true - sed -i "/key: 'directdebit'/g" $(pwd)/tests/Cypress/cypress/integration/storefront/checkout/checkout-success.spec.js || true - - - name: Start Cypress - if: ${{ inputs.RUN_CYPRESS == 'true' && inputs.TESTRAIL == 'false' }} - shell: bash - run: | - cd tests/Cypress && \ - make run shopware=${{ inputs.SHOPWARE }} storeApiKey=${{ inputs._STORE_API_KEY }} url=https://${{ inputs._SHOP_DOMAIN }} filters="${{ inputs.FILTERS }}" - - - name: Start Cypress with TestRail - if: ${{ inputs.RUN_CYPRESS == 'true' && inputs.TESTRAIL == 'true' }} - shell: bash - run: | - cd tests/Cypress && \ - CYPRESS_TESTRAIL_DOMAIN=${{ inputs.TESTRAIL_DOMAIN }} \ - CYPRESS_TESTRAIL_USERNAME=${{ inputs.TESTRAIL_USERNAME }} \ - CYPRESS_TESTRAIL_PASSWORD=${{ inputs.TESTRAIL_PASSWORD }} \ - CYPRESS_TESTRAIL_PROJECT_ID=7 \ - CYPRESS_TESTRAIL_MILESTONE_ID=15 \ - CYPRESS_TESTRAIL_RUN_NAME="Github Workflow __datetime__, ${{ github.event.head_commit.message }}, Shopware ${{ inputs.SHOPWARE }}" \ - CYPRESS_TESTRAIL_RUN_CLOSE=true \ - make run shopware=${{ inputs.SHOPWARE }} storeApiKey=${{ inputs._STORE_API_KEY }} url=https://${{ inputs._SHOP_DOMAIN }} - - # -------------------------------------------------------------------------------------------------------------------------------------- - - - name: Download Logs - if: ${{ inputs.RUN_CYPRESS == 'true' && always() }} - shell: bash - run: | - mkdir -p $(pwd)/tests/Cypress/cypress/logs/shopware - mkdir -p $(pwd)/tests/Cypress/cypress/logs/apache - docker cp shop:/var/www/html/var/log/. $(pwd)/tests/Cypress/cypress/logs/shopware - docker cp shop:/var/log/php/. $(pwd)/tests/Cypress/cypress/logs/apache - - - name: Store Cypress Results - if: ${{ inputs.RUN_CYPRESS == 'true' && always() }} - uses: actions/upload-artifact@v4 - with: - name: cypress_results_v${{ inputs.SHOPWARE }}${{ inputs.CYPRESS_RESULTS_SUFFIX }} - retention-days: 1 - path: | - tests/Cypress/cypress/results - tests/Cypress/cypress/logs - tests/Cypress/cypress/videos +name: 'Run E2E Tests' +description: "Runs installation and Cypress tests" + + +branding: + icon: 'award' + color: 'green' + + +inputs: + # ------------------------------------------------------------------------------------ + # ENVIRONMENT SETTINGS + SHOPWARE: + description: "The Shopware version that is used to run the Cypress tests." + required: true + PHP: + description: "The PHP Version that is used for the Shopware container." + required: true + IMAGE: + description: "dockware image container." + required: true + MOLLIE_APIKEY_TEST: + description: "The Mollie Test API key. Required for the installation." + default: '' + required: true + # ------------------------------------------------------------------------------------ + # CYPRESS SETTINGS + RUN_CYPRESS: + description: "If disabled, only the plugin installation will be tested" + default: 'true' + required: false + FILTERS: + description: "An optional filter for the Cypress tests. Leave empty to run all tests" + default: '' + required: false + REMOVE_DEPRECATED_TESTS: + description: "If enabled, tests that are marked as deprecated will be removed" + default: 'false' + required: false + CYPRESS_RESULTS_SUFFIX: + description: "Additional suffix for the zip file with all Cypress results." + default: '' + required: false + # ------------------------------------------------------------------------------------ + # TESTRAIL SETTINGS + TESTRAIL: + description: "If enabled, all results will be sent to TestRail." + default: 'false' + required: false + TESTRAIL_DOMAIN: + description: "The domain for the TestRail endpoint" + default: '' + required: false + TESTRAIL_USERNAME: + description: "The username for the TestRail endpoint" + default: '' + required: false + TESTRAIL_PASSWORD: + description: "The password for the TestRail endpoint" + default: '' + required: false + # ------------------------------------------------------------------------------------ + # ------------------------------------------------------------------------------------ + # PRIVATE VARIABLES + _SHOP_DOMAIN: + description: 'This domain will be used in Cypress as BASE_URL' + default: 'cypress.github.shop' + required: false + _STORE_API_KEY: + description: 'This is the Store API Key that is used when launching our Shopware. Its not confidential, its just for here' + default: 'SWSCOVFSNKLBYUTKS1VSOEDGUQ' + required: false + _ZIP_FILE: + description: 'This is the defined filename of the ZIP file that we use for the installation of the plugin' + default: '~/.build/MolliePayments-e2e.zip' + required: false + + + +runs: + using: "composite" + steps: + + - name: Download Docker + shell: bash + run: docker pull -q ${{ inputs.IMAGE }}:${{ inputs.SHOPWARE }} + + - name: Start Docker + shell: bash + run: | + docker run -p 443:443 --name shop --env PHP_VERSION=${{ inputs.PHP }} --env SW_API_ACCESS_KEY=${{ inputs._STORE_API_KEY }} -d ${{ inputs.IMAGE }}:${{ inputs.SHOPWARE }} + sleep 15 + # now change the domain of our shop, mollie doesn't work with localhost + sudo echo "127.0.0.1 ${{ inputs._SHOP_DOMAIN }}" | sudo tee -a /etc/hosts + docker exec shop bash -c "mysql -h 127.0.0.1 -u root -proot shopware -e \"UPDATE sales_channel_domain SET url='https://${{ inputs._SHOP_DOMAIN }}' WHERE url NOT LIKE 'default.%';\"" + + - name: Update Shopware Config + shell: bash + run: | + docker exec shop bash -c 'sed -i "s/APP_ENV=dev/APP_ENV=prod/g" /var/www/html/.env' || true; + # we have to enable cypress mode in our shop, this helps us to create subscriptions without webhooks + docker exec shop bash -c "echo "MOLLIE_CYPRESS_MODE=1" >> /var/www/html/.env" || true; + docker exec shop bash -c "echo "APP_URL=https://${{ inputs._SHOP_DOMAIN }}" >> /var/www/html/.env" || true; + docker exec shop bash -c "echo "MOLLIE_PAYPAL_EXPRESS_BETA=1" >> /var/www/html/.env" || true; + docker exec shop bash -c "echo "TEST_TOKEN='none'" >> /var/www/html/.env" || true; + docker exec shop bash -c "echo "MAILER_DSN=null://null" >> /var/www/html/.env" || true; + + # -------------------------------------------------------------------------------------------------------------------------------------- + + - name: Upload ZIP File to Docker + shell: bash + run: | + docker cp ${{ inputs._ZIP_FILE }} shop:/var/www/html/custom/plugins/MolliePayments.zip + docker exec shop bash -c 'cd /var/www/html/custom/plugins && unzip -qq -o MolliePayments.zip' + + - name: Configure Shopware + shell: bash + run: | + docker exec shop bash -c 'php bin/console system:config:set core.loginRegistration.showAccountTypeSelection true' + + + - name: Prepare Shop for e2e tests + shell: bash + run: | + docker exec shop bash -c 'composer require --dev phpunit/phpunit:11.* -W' + docker exec shop bash -c 'composer config --no-plugins allow-plugins.wikimedia/composer-merge-plugin true' + docker exec shop bash -c 'composer config --no-plugins allow-plugins.php-http/discovery true' + docker exec shop bash -c 'composer config --json extra.merge-plugin "{\"include\":[\"custom/plugins/MolliePayments/composer.json\"], \"ignore-duplicates\":true}"' + docker exec shop bash -c 'composer require wikimedia/composer-merge-plugin:*' + + - name: Install Plugin + shell: bash + run: | + docker exec shop bash -c 'php bin/console plugin:refresh' + docker exec shop bash -c 'php bin/console plugin:install MolliePayments --activate' + docker exec shop bash -c 'php bin/console cache:clear' + + - name: Configure Plugin + if: ${{ inputs.MOLLIE_APIKEY_TEST != '' }} + shell: bash + run: | + docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.testMode true' + docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.debugMode true' + docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.liveApiKey ${{ inputs.MOLLIE_APIKEY_TEST }}' + docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.testApiKey ${{ inputs.MOLLIE_APIKEY_TEST }}' + docker exec shop bash -c 'php bin/console system:config:set MolliePayments.config.formatOrderNumber github_{ordernumber}' + docker exec shop bash -c 'php bin/console system:config:set core.mailerSettings.disableDelivery true' + docker exec shop bash -c 'php bin/console system:config:set core.mailerSettings.emailAgent ""' + # clean settings inheritance + docker exec shop bash -c "mysql -h 127.0.0.1 -u root -proot shopware -e \"DELETE FROM system_config WHERE sales_channel_id IS NOT NULL;\"" + docker exec shop bash -c 'php bin/console cache:clear' + + - name: Install Fixtures + shell: bash + run: | + docker exec shop bash -c 'php bin/console mollie:fixtures:load' + + # -------------------------------------------------------------------------------------------------------------------------------------- + + - name: DAL Validate + shell: bash + run: | + docker exec shop bash -c 'php bin/console dal:validate' + + # -------------------------------------------------------------------------------------------------------------------------------------- + - name: Integration analyzer + shell: bash + run: | + docker exec shop bash -c 'cd custom/plugins/MolliePayments && make stan -B' + + - name: Integration tests + shell: bash + run: | + docker exec shop bash -c 'cd custom/plugins/MolliePayments && make phpintegration -B' + + - name: Functional tests + shell: bash + run: | + docker exec shop bash -c 'cd custom/plugins/MolliePayments && make behat -B' + + - name: Install Cypress + if: ${{ inputs.RUN_CYPRESS == 'true' }} + shell: bash + run: cd tests/Cypress && make install -B + + - name: Start Cypress + if: ${{ inputs.RUN_CYPRESS == 'true' && inputs.TESTRAIL == 'false' }} + shell: bash + run: | + cd tests/Cypress && \ + make run shopware=${{ inputs.SHOPWARE }} storeApiKey=${{ inputs._STORE_API_KEY }} url=https://${{ inputs._SHOP_DOMAIN }} filters="${{ inputs.FILTERS }}" + + - name: Start Cypress with TestRail + if: ${{ inputs.RUN_CYPRESS == 'true' && inputs.TESTRAIL == 'true' }} + shell: bash + run: | + cd tests/Cypress && \ + CYPRESS_TESTRAIL_DOMAIN=${{ inputs.TESTRAIL_DOMAIN }} \ + CYPRESS_TESTRAIL_USERNAME=${{ inputs.TESTRAIL_USERNAME }} \ + CYPRESS_TESTRAIL_PASSWORD=${{ inputs.TESTRAIL_PASSWORD }} \ + CYPRESS_TESTRAIL_PROJECT_ID=7 \ + CYPRESS_TESTRAIL_MILESTONE_ID=15 \ + CYPRESS_TESTRAIL_RUN_NAME="Github Workflow __datetime__, ${{ github.event.head_commit.message }}, Shopware ${{ inputs.SHOPWARE }}" \ + CYPRESS_TESTRAIL_RUN_CLOSE=true \ + make run shopware=${{ inputs.SHOPWARE }} storeApiKey=${{ inputs._STORE_API_KEY }} url=https://${{ inputs._SHOP_DOMAIN }} + + # -------------------------------------------------------------------------------------------------------------------------------------- + + - name: Download Logs + if: ${{ inputs.RUN_CYPRESS == 'true' && always() }} + shell: bash + run: | + mkdir -p $(pwd)/tests/Cypress/cypress/logs/shopware + mkdir -p $(pwd)/tests/Cypress/cypress/logs/apache + docker cp shop:/var/www/html/var/log/. $(pwd)/tests/Cypress/cypress/logs/shopware + docker cp shop:/var/log/php/. $(pwd)/tests/Cypress/cypress/logs/apache + + - name: Store Cypress Results + if: ${{ inputs.RUN_CYPRESS == 'true' && always() }} + uses: actions/upload-artifact@v4 + with: + name: cypress_results_v${{ inputs.SHOPWARE }}${{ inputs.CYPRESS_RESULTS_SUFFIX }} + retention-days: 1 + path: | + tests/Cypress/cypress/results + tests/Cypress/cypress/logs + tests/Cypress/cypress/videos tests/Cypress/cypress/screenshots \ No newline at end of file diff --git a/.github/workflows/nightly_pipe.yml b/.github/workflows/nightly_pipe.yml index 54acccc04..ad8904033 100644 --- a/.github/workflows/nightly_pipe.yml +++ b/.github/workflows/nightly_pipe.yml @@ -45,52 +45,24 @@ jobs: fail-fast: false matrix: include: - - shopware: '6.7.7.1' + - shopware: '6.7.4.0' php: '8.3' image: 'dockware/shopware' - - shopware: '6.7.6.2' - php: '8.3' - image: 'dockware/shopware' - - shopware: '6.7.5.1' - php: '8.3' - image: 'dockware/shopware' - - shopware: '6.6.10.5' - php: '8.3' - image: 'dockware/play' - - shopware: '6.6.9.0' - php: '8.2' - image: 'dockware/play' - - shopware: '6.6.6.0' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.8.12' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.6.1' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.5.2' + - shopware: '6.7.3.1' php: '8.2' - image: 'dockware/play' - - shopware: '6.5.4.1' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.3.3' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.3.0' + image: 'dockware/shopware' + - shopware: '6.7.2.2' php: '8.2' - image: 'dockware/play' - - shopware: '6.5.2.1' + image: 'dockware/shopware' + - shopware: '6.7.1.2' php: '8.2' - image: 'dockware/play' - - shopware: '6.5.1.1' + image: 'dockware/shopware' + - shopware: '6.7.0.1' php: '8.2' - image: 'dockware/play' - - shopware: '6.5.0.0' + image: 'dockware/shopware' + - shopware: '6.6.10.0' php: '8.2' image: 'dockware/play' - steps: - name: Clone Code diff --git a/.github/workflows/pr_pipe.yml b/.github/workflows/pr_pipe.yml index 3647d0d8f..3f19ad138 100644 --- a/.github/workflows/pr_pipe.yml +++ b/.github/workflows/pr_pipe.yml @@ -14,7 +14,7 @@ jobs: name: Review Pipeline uses: ./.github/workflows/step_review.yml with: - PHP_VERSION: 8.0 + PHP_VERSION: 8.2 # ------------------------------------------------------------------------------------------------------------------------ @@ -47,25 +47,12 @@ jobs: fail-fast: false matrix: include: - - shopware: '6.7.7.1' + - shopware: '6.7.4.0' php: '8.3' image: 'dockware/shopware' - - shopware: '6.7.6.2' + - shopware: '6.6.10.9' php: '8.3' image: 'dockware/shopware' - - shopware: '6.7.5.1' - php: '8.3' - image: 'dockware/shopware' - - shopware: '6.6.10.5' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.8.12' - php: '8.2' - image: 'dockware/play' - - shopware: '6.5.5.2' - php: '8.2' - image: 'dockware/play' - steps: - name: Clone Code diff --git a/.gitignore b/.gitignore index 235d4ea42..661d46a96 100644 --- a/.gitignore +++ b/.gitignore @@ -8,19 +8,14 @@ src/Resources/app/administration/node_modules src/Resources/app/storefront/dist/storefront src/Resources/app/storefront/node_modules - -src/Resources/public/administration/css/ -src/Resources/public/administration/js/ -src/Resources/public/administration/assets/ +*.js.LICENSE.txt +config-* /tests/Cypress/Cypress.env.json /tests/Cypress/cypress/results /src/Resources/app/administration/.stryker-tmp /.phpunuhi/ -/src/Resources/public/static/css -/src/Resources/public/static/js -/src/Resources/public/js -/src/Resources/public/mollie-payments.js /node_modules/ /src/Resources/public/administration/.vite composer.lock -package-lock.json \ No newline at end of file +package-lock.json +.tmp diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index 1658bfe6a..3489c8026 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,47 +1,26 @@ -# unreleased -- Behoben: Webhooks für POS-Terminal-Zahlungen funktionieren nun korrekt. -- Behoben: Beim Express Checkout werden nun nur die ausgewählten Radio-Button-Werte übermittelt, wenn das CustomProducts-Plugin verwendet wird. Zuvor wurden alle Optionen gesendet statt nur die gewählten. - -# 4.23.0 -- Neu: Vipps als Zahlungsmethode hinzugefügt. -- Neu: MobilePay als Zahlungsmethode hinzugefügt. -- Behoben: Änderungen an den Order-Daten durch Listener des `MollieOrderBuildEvent` werden nun korrekt für den Mollie-API-Request verwendet. Bisher wurde das Event zwar ausgelöst, die modifizierten Order-Daten jedoch ignoriert. -- Apple Pay Direct: Telefonnummer wird nun auch bei Gast-Checkout korrekt übernommen, wenn sie nachträglich geändert wird. -- Problem behoben mit verschiedenen Set-Plugins -- Behoben: Page Extensions werden im Checkout nun korrekt erweitert statt überschrieben, um Kompatibilität mit anderen Plugins zu gewährleisten. -- Neu: Beim Erstatten aller Line Items im Shopware Return Manager werden Versandkosten nun automatisch mit berücksichtigt. Manuell angegebene Versandkosten werden ebenfalls übernommen. -- Behoben: Der Apple Pay Direct Button wird im Shopping-Cart-Offcanvas korrekt angezeigt, wenn die Versandart geändert wird. -- Behoben: Custom Fields von anderen Herstellern werden beim Aktualisieren von OrderLineItems nicht mehr überschrieben. -- Neu: Bulgarische Übersetzungen hinzugefügt. -- Kroatische Übersetzungen aktualisiert. -- Litauische Übersetzungen aktualisiert. -- Routen mit Kundennummern in der URL wurden überarbeitet. Es wird nun der aktuell eingeloggte Kunde verwendet, anstatt der Kundenummer aus der URL - -# 4.22.1 -- Die Verarbeitung von Positionen mit negativen Beträgen wurde behoben. - -# 4.22.0 -- Behebung eines falschen Warenkorbpreises bei Apple Pay Direct in Kombination mit Netto-Anzeigepreise bei Kundengruppen. Hier wurden keine Steuern miteinberechnet. -- Behebung eines Problems, bei dem in manchen zufälligen Fällen die Kreditkartenfelder nicht funktionieren. (mollie.js defer-sync Laden wurde entfernt). -- Wenn ein Kunde die Zahlungsart eines Abonnements ändert, werden alle älteren, noch stornierbaren Zahlungen automatisch abgebrochen. -- Die Kompatibilität mit dem Plugin „Zusatzoptionen/Garantien“ wurde implementiert. -- Kunden mit bestehendem Abonnement haben nun eine Übersichtsseite in der Administration zum Kündigen ihrer Abonnements. -- Die Darstellung der Zahlarten in älteren Shopware-Versionen wurde korrigiert. -- Der „Test API Keys“-Button in den Plugin-Einstellungen wurde für Shopware 6.7 korrigiert. -- Die Zahlungsstatus-Aktion wurde versionsabhängig angepasst, sodass in älteren Shopware-Versionen wieder die korrekte Action verwendet wird. -- iDEAL wurde zu iDEAL | Wero umbenannt. - -# 4.21.0 -- Versandkosten werden bei Erstattung über Shopware Return Management berücksichtig +# 5.0.0 +- Zahlungsarten verwenden jetzt die Mollie Payments API. +- Die minimale PHP-Version ist 8.2. +- Die minimale Shopware-Version ist 6.6.10.x. +- Order Events und Flows werden nicht mehr ausgelöst. +- Neue Payment Flows wurden hinzugefügt. +- Das Event ModifyCreatePaymentPayloadEvent wurde eingeführt, um die Anfrage vor der Erstellung einer Mollie-Zahlung anzupassen. +- Alle zahlungsbezogenen Logs enthalten nun die Shopware-orderNumber. +- Die URL zum Speichern des Kreditkarten-Tokens wird nicht mehr verwendet; übergebe stattdessen creditCardToken in der Checkout-Anfrage. +- Die URL zum Speichern der Mandats-ID ist veraltet; übergebe mandateId als Body-Parameter in der Checkout-Anfrage. +- Die URL zum Speichern der POS-Terminal-ID ist veraltet; übergebe terminalId als Body-Parameter in der Checkout-Anfrage. +- Ein Produkt kann nun mehreren Gutschein-Kategorien zugeordnet werden. +- Hinzugefügt: Order-bezogene Logeinträge werden nun in einem eigenen mollie-Verzeichnis abgelegt. Die Logdateien tragen ein Namensschema im Format order-, z. B. order-12345. +- Hinzugefügt: Order-bezogene Logeinträge werden nun automatisch gelöscht, sobald sich der Zahlungsstatus auf "paid" ändert. Zudem werden alle übrigen Einträge entfernt, sobald sie die in den Einstellungen definierte Aufbewahrungsfrist überschreiten. +- Im Mollie Failure Mode werden auf der Mollie-Seite ausschließlich Zahlungsarten angezeigt, die auch im Warenkorb verfügbar sind. +- Das Order-State-Mapping wurde optimiert. Beim Statuswechsel wird nun ein präziser Übergangspfad ermittelt; kann der Wechsel nicht durchgeführt werden, werden detaillierte Log-Einträge erstellt. +- Payconiq ist eingestellt und wird nach dem Update nicht aktiviert. Bitte deaktivieren Sie die Zahlungsmethode und entfernen Sie die Zuordnung zum Verkaufskanal. +- Das Event PaymentCreatedEvent wurde eingeführt, damit ist es möglich vor der Weiterleitung zum Zahlungsanbieter noch eigene Logik einzubauen +- Neues Event ModifyCreateSubscriptionPayloadEvent hinzugefügt. Damit können Entwickler den Payload für die Mollie Subscription API vor dem Erstellen einer Subscription anpassen und erweitern. + +## [Unreleased] - Behoben: Fehler bei Warenkörben mit unterschiedlichen Steuersätzen und Promotion mit proportionaler Steuerberechnung. - Aktualisiert: Dokumentation zum Endpoint für das Validieren und Erstellen einer Apple-Pay-Zahlungssession korrigiert. -- Behoben: Versandarten wurden in Apple Pay Express angezeigt, obwohl der Versand für diese Länder in der Administration deaktiviert war. -- Aktualisiert: Die Abhängigkeit zum Basecom Fixture Plugin wurde entfernt und durch unser eigenes Fixture Plugin ersetzt. -- Behoben: MolliePaymentMethodAvailabilityRemover berücksichtigt nun auch Warenkörbe mit dem Preis 0, um zu vermeiden, dass alle Zahlungsmethoden entfernt werden. -- Kompatibilität mit Click & Collect Plugin -- Behoben: Beschreibungen von Zahlungsarten wurden beim Checkout angezeigt, obwohl diese nicht ausgewählt waren. -- Die Profilnavigation wurde erweitert und umfasst nun die Verwaltung gespeicherter Kreditkartendaten (nur sichtbar, wenn Kreditkartendaten vorhanden sind). -- Tracking-Parameter sind jetzt optional für alle Versand-API-Routen. # 4.20.1 - Problem behoben. In Shopware 6.5 war die Order Übersicht nicht aufrufbar @@ -647,7 +626,7 @@ Diese Version bietet Unterstützung für die Massenbearbeitung von Produkten in - Neues `MollieOrderBuilder` Event, um eigene Metadaten zu einer Bestellung hinzufügen zu können (Feature für Entwickler). ### Verbesserungen -- Wichtige Änderung und Fehlerbehebungen für Order Transaktionen in Shopware. Wenn ein Kunde zusätzliche Zahlungsversuche durchführt, nachdem der erste Versuch fehlschlug, kam es manchmal dazu, dass die Anzeige der Statuseinträge in Administration und API nicht mehr passten. Mollie benutzt nun stets die aktuellste Transaktion in Shopware und fügt sämtliche Aktualisierungen dieser hinzu, um alle Daten konsistent zu halten. +- Wichtige Änderung und Fehlerbehebungen für Order Transaktionen in Shopware. Wenn ein Kunde zusätzliche Zahlungsversuche durchführt, nachdem der erste Versuch scheiterte, kam es manchmal dazu, dass die Anzeige der Statuseinträge in Administration und API nicht mehr passten. Mollie benutzt nun stets die aktuellste Transaktion in Shopware und fügt sämtliche Aktualisierungen dieser hinzu, um alle Daten konsistent zu halten. - SEPA Zahlungen bleiben nun auf "In Progress", wenn diese gestartet wurden, und springen nicht mehr zurück auf "Open". - Zahlungen mit Status "Created" werden nun als "fehlerhaft" erkannt. - Kreditkartenzahlungen mit Status "Open" werden nun als "fehlerhaft" erkannt. @@ -812,7 +791,7 @@ Aber keine Sorge, es gibt eine neue Funktion **"Automatischer Versand"**, die st ## [1.4.3] - 2021-07-07 ### Fehlerbehebungen -- Fix for Backwards-Compatibility +- Fix für Backwards-Compatibility ## [1.4.2] - 2021-07-06 ### Fehlerbehebungen @@ -1065,4 +1044,4 @@ Aber keine Sorge, es gibt eine neue Funktion **"Automatischer Versand"**, die st ## [1.0.1] - 2019-10-14 ### Fehlerbehebungen -- Fixed an issue where the monolog logger service wasn't available during the activate lifecycle +- Fixed an issue where the monolog logger service wasn't available during the activate lifecycle \ No newline at end of file diff --git a/CHANGELOG_en-GB.md b/CHANGELOG_en-GB.md index e764e95e7..7fca2ed0b 100644 --- a/CHANGELOG_en-GB.md +++ b/CHANGELOG_en-GB.md @@ -1,51 +1,31 @@ -# unreleased -- Fixed: Webhooks for POS Terminal payments now work correctly‚. -- Fixed: Express Checkout now correctly submits only selected radio button values when using the CustomProducts plugin, preventing all options from being sent instead of the chosen ones. - -# 4.23.0 -- New: Added Vipps as a payment method. -- New: Added MobilePay as a payment method. -- Fixed: Changes to order data made by listeners of the `MollieOrderBuildEvent` are now correctly applied to the Mollie API request. Previously, the event was dispatched but the modified order data was ignored. -- Apple Pay Direct: Phone number is now correctly applied for guest checkout even when updated after login. -- Fixed compatibility with set plugins. -- Fixed: Page extensions are now correctly extended instead of overwritten during checkout to ensure compatibility with other plugins. -- New: Shipping costs are now automatically considered for refunds via the Shopware Return Manager, including manually entered shipping costs. -- Fixed: Apple Pay Direct button in the shopping cart offcanvas is now displayed correctly when changing the shipping method. -- Fixed: Custom fields from other vendors are no longer overwritten when updating order line items. -- New: Added Bulgarian translations. -- Updated Croatian translations. -- Updated Lithuanian translations. -- Routes with customerIds were changed, now the customerId is used from the current logged in user instead Query parameter. - -# 4.22.1 -- Fixed an issue so that line items with negative amounts work again. - -# 4.22.0 -- Fixed wrong total amount in Apple Pay Direct when using NET display prices for customer groups. Taxes were not added in this case. -- Fix a problem where the credit card input fields are sometimes not editable due to race conditions when loading the mollie.js file. (removed defer-async loading). -- When a customer changes the payment method of a subscription, all older payments that can still be canceled will be automatically canceled. -- Added support for the “Additional Options/Warranties” plugin. -- Added an admin overview page allowing existing subscribers to cancel their subscriptions. -- Fixed the display of payment methods in older Shopware versions. -- Fixed the “Test API Keys” button in the plugin settings for Shopware 6.7. -- Adjusted the payment status action based on the Shopware version to ensure compatibility with older versions. -- iDEAL was renamed to zu iDEAL | Wero. - -# 4.21.0 -- Shipping costs are now considered in refunds via Shopware Return Management. +# 5.0.0 +- Payment methods now use the Mollie Payments API. +- Minimum PHP version is 8.2. +- Minimum Shopware version is 6.6.10.x. +- Order Events and Flows are no longer triggered. +- New payment flows have been added. +- Added the ModifyCreatePaymentPayloadEvent to modify the request before creating a payment in Mollie. +- All payment-related logs now include the Shopware orderNumber. +- The URL for saving the credit card token is no longer used; provide creditCardToken in the checkout request. +- The URL for saving the mandate ID is deprecated; provide mandateId as a body parameter in the checkout request. +- The URL for saving the POS terminal ID is deprecated; provide terminalId as a body parameter in the checkout request. +- A product can now have multiple voucher categories. +- Added: order-related log entries are now stored in a dedicated mollie directory. Log files follow the naming pattern order-, for example order-12345. +- Added: order-related log entries are now automatically removed when the payment status changes to "paid". Additionally, any remaining entries are deleted once they exceed the retention period defined in the settings. +- In Mollie Failure Mode, only payment methods that are also available in the cart are displayed on the Mollie page. +- The order state mapping has been optimized. During a status change, a precise transition path is now determined; if the transition cannot be performed, detailed log entries are generated. +- Payconiq is discontinued and will not be activated after update. Please deactivate the payment method and remove it from saleschannel +- Added new event PaymentCreatedEvent, now you can execute custom logic before redirecting to the payment provider +- Added new event ModifyCreateSubscriptionPayloadEvent. This allows developers to modify and extend the payload for the Mollie Subscription API before a subscription is created. + +## [Unreleased] - Fixed: Issue with carts containing multiple tax rates in combination with a promotion using proportional tax calculation. - Updated: Corrected the documentation for the endpoint used to validate and create an Apple Pay payment session. -- Fixed: Shipping methods were shown in Apple Pay Express even for countries where shipping was disabled in the administration. -- Removed: Removed dependency for the Basecom Fixture plugin and built our own fixture framework. -- Fixed: MolliePaymentMethodAvailabilityRemover to consider carts with price 0 to avoid getting all the payment methods removed. -– Compatibility with Click & Collect plugin -- Fixed: Descriptions of payment methods were displayed during checkout even when they were not selected. -- The profile navigation has been extended to include management of saved credit card details (visible only when credit card data is available). -- Tracking parameters are now optional for all shipping API routes. # 4.20.1 - Fixed: Order overview in Shopware 6.5 does not crash anymore -# 4.20.0 + +# 4.20.0 - 2025-11-19 - Changed order builder to use order addresses instead of customer default addresses to make sure the address in mollie matches the order information in shopware. - Fixed an issue where Apple Pay Direct did not work when the phone number was configured as a required field in the shop. - Fixed compatibility with shopware commercial @@ -1041,4 +1021,4 @@ fix backwards compatibility - Payment methods are now activated in your Mollie dashboard also when they're being activated in the shop ## [1.0.1] - 2019-10-14 -- Fixed an issue where the monolog logger service wasn't available during the activate lifecycle. +- Fixed an issue where the monolog logger service wasn't available during the activate lifecycle. \ No newline at end of file diff --git a/README.md b/README.md index 6a429b0cb..2bacf45cf 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@

-[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%207.4-8892BF.svg?style=flat)](https://php.net/) ![Build Status](https://github.com/mollie/Shopware6/actions/workflows/ci_pipe.yml/badge.svg) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/mollie/Shopware6) ![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/mollie/Shopware6/latest) +[![Minimum PHP Version](https://img.shields.io/badge/php-%3E%3D%208.2-8892BF.svg?style=flat)](https://php.net/) ![Build Status](https://github.com/mollie/Shopware6/actions/workflows/ci_pipe.yml/badge.svg) ![GitHub release (latest by date)](https://img.shields.io/github/v/release/mollie/Shopware6) ![GitHub commits since latest release (by date)](https://img.shields.io/github/commits-since/mollie/Shopware6/latest) diff --git a/composer.json b/composer.json index 4160477ec..bb595cb02 100644 --- a/composer.json +++ b/composer.json @@ -1,95 +1,94 @@ -{ - "name": "kiener/mollie-payments-plugin", - "description": "Mollie Payments", - "version": "v4.23.0", - "type": "shopware-platform-plugin", - "license": "MIT", - "authors": [ - { - "name": "Mollie B.V." - } - ], - "extra": { - "shopware-plugin-class": "Kiener\\MolliePayments\\MolliePayments", - "copyright": "(c) by Mollie B.V.", - "label": { - "de-DE": "Mollie Zahlungen", - "en-GB": "Mollie Payments", - "nl-NL": "Mollie Betalingen" - }, - "description": { - "de-DE": "Mit Mollie integrieren Sie alle wichtigen internationalen und lokalen Zahlungsmethoden in nur einem Schritt in Ihren Shopware-Webshop. Starten Sie noch heute!", - "en-GB": "With Mollie you integrate every major global and local payment method in your Shopware webshop in one go. Start growing your business with effortless payments today!", - "nl-NL": "Met Mollie integreer je alle belangrijke internationale en lokale betaalmethoden in \u00e9\u00e9n keer in je Shopware webshop. Start vandaag nog!" - }, - "manufacturerLink": { - "de-DE": "https://store.shopware.com/mollie.html", - "en-GB": "https://store.shopware.com/mollie.html", - "nl-NL": "https://store.shopware.com/mollie.html" - }, - "supportLink": { - "de-DE": "https://www.mollie.com/contact", - "en-GB": "https://www.mollie.com/contact", - "nl-NL": "https://www.mollie.com/contact" - } - }, - "config": { - "optimize-autoloader": true, - "allow-plugins": { - "infection/extension-installer": true, - "php-http/discovery": true, - "symfony/runtime": true - }, - "audit": { - "block-insecure": false - } - }, - "autoload": { - "psr-4": { - "Mollie\\Shopware\\": "shopware/", - "Kiener\\MolliePayments\\": "src/", - "Mollie\\Api\\": "vendor_manual/mollie-api-php/src" - } - }, - "autoload-dev": { - "psr-4": { - "Mollie\\Unit\\": "tests/Unit/", - "Mollie\\Integration\\": "tests/Integration/", - "Mollie\\Behat\\": "tests/Behat/Context/", - "MolliePayments\\Tests\\": "tests/PHPUnit/", - "MolliePayments\\PHPStan\\": "tests/PHPStan/", - "MolliePayments\\Fixtures\\": "tests/Fixtures/" - } - }, - "suggest": { - "shopware/storefront": "Require '*'. Enables features like Creditcard Components and iDeal issuer selector.", - "shopware/administration": "Require '*'. Enables features like partial shipping and refunding." - }, - "require": { - "php": ">=8.0", - "ext-curl": "*", - "shopware/core": "6.4.5.0 - 6.8.0.0", - "shopware/administration": "6.4.5.0 - 6.8.0.0", - "shopware/storefront": "6.4.5.0 - 6.8.0.0", - "shopware/elasticsearch": "6.4.5.0 - 6.8.0.0" - }, - "require-dev": { - "phpunit/phpunit": "^9", - "phpstan/phpstan": "^2", - "friendsofphp/php-cs-fixer": "^3", - "phpcompatibility/php-compatibility": "^9.3", - "squizlabs/php_codesniffer": "^3", - "boxblinkracer/phpunuhi": "dev-main", - "spaze/phpstan-disallowed-calls": "^4", - "behat/behat": "3.15.0", - "behat/gherkin": "4.10.0" - }, - "scripts": { - "post-install-cmd": [ - "[ ! -f vendor/bin/phpcs ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility" - ], - "post-update-cmd": [ - "[ ! -f vendor/bin/phpcs ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility" - ] - } -} +{ + "name": "kiener/mollie-payments-plugin", + "description": "Mollie Payments", + "version": "v5.0.0-beta3", + "type": "shopware-platform-plugin", + "license": "MIT", + "authors": [ + { + "name": "Mollie B.V." + } + ], + "extra": { + "shopware-plugin-class": "Kiener\\MolliePayments\\MolliePayments", + "copyright": "(c) by Mollie B.V.", + "label": { + "de-DE": "Mollie Zahlungen", + "en-GB": "Mollie Payments", + "nl-NL": "Mollie Betalingen" + }, + "description": { + "de-DE": "Mit Mollie integrieren Sie alle wichtigen internationalen und lokalen Zahlungsmethoden in nur einem Schritt in Ihren Shopware-Webshop. Starten Sie noch heute!", + "en-GB": "With Mollie you integrate every major global and local payment method in your Shopware webshop in one go. Start growing your business with effortless payments today!", + "nl-NL": "Met Mollie integreer je alle belangrijke internationale en lokale betaalmethoden in \u00e9\u00e9n keer in je Shopware webshop. Start vandaag nog!" + }, + "manufacturerLink": { + "de-DE": "https://store.shopware.com/mollie.html", + "en-GB": "https://store.shopware.com/mollie.html", + "nl-NL": "https://store.shopware.com/mollie.html" + }, + "supportLink": { + "de-DE": "https://www.mollie.com/contact", + "en-GB": "https://www.mollie.com/contact", + "nl-NL": "https://www.mollie.com/contact" + } + }, + "config": { + "optimize-autoloader": true, + "allow-plugins": { + "infection/extension-installer": true, + "php-http/discovery": true, + "symfony/runtime": true, + "dealerdirect/phpcodesniffer-composer-installer": true + } + }, + "autoload": { + "psr-4": { + "Mollie\\Shopware\\": "shopware/", + "Kiener\\MolliePayments\\": "src/", + "Mollie\\Api\\": "vendor_manual/mollie-api-php/src" + } + }, + "autoload-dev": { + "psr-4": { + "Mollie\\Shopware\\Unit\\": "tests/Unit/", + "Mollie\\Shopware\\Integration\\": "tests/Integration/", + "Mollie\\Shopware\\Behat\\": "tests/Behat/", + "MolliePayments\\Shopware\\Tests\\": "tests/PHPUnit/", + "MolliePayments\\Shopware\\PHPStan\\": "tests/PHPStan/" + } + }, + "suggest": { + "shopware/storefront": "Require '*'. Enables features like Creditcard Components and iDeal issuer selector.", + "shopware/administration": "Require '*'. Enables features like partial shipping and refunding." + }, + "require": { + "php": ">=8.2", + "ext-curl": "*", + "shopware/core": ">=6.6.10.0 <6.8", + "ext-mbstring": "*" + }, + "require-dev": { + "shopware/storefront": ">=6.6.10.0 <6.8", + "phpunit/phpunit": "^11", + "phpstan/phpstan": "^2", + "friendsofphp/php-cs-fixer": "^3", + "phpcompatibility/php-compatibility": "^9", + "squizlabs/php_codesniffer": "^3", + "boxblinkracer/phpunuhi": "dev-main", + "spaze/phpstan-disallowed-calls": "^4", + "behat/behat": "^3", + "behat/gherkin": "^4", + "phpstan/phpstan-phpunit": "^2.0", + "ext-fileinfo": "*", + "ext-dom": "*" + }, + "scripts": { + "post-install-cmd": [ + "[ ! -f vendor/bin/phpcs ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility" + ], + "post-update-cmd": [ + "[ ! -f vendor/bin/phpcs ] || vendor/bin/phpcs --config-set installed_paths vendor/phpcompatibility/php-compatibility" + ] + } +} diff --git a/config/.php_cs.php b/config/.php_cs.php index 532d62a5b..c97d3a313 100644 --- a/config/.php_cs.php +++ b/config/.php_cs.php @@ -4,6 +4,8 @@ __DIR__ . '/../src', __DIR__ . '/../shopware', __DIR__.'/../tests/PHPUnit', + __DIR__.'/../tests/Behat', + __DIR__.'/../tests/Unit', __DIR__.'/../tests/Integration', ]); @@ -24,6 +26,10 @@ 'phpdoc_align' => [ 'align' => 'left', ], + 'no_superfluous_phpdoc_tags'=>[ + 'allow_mixed' => true + ], + 'method_argument_space' =>false, 'no_useless_else' => true, 'no_useless_return' => true, 'no_unused_imports' => true, diff --git a/config/.phpstan.neon b/config/.phpstan.neon index ccb33ac26..032484dd9 100644 --- a/config/.phpstan.neon +++ b/config/.phpstan.neon @@ -2,6 +2,7 @@ parameters: level: 8 paths: - ./../src + - ./../shopware excludePaths: - ./../src/Resources/* - ./../src/Migration/* @@ -21,8 +22,6 @@ parameters: message: 'use some logger instead' - function: 'putenv()' message: 'might overwrite existing variables' - scanDirectories: - - ../polyfill/Shopware reportUnmatchedIgnoredErrors: false treatPhpDocTypesAsCertain: false ignoreErrors: @@ -36,9 +35,10 @@ parameters: - identifier: parameter.unresolvableType - identifier: varTag.unresolvableType - identifier: attribute.notFound + - identifier: function.alreadyNarrowedType services: - - class: MolliePayments\PHPStan\Rules\NoManufacturerRule + - class: MolliePayments\Shopware\PHPStan\Rules\NoManufacturerRule tags: - phpstan.rules.rule diff --git a/config/.shopware-extension-6.7.yml b/config/.shopware-extension-6.7.yml index 4df87a656..eb190d101 100644 --- a/config/.shopware-extension-6.7.yml +++ b/config/.shopware-extension-6.7.yml @@ -1,2 +1,5 @@ build: - shopwareVersionConstraint: '6.7.0.0' \ No newline at end of file + shopwareVersionConstraint: '6.7.0.0' + zip: + assets: + npm_strict: true \ No newline at end of file diff --git a/config/.shopware-extension.yml b/config/.shopware-extension.yml index 6a0d5ba11..91318fed8 100644 --- a/config/.shopware-extension.yml +++ b/config/.shopware-extension.yml @@ -1,2 +1,5 @@ build: - shopwareVersionConstraint: '6.4.5.0' \ No newline at end of file + shopwareVersionConstraint: '6.6.10.0' + zip: + assets: + npm_strict: true \ No newline at end of file diff --git a/config/behat.yaml b/config/behat.yaml index c23f3bdac..a2ef7a2b0 100644 --- a/config/behat.yaml +++ b/config/behat.yaml @@ -4,7 +4,8 @@ default: paths: features: '%paths.base%/../tests/Behat/Features' contexts: - - Mollie\Behat\BootstrapContext - - Mollie\Behat\PaymentContext - - Mollie\Behat\CustomerContext - - Mollie\Behat\CheckoutContext \ No newline at end of file + - Mollie\Shopware\Behat\Context\BootstrapContext + - Mollie\Shopware\Behat\Context\PaymentContext + - Mollie\Shopware\Behat\Context\CustomerContext + - Mollie\Shopware\Behat\Context\CheckoutContext + - Mollie\Shopware\Behat\Context\SubscriptionContext \ No newline at end of file diff --git a/config/phpunit.integration.xml b/config/phpunit.integration.xml index a2fb475a3..403a1c809 100644 --- a/config/phpunit.integration.xml +++ b/config/phpunit.integration.xml @@ -1,6 +1,6 @@ ./../tests/Integration - ./../tests/Integration/Repository/OrderTransactionRepositoryTest.php - + - ./../src - ./../shopware + ./../src + ./../shopware - + \ No newline at end of file diff --git a/config/phpunit.xml b/config/phpunit.xml index 369f5bf7a..35464daaa 100644 --- a/config/phpunit.xml +++ b/config/phpunit.xml @@ -1,10 +1,11 @@ @@ -14,12 +15,10 @@ - - - ./../src - ./../shopware - - - - + + + ./../src + ./../shopware + + diff --git a/makefile b/makefile index ba9f1c093..6d09cfa0c 100644 --- a/makefile +++ b/makefile @@ -33,22 +33,20 @@ help: prod: ##1 Installs all production dependencies # ---------------------------------------------------------------- - @composer validate - @composer install --no-dev + composer validate + composer install --no-dev npm install --omit=dev cd src/Resources/app/administration && npm install --omit=dev cd src/Resources/app/storefront && npm install --omit=dev dev: ##1 Installs all dev dependencies - @composer validate + composer validate COMPOSER_NO_SECURITY_BLOCKING=1 composer update --ignore-platform-req=ext-amqp npm install chmod a+x node_modules/.bin/prettier cd src/Resources/app/administration && npm install cd src/Resources/app/storefront && npm install -install: ##1 [deprecated] Installs all production dependencies. Please use "make prod" now. - @make prod -B clean: ##1 Cleans all dependencies and files rm -rf vendor/* @@ -56,16 +54,16 @@ clean: ##1 Cleans all dependencies and files rm -rf .reports | true # ------------------------------------------------------ rm -rf ./node_modules/* + rm -rf config-* rm -rf ./src/Resources/app/administration/node_modules/* rm -rf ./src/Resources/app/storefront/node_modules/* # ------------------------------------------------------ rm -rf ./src/Resources/app/storefront/dist/storefront - # ------------------------------------------------------ - rm -rf ./src/Resources/public/administration - rm -rf ./src/Resources/public/mollie-payments.js + build: ##2 Installs the plugin, and builds the artifacts using the Shopware build commands. sudo apt-get update --allow-releaseinfo-change -y + sudo apt-get install zip curl -1sLf 'https://dl.cloudsmith.io/public/friendsofshopware/stable/setup.deb.sh' | sudo -E bash && sudo apt-get install shopware-cli -y && sudo apt-get autoremove -y && shopware-cli -v # CUSTOM WEBPACK cd ./src/Resources/app/storefront && make build -B @@ -88,7 +86,7 @@ endif fixtures: ##2 Installs all available testing fixtures of the Mollie plugin cd ../../.. && php bin/console --no-debug cache:clear - cd ../../.. && php bin/console --no-debug mollie:fixtures:install + cd ../../.. && php bin/console --no-debug mollie:fixtures:load pr: ##2 Prepares everything for a Pull Request # ----------------------------------------------------------------- @@ -103,12 +101,11 @@ pr: ##2 Prepares everything for a Pull Request @make phpmin -B @make stan -B @make phpunit -B + @make phpintegration -B + @make behat -B @make vitest -B @make configcheck -B @make phpunuhi -B - # ----------------------------------------------------------------- - @make phpintegration -B - @make behat -B snippetexport: ##2 Exports all snippets php vendor/bin/phpunuhi export --configuration=./config/.phpunuhi.xml --dir=./.phpunuhi @@ -122,14 +119,15 @@ phpcheck: ##3 Starts the PHP syntax checks @find . -name '*.php' -not -path "./vendor/*" -not -path "./tests/*" | xargs -n 1 -P4 php -l phpmin: ##3 Starts the PHP compatibility checks - @php vendor/bin/phpcs -p --standard=PHPCompatibility --extensions=php --runtime-set testVersion 8.0 ./src ./shopware + echo "PHPCompatibility is in alpha right now and has issues with enums" + #@php vendor/bin/phpcs -p --standard=PHPCompatibility --extensions=php --runtime-set testVersion 8.2 ./src ./shopware csfix: ##3 Starts the PHP CS Fixer ifndef mode - @PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer fix --config=./config/.php_cs.php --dry-run --show-progress=dots --verbose + php vendor/bin/php-cs-fixer fix --config=./config/.php_cs.php --dry-run --show-progress=dots --verbose endif ifeq ($(mode), fix) - @PHP_CS_FIXER_IGNORE_ENV=1 php vendor/bin/php-cs-fixer fix --config=./config/.php_cs.php --show-progress=dots --verbose + php vendor/bin/php-cs-fixer fix --config=./config/.php_cs.php --show-progress=dots --verbose endif stan: ##3 Starts the PHPStan Analyser @@ -182,8 +180,8 @@ phpunuhi: ##3 Tests and verifies all plugin snippets php vendor/bin/phpunuhi validate --configuration=./config/.phpunuhi.xml --report-format=junit --report-output=./.phpunuhi/junit.xml # ------------------------------------------------------------------------------------------------- -IGNORED = '*/vendor/*' '*.git*' '*.reports*' '*/.idea*' '*/node_modules*' '*/.phpunuhi*' '*.DS_Store' '*.prettierignore' './package.json' './package-lock.json' 'composer.lock' -IGNORED_FINAL = $(IGNORED) '*/tests*' 'config/*' '*/makefile' +IGNORED = '*/vendor/*' '*.git*' '*.reports*' '*/.idea*' '*/node_modules*' '*/.phpunuhi*' '*.DS_Store' '*.prettierignore' 'MolliePayments/package.json' 'MolliePayments/package-lock.json' 'MolliePayments/composer.lock' +IGNORED_FINAL = $(IGNORED) '*/tests*' 'MolliePayments/config/*' '*/makefile' release: ##4 Builds a PROD version and creates a ZIP file in plugins/.build. ifneq (,$(findstring v12,$(NODE_VERSION))) @@ -195,12 +193,11 @@ endif # ------------------------------------------------------------------------------------------------- @echo "INSTALL DEV DEPENDENCIES AND BUILD" make clean -B - make dev -B - make build -B + cd src/Resources/app/administration && npm install + cd src/Resources/app/storefront && npm install + make build use67=true -B # ------------------------------------------------------------------------------------------------- @echo "INSTALL PRODUCTION DEPENDENCIES" - make prod -B - rm -rf ./src/Resources/app/storefront/node_modules/* # DELETE distribution file. that ones not compatible between 6.5 and 6.4 # if one wants to use it, they need to run build-storefront.sh manually and activate that feature # in our plugin configuration! (use shopware standard js) diff --git a/polyfill/Shopware/Core/Checkout/Cart/CartException.php b/polyfill/Shopware/Core/Checkout/Cart/CartException.php deleted file mode 100644 index d2d5d8980..000000000 --- a/polyfill/Shopware/Core/Checkout/Cart/CartException.php +++ /dev/null @@ -1,20 +0,0 @@ -orderTransactionId = $orderTransactionId; - - parent::__construct($message, $parameters, $e); - } - - public function getStatusCode(): int - { - return Response::HTTP_BAD_REQUEST; - } - - public function getOrderTransactionId(): string - { - return $this->orderTransactionId; - } -} diff --git a/polyfill/Shopware/Core/Checkout/Payment/PaymentException.php b/polyfill/Shopware/Core/Checkout/Payment/PaymentException.php deleted file mode 100644 index 98c1ff01d..000000000 --- a/polyfill/Shopware/Core/Checkout/Payment/PaymentException.php +++ /dev/null @@ -1,24 +0,0 @@ -definition = $definition; - $this->reader = $reader; - $this->versionManager = $versionManager; - $this->searcher = $searcher; - $this->aggregator = $aggregator; - $this->eventDispatcher = $eventDispatcher; - $this->eventFactory = $eventFactory; - } - - public function getDefinition(): EntityDefinition - { - return $this->definition; - } - - /** - * @return EntitySearchResult - */ - public function search(Criteria $criteria, Context $context): EntitySearchResult - { - if (!$criteria->getTitle()) { - return $this->_search($criteria, $context); - } - - return Profiler::trace($criteria->getTitle(), fn () => $this->_search($criteria, $context), 'repository'); - } - - public function aggregate(Criteria $criteria, Context $context): AggregationResultCollection - { - if (!$criteria->getTitle()) { - return $this->_aggregate($criteria, $context); - } - - return Profiler::trace($criteria->getTitle(), fn () => $this->_aggregate($criteria, $context), 'repository'); - } - - public function searchIds(Criteria $criteria, Context $context): IdSearchResult - { - if (!$criteria->getTitle()) { - return $this->_searchIds($criteria, $context); - } - - return Profiler::trace($criteria->getTitle(), fn () => $this->_searchIds($criteria, $context), 'repository'); - } - - /** - * @param array> $data - */ - public function update(array $data, Context $context): EntityWrittenContainerEvent - { - ReplicaConnection::ensurePrimary(); - - $affected = $this->versionManager->update($this->definition, $data, WriteContext::createFromContext($context)); - $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); - $this->eventDispatcher->dispatch($event); - - return $event; - } - - /** - * @param array> $data - */ - public function upsert(array $data, Context $context): EntityWrittenContainerEvent - { - ReplicaConnection::ensurePrimary(); - - $affected = $this->versionManager->upsert($this->definition, $data, WriteContext::createFromContext($context)); - $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); - $this->eventDispatcher->dispatch($event); - - return $event; - } - - /** - * @param array> $data - */ - public function create(array $data, Context $context): EntityWrittenContainerEvent - { - ReplicaConnection::ensurePrimary(); - - $affected = $this->versionManager->insert($this->definition, $data, WriteContext::createFromContext($context)); - $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); - $this->eventDispatcher->dispatch($event); - - return $event; - } - - /** - * @param array> $ids - */ - public function delete(array $ids, Context $context): EntityWrittenContainerEvent - { - ReplicaConnection::ensurePrimary(); - - $affected = $this->versionManager->delete($this->definition, $ids, WriteContext::createFromContext($context)); - $event = EntityWrittenContainerEvent::createWithDeletedEvents($affected->getDeleted(), $context, $affected->getNotFound()); - - if ($affected->getWritten()) { - $updates = EntityWrittenContainerEvent::createWithWrittenEvents($affected->getWritten(), $context, []); - - if ($updates->getEvents() !== null) { - $event->addEvent(...$updates->getEvents()); - } - } - - $this->eventDispatcher->dispatch($event); - - return $event; - } - - public function createVersion(string $id, Context $context, ?string $name = null, ?string $versionId = null): string - { - ReplicaConnection::ensurePrimary(); - - if (!$this->definition->isVersionAware()) { - throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName())); - } - - return $this->versionManager->createVersion($this->definition, $id, WriteContext::createFromContext($context), $name, $versionId); - } - - public function merge(string $versionId, Context $context): void - { - ReplicaConnection::ensurePrimary(); - - if (!$this->definition->isVersionAware()) { - throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName())); - } - $this->versionManager->merge($versionId, WriteContext::createFromContext($context)); - } - - public function clone(string $id, Context $context, ?string $newId = null, ?CloneBehavior $behavior = null): EntityWrittenContainerEvent - { - ReplicaConnection::ensurePrimary(); - - $newId ??= Uuid::randomHex(); - if (!Uuid::isValid($newId)) { - throw new InvalidUuidException($newId); - } - - $affected = $this->versionManager->clone( - $this->definition, - $id, - $newId, - $context->getVersionId(), - WriteContext::createFromContext($context), - $behavior ?? new CloneBehavior() - ); - - $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, [], true); - $this->eventDispatcher->dispatch($event); - - return $event; - } - - /** - * @return TEntityCollection - */ - private function read(Criteria $criteria, Context $context): EntityCollection - { - $criteria = clone $criteria; - - /** @var TEntityCollection $entities */ - $entities = $this->reader->read($this->definition, $criteria, $context); - - if ($criteria->getFields() === []) { - $event = $this->eventFactory->create($entities->getElements(), $context); - } else { - $event = $this->eventFactory->createPartial($entities->getElements(), $context); - } - - $this->eventDispatcher->dispatch($event); - - return $entities; - } - - /** - * @return EntitySearchResult - */ - private function _search(Criteria $criteria, Context $context): EntitySearchResult - { - $criteria = clone $criteria; - $aggregations = null; - if ($criteria->getAggregations()) { - $aggregations = $this->aggregate($criteria, $context); - } - - if (!RepositorySearchDetector::isSearchRequired($this->definition, $criteria)) { - $this->eventDispatcher->dispatch( - new EntitySearchedEvent($criteria, $this->definition, $context) - ); - $entities = $this->read($criteria, $context); - - return new EntitySearchResult($this->definition->getEntityName(), $entities->count(), $entities, $aggregations, $criteria, $context); - } - - $ids = $this->searchIds($criteria, $context); - - if (empty($ids->getIds())) { - /** @var TEntityCollection $collection */ - $collection = $this->definition->getCollectionClass(); - - return new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), new $collection(), $aggregations, $criteria, $context); - } - - $readCriteria = $criteria->cloneForRead($ids->getIds()); - - $entities = $this->read($readCriteria, $context); - - $search = $ids->getData(); - - foreach ($entities as $element) { - if (!\array_key_exists($element->getUniqueIdentifier(), $search)) { - continue; - } - - $data = $search[$element->getUniqueIdentifier()]; - unset($data['id']); - - if (empty($data)) { - continue; - } - - $element->addExtension('search', new ArrayEntity($data)); - } - - $result = new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), $entities, $aggregations, $criteria, $context); - $result->addState(...$ids->getStates()); - - $event = new EntitySearchResultLoadedEvent($this->definition, $result); - $this->eventDispatcher->dispatch($event, $event->getName()); - - return $result; - } - - private function _aggregate(Criteria $criteria, Context $context): AggregationResultCollection - { - $criteria = clone $criteria; - - $result = $this->aggregator->aggregate($this->definition, $criteria, $context); - - $event = new EntityAggregationResultLoadedEvent($this->definition, $result, $context); - $this->eventDispatcher->dispatch($event, $event->getName()); - - return $result; - } - - private function _searchIds(Criteria $criteria, Context $context): IdSearchResult - { - $criteria = clone $criteria; - - $this->eventDispatcher->dispatch(new EntitySearchedEvent($criteria, $this->definition, $context)); - - $result = $this->searcher->search($this->definition, $criteria, $context); - - $event = new EntityIdSearchResultLoadedEvent($this->definition, $result); - $this->eventDispatcher->dispatch($event, $event->getName()); - - return $result; - } -} diff --git a/polyfill/Shopware/Core/Framework/Event/BusinessEventInterface.php b/polyfill/Shopware/Core/Framework/Event/BusinessEventInterface.php deleted file mode 100644 index f5860fd04..000000000 --- a/polyfill/Shopware/Core/Framework/Event/BusinessEventInterface.php +++ /dev/null @@ -1,19 +0,0 @@ -statusCode = $statusCode; - $this->errorCode = $errorCode; - - parent::__construct($message, $parameters, $previous); - } - - public function getErrorCode(): string - { - return $this->errorCode; - } - - public function getStatusCode(): int - { - return $this->statusCode; - } -} \ No newline at end of file diff --git a/polyfill/Shopware/Core/System/Snippet/Files/AbstractSnippetFile.php b/polyfill/Shopware/Core/System/Snippet/Files/AbstractSnippetFile.php deleted file mode 100644 index 910293985..000000000 --- a/polyfill/Shopware/Core/System/Snippet/Files/AbstractSnippetFile.php +++ /dev/null @@ -1,56 +0,0 @@ - ['storefront']])] +#[AsDecorator(decorates: AccountOrderController::class)] +final class FailureModeOrderController extends AccountOrderController +{ + public function __construct( + #[AutowireDecorated] + private AccountOrderController $accountOrderController, + #[Autowire(service: OrderRoute::class)] + private AbstractOrderRoute $orderRoute, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + private AccountEditOrderPageLoader $accountEditOrderPageLoader, + ) { + } + + public function editOrder(string $orderId, Request $request, SalesChannelContext $context): Response + { + $salesChannelId = $context->getSalesChannelId(); + + $paymentSettings = $this->settingsService->getPaymentSettings($salesChannelId); + + if ($paymentSettings->isShopwareFailedPayment()) { + return $this->accountOrderController->editOrder($orderId, $request, $context); + } + + try { + $editOrderPage = $this->accountEditOrderPageLoader->load($request, $context); + $paymentMethods = $editOrderPage->getPaymentMethods(); + } catch (OrderException $exception) { + $criteria = new Criteria([$orderId]); + $orderRouteResponse = $this->orderRoute->load($request,$context,$criteria); + $order = $orderRouteResponse->getOrders()->first(); + + if ($order instanceof OrderEntity) { + $this->addFlash(self::DANGER, $this->trans('error.' . $exception->getErrorCode(), ['%orderNumber%' => (string) $order->getOrderNumber()])); + } + + return $this->redirectToRoute('frontend.account.order.page'); + } + + $paymentMethodList = []; + foreach ($paymentMethods as $paymentMethod) { + /** @var ?PaymentMethod $paymentMethodExtension */ + $paymentMethodExtension = $paymentMethod->getExtension(Mollie::EXTENSION); + if ($paymentMethodExtension === null) { + continue; + } + $paymentMethodList[] = $paymentMethodExtension->getPaymentMethod()->value; + } + + return $this->renderStorefront('@Storefront/storefront/page/checkout/payment/failed.html.twig', [ + 'redirectUrl' => $this->generateUrl('frontend.account.edit-order.update-order', ['orderId' => $orderId]), + 'paymentMethods' => $paymentMethodList, + 'paymentMethodId' => $context->getPaymentMethod()->getId(), + ]); + } + + public function orderOverview(Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->orderOverview($request, $context); + } + + public function cancelOrder(Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->cancelOrder($request, $context); + } + + public function orderSingleOverview(Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->orderSingleOverview($request, $context); + } + + public function ajaxOrderDetail(Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->ajaxOrderDetail($request, $context); + } + + public function orderChangePayment(string $orderId, Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->orderChangePayment($orderId, $request, $context); + } + + public function updateOrder(string $orderId, Request $request, SalesChannelContext $context): Response + { + return $this->accountOrderController->updateOrder($orderId, $request, $context); + } +} diff --git a/shopware/Component/FailureMode/PaymentPageFailedEvent.php b/shopware/Component/FailureMode/PaymentPageFailedEvent.php new file mode 100644 index 000000000..eb09e2a20 --- /dev/null +++ b/shopware/Component/FailureMode/PaymentPageFailedEvent.php @@ -0,0 +1,45 @@ +transactionId; + } + + public function getOrder(): OrderEntity + { + return $this->order; + } + + public function getPayment(): Payment + { + return $this->payment; + } + + public function getSalesChannelContext(): SalesChannelContext + { + return $this->salesChannelContext; + } + + public function getSalesChannelId(): string + { + return $this->salesChannelContext->getSalesChannelId(); + } + + public function getRedirectUrl(): string + { + return $this->payment->getCheckoutUrl(); + } +} diff --git a/shopware/Component/Fixture/AbstractFixture.php b/shopware/Component/Fixture/AbstractFixture.php new file mode 100644 index 000000000..7cb94bf19 --- /dev/null +++ b/shopware/Component/Fixture/AbstractFixture.php @@ -0,0 +1,22 @@ +> $categoryRepository + */ + public function __construct( + #[Autowire(service: 'category.repository')] + private readonly EntityRepository $categoryRepository + ) { + } + + public function getPriority(): int + { + return 100; + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $rootCategory = $this->getRootCategoryId($context); + $categoryTree = $this->getCategoryTree($rootCategory); + + $upsertData = []; + foreach ($categoryTree as $categoryData) { + $upsertData[] = $this->getCategoryData($categoryData['id'], $categoryData['name'], $categoryData['parentId']); + } + + $this->categoryRepository->upsert($upsertData, $context); + } + + public function uninstall(Context $context): void + { + $categoryTree = $this->getCategoryTree('root'); + $deleteData = []; + foreach ($categoryTree as $categoryData) { + $deleteData[] = [ + 'id' => $categoryData['id'], + ]; + } + $this->categoryRepository->delete($deleteData, $context); + } + + /** + * @return array + */ + private function getCategoryTree(string $rootCategoryId): array + { + $mollieRootId = Uuid::fromStringToHex('mollie'); + + return [ + [ + 'id' => $mollieRootId, + 'name' => 'Mollie', + 'parentId' => $rootCategoryId, + ], + [ + 'id' => Uuid::fromStringToHex('mollie-' . self::CATEGORY_REGULAR), + 'name' => 'Regular Products', + 'parentId' => $mollieRootId, + ], + [ + 'id' => Uuid::fromStringToHex('mollie-' . self::CATEGORY_VOUCHER), + 'name' => 'Voucher', + 'parentId' => $mollieRootId, + ], + [ + 'id' => Uuid::fromStringToHex('mollie-' . self::CATEGORY_SUBSCRIPTIONS), + 'name' => 'Subscriptions', + 'parentId' => $mollieRootId, + ], + [ + 'id' => Uuid::fromStringToHex('mollie-' . self::CATEGORY_ROUNDING), + 'name' => 'Rounding', + 'parentId' => $mollieRootId, + ], + [ + 'id' => Uuid::fromStringToHex('mollie-' . self::CATEGORY_CREDIT_CARD_ERRORS), + 'name' => 'Credit Card Errors', + 'parentId' => $mollieRootId, + ], + ]; + } + + private function getRootCategoryId(Context $context): string + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('parentId', null)); + + return (string) $this->categoryRepository->searchIds($criteria, $context)->firstId(); + } + + /** + * @return array + */ + private function getCategoryData(string $id, string $name, string $parentId): array + { + return [ + 'id' => $id, + 'translations' => [ + 'de-DE' => [ + 'name' => $name, + ], + 'en-GB' => [ + 'name' => $name, + ], + ], + 'productAssignmentType' => 'product', + 'level' => 2, + 'active' => true, + 'displayNestedProducts' => true, + 'visible' => true, + 'type' => 'page', + 'cmsPageId' => null, + 'parentId' => $parentId, + 'afterCategoryId' => null, + ]; + } +} diff --git a/shopware/Component/Fixture/Customer/CustomerTrait.php b/shopware/Component/Fixture/Customer/CustomerTrait.php new file mode 100644 index 000000000..e7a3950d3 --- /dev/null +++ b/shopware/Component/Fixture/Customer/CustomerTrait.php @@ -0,0 +1,112 @@ +setLimit(1) + ->addSorting(new FieldSorting('salutationKey')) + ; + + /** @var EntityRepository> $salutationRepository */ + $salutationRepository = $this->container->get('salutation.repository'); + + return (string) $salutationRepository->searchIds($criteria, $context)->firstId(); + } + + /** + * @param string[] $isoCodes + * + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + * + * @return EntitySearchResult> + */ + private function getCountries(array $isoCodes, Context $context): EntitySearchResult + { + $criteria = (new Criteria()) + ->addFilter(new EqualsFilter('active', true)) + ->addFilter(new EqualsFilter('shippingAvailable', true)) + ->addFilter(new EqualsAnyFilter('iso', $isoCodes)) + ; + + /** @var EntityRepository> $countryRepository */ + $countryRepository = $this->container->get('country.repository'); + + return $countryRepository->search($criteria, $context); + } + + private function getPaymentMethodId(Context $context): string + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('active', true)); + $criteria->setLimit(1); + /** @var EntityRepository> $paymentMethodRepository */ + $paymentMethodRepository = $this->container->get('payment_method.repository'); + $searchResult = $paymentMethodRepository->searchIds($criteria, $context); + + return (string) $searchResult->firstId(); + } + + /** + * @param array $customer + * + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + * + * @return array + */ + private function getAddresses(array $customer, Context $context): array + { + $countries = $this->getCountries(['DE', 'NL', 'FR', 'BE', 'PL', 'ES', 'SE', 'IT'], $context); + + $addresses = []; + /** @var CountryEntity $country */ + foreach ($countries as $country) { + $isoCode = (string) $country->getIso(); + $addresses[$isoCode] = [ + 'id' => $this->getAddressId($isoCode), + 'company' => 'Mollie B.V.', + 'salutationId' => $customer['salutationId'], + 'firstName' => $customer['firstName'], + 'lastName' => $customer['lastName'], + 'street' => 'Cypress Street 1', + 'zipcode' => '10115', + 'city' => 'Berlin', + 'countryId' => $country->getId(), + 'phoneNumber' => '+490123456789', + ]; + } + + return array_values($addresses); + } + + private function getAddressId(string $iso): string + { + $addressId = sprintf('%s-%s', $this->getCustomerId(), $iso); + + return Uuid::fromStringToHex($addressId); + } +} diff --git a/shopware/Component/Fixture/Customer/DefaultCustomerFixture.php b/shopware/Component/Fixture/Customer/DefaultCustomerFixture.php new file mode 100644 index 000000000..8674f7b74 --- /dev/null +++ b/shopware/Component/Fixture/Customer/DefaultCustomerFixture.php @@ -0,0 +1,83 @@ +> $customerRepository + */ + public function __construct( + #[Autowire(service: 'customer.repository')] + private readonly EntityRepository $customerRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $salutationId = $this->getDefaultSalutationId($context); + $salesChannelId = $this->getSalesChannelId($context); + $paymentMethodId = $this->getPaymentMethodId($context); + $email = 'cypress@mollie.com'; + $password = 'cypress123'; + + $defaultAddressId = $this->getAddressId('DE'); + $customer = [ + 'id' => $this->getCustomerId(), + 'salutationId' => $salutationId, + 'accountType' => 'commercial', + 'customerNumber' => 'mollie-CYPRESS', + 'firstName' => 'Cypress', + 'lastName' => 'TestUser', + 'createCustomerAccount' => true, + 'password' => $password, + 'email' => $email, + 'group' => [ + 'id' => TestDefaults::FALLBACK_CUSTOMER_GROUP, + 'name' => 'Standard customer group', + 'displayGross' => true + ], + 'salesChannelId' => $salesChannelId, + 'defaultPaymentMethodId' => $paymentMethodId, + 'defaultBillingAddressId' => $defaultAddressId, + 'defaultShippingAddressId' => $defaultAddressId, + ]; + + $customer['addresses'] = $this->getAddresses($customer, $context); + + $this->customerRepository->upsert([$customer], $context); + } + + public function uninstall(Context $context): void + { + $this->customerRepository->delete([[ + 'id' => $this->getCustomerId(), + ]], $context); + } + + private function getCustomerId(): string + { + return Uuid::fromStringToHex('default-customer-id'); + } +} diff --git a/shopware/Component/Fixture/Customer/NetCustomerFixture.php b/shopware/Component/Fixture/Customer/NetCustomerFixture.php new file mode 100644 index 000000000..daf666427 --- /dev/null +++ b/shopware/Component/Fixture/Customer/NetCustomerFixture.php @@ -0,0 +1,82 @@ +> $customerRepository + */ + public function __construct( + #[Autowire(service: 'customer.repository')] + private readonly EntityRepository $customerRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $salutationId = $this->getDefaultSalutationId($context); + $salesChannelId = $this->getSalesChannelId($context); + $paymentMethodId = $this->getPaymentMethodId($context); + $email = 'cypress-net@mollie.com'; + $password = 'cypress123'; + $defaultAddressId = $this->getAddressId('DE'); + + $customer = [ + 'id' => $this->getCustomerId(), + 'salutationId' => $salutationId, + 'accountType' => 'commercial', + 'customerNumber' => 'mollie-net-CYPRESS', + 'firstName' => 'Cypress', + 'lastName' => 'TestUser', + 'createCustomerAccount' => true, + 'password' => $password, + 'email' => $email, + 'group' => [ + 'id' => Uuid::fromStringToHex('net-customer-group'), + 'name' => 'Net customer group', + 'displayGross' => false + ], + 'salesChannelId' => $salesChannelId, + 'defaultPaymentMethodId' => $paymentMethodId, + 'defaultBillingAddressId' => $defaultAddressId, + 'defaultShippingAddressId' => $defaultAddressId, + ]; + + $customer['addresses'] = $this->getAddresses($customer, $context); + + $this->customerRepository->upsert([$customer], $context); + } + + public function uninstall(Context $context): void + { + $this->customerRepository->delete([[ + 'id' => $this->getCustomerId(), + ]], $context); + } + + private function getCustomerId(): string + { + return Uuid::fromStringToHex('net-customer-id'); + } +} diff --git a/shopware/Component/Fixture/FixtureCommand.php b/shopware/Component/Fixture/FixtureCommand.php new file mode 100644 index 000000000..e9ce8e30a --- /dev/null +++ b/shopware/Component/Fixture/FixtureCommand.php @@ -0,0 +1,90 @@ + $fixtures + */ + public function __construct( + #[AutowireIterator('mollie.fixture')] + private iterable $fixtures + ) { + parent::__construct(); + } + + protected function configure(): void + { + $this->addOption('uninstall', 'r', InputOption::VALUE_NONE, 'uninstall all fixtures'); + $this->addArgument('group', InputArgument::IS_ARRAY, 'Groups to install', []); + } + + protected function execute(InputInterface $input, OutputInterface $output): int + { + $groupArguments = $input->getArgument('group'); + $groups = []; + if (count($groupArguments) > 0) { + foreach ($groupArguments as $group) { + $groups[] = FixtureGroup::from($group); + } + } + $fixtures = iterator_to_array($this->fixtures); + + $context = new Context(new SystemSource()); + $isUninstall = $input->getOption('uninstall'); + + if ($isUninstall) { + $output->writeln('uninstalling all fixtures'); + + // Uninstall fixtures with lowest priority first + uasort($fixtures,function (AbstractFixture $a, AbstractFixture $b) { + return $a->getPriority() <=> $b->getPriority(); + }); + + foreach ($fixtures as $fixture) { + $fixtureClass = (string) get_class($fixture); + $fixtureGroup = $fixture->getGroup()->value; + $output->writeln('uninstalling ' . $fixtureClass . ' group:' . $fixtureGroup . ''); + $fixture->uninstall($context); + } + $output->writeln('finished uninstalling'); + + return Command::SUCCESS; + } + $output->writeln('installing fixtures'); + + // Install fixtures with highest priority first + uasort($fixtures,function (AbstractFixture $a, AbstractFixture $b) { + return $b->getPriority() <=> $a->getPriority(); + }); + + /** @var AbstractFixture $fixture */ + foreach ($fixtures as $fixture) { + if (count($groups) > 0 && ! in_array($fixture->getGroup(), $groups)) { + continue; + } + $fixtureClass = (string) get_class($fixture); + $fixtureGroup = $fixture->getGroup()->value; + $output->writeln('installing ' . $fixtureClass . ' group:' . $fixtureGroup . ''); + $fixture->install($context); + } + $output->writeln('finished installing fixtures'); + + return Command::SUCCESS; + } +} diff --git a/shopware/Component/Fixture/FixtureGroup.php b/shopware/Component/Fixture/FixtureGroup.php new file mode 100644 index 000000000..61d89cc32 --- /dev/null +++ b/shopware/Component/Fixture/FixtureGroup.php @@ -0,0 +1,10 @@ +> $salesChannelRepository + */ + public function __construct( + private readonly PaymentHandlerLocator $paymentHandlerLocator, + #[Autowire(service: 'sales_channel.repository')] + private readonly EntityRepository $salesChannelRepository, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::SETUP; + } + + public function install(Context $context): void + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('active', true)); + $salesChannels = $this->salesChannelRepository->search($criteria, $context)->getEntities(); + $upsertData = []; + $activePaymentMethods = $this->getActivePaymentMethods(); + foreach ($salesChannels as $salesChannel) { + $upsertData[] = [ + 'id' => $salesChannel->getId(), + 'paymentMethods' => $activePaymentMethods + ]; + } + $this->salesChannelRepository->upsert($upsertData, $context); + } + + public function uninstall(Context $context): void + { + // We dont want to unassign payment methods + } + + /** + * @return array + */ + private function getActivePaymentMethods(): array + { + $paymentHandlers = $this->paymentHandlerLocator->getPaymentMethods(); + $paypalExpressSettings = $this->settingsService->getPaypalExpressSettings(); + $result = []; + foreach ($paymentHandlers as $paymentHandler) { + if ($paymentHandler instanceof PayPalExpressPayment && ! $paypalExpressSettings->isEnabled()) { + continue; + } + $paymentMethodName = $paymentHandler->getName(); + $isDeprecatedMethod = $paymentHandler instanceof DeprecatedMethodAwareInterface; + $result[] = [ + 'id' => Uuid::fromStringToHex('mollie-payment-' . $paymentHandler->getTechnicalName()), + 'name' => $paymentMethodName, + 'translations' => [ + Defaults::LANGUAGE_SYSTEM => [ + 'name' => $paymentMethodName, + ], + ], + 'active' => $isDeprecatedMethod === false + ]; + } + + return $result; + } +} diff --git a/src/Components/Fixtures/Handler/Product/Assets/champagne.png b/shopware/Component/Fixture/Product/Assets/champagne.png similarity index 100% rename from src/Components/Fixtures/Handler/Product/Assets/champagne.png rename to shopware/Component/Fixture/Product/Assets/champagne.png diff --git a/src/Components/Fixtures/Handler/Product/Assets/sweater-black.png b/shopware/Component/Fixture/Product/Assets/sweater-black.png similarity index 100% rename from src/Components/Fixtures/Handler/Product/Assets/sweater-black.png rename to shopware/Component/Fixture/Product/Assets/sweater-black.png diff --git a/src/Components/Fixtures/Handler/Product/Assets/tshirt-black-fail.png b/shopware/Component/Fixture/Product/Assets/tshirt-black-fail.png similarity index 100% rename from src/Components/Fixtures/Handler/Product/Assets/tshirt-black-fail.png rename to shopware/Component/Fixture/Product/Assets/tshirt-black-fail.png diff --git a/src/Components/Fixtures/Handler/Product/Assets/tshirt-black.png b/shopware/Component/Fixture/Product/Assets/tshirt-black.png similarity index 100% rename from src/Components/Fixtures/Handler/Product/Assets/tshirt-black.png rename to shopware/Component/Fixture/Product/Assets/tshirt-black.png diff --git a/src/Components/Fixtures/Handler/Product/Assets/tshirt-white.png b/shopware/Component/Fixture/Product/Assets/tshirt-white.png similarity index 100% rename from src/Components/Fixtures/Handler/Product/Assets/tshirt-white.png rename to shopware/Component/Fixture/Product/Assets/tshirt-white.png diff --git a/shopware/Component/Fixture/Product/CreditCardFailureProductsFixture.php b/shopware/Component/Fixture/Product/CreditCardFailureProductsFixture.php new file mode 100644 index 000000000..fb867e2fd --- /dev/null +++ b/shopware/Component/Fixture/Product/CreditCardFailureProductsFixture.php @@ -0,0 +1,78 @@ +> $productRepository + */ + public function __construct( + private FileFetcher $fileFetcher, + private MediaService $mediaService, + #[Autowire(service: 'product.repository')] + private readonly EntityRepository $productRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $image = 'tshirt-black-fail.png'; + $mediaIds = $this->getMediaMapping([$image], $context); + $salesChannelId = $this->getSalesChannelId($context); + $mediaId = $mediaIds[$image]; + $category = MollieCategoriesFixture::CATEGORY_CREDIT_CARD_ERRORS; + $description = 'Mollie Product for testing purpose in development environment. Use "failed" on the Mollie Payment Sandbox page to force the special error reason of this product.'; + + $productData = []; + $productData[] = $this->getProductData('Invalid Card Number', 'MOL_ERROR_1', $description, $mediaId, $category, $salesChannelId, 1001.00); + $productData[] = $this->getProductData('Invalid CVV', 'MOL_ERROR_2', $description, $mediaId, $category, $salesChannelId, 1002.00); + $productData[] = $this->getProductData('Invalid Card Holder Name', 'MOL_ERROR_3', $description, $mediaId, $category, $salesChannelId, 1003.00); + $productData[] = $this->getProductData('Card Expired', 'MOL_ERROR_4', $description, $mediaId, $category, $salesChannelId, 1004.00); + $productData[] = $this->getProductData('Invalid Card Type', 'MOL_ERROR_5', $description, $mediaId, $category, $salesChannelId, 1005.00); + $productData[] = $this->getProductData('Refused by Issuer', 'MOL_ERROR_6', $description, $mediaId, $category, $salesChannelId, 1006.00); + $productData[] = $this->getProductData('Insufficient Funds', 'MOL_ERROR_7', $description, $mediaId, $category, $salesChannelId, 1007.00); + $productData[] = $this->getProductData('Inactive Card', 'MOL_ERROR_8', $description, $mediaId, $category, $salesChannelId, 1008.00); + $productData[] = $this->getProductData('Possible Fraud', 'MOL_ERROR_9', $description, $mediaId, $category, $salesChannelId, 1009.00); + $productData[] = $this->getProductData('Authentication Failed', 'MOL_ERROR_10', $description, $mediaId, $category, $salesChannelId, 1010.00); + $productData[] = $this->getProductData('Card Declined', 'MOL_ERROR_11', $description, $mediaId, $category, $salesChannelId, 1011.00); + + $this->productRepository->upsert($productData, $context); + } + + public function uninstall(Context $context): void + { + $productData = []; + for ($i = 1; $i <= 11; ++$i) { + $productData[] = [ + 'id' => $this->getProductId('MOL_ERROR_' . $i) + ]; + } + + $this->productRepository->delete($productData, $context); + } +} diff --git a/shopware/Component/Fixture/Product/ProductTrait.php b/shopware/Component/Fixture/Product/ProductTrait.php new file mode 100644 index 000000000..a1b9f9ceb --- /dev/null +++ b/shopware/Component/Fixture/Product/ProductTrait.php @@ -0,0 +1,147 @@ + $customFields + * @param array $options + * + * @return array + */ + private function getProductData(string $name, string $productNumber, string $description, string $mediaId, string $category, string $salesChannelId, float $price, float $taxRate = 19.0, int $stock = 10, bool $shippingFree = false, ?string $parentId = null, array $customFields = [], array $options = []): array + { + $productId = $this->getProductId($productNumber); + $parts = explode('.', (string) $price); + $decimals = isset($parts[1]) ? strlen($parts[1]) : 0; + + $netPrice = round($price / (1 + $taxRate / 100), $decimals); + $productMediaId = Uuid::fromStringToHex(sprintf('%s-%s', $productId, $mediaId)); + $variantListingConfig = []; + $configuratorSettings = []; + if ($parentId === null && count($options) > 0) { + $variantListingConfig = [ + 'displayParent' => true + ]; + foreach ($options as $option) { + $configuratorSettings[] = [ + 'id' => Uuid::fromStringToHex(sprintf('%s-%s', $productId, $option['id'])), + 'option' => $option, + ]; + } + } + + return [ + 'id' => $productId, + 'name' => $name, + 'parentId' => $parentId, + 'taxId' => Uuid::fromStringToHex('tax-' . $taxRate), + 'productNumber' => $productNumber, + 'description' => $description, + 'visibilities' => [ + [ + 'id' => Uuid::fromStringToHex(sprintf('%s-%s', $productId, $salesChannelId)), + 'salesChannelId' => $salesChannelId, + 'visibility' => 30, + ] + ], + 'categories' => [ + [ + 'id' => Uuid::fromStringToHex('mollie-' . $category), + ] + ], + 'stock' => $stock, + 'price' => [ + [ + 'currencyId' => Defaults::CURRENCY, + 'gross' => $price, + 'net' => $netPrice, + 'linked' => true, + ] + ], + 'media' => [ + [ + 'id' => $productMediaId, + 'mediaId' => $mediaId, + ] + ], + 'coverId' => $productMediaId, + 'customFields' => $customFields, + 'shippingFree' => $shippingFree, + 'options' => $options, + 'properties' => $options, + 'variantListingConfig' => $variantListingConfig, + 'configuratorSettings' => $configuratorSettings, + 'manufacturer' => [ + 'id' => Uuid::fromStringToHex('mollie-manufacturer'), + 'name' => 'Mollie', + ] + ]; + } + + /** + * @param array $images + * + * @throws \Psr\Container\ContainerExceptionInterface + * @throws \Psr\Container\NotFoundExceptionInterface + * + * @return array + */ + private function getMediaMapping(array $images, Context $context): array + { + $criteria = new Criteria(); + $criteriaImages = array_map(function ($image) { + $extension = pathinfo($image, PATHINFO_EXTENSION); + + return str_replace('.' . $extension, '', $image); + }, $images); + + $criteria->addFilter(new EqualsAnyFilter('fileName', $criteriaImages)); + $mediaRepository = $this->container->get('media.repository'); + $searchResult = $mediaRepository->search($criteria, $context); + $requestedImages = array_flip($images); + + $result = []; + /** @var MediaEntity $media */ + foreach ($searchResult as $media) { + $key = sprintf('%s.%s', $media->getFileName(), $media->getFileExtension()); + + $result[$key] = $media->getId(); + unset($requestedImages[$key]); + } + + foreach ($requestedImages as $image => $number) { + $filePath = __DIR__ . '/Assets/' . $image; + $fileContent = file_get_contents($filePath); + if ($fileContent === false) { + continue; + } + + $fileInfo = new \finfo(); + $contentType = (string) $fileInfo->file($filePath, FILEINFO_MIME_TYPE); + $extension = (string) $fileInfo->file($filePath, FILEINFO_EXTENSION); + $fileName = str_replace('.' . $extension, '', $image); + + $mediaFile = $this->fileFetcher->fetchBlob($fileContent, $extension, $contentType); + $mediaId = $this->mediaService->saveMediaFile($mediaFile, $fileName, $context, 'product', null, false); + $result[$image] = $mediaId; + unset($requestedImages[$image]); + } + + return $result; + } +} diff --git a/shopware/Component/Fixture/Product/RegularProductsFixture.php b/shopware/Component/Fixture/Product/RegularProductsFixture.php new file mode 100644 index 000000000..3945fdf73 --- /dev/null +++ b/shopware/Component/Fixture/Product/RegularProductsFixture.php @@ -0,0 +1,70 @@ +> $productRepository + */ + public function __construct( + private FileFetcher $fileFetcher, + private MediaService $mediaService, + #[Autowire(service: 'product.repository')] + private readonly EntityRepository $productRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $image = 'tshirt-black.png'; + $mediaIds = $this->getMediaMapping([$image], $context); + $salesChannelId = $this->getSalesChannelId($context); + $mediaId = $mediaIds[$image]; + $category = MollieCategoriesFixture::CATEGORY_REGULAR; + $description = 'Mollie Product for testing purpose in development environment. You can use this products for LIVE tests or other scenarios'; + + $productData = []; + $productData[] = $this->getProductData('Cheap Mollie Shirt', 'MOL_CHEAP', $description, $mediaId, $category, $salesChannelId, 1); + $productData[] = $this->getProductData('Regular Mollie Shirt', 'MOL_REGULAR', $description, $mediaId, $category, $salesChannelId, 29.90); + $productData[] = $this->getProductData('Reduced Tax Rate Mollie Shirt', 'MOL_REDUCED_TAX', $description, $mediaId, $category, $salesChannelId, 19.90, 7.00); + $productData[] = $this->getProductData('Tax Free Mollie Shirt', 'MOL_TAX_FREE', $description, $mediaId, $category, $salesChannelId, 19.90, 0.00); + + $this->productRepository->upsert($productData, $context); + } + + public function uninstall(Context $context): void + { + $productData = [ + ['id' => $this->getProductId('MOL_CHEAP')], + ['id' => $this->getProductId('MOL_REGULAR')], + ['id' => $this->getProductId('MOL_REDUCED_TAX')], + ['id' => $this->getProductId('MOL_TAX_FREE')], + ]; + $this->productRepository->delete($productData, $context); + } +} diff --git a/shopware/Component/Fixture/Product/RoundingProductsFixture.php b/shopware/Component/Fixture/Product/RoundingProductsFixture.php new file mode 100644 index 000000000..c1f6d6f48 --- /dev/null +++ b/shopware/Component/Fixture/Product/RoundingProductsFixture.php @@ -0,0 +1,68 @@ +> $productRepository + */ + public function __construct( + private FileFetcher $fileFetcher, + private MediaService $mediaService, + #[Autowire(service: 'product.repository')] + private readonly EntityRepository $productRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $image = 'tshirt-white.png'; + $mediaIds = $this->getMediaMapping([$image], $context); + $salesChannelId = $this->getSalesChannelId($context); + $mediaId = $mediaIds[$image]; + $category = MollieCategoriesFixture::CATEGORY_ROUNDING; + $description = 'Product to test rounding issues.'; + + $productData = []; + $productData[] = $this->getProductData('Product A 4 Decimals', 'MOL_ROUNDING_1', $description, $mediaId, $category, $salesChannelId, 2.7336); + $productData[] = $this->getProductData('Product B 4 Decimals', 'MOL_ROUNDING_2', $description, $mediaId, $category, $salesChannelId, 2.9334); + $productData[] = $this->getProductData('Product C 4 Decimals', 'MOL_ROUNDING_3', $description, $mediaId, $category, $salesChannelId, 1.6494); + + $this->productRepository->upsert($productData, $context); + } + + public function uninstall(Context $context): void + { + $productData = [ + ['id' => $this->getProductId('MOL_ROUNDING_1')], + ['id' => $this->getProductId('MOL_ROUNDING_2')], + ['id' => $this->getProductId('MOL_ROUNDING_3')], + ]; + $this->productRepository->delete($productData, $context); + } +} diff --git a/shopware/Component/Fixture/Product/SubscriptionProductsFixture.php b/shopware/Component/Fixture/Product/SubscriptionProductsFixture.php new file mode 100644 index 000000000..207f2da6f --- /dev/null +++ b/shopware/Component/Fixture/Product/SubscriptionProductsFixture.php @@ -0,0 +1,174 @@ +> $productRepository + * @param EntityRepository> $propertyGroupRepository + */ + public function __construct( + private FileFetcher $fileFetcher, + private MediaService $mediaService, + #[Autowire(service: 'product.repository')] + private readonly EntityRepository $productRepository, + #[Autowire(service: 'property_group.repository')] + private readonly EntityRepository $propertyGroupRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $image = 'champagne.png'; + $mediaIds = $this->getMediaMapping([$image], $context); + $salesChannelId = $this->getSalesChannelId($context); + + $mediaId = $mediaIds[$image]; + $category = MollieCategoriesFixture::CATEGORY_SUBSCRIPTIONS; + $description = 'Mollie Subscription Product for testing purpose in development environment.'; + + $customFieldsDaily = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => 'days' + ]; + + $customFieldsWeekly = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => 'weeks' + ]; + $customFieldsMonthly = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => 'months' + ]; + + $customFieldsThreeWeekly = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 3, + 'mollie_payments_product_subscription_interval_unit' => 'weeks' + ]; + $customFieldsDailyRepetition = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => 'days', + 'mollie_payments_product_subscription_repetition' => '10' + ]; + $parentId = $this->getProductId('MOL_SUB_6'); + $options = $this->getSubscriptionOptions(); + + $productData = []; + $productData[] = $this->getProductData('Subscription (1x Daily)', 'MOL_SUB_1', $description, $mediaId, $category, $salesChannelId, 19.00, customFields: $customFieldsDaily); + $productData[] = $this->getProductData('Subscription (1x Weekly)', 'MOL_SUB_2', $description, $mediaId, $category, $salesChannelId, 29.00, customFields: $customFieldsWeekly); + $productData[] = $this->getProductData('Subscription (3x Weekly)', 'MOL_SUB_3', $description, $mediaId, $category, $salesChannelId, 29.00, customFields: $customFieldsThreeWeekly); + $productData[] = $this->getProductData('Subscription (1x Monthly)', 'MOL_SUB_4', $description, $mediaId, $category, $salesChannelId, 19.90, customFields: $customFieldsMonthly); + $productData[] = $this->getProductData('Subscription (1x Daily, 10 Times)', 'MOL_SUB_5', $description, $mediaId, $category, $salesChannelId, 19.90, customFields: $customFieldsDailyRepetition); + $productData[] = $this->getProductData('Subscription Variant', 'MOL_SUB_6', $description, $mediaId, $category, $salesChannelId, 19.90, options: $options); + + $productData[] = $this->getProductData('Regular Child', 'MOL_SUB_6.1', $description, $mediaId, $category, $salesChannelId, 19.90, parentId: $parentId, options: [['id' => $this->getOptionId('regular')]]); + $productData[] = $this->getProductData('Daily Child', 'MOL_SUB_6.2', $description, $mediaId, $category, $salesChannelId, 10.99, parentId: $parentId, customFields: $customFieldsDaily, options: [['id' => $this->getOptionId('daily')]]); + $productData[] = $this->getProductData('Weekly Child', 'MOL_SUB_6.3', $description, $mediaId, $category, $salesChannelId, 8.99, parentId: $parentId, customFields: $customFieldsWeekly, options: [['id' => $this->getOptionId('weekly')]]); + $productData[] = $this->getProductData('Monthly Child', 'MOL_SUB_6.4', $description, $mediaId, $category, $salesChannelId, 5.99, parentId: $parentId, customFields: $customFieldsMonthly, options: [['id' => $this->getOptionId('monthly')]]); + + $this->productRepository->upsert($productData, $context); + } + + public function uninstall(Context $context): void + { + $productData = [ + ['id' => $this->getProductId('MOL_SUB_1')], + ['id' => $this->getProductId('MOL_SUB_2')], + ['id' => $this->getProductId('MOL_SUB_3')], + ['id' => $this->getProductId('MOL_SUB_4')], + ['id' => $this->getProductId('MOL_SUB_5')], + ['id' => $this->getProductId('MOL_SUB_6')], + ['id' => $this->getProductId('MOL_SUB_6.1')], + ['id' => $this->getProductId('MOL_SUB_6.2')], + ['id' => $this->getProductId('MOL_SUB_6.3')], + ['id' => $this->getProductId('MOL_SUB_6.4')], + ]; + $this->productRepository->delete($productData, $context); + + $propertyGroups = [ + ['id' => $this->getOptionId('subscriptions')], + ]; + + $this->propertyGroupRepository->delete($propertyGroups, $context); + } + + /** + * @return array + */ + private function getSubscriptionOptions(): array + { + $subscriptionGroup = [ + 'id' => $this->getOptionId('subscriptions'), + 'name' => 'Subscription Interval', + 'filterable' => true, + 'visibleOnProductDetailPage' => true, + 'displayType' => 'text', + 'sortingType' => 'position' + ]; + + return [ + [ + 'id' => $this->getOptionId('regular'), + 'name' => 'Regular', + 'position' => 1, + 'group' => $subscriptionGroup + ], + [ + 'id' => $this->getOptionId('daily'), + 'name' => 'Daily', + 'position' => 2, + 'group' => $subscriptionGroup + ], + [ + 'id' => $this->getOptionId('weekly'), + 'name' => 'Weekly', + 'position' => 3, + 'group' => $subscriptionGroup + ], + [ + 'id' => $this->getOptionId('monthly'), + 'name' => 'Monthly', + 'position' => 4, + 'group' => $subscriptionGroup + ] + ]; + } + + private function getOptionId(string $optionName): string + { + return Uuid::fromStringToHex('mollie-option-' . $optionName); + } +} diff --git a/shopware/Component/Fixture/Product/VoucherProductsFixture.php b/shopware/Component/Fixture/Product/VoucherProductsFixture.php new file mode 100644 index 000000000..134926452 --- /dev/null +++ b/shopware/Component/Fixture/Product/VoucherProductsFixture.php @@ -0,0 +1,85 @@ +> $productRepository + */ + public function __construct( + private FileFetcher $fileFetcher, + private MediaService $mediaService, + #[Autowire(service: 'product.repository')] + private readonly EntityRepository $productRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $mediaIds = $this->getMediaMapping(['tshirt-white.png', 'champagne.png'], $context); + $salesChannelId = $this->getSalesChannelId($context); + + $category = MollieCategoriesFixture::CATEGORY_VOUCHER; + + $description = 'Mollie Voucher Product for testing purpose in development environment.'; + + $customFieldsEco = [ + 'mollie_payments_product_voucher_type' => 1, + ]; + + $customFieldsMeal = [ + 'mollie_payments_product_voucher_type' => 2, + ]; + + $customFieldsGift = [ + 'mollie_payments_product_voucher_type' => 3, + ]; + $customFieldsAll = [ + 'mollie_payments_product_voucher_type' => [1, 2, 3], + ]; + + $productData = []; + $productData[] = $this->getProductData('Voucher ECO', 'MOL_VOUCHER_1', $description, $mediaIds['tshirt-white.png'], $category, $salesChannelId, 19.00, customFields: $customFieldsEco); + $productData[] = $this->getProductData('Voucher MEAL', 'MOL_VOUCHER_2', $description, $mediaIds['champagne.png'], $category, $salesChannelId, 19.00, customFields: $customFieldsMeal); + $productData[] = $this->getProductData('Voucher GIFT', 'MOL_VOUCHER_3', $description, $mediaIds['tshirt-white.png'], $category, $salesChannelId, 19.00, customFields: $customFieldsGift); + $productData[] = $this->getProductData('Voucher ALL', 'MOL_VOUCHER_4', $description, $mediaIds['champagne.png'], $category, $salesChannelId, 19.00, customFields: $customFieldsAll); + + $this->productRepository->upsert($productData, $context); + } + + public function uninstall(Context $context): void + { + $productData = [ + ['id' => $this->getProductId('MOL_VOUCHER_1')], + ['id' => $this->getProductId('MOL_VOUCHER_2')], + ['id' => $this->getProductId('MOL_VOUCHER_3')], + ['id' => $this->getProductId('MOL_VOUCHER_4')], + ]; + $this->productRepository->delete($productData, $context); + } +} diff --git a/shopware/Component/Fixture/SalesChannelTrait.php b/shopware/Component/Fixture/SalesChannelTrait.php new file mode 100644 index 000000000..2c62dda49 --- /dev/null +++ b/shopware/Component/Fixture/SalesChannelTrait.php @@ -0,0 +1,28 @@ +addFilter(new EqualsFilter('type.name', 'Storefront')); + $criteria->addFilter(new EqualsFilter('active', true)); + $criteria->setLimit(1); + + /** @var EntityRepository> $salesChannelRepository */ + $salesChannelRepository = $this->container->get('sales_channel.repository'); + $searchResult = $salesChannelRepository->searchIds($criteria, $context); + + return (string) $searchResult->firstId(); + } +} diff --git a/shopware/Component/Fixture/Shipping/ShippingMethodFixture.php b/shopware/Component/Fixture/Shipping/ShippingMethodFixture.php new file mode 100644 index 000000000..c4659519a --- /dev/null +++ b/shopware/Component/Fixture/Shipping/ShippingMethodFixture.php @@ -0,0 +1,115 @@ +> $shippingMethodRepository + * @param EntityRepository> $ruleRepository + * @param EntityRepository> $deliveryTimeRepository + */ + public function __construct( + #[Autowire(service: 'shipping_method.repository')] + private readonly EntityRepository $shippingMethodRepository, + #[Autowire(service: 'rule.repository')] + private readonly EntityRepository $ruleRepository, + #[Autowire(service: 'delivery_time.repository')] + private readonly EntityRepository $deliveryTimeRepository, + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $price = 4.99; + $taxRate = 19; + $netPrice = round($price / (1 + $taxRate / 100), 2); + $data = [ + 'id' => Uuid::fromStringToHex('mollie-shipping-method'), + 'name' => 'Mollie Test Shipment', + 'active' => true, + 'trackingUrl' => 'https://www.carrier.com/de/tracking/%s', + 'technicalName' => 'mollie_fixture_shipment', + 'taxId' => Uuid::fromStringToHex('tax-' . $taxRate), + 'availabilityRule' => [ + 'id' => Uuid::fromStringToHex('mollie-always-valid-rule'), + 'name' => 'Always valid', + 'priority' => 100, + 'conditions' => [ + [ + 'id' => Uuid::fromStringToHex('mollie-always-valid-condition'), + 'type' => 'alwaysValid', + 'position' => 1, + ] + ] + ], + 'deliveryTime' => [ + 'id' => Uuid::fromStringToHex('mollie-delivery-time'), + 'name' => '1-3 days', + 'min' => 1, + 'max' => 3, + 'unit' => 'day', + ], + 'prices' => [ + [ + 'id' => Uuid::fromStringToHex('price-' . $price), + 'calculation' => 2, + 'quantityStart' => 0, + 'currencyPrice' => [ + [ + 'currencyId' => Defaults::CURRENCY, + 'net' => $netPrice, + 'gross' => 4.99, + 'linked' => true + ] + ] + ] + ], + ]; + $this->shippingMethodRepository->upsert([$data], $context); + } + + public function uninstall(Context $context): void + { + $shippingMethods = [ + [ + 'id' => Uuid::fromStringToHex('mollie-shipping-method'), + ] + ]; + $this->shippingMethodRepository->delete($shippingMethods, $context); + + $rules = [ + [ + 'id' => Uuid::fromStringToHex('mollie-always-valid-rule'), + ] + ]; + $this->ruleRepository->delete($rules, $context); + + $deliveryTimes = [ + [ + 'id' => Uuid::fromStringToHex('mollie-delivery-time'), + ] + ]; + $this->deliveryTimeRepository->delete($deliveryTimes, $context); + } +} diff --git a/shopware/Component/Fixture/Tax/TaxFixture.php b/shopware/Component/Fixture/Tax/TaxFixture.php new file mode 100644 index 000000000..f9f8f331e --- /dev/null +++ b/shopware/Component/Fixture/Tax/TaxFixture.php @@ -0,0 +1,66 @@ +> $taxRepository + */ + public function __construct( + #[Autowire(service: 'tax.repository')] + private readonly EntityRepository $taxRepository, + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function getPriority(): int + { + return 100; + } + + public function install(Context $context): void + { + $upsertData = []; + $upsertData[] = $this->getTaxData('Standard tax rate (19%)', 19); + $upsertData[] = $this->getTaxData('Reduced tax rate (7%)', 7); + $upsertData[] = $this->getTaxData('Free tax rate (0%)', 0); + $this->taxRepository->upsert($upsertData, $context); + } + + public function uninstall(Context $context): void + { + $taxes = [ + ['id' => Uuid::fromStringToHex('tax-19')], + ['id' => Uuid::fromStringToHex('tax-7')], + ['id' => Uuid::fromStringToHex('tax-0')], + ]; + $this->taxRepository->delete($taxes, $context); + } + + /** + * @return array + */ + private function getTaxData(string $name, int $taxRate): array + { + return [ + 'id' => Uuid::fromStringToHex('tax-' . $taxRate), + 'taxRate' => $taxRate, + 'name' => $name, + ]; + } +} diff --git a/shopware/Component/Fixture/Voucher/VoucherFixture.php b/shopware/Component/Fixture/Voucher/VoucherFixture.php new file mode 100644 index 000000000..117fe15ec --- /dev/null +++ b/shopware/Component/Fixture/Voucher/VoucherFixture.php @@ -0,0 +1,94 @@ +> $promotionRepository + */ + public function __construct( + #[Autowire(service: 'promotion.repository')] + private readonly EntityRepository $promotionRepository, + #[Autowire(service: 'service_container')] + private readonly ContainerInterface $container + ) { + } + + public function getGroup(): FixtureGroup + { + return FixtureGroup::DATA; + } + + public function install(Context $context): void + { + $salesChannelId = $this->getSalesChannelId($context); + $promotions = []; + $promotions[] = $this->getPromotionData('Mollie test: 5 euro', 'mollie_5', 5.00, $salesChannelId); + $promotions[] = $this->getPromotionData('Mollie test: 50 percent', 'mollie_50', 50.00, $salesChannelId, type: 'percentage'); + $promotions[] = $this->getPromotionData('Mollie test: free shipping', 'mollie_free_shipping', 100.00, $salesChannelId, 'delivery', 'percentage'); + $promotions[] = $this->getPromotionData('Mollie test: reduced shipping', 'mollie_shipping', 2.00, $salesChannelId, 'delivery'); + + $this->promotionRepository->upsert($promotions, $context); + } + + public function uninstall(Context $context): void + { + $promotions = [ + ['id' => $this->getId('mollie_5')], + ['id' => $this->getId('mollie_50')], + ['id' => $this->getId('mollie_free_shipping')], + ['id' => $this->getId('mollie_shipping')], + ]; + $this->promotionRepository->delete($promotions, $context); + } + + private function getId(string $code): string + { + return Uuid::fromStringToHex('mollie-promotion-' . $code); + } + + /** + * @return array + */ + private function getPromotionData(string $name, string $code, float $value, string $salesChannelId, string $scope = 'cart', string $type = 'absolute'): array + { + return [ + 'id' => $this->getId($code), + 'name' => $name, + 'priority' => 1, + 'exclusive' => false, + 'useCodes' => true, + 'code' => $code, + 'salesChannels' => [ + [ + 'salesChannelId' => $salesChannelId, + 'priority' => 1 + ] + ], + 'discounts' => [ + [ + 'id' => Uuid::fromStringToHex('promotion-discount-' . $code), + 'scope' => $scope, + 'type' => $type, + 'value' => $value + ] + ], + 'active' => true, + ]; + } +} diff --git a/shopware/Component/FlowBuilder/Event/EventData/PaymentType.php b/shopware/Component/FlowBuilder/Event/EventData/PaymentType.php new file mode 100644 index 000000000..5cec295aa --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/EventData/PaymentType.php @@ -0,0 +1,31 @@ + + */ + private array $data; + + public function __construct() + { + $this->data = [ + 'id' => 'tr_123456', + 'status' => 'paid' + ]; + } + + public function toArray(): array + { + return [ + 'type' => self::TYPE, + 'data' => $this->data, + ]; + } +} diff --git a/shopware/Component/FlowBuilder/Event/MolliePaymentAware.php b/shopware/Component/FlowBuilder/Event/MolliePaymentAware.php new file mode 100644 index 000000000..5aba882fb --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/MolliePaymentAware.php @@ -0,0 +1,15 @@ +add('customer', new EntityType(CustomerDefinition::class)) + ->add('order', new EntityType(OrderDefinition::class)) + ->add('payment', new PaymentType()) + ; + } + + public function getPaymentId(): string + { + return $this->payment->getId(); + } + + public function getCustomerId(): string + { + return $this->customer->getId(); + } + + public function getOrderId(): string + { + return $this->order->getId(); + } + + public function getSalesChannelId(): string + { + return $this->order->getSalesChannelId(); + } + + public function getPayment(): Payment + { + return $this->payment; + } + + public function getOrder(): OrderEntity + { + return $this->order; + } + + public function getCustomer(): CustomerEntity + { + return $this->customer; + } + + public function getContext(): Context + { + return $this->context; + } + + public function getMailStruct(): MailRecipientStruct + { + $customerFullName = $this->customer->getFirstName() . ' ' . $this->customer->getLastName(); + + return new MailRecipientStruct([ + $this->customer->getEmail() => $customerFullName, + ]); + } +} diff --git a/shopware/Component/FlowBuilder/Event/Payment/CancelledEvent.php b/shopware/Component/FlowBuilder/Event/Payment/CancelledEvent.php new file mode 100644 index 000000000..7054fdbce --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Payment/CancelledEvent.php @@ -0,0 +1,14 @@ +add('order', new EntityType(OrderDefinition::class)) + ->add('payment', new PaymentType()) + ; + } + + public function getName(): string + { + return 'mollie.webhook_received.' . self::getStatus(); + } + + public function getMailStruct(): MailRecipientStruct + { + $customer = $this->order->getOrderCustomer(); + if ($customer === null) { + return new MailRecipientStruct([]); + } + + $customerFullName = $customer->getFirstName() . ' ' . $customer->getLastName(); + + return new MailRecipientStruct([ + $customer->getEmail() => $customerFullName, + ]); + } + + public function getSalesChannelId(): string + { + return $this->order->getSalesChannelId(); + } + + public function getPayment(): Payment + { + return $this->payment; + } + + public function getPaymentId(): string + { + return $this->payment->getId(); + } + + public function getOrderId(): string + { + return $this->order->getId(); + } + + public function getContext(): Context + { + return $this->context; + } + + public function getOrder(): OrderEntity + { + return $this->order; + } + + protected static function getStatus(): string + { + return 'all'; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusAuthorizedEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusAuthorizedEvent.php new file mode 100644 index 000000000..d1b62ec8c --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusAuthorizedEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusCancelledEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusCancelledEvent.php new file mode 100644 index 000000000..a9f55f44b --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusCancelledEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusExpiredEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusExpiredEvent.php new file mode 100644 index 000000000..67b7de651 --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusExpiredEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusFailedEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusFailedEvent.php new file mode 100644 index 000000000..a1ddd4707 --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusFailedEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusOpenEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusOpenEvent.php new file mode 100644 index 000000000..74f64a9d0 --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusOpenEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPaidEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPaidEvent.php new file mode 100644 index 000000000..ae6b14c8f --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPaidEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPendingEvent.php b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPendingEvent.php new file mode 100644 index 000000000..ee4f7972c --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/Webhook/WebhookStatusPendingEvent.php @@ -0,0 +1,14 @@ +value; + } +} diff --git a/shopware/Component/FlowBuilder/Event/WebhookReceivedEvent.php b/shopware/Component/FlowBuilder/Event/WebhookReceivedEvent.php new file mode 100644 index 000000000..dd5db7a19 --- /dev/null +++ b/shopware/Component/FlowBuilder/Event/WebhookReceivedEvent.php @@ -0,0 +1,8 @@ +getPayment(); + + return $stored; + } + + public function restore(StorableFlow $storable): void + { + if (! $storable->hasStore(MolliePaymentAware::PAYMENT_STORAGE_KEY)) { + return; + } + $storable->setData(MolliePaymentAware::PAYMENT_STORAGE_KEY, $storable->getStore(MolliePaymentAware::PAYMENT_STORAGE_KEY)); + } +} diff --git a/shopware/Component/FlowBuilder/Subscriber/BusinessEventSubscriber.php b/shopware/Component/FlowBuilder/Subscriber/BusinessEventSubscriber.php new file mode 100644 index 000000000..512589a69 --- /dev/null +++ b/shopware/Component/FlowBuilder/Subscriber/BusinessEventSubscriber.php @@ -0,0 +1,54 @@ + ['addEvents', 1000], + ]; + } + + public function addEvents(BusinessEventCollectorEvent $eventCollectorEvent): void + { + $collection = $eventCollectorEvent->getCollection(); + $flowEventList = $this->flowEventList; + $flowEventList = array_merge($flowEventList, PaymentStatus::getAllWebhookEvents()); + $flowEventList = array_merge($flowEventList, $this->subscriptionActionHandler->getActionEvents()); + + foreach ($flowEventList as $className) { + $definition = $this->businessEventCollector->define($className); + if (! $definition) { + continue; + } + $collection->set($definition->getName(), $definition); + } + } +} diff --git a/shopware/Component/Logger/CleanUpLoggerScheduledTask.php b/shopware/Component/Logger/CleanUpLoggerScheduledTask.php new file mode 100644 index 000000000..5c0a7040b --- /dev/null +++ b/shopware/Component/Logger/CleanUpLoggerScheduledTask.php @@ -0,0 +1,21 @@ +> $scheduledTaskRepository + */ + public function __construct( + #[Autowire(service: 'scheduled_task.repository')] + EntityRepository $scheduledTaskRepository, + #[Autowire(value: '%kernel.logs_dir%')] + private string $logDir, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + parent::__construct($scheduledTaskRepository, $logger); + } + + public function run(): void + { + $loggerSettings = $this->settingsService->getLoggerSettings(); + $logFileDays = $loggerSettings->getLogFileDays(); + $mollieLogDir = $this->logDir . '/mollie'; + if (! is_dir($mollieLogDir)) { + return; + } + try { + $daysToKeep = $logFileDays; + $cutoffTime = time() - ($daysToKeep * 24 * 60 * 60); + + $deletedCount = 0; + $handle = opendir($mollieLogDir); + + if ($handle === false) { + $this->logger->warning('Could not open mollie log directory', ['dir' => $mollieLogDir]); + + return; + } + + while (($file = readdir($handle)) !== false) { + if ($deletedCount >= self::MAX_DELETE_PER_RUN) { + break; + } + + if (! str_starts_with($file, 'order-') || ! str_ends_with($file, '.log')) { + continue; + } + + $logFile = $mollieLogDir . '/' . $file; + + if (! is_file($logFile)) { + continue; + } + + if (filemtime($logFile) < $cutoffTime) { + try { + unlink($logFile); + ++$deletedCount; + } catch (\Throwable $e) { + $this->logger->warning('Could not delete log file: ' . $file, [ + 'error' => $e->getMessage(), + ]); + } + } + } + + closedir($handle); + + $this->logger->debug('Cleanup logger task executed', [ + 'filesDeleted' => $deletedCount, + 'daysToKeep' => $daysToKeep, + 'maxPerRun' => self::MAX_DELETE_PER_RUN, + ]); + } catch (\Throwable $e) { + $this->logger->error('Error in cleanup logger task: ' . $e->getMessage()); + } + } + + /** + * @return iterable + */ + public static function getHandledMessages(): iterable + { + return [ + CleanUpLoggerScheduledTask::class, + ]; + } +} diff --git a/shopware/Component/Logger/OrderFileHandler.php b/shopware/Component/Logger/OrderFileHandler.php new file mode 100644 index 000000000..026bb9a57 --- /dev/null +++ b/shopware/Component/Logger/OrderFileHandler.php @@ -0,0 +1,52 @@ +logDir = $logDir; + } + + public function handle(LogRecord $record): bool + { + $orderNumber = $record->context['orderNumber'] ?? null; + + if ($orderNumber === null) { + return false; + } + + $orderNumber = (string) $orderNumber; + + $mollieLogDir = $this->logDir . '/mollie'; + if (! is_dir($mollieLogDir)) { + mkdir($mollieLogDir, 0755, true); + } + + $orderLogPath = $mollieLogDir . '/order-' . $orderNumber . '.log'; + + try { + $handler = new StreamHandler($orderLogPath, LogLevel::DEBUG); + $handler->handle($record); + } catch (\Exception $e) { + return false; + } + + return $record->level->value < Level::Warning->value; + } +} diff --git a/shopware/Component/Logger/PluginSettingsHandler.php b/shopware/Component/Logger/PluginSettingsHandler.php index b995cbe3a..e0c4c17a9 100644 --- a/shopware/Component/Logger/PluginSettingsHandler.php +++ b/shopware/Component/Logger/PluginSettingsHandler.php @@ -5,10 +5,12 @@ use Doctrine\DBAL\Connection; use Mollie\Shopware\Component\Settings\AbstractSettingsService; +use Mollie\Shopware\Component\Settings\SettingsService; use Monolog\Handler\AbstractHandler; use Monolog\Handler\RotatingFileHandler; use Monolog\LogRecord; use Psr\Log\LogLevel; +use Symfony\Component\DependencyInjection\Attribute\Autowire; final class PluginSettingsHandler extends AbstractHandler { @@ -20,7 +22,13 @@ final class PluginSettingsHandler extends AbstractHandler private AbstractSettingsService $settingsService; - public function __construct(AbstractSettingsService $settingsService, Connection $connection, string $filePath, bool $bubble = true) + public function __construct( + #[Autowire(service: SettingsService::class)] + AbstractSettingsService $settingsService, + Connection $connection, + #[Autowire(value: '%kernel.logs_dir%/mollie_%kernel.environment%.log')] + string $filePath, + bool $bubble = true) { parent::__construct(LogLevel::DEBUG, $bubble); $this->connection = $connection; @@ -28,12 +36,7 @@ public function __construct(AbstractSettingsService $settingsService, Connection $this->settingsService = $settingsService; } - /** - * We need to define types here because shopware 6.4 uses old monologger where LogRecord does not exists. - * - * @param array|LogRecord $record - */ - public function handle($record): bool + public function handle(LogRecord $record): bool { if ($this->isConnected() === false) { return false; diff --git a/shopware/Component/Logger/Processor/MolliePluginVersionProcessor.php b/shopware/Component/Logger/Processor/MolliePluginVersionProcessor.php new file mode 100644 index 000000000..6a52136fe --- /dev/null +++ b/shopware/Component/Logger/Processor/MolliePluginVersionProcessor.php @@ -0,0 +1,22 @@ +channel === 'mollie') { + $record->extra['pluginVersion'] = MolliePayments::PLUGIN_VERSION; + } + + return $record; + } +} diff --git a/shopware/Component/Logger/RecordAnonymizer.php b/shopware/Component/Logger/RecordAnonymizer.php index 525213f69..38b0e522e 100644 --- a/shopware/Component/Logger/RecordAnonymizer.php +++ b/shopware/Component/Logger/RecordAnonymizer.php @@ -3,36 +3,45 @@ namespace Mollie\Shopware\Component\Logger; +use Monolog\Attribute\AsMonologProcessor; use Monolog\LogRecord; use Monolog\Processor\ProcessorInterface; use Symfony\Component\HttpFoundation\IpUtils; +#[AsMonologProcessor(channel: 'mollie')] final class RecordAnonymizer implements ProcessorInterface { private const URL_SLUG = '/payment/finalize-transaction'; - /** - * We need to define types here because shopware 6.4 uses old monologger where LogRecord does not exists. - * - * @param array|LogRecord $record - * - * @return array|LogRecord - */ - public function __invoke($record) + public function __invoke(LogRecord $record): LogRecord { - /* @phpstan-ignore-next-line */ - if (isset($record['extra'])) { - if (array_key_exists('ip', $record['extra'])) { - // replace it with our anonymous IP - $record['extra']['ip'] = IpUtils::anonymize(trim($record['extra']['ip'])); - } + $recordArray = $record->toArray(); - if (array_key_exists('url', $record['extra'])) { - $record['extra']['url'] = $this->anonymize($record['extra']['url']); - } + /** @var array $extraData */ + $extraData = $recordArray['extra'] ?? []; + if (isset($extraData['ip'])) { + // replace it with our anonymous IP + $extraData['ip'] = IpUtils::anonymize(trim((string) $extraData['ip'])); } - return $record; + if (isset($extraData['url'])) { + $extraData['url'] = $this->anonymize((string) $extraData['url']); + } + $recordArray['extra'] = $extraData; + + if (isset($recordArray['context']) && is_array($recordArray['context'])) { + $recordArray['context'] = $this->maskPersonalDataInArray($recordArray['context']); + } + + return new LogRecord( + datetime: $record->datetime, + channel: $record->channel, + level: $record->level, + message: $record->message, + context: $recordArray['context'] ?? [], + extra: $recordArray['extra'] ?? [], + formatted: $record->formatted, + ); } private function anonymize(string $url): string @@ -47,4 +56,44 @@ private function anonymize(string $url): string return (string) $url; } + + /** + * @param array $data + * + * @return array + */ + private function maskPersonalDataInArray(array $data): array + { + $sensitiveFields = ['givenName', 'familyName', 'organizationName', 'email', 'phone', 'streetAndNumber', 'postalCode']; + $urlFields = ['redirectUrl', 'webhookUrl', 'cancelUrl', 'href', 'checkoutUrl', 'finalizeUrl']; + $tokenFields = ['applePayPaymentToken']; + + foreach ($data as $key => &$value) { + if (is_array($value)) { + $value = $this->maskPersonalDataInArray($value); + continue; + } + + if (in_array($key, $sensitiveFields, true)) { + $value = '**'; + continue; + } + + if (in_array($key, $urlFields, true) && is_string($value)) { + $value = preg_replace_callback( + '/(?:token|_sw_payment_token)=([a-z0-9._\-]+?)(?:\*{2})?(?=[&"]|$)/i', + fn ($m) => (strpos($m[0], '_sw_payment_token') !== false ? '_sw_payment_token=' : 'token=') . substr($m[1], 0, 2) . '**', + $value + ); + continue; + } + + if (in_array($key, $tokenFields, true)) { + $value = '**'; + } + } + unset($value); + + return $data; + } } diff --git a/shopware/Component/Logger/Resources/config/services.xml b/shopware/Component/Logger/Resources/config/services.xml index 4496ca780..4801c195d 100644 --- a/shopware/Component/Logger/Resources/config/services.xml +++ b/shopware/Component/Logger/Resources/config/services.xml @@ -6,10 +6,6 @@ - - - - @@ -17,11 +13,5 @@ - - - - - %kernel.logs_dir%/mollie_%kernel.environment%.log - \ No newline at end of file diff --git a/shopware/Component/Logger/WebhookStatusPaidEventSubscriber.php b/shopware/Component/Logger/WebhookStatusPaidEventSubscriber.php new file mode 100644 index 000000000..304504e57 --- /dev/null +++ b/shopware/Component/Logger/WebhookStatusPaidEventSubscriber.php @@ -0,0 +1,58 @@ + 'onWebhookStatusPaid', + SuccessEvent::class => 'onWebhookStatusPaid', + ]; + } + + /** + * @param SuccessEvent|WebhookStatusPaidEvent $event + */ + public function onWebhookStatusPaid(Event $event): void + { + try { + $payment = $event->getPayment(); + $successStatus = [ + PaymentStatus::PAID, + PaymentStatus::AUTHORIZED + ]; + if (! in_array($payment->getStatus(),$successStatus)) { + return; + } + $orderNumber = (string) $event->getOrder()->getOrderNumber(); + + $logFile = $this->logDir . '/mollie/order-' . $orderNumber . '.log'; + + if (file_exists($logFile)) { + unlink($logFile); + $this->logger->info('Order log file deleted on paid webhook', ['order_number' => $orderNumber]); + } + } catch (\Throwable $e) { + $this->logger->error('Error deleting order log file: ' . $e->getMessage()); + } + } +} diff --git a/shopware/Component/Mollie/Address.php b/shopware/Component/Mollie/Address.php new file mode 100644 index 000000000..5ded4f694 --- /dev/null +++ b/shopware/Component/Mollie/Address.php @@ -0,0 +1,212 @@ +email = $email; + $this->title = $title; + $this->givenName = $givenName; + $this->familyName = $familyName; + $this->streetAndNumber = $streetAndNumber; + $this->postalCode = $postalCode; + $this->city = $city; + $this->country = $country; + } + + public static function fromAddress(CustomerEntity $customer, OrderAddressEntity $orderAddress): self + { + $salutation = $customer->getSalutation(); + if ($salutation === null) { + throw new MissingSalutationException(); + } + $country = $orderAddress->getCountry(); + if ($country === null) { + throw new MissingCountryException(); + } + $address = new self($customer->getEmail(), + (string) $salutation->getDisplayName(), + $orderAddress->getFirstName(), + $orderAddress->getLastName(), + $orderAddress->getStreet(), + (string) $orderAddress->getZipcode(), + $orderAddress->getCity(), + (string) $country->getIso() + ); + + if ($orderAddress->getPhoneNumber() !== null) { + $address->setPhone($orderAddress->getPhoneNumber()); + } + $additionalAddressLines = []; + if ($orderAddress->getAdditionalAddressLine1()) { + $additionalAddressLines[] = $orderAddress->getAdditionalAddressLine1(); + } + if ($orderAddress->getAdditionalAddressLine2()) { + $additionalAddressLines[] = $orderAddress->getAdditionalAddressLine2(); + } + if (count($additionalAddressLines) > 0) { + $address->setStreetAdditional(implode(' ', $additionalAddressLines)); + } + if ($orderAddress->getCompany() !== null) { + $address->setOrganizationName($orderAddress->getCompany()); + } + + return $address; + } + + /** + * @param array $body + */ + public static function fromResponseBody(array $body): self + { + $address = new self($body['email'] ?? '', + '', + $body['givenName'] ?? '', + $body['familyName'] ?? '', + $body['streetAndNumber'] ?? '', + $body['postalCode'] ?? '', + $body['city'] ?? '', + $body['country'] ?? '' + ); + $phone = $body['phone'] ?? null; + $streetAdditional = $body['streetAdditional'] ?? null; + if ($streetAdditional !== null) { + $address->setStreetAdditional($streetAdditional); + } + if ($phone !== null) { + $address->setPhone($phone); + } + + return $address; + } + + /** + * @return array + */ + public function toRegisterFormArray(): array + { + return [ + 'firstName' => $this->givenName, + 'lastName' => $this->familyName, + 'email' => $this->email, + 'street' => $this->streetAndNumber, + 'zipcode' => $this->postalCode, + 'city' => $this->city, + ]; + } + + public function setOrganizationName(string $organizationName): void + { + $this->organizationName = $organizationName; + } + + public function setStreetAdditional(string $streetAdditional): void + { + $this->streetAdditional = $streetAdditional; + } + + public function setPhone(string $phone): void + { + $this->phone = $phone; + } + + public function getTitle(): string + { + return $this->title; + } + + public function getGivenName(): string + { + return $this->givenName; + } + + public function getFamilyName(): string + { + return $this->familyName; + } + + public function getOrganizationName(): string + { + return $this->organizationName; + } + + public function getStreetAndNumber(): string + { + return $this->streetAndNumber; + } + + public function getStreetAdditional(): string + { + return $this->streetAdditional; + } + + public function getPostalCode(): string + { + return $this->postalCode; + } + + public function getEmail(): string + { + return $this->email; + } + + public function getPhone(): string + { + return $this->phone; + } + + public function getCity(): string + { + return $this->city; + } + + public function getCountry(): string + { + return $this->country; + } + + public function getId(): string + { + $keys = [ + $this->givenName, + $this->familyName, + $this->email, + $this->streetAndNumber, + $this->streetAdditional, + $this->postalCode, + $this->city, + $this->country + ]; + if (mb_strlen($this->organizationName) > 0) { + $keys[] = $this->organizationName; + } + if (mb_strlen($this->phone) > 0) { + $keys[] = $this->phone; + } + + return md5(implode('-', $keys)); + } +} diff --git a/shopware/Component/Mollie/Capture.php b/shopware/Component/Mollie/Capture.php new file mode 100644 index 000000000..1dbbedbdd --- /dev/null +++ b/shopware/Component/Mollie/Capture.php @@ -0,0 +1,47 @@ + $body + */ + public static function createFromClientResponse(array $body): self + { + $id = $body['id']; + $status = CaptureStatus::from($body['status']); + + $amount = new Money((float) $body['amount']['value'],$body['amount']['currency']); + + return new self($id, $status, $amount); + } + + public function getId(): string + { + return $this->id; + } + + public function getStatus(): CaptureStatus + { + return $this->status; + } + + public function getAmount(): Money + { + return $this->amount; + } + + public function setStatus(CaptureStatus $status): void + { + $this->status = $status; + } +} diff --git a/shopware/Component/Mollie/CaptureMode.php b/shopware/Component/Mollie/CaptureMode.php new file mode 100644 index 000000000..ab171fec4 --- /dev/null +++ b/shopware/Component/Mollie/CaptureMode.php @@ -0,0 +1,10 @@ +money; + } + + public function setMoney(Money $money): void + { + $this->money = $money; + } + + public function add(Money $money): void + { + } + + public function getDescription(): string + { + return $this->description; + } + + public function setDescription(string $description): void + { + $this->description = $description; + } + + /** + * @return array + */ + public function toArray(): array + { + return $captureArray = [ + 'amount' => $this->money->toArray(), + 'description' => $this->description, + ]; + } +} diff --git a/shopware/Component/Mollie/CreatePayment.php b/shopware/Component/Mollie/CreatePayment.php new file mode 100644 index 000000000..8c8aa8ae6 --- /dev/null +++ b/shopware/Component/Mollie/CreatePayment.php @@ -0,0 +1,279 @@ + + */ + private array $metadata = []; + /** + * @var string[] + */ + private array $methods = []; + + public function __construct(private string $description,private string $redirectUrl,private Money $amount) + { + $this->setSequenceType(SequenceType::ONEOFF); + } + + public function getBillingAddress(): Address + { + return $this->billingAddress; + } + + public function setBillingAddress(Address $billingAddress): void + { + $this->billingAddress = $billingAddress; + } + + public function getShippingAddress(): Address + { + return $this->shippingAddress; + } + + public function setShippingAddress(Address $shippingAddress): void + { + $this->shippingAddress = $shippingAddress; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getAmount(): Money + { + return $this->amount; + } + + public function getRedirectUrl(): string + { + return $this->redirectUrl; + } + + public function getMethod(): PaymentMethod + { + return $this->method; + } + + public function setMethod(PaymentMethod $method): void + { + $this->method = $method; + } + + /** + * @param string[] $methods + */ + public function setMethods(array $methods): void + { + $this->methods = $methods; + } + + public function getLines(): LineItemCollection + { + return $this->lines; + } + + public function getLocale(): Locale + { + return $this->locale; + } + + public function setLocale(Locale $locale): void + { + $this->locale = $locale; + } + + public function setSequenceType(SequenceType $sequenceType): void + { + $this->sequenceType = $sequenceType; + } + + public function getSequenceType(): SequenceType + { + return $this->sequenceType; + } + + public function setLines(LineItemCollection $lines): void + { + $this->lines = $lines; + } + + public function getWebhookUrl(): string + { + return $this->webhookUrl; + } + + public function setWebhookUrl(string $webhookUrl): void + { + $this->webhookUrl = $webhookUrl; + } + + public function setDescription(string $description): void + { + $this->description = $description; + } + + public function getCaptureMode(): ?CaptureMode + { + return $this->captureMode; + } + + public function setCaptureMode(CaptureMode $captureMode): void + { + $this->captureMode = $captureMode; + } + + public function setCardToken(string $creditCardToken): void + { + $this->cardToken = $creditCardToken; + } + + public function getCardToken(): ?string + { + return $this->cardToken; + } + + public function getCancelUrl(): string + { + return $this->cancelUrl; + } + + /** + * @return array + */ + public function toArray(): array + { + $createPaymentBody = json_decode((string) json_encode($this), true); + if ($this->dueDate !== null) { + $createPaymentBody['dueDate'] = $this->dueDate->format('Y-m-d'); + } + if (count($this->methods) > 0) { + $createPaymentBody['method'] = $this->methods; + } + unset($createPaymentBody['methods']); + + // Remove all entries with null values + return array_filter($createPaymentBody, function ($entry) { + return $entry !== null; + }); + } + + public function setShopwareOrderNumber(string $orderNumber): void + { + $this->metadata['shopwareOrderNumber'] = $orderNumber; + } + + public function getShopwareOrderNumber(): string + { + return $this->metadata['shopwareOrderNumber']; + } + + public function setApplePayPaymentToken(?string $applePayPaymentToken): void + { + $this->applePayPaymentToken = $applePayPaymentToken; + } + + public function getApplePayPaymentToken(): ?string + { + return $this->applePayPaymentToken; + } + + public function getDueDate(): ?\DateTimeInterface + { + return $this->dueDate; + } + + public function setDueDate(?\DateTimeInterface $dueDate): void + { + $this->dueDate = $dueDate; + } + + public function setCustomerReference(string $customerReference): void + { + $this->customerReference = $customerReference; + } + + public function getCustomerReference(): ?string + { + return $this->customerReference; + } + + public function getCustomerId(): ?string + { + return $this->customerId; + } + + public function setCustomerId(string $customerId): void + { + $this->customerId = $customerId; + } + + public function getMandateId(): ?string + { + return $this->mandateId; + } + + public function setMandateId(string $mandateId): void + { + $this->mandateId = $mandateId; + } + + public function getProfileId(): ?string + { + return $this->profileId; + } + + public function setProfileId(string $profileId): void + { + $this->profileId = $profileId; + } + + public function getTerminalId(): ?string + { + return $this->terminalId; + } + + public function setTerminalId(?string $terminalId): void + { + $this->terminalId = $terminalId; + } + + public function getAuthenticationId(): ?string + { + return $this->authenticationId; + } + + public function setAuthenticationId(string $authenticationId): void + { + $this->authenticationId = $authenticationId; + } +} diff --git a/shopware/Component/Mollie/CreateSubscription.php b/shopware/Component/Mollie/CreateSubscription.php new file mode 100644 index 000000000..ced7ef0e4 --- /dev/null +++ b/shopware/Component/Mollie/CreateSubscription.php @@ -0,0 +1,111 @@ + + */ + private array $metadata = []; + private string $webhookUrl = ''; + private string $mandateId = ''; + + public function __construct( + private string $description, + private Interval $interval, + private Money $amount, + ) { + } + + public function getDescription(): string + { + return $this->description; + } + + public function getInterval(): Interval + { + return $this->interval; + } + + public function getAmount(): Money + { + return $this->amount; + } + + public function getTimes(): ?int + { + return $this->times; + } + + public function setTimes(int $times): void + { + $this->times = $times; + } + + public function getStartDate(): string + { + return $this->startDate; + } + + public function setStartDate(string $startDate): void + { + $this->startDate = $startDate; + } + + /** + * @return mixed[] + */ + public function getMetadata(): array + { + return $this->metadata; + } + + /** + * @param array $metadata + */ + public function setMetadata(array $metadata): void + { + $this->metadata = $metadata; + } + + public function getWebhookUrl(): string + { + return $this->webhookUrl; + } + + public function setWebhookUrl(string $webhookUrl): void + { + $this->webhookUrl = $webhookUrl; + } + + public function getMandateId(): string + { + return $this->mandateId; + } + + public function setMandateId(string $mandateId): void + { + $this->mandateId = $mandateId; + } + + /** + * @return array + */ + public function toArray(): array + { + $createSubscriptionBody = json_decode((string) json_encode($this), true); + $createSubscriptionBody['interval'] = (string) $this->interval; + + // Remove all entries with null values + return array_filter($createSubscriptionBody, function ($entry) { + return $entry !== null; + }); + } +} diff --git a/shopware/Component/Mollie/Customer.php b/shopware/Component/Mollie/Customer.php new file mode 100644 index 000000000..0227a6deb --- /dev/null +++ b/shopware/Component/Mollie/Customer.php @@ -0,0 +1,71 @@ + $metaData + */ + public function __construct(private string $id, private string $name, private string $email, private array $metaData) + { + } + + /** + * @param array $body + */ + public static function fromClientResponse(array $body): self + { + $customer = new self( + $body['id'], + $body['name'], + $body['email'], + $body['metadata'], + ); + if ($body['locale'] !== null) { + $customer->setLocale(Locale::from($body['locale'])); + } + + return $customer; + } + + public function getId(): string + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getEmail(): string + { + return $this->email; + } + + /** + * @return mixed[] + */ + public function getMetaData(): array + { + return $this->metaData; + } + + public function getLocale(): Locale + { + return $this->locale; + } + + public function setLocale(Locale $locale): void + { + $this->locale = $locale; + } +} diff --git a/shopware/Component/Mollie/Exception/ApiException.php b/shopware/Component/Mollie/Exception/ApiException.php new file mode 100644 index 000000000..941d2d092 --- /dev/null +++ b/shopware/Component/Mollie/Exception/ApiException.php @@ -0,0 +1,13 @@ +clientFactory->create($salesChannelId, true); + $response = $client->post('wallets/applepay/sessions', [ + 'form_params' => [ + 'validationUrl' => $validationUrl, + 'domain' => str_replace(['https://', 'http://'], '', $domain), + ] + ]); + + $this->logger->debug('Requested apple pay session'); + + return json_decode($response->getBody()->getContents(),true); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } +} diff --git a/shopware/Component/Mollie/Gateway/ApplePayGatewayInterface.php b/shopware/Component/Mollie/Gateway/ApplePayGatewayInterface.php new file mode 100644 index 000000000..93f003b6d --- /dev/null +++ b/shopware/Component/Mollie/Gateway/ApplePayGatewayInterface.php @@ -0,0 +1,12 @@ + + */ + public function requestSession(string $domain, string $validationUrl,string $salesChannelId): array; +} diff --git a/shopware/Component/Mollie/Gateway/CachedMollieGateway.php b/shopware/Component/Mollie/Gateway/CachedMollieGateway.php new file mode 100644 index 000000000..dc3072528 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/CachedMollieGateway.php @@ -0,0 +1,110 @@ + + */ + private array $transactionPayments = []; + + /** + * @var array + */ + private array $profiles = []; + + /** + * @var array + */ + private array $paymentIdPayments = []; + + public function __construct( + private MollieGatewayInterface $decorated + ) { + } + + public function getCurrentProfile(?string $salesChannelId = null): Profile + { + $cacheKey = $salesChannelId ?? 'all'; + if (isset($this->profiles[$cacheKey])) { + return $this->profiles[$cacheKey]; + } + $this->profiles[$cacheKey] = $this->decorated->getCurrentProfile($salesChannelId); + + return $this->profiles[$cacheKey]; + } + + public function createPayment(CreatePayment $molliePayment, string $salesChannelId): Payment + { + return $this->decorated->createPayment($molliePayment, $salesChannelId); + } + + public function getPaymentByTransactionId(string $transactionId, Context $context): Payment + { + $key = sprintf('%s', $transactionId); + if (isset($this->transactionPayments[$key])) { + return $this->transactionPayments[$key]; + } + $this->transactionPayments[$key] = $this->decorated->getPaymentByTransactionId($transactionId, $context); + + return $this->transactionPayments[$key]; + } + + public function getPayment(string $molliePaymentId, string $orderNumber, string $salesChannelId): Payment + { + $key = sprintf('%s', $molliePaymentId); + if (isset($this->paymentIdPayments[$key])) { + return $this->paymentIdPayments[$key]; + } + $this->paymentIdPayments[$key] = $this->decorated->getPayment($molliePaymentId, $orderNumber, $salesChannelId); + + return $this->paymentIdPayments[$key]; + } + + public function createCustomer(CustomerEntity $customer, string $salesChannelId): Customer + { + return $this->decorated->createCustomer($customer, $salesChannelId); + } + + public function listMandates(string $mollieCustomerId, string $salesChannelId): MandateCollection + { + // TODO save in array + return $this->decorated->listMandates($mollieCustomerId, $salesChannelId); + } + + public function revokeMandate(string $mollieCustomerId, string $mandateId, string $salesChannelId): bool + { + return $this->decorated->revokeMandate($mollieCustomerId, $mandateId, $salesChannelId); + } + + public function listTerminals(string $salesChannelId): TerminalCollection + { + return $this->decorated->listTerminals($salesChannelId); + } + + public function createCapture(CreateCapture $createCapture, string $paymentId, string $orderNumber, string $salesChannelId): Capture + { + return $this->decorated->createCapture($createCapture, $paymentId, $orderNumber, $salesChannelId); + } + + public function clearCache(): void + { + $this->paymentIdPayments = []; + $this->transactionPayments = []; + } +} diff --git a/shopware/Component/Mollie/Gateway/CaptureGatewayInterface.php b/shopware/Component/Mollie/Gateway/CaptureGatewayInterface.php new file mode 100644 index 000000000..ba19f6cc9 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/CaptureGatewayInterface.php @@ -0,0 +1,12 @@ +settings->getApiSettings($salesChannelId); + + $userAgent = implode(' ', [ + 'Shopware/' . $this->shopwareVersion, + 'MollieShopware6/' . MolliePayments::PLUGIN_VERSION, + ]); + $apiKey = $apiSettings->getApiKey(); + $testMode = $apiSettings->isTestMode(); + if ($forceLive) { + $apiKey = $apiSettings->getLiveApiKey(); + $testMode = false; + } + if (mb_strlen($apiKey) === 0) { + $message = sprintf('API key is empty. SalesChannelId: %s, TestMode: %s', $salesChannelId, $testMode ? 'true' : 'false'); + throw new ApiKeyException($message); + } + $authorizationValue = sprintf('Bearer %s', $apiKey); + + return new Client([ + 'base_uri' => self::MOLLIE_BASE_URL, + 'headers' => [ + 'Authorization' => $authorizationValue, + 'User-Agent' => $userAgent + ] + ]); + } +} diff --git a/shopware/Component/Mollie/Gateway/ClientFactoryInterface.php b/shopware/Component/Mollie/Gateway/ClientFactoryInterface.php new file mode 100644 index 000000000..2948b9c11 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/ClientFactoryInterface.php @@ -0,0 +1,11 @@ +getResponse()->getBody()->getContents(), true); + $logData = [ + 'title' => $body['title'] ?? 'no title', + 'error' => $body['detail'] ?? 'no details', + 'field' => $body['field'] ?? 'no field', + ]; + if ($orderNumber !== null) { + $logData['orderNumber'] = $orderNumber; + } + $this->logger->error('There was an error from Mollies API', $logData); + + return new ApiException($exception->getCode(), $body['title'] ?? '', $body['detail'] ?? '', $body['field'] ?? ''); + } +} diff --git a/shopware/Component/Mollie/Gateway/MollieGateway.php b/shopware/Component/Mollie/Gateway/MollieGateway.php new file mode 100644 index 000000000..37861bc5a --- /dev/null +++ b/shopware/Component/Mollie/Gateway/MollieGateway.php @@ -0,0 +1,310 @@ +transactionService->findById($transactionId, $context); + + $transaction = $transactionData->getTransaction(); + $transactionOrder = $transactionData->getOrder(); + + $orderNumber = (string) $transactionOrder->getOrderNumber(); + $salesChannelId = $transactionOrder->getSalesChannelId(); + + $logData = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]; + + $this->logger->info('Start - load payment data by transaction id', $logData); + + /** @var ?Payment $mollieTransaction */ + $mollieTransaction = $transaction->getExtension(Mollie::EXTENSION); + + if ($mollieTransaction instanceof Payment) { + $logData['molliePaymentId'] = $mollieTransaction->getId(); + $this->logger->debug('Transaction has mollie payment data, load additional data from mollie', $logData); + + $payment = $this->getPayment($mollieTransaction->getId(), $orderNumber, $salesChannelId); + $payment->setFinalizeUrl($mollieTransaction->getFinalizeUrl()); + } + + if ($mollieTransaction === null) { + $this->logger->debug('Transaction is without mollie payment data', $logData); + $payment = $this->repairLegacyTransaction($transaction, $transactionOrder, $context); + if ($payment === null) { + throw new TransactionWithoutMollieDataException($transactionId); + } + } + + $payment->setShopwareTransaction($transaction); + $logData['molliePaymentId'] = $payment->getId(); + $logData['paymentStatus'] = $payment->getStatus()->value; + $this->logger->info('Finished - load payment data by transaction id', $logData); + + return $payment; + } + + public function createPayment(CreatePayment $molliePayment, string $salesChannelId): Payment + { + $shopwareOrderNumber = $molliePayment->getShopwareOrderNumber(); + try { + $client = $this->clientFactory->create($salesChannelId); + $formParams = $molliePayment->toArray(); + + $response = $client->post('payments', [ + 'form_params' => $formParams, + ]); + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Mollie Payment created', [ + 'requestParameter' => $formParams, + 'responseParameter' => $body, + 'orderNumber' => $shopwareOrderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return Payment::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $shopwareOrderNumber); + } + } + + public function getCurrentProfile(?string $salesChannelId = null): Profile + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get('profiles/me'); + $body = json_decode($response->getBody()->getContents(), true); + $this->logger->debug('Fetched profile Id from Mollie'); + + return Profile::fromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function createCustomer(CustomerEntity $customer, string $salesChannelId): Customer + { + try { + $client = $this->clientFactory->create($salesChannelId); + $formParams = [ + 'name' => sprintf('%s %s', $customer->getFirstName(), $customer->getLastName()), + 'email' => $customer->getEmail(), + 'metadata' => [ + 'shopwareCustomerNumber' => $customer->getCustomerNumber(), + ] + ]; + $customerLanguage = $customer->getLanguage(); + if ($customerLanguage instanceof LanguageEntity) { + $formParams['locale'] = Locale::fromLanguage($customerLanguage); + } + $response = $client->post('customers', [ + 'form_params' => $formParams + ]); + $body = json_decode($response->getBody()->getContents(), true); + + return Customer::fromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function listMandates(string $mollieCustomerId, string $salesChannelId): MandateCollection + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get(sprintf('customers/%s/mandates', $mollieCustomerId)); + $body = json_decode($response->getBody()->getContents(), true); + $collection = new MandateCollection(); + foreach ($body['_embedded']['mandates'] as $mandateData) { + $mandate = Mandate::fromClientResponse($mandateData); + $collection->set($mandate->getId(), $mandate); + } + + return $collection; + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function listTerminals(string $salesChannelId): TerminalCollection + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get('terminals'); + $body = json_decode($response->getBody()->getContents(), true); + $collection = new TerminalCollection(); + foreach ($body['_embedded']['terminals'] as $terminalData) { + $terminal = Terminal::fromClientResponse($terminalData); + $collection->set($terminal->getId(), $terminalData); + } + + return $collection; + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function revokeMandate(string $mollieCustomerId, string $mandateId, string $salesChannelId): bool + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->delete('customers/' . $mollieCustomerId . '/mandates/' . $mandateId); + + return $response->getStatusCode() !== Response::HTTP_NOT_FOUND; + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function getPayment(string $molliePaymentId, string $orderNumber, string $salesChannelId): Payment + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get('payments/' . $molliePaymentId); + $body = json_decode($response->getBody()->getContents(), true); + $this->logger->debug('Additional data from mollie loaded', [ + 'molliePaymentId' => $molliePaymentId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'body' => $body + ]); + + return Payment::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + public function createCapture(CreateCapture $createCapture, string $paymentId, string $orderNumber, string $salesChannelId): Capture + { + try { + $client = $this->clientFactory->create($salesChannelId); + + $formParams = $createCapture->toArray(); + + $response = $client->post('payments/' . $paymentId . '/captures', [ + 'form_params' => $formParams, + ]); + + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Capture created', [ + 'requestParameter' => $formParams, + 'responseParameter' => $body, + 'paymentId' => $paymentId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return Capture::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + private function getPaymentByMollieOrderId(string $mollieOrderId, string $orderNumber, string $salesChannelId): Payment + { + try { + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get('orders/' . $mollieOrderId, [ + 'query' => [ + 'embed' => 'payments', + ] + ]); + $body = json_decode($response->getBody()->getContents(), true); + $paymentsBody = $body['_embedded']['payments'][0] ?? []; + + $this->logger->debug('Additional data from mollie loaded based on mollie order id', [ + 'mollieOrderId' => $mollieOrderId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'body' => $paymentsBody, + ]); + + return Payment::createFromClientResponse($paymentsBody); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + private function repairLegacyTransaction(OrderTransactionEntity $transaction, OrderEntity $order, Context $context): ?Payment + { + $transactionId = $transaction->getId(); + $orderNumber = (string) $order->getOrderNumber(); + $salesChannelId = $order->getSalesChannelId(); + $logData = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->debug('Trying to load data based on order entity', $logData); + + $customFields = $order->getCustomFields()[Mollie::EXTENSION] ?? null; + if ($customFields === null) { + $this->logger->error('Order does not have mollie custom fields', $logData); + + return null; + } + $mollieOrderId = $customFields['order_id'] ?? null; + $returnUrl = $customFields['transactionReturnUrl'] ?? null; + if ($mollieOrderId === null || $returnUrl === null) { + $logData['mollieOrderId'] = $mollieOrderId; + $logData['returnUrl'] = $returnUrl; + + $this->logger->error('Order does have mollie custom fields but mollie oder id or return url is not set', $logData); + + return null; + } + + $payment = $this->getPaymentByMollieOrderId($mollieOrderId, $orderNumber, $salesChannelId); + $payment->setFinalizeUrl($returnUrl); + + $this->transactionService->savePaymentExtension($transactionId, $order, $payment, $context); + + return $payment; + } +} diff --git a/shopware/Component/Mollie/Gateway/MollieGatewayInterface.php b/shopware/Component/Mollie/Gateway/MollieGatewayInterface.php new file mode 100644 index 000000000..5180baa90 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/MollieGatewayInterface.php @@ -0,0 +1,36 @@ +getSalesChannelId(); + $currencyIso = $salesChannelContext->getCurrency()->getIsoCode(); + $client = $this->clientFactory->create($salesChannelId); + $amount = new Money($cart->getPrice()->getTotalPrice(), $currencyIso); + $method = PaymentMethod::PAYPAL; + $formParams = [ + 'method' => $method->value, + 'methodDetails' => [ + 'checkoutFlow' => 'express', + ], + 'amount' => $amount->toArray(), + 'redirectUrl' => $this->routeBuilder->getPaypalExpressRedirectUrl(), + 'cancelUrl' => $this->routeBuilder->getPaypalExpressCancelUrl(), + ]; + + $response = $client->post('sessions', [ + 'form_params' => $formParams, + ]); + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Paypal express session created', [ + 'requestParameter' => $formParams, + 'responseParameter' => $body, + 'salesChannelId' => $salesChannelId, + ]); + + $session = Session::createFromClientResponse($body); + $session->setAuthenticationId(''); + + return $session; + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function loadSession(string $sessionId, SalesChannelContext $salesChannelContext): Session + { + try { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + + $client = $this->clientFactory->create($salesChannelId); + $response = $client->get('sessions/' . $sessionId); + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Session loaded', [ + 'sessionId' => $sessionId, + 'responseParameter' => $body, + 'salesChannelId' => $salesChannelId, + ]); + + return Session::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } + + public function cancelSession(string $sessionId, SalesChannelContext $salesChannelContext): Session + { + try { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + + $client = $this->clientFactory->create($salesChannelId); + $response = $client->delete('sessions/' . $sessionId); + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Session cancelled', [ + 'sessionId' => $sessionId, + 'responseParameter' => $body, + 'salesChannelId' => $salesChannelId, + ]); + + return Session::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception); + } + } +} diff --git a/shopware/Component/Mollie/Gateway/SessionGatewayInterface.php b/shopware/Component/Mollie/Gateway/SessionGatewayInterface.php new file mode 100644 index 000000000..45368f210 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/SessionGatewayInterface.php @@ -0,0 +1,17 @@ +clientFactory->create($salesChannelId); + + $formParams = $createSubscription->toArray(); + + $response = $client->post('customers/' . $customerId . '/subscriptions', [ + 'form_params' => $formParams, + ]); + $body = json_decode($response->getBody()->getContents(), true); + $this->logger->info('Subscription created', [ + 'requestParameter' => $formParams, + 'responseParameter' => $body, + 'customerId' => $customerId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return Subscription::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + public function getSubscription(string $mollieSubscriptionId, string $customerId, string $orderNumber, string $salesChannelId): Subscription + { + try { + $client = $this->clientFactory->create($salesChannelId); + + $response = $client->get('customers/' . $customerId . '/subscriptions/' . $mollieSubscriptionId); + $body = json_decode($response->getBody()->getContents(), true); + $this->logger->info('Subscription loaded from mollie api', [ + 'responseParameter' => $body, + 'customerId' => $customerId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'subscriptionId' => $mollieSubscriptionId + ]); + + return Subscription::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + public function copySubscription(Subscription $mollieSubscription, string $customerId, string $orderNumber, string $salesChannelId): Subscription + { + try { + $createSubscription = new CreateSubscription($mollieSubscription->getDescription(), $mollieSubscription->getInterval(), $mollieSubscription->getAmount()); + + $createSubscription->setStartDate($mollieSubscription->getStartDate()->format('Y-m-d')); + $createSubscription->setWebhookUrl($mollieSubscription->getWebhookUrl()); + $createSubscription->setMetadata($mollieSubscription->getMetadata()); + $createSubscription->setMandateId($mollieSubscription->getMandateId()); + + if ($mollieSubscription->getTimesRemaining() !== null) { + $createSubscription->setTimes($mollieSubscription->getTimesRemaining()); + } + $this->logger->info('Subscription copied', [ + 'requestParameter' => $createSubscription->toArray(), + 'customerId' => $customerId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return $this->createSubscription($createSubscription, $customerId, $orderNumber, $salesChannelId); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + public function cancelSubscription(string $mollieSubscriptionId, string $customerId, string $orderNumber, string $salesChannelId): Subscription + { + try { + $client = $this->clientFactory->create($salesChannelId); + + $response = $client->delete('customers/' . $customerId . '/subscriptions/' . $mollieSubscriptionId); + $body = json_decode($response->getBody()->getContents(), true); + + $this->logger->info('Subscription cancelled over mollie api', [ + 'responseParameter' => $body, + 'customerId' => $customerId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return Subscription::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } + + public function updateSubscription(Subscription $mollieSubscription, string $customerId, string $orderNumber, string $salesChannelId): Subscription + { + try { + $client = $this->clientFactory->create($salesChannelId); + + $mollieSubscriptionId = $mollieSubscription->getId(); + + $response = $client->patch('customers/' . $customerId . '/subscriptions/' . $mollieSubscriptionId, [ + 'form_params' => $mollieSubscription->toArray() + ]); + + $body = json_decode($response->getBody()->getContents(), true); + $this->logger->info('Subscription updated over mollie api', [ + 'responseParameter' => $body, + 'customerId' => $customerId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]); + + return Subscription::createFromClientResponse($body); + } catch (ClientException $exception) { + throw $this->convertException($exception, $orderNumber); + } + } +} diff --git a/shopware/Component/Mollie/Gateway/SubscriptionGatewayInterface.php b/shopware/Component/Mollie/Gateway/SubscriptionGatewayInterface.php new file mode 100644 index 000000000..3fd6bfe09 --- /dev/null +++ b/shopware/Component/Mollie/Gateway/SubscriptionGatewayInterface.php @@ -0,0 +1,20 @@ +intervalValue . ' ' . $this->intervalUnit->value; + } + + public static function fromString(string $interval): self + { + $intervalValues = explode(' ', $interval); + $intervalUnit = str_replace('ss','s',$intervalValues[1] . 's'); + + return new self((int) $intervalValues[0], IntervalUnit::from($intervalUnit)); + } + + public function getIntervalValue(): int + { + return $this->intervalValue; + } + + public function getIntervalUnit(): IntervalUnit + { + return $this->intervalUnit; + } +} diff --git a/shopware/Component/Mollie/IntervalUnit.php b/shopware/Component/Mollie/IntervalUnit.php new file mode 100644 index 000000000..17bc1afde --- /dev/null +++ b/shopware/Component/Mollie/IntervalUnit.php @@ -0,0 +1,11 @@ +type = LineItemType::PHYSICAL; + } + + public static function fromDelivery(OrderDeliveryEntity $delivery, CurrencyEntity $currency, string $taxStatus = CartPrice::TAX_STATE_GROSS): self + { + $shippingMethod = $delivery->getShippingMethod(); + if (! $shippingMethod instanceof ShippingMethodEntity) { + throw new MissingShippingMethodException(); + } + $shippingCosts = $delivery->getShippingCosts(); + + $lineItem = self::createBaseLineItem((string) $shippingMethod->getName(), $taxStatus, $shippingCosts, $currency); + $lineItem->setType(LineItemType::SHIPPING); + $lineItem->setSku(sprintf('mol-delivery-%s', $shippingMethod->getId())); + + return $lineItem; + } + + public static function fromOrderLine(OrderLineItemEntity $orderLineItem, CurrencyEntity $currency, string $taxStatus = CartPrice::TAX_STATE_GROSS): self + { + $sku = $orderLineItem->getId(); + + $product = $orderLineItem->getProduct(); + $linItemPrice = $orderLineItem->getPrice(); + if (! $linItemPrice instanceof CalculatedPrice) { + throw new MissingLineItemPriceException($orderLineItem->getLabel()); + } + + $lineItem = self::createBaseLineItem($orderLineItem->getLabel(), $taxStatus, $linItemPrice, $currency); + + $lineItemType = LineItemType::fromOderLineItem($orderLineItem); + + $lineItem->setType($lineItemType); + $lineItem->setSku($sku); + + if ($product instanceof ProductEntity) { + $mollieProduct = $product->getExtension(Mollie::EXTENSION); + if ($mollieProduct instanceof Product) { + $voucherCategories = $mollieProduct->getVoucherCategories(); + foreach ($voucherCategories as $voucherCategory) { + $lineItem->addCategory($voucherCategory); + } + } + + $lineItem->setSku($product->getProductNumber()); + } + + return $lineItem; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getQuantity(): int + { + return $this->quantity; + } + + public function getUnitPrice(): Money + { + return $this->unitPrice; + } + + public function getTotalAmount(): Money + { + return $this->totalAmount; + } + + public function getType(): LineItemType + { + return $this->type; + } + + public function setType(LineItemType $type): void + { + $this->type = $type; + } + + public function getQuantityUnit(): string + { + return $this->quantityUnit; + } + + public function setQuantityUnit(string $quantityUnit): void + { + $this->quantityUnit = $quantityUnit; + } + + public function getDiscountAmount(): Money + { + return $this->discountAmount; + } + + public function setDiscountAmount(Money $discountAmount): void + { + $this->discountAmount = $discountAmount; + } + + public function getVatRate(): string + { + return $this->vatRate; + } + + public function setVatRate(string $vatRate): void + { + $this->vatRate = $vatRate; + } + + public function getVatAmount(): Money + { + return $this->vatAmount; + } + + public function setVatAmount(Money $vatAmount): void + { + $this->vatAmount = $vatAmount; + } + + public function getSku(): string + { + return $this->sku; + } + + public function setSku(string $sku): void + { + $this->sku = $sku; + } + + public function getImageUrl(): string + { + return $this->imageUrl; + } + + public function setImageUrl(string $imageUrl): void + { + $this->imageUrl = $imageUrl; + } + + public function getProductUrl(): string + { + return $this->productUrl; + } + + /** + * @return VoucherCategory[] + */ + public function getCategories(): array + { + return $this->categories; + } + + public function setProductUrl(string $productUrl): void + { + $this->productUrl = $productUrl; + } + + private static function createBaseLineItem(string $label, string $taxStatus, CalculatedPrice $price, CurrencyEntity $currency): self + { + $tax = self::calculateTax($price->getCalculatedTaxes(), $price->getTotalPrice()); + + $unitPrice = new Money($price->getUnitPrice(), $currency->getIsoCode()); + $totalPrice = new Money($price->getTotalPrice(), $currency->getIsoCode()); + + if ($taxStatus === CartPrice::TAX_STATE_NET && $tax instanceof CalculatedTax) { + $unitPrice = new Money($price->getUnitPrice() + $tax->getTax() / $price->getQuantity(), $currency->getIsoCode()); + $totalPrice = new Money($price->getTotalPrice() + $tax->getTax(), $currency->getIsoCode()); + } + + $lineItem = new self($label, $price->getQuantity(), $unitPrice, $totalPrice); + + if ($tax instanceof CalculatedTax) { + $lineItem->setVatAmount(new Money($tax->getTax(), $currency->getIsoCode())); + $lineItem->setVatRate((string) $tax->getTaxRate()); + } + + return $lineItem; + } + + /** + * Mollie Payments API does allow only one vatRate and vatAmount per line item. + * In Shopware, the shipping costs and voucher lineitems might have multiple vat rates + * so we need to create an avarage tax amount and recalculate it for the API + */ + private static function calculateTax(CalculatedTaxCollection $taxCollection, float $price): ?CalculatedTax + { + if ($taxCollection->count() === 0) { + return null; + } + if ($taxCollection->count() === 1) { + /** @var CalculatedTax $calculatedTax */ + $calculatedTax = $taxCollection->first(); + if ($calculatedTax instanceof CalculatedTax) { + return $calculatedTax; + } + + return null; + } + $totalAmount = 0.0; + $totalTaxAmount = 0.0; + /** @var CalculatedTax $calculatedTax */ + foreach ($taxCollection as $calculatedTax) { + $totalTaxAmount += $calculatedTax->getTax(); + $totalAmount += $calculatedTax->getPrice(); + } + + $averageVatRate = round($totalTaxAmount / $totalAmount * 100, 2); + $vatAmount = $price * ($averageVatRate / (100 + $averageVatRate)); + + return new CalculatedTax($vatAmount, $averageVatRate, $price); + } + + private function addCategory(VoucherCategory $voucherCategory): void + { + $this->categories[] = $voucherCategory; + } +} diff --git a/shopware/Component/Mollie/LineItemCollection.php b/shopware/Component/Mollie/LineItemCollection.php new file mode 100644 index 000000000..3a0517ef3 --- /dev/null +++ b/shopware/Component/Mollie/LineItemCollection.php @@ -0,0 +1,13 @@ + + */ +final class LineItemCollection extends Collection +{ +} diff --git a/shopware/Component/Mollie/LineItemType.php b/shopware/Component/Mollie/LineItemType.php new file mode 100644 index 000000000..55e38da30 --- /dev/null +++ b/shopware/Component/Mollie/LineItemType.php @@ -0,0 +1,32 @@ +getType(); + + return match ($oderLineItemType) { + LineItem::PRODUCT_LINE_ITEM_TYPE, self::LINE_ITEM_TYPE_CUSTOM_PRODUCTS->value => self::PHYSICAL, + LineItem::CREDIT_LINE_ITEM_TYPE => self::CREDIT, + LineItem::PROMOTION_LINE_ITEM_TYPE => self::DISCOUNT, + default => self::DIGITAL, + }; + } +} diff --git a/shopware/Component/Mollie/Locale.php b/shopware/Component/Mollie/Locale.php new file mode 100644 index 000000000..eab32e124 --- /dev/null +++ b/shopware/Component/Mollie/Locale.php @@ -0,0 +1,49 @@ +getLocale(); + $code = 'en-GB'; + if ($locale instanceof LocaleEntity) { + $code = $locale->getCode(); + } + + return self::fromLocaleCode($code); + } + + public static function fromLocaleCode(string $code): self + { + $languageLocale = str_replace('-', '_', $code); + + return self::from($languageLocale); + } +} diff --git a/shopware/Component/Mollie/Mandate.php b/shopware/Component/Mollie/Mandate.php new file mode 100644 index 000000000..c06d7b4b4 --- /dev/null +++ b/shopware/Component/Mollie/Mandate.php @@ -0,0 +1,44 @@ + $details + */ + public function __construct(private string $id, private PaymentMethod $method, private array $details) + { + } + + /** + * @param array $body + */ + public static function fromClientResponse(array $body): self + { + return new self($body['id'],PaymentMethod::from($body['method']),$body['details']); + } + + public function getId(): string + { + return $this->id; + } + + public function getMethod(): PaymentMethod + { + return $this->method; + } + + /** + * @return mixed[] + */ + public function getDetails(): array + { + return $this->details; + } +} diff --git a/shopware/Component/Mollie/MandateCollection.php b/shopware/Component/Mollie/MandateCollection.php new file mode 100644 index 000000000..809698dc9 --- /dev/null +++ b/shopware/Component/Mollie/MandateCollection.php @@ -0,0 +1,19 @@ + + */ +final class MandateCollection extends Collection +{ + public function filterByPaymentMethod(PaymentMethod $paymentMethod): self + { + return $this->filter(function (Mandate $mandate) use ($paymentMethod) { + return $mandate->getMethod() === $paymentMethod; + }); + } +} diff --git a/shopware/Component/Mollie/Mode.php b/shopware/Component/Mollie/Mode.php new file mode 100644 index 000000000..25dcec9a0 --- /dev/null +++ b/shopware/Component/Mollie/Mode.php @@ -0,0 +1,10 @@ +currency = $currency; + $this->value = $this->formatValue($value); + } + + /** + * @return array + */ + public function toArray(): array + { + return json_decode((string) json_encode($this), true); + } + + public function getCurrency(): string + { + return $this->currency; + } + + public function getValue(): string + { + return $this->value; + } + + public static function fromOrder(OrderEntity $order,CurrencyEntity $currency): self + { + $value = $order->getAmountTotal(); + if ((string) $order->getTaxStatus() === CartPrice::TAX_STATE_FREE) { + $value = $order->getAmountNet(); + } + + return new self($value, $currency->getIsoCode()); + } + + private function formatValue(float $value): string + { + return number_format(round($value, self::MOLLIE_PRICE_PRECISION), self::MOLLIE_PRICE_PRECISION, '.', ''); + } +} diff --git a/shopware/Component/Mollie/Payment.php b/shopware/Component/Mollie/Payment.php new file mode 100644 index 000000000..4c4041137 --- /dev/null +++ b/shopware/Component/Mollie/Payment.php @@ -0,0 +1,295 @@ +id; + } + + public function getStatus(): PaymentStatus + { + return $this->status; + } + + public function setStatus(PaymentStatus $status): void + { + $this->status = $status; + } + + public function getFinalizeUrl(): string + { + return $this->finalizeUrl; + } + + public function setFinalizeUrl(string $finalizeUrl): void + { + $this->finalizeUrl = $finalizeUrl; + } + + public function getCountPayments(): int + { + return $this->countPayments; + } + + public function setCountPayments(int $countPayments): void + { + $this->countPayments = $countPayments; + } + + public function getShopwareTransaction(): OrderTransactionEntity + { + return $this->shopwareTransaction; + } + + public function setShopwareTransaction(OrderTransactionEntity $shopwareTransaction): void + { + $this->shopwareTransaction = $shopwareTransaction; + } + + public function getMethod(): ?PaymentMethod + { + return $this->method; + } + + public function setMethod(PaymentMethod $method): void + { + $this->method = $method; + } + + public function getThirdPartyPaymentId(): string + { + return $this->thirdPartyPaymentId; + } + + public function setThirdPartyPaymentId(string $thirdPartyPaymentId): void + { + $this->thirdPartyPaymentId = $thirdPartyPaymentId; + } + + /** + * @param array $body + */ + public static function createFromClientResponse(array $body): self + { + $payment = new self($body['id']); + $paymentMethod = PaymentMethod::tryFrom($body['method'] ?? ''); + $payment->setStatus(PaymentStatus::from($body['status'])); + $thirdPartyPaymentId = $body['details']['paypalReference'] ?? null; + $checkoutUrl = $body['_links']['checkout']['href'] ?? null; + $changePaymentStateUrl = $body['_links']['changePaymentState']['href'] ?? null; + $customerId = $body['customerId'] ?? null; + $mandateId = $body['mandateId'] ?? null; + $profileId = $body['profileId'] ?? null; + $createdAt = $body['createdAt'] ?? null; + $subscriptionId = $body['subscriptionId'] ?? null; + $capturedAmount = $body['amountCaptured'] ?? null; + $amountRemaining = $body['amountRemaining'] ?? null; + $amount = $body['amount'] ?? null; + + if ($paymentMethod !== null) { + $payment->setMethod($paymentMethod); + } + if ($thirdPartyPaymentId !== null) { + $payment->setThirdPartyPaymentId($thirdPartyPaymentId); + } + if ($checkoutUrl !== null) { + $payment->setCheckoutUrl($checkoutUrl); + } + if ($changePaymentStateUrl !== null) { + $payment->setChangePaymentStateUrl($changePaymentStateUrl); + } + if ($customerId !== null) { + $payment->setCustomerId($customerId); + } + if ($mandateId !== null) { + $payment->setMandateId($mandateId); + } + if ($profileId !== null) { + $payment->setProfileId($profileId); + } + if ($createdAt !== null) { + $createdAtDate = \DateTime::createFromFormat(\DateTimeInterface::ATOM, $createdAt); + if ($createdAtDate instanceof \DateTimeInterface) { + $payment->setCreatedAt($createdAtDate); + } + } + + if ($subscriptionId !== null) { + $payment->setSubscriptionId($subscriptionId); + } + + if ($capturedAmount !== null) { + $payment->setCapturedAmount(new Money((float) $capturedAmount['value'], $capturedAmount['currency'])); + } + + if ($amountRemaining !== null) { + $payment->setAmountRemaining(new Money((float) $amountRemaining['value'], $amountRemaining['currency'])); + } + if ($amount !== null) { + $payment->setAmount(new Money((float) $amount['value'], $amount['currency'])); + } + + return $payment; + } + + public function getSubscriptionId(): ?string + { + return $this->subscriptionId; + } + + public function setSubscriptionId(?string $subscriptionId): void + { + $this->subscriptionId = $subscriptionId; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(\DateTimeInterface $createdAt): void + { + $this->createdAt = $createdAt; + } + + public function getProfileId(): ?string + { + return $this->profileId; + } + + public function setProfileId(string $profileId): void + { + $this->profileId = $profileId; + } + + public function getCustomerId(): ?string + { + return $this->customerId; + } + + public function setCustomerId(string $customerId): void + { + $this->customerId = $customerId; + } + + public function getMandateId(): ?string + { + return $this->mandateId; + } + + public function setMandateId(string $mandateId): void + { + $this->mandateId = $mandateId; + } + + public function getCheckoutUrl(): string + { + return $this->checkoutUrl; + } + + public function setCheckoutUrl(string $checkoutUrl): void + { + $this->checkoutUrl = $checkoutUrl; + } + + /** + * @return array + */ + public function toArray(): array + { + $data = json_decode((string) json_encode($this), true); + unset($data['shopwareTransaction']); + + return array_filter($data); + } + + public function getChangePaymentStateUrl(): string + { + return $this->changePaymentStateUrl; + } + + public function setChangePaymentStateUrl(string $changePaymentStateUrl): void + { + $this->changePaymentStateUrl = $changePaymentStateUrl; + } + + public function getAuthenticationId(): ?string + { + return $this->authenticationId; + } + + public function setAuthenticationId(?string $authenticationId): void + { + $this->authenticationId = $authenticationId; + } + + public function getCapturedAmount(): ?Money + { + return $this->capturedAmount; + } + + public function setCapturedAmount(Money $capturedAmount): void + { + $this->capturedAmount = $capturedAmount; + } + + public function getAmountRemaining(): ?Money + { + return $this->amountRemaining; + } + + public function setAmountRemaining(Money $amountRemaining): void + { + $this->amountRemaining = $amountRemaining; + } + + public function getAmount(): ?Money + { + return $this->amount; + } + + public function setAmount(Money $amount): void + { + $this->amount = $amount; + } +} diff --git a/shopware/Component/Mollie/PaymentMethod.php b/shopware/Component/Mollie/PaymentMethod.php new file mode 100644 index 000000000..c3b5bafb4 --- /dev/null +++ b/shopware/Component/Mollie/PaymentMethod.php @@ -0,0 +1,46 @@ + WebhookStatusOpenEvent::class, + self::PENDING => WebhookStatusPendingEvent::class, + self::AUTHORIZED => WebhookStatusAuthorizedEvent::class, + self::PAID => WebhookStatusPaidEvent::class, + self::CANCELED => WebhookStatusCancelledEvent::class, + self::EXPIRED => WebhookStatusExpiredEvent::class, + self::FAILED => WebhookStatusFailedEvent::class + }; + } + + public function getShopwarePaymentStatus(): string + { + return match ($this) { + self::OPEN => OrderTransactionStates::STATE_OPEN, + self::PENDING => OrderTransactionStates::STATE_UNCONFIRMED, + self::AUTHORIZED => OrderTransactionStates::STATE_AUTHORIZED, + self::PAID => OrderTransactionStates::STATE_PAID, + self::CANCELED, self::EXPIRED => OrderTransactionStates::STATE_CANCELLED, + self::FAILED => OrderTransactionStates::STATE_FAILED, + }; + } + + public function getShopwareHandlerMethod(): string + { + return match ($this) { + self::PAID => 'paid', + self::CANCELED => 'cancel', + self::AUTHORIZED => 'authorize', + self::FAILED => 'fail', + default => '', + }; + } +} diff --git a/shopware/Component/Mollie/Profile.php b/shopware/Component/Mollie/Profile.php new file mode 100644 index 000000000..66381a47c --- /dev/null +++ b/shopware/Component/Mollie/Profile.php @@ -0,0 +1,38 @@ + $body + */ + public static function fromClientResponse(array $body): self + { + return new self($body['id'],$body['name'],$body['email']); + } + + public function getId(): string + { + return $this->id; + } + + public function getName(): string + { + return $this->name; + } + + public function getEmail(): string + { + return $this->email; + } +} diff --git a/shopware/Component/Mollie/SequenceType.php b/shopware/Component/Mollie/SequenceType.php new file mode 100644 index 000000000..44cc398cc --- /dev/null +++ b/shopware/Component/Mollie/SequenceType.php @@ -0,0 +1,11 @@ + $body + */ + public static function createFromClientResponse(array $body): self + { + $session = new self($body['id']); + $authenticateId = $body['authenticationId'] ?? ''; + $redirectUrl = $body['_links']['redirect']['href'] ?? ''; + $session->setAuthenticationId($authenticateId); + $session->setRedirectUrl($redirectUrl); + + $shippingAddress = $body['shippingAddress'] ?? null; + $billingAddress = $body['billingAddress'] ?? null; + + if ($shippingAddress) { + if (! isset($shippingAddress['givenName'])) { + $shippingAddress['givenName'] = $billingAddress['givenName'] ?? null; + $shippingAddress['familyName'] = $billingAddress['familyName'] ?? null; + } + if (! isset($shippingAddress['email'])) { + $shippingAddress['email'] = $billingAddress['email'] ?? null; + } + + if (! isset($shippingAddress['phone'])) { + $shippingAddress['phone'] = $billingAddress['phone'] ?? null; + } + $session->shippingAddress = Address::fromResponseBody($shippingAddress); + } + + if ($billingAddress) { + if ($billingAddress['streetAndNumber'] === null) { + $billingAddress['streetAndNumber'] = $shippingAddress['streetAndNumber'] ?? ''; + } + if ($billingAddress['streetAdditional'] === null) { + $billingAddress['streetAdditional'] = $shippingAddress['streetAdditional'] ?? ''; + } + if ($billingAddress['city'] === null) { + $billingAddress['city'] = $shippingAddress['city'] ?? ''; + } + if ($billingAddress['postalCode'] === null) { + $billingAddress['postalCode'] = $shippingAddress['postalCode'] ?? ''; + } + $session->billingAddress = Address::fromResponseBody($billingAddress); + } + + return $session; + } + + public function getId(): string + { + return $this->id; + } + + public function getAuthenticationId(): string + { + return $this->authenticationId; + } + + public function getRedirectUrl(): string + { + return $this->redirectUrl; + } + + public function setAuthenticationId(string $authenticationId): void + { + $this->authenticationId = $authenticationId; + } + + public function setRedirectUrl(string $redirectUrl): void + { + $this->redirectUrl = $redirectUrl; + } + + public function getBillingAddress(): ?Address + { + return $this->billingAddress; + } + + public function getShippingAddress(): ?Address + { + return $this->shippingAddress; + } +} diff --git a/shopware/Component/Mollie/Subscription.php b/shopware/Component/Mollie/Subscription.php new file mode 100644 index 000000000..10c4f44da --- /dev/null +++ b/shopware/Component/Mollie/Subscription.php @@ -0,0 +1,214 @@ + $metadata + */ + public function __construct( + private string $id, + private string $customerId, + private string $mandateId, + private SubscriptionStatus $status, + private Interval $interval, + private Money $amount, + private string $description, + private string $webhookUrl, + private array $metadata, + private \DateTimeInterface $startDate + ) { + } + + /** + * @param array $body + */ + public static function createFromClientResponse(array $body): self + { + $id = $body['id']; + $customerId = $body['customerId']; + $mandateId = $body['mandateId']; + $description = $body['description']; + $webhookUrl = $body['webhookUrl']; + $amount = new Money((float) $body['amount']['value'], $body['amount']['currency']); + $startDateValue = $body['startDate'] ?? ''; + $startDate = \DateTime::createFromFormat('Y-m-d', $startDateValue); + if (! $startDate instanceof \DateTimeInterface) { + throw new \RuntimeException('Startdate "%s" of Subscription is missing or invalid', $startDateValue); + } + $cancelledAt = \DateTime::createFromFormat(\DateTime::ATOM, $body['canceledAt'] ?? ''); + $createdAt = \DateTime::createFromFormat(\DateTime::ATOM, $body['createdAt'] ?? ''); + $interval = Interval::fromString($body['interval']); + $status = SubscriptionStatus::from($body['status']); + + $nextPaymentDate = \DateTime::createFromFormat('Y-m-d', $body['nextPaymentDate'] ?? ''); + $timesRemaining = $body['timesRemaining'] ?? null; + $metadata = $body['metadata'] ?? []; + + $subscription = new self($id, $customerId, $mandateId, $status, $interval, $amount, $description, $webhookUrl, $metadata, $startDate); + + if ($cancelledAt instanceof \DateTimeInterface) { + $subscription->setCancelledAt($cancelledAt); + } + if ($createdAt instanceof \DateTimeInterface) { + $subscription->setCreatedAt($createdAt); + } + if ($nextPaymentDate instanceof \DateTimeInterface) { + $subscription->setNextPaymentDate($nextPaymentDate); + } + if ($timesRemaining !== null) { + $subscription->setTimesRemaining((int) $timesRemaining); + } + + return $subscription; + } + + public function getId(): string + { + return $this->id; + } + + public function getStatus(): SubscriptionStatus + { + return $this->status; + } + + public function getNextPaymentDate(): ?\DateTimeInterface + { + return $this->nextPaymentDate; + } + + public function getTimesRemaining(): ?int + { + return $this->timesRemaining; + } + + /** + * @return mixed[] + */ + public function getMetadata(): array + { + return $this->metadata; + } + + public function setStatus(SubscriptionStatus $status): void + { + $this->status = $status; + } + + public function getCustomerId(): string + { + return $this->customerId; + } + + public function getInterval(): Interval + { + return $this->interval; + } + + public function getMandateId(): string + { + return $this->mandateId; + } + + public function getStartDate(): \DateTimeInterface + { + return $this->startDate; + } + + public function setStartDate(\DateTimeInterface $startDate): void + { + $this->startDate = $startDate; + } + + public function getCancelledAt(): ?\DateTimeInterface + { + return $this->cancelledAt; + } + + public function setCancelledAt(?\DateTimeInterface $cancelledAt): void + { + $this->cancelledAt = $cancelledAt; + } + + public function getCreatedAt(): ?\DateTimeInterface + { + return $this->createdAt; + } + + public function setCreatedAt(?\DateTimeInterface $createdAt): void + { + $this->createdAt = $createdAt; + } + + public function getAmount(): Money + { + return $this->amount; + } + + public function getDescription(): string + { + return $this->description; + } + + public function isStateChangeWindowOpen(\DateTimeInterface $now, int $daysBeforeRenewal): bool + { + $nextPaymentDate = $this->getNextPaymentDate(); + if (! $nextPaymentDate instanceof \DateTimeInterface) { + return true; + } + /** @var \DateTime $latestCancellation */ + $latestCancellation = clone $nextPaymentDate; + + $latestCancellation->modify('-' . $daysBeforeRenewal . ' day'); + + return $now <= $latestCancellation; + } + + public function setNextPaymentDate(\DateTimeInterface $nextPaymentDate): void + { + $this->nextPaymentDate = $nextPaymentDate; + } + + public function setTimesRemaining(int $timesRemaining): void + { + $this->timesRemaining = $timesRemaining; + } + + public function getWebhookUrl(): string + { + return $this->webhookUrl; + } + + public function skipPayment(): \DateTimeInterface + { + $nextPaymentDate = new \DateTime(); + if ($this->nextPaymentDate instanceof \DateTimeInterface) { + /** @var \DateTime $nextPaymentDate */ + $nextPaymentDate = clone $this->nextPaymentDate; + } + + return $nextPaymentDate->modify('+' . (string) $this->interval); + } + + /** + * @return array + */ + public function toArray(): array + { + $createSubscriptionBody = json_decode((string) json_encode($this), true); + $createSubscriptionBody['interval'] = (string) $this->interval; + + // Remove all entries with null values + return array_filter($createSubscriptionBody, function ($entry) { + return $entry !== null; + }); + } +} diff --git a/shopware/Component/Mollie/SubscriptionStatus.php b/shopware/Component/Mollie/SubscriptionStatus.php new file mode 100644 index 000000000..d22f3a97d --- /dev/null +++ b/shopware/Component/Mollie/SubscriptionStatus.php @@ -0,0 +1,47 @@ + SkipAction::getActioName(), + self::PAUSED_AFTER_RENEWAL => PauseAction::getActioName(), + self::CANCELED_AFTER_RENEWAL => CancelAction::getActioName(), + default => null, + }; + } +} diff --git a/shopware/Component/Mollie/Terminal.php b/shopware/Component/Mollie/Terminal.php new file mode 100644 index 000000000..80e6dddaf --- /dev/null +++ b/shopware/Component/Mollie/Terminal.php @@ -0,0 +1,80 @@ + $body + */ + public static function fromClientResponse(array $body): self + { + $terminal = new self($body['id'], + $body['description'], + $body['currency'], + TerminalStatus::from($body['status']), + TerminalBrand::from($body['brand']), + TerminalModel::from($body['model']), + ); + if ($body['serialNumber'] !== null) { + $terminal->setSerialNumber($body['serialNumber']); + } + + return $terminal; + } + + public function getId(): string + { + return $this->id; + } + + public function setSerialNumber(string $serialNumber): void + { + $this->serialNumber = $serialNumber; + } + + public function getSerialNumber(): string + { + return $this->serialNumber; + } + + public function getDescription(): string + { + return $this->description; + } + + public function getCurrency(): string + { + return $this->currency; + } + + public function getStatus(): TerminalStatus + { + return $this->status; + } + + public function getBrand(): TerminalBrand + { + return $this->brand; + } + + public function getModel(): TerminalModel + { + return $this->model; + } +} diff --git a/shopware/Component/Mollie/TerminalBrand.php b/shopware/Component/Mollie/TerminalBrand.php new file mode 100644 index 000000000..6769a8f9a --- /dev/null +++ b/shopware/Component/Mollie/TerminalBrand.php @@ -0,0 +1,10 @@ + + */ +final class TerminalCollection extends Collection +{ +} diff --git a/shopware/Component/Mollie/TerminalModel.php b/shopware/Component/Mollie/TerminalModel.php new file mode 100644 index 000000000..ab36edd4b --- /dev/null +++ b/shopware/Component/Mollie/TerminalModel.php @@ -0,0 +1,14 @@ + VoucherCategory::ECO, + 2 => VoucherCategory::GIFT, + 3 => VoucherCategory::MEAL, + default => null, + }; + } +} diff --git a/shopware/Component/Mollie/VoucherCategoryCollection.php b/shopware/Component/Mollie/VoucherCategoryCollection.php new file mode 100644 index 000000000..60a0f98f7 --- /dev/null +++ b/shopware/Component/Mollie/VoucherCategoryCollection.php @@ -0,0 +1,13 @@ + + */ +final class VoucherCategoryCollection extends Collection +{ +} diff --git a/shopware/Component/Payment/Action/Finalize.php b/shopware/Component/Payment/Action/Finalize.php new file mode 100644 index 000000000..11408d50e --- /dev/null +++ b/shopware/Component/Payment/Action/Finalize.php @@ -0,0 +1,91 @@ +getOrderTransactionId(); + $transactionData = $this->transactionDataLoader->findById($transactionId,$context); + + $order = $transactionData->getOrder(); + $orderNumber = (string) $order->getOrderNumber(); + $salesChannelId = $order->getSalesChannelId(); + $customer = $transactionData->getCustomer(); + + $logData = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]; + + $this->logger->info('Finalize Process - Start', $logData); + // We need to change that part at some point. Because inside getPaymentByTraansactionId also calls the transactionData Loader. + $payment = $this->mollieGateway->getPaymentByTransactionId($transactionId, $context); + + $paymentStatus = $payment->getStatus(); + + $logData['paymentId'] = $payment->getId(); + $logData['paymentStatus'] = $paymentStatus->value; + + $this->logger->info('Fetched Payment Information from Mollie', $logData); + + $finalizeEvent = new PaymentFinalizeEvent($payment, $context); + $this->eventDispatcher->dispatch($finalizeEvent); + + $this->logger->debug('PaymentFinalizeEvent fired', $logData); + + if ($paymentStatus->isCanceled()) { + $message = sprintf('Payment for order %s (%s) was cancelled by the customer.', $orderNumber, $payment->getId()); + $this->logger->warning('Finalize Process - Finished. Payment was cancelled, CancelledEvent fired', $logData); + + $paymentCancelledEvent = new CancelledEvent($payment, $order, $customer, $context); + $this->eventDispatcher->dispatch($paymentCancelledEvent); + + throw PaymentException::customerCanceled($transaction->getOrderTransactionId(), $message); + } + + if ($paymentStatus->isFailed()) { + $message = sprintf('Payment for order %s (%s) is failed', $orderNumber, $payment->getId()); + + $this->logger->warning('Finalize Process - Finished. Payment is failed, FailedEvent fired', $logData); + + $paymentFailedEvent = new FailedEvent($payment, $order, $customer, $context); + $this->eventDispatcher->dispatch($paymentFailedEvent); + + throw PaymentException::asyncFinalizeInterrupted($transaction->getOrderTransactionId(), $message); + } + $this->logger->info('Finalize Process - Finished. Payment is successful, SuccessEvent fired', $logData); + $paymentSuccessEvent = new SuccessEvent($payment, $order, $customer, $context); + $this->eventDispatcher->dispatch($paymentSuccessEvent); + } +} diff --git a/shopware/Component/Payment/Action/Pay.php b/shopware/Component/Payment/Action/Pay.php new file mode 100644 index 000000000..789c74a41 --- /dev/null +++ b/shopware/Component/Payment/Action/Pay.php @@ -0,0 +1,158 @@ +getOrderTransactionId(); + $shopwareFinalizeUrl = (string) $transaction->getReturnUrl(); + + $transactionDataStruct = $this->transactionService->findById($transactionId, $context); + + $order = $transactionDataStruct->getOrder(); + $transaction = $transactionDataStruct->getTransaction(); + $orderNumber = (string) $order->getOrderNumber(); + $salesChannel = $transactionDataStruct->getSalesChannel(); + $salesChannelName = (string) $salesChannel->getName(); + + $logData = [ + 'salesChannel' => $salesChannelName, + 'paymentMethod' => $paymentHandler->getPaymentMethod()->value, + 'orderNumber' => $orderNumber, + 'transactionId' => $transactionId, + ]; + + $this->logger->info('Payment Process - Start', $logData); + + $createPaymentStruct = $this->createPaymentBuilder->build($transactionDataStruct, $paymentHandler, $dataBag, $context); + + $countPayments = $this->updatePaymentCounter($transaction, $createPaymentStruct); + + /** @var RequestDataBag $paymentMethods */ + $paymentMethods = $dataBag->get('paymentMethods', new DataBag()); + + if ($paymentMethods->count() > 0) { + $createPaymentStruct->setMethods($paymentMethods->all()); + } + $paymentEvent = new ModifyCreatePaymentPayloadEvent($createPaymentStruct, $context); + /** @var ModifyCreatePaymentPayloadEvent $paymentEvent */ + $paymentEvent = $this->eventDispatcher->dispatch($paymentEvent); + $createPaymentStruct = $paymentEvent->getPayment(); + $payment = $this->mollieGateway->createPayment($createPaymentStruct, $salesChannel->getId()); + $paypalExpressAuthenticationId = $createPaymentStruct->getAuthenticationId(); + if ($paypalExpressAuthenticationId !== null) { + $payment->setAuthenticationId($paypalExpressAuthenticationId); + } + + $payment->setFinalizeUrl($shopwareFinalizeUrl); + $payment->setCountPayments($countPayments); + + $this->transactionService->savePaymentExtension($transactionId, $order, $payment, $context); + + $this->processPaymentStatus($paymentHandler, $transactionId, $orderNumber, $context); + + $redirectUrl = $payment->getCheckoutUrl(); + if ($paymentHandler instanceof PosPayment) { + $redirectUrl = $this->routeBuilder->getPosCheckoutUrl($payment, $transactionId, $orderNumber); + } + if (mb_strlen($redirectUrl) === 0) { + $redirectUrl = $shopwareFinalizeUrl; + } + + $paymentCreatedEvent = new PaymentCreatedEvent($redirectUrl, $payment, $transactionDataStruct, $dataBag, $context); + $this->eventDispatcher->dispatch($paymentCreatedEvent); + + $logData['redirectUrl'] = $redirectUrl; + $this->logger->info('Payment Process - Finished, redirecting customer to URL', $logData); + + return new RedirectResponse($redirectUrl); + } + + private function processPaymentStatus(AbstractMolliePaymentHandler $paymentHandler, string $transactionId, string $orderNumber, Context $context): void + { + $method = 'processUnconfirmed'; + $shopwareStatus = 'unconfirmed'; + if ($paymentHandler instanceof BankTransferAwareInterface) { + $method = 'process'; + $shopwareStatus = 'in_progress'; + } + $logData = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'method' => $method, + 'shopwareStatus' => $shopwareStatus, + ]; + + try { + $this->stateMachineHandler->{$method}($transactionId, $context); + $this->logger->info('Changed payment status', $logData); + } catch (IllegalTransitionException $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to change payment status', $logData); + } + } + + private function updatePaymentCounter(OrderTransactionEntity $transaction, CreatePayment $createPaymentStruct): int + { + $countPayments = 1; + $oldMollieTransaction = $transaction->getExtension(Mollie::EXTENSION); + if ($oldMollieTransaction instanceof Payment) { + $countPayments = $oldMollieTransaction->getCountPayments() + 1; + $createPaymentStruct->setDescription($createPaymentStruct->getDescription() . '-' . $countPayments); + } + + return $countPayments; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/ApplePayController.php b/shopware/Component/Payment/ApplePayDirect/ApplePayController.php new file mode 100644 index 000000000..62cc19e6c --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/ApplePayController.php @@ -0,0 +1,207 @@ + ['storefront'], 'csrf_protected' => false])] +final class ApplePayController extends StorefrontController +{ + public function __construct( + #[Autowire(service: CreateSessionRoute::class)] + private AbstractCreateSessionRoute $createSessionRoute, + #[Autowire(service: GetCartRoute::class)] + private AbstractGetCartRoute $getCartRoute, + #[Autowire(service: GetShippingMethodsRoute::class)] + private AbstractGetShippingMethodsRoute $getShippingMethodsRoute, + #[Autowire(service: SetShippingMethodRoute::class)] + private AbstractSetShippingMethodRoute $setShippingMethodRoute, + #[Autowire(service: PayRoute::class)] + private AbstractPayRoute $payRoute, + #[Autowire(service: GetApplePayIdRoute::class)] + private AbstractGetApplePayIdRoute $getApplePayIdRoute, + #[Autowire(service: ApplePayDirectEnabledRoute::class)] + private AbstractApplePayDirectEnabledRoute $applePayDirectEnabledRoute, + #[Autowire(service: RestoreCartRoute::class)] + private AbstractRestoreCartRoute $restoreCartRoute, + ) { + } + + #[Route(name: 'frontend.mollie.apple-pay.validate', path: '/mollie/apple-pay/validate', methods: ['POST'], options: ['seo' => false])] + public function createSession(Request $request, SalesChannelContext $salesChannelContext): JsonResponse + { + $session = ''; + $success = false; + try { + $response = $this->createSessionRoute->session($request, $salesChannelContext); + $success = true; + $session = $response->getSession(); + } catch (\Throwable $exception) { + } + + return new JsonResponse([ + 'data' => [ + 'success' => $success, + 'session' => json_encode($session), + ] + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.shipping-methods', path: '/mollie/apple-pay/shipping-methods', methods: ['POST'], options: ['seo' => false])] + public function updateShippingMethods(Request $request, SalesChannelContext $salesChannelContext): JsonResponse + { + $success = false; + $cart = []; + $shippingMethods = []; + $error = ''; + try { + $cartResponse = $this->getCartRoute->cart($request, $salesChannelContext); + $shippingMethodsResponse = $this->getShippingMethodsRoute->methods($request, $salesChannelContext); + + $cart = $cartResponse->getCart(); + $shippingMethods = $shippingMethodsResponse->getShippingMethods(); + $success = true; + } catch (\Throwable $exception) { + $error = $exception->getMessage(); + } + + return new JsonResponse([ + 'success' => $success, + 'shippingmethods' => $shippingMethods, + 'data' => [ + 'cart' => $cart, + 'error' => $error, + 'success' => $success, + ] + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.set-shipping', path: '/mollie/apple-pay/set-shipping', methods: ['POST'], options: ['seo' => false])] + public function setShippingMethod(Request $request, SalesChannelContext $salesChannelContext): JsonResponse + { + $cart = []; + $success = false; + $error = ''; + try { + $setShippingMethodResponse = $this->setShippingMethodRoute->setShipping($request, $salesChannelContext); + $salesChannelContext = $setShippingMethodResponse->getSalesChannelContext(); + $cartResponse = $this->getCartRoute->cart($request, $salesChannelContext); + $cart = $cartResponse->getCart(); + $success = true; + } catch (\Throwable $exception) { + $error = $exception->getMessage(); + } + + return new JsonResponse([ + 'data' => [ + 'success' => $success, + 'cart' => $cart, + 'error' => $error, + ] + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.start-payment', path: '/mollie/apple-pay/start-payment', methods: ['POST'], options: ['seo' => false])] + public function startPayment(Request $request, SalesChannelContext $salesChannelContext): Response + { + $errorSnippet = 'molliePayments.payments.applePayDirect.paymentError'; + try { + $response = $this->payRoute->pay($request, $salesChannelContext); + $orderId = $response->getOrderId(); + $finishUrl = $this->generateUrl('frontend.checkout.finish.page', ['orderId' => $orderId]); + + return new RedirectResponse($finishUrl); + } catch (ApplePayDirectException $exception) { + $this->addFlash('danger', $this->trans($errorSnippet)); + if ($exception->getErrorCode() === ApplePayDirectException::PAYMENT_FAILED) { + $orderId = $exception->getParameter('orderId'); + + return $this->forwardToRoute('frontend.account.edit-order.page', [], ['orderId' => $orderId]); + } + + return $this->forwardToRoute('frontend.checkout.confirm.page'); + } catch (\Throwable $exception) { + $this->addFlash('danger', $exception->getMessage()); + + return $this->forwardToRoute('frontend.checkout.confirm.page'); + } + } + + #[Route(name: 'frontend.mollie.apple-pay.id', path: '/mollie/apple-pay/applepay-id', methods: ['GET'], options: ['seo' => false])] + public function getApplePayId(SalesChannelContext $salesChannelContext): Response + { + $id = 'not-found'; + try { + $response = $this->getApplePayIdRoute->getId($salesChannelContext); + + $id = $response->getId() ?? $id; + } catch (\Throwable $exception) { + } + + return new JsonResponse([ + 'id' => $id, + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.available', path: '/mollie/apple-pay/available', methods: ['GET'], options: ['seo' => false])] + public function isDirectAvailable(SalesChannelContext $salesChannelContext): Response + { + $available = false; + try { + $response = $this->applePayDirectEnabledRoute->getEnabled($salesChannelContext); + $available = $response->isEnabled(); + } catch (\Throwable $exception) { + } + + return new JsonResponse([ + 'available' => $available, + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.restore-cart', path: '/mollie/apple-pay/restore-cart', methods: ['POST'], options: ['seo' => false])] + public function restoreCart(SalesChannelContext $salesChannelContext): Response + { + $success = false; + try { + $response = $this->restoreCartRoute->restore($salesChannelContext); + $success = $response->isSuccessful(); + } catch (\Throwable $exception) { + } + + return new JsonResponse([ + 'success' => $success, + ]); + } + + #[Route(name: 'frontend.mollie.apple-pay.add-product', path: '/mollie/apple-pay/add-product', methods: ['POST'], options: ['seo' => false])] + public function addProduct(SalesChannelContext $salesChannelContext): JsonResponse + { + return new JsonResponse([ + 'success' => true, + ]); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/ApplePayDirectException.php b/shopware/Component/Payment/ApplePayDirect/ApplePayDirectException.php new file mode 100644 index 000000000..b347baf40 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/ApplePayDirectException.php @@ -0,0 +1,135 @@ + $countryCode, + ] + ); + } + + public static function validationUrlNotFound(): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::INVALID_VALIDATION_URL, + 'Please provide a validation url' + ); + } + + public static function sessionRequestFailed(\Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::CREATE_SESSION_FAILED, + 'Failed to request apple pay direct session', + [], + $exception + ); + } + + public static function missingShippingMethodIdentifier(): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::MISSING_SHIPPING_METHOD, + 'Missing shipping method identifier', + ); + } + + public static function paymentTokenNotFound(): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::PAYMENT_TOKEN_NOT_FOUND, + '"paymentToken" not set in request body', + ); + } + + public static function paymentDisabled(): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::PAYMENT_DISABLED, + 'Applepay Direct payment is disabled', + ); + } + + public static function customerActionFailed(\Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::CUSTOMER_ACTION_FAILED, + 'Failed to login by email or create a customer guest account', + [], + $exception + ); + } + + public static function loadCartFailed(\Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::CART_ACTION_FAILED, + 'Failed to load apple pay cart', + [], + $exception + ); + } + + public static function createOrderFailed(\Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::ORDER_ACTION_FAILED, + 'Failed to create an order from cart', + [], + $exception + ); + } + + public static function paymentFailed(\Throwable $exception,string $orderId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::PAYMENT_FAILED, + 'Apple pay payment failed', + [ + 'orderId' => $orderId, + ], + $exception + ); + } + + public static function countryCodeEmpty(): self + { + return new self( + Response::HTTP_INTERNAL_SERVER_ERROR, + self::ORDER_ACTION_FAILED, + 'No Country Code provided', + ); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/ApplePayStoreFrontSubscriber.php b/shopware/Component/Payment/ApplePayDirect/ApplePayStoreFrontSubscriber.php new file mode 100644 index 000000000..6a352fc65 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/ApplePayStoreFrontSubscriber.php @@ -0,0 +1,67 @@ + 'onStorefrontRender', + ]; + } + + public function onStorefrontRender(StorefrontRenderEvent $event): void + { + $salesChannelContext = $event->getSalesChannelContext(); + $salesChannel = $salesChannelContext->getSalesChannel(); + + $salesChannelId = $salesChannel->getId(); + + try { + $response = $this->applePayDirectEnabledRoute->getEnabled($salesChannelContext); + + $applePayMethodId = $response->getPaymentMethodId(); + + if ($applePayMethodId === null) { + return; + } + $accountSettings = $this->settings->getAccountSettings($salesChannelId); + $applePaySettings = $this->settings->getApplePaySettings($salesChannelId); + $shoPhoneNumberField = $accountSettings->isPhoneFieldShown() || $accountSettings->isPhoneFieldRequired(); + $isNotLoggedIn = $salesChannelContext->getCustomer() === null; + + $event->setParameter('apple_pay_payment_method_id', $applePayMethodId); + $event->setParameter('mollie_applepaydirect_phonenumber_required', (int) $shoPhoneNumberField); + $event->setParameter('mollie_applepaydirect_enabled', $response->isEnabled()); + + $event->setParameter('mollie_applepaydirect_restrictions', $applePaySettings->getVisibilityRestrictions()); + $event->setParameter('mollie_express_required_data_protection', $isNotLoggedIn && $accountSettings->isDataProtectionEnabled()); + } catch (\Throwable $exception) { + $this->logger->error('Failed to assign apple pay direct data to storefront', [ + 'error' => $exception->getMessage(), + 'salesChannelId' => $salesChannelId, + ]); + } + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/AbstractApplePayDirectEnabledRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/AbstractApplePayDirectEnabledRoute.php new file mode 100644 index 000000000..32e71580d --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/AbstractApplePayDirectEnabledRoute.php @@ -0,0 +1,13 @@ + + */ +final class AddProductResponse extends StoreApiResponse +{ + public function __construct() + { + $object = new ArrayStruct( + ['cart' => []], + 'mollie_payments_applepay_direct_cart' + ); + parent::__construct($object); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/AddProductRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/AddProductRoute.php new file mode 100644 index 000000000..9f2a80ce3 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/AddProductRoute.php @@ -0,0 +1,29 @@ + ['store-api']])] +final class AddProductRoute +{ + public function __construct( + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(name: 'store-api.mollie.apple-pay.add-product',path: '/store-api/mollie/applepay/add-product', methods: ['POST'])] + public function addProduct(SalesChannelContext $salesChannelContext): AddProductResponse + { + $this->logger->warning('Deprecated add product route for apple pay was called. Please use shopware default addCartItemRoute with "isExpressCheckout" in request body'); + + return new AddProductResponse(); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledResponse.php new file mode 100644 index 000000000..61a69afa6 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledResponse.php @@ -0,0 +1,36 @@ + + */ +final class ApplePayDirectEnabledResponse extends StoreApiResponse +{ + public function __construct(private bool $enabled,private ?string $paymentMethodId = null) + { + $object = new ArrayStruct( + [ + 'enabled' => $this->enabled, + 'paymentMethodId' => $this->paymentMethodId, + ], + 'mollie_payments_applepay_direct_enabled' + ); + + parent::__construct($object); + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + public function getPaymentMethodId(): ?string + { + return $this->paymentMethodId; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledRoute.php new file mode 100644 index 000000000..efba8a0df --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/ApplePayDirectEnabledRoute.php @@ -0,0 +1,48 @@ + ['store-api']])] +final class ApplePayDirectEnabledRoute extends AbstractApplePayDirectEnabledRoute +{ + public function __construct( + #[Autowire(service: PaymentMethodRepository::class)] + private PaymentMethodRepositoryInterface $paymentMethodRepository, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService + ) { + } + + public function getDecorated(): AbstractApplePayDirectEnabledRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.apple-pay.enabled', path: '/store-api/mollie/applepay/enabled', methods: ['GET'])] + public function getEnabled(SalesChannelContext $salesChannelContext): ApplePayDirectEnabledResponse + { + $enabled = false; + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $id = $this->paymentMethodRepository->getIdByPaymentHandler(ApplePayPayment::class, $salesChannelId, $salesChannelContext->getContext()); + + if ($id !== null) { + $applePaySettings = $this->settingsService->getApplePaySettings($salesChannelContext->getSalesChannelId()); + $enabled = $applePaySettings->isApplePayDirectEnabled(); + } + + return new ApplePayDirectEnabledResponse($enabled, $id); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionResponse.php new file mode 100644 index 000000000..0a8d94265 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionResponse.php @@ -0,0 +1,34 @@ + + */ +final class CreateSessionResponse extends StoreApiResponse +{ + /** + * @param array $session + */ + public function __construct(private array $session) + { + $object = new ArrayStruct( + ['session' => $session], + 'mollie_payments_applepay_direct_session' + ); + + parent::__construct($object); + } + + /** + * @return mixed[] + */ + public function getSession(): array + { + return $this->session; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionRoute.php new file mode 100644 index 000000000..1a9abe744 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/CreateSessionRoute.php @@ -0,0 +1,90 @@ + ['store-api']])] +final class CreateSessionRoute extends AbstractCreateSessionRoute +{ + public function __construct( + #[Autowire(service: ApplePayGateway::class)] + private ApplePayGatewayInterface $gateway, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractCreateSessionRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/applepay/validate', name: 'store-api.mollie.apple-pay.validate', methods: ['POST'])] + public function session(Request $request, SalesChannelContext $salesChannelContext): CreateSessionResponse + { + $validationUrl = $request->get('validationUrl'); + $domain = $request->get('domain', ''); + $salesChannel = $salesChannelContext->getSalesChannel(); + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $logData = [ + 'domain' => $domain, + 'validationUrl' => $validationUrl, + 'salesChannelId' => $salesChannelId, + ]; + + $this->logger->info('Apple pay direct session was requested', $logData); + if ($validationUrl === null) { + $this->logger->warning('Validation Url from apple pay JavaScript was not provided', $logData); + throw ApplePayDirectException::validationUrlNotFound(); + } + + if (mb_strlen($domain) > 0) { + $this->logger->debug('Custom domain was provided, validating', $logData); + $applePaySettings = $this->settingsService->getApplePaySettings($salesChannelId); + $allowedDomain = in_array($domain, $applePaySettings->getAllowDomainList()); + if (! $allowedDomain) { + $logData['allowedDomains'] = $domain; + $this->logger->error('Custom domain was provided but it is not in the allow list, please add the domain to allowed domain list in plugin configuration', $logData); + throw new \InvalidArgumentException(sprintf('Creating session from domain %s is now allowed', $domain)); + } + } + $salesChannelDomains = $salesChannel->getDomains(); + if (mb_strlen($domain) === 0 && $salesChannelDomains instanceof SalesChannelDomainCollection) { + $salesChannelDomain = $salesChannelDomains->get((string) $salesChannelContext->getDomainId()); + if ($salesChannelDomain instanceof SalesChannelDomainEntity) { + $domain = $salesChannelDomain->getUrl(); + } + $logData['domain'] = $domain; + $this->logger->debug('Custom domain was not provided, using shopware storefront domain', $logData); + } + + try { + $session = $this->gateway->requestSession($domain, $validationUrl, $salesChannelContext->getSalesChannelId()); + $this->logger->info('Apple pay session successfully requested', $logData); + } catch (\Throwable $exception) { + $logData['exception'] = $exception->getMessage(); + $this->logger->error('Failed to request apple pay direct session', $logData); + throw ApplePayDirectException::sessionRequestFailed($exception); + } + + return new CreateSessionResponse($session); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdResponse.php new file mode 100644 index 000000000..490186638 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdResponse.php @@ -0,0 +1,31 @@ + + */ +final class GetApplePayIdResponse extends StoreApiResponse +{ + public function __construct(private ?string $id) + { + $object = new ArrayStruct( + [ + 'success' => $this->id !== null, + 'id' => $id, + ], + 'mollie_payments_applepay_direct_id' + ); + + parent::__construct($object); + } + + public function getId(): ?string + { + return $this->id; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdRoute.php new file mode 100644 index 000000000..402eb2548 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetApplePayIdRoute.php @@ -0,0 +1,43 @@ + ['store-api']])] +final class GetApplePayIdRoute extends AbstractGetApplePayIdRoute +{ + public function __construct( + #[Autowire(service: PaymentMethodRepository::class)] + private PaymentMethodRepositoryInterface $paymentMethodRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractGetApplePayIdRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.apple-pay.id', path: '/store-api/mollie/applepay/id', methods: ['GET'])] + public function getId(SalesChannelContext $salesChannelContext): GetApplePayIdResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $applePayMethodId = $this->paymentMethodRepository->getIdByPaymentHandler(ApplePayPayment::class, $salesChannelId, $salesChannelContext->getContext()); + + $this->logger->warning('Route get apple pay id route is deprecated, please use the enabled'); + + return new GetApplePayIdResponse($applePayMethodId); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetCartResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/GetCartResponse.php new file mode 100644 index 000000000..4910153ee --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetCartResponse.php @@ -0,0 +1,33 @@ + + */ +final class GetCartResponse extends StoreApiResponse +{ + public function __construct(private ApplePayCart $cart, private ShopwareCart $shopwareCart) + { + $response = new ArrayStruct([ + 'cart' => $this->cart, + ],'mollie_payments_applepay_direct_cart'); + parent::__construct($response); + } + + public function getCart(): ApplePayCart + { + return $this->cart; + } + + public function getShopwareCart(): ShopwareCart + { + return $this->shopwareCart; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetCartRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/GetCartRoute.php new file mode 100644 index 000000000..e0b0108e8 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetCartRoute.php @@ -0,0 +1,144 @@ + ['store-api']])] +final class GetCartRoute extends AbstractGetCartRoute +{ + public function __construct( + private CartService $cartService, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: Translator::class)] + private AbstractTranslator $translator, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractGetCartRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.apple-pay.cart', path: '/store-api/mollie/applepay/cart', methods: ['GET'])] + public function cart(Request $request, SalesChannelContext $salesChannelContext): GetCartResponse + { + $localeCode = ''; + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $languageInfo = $salesChannelContext->getLanguageInfo(); + /** @phpstan-ignore-next-line */ + if ($languageInfo instanceof LanguageInfo) { + $localeCode = $languageInfo->localeCode; + } + $logData = [ + 'localeCode' => $localeCode, + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->info('Start - Apple Pay cart route request', $logData); + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + + $applePayCart = $this->getApplePayCart($cart, $salesChannelContext, $localeCode); + + $this->logger->info('Finished - Apple Pay cart route request', $logData); + + return new GetCartResponse($applePayCart, $cart); + } + + private function getApplePayCart(Cart $cart, SalesChannelContext $salesChannelContext, string $localeCode): ApplePayCart + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $apiSettings = $this->settingsService->getApiSettings($salesChannelId); + $shopName = (string) $salesChannelContext->getSalesChannel()->getName(); + $isTestMode = $apiSettings->isTestMode(); + + $this->translator->injectSettings($salesChannelId, $salesChannelContext->getLanguageId(), $localeCode, $salesChannelContext->getContext()); + + $testModeLabel = $this->translator->trans('molliePayments.testMode.label'); + if (mb_strlen($testModeLabel) === 0) { + $testModeLabel = 'Test mode'; + } + $subTotalLabel = $this->translator->trans('molliePayments.payments.applePayDirect.captionSubtotal'); + if (mb_strlen($subTotalLabel) === 0) { + $subTotalLabel = 'Subtotal'; + } + $taxLabel = $this->translator->trans('molliePayments.payments.applePayDirect.captionTaxes'); + if (mb_strlen($taxLabel) === 0) { + $taxLabel = 'Taxes'; + } + + if ($isTestMode) { + $shopName = sprintf('%s (%s)', $shopName, $testModeLabel); + } + $price = $cart->getPrice(); + + $applePayCart = new ApplePayCart($shopName, new ApplePayAmount($price->getTotalPrice())); + + $taxAmount = 0.0; + $subTotal = 0.0; + + foreach ($cart->getLineItems() as $lineItem) { + $totalPrice = 0.0; + + $price = $lineItem->getPrice(); + if ($price instanceof CalculatedPrice) { + $totalPrice = $price->getTotalPrice(); + /** @var CalculatedTax $tax */ + foreach ($price->getCalculatedTaxes() as $tax) { + $taxAmount += $tax->getTax(); + } + } + $subTotal += $totalPrice; + $item = new ApplePayLineItem((string) $lineItem->getLabel(), new ApplePayAmount($totalPrice)); + $applePayCart->addItem($item); + } + + $taxItem = new ApplePayLineItem($subTotalLabel, new ApplePayAmount($subTotal)); + $applePayCart->addItem($taxItem); + + /** @var Delivery $delivery */ + foreach ($cart->getDeliveries() as $delivery) { + $shippingCosts = $delivery->getShippingCosts(); + $deliveryTaxes = $shippingCosts->getCalculatedTaxes(); + + /** @var CalculatedTax $tax */ + foreach ($deliveryTaxes as $tax) { + $taxAmount += $tax->getTax(); + } + + $item = new ApplePayShippingLineItem((string) $delivery->getShippingMethod()->getName(), new ApplePayAmount($shippingCosts->getTotalPrice())); + $applePayCart->addItem($item); + } + + if ($taxAmount > 0) { + $taxItem = new ApplePayLineItem($taxLabel, new ApplePayAmount($taxAmount)); + $applePayCart->addItem($taxItem); + } + + return $applePayCart; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsResponse.php new file mode 100644 index 000000000..19d118c65 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsResponse.php @@ -0,0 +1,34 @@ + + */ +final class GetShippingMethodsResponse extends StoreApiResponse +{ + /** + * @param ApplePayShippingMethod[] $shippingMethods + */ + public function __construct(private array $shippingMethods) + { + $object = new ArrayStruct([ + 'shippingMethods' => $shippingMethods, + ], + 'mollie_payments_applepay_direct_shipping_methods'); + parent::__construct($object); + } + + /** + * @return ApplePayShippingMethod[] + */ + public function getShippingMethods(): array + { + return $this->shippingMethods; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsRoute.php new file mode 100644 index 000000000..cbb7a2310 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/GetShippingMethodsRoute.php @@ -0,0 +1,238 @@ + ['store-api']])] +final class GetShippingMethodsRoute extends AbstractGetShippingMethodsRoute +{ + /** + * @param EntityRepository> $customerAddressRepository + * @param EntityRepository> $countryRepository + */ + public function __construct( + #[Autowire(service: CheckoutGatewayRoute::class)] + private AbstractCheckoutGatewayRoute $checkoutGatewayRoute, + #[Autowire(service: SetShippingMethodRoute::class)] + private AbstractSetShippingMethodRoute $setShippingMethodRoute, + #[Autowire(service: SalesChannelContextService::class)] + private SalesChannelContextServiceInterface $salesChannelContextService, + #[Autowire(service: ContextSwitchRoute::class)] + private AbstractContextSwitchRoute $contextSwitchRoute, + #[Autowire(service: GetCartRoute::class)] + private AbstractGetCartRoute $getCartRoute, + #[Autowire(service: 'customer_address.repository')] + private EntityRepository $customerAddressRepository, + #[Autowire(service: 'country.repository')] + private EntityRepository $countryRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractGetShippingMethodsRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/applepay/shipping-methods', name: 'store-api.mollie.apple-pay.shipping-methods', methods: ['POST'])] + public function methods(Request $request, SalesChannelContext $salesChannelContext): GetShippingMethodsResponse + { + $countryCode = $request->get('countryCode'); + + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $logData = [ + 'countryCode' => $countryCode, + 'salesChannelId' => $salesChannelId, + ]; + + $this->logger->info('Start - set shipping country for apple pay', $logData); + if ($countryCode === null) { + $this->logger->error('Failed to set shipping country for apple pay, country code is not provided', $logData); + throw ApplePayDirectException::countryCodeEmpty(); + } + $countryId = $this->getCountryId($countryCode, $salesChannelContext); + if ($countryId === null) { + $this->logger->error('Failed to find shipping country for apple pay', $logData); + throw ApplePayDirectException::invalidCountryCode($countryCode); + } + + $logData['countryId'] = $countryId; + $requestDataBag = new RequestDataBag(); + $requestDataBag->set(SalesChannelContextService::COUNTRY_ID, $countryId); + + $customer = $salesChannelContext->getCustomer(); + + $customerId = null; + if ($customer !== null) { + $customerId = $customer->getId(); + } + + $requestDataBag = $this->addFakeAddress($requestDataBag, $countryId, $logData, $salesChannelContext); + + $contextSwitchResponse = $this->contextSwitchRoute->switchContext($requestDataBag, $salesChannelContext); + + $salesChannelContextServiceParameters = new SalesChannelContextServiceParameters( + $salesChannelContext->getSalesChannelId(), + $contextSwitchResponse->getToken(), + originalContext: $salesChannelContext->getContext(), + customerId: $customerId + ); + + $newContext = $this->salesChannelContextService->get($salesChannelContextServiceParameters); + + $this->logger->info('Finished - set shipping country for apple pay', $logData); + + $cartResponse = $this->getCartRoute->cart($request, $newContext); + + $request->query->set('onlyAvailable', '1'); + $checkoutResponse = $this->checkoutGatewayRoute->load($request, $cartResponse->getShopwareCart(), $salesChannelContext); + + $selectedShippingMethodId = $salesChannelContext->getShippingMethod()->getId(); + $salesChannelId = $salesChannelContext->getSalesChannelId(); + + $logData = [ + 'shippingMethodId' => $selectedShippingMethodId, + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->info('Start - get shipping methods for apple pay express', $logData); + + $applePayMethods = []; + $shippingMethods = $checkoutResponse->getShippingMethods(); + + /** @var ShippingMethodEntity $shippingMethod */ + foreach ($shippingMethods as $shippingMethod) { + $detail = ''; + $shippingMethodId = $shippingMethod->getId(); + $deliveryTime = $shippingMethod->getDeliveryTime(); + if ($deliveryTime instanceof DeliveryTimeEntity) { + $detail = (string) $deliveryTime->getName(); + } + $tempContext = $this->setShippingMethod($shippingMethodId, $salesChannelContext); + $cartResponse = $this->getCartRoute->cart($request, $tempContext); + + $cart = $cartResponse->getCart(); + $shippingCosts = $cart->getShippingAmount(); + + $applePayMethods[$shippingMethodId] = new ApplePayShippingMethod($shippingMethod->getId(), (string) $shippingMethod->getName(), $detail, $shippingCosts); + } + + $this->setShippingMethod($selectedShippingMethodId, $salesChannelContext); + + $applePayMethods = $this->setSelectedMethodToFirstElement($applePayMethods, $selectedShippingMethodId); + + $this->deleteFakeAddress($salesChannelContext); + + $this->logger->info('Finished - get shipping methods for apple pay express', $logData); + + return new GetShippingMethodsResponse($applePayMethods); + } + + /** + * @param array $logData + */ + public function addFakeAddress(RequestDataBag $requestDataBag, string $countryId, array $logData, SalesChannelContext $salesChannelContext): RequestDataBag + { + $customer = $salesChannelContext->getCustomer(); + if ($customer === null) { + return $requestDataBag; + } + $customerId = $customer->getId(); + $fakeApplePayAddress = new FakeApplePayAddress($customer, $countryId); + $fakeApplePayAddressId = FakeApplePayAddress::getId($customer); + $logData['customerId'] = $customerId; + $logData['addressId'] = $fakeApplePayAddressId; + $this->logger->info('Customer is logged in, fake apple pay address added for cart rules', $logData); + + $this->customerAddressRepository->upsert([$fakeApplePayAddress->toUpsertArray()], $salesChannelContext->getContext()); + + $requestDataBag->set(SalesChannelContextService::CUSTOMER_ID, $customerId); + $requestDataBag->set(SalesChannelContextService::SHIPPING_ADDRESS_ID, $fakeApplePayAddressId); + $requestDataBag->set(SalesChannelContextService::BILLING_ADDRESS_ID, $fakeApplePayAddressId); + + return $requestDataBag; + } + + public function deleteFakeAddress(SalesChannelContext $salesChannelContext): void + { + $customer = $salesChannelContext->getCustomer(); + if ($customer === null) { + return; + } + + $fakeAddressId = FakeApplePayAddress::getId($customer); + $this->customerAddressRepository->delete([ + [ + 'id' => $fakeAddressId, + ] + ], $salesChannelContext->getContext()); + } + + private function setShippingMethod(string $shippingMethodId, SalesChannelContext $salesChannelContext): SalesChannelContext + { + $request = new Request(); + $request->attributes->set('identifier', $shippingMethodId); + $setShippingMethodResponse = $this->setShippingMethodRoute->setShipping($request, $salesChannelContext); + + return $setShippingMethodResponse->getSalesChannelContext(); + } + + /** + * @param ApplePayShippingMethod[] $applePayMethods + * + * @return ApplePayShippingMethod[] + */ + private function setSelectedMethodToFirstElement(array $applePayMethods, string $selectedShippingMethodId): array + { + $selectedShippingMethod = $applePayMethods[$selectedShippingMethodId]; + + unset($applePayMethods[$selectedShippingMethodId]); + $applePayMethods = array_values($applePayMethods); + array_unshift($applePayMethods, $selectedShippingMethod); + + return $applePayMethods; + } + + private function getCountryId(string $countryCode, SalesChannelContext $salesChannelContext): ?string + { + $criteria = new Criteria(); + $criteria->addAssociation('salesChannels'); + $criteria->addFilter(new EqualsFilter('active', 1)); + $criteria->addFilter(new EqualsFilter('shippingAvailable', 1)); + $criteria->addFilter(new EqualsFilter('salesChannels.id', $salesChannelContext->getSalesChannelId())); + $criteria->addFilter(new EqualsFilter('iso', $countryCode)); + + $searchResult = $this->countryRepository->searchIds($criteria, $salesChannelContext->getContext()); + + return $searchResult->firstId(); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/PayResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/PayResponse.php new file mode 100644 index 000000000..bf5df4950 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/PayResponse.php @@ -0,0 +1,44 @@ + + */ +final class PayResponse extends StoreApiResponse +{ + public function __construct(bool $success, private string $redirectUrl,string $message,private string $orderId,private SalesChannelContext $salesChannelContext) + { + $object = new ArrayStruct( + [ + 'success' => $success, + 'url' => $redirectUrl, + 'message' => $message, + 'orderId' => $orderId, + ], + 'mollie_payments_applepay_direct_payment' + ); + + parent::__construct($object); + } + + public function getRedirectUrl(): string + { + return $this->redirectUrl; + } + + public function getOrderId(): string + { + return $this->orderId; + } + + public function getSalesChannelContext(): SalesChannelContext + { + return $this->salesChannelContext; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/PayRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/PayRoute.php new file mode 100644 index 000000000..6fa34904d --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/PayRoute.php @@ -0,0 +1,148 @@ + ['store-api']])] +final class PayRoute extends AbstractPayRoute +{ + public function __construct( + #[Autowire(service: AccountService::class)] + private AbstractAccountService $accountService, + #[Autowire(service: CartOrderRoute::class)] + private AbstractCartOrderRoute $cartOrderRoute, + #[Autowire(service: HandlePaymentMethodRoute::class)] + private AbstractHandlePaymentMethodRoute $handlePaymentMethodRoute, + #[Autowire(service: GetCartRoute::class)] + private AbstractGetCartRoute $getCartRoute, + #[Autowire(service: ApplePayDirectEnabledRoute::class)] + private AbstractApplePayDirectEnabledRoute $applePayDirectEnabledRoute, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractPayRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/applepay/pay', name: 'store-api.apple-pay.pay', methods: ['POST'])] + public function pay(Request $request, SalesChannelContext $salesChannelContext): PayResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $logData = [ + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->info('Start - applepay direct payment', $logData); + $response = $this->applePayDirectEnabledRoute->getEnabled($salesChannelContext); + + $applePayPaymentMethodId = $response->getPaymentMethodId(); + $applePayDirectEnabled = $response->isEnabled(); + if ($applePayDirectEnabled === false && $applePayPaymentMethodId === null) { + $this->logger->error('Apple pay direct ist disabled', $logData); + throw ApplePayDirectException::paymentDisabled(); + } + + $paymentToken = $request->get('paymentToken'); + + if ($paymentToken === null) { + $this->logger->error('"paymentToken" not set in request body', $logData); + throw ApplePayDirectException::paymentTokenNotFound(); + } + + $email = (string) $request->get('email', ''); + $firstname = (string) $request->get('firstname', ''); + $lastname = (string) $request->get('lastname', ''); + $street = (string) $request->get('street', ''); + $zipcode = (string) $request->get('postalCode', ''); + $city = (string) $request->get('city', ''); + $countryCode = (string) $request->get('countryCode', ''); + $phone = (string) $request->get('phone', ''); + $acceptedDataProtection = (int) $request->get('acceptedDataProtection', '0'); + + $billingAddress = new Address($email, '', $firstname, $lastname, $street, $zipcode, $city, $countryCode); + if (mb_strlen($phone) > 0) { + $billingAddress->setPhone($phone); + } + $shippingAddress = $billingAddress; + + try { + $salesChannelContext = $this->accountService->loginOrCreateAccount((string) $applePayPaymentMethodId, $billingAddress, $shippingAddress, $salesChannelContext); + $customer = $salesChannelContext->getCustomer(); + if ($customer instanceof CustomerEntity) { + $logData['customerNumber'] = $customer->getCustomerNumber(); + $logData['customerId'] = $customer->getId(); + } + + $this->logger->debug('Login or create account successfull', $logData); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to create a guest account or login with existing customer', $logData); + throw ApplePayDirectException::customerActionFailed($exception); + } + + try { + $cartResponse = $this->getCartRoute->cart($request, $salesChannelContext); + $this->logger->debug('Apple pay direct cart loaded', $logData); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to load apple pay direct cart', $logData); + throw ApplePayDirectException::loadCartFailed($exception); + } + + try { + $orderResponse = $this->cartOrderRoute->order($cartResponse->getShopwareCart(), $salesChannelContext, new RequestDataBag()); + $orderEntity = $orderResponse->getOrder(); + $orderId = $orderEntity->getId(); + $logData['orderId'] = $orderId; + $logData['orderNumber'] = $orderEntity->getOrderNumber(); + $this->logger->debug('Apple pay direct order created', $logData); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to create an apple pay direct order', $logData); + throw ApplePayDirectException::createOrderFailed($exception); + } + + try { + $request = new Request(); + $request->request->set('orderId', $orderId); + $request->request->set('paymentToken', $paymentToken); + $handlePaymentResponse = $this->handlePaymentMethodRoute->load($request, $salesChannelContext); + $this->logger->debug('Apple pay direct payment handled', $logData); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to handle apple pay direct payment', $logData); + throw ApplePayDirectException::paymentFailed($exception, $orderId); + } + $redirectUrl = ''; + $redirectResponse = $handlePaymentResponse->getRedirectResponse(); + if ($redirectResponse instanceof RedirectResponse) { + $redirectUrl = $redirectResponse->getTargetUrl(); + } + $logData['redirectUrl'] = $redirectUrl; + $this->logger->info('Finished - applepay direct payment', $logData); + + return new PayResponse(true, $redirectUrl, '', $orderId,$salesChannelContext); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartResponse.php new file mode 100644 index 000000000..d937c9d52 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartResponse.php @@ -0,0 +1,23 @@ + + */ +final class RestoreCartResponse extends StoreApiResponse +{ + public function __construct(bool $success) + { + $object = new ArrayStruct( + ['success' => $success], + 'mollie_payments_applepay_direct_cart_restored' + ); + + parent::__construct($object); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartRoute.php new file mode 100644 index 000000000..636e83860 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/RestoreCartRoute.php @@ -0,0 +1,49 @@ + ['store-api']])] +final class RestoreCartRoute extends AbstractRestoreCartRoute +{ + public function __construct( + #[Autowire(service: CartBackupService::class)] + private AbstractCartBackupService $cartBackupService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractRestoreCartRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/applepay/restore-cart', name: 'store-api.mollie.apple-pay.restore-cart', methods: ['POST'])] + public function restore(SalesChannelContext $salesChannelContext): RestoreCartResponse + { + $success = false; + $salesChannelId = $salesChannelContext->getSalesChannelId(); + + try { + $this->cartBackupService->restoreCart($salesChannelContext); + $this->cartBackupService->clearBackup($salesChannelContext); + $success = true; + $this->logger->debug('Original cart was restored in apple pay direct',['salesChannelId' => $salesChannelId]); + } catch (\Throwable $exception) { + $this->logger->error('Failed to restore cart in apple pay direct',['salesChannelId' => $salesChannelId]); + } + + return new RestoreCartResponse($success); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodResponse.php b/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodResponse.php new file mode 100644 index 000000000..5078e3eb8 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodResponse.php @@ -0,0 +1,29 @@ + + */ +final class SetShippingMethodResponse extends StoreApiResponse +{ + public function __construct(private SalesChannelContext $salesChannelContext) + { + $response = new ArrayStruct([ + 'salesChannelContextToken' => $this->salesChannelContext->getToken(), + ], + 'mollie_payments_applepay_direct_shipping_updated' + ); + parent::__construct($response); + } + + public function getSalesChannelContext(): SalesChannelContext + { + return $this->salesChannelContext; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodRoute.php b/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodRoute.php new file mode 100644 index 000000000..7829326bd --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Route/SetShippingMethodRoute.php @@ -0,0 +1,71 @@ + ['store-api']])] +final class SetShippingMethodRoute extends AbstractSetShippingMethodRoute +{ + public function __construct( + #[Autowire(service: ContextSwitchRoute::class)] + private AbstractContextSwitchRoute $contextSwitchRoute, + #[Autowire(service: SalesChannelContextService::class)] + private SalesChannelContextServiceInterface $salesChannelContextService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractSetShippingMethodRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.apple-pay.set-shipping-methods', path: '/store-api/mollie/applepay/shipping-method', methods: ['POST'])] + public function setShipping(Request $request, SalesChannelContext $salesChannelContext): SetShippingMethodResponse + { + $shippingMethodId = $request->get('identifier'); + $salesChannelId = $salesChannelContext->getSalesChannelId(); + + $logData = [ + 'shippingMethodId' => $shippingMethodId, + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->info('Start - set apple pay shipping method', $logData); + if ($shippingMethodId === null) { + $this->logger->error('Shipping method id not set', $logData); + throw ApplePayDirectException::missingShippingMethodIdentifier(); + } + + $requestDataBag = new RequestDataBag(); + $requestDataBag->set(SalesChannelContextService::SHIPPING_METHOD_ID, $shippingMethodId); + $contextSwitchResponse = $this->contextSwitchRoute->switchContext($requestDataBag, $salesChannelContext); + + $salesChannelContextServiceParameters = new SalesChannelContextServiceParameters( + $salesChannelContext->getSalesChannelId(), + $contextSwitchResponse->getToken(), + originalContext: $salesChannelContext->getContext(), + customerId: $salesChannelContext->getCustomerId() + ); + $newContext = $this->salesChannelContextService->get($salesChannelContextServiceParameters); + $this->logger->info('Finsihed - set apple pay shipping method', $logData); + + return new SetShippingMethodResponse($newContext); + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayAmount.php b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayAmount.php new file mode 100644 index 000000000..31272a532 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayAmount.php @@ -0,0 +1,21 @@ +value; + } + + public function jsonSerialize(): mixed + { + return $this->value; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayCart.php b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayCart.php new file mode 100644 index 000000000..b4c8dc4d9 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayCart.php @@ -0,0 +1,60 @@ +total = new ApplePayLineItem($this->label, $this->amount); + } + + public function addItem(ApplePayLineItem $item): void + { + $this->items[] = $item; + } + + public function getApiAlias(): string + { + return 'mollie_payments_applepay_direct_cart'; + } + + public function getShippingAmount(): ApplePayAmount + { + $amount = 0.0; + foreach ($this->items as $item) { + if ($item instanceof ApplePayShippingLineItem) { + $amount += $item->getAmount()->getValue(); + } + } + + return new ApplePayAmount($amount); + } + + /** + * @return array + */ + public function jsonSerialize(): array + { + $vars = get_object_vars($this); + unset($vars['extensions']); + $this->convertDateTimePropertiesToJsonStringRepresentation($vars); + + return $vars; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayLineItem.php b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayLineItem.php new file mode 100644 index 000000000..7b73751e0 --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayLineItem.php @@ -0,0 +1,33 @@ +label; + } + + public function getAmount(): ApplePayAmount + { + return $this->amount; + } + + public function getType(): string + { + return $this->type; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayShippingLineItem.php b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayShippingLineItem.php new file mode 100644 index 000000000..5dd94beda --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Struct/ApplePayShippingLineItem.php @@ -0,0 +1,8 @@ +identifier; + } + + public function getLabel(): string + { + return $this->label; + } + + public function getDetail(): string + { + return $this->detail; + } + + public function getAmount(): ApplePayAmount + { + return $this->amount; + } +} diff --git a/shopware/Component/Payment/ApplePayDirect/Struct/FakeApplePayAddress.php b/shopware/Component/Payment/ApplePayDirect/Struct/FakeApplePayAddress.php new file mode 100644 index 000000000..577c4071e --- /dev/null +++ b/shopware/Component/Payment/ApplePayDirect/Struct/FakeApplePayAddress.php @@ -0,0 +1,43 @@ +getId() . '-' . self::ID_SUFFIX, true)); + } + + /** + * @return array + */ + public function toUpsertArray(): array + { + return [ + 'id' => $this->getId($this->customer), + 'salutationId' => $this->customer->getSalutationId(), + 'countryId' => $this->countryId, + 'customerId' => $this->customer->getId(), + 'firstName' => $this->customer->getFirstName(), + 'lastName' => $this->customer->getLastName(), + 'city' => 'not provided', // city is not necessary for rule builder + 'street' => 'not provided', // apple pay event "onshippingcontactselected" does not provide a street https://developer.apple.com/documentation/apple_pay_on_the_web/applepaysession/1778009-onshippingcontactselected + ]; + } +} diff --git a/shopware/Component/Payment/Controller/PaymentController.php b/shopware/Component/Payment/Controller/PaymentController.php new file mode 100644 index 000000000..b6957867e --- /dev/null +++ b/shopware/Component/Payment/Controller/PaymentController.php @@ -0,0 +1,119 @@ + ['storefront'], 'csrf_protected' => false])] +final class PaymentController extends StorefrontController +{ + public function __construct( + #[Autowire(service: ReturnRoute::class)] + private AbstractReturnRoute $returnRoute, + #[Autowire(service: WebhookRoute::class)] + private AbstractWebhookRoute $webhookRoute, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: 'event_dispatcher')] + private EventDispatcherInterface $eventDispatcher, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/mollie/payment/{transactionId}', name: 'frontend.mollie.payment', methods: ['GET', 'POST'], options: ['seo' => false])] + public function return(string $transactionId, SalesChannelContext $salesChannelContext): Response + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $logData = [ + 'transactionId' => $transactionId, + 'salesChannelId' => $salesChannelId, + ]; + $this->logger->debug('Returning from Payment Provider', $logData); + $response = $this->returnRoute->return($transactionId, $salesChannelContext->getContext()); + $paymentStatus = $response->getPaymentStatus(); + $payment = $response->getPayment(); + + $paymentSettings = $this->settingsService->getPaymentSettings($salesChannelId); + + $logData['paymentStatus'] = $paymentStatus->value; + $logData['paymentId'] = $payment->getId(); + + $orderTransaction = $payment->getShopwareTransaction(); + $shopwareOrder = $orderTransaction->getOrder(); + if ($shopwareOrder instanceof OrderEntity) { + $logData['orderNumber'] = (string) $shopwareOrder->getOrderNumber(); + + if ($paymentStatus->isFailed() && ! $paymentSettings->isShopwareFailedPayment()) { + $paymentFailedEvent = new PaymentPageFailedEvent( + $transactionId, + $shopwareOrder, + $payment, + $salesChannelContext + ); + $this->logger->info('Payment failed, send PaymentPageFailedEvent in mollie failure mode', $logData); + $this->eventDispatcher->dispatch($paymentFailedEvent); + } + } + + $query = (string) parse_url($response->getFinalizeUrl(), PHP_URL_QUERY); + $queryParameters = []; + parse_str($query, $queryParameters); + $this->logger->info('Call shopware finalize transaction', $logData); + $controller = sprintf('%s::%s', ShopwarePaymentController::class, 'finalizeTransaction'); + + return $this->forward($controller, [], $queryParameters); + } + + #[Route(path: '/mollie/webhook/{transactionId}', name: 'frontend.mollie.webhook', methods: ['GET', 'POST'], options: ['seo' => false])] + public function webhook(string $transactionId, Context $context): Response + { + try { + $this->logger->debug('Webhook received', [ + 'transactionId' => $transactionId, + ]); + $response = $this->webhookRoute->notify($transactionId, $context); + + return new JsonResponse($response->getObject()); + } catch (ShopwareHttpException $exception) { + $this->logger->warning( + 'Webhook request failed with warning', + [ + 'transactionId' => $transactionId, + 'message' => $exception->getMessage(), + ] + ); + + return new JsonResponse(['success' => false, 'error' => $exception->getMessage()], $exception->getStatusCode()); + } catch (\Throwable $exception) { + $this->logger->error( + 'Webhook request failed', + [ + 'transactionId' => $transactionId, + 'message' => $exception->getMessage(), + ] + ); + + return new JsonResponse(['success' => false, 'error' => $exception->getMessage()], 422); + } + } +} diff --git a/shopware/Component/Payment/Controller/PaymentMethodController.php b/shopware/Component/Payment/Controller/PaymentMethodController.php new file mode 100644 index 000000000..cf19e9b4a --- /dev/null +++ b/shopware/Component/Payment/Controller/PaymentMethodController.php @@ -0,0 +1,48 @@ + ['api']])] +final class PaymentMethodController extends AbstractController +{ + public function __construct( + private PaymentMethodInstaller $paymentMethodInstaller, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/api/_action/mollie/payment-method/update-methods', name: 'api.mollie.payment-method.update-methods', methods: ['GET'])] + public function update(Context $context): JsonResponse + { + try { + $this->paymentMethodInstaller->install($context); + $this->logger->info('Update payment methods action executed from Plugin Configuration'); + + return new JsonResponse([ + 'success' => true, + ]); + } catch (\Throwable $exception) { + $message = $exception->getMessage(); + $statusCode = $exception instanceof ShopwareHttpException ? $exception->getStatusCode() : 500; + $this->logger->error('Failed to update payment methods action ', [ + 'error' => $message, + ]); + + return new JsonResponse([ + 'success' => false, + 'message' => $message, + ], $statusCode); + } + } +} diff --git a/shopware/Component/Payment/CreatePaymentBuilder.php b/shopware/Component/Payment/CreatePaymentBuilder.php new file mode 100644 index 000000000..b8505a48d --- /dev/null +++ b/shopware/Component/Payment/CreatePaymentBuilder.php @@ -0,0 +1,245 @@ +> $customerRepository + */ + public function __construct( + #[Autowire(service: RouteBuilder::class)] + private RouteBuilderInterface $routeBuilder, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + private LineItemAnalyzer $lineItemAnalyzer, + #[Autowire(service: 'customer.repository')] + private EntityRepository $customerRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + } + + public function build(TransactionDataStruct $transactionData, AbstractMolliePaymentHandler $paymentHandler, RequestDataBag $dataBag, Context $context): CreatePayment + { + $transactionId = $transactionData->getTransaction()->getId(); + $order = $transactionData->getOrder(); + $salesChannelId = $order->getSalesChannelId(); + $customer = $transactionData->getCustomer(); + $currency = $transactionData->getCurrency(); + $language = $transactionData->getLanguage(); + $salesChannelName = (string) $transactionData->getSalesChannel()->getName(); + $shippingOrderAddress = $transactionData->getShippingOrderAddress(); + $billingOrderAddress = $transactionData->getBillingOrderAddress(); + $deliveries = $transactionData->getDeliveries(); + + $paymentSettings = $this->settingsService->getPaymentSettings($order->getSalesChannelId()); + $orderNumberFormat = $paymentSettings->getOrderNumberFormat(); + + $customerNumber = $customer->getCustomerNumber(); + $description = (string) $order->getOrderNumber(); + $orderNumber = (string) $order->getOrderNumber(); + $taxStatus = (string) $order->getTaxStatus(); + $apiSettings = $this->settingsService->getApiSettings($salesChannelId); + $profileId = $apiSettings->getProfileId(); + + if (mb_strlen($profileId) === 0) { + $profile = $this->mollieGateway->getCurrentProfile($salesChannelId); + $profileId = $profile->getId(); + } + + $logData = [ + 'salesChannel' => $salesChannelName, + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'taxStatus' => $taxStatus, + ]; + + if (mb_strlen($orderNumberFormat) > 0) { + $description = str_replace([ + '{ordernumber}', + '{customernumber}' + ], [ + $orderNumber, + $customerNumber + ], $orderNumberFormat); + } + + $returnUrl = $this->routeBuilder->getReturnUrl($transactionId); + $webhookUrl = $this->routeBuilder->getWebhookUrl($transactionId); + + $lineItemCollection = new LineItemCollection(); + $oderLineItems = $order->getLineItems(); + $hasSubscriptionLineItem = false; + if ($oderLineItems !== null) { + foreach ($oderLineItems as $lineItem) { + $lineItem = LineItem::fromOrderLine($lineItem, $currency, $taxStatus); + $lineItemCollection->add($lineItem); + } + $hasSubscriptionLineItem = $this->lineItemAnalyzer->hasSubscriptionProduct($oderLineItems); + } + + $shippingAddress = Address::fromAddress($customer, $shippingOrderAddress); + + foreach ($deliveries as $delivery) { + $deliveryOrderShippingAddress = $delivery->getShippingOrderAddress(); + if (method_exists($order, 'getPrimaryOrderDeliveryId') + && $deliveryOrderShippingAddress instanceof OrderAddressEntity + && $order->getPrimaryOrderDeliveryId() !== null + && $delivery->getId() === $order->getPrimaryOrderDeliveryId() + ) { + $shippingAddress = Address::fromAddress($customer, $deliveryOrderShippingAddress); + } + + if ($delivery->getShippingCosts()->getTotalPrice() <= 0) { + continue; + } + + $lineItem = LineItem::fromDelivery($delivery, $currency, $taxStatus); + $lineItemCollection->add($lineItem); + } + + $billingAddress = Address::fromAddress($customer, $billingOrderAddress); + + $createPaymentStruct = new CreatePayment($description, $returnUrl, Money::fromOrder($order, $currency)); + + $createPaymentStruct->setBillingAddress($billingAddress); + $createPaymentStruct->setShippingAddress($shippingAddress); + $createPaymentStruct->setLines($lineItemCollection); + $createPaymentStruct->setLocale(Locale::fromLanguage($language)); + $createPaymentStruct->setWebhookUrl($webhookUrl); + $createPaymentStruct->setShopwareOrderNumber($orderNumber); + $createPaymentStruct->setMethod($paymentHandler->getPaymentMethod()); + + if ($paymentHandler instanceof ManualCaptureModeAwareInterface) { + $createPaymentStruct->setCaptureMode(CaptureMode::MANUAL); + } + + if ($paymentHandler instanceof BankTransferAwareInterface && $paymentSettings->getDueDateDays() > 0) { + $dueDate = new \DateTime('now', new \DateTimeZone('UTC')); + $dueDate->modify('+' . $paymentSettings->getDueDateDays() . ' days'); + $createPaymentStruct->setDueDate($dueDate); + } + + $mollieCustomerExtension = $customer->getExtension(Mollie::EXTENSION); + + if ($mollieCustomerExtension instanceof CustomerExtension) { + $mollieCustomerId = $mollieCustomerExtension->getForProfileId($profileId, $apiSettings->getMode()); + if ($mollieCustomerId !== null) { + $createPaymentStruct->setCustomerId($mollieCustomerId); + } + } + + if (! $customer->getGuest()) { + $createPaymentStruct = $this->modifySequenceType($createPaymentStruct, $paymentHandler, $dataBag, $salesChannelId, $hasSubscriptionLineItem); + + if ( + ( + $createPaymentStruct->getSequenceType() !== SequenceType::ONEOFF + || $paymentSettings->forceCustomerCreation() + ) + && $createPaymentStruct->getCustomerId() === null + ) { + $mollieCustomer = $this->mollieGateway->createCustomer($customer, $salesChannelId); + $createPaymentStruct->setCustomerId($mollieCustomer->getId()); + + $customer = $this->saveCustomerId($customer, $mollieCustomer, $profileId, $apiSettings->getMode(), $context); + + $this->logger->info('Mollie customer created and assigned to shopware customer', $logData); + } + } + + $createPaymentStruct = $paymentHandler->applyPaymentSpecificParameters($createPaymentStruct, $dataBag, $customer); + + $logData['payload'] = $createPaymentStruct->toArray(); + $this->logger->info('Payment payload created for mollie API', $logData); + + return $createPaymentStruct; + } + + private function modifySequenceType(CreatePayment $createPaymentStruct, AbstractMolliePaymentHandler $paymentHandler, RequestDataBag $dataBag, string $salesChannelId, bool $hasSubscriptionLineItem): CreatePayment + { + $savePaymentDetails = $dataBag->get('savePaymentDetails', false); + + if ($savePaymentDetails || ($hasSubscriptionLineItem && $paymentHandler instanceof SubscriptionAwareInterface)) { + $createPaymentStruct->setSequenceType(SequenceType::FIRST); + } + + $mandateId = $dataBag->get('mandateId'); + $mollieCustomerId = $createPaymentStruct->getCustomerId(); + + if ( + $mollieCustomerId + && $mandateId + && $paymentHandler instanceof RecurringAwareInterface + ) { + $mandates = $this->mollieGateway->listMandates($mollieCustomerId, $salesChannelId); + $paymentMethodMandates = $mandates->filterByPaymentMethod($paymentHandler->getPaymentMethod()); + $mandate = $paymentMethodMandates->get($mandateId); + if ($mandate instanceof Mandate) { + $createPaymentStruct->setMandateId($mandateId); + $createPaymentStruct->setSequenceType(SequenceType::RECURRING); + } + } + + return $createPaymentStruct; + } + + private function saveCustomerId(CustomerEntity $customerEntity, Customer $mollieCustomer, string $profileId, Mode $mode, Context $context): CustomerEntity + { + $customerExtension = new CustomerExtension(); + $customerExtension->setCustomerId($profileId, $mode, $mollieCustomer->getId()); + $customerEntity->addExtension(Mollie::EXTENSION, $customerExtension); + + $customerCustomFields = $customerEntity->getCustomFields() ?? []; + $customerCustomFields[Mollie::EXTENSION] = $customerExtension->toArray(); + $customerEntity->setCustomFields($customerCustomFields); + + $this->customerRepository->upsert([ + [ + 'id' => $customerEntity->getId(), + 'customFields' => $customerCustomFields + ] + ], $context); + + return $customerEntity; + } +} diff --git a/shopware/Component/Payment/CreatePaymentBuilderInterface.php b/shopware/Component/Payment/CreatePaymentBuilderInterface.php new file mode 100644 index 000000000..f7b0b9f22 --- /dev/null +++ b/shopware/Component/Payment/CreatePaymentBuilderInterface.php @@ -0,0 +1,15 @@ + ['storefront'], 'csrf_protected' => false])] +final class CreditCardController extends StorefrontController +{ + public function __construct( + private StoreCreditCardTokenRoute $storeCreditCardTokenRoute, + ) { + } + + #[Route(name: 'frontend.mollie.components.storeCardToken', path: '/mollie/components/store-card-token/{customerId}/{cardToken}', methods: ['GET'], options: ['seo' => false])] + public function storeCardToken(string $customerId, string $cardToken, SalesChannelContext $salesChannelContext): JsonResponse + { + $response = $this->storeCreditCardTokenRoute->store($customerId, $cardToken, $salesChannelContext->getContext()); + + return new JsonResponse([ + 'success' => true, + 'customerId' => $customerId, + 'result' => null, + ]); + } +} diff --git a/shopware/Component/Payment/CreditCard/StoreCreditCardTokenResponse.php b/shopware/Component/Payment/CreditCard/StoreCreditCardTokenResponse.php new file mode 100644 index 000000000..3465eca26 --- /dev/null +++ b/shopware/Component/Payment/CreditCard/StoreCreditCardTokenResponse.php @@ -0,0 +1,25 @@ + + */ +final class StoreCreditCardTokenResponse extends StoreApiResponse +{ + public function __construct() + { + $object = new ArrayStruct( + [ + 'success' => true, + 'message' => 'Using deprecated route, please provide "creditCardToken" in request body for payment' + ], + 'mollie_payments_creditcard_token_stored' + ); + parent::__construct($object); + } +} diff --git a/shopware/Component/Payment/CreditCard/StoreCreditCardTokenRoute.php b/shopware/Component/Payment/CreditCard/StoreCreditCardTokenRoute.php new file mode 100644 index 000000000..ad0cdce3e --- /dev/null +++ b/shopware/Component/Payment/CreditCard/StoreCreditCardTokenRoute.php @@ -0,0 +1,29 @@ + ['store-api']])] +final class StoreCreditCardTokenRoute +{ + public function __construct( + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/store-api/mollie/creditcard/store-token/{customerId}/{cardToken}', name: 'store-api.mollie.creditcard.store-token', methods: ['POST'])] + public function store(string $customerId,string $cardToken, Context $context): StoreCreditCardTokenResponse + { + $this->logger->warning('Deprecated route was called, credit card tokens are not stored anymore, please provide "creditCardToken" in request body for payment'); + + return new StoreCreditCardTokenResponse(); + } +} diff --git a/shopware/Component/Payment/Event/ModifyCreatePaymentPayloadEvent.php b/shopware/Component/Payment/Event/ModifyCreatePaymentPayloadEvent.php new file mode 100644 index 000000000..10feae948 --- /dev/null +++ b/shopware/Component/Payment/Event/ModifyCreatePaymentPayloadEvent.php @@ -0,0 +1,24 @@ +payment; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/shopware/Component/Payment/Event/PaymentCreatedEvent.php b/shopware/Component/Payment/Event/PaymentCreatedEvent.php new file mode 100644 index 000000000..431dfcf6b --- /dev/null +++ b/shopware/Component/Payment/Event/PaymentCreatedEvent.php @@ -0,0 +1,46 @@ +redirectUrl; + } + + public function getPayment(): Payment + { + return $this->payment; + } + + public function getTransactionDataStruct(): TransactionDataStruct + { + return $this->transactionDataStruct; + } + + public function getRequestDataBag(): RequestDataBag + { + return $this->requestDataBag; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/shopware/Component/Payment/Event/PaymentFinalizeEvent.php b/shopware/Component/Payment/Event/PaymentFinalizeEvent.php new file mode 100644 index 000000000..49dbe9638 --- /dev/null +++ b/shopware/Component/Payment/Event/PaymentFinalizeEvent.php @@ -0,0 +1,24 @@ +payment; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/shopware/Component/Payment/ExpressMethod/AbstractAccountService.php b/shopware/Component/Payment/ExpressMethod/AbstractAccountService.php new file mode 100644 index 000000000..31182b943 --- /dev/null +++ b/shopware/Component/Payment/ExpressMethod/AbstractAccountService.php @@ -0,0 +1,14 @@ +> $customerRepository + * @param EntityRepository> $countryRepository + * @param EntityRepository> $salutationRepository + * @param EntityRepository> $customerAddressRepository + */ + public function __construct( + #[Autowire(service: 'customer.repository')] + private EntityRepository $customerRepository, + #[Autowire(service: 'country.repository')] + private EntityRepository $countryRepository, + #[Autowire(service: 'salutation.repository')] + private EntityRepository $salutationRepository, + #[Autowire(service: 'customer_address.repository')] + private EntityRepository $customerAddressRepository, + #[Autowire(service: RegisterRoute::class)] + private AbstractRegisterRoute $registerRoute, + private ShopwareAccountService $accountService, + #[Autowire(service: ContextSwitchRoute::class)] + private AbstractContextSwitchRoute $contextSwitchRoute, + #[Autowire(service: SalesChannelContextService::class)] + private SalesChannelContextServiceInterface $salesChannelContextService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractAccountService + { + throw new DecorationPatternException(self::class); + } + + public function loginOrCreateAccount(string $paymentMethodId, Address $billingAddress, Address $shippingAddress, SalesChannelContext $salesChannelContext): SalesChannelContext + { + $currentPaymentMethodId = $salesChannelContext->getPaymentMethod()->getId(); + + $logData = [ + 'salesChannelId' => $salesChannelContext->getSalesChannelId(), + 'currentPaymentMethodId' => $currentPaymentMethodId, + 'paymentMethodId' => $paymentMethodId, + ]; + $email = $billingAddress->getEmail(); + $this->logger->debug('Start - login or create express customer', $logData); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set(SalesChannelContextService::PAYMENT_METHOD_ID, $paymentMethodId); + + $customer = $salesChannelContext->getCustomer(); + if ($customer === null) { + $this->logger->debug('Customer not logged in, try to login or create an account', $logData); + try { + $customer = $this->getCustomerByEmail($email, $salesChannelContext); + $logData['customerId'] = $customer->getId(); + $logData['customerNumber'] = $customer->getCustomerNumber(); + $this->logger->debug('Customer was found by email', $logData); + $this->accountService->loginById($customer->getId(), $salesChannelContext); + $requestDataBag = $this->createOrReuseAddresses($requestDataBag,$customer,$billingAddress,$shippingAddress,$salesChannelContext); + } catch (\Throwable $e) { + $customer = $this->createNewGuestAccount($billingAddress, $shippingAddress, $salesChannelContext); + $logData['customerId'] = $customer->getId(); + $logData['customerNumber'] = $customer->getCustomerNumber(); + $this->logger->debug('New guest account created', $logData); + } + } + + $requestDataBag->set(SalesChannelContextService::CUSTOMER_ID, $customer->getId()); + $this->logger->debug('Switch customers payment method', $logData); + $contextSwitchResponse = $this->contextSwitchRoute->switchContext($requestDataBag, $salesChannelContext); + + $parameters = new SalesChannelContextServiceParameters($salesChannelContext->getSalesChannelId(), + $contextSwitchResponse->getToken(), + originalContext: $salesChannelContext->getContext(), + customerId: $customer->getId() + ); + $this->logger->debug('Finished - login or create express customer', $logData); + + return $this->salesChannelContextService->get($parameters); + } + + /** + * @return array + */ + private function getCountryIsoMapping(Address $shippingAddress, Address $billingAddress, SalesChannelContext $salesChannelContext): array + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('active', true)); + $criteria->addFilter(new EqualsAnyFilter('iso', [$shippingAddress->getCountry(), $billingAddress->getCountry()])); + + $countrySearchResult = $this->countryRepository->search($criteria, $salesChannelContext->getContext()); + + $countryIsoMapping = []; + /** @var CountryEntity $country */ + foreach ($countrySearchResult->getElements() as $country) { + $countryIsoMapping[$country->getIso()] = $country->getId(); + } + + return $countryIsoMapping; + } + + private function getCustomerByEmail(string $email, SalesChannelContext $salesChannelContext): CustomerEntity + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('email', $email)); + + $customer = $this->fetchCustomer($criteria, $salesChannelContext, true); + if ($customer === null) { + throw CustomerException::customerNotFound($email); + } + + return $customer; + } + + private function getNotSpecifiedSalutation(SalesChannelContext $context): SalutationEntity + { + $criteria = new Criteria(); + $salutationSearchResult = $this->salutationRepository->search($criteria, $context->getContext()); + $foundSalutation = null; + /** @var SalutationEntity $salutation */ + foreach ($salutationSearchResult->getElements() as $salutation) { + $foundSalutation = $salutation; + if ($salutation->getSalutationKey() === 'not_specified') { + return $foundSalutation; + } + } + if ($foundSalutation === null) { + throw new \Exception('Salutations not found, please add at least one salutation'); + } + + return $foundSalutation; + } + + private function getStorefrontUrl(SalesChannelContext $salesChannelContext): ?string + { + $domainId = $salesChannelContext->getDomainId(); + if ($domainId === null) { + return null; + } + $salesChannel = $salesChannelContext->getSalesChannel(); + $salesChannelDomains = $salesChannel->getDomains(); + if ($salesChannelDomains === null) { + return null; + } + /** @var ?SalesChannelDomainEntity $salesChannelDomain */ + $salesChannelDomain = $salesChannelDomains->get($domainId); + if ($salesChannelDomain === null) { + return null; + } + + return $salesChannelDomain->getUrl(); + } + + private function createNewGuestAccount(Address $billingAddress, Address $shippingAddress, SalesChannelContext $salesChannelContext): CustomerEntity + { + $data = new DataBag(); + + $storeFrontUrl = $this->getStorefrontUrl($salesChannelContext); + if ($storeFrontUrl !== null) { + $data->set('storeFrontUrl', $storeFrontUrl); + } + + $countryIsoMapping = $this->getCountryIsoMapping($shippingAddress, $billingAddress, $salesChannelContext); + $defaultSalutation = $this->getNotSpecifiedSalutation($salesChannelContext); + + $billingAddressData = new DataBag($billingAddress->toRegisterFormArray()); + $billingAddressData->set('countryId', $countryIsoMapping[$billingAddress->getCountry()] ?? null); + $billingAddressData->set('salutationId', $defaultSalutation->getId()); + $billingAddressData->set('customFields', [ + Mollie::EXTENSION => [ + Address::CUSTOM_FIELDS_KEY => $billingAddress->getId() + ] + ]); + + $shippingAddressData = new DataBag($shippingAddress->toRegisterFormArray()); + $shippingAddressData->set('countryId', $countryIsoMapping[$shippingAddress->getCountry()] ?? null); + $shippingAddressData->set('salutationId', $defaultSalutation->getId()); + $shippingAddressData->set('customFields', [ + Mollie::EXTENSION => [ + Address::CUSTOM_FIELDS_KEY => $billingAddress->getId() + ] + ]); + + $data->set('guest', true); + $data->set('salutationId', $defaultSalutation->getId()); + $data->set('firstName', $billingAddress->getGivenName()); + $data->set('lastName', $billingAddress->getFamilyName()); + $data->set('email', $billingAddress->getEmail()); + + $data->set('billingAddress', $billingAddressData); + $data->set('shippingAddress', $shippingAddressData); + + $registerRouteResponse = $this->registerRoute->register($data->toRequestDataBag(), $salesChannelContext, $data->has('storefrontUrl')); + + return $registerRouteResponse->getCustomer(); + } + + /** + * This method filters for the standard customer related constraints like active or the sales channel + * assignment. + * Add only filters to the $criteria for values which have an index in the database, e.g. id, or email. The rest + * should be done via PHP because it's a lot faster to filter a few entities on PHP side with the same email + * address, than to filter a huge numbers of rows in the DB on a not indexed column. + */ + private function fetchCustomer(Criteria $criteria, SalesChannelContext $context, bool $includeGuest = false): ?CustomerEntity + { + $criteria->setTitle('account-service::fetchCustomer'); + + $result = $this->customerRepository->search($criteria, $context->getContext())->getEntities(); + $customers = $result->getElements(); + $resultArray = []; + /** @var CustomerEntity $customer */ + foreach ($customers as $customer) { + // Skip not active users + if (! $customer->getActive()) { + continue; + } + // Skip guest if not required + if (! $includeGuest && $customer->getGuest()) { + continue; + } + // It is bound, but not to the current one. Skip it + if ($customer->getBoundSalesChannelId() !== null && $customer->getBoundSalesChannelId() !== $context->getSalesChannelId()) { + continue; + } + $resultArray[] = $customer; + } + + if (count($resultArray) === 0) { + return null; + } + // If there is more than one account we want to return the latest, this is important + // for guest accounts, real customer accounts should only occur once, otherwise the + // wrong password will be validated + if (count($resultArray) > 1) { + usort($resultArray, function (CustomerEntity $a, CustomerEntity $b) { + return $b->getCreatedAt() <=> $a->getCreatedAt(); + }); + } + + return $resultArray[0]; + } + + private function createOrReuseAddresses(RequestDataBag $requestDataBag, CustomerEntity $customer, Address $billingAddress, Address $shippingAddress, SalesChannelContext $salesChannelContext): RequestDataBag + { + $mollieAddressIds[] = $billingAddress->getId(); + $mollieAddressIds[] = $shippingAddress->getId(); + $mollieAddressIds = array_unique($mollieAddressIds); + + $criteria = new Criteria(); + $criteria->addFilter(new AndFilter([ + new EqualsFilter('customerId', $customer->getId()), + new EqualsAnyFilter('customFields.' . Mollie::EXTENSION . '.' . Address::CUSTOM_FIELDS_KEY, $mollieAddressIds), + ])); + $addressSearchResult = $this->customerAddressRepository->search($criteria, $salesChannelContext->getContext()); + + return $requestDataBag; + } +} diff --git a/src/Service/Cart/CartBackupService.php b/shopware/Component/Payment/ExpressMethod/CartBackupService.php similarity index 78% rename from src/Service/Cart/CartBackupService.php rename to shopware/Component/Payment/ExpressMethod/CartBackupService.php index 7dd062b21..0fb9a8122 100644 --- a/src/Service/Cart/CartBackupService.php +++ b/shopware/Component/Payment/ExpressMethod/CartBackupService.php @@ -1,42 +1,35 @@ */ - private array $existingBackups; + private array $existingBackups = []; - /** - * @param AbstractCartPersister|CartPersisterInterface $cartPersister - */ - public function __construct(CartService $cartService, $cartPersister) + public function __construct(private CartService $cartService, + #[Autowire(service: CartPersister::class)] + private AbstractCartPersister $cartPersister) { - $this->cartService = $cartService; - $this->cartPersister = $cartPersister; + } - $this->existingBackups = []; + public function getDecorated(): AbstractCartBackupService + { + throw new DecorationPatternException(self::class); } public function backupCart(SalesChannelContext $context): void @@ -101,12 +94,9 @@ public function clearBackup(SalesChannelContext $context): void public function replaceToken(string $oldToken, string $currentToken, SalesChannelContext $context): void { - // only cart persister has replace method, so it wont work in shopware 6.4.1.0 - if ($this->cartPersister instanceof AbstractCartPersister) { - $oldToken = $this->getToken($oldToken); - $currentToken = $this->getToken($currentToken); - $this->cartPersister->replace($oldToken, $currentToken, $context); - } + $oldToken = $this->getToken($oldToken); + $currentToken = $this->getToken($currentToken); + $this->cartPersister->replace($oldToken, $currentToken, $context); } public function isBackupExisting(SalesChannelContext $context): bool diff --git a/src/Checkout/Cart/ExpressCartItemAddRoute.php b/shopware/Component/Payment/ExpressMethod/ExpressCartItemAddRoute.php similarity index 64% rename from src/Checkout/Cart/ExpressCartItemAddRoute.php rename to shopware/Component/Payment/ExpressMethod/ExpressCartItemAddRoute.php index e93dc927d..372504cbf 100644 --- a/src/Checkout/Cart/ExpressCartItemAddRoute.php +++ b/shopware/Component/Payment/ExpressMethod/ExpressCartItemAddRoute.php @@ -1,35 +1,30 @@ cartItemAddRoute = $cartItemAddRoute; - $this->container = $container; } public function getDecorated(): AbstractCartItemAddRoute @@ -51,18 +46,17 @@ public function add(Request $request, Cart $cart, SalesChannelContext $context, return $this->getDecorated()->add($request, $cart, $context, $items); } - // Shopware 6.4 have circular injection, we have to use container - $cartBackupService = $this->container->get(CartBackupService::class); - $cartService = $this->container->get(CartService::class); - // add product somehow happens twice, so dont backup our express-cart, only originals - if (! $cartBackupService->isBackupExisting($context)) { - $cartBackupService->backupCart($context); + if (! $this->cartBackupService->isBackupExisting($context)) { + $this->cartBackupService->backupCart($context); } // clear existing cart and also update it to save it $cart->setLineItems(new LineItemCollection()); + $this->cartService->recalculate($cart, $context); + + /* $mollieCart = new MollieShopwareCart($cart); // we mark the cart as single product express checkout @@ -72,7 +66,7 @@ public function add(Request $request, Cart $cart, SalesChannelContext $context, $cart = $mollieCart->getCart(); - $cartService->updateCart($cart); + $cartService->updateCart($cart);*/ return $this->getDecorated()->add($request, $cart, $context, $items); } diff --git a/shopware/Component/Payment/ExpressMethod/VisibilityRestriction.php b/shopware/Component/Payment/ExpressMethod/VisibilityRestriction.php new file mode 100644 index 000000000..c18d9a36a --- /dev/null +++ b/shopware/Component/Payment/ExpressMethod/VisibilityRestriction.php @@ -0,0 +1,13 @@ + + */ +final class VisibilityRestrictionCollection extends Collection +{ +} diff --git a/shopware/Component/Payment/FinalizeAction.php b/shopware/Component/Payment/FinalizeAction.php index d28f02456..f19ef5ef7 100644 --- a/shopware/Component/Payment/FinalizeAction.php +++ b/shopware/Component/Payment/FinalizeAction.php @@ -6,50 +6,48 @@ use Kiener\MolliePayments\Facade\MolliePaymentFinalize; use Kiener\MolliePayments\Handler\PaymentHandler; use Kiener\MolliePayments\Struct\Order\OrderAttributes; +use Mollie\Shopware\Component\Transaction\TransactionConverter; use Mollie\Shopware\Component\Transaction\TransactionConverterInterface; use Psr\Log\LoggerInterface; -use Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct; use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct; -use Shopware\Core\Checkout\Payment\Exception\AsyncPaymentFinalizeException; -use Shopware\Core\Checkout\Payment\Exception\CustomerCanceledAsyncPaymentException; use Shopware\Core\Checkout\Payment\PaymentException; use Shopware\Core\Framework\Context; +use Symfony\Component\DependencyInjection\Attribute\Autowire; final class FinalizeAction { - private LoggerInterface $logger; - private MolliePaymentFinalize $finalizeFacade; - private TransactionConverterInterface $transactionConverter; - - public function __construct(MolliePaymentFinalize $finalizeFacade, TransactionConverterInterface $transactionConverter, LoggerInterface $logger) + public function __construct( + private MolliePaymentFinalize $finalizeFacade, + #[Autowire(service: TransactionConverter::class)] + private TransactionConverterInterface $transactionConverter, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger) { - $this->finalizeFacade = $finalizeFacade; - $this->logger = $logger; - $this->transactionConverter = $transactionConverter; } - /** @param AsyncPaymentTransactionStruct|PaymentTransactionStruct $transaction */ - public function finalize(PaymentHandler $paymentHandler, $transaction, Context $context): void + public function finalize(PaymentHandler $paymentHandler,PaymentTransactionStruct $shopwareTransaction, Context $context): void { + $mollieID = 'notLoaded'; + $shopOrderNumber = 'notLoaded'; try { - $transaction = $this->transactionConverter->convert($transaction, $context); + $transaction = $this->transactionConverter->convert($shopwareTransaction, $context); $shopwareOrder = $transaction->getOrder(); $salesChannelId = $shopwareOrder->getSalesChannelId(); $orderAttributes = new OrderAttributes($shopwareOrder); $mollieID = $orderAttributes->getMollieOrderId(); - + $shopOrderNumber = $shopwareOrder->getOrderNumber(); $this->logger->info( - 'Finalizing Mollie payment for order ' . $transaction->getOrder()->getOrderNumber() . ' with payment: ' . $paymentHandler->getPaymentMethod() . ' and Mollie ID' . $mollieID, + 'Finalizing Mollie payment for order ' . $shopOrderNumber . ' with payment: ' . $paymentHandler->getPaymentMethod() . ' and Mollie ID' . $mollieID, [ 'salesChannelId' => $salesChannelId, // todo: add a name somehow ] ); $this->finalizeFacade->finalize($transaction, $context, (string) $salesChannelId); - } catch (AsyncPaymentFinalizeException|CustomerCanceledAsyncPaymentException|PaymentException $ex) { + } catch (PaymentException $ex) { $this->logger->error( - 'Error when finalizing order ' . $transaction->getOrder()->getOrderNumber() . ', Mollie ID: ' . $mollieID . ', ' . $ex->getMessage() + 'Error when finalizing order ' . $shopOrderNumber . ', Mollie ID: ' . $mollieID . ', ' . $ex->getMessage() ); // these are already correct exceptions @@ -62,9 +60,9 @@ public function finalize(PaymentHandler $paymentHandler, $transaction, Context $ // Only the 2 exceptions above, lead to a correct failure-behaviour in Shopware. // All other exceptions would lead to a 500 exception in the storefront. $this->logger->error( - 'Unknown Error when finalizing order ' . $transaction->getOrder()->getOrderNumber() . ', Mollie ID: ' . $mollieID . ', ' . $ex->getMessage() + 'Unknown Error when finalizing order ' . $shopOrderNumber . ', Mollie ID: ' . $mollieID . ', ' . $ex->getMessage() ); - throw PaymentException::asyncFinalizeInterrupted($transaction->getOrderTransactionId(), 'An unknown error happened when finalizing the order. Please see the Shopware logs for more. It can be that the payment in Mollie was succesful and the Shopware order is now cancelled or failed!'); + throw PaymentException::asyncFinalizeInterrupted($shopwareTransaction->getOrderTransactionId(), 'An unknown error happened when finalizing the order. Please see the Shopware logs for more. It can be that the payment in Mollie was succesful and the Shopware order is now cancelled or failed!'); } } } diff --git a/shopware/Component/Payment/Handler/AbstractMolliePaymentHandler.php b/shopware/Component/Payment/Handler/AbstractMolliePaymentHandler.php new file mode 100644 index 000000000..b6bfbe7bb --- /dev/null +++ b/shopware/Component/Payment/Handler/AbstractMolliePaymentHandler.php @@ -0,0 +1,101 @@ +request->all()); + + return $this->pay->execute($this, $transaction, $dataBag, $context); + } catch (\Throwable $exception) { + $this->logger->error('Mollie Pay Process Failed', [ + 'error' => $exception->getMessage(), + 'paymentMethod' => $this->getPaymentMethod()->value + ]); + throw PaymentException::asyncProcessInterrupted($transaction->getOrderTransactionId(), $exception->getMessage(), $exception); + } + } + + public function finalize(Request $request, PaymentTransactionStruct $transaction, Context $context): void + { + try { + $this->finalize->execute($transaction, $context); + } catch (HttpException $exception) { + $this->logger->error('Payment is aborted or failed', [ + 'error' => $exception->getMessage(), + 'paymentMethod' => $this->getPaymentMethod()->value + ]); + + throw $exception; + } catch (\Throwable $exception) { + $this->logger->error('Payment failed unexpected', [ + 'error' => $exception->getMessage(), + 'paymentMethod' => $this->getPaymentMethod()->value, + 'trace' => $exception->getTrace() + ]); + throw PaymentException::asyncFinalizeInterrupted($transaction->getOrderTransactionId(), $exception->getMessage(), $exception); + } + } + + public function supports(PaymentHandlerType $type, string $paymentMethodId, Context $context): bool + { + return false; + } + + public function applyPaymentSpecificParameters(CreatePayment $payment,RequestDataBag $dataBag, CustomerEntity $customer): CreatePayment + { + return $payment; + } + + public function getIconFileName(): string + { + return $this->getPaymentMethod()->value . '-icon'; + } + + abstract public function getPaymentMethod(): PaymentMethod; + + abstract public function getName(): string; + + public function getTechnicalName(): string + { + return self::TECHNICAL_NAME_PREFIX . $this->getPaymentMethod()->value; + } +} diff --git a/shopware/Component/Payment/Handler/BankTransferAwareInterface.php b/shopware/Component/Payment/Handler/BankTransferAwareInterface.php new file mode 100644 index 000000000..5a3e6e5f7 --- /dev/null +++ b/shopware/Component/Payment/Handler/BankTransferAwareInterface.php @@ -0,0 +1,8 @@ + ['storefront'], 'csrf_protected' => false])] +final class MandateController extends StorefrontController +{ + public function __construct( + private StoreMandateIdRoute $storeMandateIdRoute, + #[Autowire(service: RevokeMandateRoute::class)] + private AbstractRevokeMandateRoute $revokeMandateRoute, + ) { + } + + #[Route(name: 'frontend.mollie.components.storeMandateId', path: '/mollie/components/store-mandate-id/{customerId}/{mandateId}', methods: ['GET'], options: ['seo' => false])] + public function storeId(string $customerId, string $mandateId, SalesChannelContext $salesChannelContext): Response + { + $this->storeMandateIdRoute->store($customerId, $mandateId, $salesChannelContext); + + return new JsonResponse([ + 'success' => true, + 'customerId' => $customerId, + 'result' => null, + ]); + } + + #[Route(name: 'frontend.mollie.components.revokeMandate', path: '/mollie/components/revoke-mandate/{customerId}/{mandateId}', methods: ['GET'], options: ['seo' => false])] + public function revoke(string $customerId, string $mandateId, SalesChannelContext $salesChannelContext): Response + { + $response = $this->revokeMandateRoute->revoke($customerId, $mandateId, $salesChannelContext); + + return new JsonResponse( + [ + 'success' => $response->isSuccess(), + 'customerId' => $customerId, + 'mandateId' => $mandateId, + 'result' => null, + ] + ); + } +} diff --git a/shopware/Component/Payment/Mandate/MandateException.php b/shopware/Component/Payment/Mandate/MandateException.php new file mode 100644 index 000000000..482f544db --- /dev/null +++ b/shopware/Component/Payment/Mandate/MandateException.php @@ -0,0 +1,53 @@ + $customerNumber] + ); + } + + public static function oneClickPaymentDisabled(string $salesChannelId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::ONE_CLICK_DISABLED, + 'One click payment is disabled for SalesChannel {{salesChannelId}}', + ['salesChannelId' => $salesChannelId] + ); + } + + public static function customerIdNotSetForProfile(string $customerNumber,string $mollieProfileId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::ONE_CLICK_DISABLED, + 'The customer {{customerNumber}} does not have mollie customer ID in profile {{mollieProfileId}}', + ['customerNumber' => $customerNumber, 'mollieProfileId' => $mollieProfileId] + ); + } +} diff --git a/shopware/Component/Payment/Mandate/Route/AbstractListMandatesRoute.php b/shopware/Component/Payment/Mandate/Route/AbstractListMandatesRoute.php new file mode 100644 index 000000000..c92d82a3e --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/AbstractListMandatesRoute.php @@ -0,0 +1,13 @@ + + */ +final class ListMandatesResponse extends StoreApiResponse +{ + public function __construct(private MandateCollection $mandates) + { + $object = new ArrayStruct( + [ + 'mandates' => $this->mandates->jsonSerialize(), + ], + 'mollie_payments_credit_card_mandates' + ); + + parent::__construct($object); + } + + public function getMandates(): MandateCollection + { + return $this->mandates; + } +} diff --git a/shopware/Component/Payment/Mandate/Route/ListMandatesRoute.php b/shopware/Component/Payment/Mandate/Route/ListMandatesRoute.php new file mode 100644 index 000000000..0d9800a13 --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/ListMandatesRoute.php @@ -0,0 +1,94 @@ + ['store-api']])] +final class ListMandatesRoute extends AbstractListMandatesRoute +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settings, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractListMandatesRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/mandates/{customerId}', name: 'store-api.mollie.mandates', methods: ['GET'])] + public function list(string $customerId, SalesChannelContext $salesChannelContext): ListMandatesResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $salesChannelName = (string) $salesChannelContext->getSalesChannel()->getName(); + $logData = [ + 'path' => '/store-api/mollie/mandates/{customerId}', + 'customerId' => $customerId, + 'salesChannelId' => $salesChannelId, + 'salesChannelName' => $salesChannelName, + ]; + $this->logger->debug('List mandates route called', $logData); + + $mandateCollection = new MandateCollection(); + + $customer = $salesChannelContext->getCustomer(); + if (! $customer instanceof CustomerEntity) { + $this->logger->debug('Customer is not logged in', $logData); + + return new ListMandatesResponse($mandateCollection); + } + $logData['customerNumber'] = $customer->getCustomerNumber(); + + $customerExtension = $customer->getExtension(Mollie::EXTENSION); + if (! $customerExtension instanceof Customer) { + $this->logger->debug('Customer does not have mollie customer id', $logData); + + return new ListMandatesResponse($mandateCollection); + } + + $paymentSettings = $this->settings->getPaymentSettings($salesChannelId); + + if (! $paymentSettings->isOneClickPayment()) { + $this->logger->debug('One click payment is disabled, mandates are not loaded', $logData); + + return new ListMandatesResponse($mandateCollection); + } + + $apiSettings = $this->settings->getApiSettings($salesChannelId); + $mollieProfileId = $apiSettings->getProfileId(); + $logData['profileId'] = $mollieProfileId; + $mollieCustomerId = $customerExtension->getForProfileId($mollieProfileId,$apiSettings->getMode()); + if ($mollieCustomerId === null) { + $this->logger->debug('Mollie Customer ID not found for Mollie Profile', $logData); + + return new ListMandatesResponse($mandateCollection); + } + + $mandateCollection = $this->mollieGateway->listMandates($mollieCustomerId, $salesChannelId); + $logData['total'] = $mandateCollection->count(); + $this->logger->info('Mandates for mollie customer loaded', $logData); + + return new ListMandatesResponse($mandateCollection); + } +} diff --git a/shopware/Component/Payment/Mandate/Route/RevokeMandateResponse.php b/shopware/Component/Payment/Mandate/Route/RevokeMandateResponse.php new file mode 100644 index 000000000..8f2e14066 --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/RevokeMandateResponse.php @@ -0,0 +1,28 @@ + + */ +final class RevokeMandateResponse extends StoreApiResponse +{ + public function __construct(private bool $success) + { + $object = new ArrayStruct( + ['success' => $this->success], + 'mollie_payments_mandate_revoke' + ); + + parent::__construct($object); + } + + public function isSuccess(): bool + { + return $this->success; + } +} diff --git a/shopware/Component/Payment/Mandate/Route/RevokeMandateRoute.php b/shopware/Component/Payment/Mandate/Route/RevokeMandateRoute.php new file mode 100644 index 000000000..c15880c21 --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/RevokeMandateRoute.php @@ -0,0 +1,91 @@ + ['store-api']])] +final class RevokeMandateRoute extends AbstractRevokeMandateRoute +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settings, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractRevokeMandateRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/mandate/revoke/{customerId}/{mandateId}', name: 'store-api.mollie.mandate.revoke', methods: ['POST'])] + public function revoke(string $customerId, string $mandateId, SalesChannelContext $salesChannelContext): RevokeMandateResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $salesChannelName = (string) $salesChannelContext->getSalesChannel()->getName(); + $logData = [ + 'path' => '/store-api/mollie/mandate/revoke/{customerId}/{mandateId}', + 'customerId' => $customerId, + 'salesChannelId' => $salesChannelId, + 'salesChannelName' => $salesChannelName, + ]; + $this->logger->debug('Revoke mandate route called', $logData); + + $paymentSettings = $this->settings->getPaymentSettings($salesChannelId); + + if (! $paymentSettings->isOneClickPayment()) { + $this->logger->debug('One click payment is disabled, mandates are not loaded', $logData); + + throw MandateException::oneClickPaymentDisabled($salesChannelId); + } + + $customer = $salesChannelContext->getCustomer(); + if (! $customer instanceof CustomerEntity) { + $this->logger->debug('Customer is not logged in', $logData); + + throw MandateException::customerNotLoggedIn(); + } + $customerNumber = $customer->getCustomerNumber(); + $logData['customerNumber'] = $customerNumber; + + $customerExtension = $customer->getExtension(Mollie::EXTENSION); + if (! $customerExtension instanceof Customer) { + $this->logger->debug('Customer does not have mollie customer id', $logData); + + throw MandateException::mollieCustomerIdNotSet($customerNumber); + } + + $apiSettings = $this->settings->getApiSettings($salesChannelId); + $mollieProfileId = $apiSettings->getProfileId(); + $logData['profileId'] = $mollieProfileId; + $mollieCustomerId = $customerExtension->getForProfileId($mollieProfileId,$apiSettings->getMode()); + if ($mollieCustomerId === null) { + $this->logger->debug('Mollie Customer ID not found for Mollie Profile', $logData); + + throw MandateException::customerIdNotSetForProfile($customerNumber, $mollieProfileId); + } + + $success = $this->mollieGateway->revokeMandate($mollieCustomerId, $mandateId, $salesChannelId); + + return new RevokeMandateResponse($success); + } +} diff --git a/shopware/Component/Payment/Mandate/Route/StoreMandateIdResponse.php b/shopware/Component/Payment/Mandate/Route/StoreMandateIdResponse.php new file mode 100644 index 000000000..ab508d92b --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/StoreMandateIdResponse.php @@ -0,0 +1,26 @@ + + */ +final class StoreMandateIdResponse extends StoreApiResponse +{ + public function __construct() + { + $object = new ArrayStruct( + [ + 'success' => true, + 'message' => 'Using deprecated route, please provide "mandateId" in request body for payment' + ], + 'mollie_payments_creditcard_mandate_id_stored' + ); + + parent::__construct($object); + } +} diff --git a/shopware/Component/Payment/Mandate/Route/StoreMandateIdRoute.php b/shopware/Component/Payment/Mandate/Route/StoreMandateIdRoute.php new file mode 100644 index 000000000..172394871 --- /dev/null +++ b/shopware/Component/Payment/Mandate/Route/StoreMandateIdRoute.php @@ -0,0 +1,29 @@ + ['store-api']])] +final class StoreMandateIdRoute +{ + public function __construct( + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/store-api/mollie/creditcard/store-mandate-id/{customerId}/{mandateId}', name: 'store-api.mollie.creditcard.store-mandate-id', methods: ['POST'])] + public function store(string $customerId, string $mandateId, SalesChannelContext $salesChannelContext): StoreMandateIdResponse + { + $this->logger->warning('Deprecated URL was called, mandate IDs are not stored anymore, please provide "mandateId" in checkout'); + + return new StoreMandateIdResponse(); + } +} diff --git a/shopware/Component/Payment/Method/AlmaPayment.php b/shopware/Component/Payment/Method/AlmaPayment.php new file mode 100644 index 000000000..1cf917c5a --- /dev/null +++ b/shopware/Component/Payment/Method/AlmaPayment.php @@ -0,0 +1,20 @@ +get('paymentToken'); + if ($paymentToken !== null) { + $payment->setApplePayPaymentToken($paymentToken); + } + + return $payment; + } +} diff --git a/shopware/Component/Payment/Method/BanContactPayment.php b/shopware/Component/Payment/Method/BanContactPayment.php new file mode 100644 index 000000000..7897c3dc4 --- /dev/null +++ b/shopware/Component/Payment/Method/BanContactPayment.php @@ -0,0 +1,21 @@ +getBillingAddress(); + $phoneNumber = $dataBag->get('molliePayPhone',$billingAddress->getPhone()); + $billingAddress->setPhone($phoneNumber); + + return $payment; + } +} diff --git a/shopware/Component/Payment/Method/BankTransferPayment.php b/shopware/Component/Payment/Method/BankTransferPayment.php new file mode 100644 index 000000000..57356e700 --- /dev/null +++ b/shopware/Component/Payment/Method/BankTransferPayment.php @@ -0,0 +1,21 @@ +getBillingAddress(); + $phoneNumber = $dataBag->get('molliePayPhone',$billingAddress->getPhone()); + $billingAddress->setPhone($phoneNumber); + + return $payment; + } +} diff --git a/shopware/Component/Payment/Method/BlikPayment.php b/shopware/Component/Payment/Method/BlikPayment.php new file mode 100644 index 000000000..42a96f9bd --- /dev/null +++ b/shopware/Component/Payment/Method/BlikPayment.php @@ -0,0 +1,20 @@ +getMandateId() !== null) { + return $payment; + } + + $cardToken = $dataBag->get('creditCardToken'); + if ($cardToken === null) { + return $payment; + } + $payment->setCardToken($cardToken); + + return $payment; + } + + public function getPaymentMethod(): PaymentMethod + { + return PaymentMethod::CREDIT_CARD; + } + + public function getName(): string + { + return 'Card'; + } +} diff --git a/shopware/Component/Payment/Method/DirectDebitPayment.php b/shopware/Component/Payment/Method/DirectDebitPayment.php new file mode 100644 index 000000000..7e8a87a74 --- /dev/null +++ b/shopware/Component/Payment/Method/DirectDebitPayment.php @@ -0,0 +1,21 @@ +get('authenticationId'); + if ($authenticationId !== null) { + $payment->setAuthenticationId($authenticationId); + } + + return $payment; + } + + public function getTechnicalName(): string + { + return parent::getTechnicalName() . 'express'; + } +} diff --git a/shopware/Component/Payment/Method/PayPalPayment.php b/shopware/Component/Payment/Method/PayPalPayment.php new file mode 100644 index 000000000..9f6d866ec --- /dev/null +++ b/shopware/Component/Payment/Method/PayPalPayment.php @@ -0,0 +1,22 @@ +setCustomerReference($customer->getCustomerNumber()); + + return $payment; + } +} diff --git a/shopware/Component/Payment/Method/PayconiqPayment.php b/shopware/Component/Payment/Method/PayconiqPayment.php new file mode 100644 index 000000000..a373e7d8a --- /dev/null +++ b/shopware/Component/Payment/Method/PayconiqPayment.php @@ -0,0 +1,21 @@ +get('terminalId'); + if ($terminalId !== null) { + $payment->setTerminalId($terminalId); + } + + return $payment; + } +} diff --git a/shopware/Component/Payment/Method/Przelewy24Payment.php b/shopware/Component/Payment/Method/Przelewy24Payment.php new file mode 100644 index 000000000..416fc3486 --- /dev/null +++ b/shopware/Component/Payment/Method/Przelewy24Payment.php @@ -0,0 +1,20 @@ +decorated; + } + + public function load(Request $request, SalesChannelContext $context, Criteria $criteria): PaymentMethodRouteResponse + { + $response = $this->decorated->load($request, $context, $criteria); + + if ($this->shouldRemove($request) === false) { + return $response; + } + + $orderId = $request->get('orderId',''); + + $paymentMethods = $response->getPaymentMethods(); + + /** @var AbstractPaymentRemover $paymentMethodRemover */ + foreach ($this->paymentMethodRemovers as $paymentMethodRemover) { + $paymentMethods = $paymentMethodRemover->remove($paymentMethods, $orderId, $context); + } + $response = $response->getObject(); + $response->assign(['entities' => $paymentMethods, 'elements' => $paymentMethods, 'total' => $paymentMethods->count()]); + + return new PaymentMethodRouteResponse($response); + } + + private function getControllerClass(Request $request): ?string + { + $controller = $request->attributes->get('_controller'); + if ($controller === null) { + return null; + } + $controllerParts = explode('::', $controller); + + $controllerClass = $controllerParts[0] ?? null; + if ($controllerClass === null) { + return null; + } + + return $controllerClass; + } + + private function shouldRemove(Request $request): bool + { + $controllerClass = $this->getControllerClass($request); + if ($controllerClass === null) { + return false; + } + + return in_array( + $controllerClass, + [ + CheckoutController::class, + AccountOrderController::class, + ] + ); + } +} diff --git a/shopware/Component/Payment/MethodRemover/VoucherPaymentMethodRemover.php b/shopware/Component/Payment/MethodRemover/VoucherPaymentMethodRemover.php new file mode 100644 index 000000000..68d6c8871 --- /dev/null +++ b/shopware/Component/Payment/MethodRemover/VoucherPaymentMethodRemover.php @@ -0,0 +1,108 @@ +> $orderRepository + */ + public function __construct( + private CartService $cartService, + #[Autowire(service: 'order.repository')] + private EntityRepository $orderRepository, + ) { + } + + public function remove(PaymentMethodCollection $paymentMethods, string $orderId, SalesChannelContext $salesChannelContext): PaymentMethodCollection + { + $filteredPaymentMethods = $paymentMethods->filter(function (PaymentMethodEntity $paymentMethod) { + return $paymentMethod->getHandlerIdentifier() === VoucherPayment::class; + }); + $voucherPaymentMethod = $filteredPaymentMethods->first(); + + if (! $voucherPaymentMethod instanceof PaymentMethodEntity) { + return $paymentMethods; + } + + $voucherPaymentMethodId = $voucherPaymentMethod->getId(); + $hasVoucherItems = false; + if (mb_strlen($orderId) === 0) { + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + $hasVoucherItems = $this->hasVoucherLineItemsByCart($cart); + } else { + $criteria = new Criteria([$orderId]); + $criteria->addAssociation('lineItems'); + $orderSearchResult = $this->orderRepository->search($criteria, $salesChannelContext->getContext()); + $orderEntity = $orderSearchResult->first(); + if ($orderEntity instanceof OrderEntity) { + $hasVoucherItems = $this->hasVoucherLineItemsByOrder($orderEntity); + } + } + if ($hasVoucherItems === false) { + $paymentMethods->remove($voucherPaymentMethodId); + } + + return $paymentMethods; + } + + private function hasVoucherLineItemsByCart(Cart $cart): bool + { + /** @var LineItem $lineItem */ + foreach ($cart->getLineItems() as $lineItem) { + /** @var ?Product $mollieProduct */ + $mollieProduct = $lineItem->getExtension(Mollie::EXTENSION); + if ($mollieProduct === null) { + continue; + } + $voucherCategories = $mollieProduct->getVoucherCategories(); + if ($voucherCategories->count() === 0) { + continue; + } + + return true; + } + + return false; + } + + private function hasVoucherLineItemsByOrder(OrderEntity $orderEntity): bool + { + $lineItems = $orderEntity->getLineItems(); + if ($lineItems === null) { + return false; + } + foreach ($lineItems as $lineItem) { + /** @var ?Product $mollieProduct */ + $mollieProduct = $lineItem->getExtension(Mollie::EXTENSION); + + if ($mollieProduct === null) { + continue; + } + $voucherCategories = $mollieProduct->getVoucherCategories(); + if ($voucherCategories->count() === 0) { + continue; + } + + return true; + } + + return false; + } +} diff --git a/shopware/Component/Payment/PayAction.php b/shopware/Component/Payment/PayAction.php index 26563a91f..63b2a6419 100644 --- a/shopware/Component/Payment/PayAction.php +++ b/shopware/Component/Payment/PayAction.php @@ -7,12 +7,13 @@ use Kiener\MolliePayments\Facade\MolliePaymentDoPay; use Kiener\MolliePayments\Handler\PaymentHandler; use Kiener\MolliePayments\Service\Transition\TransactionTransitionService; +use Mollie\Shopware\Component\Transaction\TransactionConverter; use Mollie\Shopware\Component\Transaction\TransactionConverterInterface; use Psr\Log\LoggerInterface; -use Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct; use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; use Shopware\Core\System\SalesChannel\SalesChannelContext; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\HttpFoundation\RedirectResponse; final class PayAction @@ -22,7 +23,14 @@ final class PayAction private TransactionTransitionService $transactionTransitionService; private TransactionConverterInterface $transactionConverter; - public function __construct(MolliePaymentDoPay $payFacade, TransactionConverterInterface $transactionConverter, TransactionTransitionService $transactionTransitionService, LoggerInterface $logger) + public function __construct( + MolliePaymentDoPay $payFacade, + #[Autowire(service: TransactionConverter::class)] + TransactionConverterInterface $transactionConverter, + #[Autowire(service: TransactionTransitionService::class)] + TransactionTransitionService $transactionTransitionService, + #[Autowire(service: 'monolog.logger.mollie')] + LoggerInterface $logger) { $this->payFacade = $payFacade; $this->transactionTransitionService = $transactionTransitionService; @@ -30,11 +38,10 @@ public function __construct(MolliePaymentDoPay $payFacade, TransactionConverterI $this->transactionConverter = $transactionConverter; } - /** @param AsyncPaymentTransactionStruct|PaymentTransactionStruct $transaction */ - public function pay(PaymentHandler $paymentHandler, $transaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): RedirectResponse + public function pay(PaymentHandler $paymentHandler,PaymentTransactionStruct $shopWareTransaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): RedirectResponse { try { - $transaction = $this->transactionConverter->convert($transaction, $salesChannelContext->getContext()); + $transaction = $this->transactionConverter->convert($shopWareTransaction, $salesChannelContext->getContext()); $this->logger->info( 'Starting Checkout for order ' . $transaction->getOrder()->getOrderNumber() . ' with payment: ' . $paymentHandler->getPaymentMethod(), [ @@ -63,7 +70,7 @@ public function pay(PaymentHandler $paymentHandler, $transaction, RequestDataBag ] ); - throw new PaymentUrlException($transaction->getOrderTransaction()->getId(), $exception->getMessage()); + throw new PaymentUrlException($shopWareTransaction->getOrderTransactionId(), $exception->getMessage()); } try { diff --git a/shopware/Component/Payment/PayPalExpress/PayPalExpressController.php b/shopware/Component/Payment/PayPalExpress/PayPalExpressController.php new file mode 100644 index 000000000..4eefca9a5 --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/PayPalExpressController.php @@ -0,0 +1,91 @@ + ['storefront'], 'csrf_protected' => true])] +final class PayPalExpressController extends StorefrontController +{ + private const SNIPPET_ERROR = 'molliePayments.payments.paypalExpress.paymentError'; + + public function __construct( + #[Autowire(service: StartCheckoutRoute::class)] + private AbstractStartCheckoutRoute $startCheckoutRoute, + #[Autowire(service: FinishCheckoutRoute::class)] + private AbstractFinishCheckoutRoute $finishCheckoutRoute, + #[Autowire(service: CancelCheckoutRoute::class)] + private AbstractCancelCheckoutRoute $cancelCheckoutRoute, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(name: 'frontend.mollie.paypal-express.start', path: '/mollie/paypal-express/start', methods: ['POST', 'GET'], options: ['seo' => false])] + public function startCheckout(Request $request, SalesChannelContext $salesChannelContext): Response + { + try { + $response = $this->startCheckoutRoute->startCheckout($request, $salesChannelContext); + + return new RedirectResponse((string) $response->getRedirectUrl()); + } catch (\Throwable $exception) { + $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); + $this->logger->error( + 'Failed to start Paypal Express checkout', + ['message' => $exception->getMessage()] + ); + + return $this->forwardToRoute('frontend.checkout.cart.page'); + } + } + + #[Route(name: 'frontend.mollie.paypal-express.finish', path: '/mollie/paypal-express/finish', methods: ['POST', 'GET'], options: ['seo' => false])] + public function finishCheckout(Request $request, SalesChannelContext $salesChannelContext): Response + { + try { + $response = $this->finishCheckoutRoute->finishCheckout($salesChannelContext); + + return $this->forwardToRoute('frontend.checkout.confirm.page'); + } catch (\Throwable $exception) { + $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); + $this->logger->error( + 'Failed to finish Paypal Express checkout', + ['message' => $exception->getMessage()] + ); + + return $this->forwardToRoute('frontend.checkout.cart.page'); + } + } + + #[Route(name: 'frontend.mollie.paypal-express.cancel', path: '/mollie/paypal-express/cancel', methods: ['POST', 'GET'], options: ['seo' => false])] + public function cancelCheckout(Request $request, SalesChannelContext $salesChannelContext): Response + { + try { + $response = $this->cancelCheckoutRoute->cancel($salesChannelContext); + + return $this->forwardToRoute('frontend.checkout.cart.page'); + } catch (\Throwable $exception) { + $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); + $this->logger->error( + 'Failed to cancel Paypal Express checkout', + ['message' => $exception->getMessage()] + ); + + return $this->forwardToRoute('frontend.checkout.cart.page'); + } + } +} diff --git a/shopware/Component/Payment/PayPalExpress/PayPalExpressStoreFrontSubscriber.php b/shopware/Component/Payment/PayPalExpress/PayPalExpressStoreFrontSubscriber.php new file mode 100644 index 000000000..5e19a4e6a --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/PayPalExpressStoreFrontSubscriber.php @@ -0,0 +1,59 @@ + 'onStorefrontRender', + ]; + } + + public function onStorefrontRender(StorefrontRenderEvent $event): void + { + $salesChannelContext = $event->getSalesChannelContext(); + $salesChannel = $salesChannelContext->getSalesChannel(); + $salesChannelId = $salesChannel->getId(); + try { + $paypalExpressMethodId = $this->paymentMethodRepository->getIdByPaymentHandler(PayPalExpressPayment::class, $salesChannelId,$salesChannelContext->getContext()); + if ($paypalExpressMethodId === null) { + return; + } + $paypalExpressSettings = $this->settings->getPaypalExpressSettings(); + + $event->setParameter('mollie_paypalexpress_enabled', $paypalExpressSettings->isEnabled()); + + $event->setParameter('mollie_paypalexpress_style', $paypalExpressSettings->getStyle()); + $event->setParameter('mollie_paypalexpress_shape', $paypalExpressSettings->getShape()); + $event->setParameter('mollie_paypalexpress_restrictions', $paypalExpressSettings->getRestrictions()); + } catch (\Throwable $exception) { + $this->logger->error('Failed to assign paypal express data to storefront', [ + 'error' => $exception->getMessage(), + 'salesChannelId' => $salesChannelId, + ]); + } + } +} diff --git a/src/Components/PaypalExpress/PaypalExpressException.php b/shopware/Component/Payment/PayPalExpress/PaypalExpressException.php similarity index 98% rename from src/Components/PaypalExpress/PaypalExpressException.php rename to shopware/Component/Payment/PayPalExpress/PaypalExpressException.php index 1f578ab6d..8cb567d28 100644 --- a/src/Components/PaypalExpress/PaypalExpressException.php +++ b/shopware/Component/Payment/PayPalExpress/PaypalExpressException.php @@ -1,7 +1,7 @@ > $orderRepository + */ + public function __construct( + private CartService $cartService, + #[Autowire(service: 'order.repository')] + private EntityRepository $orderRepository, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + ) { + } + + public function remove(PaymentMethodCollection $paymentMethods, string $orderId, SalesChannelContext $salesChannelContext): PaymentMethodCollection + { + $filteredPaymentMethods = $paymentMethods->filter(function (PaymentMethodEntity $paymentMethod) { + return $paymentMethod->getHandlerIdentifier() === PayPalExpressPayment::class; + }); + $paypalExpressPaymentMethod = $filteredPaymentMethods->first(); + + if (! $paypalExpressPaymentMethod instanceof PaymentMethodEntity) { + return $paymentMethods; + } + + $paypalExpressPaymentMethodId = $paypalExpressPaymentMethod->getId(); + + $paymentMethods->remove($paypalExpressPaymentMethodId); + + $paypalExpressSettings = $this->settingsService->getPaypalExpressSettings($salesChannelContext->getSalesChannelId()); + if (! $paypalExpressSettings->isEnabled()) { + return $paymentMethods; + } + + if (mb_strlen($orderId) === 0) { + return $this->getPaymentMethodsByCart($salesChannelContext, $paypalExpressPaymentMethod, $filteredPaymentMethods, $paymentMethods); + } + + return $this->getPaymentMethodsByOrder($orderId, $salesChannelContext, $paymentMethods, $paypalExpressPaymentMethod, $filteredPaymentMethods); + } + + private function getPaymentMethodsByCart(SalesChannelContext $salesChannelContext, + PaymentMethodEntity $paypalExpressPaymentMethod, + PaymentMethodCollection $filteredPaymentMethods, + PaymentMethodCollection $paymentMethods): PaymentMethodCollection + { + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + /** @var ?Session $paypalSession */ + $paypalSession = $cart->getExtension(Mollie::EXTENSION); + if (! $paypalSession instanceof Session) { + return $paymentMethods; + } + + $this->setAuthenticateId($paypalExpressPaymentMethod, $paypalSession->getAuthenticationId()); + + return $filteredPaymentMethods; + } + + private function getPaymentMethodsByOrder(string $orderId, SalesChannelContext $salesChannelContext, PaymentMethodCollection $paymentMethods, PaymentMethodEntity $paypalExpressPaymentMethod, PaymentMethodCollection $filteredPaymentMethods): PaymentMethodCollection + { + $criteria = new Criteria([$orderId]); + $criteria->addAssociation('transactions'); + $criteria->getAssociation('transactions')->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING))->setLimit(1); + + $orderSearchResult = $this->orderRepository->search($criteria, $salesChannelContext->getContext()); + $orderEntity = $orderSearchResult->first(); + + if (! $orderEntity instanceof OrderEntity) { + return $paymentMethods; + } + + $orderTransactions = $orderEntity->getTransactions(); + + if (! $orderTransactions instanceof OrderTransactionCollection) { + return $paymentMethods; + } + $latestTransaction = $orderTransactions->first(); + + if (! $latestTransaction instanceof OrderTransactionEntity) { + return $paymentMethods; + } + /** @var ?Payment $paymentExtension */ + $paymentExtension = $latestTransaction->getExtension(Mollie::EXTENSION); + if (! $paymentExtension instanceof Payment) { + return $paymentMethods; + } + $authenticationId = $paymentExtension->getAuthenticationId(); + if ($authenticationId === null) { + return $paymentMethods; + } + + $this->setAuthenticateId($paypalExpressPaymentMethod, $authenticationId); + + return $filteredPaymentMethods; + } + + private function setAuthenticateId(PaymentMethodEntity $paypalExpressPaymentMethod, string $authenticationId): void + { + $paymentMethodCustomFields = $paypalExpressPaymentMethod->getCustomFields() ?? []; + $paymentMethodCustomFields[Mollie::EXTENSION] = [ + 'authenticationId' => $authenticationId, + ]; + $paypalExpressPaymentMethod->setCustomFields($paymentMethodCustomFields); + } +} diff --git a/shopware/Component/Payment/PayPalExpress/Route/AbstractCancelCheckoutRoute.php b/shopware/Component/Payment/PayPalExpress/Route/AbstractCancelCheckoutRoute.php new file mode 100644 index 000000000..39eb26222 --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/Route/AbstractCancelCheckoutRoute.php @@ -0,0 +1,13 @@ +> + * @extends StoreApiResponse */ -class CancelCheckoutResponse extends StoreApiResponse +final class CancelCheckoutResponse extends StoreApiResponse { - private string $sessionId; - - public function __construct(string $sessionId) + public function __construct(private string $sessionId) { - $this->sessionId = $sessionId; - parent::__construct(new ArrayStruct( [ - 'sessionId' => $sessionId, + 'sessionId' => $this->sessionId, ], 'paypal_express_cancel_checkout_response' )); diff --git a/shopware/Component/Payment/PayPalExpress/Route/CancelCheckoutRoute.php b/shopware/Component/Payment/PayPalExpress/Route/CancelCheckoutRoute.php new file mode 100644 index 000000000..c8fea9069 --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/Route/CancelCheckoutRoute.php @@ -0,0 +1,74 @@ + ['store-api']])] +final class CancelCheckoutRoute extends AbstractCancelCheckoutRoute +{ + public function __construct( + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: PaymentMethodRepository::class)] + private PaymentMethodRepositoryInterface $paymentMethodRepository, + #[Autowire(service: SessionGateway::class)] + private SessionGatewayInterface $sessionGateway, + private CartService $cartService, + ) { + } + + public function getDecorated(): AbstractCancelCheckoutRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.paypal-express.checkout.cancel', path: '/store-api/mollie/paypal-express/cancel', methods: ['GET'])] + public function cancel(SalesChannelContext $salesChannelContext): CancelCheckoutResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $payPalExpressId = $this->paymentMethodRepository->getIdByPaymentHandler(PayPalExpressPayment::class, $salesChannelId, $salesChannelContext->getContext()); + if ($payPalExpressId === null) { + throw PaypalExpressException::paymentNotEnabled($salesChannelId); + } + + $settings = $this->settingsService->getPaypalExpressSettings($salesChannelId); + + if ($settings->isEnabled() === false) { + throw PaypalExpressException::paymentNotEnabled($salesChannelId); + } + + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + /** @var ?Session $cartExtension */ + $cartExtension = $cart->getExtension(Mollie::EXTENSION); + if ($cartExtension === null) { + throw PaypalExpressException::cartSessionIdIsEmpty(); + } + $cart->removeExtension(Mollie::EXTENSION); + $this->cartService->recalculate($cart, $salesChannelContext); + + try { + $this->sessionGateway->cancelSession($cartExtension->getId(), $salesChannelContext); + } catch (\Throwable $exception) { + } + + return new CancelCheckoutResponse($cartExtension->getId()); + } +} diff --git a/src/Components/PaypalExpress/Route/FinishCheckoutResponse.php b/shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutResponse.php similarity index 87% rename from src/Components/PaypalExpress/Route/FinishCheckoutResponse.php rename to shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutResponse.php index 3de658906..4ef07e80e 100644 --- a/src/Components/PaypalExpress/Route/FinishCheckoutResponse.php +++ b/shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutResponse.php @@ -1,17 +1,15 @@ > */ -class FinishCheckoutResponse extends StoreApiResponse +final class FinishCheckoutResponse extends StoreApiResponse { private string $sessionId; private string $authenticateId; diff --git a/shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutRoute.php b/shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutRoute.php new file mode 100644 index 000000000..1b220e9d9 --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/Route/FinishCheckoutRoute.php @@ -0,0 +1,86 @@ + ['store-api']])] +final class FinishCheckoutRoute extends AbstractFinishCheckoutRoute +{ + public function __construct( + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: SessionGateway::class)] + private SessionGatewayInterface $sessionGateway, + #[Autowire(service: AccountService::class)] + private AbstractAccountService $accountService, + #[Autowire(service: PaymentMethodRepository::class)] + private PaymentMethodRepositoryInterface $paymentMethodRepository, + private CartService $cartService, + ) { + } + + public function getDecorated(): AbstractStartCheckoutRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.paypal-express.checkout.finish', path: '/store-api/mollie/paypal-express/finish', methods: ['GET'])] + public function finishCheckout(SalesChannelContext $salesChannelContext): FinishCheckoutResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $payPalExpressId = $this->paymentMethodRepository->getIdByPaymentHandler(PayPalExpressPayment::class, $salesChannelId, $salesChannelContext->getContext()); + if ($payPalExpressId === null) { + throw PaypalExpressException::paymentNotEnabled($salesChannelId); + } + + $settings = $this->settingsService->getPaypalExpressSettings($salesChannelId); + + if ($settings->isEnabled() === false) { + throw PaypalExpressException::paymentNotEnabled($salesChannelId); + } + + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + /** @var ?Session $cartExtension */ + $cartExtension = $cart->getExtension(Mollie::EXTENSION); + if ($cartExtension === null) { + throw PaypalExpressException::cartSessionIdIsEmpty(); + } + $session = $this->sessionGateway->loadSession($cartExtension->getId(), $salesChannelContext); + + $billingAddress = $session->getBillingAddress(); + if ($billingAddress === null) { + throw PaypalExpressException::billingAddressMissing(); + } + $shippingAddress = $session->getShippingAddress(); + if ($shippingAddress === null) { + throw PaypalExpressException::shippingAddressMissing(); + } + + $newContext = $this->accountService->loginOrCreateAccount($payPalExpressId, $billingAddress, $shippingAddress, $salesChannelContext); + $cart = $this->cartService->getCart($newContext->getToken(), $newContext); + $cart->addExtension(Mollie::EXTENSION, $session); + $this->cartService->recalculate($cart, $salesChannelContext); + + return new FinishCheckoutResponse($session->getId(), $session->getAuthenticationId()); + } +} diff --git a/src/Components/PaypalExpress/Route/StartCheckoutResponse.php b/shopware/Component/Payment/PayPalExpress/Route/StartCheckoutResponse.php similarity index 87% rename from src/Components/PaypalExpress/Route/StartCheckoutResponse.php rename to shopware/Component/Payment/PayPalExpress/Route/StartCheckoutResponse.php index 46cc4e638..8e61856ab 100644 --- a/src/Components/PaypalExpress/Route/StartCheckoutResponse.php +++ b/shopware/Component/Payment/PayPalExpress/Route/StartCheckoutResponse.php @@ -1,17 +1,15 @@ > - * - * @final */ -class StartCheckoutResponse extends StoreApiResponse +final class StartCheckoutResponse extends StoreApiResponse { private string $sessionId; private ?string $redirectUrl; diff --git a/shopware/Component/Payment/PayPalExpress/Route/StartCheckoutRoute.php b/shopware/Component/Payment/PayPalExpress/Route/StartCheckoutRoute.php new file mode 100644 index 000000000..7b01e7a4d --- /dev/null +++ b/shopware/Component/Payment/PayPalExpress/Route/StartCheckoutRoute.php @@ -0,0 +1,65 @@ + ['store-api']])] +final class StartCheckoutRoute extends AbstractStartCheckoutRoute +{ + public function __construct( + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: SessionGateway::class)] + private SessionGatewayInterface $sessionGateway, + private CartService $cartService, + ) { + } + + public function getDecorated(): AbstractStartCheckoutRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(name: 'store-api.mollie.paypal-express.checkout.start', path: '/store-api/mollie/paypal-express/start', methods: ['GET'])] + public function startCheckout(Request $request, SalesChannelContext $salesChannelContext): StartCheckoutResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $settings = $this->settingsService->getPaypalExpressSettings($salesChannelId); + + if ($settings->isEnabled() === false) { + throw PaypalExpressException::paymentNotEnabled($salesChannelId); + } + + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + + if ($cart->getLineItems()->count() === 0) { + throw PaypalExpressException::cartIsEmpty(); + } + + $session = $this->sessionGateway->createPaypalExpressSession($cart, $salesChannelContext); + + $cart->addExtension(Mollie::EXTENSION, $session); + + $this->cartService->recalculate($cart, $salesChannelContext); + + return new StartCheckoutResponse( + $session->getId(), + $session->getRedirectUrl(), + ); + } +} diff --git a/shopware/Component/Payment/PaymentHandlerLegacyTrait.php b/shopware/Component/Payment/PaymentHandlerLegacyTrait.php deleted file mode 100644 index 2dfbd0b25..000000000 --- a/shopware/Component/Payment/PaymentHandlerLegacyTrait.php +++ /dev/null @@ -1,65 +0,0 @@ -payAction = $payAction; - $this->finalizeAction = $finalizeAction; - } - - public function getPaymentMethod(): string - { - return $this->paymentMethod; - } - - /** - * @param array $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } - - /** - * The pay function will be called after the customer completed the order. - * Allows to process the order and store additional information. - * - * A redirect to the url will be performed - * - * Throw a - * - * @throws ApiException - * - * @return RedirectResponse @see AsyncPaymentProcessException exception if an error ocurres while processing the - * payment - */ - public function pay(AsyncPaymentTransactionStruct $transaction, RequestDataBag $dataBag, SalesChannelContext $salesChannelContext): RedirectResponse - { - return $this->payAction->pay($this, $transaction, $dataBag, $salesChannelContext); - } - - public function finalize(AsyncPaymentTransactionStruct $transaction, Request $request, SalesChannelContext $salesChannelContext): void - { - $this->finalizeAction->finalize($this, $transaction, $salesChannelContext->getContext()); - } -} diff --git a/shopware/Component/Payment/PaymentHandlerLocator.php b/shopware/Component/Payment/PaymentHandlerLocator.php new file mode 100644 index 000000000..0d2005d08 --- /dev/null +++ b/shopware/Component/Payment/PaymentHandlerLocator.php @@ -0,0 +1,60 @@ +addPaymentMethod($paymentMethod); + } + } + + /** + * @return AbstractMolliePaymentHandler[] + */ + public function getPaymentMethods(): array + { + return $this->paymentMethods; + } + + public function findByPaymentMethod(string $paymentMethodName): ?AbstractMolliePaymentHandler + { + foreach ($this->paymentMethods as $paymentMethod) { + if ($paymentMethod->getPaymentMethod()->value === $paymentMethodName) { + return $paymentMethod; + } + } + + return null; + } + + public function findByIdentifier(string $paymentHandlerIdentifier): ?AbstractMolliePaymentHandler + { + foreach ($this->paymentMethods as $paymentMethod) { + if (get_class($paymentMethod) === $paymentHandlerIdentifier) { + return $paymentMethod; + } + } + + return null; + } + + private function addPaymentMethod(AbstractMolliePaymentHandler $paymentMethod): void + { + $this->paymentMethods[] = $paymentMethod; + } +} diff --git a/shopware/Component/Payment/PaymentMethodInstaller.php b/shopware/Component/Payment/PaymentMethodInstaller.php new file mode 100644 index 000000000..2c5f28904 --- /dev/null +++ b/shopware/Component/Payment/PaymentMethodInstaller.php @@ -0,0 +1,207 @@ +> $shopwarePaymentMethodRepository + * @param EntityRepository> $mediaRepository + */ + public function __construct( + private PaymentHandlerLocator $paymentHandlerLocator, + #[Autowire(service: 'payment_method.repository')] + private EntityRepository $shopwarePaymentMethodRepository, + #[Autowire(service: 'media.repository')] + private EntityRepository $mediaRepository, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + private MediaService $mediaService, + private FileFetcher $fileFetcher, + private PluginIdProvider $pluginIdProvider, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function install(Context $context): EntityWrittenContainerEvent + { + $upsertData = $this->loadPaymentMethodMapping($context); + + return $this->shopwarePaymentMethodRepository->upsert($upsertData, $context); + } + + /** + * @return array + */ + private function loadPaymentMethodMapping(Context $context): array + { + $molliePaymentMethods = $this->paymentHandlerLocator->getPaymentMethods(); + $pluginId = $this->pluginIdProvider->getPluginIdByBaseClass(MolliePayments::class, $context); + $paypalExpressSettings = $this->settingsService->getPaypalExpressSettings(); + + $mapping = []; + $iconMapping = []; + $handlers = []; + /** @var AbstractMolliePaymentHandler $paymentHandler */ + foreach ($molliePaymentMethods as $paymentHandler) { + $handlerIdentifier = get_class($paymentHandler); + + if ($paymentHandler instanceof PayPalExpressPayment && ! $paypalExpressSettings->isEnabled()) { + continue; + } + $paymentMethod = $paymentHandler->getPaymentMethod(); + $isDeprecatedMethod = $paymentHandler instanceof DeprecatedMethodAwareInterface; + $paymentMethodName = $paymentHandler->getName(); + $paymentMethodTechnicalName = $paymentHandler->getTechnicalName(); + $mapping[$handlerIdentifier] = [ + 'id' => Uuid::fromStringToHex('mollie-payment-' . $paymentMethodTechnicalName), + 'pluginId' => $pluginId, + 'afterOrderEnabled' => true, + 'technicalName' => $paymentMethodTechnicalName, + 'handlerIdentifier' => $handlerIdentifier, + 'name' => $paymentMethodName, + 'translations' => [ + Defaults::LANGUAGE_SYSTEM => [ + 'name' => $paymentMethodName, + ], + ], + 'customFields' => [ + 'mollie_payment_method_name' => $paymentMethod->value, + ], + 'active' => $isDeprecatedMethod === false + ]; + + $handlers[$handlerIdentifier] = $paymentHandler; + $iconMapping[$paymentHandler->getIconFileName()] = $handlerIdentifier; + } + + $iconNames = array_keys($iconMapping); + $criteria = new Criteria(); + $criteria->addFilter(new EqualsAnyFilter('fileName', $iconNames)); + $iconNamesSearchResult = $this->mediaRepository->search($criteria, $context); + if ($iconNamesSearchResult->getTotal() > 0) { + /** @var MediaEntity $mediaEntity */ + foreach ($iconNamesSearchResult->getIterator() as $mediaEntity) { + $fileName = (string) $mediaEntity->getFileName(); + $currentHandlerIdentifier = $iconMapping[$fileName]; + $mapping[$currentHandlerIdentifier]['mediaId'] = $mediaEntity->getId(); + unset($iconMapping[$fileName]); + } + } + + if (count($iconMapping) > 0) { + foreach ($iconMapping as $fileName => $handlerIdentifier) { + $currentHandlerIdentifier = $iconMapping[$fileName]; + $mediaFile = $this->loadMedia($fileName); + if ($mediaFile === null) { + unset($iconMapping[$fileName]); + continue; + } + $mediaId = $this->mediaService->saveMediaFile($mediaFile, $fileName, $context, 'payment_method', null, false); + $mapping[$currentHandlerIdentifier]['mediaId'] = $mediaId; + unset($iconMapping[$fileName]); + } + } + + $handlerIdentifiers = array_keys($mapping); + $criteria = new Criteria(); + $criteria->addFilter(new EqualsAnyFilter('handlerIdentifier', $handlerIdentifiers)); + $criteria->addAssociation('translations'); + $paymentMethodSearchResult = $this->shopwarePaymentMethodRepository->search($criteria, $context); + + if ($paymentMethodSearchResult->getTotal() > 0) { + /** @var PaymentMethodEntity $paymentMethodEntity */ + foreach ($paymentMethodSearchResult->getIterator() as $paymentMethodEntity) { + $changedData = [ + 'id' => $paymentMethodEntity->getId(), + 'afterOrderEnabled' => $paymentMethodEntity->getAfterOrderEnabled(), + 'technicalName' => (string) $paymentMethodEntity->getTechnicalName(), + 'name' => $paymentMethodEntity->getName(), + 'description' => $paymentMethodEntity->getDescription(), + 'active' => $paymentMethodEntity->getActive(), + ]; + $translations = $paymentMethodEntity->getTranslations(); + + if ($translations !== null) { + $changedData['translations'][Defaults::LANGUAGE_SYSTEM] = [ + 'name' => $paymentMethodEntity->getName(), + 'description' => $paymentMethodEntity->getDescription(), + ]; + + foreach ($translations as $translation) { + $changedData['translations'][$translation->getLanguageId()] = [ + 'name' => $translation->getName(), + 'description' => $translation->getDescription(), + ]; + } + } + + $handler = $handlers[$paymentMethodEntity->getHandlerIdentifier()] ?? null; + + if ($handler instanceof DeprecatedMethodAwareInterface) { + $changedData['active'] = false; + } + + $mapping[$paymentMethodEntity->getHandlerIdentifier()] = array_replace($mapping[$paymentMethodEntity->getHandlerIdentifier()], $changedData); + } + } + + return array_values($mapping); + } + + private function loadMedia(string $fileName): ?MediaFile + { + $request = new Request(); + $extensions = ['.svg', '.png']; + foreach ($extensions as $extension) { + $url = 'https://www.mollie.com/external/icons/payment-methods/' . str_replace('-icon', '', $fileName) . $extension; + try { + $request->request->set('url', $url); + + return $this->fileFetcher->fetchFileFromURL($request, $fileName); + } catch (MediaException $e) { + $message = sprintf('Failed to load icon from url'); + $this->logger->warning($message, [ + 'exception' => $e->getMessage(), + 'file' => $fileName, + 'url' => $url, + ]); + } + } + + $this->logger->error('Failed to load payment method icon, PNG and SVG', [ + 'file' => $fileName, + 'url' => $url, + ]); + + return null; + } +} diff --git a/shopware/Component/Payment/PaymentMethodRepository.php b/shopware/Component/Payment/PaymentMethodRepository.php new file mode 100644 index 000000000..330332d6d --- /dev/null +++ b/shopware/Component/Payment/PaymentMethodRepository.php @@ -0,0 +1,54 @@ +> $paymentMethodRepository + */ + public function __construct( + #[Autowire(service: 'payment_method.repository')] + private EntityRepository $paymentMethodRepository + ) { + } + + public function getIdByPaymentHandler(string $handlerIdentifier, string $salesChannelId, Context $context): ?string + { + $criteria = $this->getCriteria($salesChannelId); + $criteria->addFilter(new EqualsFilter('handlerIdentifier', $handlerIdentifier)); + $searchResult = $this->paymentMethodRepository->searchIds($criteria, $context); + + return $searchResult->firstId(); + } + + public function getIdByPaymentMethod(PaymentMethod $paymentMethod, string $salesChannelId, Context $context): ?string + { + $criteria = $this->getCriteria($salesChannelId); + $criteria->addFilter(new EqualsFilter('technicalName', 'payment_mollie_' . $paymentMethod->value)); + + $searchResult = $this->paymentMethodRepository->searchIds($criteria, $context); + + return $searchResult->firstId(); + } + + private function getCriteria(string $salesChannelId): Criteria + { + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('active', true)); + $criteria->addFilter(new EqualsFilter('salesChannels.id', $salesChannelId)); + $criteria->setLimit(1); + + return $criteria; + } +} diff --git a/shopware/Component/Payment/PaymentMethodRepositoryInterface.php b/shopware/Component/Payment/PaymentMethodRepositoryInterface.php new file mode 100644 index 000000000..1ab7f3287 --- /dev/null +++ b/shopware/Component/Payment/PaymentMethodRepositoryInterface.php @@ -0,0 +1,14 @@ +> $orderTransactionRepository + */ + public function __construct( + #[Autowire(service: 'order_transaction.repository')] + private EntityRepository $orderTransactionRepository, + #[Autowire(service: PaymentMethodRepository::class)] + private PaymentMethodRepositoryInterface $paymentMethodRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function updatePaymentMethod(PaymentMethodExtension $paymentMethodExtension, PaymentMethod $molliePaymentMethod, string $transactionId, string $orderNumber, string $salesChannelId, Context $context): string + { + $shopwarePaymentMethod = $paymentMethodExtension->getPaymentMethod(); + $logData = [ + 'transactionId' => $transactionId, + 'molliePaymentMethod' => $molliePaymentMethod->value, + 'orderNumber' => $orderNumber, + 'shopwarePaymentMethod' => $shopwarePaymentMethod->value, + ]; + + $this->logger->info('Change payment method if changed', $logData); + + if ($molliePaymentMethod === PaymentMethod::DIRECT_DEBIT) { + $this->logger->debug('Payment method is direct debit, must be subscription renewal', $logData); + + return $paymentMethodExtension->getId(); + } + + if ($shopwarePaymentMethod === $molliePaymentMethod) { + $this->logger->debug('Payment methods are the same', $logData); + + return $paymentMethodExtension->getId(); + } + + if ($shopwarePaymentMethod === PaymentMethod::APPLEPAY && $molliePaymentMethod === PaymentMethod::CREDIT_CARD) { + $this->logger->debug('Apple Pay payment methods are stored as credit card in mollie, no change needed', $logData); + + return $paymentMethodExtension->getId(); + } + + $this->logger->debug('Payment methods are different, try to find payment method based on mollies payment method name', $logData); + + $newPaymentMethodId = $this->paymentMethodRepository->getIdByPaymentMethod($molliePaymentMethod, $salesChannelId, $context); + + if ($newPaymentMethodId === null) { + $this->logger->error('Failed to find payment payment method based on "molliePaymentMethod" in database', $logData); + $message = sprintf('The Transaction has %s set as payment method in Mollie, but this payment method does not exists or not enabled in shopware',$molliePaymentMethod->value); + throw new \RuntimeException($message); + } + + $this->orderTransactionRepository->upsert([ + [ + 'id' => $transactionId, + 'paymentMethodId' => $newPaymentMethodId + ] + ], $context); + + $this->logger->info('Changed payment methods for transaction', $logData); + + return $newPaymentMethodId; + } +} diff --git a/shopware/Component/Payment/PaymentMethodUpdaterInterface.php b/shopware/Component/Payment/PaymentMethodUpdaterInterface.php new file mode 100644 index 000000000..8623bedbd --- /dev/null +++ b/shopware/Component/Payment/PaymentMethodUpdaterInterface.php @@ -0,0 +1,13 @@ + ['storefront']])] +final class PointOfSaleController extends StorefrontController +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + private StoreTerminalRoute $storeTerminalRoute, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/mollie/pos/checkout', methods: ['GET'], name: 'frontend.mollie.pos.checkout', options: ['seo' => false])] + public function checkout(Request $request, SalesChannelContext $salesChannelContext): Response + { + $salesChannel = $salesChannelContext->getSalesChannel(); + + $logParameters = [ + 'transactionId' => $request->get('transactionId'), + 'orderNumber' => $request->get('orderNumber'), + 'salesChannelId' => $salesChannel->getId(), + 'salesChannelName' => $salesChannel->getName(), + ]; + + $this->logger->info('Opened Terminal route', $logParameters); + + return $this->renderStorefront('@Storefront/mollie/pos/checkout.html.twig', $request->query->all()); + } + + #[Route(path: '/mollie/pos/{transactionId}/{paymentId}/status', methods: ['GET'], name: 'frontend.mollie.pos.checkout_status', options: ['seo' => false])] + public function checkStatus(string $transactionId, string $paymentId, SalesChannelContext $salesChannelContext): Response + { + $salesChannel = $salesChannelContext->getSalesChannel(); + + $logParameters = [ + 'orderNumber' => $transactionId, + 'paymentId' => $paymentId, + 'salesChannelId' => $salesChannel->getId(), + 'salesChannelName' => $salesChannel->getName(), + ]; + $this->logger->debug('Check payment status from terminal', $logParameters); + + $payment = $this->mollieGateway->getPaymentByTransactionId($transactionId, $salesChannelContext->getContext()); + $ready = $payment->getStatus() !== PaymentStatus::OPEN; + + return new JsonResponse([ + 'ready' => $ready, + 'redirectUrl' => $payment->getFinalizeUrl(), + 'success' => true, + ]); + } + + #[Route(path: '/mollie/pos/store-terminal/{customerId}/{terminalId}',name: 'frontend.mollie.pos.storeTerminal',options: ['seo' => false])] + public function storeTerminal(string $customerId,string $terminalId,SalesChannelContext $salesChannelContext): JsonResponse + { + $response = $this->storeTerminalRoute->storeTerminal($customerId, $terminalId, $salesChannelContext); + + return new JsonResponse($response->getObject()->getVars()); + } +} diff --git a/shopware/Component/Payment/PointOfSale/Route/AbstractListTerminalsRoute.php b/shopware/Component/Payment/PointOfSale/Route/AbstractListTerminalsRoute.php new file mode 100644 index 000000000..bd72f9f64 --- /dev/null +++ b/shopware/Component/Payment/PointOfSale/Route/AbstractListTerminalsRoute.php @@ -0,0 +1,13 @@ + + */ +final class ListTerminalsResponse extends StoreApiResponse +{ + public function __construct(private TerminalCollection $terminals) + { + $object = new ArrayStruct( + [ + 'terminals' => $this->terminals->jsonSerialize(), + ], + 'mollie_payments_pos_terminals' + ); + + parent::__construct($object); + } + + public function getTerminals(): TerminalCollection + { + return $this->terminals; + } +} diff --git a/shopware/Component/Payment/PointOfSale/Route/ListTerminalsRoute.php b/shopware/Component/Payment/PointOfSale/Route/ListTerminalsRoute.php new file mode 100644 index 000000000..8a392ca55 --- /dev/null +++ b/shopware/Component/Payment/PointOfSale/Route/ListTerminalsRoute.php @@ -0,0 +1,47 @@ + ['store-api']])] +final class ListTerminalsRoute extends AbstractListTerminalsRoute +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractListTerminalsRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/store-api/mollie/pos/terminals', name: 'store-api.mollie.pos.terminals', methods: ['GET'])] + public function list(SalesChannelContext $salesChannelContext): ListTerminalsResponse + { + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $salesChannelName = (string) $salesChannelContext->getSalesChannel()->getName(); + $logData = [ + 'path' => '/store-api/mollie/pos/terminals', + 'salesChannelId' => $salesChannelId, + 'salesChannelName' => $salesChannelName, + ]; + $this->logger->debug('List terminals route called', $logData); + $terminals = $this->mollieGateway->listTerminals($salesChannelContext->getSalesChannelId()); + + return new ListTerminalsResponse($terminals); + } +} diff --git a/shopware/Component/Payment/PointOfSale/Route/StoreTerminalResponse.php b/shopware/Component/Payment/PointOfSale/Route/StoreTerminalResponse.php new file mode 100644 index 000000000..85172cd3b --- /dev/null +++ b/shopware/Component/Payment/PointOfSale/Route/StoreTerminalResponse.php @@ -0,0 +1,26 @@ + + */ +final class StoreTerminalResponse extends StoreApiResponse +{ + public function __construct() + { + $object = new ArrayStruct( + [ + 'success' => true, + 'message' => 'Using deprecated route, please provide "terminalId" in request body for payment' + ], + 'mollie_payments_pos_terminal_stored' + ); + + parent::__construct($object); + } +} diff --git a/shopware/Component/Payment/PointOfSale/Route/StoreTerminalRoute.php b/shopware/Component/Payment/PointOfSale/Route/StoreTerminalRoute.php new file mode 100644 index 000000000..22c40089e --- /dev/null +++ b/shopware/Component/Payment/PointOfSale/Route/StoreTerminalRoute.php @@ -0,0 +1,29 @@ + ['store-api']])] +final class StoreTerminalRoute +{ + public function __construct( + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + #[Route(path: '/store-api/mollie/pos/store-terminal/{customerId}/{terminalId}', name: 'store-api.mollie.pos.store-terminal', methods: ['POST'])] + public function storeTerminal(string $customerId, string $terminalId, SalesChannelContext $salesChannelContext): StoreTerminalResponse + { + $this->logger->warning('Deprecated URL was called, terminal IDs are not stored anymore, please provide "terminalId" in checkout'); + + return new StoreTerminalResponse(); + } +} diff --git a/shopware/Component/Payment/Resources/config/services.xml b/shopware/Component/Payment/Resources/config/services.xml deleted file mode 100644 index 2530827b2..000000000 --- a/shopware/Component/Payment/Resources/config/services.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Component/Payment/Route/AbstractReturnRoute.php b/shopware/Component/Payment/Route/AbstractReturnRoute.php new file mode 100644 index 000000000..a3aba2147 --- /dev/null +++ b/shopware/Component/Payment/Route/AbstractReturnRoute.php @@ -0,0 +1,13 @@ + ['api'], 'auth_required' => false, 'auth_enabled' => false])] +final class ReturnRoute extends AbstractReturnRoute +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private MollieGatewayInterface $mollieGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger, + ) { + } + + public function getDecorated(): AbstractReturnRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/api/mollie/payment/return/{transactionId}',name: 'api.mollie.payment-return', methods: ['GET', 'POST'])] + public function return(string $transactionId, Context $context): ReturnRouteResponse + { + $this->logger->debug('Return route opened',[ + 'transactionId' => $transactionId, + ]); + $payment = $this->mollieGateway->getPaymentByTransactionId($transactionId, $context); + + return new ReturnRouteResponse($payment); + } +} diff --git a/shopware/Component/Payment/Route/ReturnRouteResponse.php b/shopware/Component/Payment/Route/ReturnRouteResponse.php new file mode 100644 index 000000000..5a826edb9 --- /dev/null +++ b/shopware/Component/Payment/Route/ReturnRouteResponse.php @@ -0,0 +1,56 @@ + + */ +final class ReturnRouteResponse extends StoreApiResponse +{ + public function __construct(private Payment $payment) + { + parent::__construct(new ArrayStruct( + [ + 'paymentId' => $this->payment->getId(), + 'status' => $this->payment->getStatus(), + 'orderId' => $this->payment->getShopwareTransaction()->getOrderId(), + 'finalizeUrl' => $this->payment->getFinalizeUrl(), + ], + 'mollie_payment_return_response' + )); + } + + public function getPaymentStatus(): PaymentStatus + { + return $this->payment->getStatus(); + } + + public function getPaymentId(): string + { + return $this->payment->getId(); + } + + public function getPayment(): Payment + { + return $this->payment; + } + + /** + * @return mixed + */ + public function getOrderId() + { + return $this->payment->getShopwareTransaction()->getOrderId(); + } + + public function getFinalizeUrl(): string + { + return $this->payment->getFinalizeUrl(); + } +} diff --git a/shopware/Component/Payment/Route/WebhookException.php b/shopware/Component/Payment/Route/WebhookException.php new file mode 100644 index 000000000..7b3b9f0cd --- /dev/null +++ b/shopware/Component/Payment/Route/WebhookException.php @@ -0,0 +1,116 @@ + $transactionId, + ] + ); + } + + public static function transactionWithoutPaymentMethod(string $transactionId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::TRANSACTION_WITHOUT_PAYMENT_METHOD, + 'Transaction {{transactionId}} was loaded without payment method',[ + 'transactionId' => $transactionId, + ] + ); + } + + public static function transactionWithoutMolliePayment(string $transactionId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::TRANSACTION_WITHOUT_MOLLIE_PAYMENT, + 'Transaction {{transactionId}} does not have mollie custom fields',[ + 'transactionId' => $transactionId, + ] + ); + } + + public static function paymentWithoutMethod(string $transactionId, string $paymentId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::PAYMENT_WITHOUT_METHOD, + 'Mollie payment {{paymentId}} is without payment method in transaction {{transactionId}}',[ + 'transactionId' => $transactionId, + 'paymentId' => $paymentId, + ] + ); + } + + public static function orderWithoutState(string $transactionId, string $orderNumber): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::ORDER_WITHOUT_STATE, + 'Transaction {{transactionId}} in order {{orderNumber}} does not have a StateMachineState',[ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + ] + ); + } + + public static function paymentStatusChangeFailed(string $transactionId, string $orderNumber, \Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::PAYMENT_STATUS_CHANGE_FAILED, + 'Failed to change payment status in order {{orderNumber}} for transaction {{transactionId}}',[ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + ], + $exception + ); + } + + public static function orderStatusChangeFailed(string $transactionId, string $orderNumber, \Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::ORDER_STATUS_CHANGE_FAILED, + 'Failed to change order status in order {{orderNumber}} for transaction {{transactionId}}',[ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + ], + $exception + ); + } + + public static function paymentMethodChangeFailed(string $transactionId, string $orderNumber, \Throwable $exception): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::PAYMENT_METHOD_CHANGE_FAILED, + 'Failed to change payment method in order {{orderNumber}} for transaction {{transactionId}}',[ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + ], + $exception + ); + } +} diff --git a/shopware/Component/Payment/Route/WebhookResponse.php b/shopware/Component/Payment/Route/WebhookResponse.php new file mode 100644 index 000000000..6d4e7def6 --- /dev/null +++ b/shopware/Component/Payment/Route/WebhookResponse.php @@ -0,0 +1,29 @@ + + */ +final class WebhookResponse extends StoreApiResponse +{ + public function __construct(private Payment $payment) + { + parent::__construct(new ArrayStruct( + [ + 'payment' => $this->payment, + 'status' => 'success', + ], 'webhook.route.success' + )); + } + + public function getPayment(): Payment + { + return $this->payment; + } +} diff --git a/shopware/Component/Payment/Route/WebhookRoute.php b/shopware/Component/Payment/Route/WebhookRoute.php new file mode 100644 index 000000000..c27af7f1a --- /dev/null +++ b/shopware/Component/Payment/Route/WebhookRoute.php @@ -0,0 +1,220 @@ + ['api'], 'auth_required' => false, 'auth_enabled' => false])] +final class WebhookRoute extends AbstractWebhookRoute +{ + public function __construct( + #[Autowire(service: MollieGateway::class)] + private readonly MollieGatewayInterface $mollieGateway, + private readonly OrderTransactionStateHandler $stateMachineHandler, + #[Autowire(service: 'event_dispatcher')] + private readonly EventDispatcherInterface $eventDispatcher, + #[Autowire(service: PaymentMethodUpdater::class)] + private readonly PaymentMethodUpdaterInterface $paymentMethodUpdater, + #[Autowire(service: OrderStateHandler::class)] + private readonly OrderStateHandlerInterface $orderStateHandler, + private readonly OrderService $orderService, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger, + ) { + } + + public function getDecorated(): self + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/api/mollie/webhook/{transactionId}', name: 'api.mollie.webhook', methods: ['GET', 'POST'])] + public function notify(string $transactionId, Context $context): WebhookResponse + { + $logData = [ + 'transactionId' => $transactionId, + ]; + $this->logger->debug('Webhook Process - Requested', $logData); + $payment = $this->mollieGateway->getPaymentByTransactionId($transactionId, $context); + + $shopwareOrder = $payment->getShopwareTransaction()->getOrder(); + if ($shopwareOrder === null) { + $this->logger->error('Webhook Process Failed - Order not found'); + throw WebhookException::transactionWithoutOrder($transactionId); + } + $orderNumber = (string) $shopwareOrder->getOrderNumber(); + $logData['orderNumber'] = $orderNumber; + + $this->logger->info('Webhook Process - Start', $logData); + $webhookEvent = new WebhookEvent($payment, $shopwareOrder, $context); + $this->eventDispatcher->dispatch($webhookEvent); + + $this->updatePaymentStatus($payment, $transactionId, $orderNumber, $context); + $this->updatePaymentMethod($payment, $orderNumber, $shopwareOrder->getSalesChannelId(), $context); + $this->updateOrderStatus($payment, $shopwareOrder, $context); + $this->updateDeliveryStatus($payment, $shopwareOrder, $context); + + $webhookStatusEventClass = $payment->getStatus()->getWebhookEventClass(); + $webhookStatusEvent = new $webhookStatusEventClass($payment, $shopwareOrder, $context); + $this->eventDispatcher->dispatch($webhookStatusEvent); + $this->logger->info('Webhook Process - Finished', $logData); + + return new WebhookResponse($payment); + } + + private function updatePaymentStatus(Payment $payment, string $transactionId, string $orderNumber, Context $context): void + { + $shopwareHandlerMethod = $payment->getStatus()->getShopwareHandlerMethod(); + $logData = [ + 'transactionId' => $transactionId, + 'paymentStatus' => $payment->getStatus()->value, + 'shopwareMethod' => $shopwareHandlerMethod, + 'orderNumber' => $orderNumber, + ]; + $this->logger->info('Change payment status', $logData); + if (mb_strlen($shopwareHandlerMethod) === 0) { + $this->logger->warning('Failed to find shopware handler method for status', $logData); + + return; + } + + try { + $this->stateMachineHandler->{$shopwareHandlerMethod}($transactionId, $context); + $this->logger->info('Payment status changed', $logData); + } catch (\Throwable $exception) { + $logData['exceptionMessage'] = $exception->getMessage(); + $this->logger->error('Failed to change payment status', $logData); + throw WebhookException::paymentStatusChangeFailed($transactionId,$orderNumber,$exception); + } + } + + private function updatePaymentMethod(Payment $payment, string $orderNumber, string $salesChannelId, Context $context): void + { + $transaction = $payment->getShopwareTransaction(); + $transactionId = $transaction->getId(); + $transactionPaymentMethod = $transaction->getPaymentMethod(); + + $molliePaymentMethod = $payment->getMethod(); + if ($molliePaymentMethod === null) { + throw WebhookException::paymentWithoutMethod($transactionId, $payment->getId()); + } + if ($transactionPaymentMethod === null) { + throw WebhookException::transactionWithoutPaymentMethod($transactionId); + } + /** @var ?PaymentMethodExtension $molliePaymentMethodExtension */ + $molliePaymentMethodExtension = $transactionPaymentMethod->getExtension(Mollie::EXTENSION); + + if ($molliePaymentMethodExtension === null) { + throw WebhookException::transactionWithoutMolliePayment($transactionId); + } + $logData = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + ]; + try { + $newPaymentMethodId = $this->paymentMethodUpdater->updatePaymentMethod($molliePaymentMethodExtension,$molliePaymentMethod,$transactionId,$orderNumber,$salesChannelId,$context); + $logData['newPaymentMethodId'] = $newPaymentMethodId; + $this->logger->info('Updated payment method id for transaction', $logData); + } catch (\Throwable $exception) { + $logData['exceptionMessage'] = $exception->getMessage(); + $this->logger->error('Failed to update payment method id for transaction', $logData); + throw WebhookException::paymentMethodChangeFailed($transactionId,$orderNumber,$exception); + } + } + + private function updateOrderStatus(Payment $payment, OrderEntity $shopwareOrder, Context $context): void + { + $transaction = $payment->getShopwareTransaction(); + $transactionId = $transaction->getId(); + $paymentId = $payment->getId(); + $salesChannelId = $shopwareOrder->getSalesChannelId(); + $orderNumber = (string) $shopwareOrder->getOrderNumber(); + $paymentStatus = $payment->getStatus(); + $shopwarePaymentStatus = $paymentStatus->getShopwarePaymentStatus(); + $orderStateId = $shopwareOrder->getStateId(); + + $currentOrderState = $shopwareOrder->getStateMachineState(); + if ($currentOrderState === null) { + throw WebhookException::orderWithoutState($transactionId,$orderNumber); + } + + $currentState = $currentOrderState->getTechnicalName(); + + $logData = [ + 'transactionId' => $transactionId, + 'paymentId' => $paymentId, + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'molliePaymentStatus' => $paymentStatus->value, + 'shopwarePaymentStatus' => $shopwarePaymentStatus, + 'currentOrderStateId' => $orderStateId, + 'currentState' => $currentState, + ]; + + try { + $this->logger->info('Start - Change order status', $logData); + + $newOrderStateId = $this->orderStateHandler->performTransition($shopwareOrder,$shopwarePaymentStatus,$currentState, $salesChannelId, $context); + + $logData['newOrderStateId'] = $newOrderStateId; + + $this->logger->info('Finished - Change order status, successful', $logData); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Finished - Change order status, Failed to change order status', $logData); + throw WebhookException::orderStatusChangeFailed($transactionId, $orderNumber, $exception); + } + } + + private function updateDeliveryStatus(Payment $payment, OrderEntity $shopwareOrder, Context $context): void + { + $captured = $payment->getCapturedAmount(); + if ($captured === null || (float) $captured->getValue() <= 0.0 || $payment->getStatus() !== PaymentStatus::PAID) { + return; + } + + $deliveries = $shopwareOrder->getDeliveries(); + if ($deliveries === null) { + return; + } + $firstDelivery = $deliveries->first(); + if ($firstDelivery === null) { + return; + } + $orderDeliveryId = $firstDelivery->getId(); + + $transition = StateMachineTransitionActions::ACTION_SHIP; + + $this->orderService->orderDeliveryStateTransition( + $orderDeliveryId, + $transition, + new ParameterBag(), + $context + ); + } +} diff --git a/shopware/Component/Router/RouteBuilder.php b/shopware/Component/Router/RouteBuilder.php new file mode 100644 index 000000000..63589e815 --- /dev/null +++ b/shopware/Component/Router/RouteBuilder.php @@ -0,0 +1,95 @@ +isStoreApiRequest()) { + $routeName = 'api.mollie.payment-return'; + } + + return $this->router->generate($routeName, ['transactionId' => $transactionId], RouterInterface::ABSOLUTE_URL); + } + + public function getWebhookUrl(string $transactionId): string + { + $routeName = 'frontend.mollie.webhook'; + if ($this->isStoreApiRequest()) { + $routeName = 'api.mollie.webhook'; + } + + return $this->router->generate($routeName, ['transactionId' => $transactionId], RouterInterface::ABSOLUTE_URL); + } + + public function getSubscriptionWebhookUrl(string $subscriptionId): string + { + $routeName = 'frontend.mollie.webhook.subscription'; + if ($this->isStoreApiRequest()) { + $routeName = 'api.mollie.webhook.subscription'; + } + + return $this->router->generate($routeName, ['subscriptionId' => $subscriptionId], RouterInterface::ABSOLUTE_URL); + } + + public function getPaypalExpressRedirectUrl(): string + { + $routeName = 'frontend.mollie.paypal-express.finish'; + if ($this->isStoreApiRequest()) { + $routeName = 'astore-api.mollie.paypal-express.checkout.finish'; + } + + return $this->router->generate($routeName, [], RouterInterface::ABSOLUTE_URL); + } + + public function getPaypalExpressCancelUrl(): string + { + $routeName = 'frontend.mollie.paypal-express.cancel'; + if ($this->isStoreApiRequest()) { + $routeName = 'store-api.mollie.paypal-express.checkout.cancel'; + } + + return $this->router->generate($routeName, [], RouterInterface::ABSOLUTE_URL); + } + + public function getPosCheckoutUrl(Payment $payment,string $transactionId, string $orderNumber): string + { + $parameters = [ + 'transactionId' => $transactionId, + 'orderNumber' => $orderNumber + ]; + $changePaymentStatusUrl = $payment->getChangePaymentStateUrl(); + if (mb_strlen($changePaymentStatusUrl) > 0) { + $parameters['changePaymentStateUrl'] = $changePaymentStatusUrl; + } + + return $this->router->generate('frontend.mollie.pos.checkout', $parameters, RouterInterface::ABSOLUTE_URL); + } + + private function isStoreApiRequest(): bool + { + $request = $this->requestStack->getCurrentRequest(); + if ($request === null) { + return false; + } + + return str_starts_with($request->getPathInfo(), '/store-api'); + } +} diff --git a/shopware/Component/Router/RouteBuilderInterface.php b/shopware/Component/Router/RouteBuilderInterface.php new file mode 100644 index 000000000..465b90bec --- /dev/null +++ b/shopware/Component/Router/RouteBuilderInterface.php @@ -0,0 +1,21 @@ + - - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Component/Settings/SettingsService.php b/shopware/Component/Settings/SettingsService.php index 6c0431993..b205365e7 100644 --- a/shopware/Component/Settings/SettingsService.php +++ b/shopware/Component/Settings/SettingsService.php @@ -3,25 +3,72 @@ namespace Mollie\Shopware\Component\Settings; +use Mollie\Shopware\Component\Settings\Struct\AccountSettings; +use Mollie\Shopware\Component\Settings\Struct\ApiSettings; +use Mollie\Shopware\Component\Settings\Struct\ApplePaySettings; +use Mollie\Shopware\Component\Settings\Struct\CreditCardSettings; +use Mollie\Shopware\Component\Settings\Struct\EnvironmentSettings; use Mollie\Shopware\Component\Settings\Struct\LoggerSettings; -use Psr\Container\ContainerInterface; +use Mollie\Shopware\Component\Settings\Struct\OrderStateSettings; +use Mollie\Shopware\Component\Settings\Struct\PaymentSettings; +use Mollie\Shopware\Component\Settings\Struct\PayPalExpressSettings; +use Mollie\Shopware\Component\Settings\Struct\SubscriptionSettings; use Shopware\Core\Framework\Plugin\Exception\DecorationPatternException; use Shopware\Core\System\SystemConfig\SystemConfigService; +use Symfony\Component\DependencyInjection\Attribute\Autowire; final class SettingsService extends AbstractSettingsService { public const SYSTEM_CONFIG_DOMAIN = 'MolliePayments.config'; - private const CACHE_KEY_LOGGER = 'logger'; + private const CACHE_KEY_MOLLIE = 'mollie'; private const CACHE_KEY_SHOPWARE = 'shopware'; - private ?SystemConfigService $systemConfigService = null; - + /** + * @var array + */ private array $settingsCache = []; - private ContainerInterface $container; + private bool $devMode = false; + private bool $cypressMode = false; + private bool $paypalExpressEnabled = false; + private int $paypalExpressStyle = 1; + private int $paypalExpressShape = 1; + private string $paypalExpressRestrictions = ''; - public function __construct(ContainerInterface $container) - { - $this->container = $container; + public function __construct( + private SystemConfigService $systemConfigService, + #[Autowire(env: 'default::int:MOLLIE_DEV_MODE')] + ?int $devMode = 0, + #[Autowire(env: 'default::int:MOLLIE_CYPRESS_MODE')] + ?int $cypressMode = 0, + #[Autowire(env: 'default::int:MOLLIE_PAYPAL_EXPRESS_BETA')] + ?int $paypalExpressEnabled = 0, + #[Autowire(env: 'default::MOLLIE_PAYPAL_EXPRESS_BUTTON_STYLE')] + ?string $paypalExpressStyle = '1', + #[Autowire(env: 'default::MOLLIE_PAYPAL_EXPRESS_BUTTON_SHAPE')] + ?string $paypalExpressShape = '1', + #[Autowire(env: 'default::MOLLIE_PAYPAL_EXPRESS_BUTTON_RESTRICTIONS')] + ?string $paypalExpressRestrictions = '' + ) { + if ($devMode !== null) { + $this->devMode = (bool) $devMode; + } + + if ($cypressMode !== null) { + $this->cypressMode = (bool) $cypressMode; + } + + if ($paypalExpressEnabled !== null) { + $this->paypalExpressEnabled = (bool) $paypalExpressEnabled; + if ($paypalExpressShape !== null) { + $this->paypalExpressShape = (int) $paypalExpressShape; + } + if ($paypalExpressStyle !== null) { + $this->paypalExpressStyle = (int) $paypalExpressStyle; + } + if ($paypalExpressRestrictions !== null) { + $this->paypalExpressRestrictions = $paypalExpressRestrictions; + } + } } public function getDecorated(): AbstractSettingsService @@ -31,19 +78,179 @@ public function getDecorated(): AbstractSettingsService public function getLoggerSettings(?string $salesChannelId = null): LoggerSettings { - $cacheKey = self::CACHE_KEY_LOGGER . '_' . ($salesChannelId ?? 'all'); + $cacheKey = LoggerSettings::class . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $settings = LoggerSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getPaypalExpressSettings(?string $salesChannelId = null): PayPalExpressSettings + { + $cacheKey = PayPalExpressSettings::class . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $fallbackRestrictions = explode(' ', trim($this->paypalExpressRestrictions)); + $style = $shopwareSettings[PayPalExpressSettings::KEY_BUTTON_STYLE] ?? $this->paypalExpressStyle; + $shape = $shopwareSettings[PayPalExpressSettings::KEY_BUTTON_SHAPE] ?? $this->paypalExpressShape; + $restrictions = $shopwareSettings[PayPalExpressSettings::KEY_RESTRICTIONS] ?? $fallbackRestrictions; + $settings = new PayPalExpressSettings($this->paypalExpressEnabled); + + $settings->setStyle((int) $style); + $settings->setShape((int) $shape); + + $settings->setRestrictions($restrictions); + + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getEnvironmentSettings(): EnvironmentSettings + { + return new EnvironmentSettings($this->devMode, $this->cypressMode); + } + + public function getApiSettings(?string $salesChannelId = null): ApiSettings + { + $cacheKey = ApiSettings::class . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $settings = ApiSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getSubscriptionSettings(?string $salesChannelId = null): SubscriptionSettings + { + $cacheKey = SubscriptionSettings::class . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $settings = SubscriptionSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getPaymentSettings(?string $salesChannelId = null): PaymentSettings + { + $cacheKey = PaymentSettings::class . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $settings = PaymentSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + return $settings; + } + + public function getCreditCardSettings(?string $salesChannelId = null): CreditCardSettings + { + $cacheKey = CreditCardSettings::class . '_' . ($salesChannelId ?? 'all'); if (isset($this->settingsCache[$cacheKey])) { return $this->settingsCache[$cacheKey]; } + $shopwareSettings = $this->getMollieSettings($salesChannelId); + $settings = CreditCardSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getAccountSettings(?string $salesChannelId = null): AccountSettings + { + $cacheKey = AccountSettings::class . '_' . ($salesChannelId ?? 'all'); + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } $shopwareSettings = $this->getShopwareSettings($salesChannelId); - $loggerSettings = LoggerSettings::createFromShopwareArray($shopwareSettings); - $this->settingsCache[$cacheKey] = $loggerSettings; + $settings = AccountSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function getApplePaySettings(?string $salesChannelId = null): ApplePaySettings + { + $cacheKey = ApplePaySettings::class . '_' . ($salesChannelId ?? 'all'); + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + $shopwareSettings = $this->getMollieSettings($salesChannelId); + + $settings = ApplePaySettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; - return $loggerSettings; + return $settings; } + public function getOrderStateSettings(?string $salesChannelId = null): OrderStateSettings + { + $cacheKey = OrderStateSettings::class . '_' . ($salesChannelId ?? 'all'); + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + $shopwareSettings = $this->getMollieSettings($salesChannelId); + + $settings = OrderStateSettings::createFromShopwareArray($shopwareSettings); + $this->settingsCache[$cacheKey] = $settings; + + return $settings; + } + + public function clearCache(): void + { + $this->settingsCache = []; + } + + /** + * @throws \Psr\Container\NotFoundExceptionInterface + * @throws \Psr\Container\ContainerExceptionInterface + * + * @return array + */ + private function getMollieSettings(?string $salesChannelId = null): array + { + $cacheKey = self::CACHE_KEY_MOLLIE . '_' . ($salesChannelId ?? 'all'); + + if (isset($this->settingsCache[$cacheKey])) { + return $this->settingsCache[$cacheKey]; + } + + $shopwareSettingsArray = $this->systemConfigService->get(self::SYSTEM_CONFIG_DOMAIN, $salesChannelId); + if (! is_array($shopwareSettingsArray)) { + return []; + } + $this->settingsCache[$cacheKey] = $shopwareSettingsArray; + + return $shopwareSettingsArray; + } + + /** + * @return array + */ private function getShopwareSettings(?string $salesChannelId = null): array { $cacheKey = self::CACHE_KEY_SHOPWARE . '_' . ($salesChannelId ?? 'all'); @@ -51,13 +258,12 @@ private function getShopwareSettings(?string $salesChannelId = null): array if (isset($this->settingsCache[$cacheKey])) { return $this->settingsCache[$cacheKey]; } - /* - * Attention, we have to use service locator here, because in Shopware 6.4 there is an issue with system config service. - */ - if ($this->systemConfigService === null) { - $this->systemConfigService = $this->container->get(SystemConfigService::class); + + $shopwareSettingsArray = $this->systemConfigService->get('core', $salesChannelId); + + if (! is_array($shopwareSettingsArray)) { + return []; } - $shopwareSettingsArray = $this->systemConfigService->get(self::SYSTEM_CONFIG_DOMAIN, $salesChannelId); $this->settingsCache[$cacheKey] = $shopwareSettingsArray; return $shopwareSettingsArray; diff --git a/shopware/Component/Settings/Struct/AccountSettings.php b/shopware/Component/Settings/Struct/AccountSettings.php new file mode 100644 index 000000000..c4951e5e5 --- /dev/null +++ b/shopware/Component/Settings/Struct/AccountSettings.php @@ -0,0 +1,66 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $phoneFieldIsShown = $settings['loginRegistration']['showPhoneNumberField'] ?? false; + $phoneFieldIsRequired = $settings['loginRegistration']['phoneNumberFieldRequired'] ?? false; + + $birthdayFieldIsShown = $settings['loginRegistration']['showBirthdayField'] ?? false; + $birthdayFieldIsRequired = $settings['loginRegistration']['birthdayFieldRequired'] ?? false; + + $dataProtectionIsEnabled = $settings['loginRegistration']['requireDataProtectionCheckbox'] ?? false; + + $customerIsBoundToSalesChannel = $settings['systemWideLoginRegistration']['isCustomerBoundToSalesChannel'] ?? false; + + return new self((bool) $phoneFieldIsShown, (bool) $phoneFieldIsRequired, (bool) $birthdayFieldIsShown, (bool) $birthdayFieldIsRequired, (bool) $dataProtectionIsEnabled, (bool) $customerIsBoundToSalesChannel); + } + + public function isPhoneFieldShown(): bool + { + return $this->phoneFieldShown; + } + + public function isPhoneFieldRequired(): bool + { + return $this->phoneFieldRequired; + } + + public function isBirthdayFieldShown(): bool + { + return $this->birthdayFieldShown; + } + + public function isBirthdayFieldRequired(): bool + { + return $this->birthdayFieldRequired; + } + + public function isDataProtectionEnabled(): bool + { + return $this->dataProtectionEnabled; + } + + public function isCustomerBoundToSalesChannel(): bool + { + return $this->customerBoundToSalesChannel; + } +} diff --git a/shopware/Component/Settings/Struct/ApiSettings.php b/shopware/Component/Settings/Struct/ApiSettings.php new file mode 100644 index 000000000..0cbc9d4c7 --- /dev/null +++ b/shopware/Component/Settings/Struct/ApiSettings.php @@ -0,0 +1,69 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $testApiKey = $settings[self::KEY_TEST_API_KEY] ?? ''; + $liveApiKey = $settings[self::KEY_LIVE_API_KEY] ?? ''; + $profileId = $settings[self::KEY_PROFILE_ID] ?? ''; + $testMode = $settings[self::KEY_TEST_MODE] ?? 'true'; + + $mode = (bool) $testMode === true ? Mode::TEST : Mode::LIVE; + + return new self($testApiKey, $liveApiKey, $mode,$profileId); + } + + public function getTestApiKey(): string + { + return $this->testApiKey; + } + + public function getLiveApiKey(): string + { + return $this->liveApiKey; + } + + public function isTestMode(): bool + { + return $this->mode === Mode::TEST; + } + + public function getApiKey(): string + { + if ($this->isTestMode()) { + return $this->testApiKey; + } + + return $this->liveApiKey; + } + + public function getProfileId(): string + { + return $this->profileId; + } + + public function getMode(): Mode + { + return $this->mode; + } +} diff --git a/shopware/Component/Settings/Struct/ApplePaySettings.php b/shopware/Component/Settings/Struct/ApplePaySettings.php new file mode 100644 index 000000000..7fe76b98d --- /dev/null +++ b/shopware/Component/Settings/Struct/ApplePaySettings.php @@ -0,0 +1,58 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $applePayDirectEnabled = $settings[self::KEY_APPLE_PAY_DIRECT_ENABLED] ?? false; + $visibilityRestrictionsArray = $settings[self::KEY_RESTRICTIONS] ?? []; + $visibilityRestrictions = new VisibilityRestrictionCollection(); + foreach ($visibilityRestrictionsArray as $visibilityRestriction) { + $visibilityRestrictions->add(VisibilityRestriction::from($visibilityRestriction)); + } + $allowedDomainList = $settings[self::KEY_ALLOWED_DOMAIN_LIST] ?? ''; + $allowedDomainListArray = explode(',', $allowedDomainList); + + return new self($applePayDirectEnabled,$visibilityRestrictions,$allowedDomainListArray); + } + + public function isApplePayDirectEnabled(): bool + { + return $this->applePayDirectEnabled; + } + + public function getVisibilityRestrictions(): VisibilityRestrictionCollection + { + return $this->visibilityRestrictions; + } + + /** + * @return string[] + */ + public function getAllowDomainList(): array + { + return $this->allowDomainList; + } +} diff --git a/shopware/Component/Settings/Struct/CreditCardSettings.php b/shopware/Component/Settings/Struct/CreditCardSettings.php new file mode 100644 index 000000000..12abdfd96 --- /dev/null +++ b/shopware/Component/Settings/Struct/CreditCardSettings.php @@ -0,0 +1,28 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $creditCardComponents = $settings[self::KEY_CREDIT_CARD_COMPONENTS] ?? false; + + return new self((bool) $creditCardComponents); + } + + public function isCreditCardComponentsEnabled(): bool + { + return $this->creditCardComponentsEnabled; + } +} diff --git a/shopware/Component/Settings/Struct/EnvironmentSettings.php b/shopware/Component/Settings/Struct/EnvironmentSettings.php new file mode 100644 index 000000000..8be741a18 --- /dev/null +++ b/shopware/Component/Settings/Struct/EnvironmentSettings.php @@ -0,0 +1,21 @@ +devMode; + } + + public function isCypressMode(): bool + { + return $this->cypressMode; + } +} diff --git a/shopware/Component/Settings/Struct/LoggerSettings.php b/shopware/Component/Settings/Struct/LoggerSettings.php index 0f6f0d20f..ed53ec4ae 100644 --- a/shopware/Component/Settings/Struct/LoggerSettings.php +++ b/shopware/Component/Settings/Struct/LoggerSettings.php @@ -9,21 +9,20 @@ final class LoggerSettings extends Struct { public const KEY_LOG_FILE_DAYS = 'logFileDays'; public const KEY_DEBUG_MODE = 'debugMode'; - private bool $isDebugMode; - private int $logFileDays; - public function __construct(bool $isDebugMode, int $logFileDays) + public function __construct(private bool $isDebugMode, private int $logFileDays) { - $this->isDebugMode = $isDebugMode; - $this->logFileDays = $logFileDays; } - public static function createFromShopwareArray(array $settings): LoggerSettings + /** + * @param array $settings + */ + public static function createFromShopwareArray(array $settings): self { $logFileDays = $settings[self::KEY_LOG_FILE_DAYS] ?? 0; $debugMode = $settings[self::KEY_DEBUG_MODE] ?? false; - return new LoggerSettings((bool) $debugMode, (int) $logFileDays); + return new self((bool) $debugMode, (int) $logFileDays); } public function isDebugMode(): bool diff --git a/shopware/Component/Settings/Struct/OrderStateSettings.php b/shopware/Component/Settings/Struct/OrderStateSettings.php new file mode 100644 index 000000000..1f042188f --- /dev/null +++ b/shopware/Component/Settings/Struct/OrderStateSettings.php @@ -0,0 +1,70 @@ + $stateMapping + */ + public function __construct( + private array $stateMapping = [], + private ?string $finalOrderState = null, + ) { + } + + /** + * @param array $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $paidOrderState = $settings[self::KEY_STATE_PAID] ?? self::SKIP_STATE; + $failedOrderState = $settings[self::KEY_STATE_FAILED] ?? self::SKIP_STATE; + $cancelledOrderState = $settings[self::KEY_STATE_CANCELLED] ?? self::SKIP_STATE; + $authorizedOrderState = $settings[self::KEY_STATE_AUTHORIZED] ?? self::SKIP_STATE; + $chargeBackOrderState = $settings[self::KEY_STATE_CHARGE_BACK] ?? self::SKIP_STATE; + $refundOrderState = $settings[self::KEY_STATE_REFUND] ?? self::SKIP_STATE; + $partialRefundOrderState = $settings[self::KEY_STATE_PARTIAL_REFUND] ?? self::SKIP_STATE; + $finalOrderState = $settings[self::KEY_STATE_FINAL] ?? null; + + $stateMapping = [ + OrderTransactionStates::STATE_PAID => $paidOrderState, + OrderTransactionStates::STATE_FAILED => $failedOrderState, + OrderTransactionStates::STATE_CANCELLED => $cancelledOrderState, + OrderTransactionStates::STATE_AUTHORIZED => $authorizedOrderState, + OrderTransactionStates::STATE_CHARGEBACK => $chargeBackOrderState, + OrderTransactionStates::STATE_REFUNDED => $refundOrderState, + OrderTransactionStates::STATE_PARTIALLY_REFUNDED => $partialRefundOrderState, + ]; + + return new self($stateMapping, $finalOrderState); + } + + public function getFinalOrderState(): ?string + { + return $this->finalOrderState; + } + + public function getStatus(string $shopwarePaymentStatus): ?string + { + $status = $this->stateMapping[$shopwarePaymentStatus] ?? self::SKIP_STATE; + if ($status === self::SKIP_STATE) { + return null; + } + + return $status; + } +} diff --git a/shopware/Component/Settings/Struct/PayPalExpressSettings.php b/shopware/Component/Settings/Struct/PayPalExpressSettings.php new file mode 100644 index 000000000..6250aab2d --- /dev/null +++ b/shopware/Component/Settings/Struct/PayPalExpressSettings.php @@ -0,0 +1,70 @@ + + */ + private array $restrictions = []; + + public function __construct(private bool $enabled) + { + } + + public function getEnabled(): bool + { + return $this->enabled; + } + + public function getShape(): int + { + return $this->shape; + } + + public function setShape(int $shape): void + { + $this->shape = $shape; + } + + public function getStyle(): int + { + return $this->style; + } + + public function setStyle(int $style): void + { + $this->style = $style; + } + + /** + * @return string[] + */ + public function getRestrictions(): array + { + return $this->restrictions; + } + + /** + * @param array $restrictions + */ + public function setRestrictions(array $restrictions): void + { + $this->restrictions = $restrictions; + } + + public function isEnabled(): bool + { + return $this->enabled === true; + } +} diff --git a/shopware/Component/Settings/Struct/PaymentSettings.php b/shopware/Component/Settings/Struct/PaymentSettings.php new file mode 100644 index 000000000..d217a0a53 --- /dev/null +++ b/shopware/Component/Settings/Struct/PaymentSettings.php @@ -0,0 +1,94 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $orderNumberFormat = $settings[self::KEY_ORDER_NUMBER_FORMAT] ?? ''; + $dueDateDays = $settings[self::KEY_DUE_DATE_DAYS] ?? 0; + $oneClickPayment = $settings[self::KEY_ONE_CLICK_PAYMENT] ?? false; + $oneClickCompactView = $settings[self::KEY_ONE_CLICK_COMPACT_VIEW] ?? false; + $shopwareFailedPayment = $settings[self::KEY_SHOPWARE_FAILED_PAYMENT] ?? false; + $createCustomersAtMollie = $settings[self::KEY_CREATE_CUSTOMERS_AT_MOLLIE] ?? false; + $useMollieLimits = $settings[self::KEY_USE_MOLLIE_LIMITS] ?? false; + $automaticShipment = $settings[self::KEY_AUTOMATIC_SHIPMENT] ?? false; + + return new self($orderNumberFormat, $dueDateDays,(bool) $oneClickPayment,(bool) $oneClickCompactView,(bool) $shopwareFailedPayment,(bool) $createCustomersAtMollie,(bool) $useMollieLimits, (bool) $automaticShipment); + } + + public function getOrderNumberFormat(): string + { + return $this->orderNumberFormat; + } + + public function isShopwareFailedPayment(): bool + { + return $this->shopwareFailedPayment; + } + + public function getDueDateDays(): int + { + if ($this->dueDateDays === 0) { + return $this->dueDateDays; + } + + return max(min($this->dueDateDays, self::MAX_DUE_DAYS), self::MIN_DUE_DAYS); + } + + public function isOneClickPayment(): bool + { + return $this->oneClickPayment; + } + + public function isOneClickCompactView(): bool + { + return $this->oneClickCompactView; + } + + public function forceCustomerCreation(): bool + { + return $this->createCustomersAtMollie; + } + + public function useMollieLimits(): bool + { + return $this->useMollieLimits; + } + + public function isAutomaticShipment(): bool + { + return $this->automaticShipment; + } +} diff --git a/shopware/Component/Settings/Struct/SubscriptionSettings.php b/shopware/Component/Settings/Struct/SubscriptionSettings.php new file mode 100644 index 000000000..07faec7c3 --- /dev/null +++ b/shopware/Component/Settings/Struct/SubscriptionSettings.php @@ -0,0 +1,94 @@ + $settings + */ + public static function createFromShopwareArray(array $settings): self + { + $enabled = $settings[self::KEY_ENABLED] ?? false; + $showIndicator = $settings[self::KEY_SHOW_INDICATOR] ?? false; + $allowEditAddress = $settings[self::KEY_ALLOW_EDIT_ADDRESS] ?? false; + $allowPauseAndResume = $settings[self::KEY_ALLOW_PAUSE_RESUME] ?? false; + $allowSkip = $settings[self::KEY_ALLOW_SKIP] ?? false; + $skipIfFailed = $settings[self::KEY_SKIP_IF_FAILED] ?? false; + $reminderDays = $settings[self::KEY_REMINDER_DAYS] ?? 0; + $cancelDays = $settings[self::KEY_CANCEL_DAYS] ?? 0; + + return new self((bool) $enabled, + (bool) $showIndicator, + (bool) $allowEditAddress, + (bool) $allowPauseAndResume, + (bool) $allowSkip, + (bool) $skipIfFailed, + (int) $reminderDays, + (int) $cancelDays + ); + } + + public function isEnabled(): bool + { + return $this->enabled; + } + + public function isShowIndicator(): bool + { + return $this->showIndicator; + } + + public function isAllowEditAddress(): bool + { + return $this->allowEditAddress; + } + + public function isAllowPauseAndResume(): bool + { + return $this->allowPauseAndResume; + } + + public function isAllowSkip(): bool + { + return $this->allowSkip; + } + + public function isSkipIfFailed(): bool + { + return $this->skipIfFailed; + } + + public function getReminderDays(): int + { + return $this->reminderDays; + } + + public function getCancelDays(): int + { + return $this->cancelDays; + } +} diff --git a/shopware/Component/Settings/SystemConfigSubscriber.php b/shopware/Component/Settings/SystemConfigSubscriber.php new file mode 100644 index 000000000..ec681dfd3 --- /dev/null +++ b/shopware/Component/Settings/SystemConfigSubscriber.php @@ -0,0 +1,71 @@ + 'updateProfileId', + ]; + } + + public function updateProfileId(SystemConfigMultipleChangedEvent $event): void + { + $config = $event->getConfig(); + if (! $this->hasNeededConfig($config)) { + return; + } + $salesChannelId = $event->getSalesChannelId(); + $profileId = null; + try { + $profile = $this->mollieGateway->getCurrentProfile($salesChannelId); + + $this->logger->info('Mollie API Config was changed, a new Profile ID was set', [ + 'profileId' => $profileId, + 'salesChannelId' => $salesChannelId, + ]); + $this->systemConfigService->set(self::KEY_PROFILE_ID, $profile->getId(), $salesChannelId); + } catch (\Throwable $exception) { + $this->logger->warning('Mollie API Config was changed, profile ID was deleted', [ + 'salesChannelId' => $salesChannelId, + 'message' => $exception->getMessage(), + ]); + $this->systemConfigService->set(self::KEY_PROFILE_ID, null, $salesChannelId); + } + } + + /** + * @param array|bool|float|int|string> $config + */ + private function hasNeededConfig(array $config): bool + { + $testModeConfigKey = SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_MODE; + $liveApiConfigKey = SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_LIVE_API_KEY; + $testApiConfigKey = SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_API_KEY; + + return isset($config[$testModeConfigKey]) || isset($config[$liveApiConfigKey]) || isset($config[$testApiConfigKey]); + } +} diff --git a/shopware/Component/Shipment/OrderDeliverySubscriber.php b/shopware/Component/Shipment/OrderDeliverySubscriber.php new file mode 100644 index 000000000..226b204a3 --- /dev/null +++ b/shopware/Component/Shipment/OrderDeliverySubscriber.php @@ -0,0 +1,198 @@ + $orderDeliveryRepository + * @param EntityRepository $orderLineRepository + */ + public function __construct( + #[Autowire(service: 'order_delivery.repository')] + private readonly EntityRepository $orderDeliveryRepository, + #[Autowire(service: MollieGateway::class)] + private readonly MollieGatewayInterface $mollieGateway, + #[Autowire(service: SettingsService::class)] + private readonly AbstractSettingsService $settingsService, + #[Autowire(service: 'order_line_item.repository')] + private readonly EntityRepository $orderLineRepository, + #[Autowire(service: 'event_dispatcher')] + private EventDispatcherInterface $eventDispatcher, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger, + ) { + } + + public static function getSubscribedEvents(): array + { + return [ + 'state_machine.order_delivery.state_changed' => 'onOrderDeliveryChanged', + ]; + } + + public function onOrderDeliveryChanged(StateMachineStateChangeEvent $event): void + { + if ($event->getTransitionSide() !== StateMachineStateChangeEvent::STATE_MACHINE_TRANSITION_SIDE_ENTER) { + return; + } + + $transitionName = $event->getTransition()->getTransitionName(); + if ($transitionName !== StateMachineTransitionActions::ACTION_SHIP) { + return; + } + // dump($event->getPreviousState()->getTechnicalName()); + $transition = $event->getTransition(); + $context = $event->getContext(); + + $orderDeliveryId = $transition->getEntityId(); + + $criteria = new Criteria([$orderDeliveryId]); + $criteria->addAssociation('order.currency'); + $criteria->addAssociation('order.transactions'); + $criteria->addAssociation('order.lineItems'); + $criteria->getAssociation('order.transactions')->addSorting(new FieldSorting('updatedAt', FieldSorting::DESCENDING)); + + $searchResult = $this->orderDeliveryRepository->search($criteria, $context); + $orderDelivery = $searchResult->first(); + + if (! $orderDelivery instanceof OrderDeliveryEntity) { + $this->logger->error('Delivery not found for ' . $orderDeliveryId); + + return; + } + + $order = $orderDelivery->getOrder(); + if ($order === null) { + $this->logger->error('Order association missing for delivery ' . $orderDeliveryId); + + return; + } + + $orderNumber = $order->getOrderNumber(); + + if ($orderNumber === null) { + $this->logger->error('Order number missing for order of delivery ' . $orderDeliveryId); + + return; + } + + $salesChannelId = $order->getSalesChannelId(); + $paymentSettings = $this->settingsService->getPaymentSettings($salesChannelId); + if (! $paymentSettings->isAutomaticShipment()) { + return; + } + + $transactions = $order->getTransactions(); + if ($transactions === null || $transactions->count() === 0) { + $this->logger->debug('No transactions found for order ' . $orderNumber, [ + 'orderDeliveryId' => $orderDeliveryId, + 'salesChannelId' => $salesChannelId, + ]); + + return; + } + + $firstTransaction = $transactions->first(); + if ($firstTransaction === null) { + $this->logger->debug('No first transaction found for order ' . $orderNumber, [ + 'orderDeliveryId' => $orderDeliveryId, + 'salesChannelId' => $salesChannelId, + ]); + + return; + } + $payment = $firstTransaction->getExtension(Mollie::EXTENSION); + $transactionId = $firstTransaction->getId(); + + $logData = [ + 'orderNumber' => $orderNumber, + 'orderDeliveryId' => $orderDeliveryId, + 'transactionId' => $transactionId, + 'salesChannelId' => $salesChannelId, + ]; + + if (! $payment instanceof Payment) { + $this->logger->debug('Transaction was not paid with Mollie', $logData); + + return; + } + $paymentId = $payment->getId(); + + $currency = $order->getCurrency(); + if ($currency === null) { + $this->logger->error('Currency association missing for order ' . $orderNumber, $logData); + + return; + } + + $money = Money::fromOrder($order, $currency); + + $payment = $this->mollieGateway->getPayment($paymentId, $orderNumber, $salesChannelId); + + $alreadyCaptured = $payment->getCapturedAmount(); + + $orderShippedEvent = new OrderShippedEvent($transactionId, $context); + + if ($alreadyCaptured instanceof Money && $alreadyCaptured->getValue() >= $money->getValue()) { + $this->logger->warning('Order already shipped', $logData); + $this->eventDispatcher->dispatch($orderShippedEvent); + + return; + } + + // throw new \Exception('stop here'); + + $createCapture = new CreateCapture($money, 'automaticShipment'); + + $capture = $this->mollieGateway->createCapture($createCapture, $paymentId, $orderNumber, $salesChannelId); + + $upsertArray = []; + $lineItems = $order->getLineItems() ?? new OrderLineItemCollection(); + + /** @var OrderLineItemEntity $lineItem */ + foreach ($lineItems as $lineItem) { + $upsertArray[] = [ + 'id' => $lineItem->getId(), + 'customFields' => [ + Mollie::EXTENSION => [ + 'captureId' => $capture->getId(), + 'quantity' => $lineItem->getQuantity() + ] + ] + ]; + } + + if ($upsertArray !== []) { + $this->orderLineRepository->upsert($upsertArray, $context); + } + + $this->eventDispatcher->dispatch($orderShippedEvent); + + $this->logger->info('Order Shipped', $logData); + } +} diff --git a/shopware/Component/Shipment/OrderShippedEvent.php b/shopware/Component/Shipment/OrderShippedEvent.php new file mode 100644 index 000000000..e07b0e6a6 --- /dev/null +++ b/shopware/Component/Shipment/OrderShippedEvent.php @@ -0,0 +1,23 @@ +transactionId; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/shopware/Component/Shipment/Route/AbstractShipOrderRoute.php b/shopware/Component/Shipment/Route/AbstractShipOrderRoute.php new file mode 100644 index 000000000..446c69b7e --- /dev/null +++ b/shopware/Component/Shipment/Route/AbstractShipOrderRoute.php @@ -0,0 +1,14 @@ + + */ +final class ShipOrderResponse extends StoreApiResponse +{ + /** + * @param array[] $updatedLineItems + */ + public function __construct(string $captureId, string $orderId, array $updatedLineItems = []) + { + parent::__construct(new ArrayStruct( + [ + 'status' => 'success', + 'orderId' => $orderId, + 'captureId' => $captureId, + 'updatedLineItems' => $updatedLineItems, + ], + 'mollie_ship_order_response' + )); + } +} diff --git a/shopware/Component/Shipment/Route/ShipOrderRoute.php b/shopware/Component/Shipment/Route/ShipOrderRoute.php new file mode 100644 index 000000000..13c7353a7 --- /dev/null +++ b/shopware/Component/Shipment/Route/ShipOrderRoute.php @@ -0,0 +1,296 @@ + ['api'], 'auth_required' => false, 'auth_enabled' => false])] +final class ShipOrderRoute extends AbstractShipOrderRoute +{ + /** + * @param EntityRepository $orderRepository + * @param EntityRepository $orderLineRepository + * @param EntityRepository $orderDeliveryRepository + */ + public function __construct( + #[Autowire(service: 'order.repository')] + private readonly EntityRepository $orderRepository, + #[Autowire(service: 'order_line_item.repository')] + private readonly EntityRepository $orderLineRepository, + #[Autowire(service: 'order_delivery.repository')] + private readonly EntityRepository $orderDeliveryRepository, + #[Autowire(service: MollieGateway::class)] + private readonly MollieGatewayInterface $mollieGateway, + #[Autowire(service: 'event_dispatcher')] + private EventDispatcherInterface $eventDispatcher, + private readonly OrderService $orderService, + ) { + } + + public function getDecorated(): self + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/api/_action/mollie/ship', name: 'api.action.mollie.ship.order', methods: ['POST', 'GET'])] + public function ship(Request $request, Context $context): ShipOrderResponse + { + $orderId = (string) $request->get('orderId'); + $orderId = strtolower($orderId); + + $items = $request->get('items'); + if (count($items) === 0) { + throw ShippingException::noLineItems($orderId); + } + + $criteria = new Criteria([$orderId]); + $criteria->addAssociation('lineItems.product'); + $criteria->addAssociation('transactions'); + $criteria->addAssociation('currency'); + $criteria->addAssociation('deliveries.positions'); + $criteria->addAssociation('deliveries.shippingMethod'); + + $order = $this->orderRepository->search($criteria, $context)->first(); + + if (! $order instanceof OrderEntity) { + throw ShippingException::orderNotFound($orderId); + } + + $orderNumber = $order->getOrderNumber(); + $salesChannelId = $order->getSalesChannelId(); + if ($orderNumber === null) { + throw ShippingException::orderNotFound($orderId); + } + $transactions = $order->getTransactions(); + if ($transactions === null || $transactions->count() === 0) { + throw ShippingException::orderNotFound($orderId); + } + $firstTransaction = $transactions->first(); + if ($firstTransaction === null) { + throw ShippingException::orderNotFound($orderId); + } + $payment = $firstTransaction->getExtension(Mollie::EXTENSION); + if (! $payment instanceof Payment) { + throw ShippingException::orderNotFound($orderId); + } + $deliveryCollection = $order->getDeliveries() ?? new OrderDeliveryCollection(); + $paymentId = $payment->getId(); + $lineItems = $order->getLineItems() ?? new OrderLineItemCollection(); + $currency = $order->getCurrency(); + if ($currency === null) { + throw ShippingException::orderNotFound($orderId); + } + + $orderShippedEvent = new OrderShippedEvent($firstTransaction->getId(), $context); + + $createCapture = new CreateCapture(new Money(0.0, $currency->getIsoCode()), ''); + + $lineUpserts = $this->getLineItems($items, $lineItems, $orderId, $createCapture); + + $deliveryUpserts = $this->getDeliveries($lineUpserts, $createCapture, $deliveryCollection); + + $capture = $this->mollieGateway->createCapture($createCapture, $paymentId, (string) $orderNumber, $salesChannelId); + + foreach ($lineUpserts as $i => $row) { + $lineUpserts[$i]['customFields'][Mollie::EXTENSION]['captureId'] = $capture->getId(); + } + + $this->orderLineRepository->upsert($lineUpserts, $context); + + $deliveryIds = array_column($deliveryUpserts, 'id'); + $deliveryId = $deliveryIds[0] ?? null; + + if (\count($deliveryUpserts) > 0) { + foreach ($deliveryUpserts as $i => $row) { + $deliveryUpserts[$i]['customFields'][Mollie::EXTENSION]['captureId'] = $capture->getId(); + } + + $this->orderDeliveryRepository->upsert($deliveryUpserts, $context); + } + + if ($deliveryId !== null) { + $transition = StateMachineTransitionActions::ACTION_SHIP_PARTIALLY; + + $this->orderService->orderDeliveryStateTransition( + $deliveryId, + $transition, + new ParameterBag(), + $context + ); + } + + $this->eventDispatcher->dispatch($orderShippedEvent); + + return new ShipOrderResponse($capture->getId(), $orderId, $lineUpserts); + } + + /** + * Resolve an incoming identifier that can be either a real order line item ID or a product number. + */ + private function findLineItem(OrderLineItemCollection $lineItems, string $idOrProductNumber): ?OrderLineItemEntity + { + // Try direct ID match first + $direct = $lineItems->get(strtolower($idOrProductNumber)); + if ($direct instanceof OrderLineItemEntity) { + return $direct; + } + + return $lineItems->firstWhere(function (OrderLineItemEntity $product) use ($idOrProductNumber) { + return $product->getProduct()?->getProductNumber() === $idOrProductNumber; + }); + } + + /** + * @param list $items + * + * @return list}> + */ + private function getLineItems(array $items, OrderLineItemCollection $lineItems, string $orderId, CreateCapture $createCapture): array + { + $captureAmount = (float) $createCapture->getMoney()->getValue(); + $descriptionArray = []; + $lineUpserts = []; + foreach ($items as $item) { + $rawId = (string) $item['id']; + $requestedQuantity = (int) $item['quantity']; + + $lineItem = $this->findLineItem($lineItems, $rawId); + + if (! $lineItem instanceof OrderLineItemEntity) { + throw ShippingException::lineItemNotFound(strtolower($rawId), $orderId); + } + + $oldCaptures = $lineItem->getCustomFields()[Mollie::EXTENSION] ?? [ + 'quantity' => 0 + ]; + + $product = $lineItem->getProduct(); + $name = $product !== null ? (string) $product->getName() : (string) $lineItem->getLabel(); + $descriptionArray[] = $requestedQuantity . 'x ' . $name; + + $quantity = (int) ($oldCaptures['quantity'] ?? 0); + + if ($lineItem->getQuantity() === $quantity) { + throw ShippingException::lineItemAlreadyShipped($lineItem->getId(), $orderId); + } + + $newQuantity = $quantity + $requestedQuantity; + + if ($newQuantity > $lineItem->getQuantity()) { + throw ShippingException::shippingQuantityTooHigh($lineItem->getId(), $orderId, $newQuantity, $lineItem->getQuantity()); // message anpassen + } + + $captureAmount += $lineItem->getUnitPrice() * $requestedQuantity; + $lineUpserts[] = [ + 'id' => $lineItem->getId(), + 'customFields' => [ + Mollie::EXTENSION => [ + 'quantity' => $newQuantity + ], + ], + ]; + } + + $createCapture->setDescription(implode(', ', $descriptionArray)); + $createCapture->setMoney(new Money($captureAmount, $createCapture->getMoney()->getCurrency())); + + return $lineUpserts; + } + + /** + * @param list}> $lineUpserts + * + * @return list}> + */ + private function getDeliveries(array $lineUpserts, CreateCapture $createCapture, OrderDeliveryCollection $deliveryCollection): array + { + $descriptionArray = []; + $deliveryUpserts = []; + $targetLineItemIds = array_column($lineUpserts, 'id'); + + $captureAmount = (float) $createCapture->getMoney()->getValue(); + foreach ($deliveryCollection as $delivery) { + $shippingCosts = $delivery->getShippingCosts(); + $shippingMethod = $delivery->getShippingMethod(); + $shippingCostsQuantity = $shippingCosts->getQuantity(); + $positions = $delivery->getPositions(); + if ($positions === null) { + continue; + } + + $oldDeliveries = $delivery->getCustomFields()[Mollie::EXTENSION] ?? [ + 'quantity' => 0 + ]; + + $oldShippingCostsQuantity = (int) ($oldDeliveries['quantity'] ?? 0); + + if ($shippingCostsQuantity === $oldShippingCostsQuantity) { + continue; + } + + $deliveryBelongsToItems = false; + + // A delivery belongs to our shipment if at least one of its positions references one of the resolved line item IDs + foreach ($positions as $position) { + $posLineItemId = $position->getOrderLineItemId(); + if (in_array($posLineItemId, $targetLineItemIds, true)) { + $deliveryBelongsToItems = true; + break; + } + } + + if ($deliveryBelongsToItems === false) { + continue; + } + + if ($shippingMethod === null) { + continue; + } + + $captureAmount += ($shippingCosts->getUnitPrice() * $shippingCosts->getQuantity()); + $descriptionArray[] = $shippingCosts->getQuantity() . 'x ' . $shippingMethod->getName(); + + $deliveryId = $delivery->getId(); + + $deliveryUpserts[] = [ + 'id' => $deliveryId, + 'customFields' => [ + Mollie::EXTENSION => [ + 'quantity' => $shippingCosts->getQuantity() + ], + ], + ]; + } + + $createCapture->setDescription(implode(', ', $descriptionArray)); + $createCapture->setMoney(new Money($captureAmount, $createCapture->getMoney()->getCurrency())); + + return $deliveryUpserts; + } +} diff --git a/shopware/Component/Shipment/Route/ShippingException.php b/shopware/Component/Shipment/Route/ShippingException.php new file mode 100644 index 000000000..4bca02bf2 --- /dev/null +++ b/shopware/Component/Shipment/Route/ShippingException.php @@ -0,0 +1,89 @@ + $orderId, + ] + ); + } + + public static function lineItemNotFound(string $oldCaptureId, string $orderId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::LINE_ITEM_NOT_FOUND, + 'LineItem with oldCaptureId {{oldCaptureId}} in order {{orderId}} not found',[ + 'oldCaptureId' => $oldCaptureId, + 'orderId' => $orderId, + ] + ); + } + + public static function lineItemAlreadyShipped(string $lineItemId, string $orderId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::LINE_ITEM_ALREADY_SHIPPED, + 'LineItem {{lineItemId}} already shipped in order {{orderId}}',[ + 'lineItemId' => $lineItemId, + 'orderId' => $orderId, + ] + ); + } + + public static function shippingQuantityTooHigh(string $lineItemId, string $orderId, int $newQuantity, int $quantity): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::SHIPPING_QUANTITY_TOO_HIGH, + 'New Quantity {{newQuantity}} from lineItem {{lineItemId}} is higher than Shipping Quantity {{quantity}} {{orderId}} not found',[ + 'lineItemId' => $lineItemId, + 'orderId' => $orderId, + 'newQuantity' => $newQuantity, + 'quantity' => $quantity + ] + ); + } + + public static function shippingCostsAlreadyCalculated(string $deliveryId, string $orderId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::SHIPPING_COSTS_ALREADY_CALCULATED, + 'Delivery {{deliveryId}} already calculated all Shipping Costs for Order {{orderId}}',[ + 'lineItemId' => $deliveryId, + 'orderId' => $orderId, + ] + ); + } + + public static function noLineItems(string $orderId): self + { + return new self( + Response::HTTP_BAD_REQUEST, + self::NO_LINE_ITEMS, + 'No Line Items for Order {{orderId}}',[ + 'orderId' => $orderId, + ] + ); + } +} diff --git a/shopware/Component/StateHandler/OrderStateHandler.php b/shopware/Component/StateHandler/OrderStateHandler.php new file mode 100644 index 000000000..a651e1363 --- /dev/null +++ b/shopware/Component/StateHandler/OrderStateHandler.php @@ -0,0 +1,181 @@ +> $stateMachineRepository + */ + public function __construct( + #[Autowire(service: 'state_machine_transition.repository')] + private EntityRepository $stateMachineRepository, + private StateMachineRegistry $stateMachineRegistry, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + } + + public function performTransition(OrderEntity $shopwareOrder, string $shopwarePaymentStatus, string $currentState, string $salesChannelId, Context $context): string + { + $orderNumber = $shopwareOrder->getOrderNumber(); + $salesChannelId = $shopwareOrder->getSalesChannelId(); + $orderId = $shopwareOrder->getId(); + $currentOrderStateId = $shopwareOrder->getStateId(); + + $orderStateSettings = $this->settingsService->getOrderStateSettings($salesChannelId); + $finalOrderStateId = (string) $orderStateSettings->getFinalOrderState(); + + $logData = [ + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'orderId' => $orderId, + 'currentOrderStateId' => $currentOrderStateId, + 'currentState' => $currentState, + 'finalOrderStateId' => $finalOrderStateId, + ]; + + if ($finalOrderStateId === $currentOrderStateId) { + $this->logger->debug('Order is in final state, changing skipped', $logData); + + return $currentOrderStateId; + } + + $targetState = $orderStateSettings->getStatus($shopwarePaymentStatus); + + if ($targetState === null) { + $this->logger->debug('Target order status is not configured for shopware payment status', $logData); + + return $currentOrderStateId; + } + + $logData['targetState'] = $targetState; + + if ($targetState === $currentState) { + $this->logger->debug('Order is already in current status', $logData); + + return $currentOrderStateId; + } + + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('stateMachine.technicalName', OrderStates::STATE_MACHINE)); + $criteria->addAssociation('stateMachine'); + $criteria->addAssociation('toStateMachineState'); + $criteria->addAssociation('fromStateMachineState'); + + $searchResult = $this->stateMachineRepository->search($criteria, $context); + /** @var StateMachineTransitionCollection $transitionList */ + $transitionList = $searchResult->getEntities(); + + $movedToTransactionId = ''; + $transitionActions = $this->loadTransitionActions($transitionList, $currentState, $targetState); + + if (count($transitionActions) === 0) { + $this->logger->error('Failed to find a way to move the order transaction, please check your state machine state', $logData); + $message = sprintf('Could not find a way to move the order status from %s to status %s', $currentState, $targetState); + throw new \RuntimeException($message); + } + + foreach ($transitionActions as $action) { + $this->logger->debug(sprintf("Use action '%s' to move order state", $action), $logData); + $result = $this->stateMachineRegistry->transition(new Transition( + OrderDefinition::ENTITY_NAME, + $orderId, + $action, + 'stateId' + ), $context); + /** @var StateMachineStateEntity $movedToTransaction */ + $movedToTransaction = $result->get('toPlace'); + $movedToTransactionId = $movedToTransaction->getId(); + } + + return $movedToTransactionId; + } + + private function getAllowedTransitions(StateMachineTransitionCollection $transitions, string $currentState): StateMachineTransitionCollection + { + $result = new StateMachineTransitionCollection(); + foreach ($transitions as $transition) { + $fromState = $transition->getFromStateMachineState(); + if ($fromState === null) { + continue; + } + if ($fromState->getTechnicalName() === $currentState) { + $result->add($transition); + } + } + + return $result; + } + + /** + * @return string[] + */ + private function loadTransitionActions(StateMachineTransitionCollection $transitions, string $currentState, string $targetState): array + { + $result = []; + $allowedTransitions = $this->getAllowedTransitions($transitions, $currentState); + // If there is only one allowed actions, then we execute that action + if ($allowedTransitions->count() === 1) { + $firstTransition = $allowedTransitions->first(); + if ($firstTransition instanceof StateMachineTransitionEntity) { + $result[] = $firstTransition->getActionName(); + $toState = $firstTransition->getToStateMachineState(); + if ($toState instanceof StateMachineStateEntity) { + $currentState = $toState->getTechnicalName(); + if ($currentState === $targetState) { + return $result; + } + } + } + } + // If there are more than one way, then we look at the target state and try to find a way how to reach the target state + // imagine like a maze, you know where the target is, you trace your way back from target to start + $reverseResults = []; + /** @var StateMachineTransitionEntity $transition */ + foreach ($transitions as $transition) { + $toState = $transition->getToStateMachineState(); + if ($toState === null) { + continue; + } + if ($toState->getTechnicalName() !== $targetState) { + continue; + } + + $fromState = $transition->getFromStateMachineState(); + if ($fromState === null) { + continue; + } + $reverseResults[] = $transition->getActionName(); + + if ($fromState->getTechnicalName() === $currentState) { + return array_merge($result, array_reverse($reverseResults)); + } + $subResult = $this->loadTransitionActions($transitions, $currentState, $fromState->getTechnicalName()); + + $reverseResults = array_merge($reverseResults, $subResult); + } + + return array_merge($result, array_reverse($reverseResults)); + } +} diff --git a/shopware/Component/StateHandler/OrderStateHandlerInterface.php b/shopware/Component/StateHandler/OrderStateHandlerInterface.php new file mode 100644 index 000000000..a83bde707 --- /dev/null +++ b/shopware/Component/StateHandler/OrderStateHandlerInterface.php @@ -0,0 +1,12 @@ + - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Component/StatusUpdate/UpdateStatusAction.php b/shopware/Component/StatusUpdate/UpdateStatusAction.php index 9a1aeefdf..a141962ff 100644 --- a/shopware/Component/StatusUpdate/UpdateStatusAction.php +++ b/shopware/Component/StatusUpdate/UpdateStatusAction.php @@ -30,7 +30,7 @@ public function execute(): UpdateStatusResult return $result; } $transactionIds = $transactions->getIds(); - + /** @var string $transactionId */ foreach ($transactionIds as $transactionId) { $result->addUpdateId($transactionId); $this->notification->onNotify($transactionId, $context); diff --git a/shopware/Component/StatusUpdate/UpdateStatusResult.php b/shopware/Component/StatusUpdate/UpdateStatusResult.php index 2d44927db..5bb7a6780 100644 --- a/shopware/Component/StatusUpdate/UpdateStatusResult.php +++ b/shopware/Component/StatusUpdate/UpdateStatusResult.php @@ -3,8 +3,11 @@ namespace Mollie\Shopware\Component\StatusUpdate; -class UpdateStatusResult +final class UpdateStatusResult { + /** + * @var array + */ private array $updateTransactionIds = []; public function getUpdated(): int diff --git a/shopware/Component/StatusUpdate/UpdateStatusScheduledTask.php b/shopware/Component/StatusUpdate/UpdateStatusScheduledTask.php index 0fffa24b8..ed1eec9dd 100644 --- a/shopware/Component/StatusUpdate/UpdateStatusScheduledTask.php +++ b/shopware/Component/StatusUpdate/UpdateStatusScheduledTask.php @@ -4,7 +4,9 @@ namespace Mollie\Shopware\Component\StatusUpdate; use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTask; +use Symfony\Component\DependencyInjection\Attribute\AutoconfigureTag; +#[AutoconfigureTag('shopware.scheduled.task')] final class UpdateStatusScheduledTask extends ScheduledTask { protected const MINUTELY = 60; diff --git a/shopware/Component/StatusUpdate/UpdateStatusTaskHandler.php b/shopware/Component/StatusUpdate/UpdateStatusTaskHandler.php index 73a5c9a06..aece6ac8c 100644 --- a/shopware/Component/StatusUpdate/UpdateStatusTaskHandler.php +++ b/shopware/Component/StatusUpdate/UpdateStatusTaskHandler.php @@ -4,29 +4,31 @@ namespace Mollie\Shopware\Component\StatusUpdate; use Psr\Log\LoggerInterface; -use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; +use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskCollection; use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskEntity; use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler; +use Symfony\Component\DependencyInjection\Attribute\Autowire; use Symfony\Component\Messenger\Attribute\AsMessageHandler; #[AsMessageHandler(handles: UpdateStatusScheduledTask::class)] final class UpdateStatusTaskHandler extends ScheduledTaskHandler { - private UpdateStatusAction $action; - /** - * @param EntityRepository> $scheduledTaskRepository + * @param EntityRepository> $scheduledTaskRepository */ - public function __construct(UpdateStatusAction $action, $scheduledTaskRepository, LoggerInterface $exceptionLogger) - { + public function __construct(private UpdateStatusAction $action, + #[Autowire(service: 'scheduled_task.repository')] + EntityRepository $scheduledTaskRepository, + #[Autowire(service: 'monolog.logger.mollie')] + LoggerInterface $exceptionLogger + ) { parent::__construct($scheduledTaskRepository, $exceptionLogger); - $this->action = $action; } public function run(): void { - $result = $this->action->execute(); + $this->action->execute(); } /** diff --git a/shopware/Component/Subscription/Action/AbstractAction.php b/shopware/Component/Subscription/Action/AbstractAction.php new file mode 100644 index 000000000..d1dd4ba71 --- /dev/null +++ b/shopware/Component/Subscription/Action/AbstractAction.php @@ -0,0 +1,38 @@ + + */ + abstract public function getEventClass(): string; + + abstract public static function getActioName(): string; + + public function supports(string $actionName): bool + { + return $actionName === $this::getActioName(); + } + + public function getEvent(SubscriptionEntity $subscription, CustomerEntity $customer, Context $context): SubscriptionActionEvent + { + $eventClass = $this->getEventClass(); + + return new $eventClass($subscription, $customer, $context); + } +} diff --git a/shopware/Component/Subscription/Action/CancelAction.php b/shopware/Component/Subscription/Action/CancelAction.php new file mode 100644 index 000000000..b0e15476a --- /dev/null +++ b/shopware/Component/Subscription/Action/CancelAction.php @@ -0,0 +1,115 @@ +> $subscriptionRepository + * @param SubscriptionGateway $mollieGateway + */ + public function __construct( + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $mollieGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public function execute(SubscriptionDataStruct $subscriptionData, SubscriptionSettings $settings, Subscription $mollieSubscription, string $orderNumber, Context $context): Subscription + { + $subscription = $subscriptionData->getSubscription(); + $subscriptionId = $subscription->getId(); + $salesChannelId = $subscription->getSalesChannelId(); + $mollieSubscriptionId = $subscription->getMollieId(); + $mollieCustomerId = $subscription->getMollieCustomerId(); + $shopwareSubscriptionStatus = SubscriptionStatus::from($subscription->getStatus()); + $mollieSubscriptionStatus = $mollieSubscription->getStatus(); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'salesChannelId' => $salesChannelId, + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'mollieCustomerId' => $mollieCustomerId, + 'orderNumber' => $orderNumber, + 'shopwareSubscriptionStatus' => $shopwareSubscriptionStatus->value, + 'mollieSubscriptionStatus' => $mollieSubscriptionStatus->value + ]; + + $this->logger->info('Starting to cancel subscription', $logData); + + if (! $mollieSubscriptionStatus->isActive()) { + $this->logger->error('Subscription status is not active', $logData); + throw new SubscriptionNotActiveException($subscriptionId); + } + + $today = new \DateTime(); + $newStatus = SubscriptionStatus::CANCELED_AFTER_RENEWAL; + $canceledAt = null; + $nextPaymentAt = $mollieSubscription->getNextPaymentDate() ?? $today; + $nextPaymentAtDate = $nextPaymentAt->format('Y-m-d'); + + $metaData = $subscription->getMetadata(); + $metaData->setNextPossiblePaymentDate($nextPaymentAtDate); + + $subscriptionHistories = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => $newStatus->value, + 'mollieId' => $mollieSubscriptionId, + 'comment' => 'cancelled after ' . $nextPaymentAtDate + ]; + + if ($mollieSubscription->isStateChangeWindowOpen($today, $settings->getCancelDays())) { + $newStatus = SubscriptionStatus::CANCELED; + $canceledAt = $today; + $nextPaymentAt = null; + $subscriptionHistories['comment'] = 'cancelled'; + $subscriptionHistories['statusTo'] = $newStatus->value; + $this->logger->info('Subscription will be cancelled immediately', $logData); + $mollieSubscription = $this->mollieGateway->cancelSubscription($mollieSubscriptionId, $mollieCustomerId, $orderNumber, $salesChannelId); + } + + $upsertData = [ + 'id' => $subscriptionId, + 'status' => $newStatus->value, + 'nextPaymentAt' => $nextPaymentAt, + 'canceledAt' => $canceledAt, + 'metadata' => $metaData->toArray(), + 'historyEntries' => [$subscriptionHistories] + ]; + + $this->subscriptionRepository->upsert([$upsertData], $context); + $this->logger->info('Cancel subscription finished', $logData); + + return $mollieSubscription; + } + + public function getEventClass(): string + { + return SubscriptionCancelledEvent::class; + } + + public static function getActioName(): string + { + return self::ACTION_NAME; + } +} diff --git a/shopware/Component/Subscription/Action/Exception/NextPaymentAtNotFoundException.php b/shopware/Component/Subscription/Action/Exception/NextPaymentAtNotFoundException.php new file mode 100644 index 000000000..056689681 --- /dev/null +++ b/shopware/Component/Subscription/Action/Exception/NextPaymentAtNotFoundException.php @@ -0,0 +1,12 @@ +> $subscriptionRepository + * @param SubscriptionGateway $mollieGateway + */ + public function __construct( + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $mollieGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public static function getActioName(): string + { + return self::ACTION_NAME; + } + + /** + * @return class-string + */ + public function getEventClass(): string + { + return SubscriptionPausedEvent::class; + } + + public function execute(SubscriptionDataStruct $subscriptionData, SubscriptionSettings $settings, Subscription $mollieSubscription, string $orderNumber, Context $context): Subscription + { + $subscription = $subscriptionData->getSubscription(); + $subscriptionId = $subscription->getId(); + $salesChannelId = $subscription->getSalesChannelId(); + $mollieSubscriptionId = $subscription->getMollieId(); + $mollieCustomerId = $subscription->getMollieCustomerId(); + $shopwareSubscriptionStatus = SubscriptionStatus::from($subscription->getStatus()); + $mollieSubscriptionStatus = $mollieSubscription->getStatus(); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'salesChannelId' => $salesChannelId, + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'mollieCustomerId' => $mollieCustomerId, + 'orderNumber' => $orderNumber, + 'shopwareSubscriptionStatus' => $shopwareSubscriptionStatus->value, + 'mollieSubscriptionStatus' => $mollieSubscriptionStatus->value + ]; + + $this->logger->info('Starting to pause subscription', $logData); + + if (! $settings->isAllowPauseAndResume()) { + $this->logger->error('Pausing subscriptions is disabled in the settings', $logData); + throw new PauseAndResumeNotAllowedException($salesChannelId); + } + + if (! $mollieSubscriptionStatus->isActive()) { + $this->logger->error('Subscription status is not active', $logData); + throw new SubscriptionNotActiveException($subscriptionId); + } + + $today = new \DateTime(); + $newStatus = SubscriptionStatus::PAUSED_AFTER_RENEWAL; + $canceledAt = null; + $nextPaymentAt = $mollieSubscription->getNextPaymentDate() ?? $today; + $nextPaymentAtDate = $nextPaymentAt->format('Y-m-d'); + + $metaData = $subscription->getMetadata(); + $metaData->setNextPossiblePaymentDate($nextPaymentAtDate); + + $subscriptionHistories = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => $newStatus->value, + 'mollieId' => $mollieSubscriptionId, + 'comment' => 'paused after ' . $nextPaymentAtDate + ]; + + if ($mollieSubscription->isStateChangeWindowOpen($today, $settings->getCancelDays())) { + $newStatus = SubscriptionStatus::PAUSED; + $canceledAt = $today; + $nextPaymentAt = null; + $subscriptionHistories['comment'] = 'paused'; + $subscriptionHistories['statusTo'] = $newStatus->value; + $this->logger->info('Subscription will be paused immediately', $logData); + $mollieSubscription = $this->mollieGateway->cancelSubscription($mollieSubscriptionId, $mollieCustomerId, $orderNumber, $salesChannelId); + } + + $upsertData = [ + 'id' => $subscriptionId, + 'status' => $newStatus->value, + 'nextPaymentAt' => $nextPaymentAt, + 'canceledAt' => $canceledAt, + 'metadata' => $metaData->toArray(), + 'historyEntries' => [$subscriptionHistories] + ]; + + $this->subscriptionRepository->upsert([$upsertData], $context); + $this->logger->info('Pause subscription finished', $logData); + + return $mollieSubscription; + } +} diff --git a/shopware/Component/Subscription/Action/ResumeAction.php b/shopware/Component/Subscription/Action/ResumeAction.php new file mode 100644 index 000000000..6fb1d5a72 --- /dev/null +++ b/shopware/Component/Subscription/Action/ResumeAction.php @@ -0,0 +1,115 @@ +> $subscriptionRepository + * @param SubscriptionGateway $subscriptionGateway + */ + public function __construct( + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $subscriptionGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public static function getActioName(): string + { + return self::ACTION_NAME; + } + + public function getEventClass(): string + { + return SubscriptionResumedEvent::class; + } + + public function execute(SubscriptionDataStruct $subscriptionData, SubscriptionSettings $settings, Subscription $mollieSubscription, string $orderNumber, Context $context): Subscription + { + $subscription = $subscriptionData->getSubscription(); + $subscriptionId = $subscription->getId(); + $salesChannelId = $subscription->getSalesChannelId(); + $mollieSubscriptionId = $subscription->getMollieId(); + $mollieCustomerId = $subscription->getMollieCustomerId(); + $shopwareSubscriptionStatus = SubscriptionStatus::from($subscription->getStatus()); + $mollieSubscriptionStatus = $mollieSubscription->getStatus(); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'salesChannelId' => $salesChannelId, + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'mollieCustomerId' => $mollieCustomerId, + 'orderNumber' => $orderNumber, + 'shopwareSubscriptionStatus' => $shopwareSubscriptionStatus->value, + 'mollieSubscriptionStatus' => $mollieSubscriptionStatus->value + ]; + + $this->logger->info('Starting to resume subscription', $logData); + + if (! $settings->isAllowPauseAndResume()) { + $this->logger->error('Resuming subscriptions is disabled in the settings', $logData); + throw new PauseAndResumeNotAllowedException($salesChannelId); + } + + if ($mollieSubscriptionStatus->isActive()) { + $this->logger->error('Mollie subscription status is active', $logData); + throw new SubscriptionActiveException($subscriptionId); + } + + $metaData = $subscription->getMetadata(); + + $startDate = max($metaData->getNextPossiblePaymentDate(), new \DateTime()); + + $mollieSubscription->setStartDate($startDate); + + $newSubscription = $this->subscriptionGateway->copySubscription($mollieSubscription, $mollieCustomerId, $orderNumber, $salesChannelId); + $mollieSubscriptionId = $newSubscription->getId(); + + $logData['newMollieSubscriptionId'] = $mollieSubscriptionId; + + $newStatus = SubscriptionStatus::RESUMED; + + $subscriptionHistories = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => $newStatus->value, + 'mollieId' => $mollieSubscriptionId, + 'comment' => 'resumed' + ]; + + $upsertData = [ + 'id' => $subscriptionId, + 'status' => $newStatus->value, + 'mollieId' => $mollieSubscriptionId, + 'nextPaymentAt' => $newSubscription->getNextPaymentDate(), + 'canceledAt' => null, + 'historyEntries' => [$subscriptionHistories] + ]; + + $this->subscriptionRepository->upsert([$upsertData], $context); + $this->logger->info('Subscription resumed', $logData); + + return $newSubscription; + } +} diff --git a/shopware/Component/Subscription/Action/SkipAction.php b/shopware/Component/Subscription/Action/SkipAction.php new file mode 100644 index 000000000..e13f9a300 --- /dev/null +++ b/shopware/Component/Subscription/Action/SkipAction.php @@ -0,0 +1,136 @@ +> $subscriptionRepository + * @param SubscriptionGateway $mollieGateway + */ + public function __construct( + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $mollieGateway, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public static function getActioName(): string + { + return self::ACTION_NAME; + } + + /** + * @return class-string + */ + public function getEventClass(): string + { + return SubscriptionSkippedEvent::class; + } + + public function execute(SubscriptionDataStruct $subscriptionData, SubscriptionSettings $settings, Subscription $mollieSubscription, string $orderNumber, Context $context): Subscription + { + $subscription = $subscriptionData->getSubscription(); + $subscriptionId = $subscription->getId(); + $salesChannelId = $subscription->getSalesChannelId(); + $mollieSubscriptionId = $subscription->getMollieId(); + $mollieCustomerId = $subscription->getMollieCustomerId(); + $shopwareSubscriptionStatus = SubscriptionStatus::from($subscription->getStatus()); + $mollieSubscriptionStatus = $mollieSubscription->getStatus(); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'salesChannelId' => $salesChannelId, + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'mollieCustomerId' => $mollieCustomerId, + 'orderNumber' => $orderNumber, + 'shopwareSubscriptionStatus' => $shopwareSubscriptionStatus->value, + 'mollieSubscriptionStatus' => $mollieSubscriptionStatus->value + ]; + + $this->logger->info('Starting to skip subscription', $logData); + + if (! $settings->isAllowPauseAndResume()) { + $this->logger->error('Skipping subscriptions is disabled in the settings', $logData); + throw new PauseAndResumeNotAllowedException($salesChannelId); + } + + if (! $mollieSubscriptionStatus->isActive()) { + $this->logger->error('Subscription status is not active', $logData); + throw new SubscriptionNotActiveException($subscriptionId); + } + + $today = new \DateTime(); + $newStatus = SubscriptionStatus::SKIPPED_AFTER_RENEWAL; + $nextPaymentAt = $mollieSubscription->getNextPaymentDate() ?? $today; + + $logData['nextPaymentDate'] = $nextPaymentAt->format('Y-m-d'); + + $subscriptionHistories = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => $newStatus->value, + 'comment' => 'skipped after ' . $nextPaymentAt->format('Y-m-d') + ]; + + if ($mollieSubscription->isStateChangeWindowOpen($today, $settings->getCancelDays())) { + $newStatus = SubscriptionStatus::SKIPPED; + $subscriptionHistories['comment'] = 'skipped'; + $subscriptionHistories['statusTo'] = $newStatus->value; + + $mollieSubscription->setStartDate($mollieSubscription->skipPayment()); + + $mollieSubscription = $this->mollieGateway->cancelSubscription($mollieSubscriptionId, $mollieCustomerId, $orderNumber, $salesChannelId); + + $newSubscription = $this->mollieGateway->copySubscription($mollieSubscription, $mollieCustomerId, $orderNumber, $salesChannelId); + + $mollieSubscriptionId = $newSubscription->getId(); + $nextPaymentAt = $newSubscription->getNextPaymentDate(); + if (! $nextPaymentAt instanceof \DateTime) { + throw new NextPaymentAtNotFoundException($mollieSubscriptionId); + } + $logData['newNextPaymentDate'] = $nextPaymentAt->format('Y-m-d'); + $logData['newMollieSubscriptionId'] = $mollieSubscriptionId; + + $this->logger->info('Subscription skipped immediately', $logData); + } + + $subscriptionHistories['mollieId'] = $mollieSubscriptionId; + + $upsertData = [ + 'id' => $subscriptionId, + 'status' => $newStatus->value, + 'mollieId' => $mollieSubscriptionId, + 'nextPaymentAt' => $nextPaymentAt, + 'canceledAt' => null, + 'historyEntries' => [$subscriptionHistories] + ]; + + $this->subscriptionRepository->upsert([$upsertData], $context); + $this->logger->info('Subscription skipped', $logData); + + return $mollieSubscription; + } +} diff --git a/src/Components/Subscription/Cart/Error/InvalidGuestAccountError.php b/shopware/Component/Subscription/Cart/Error/InvalidGuestAccountError.php similarity index 90% rename from src/Components/Subscription/Cart/Error/InvalidGuestAccountError.php rename to shopware/Component/Subscription/Cart/Error/InvalidGuestAccountError.php index e0371570d..24a3e215a 100644 --- a/src/Components/Subscription/Cart/Error/InvalidGuestAccountError.php +++ b/shopware/Component/Subscription/Cart/Error/InvalidGuestAccountError.php @@ -1,7 +1,7 @@ lineItemId = $lineItemId; - parent::__construct(); } diff --git a/shopware/Component/Subscription/Cart/Validator/AvailabilityInformationValidator.php b/shopware/Component/Subscription/Cart/Validator/AvailabilityInformationValidator.php new file mode 100644 index 000000000..8bb7da7cf --- /dev/null +++ b/shopware/Component/Subscription/Cart/Validator/AvailabilityInformationValidator.php @@ -0,0 +1,61 @@ +settingsService->getSubscriptionSettings($context->getSalesChannelId()); + + if (! $subscriptionSettings->isEnabled()) { + $this->clearError($cart); + + return; + } + $lineItems = new LineItemCollection($cart->getLineItems()->getFlat()); + + /** @var ?LineItem $firstSubscriptionItem */ + $firstSubscriptionItem = $this->lineItemAnalyzer->getFirstSubscriptionProduct($lineItems); + if ($firstSubscriptionItem === null) { + $this->clearError($cart); + + return; + } + + $errors->add(new PaymentMethodAvailabilityNotice($firstSubscriptionItem->getId())); + } + + private function clearError(Cart $cart): void + { + $list = new ErrorCollection(); + + foreach ($cart->getErrors() as $error) { + if (! $error instanceof PaymentMethodAvailabilityNotice) { + $list->add($error); + } + } + + $cart->setErrors($list); + } +} diff --git a/shopware/Component/Subscription/Cart/Validator/SubscriptionCartValidator.php b/shopware/Component/Subscription/Cart/Validator/SubscriptionCartValidator.php new file mode 100644 index 000000000..dd93fa41a --- /dev/null +++ b/shopware/Component/Subscription/Cart/Validator/SubscriptionCartValidator.php @@ -0,0 +1,87 @@ +clearError($cart); + + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($context->getSalesChannelId()); + + if (! $subscriptionSettings->isEnabled()) { + return; + } + $shopwarePaymentMethod = $context->getPaymentMethod(); + + $paymentMethodHandler = $this->paymentHandlerLocator->findByIdentifier($shopwarePaymentMethod->getHandlerIdentifier()); + + if (! $paymentMethodHandler instanceof AbstractMolliePaymentHandler) { + return; + } + + $customer = $context->getCustomer(); + if ($customer === null) { + return; + } + + if ($customer->getGuest()) { + $errors->add(new InvalidGuestAccountError()); + } + + $lineItems = new LineItemCollection($cart->getLineItems()->getFlat()); + + if (! $this->lineItemAnalyzer->hasSubscriptionProduct($lineItems)) { + return; + } + + if ($this->lineItemAnalyzer->hasMixedLineItems($lineItems)) { + $errors->add(new MixedCartBlockError()); + } + + if (! $paymentMethodHandler instanceof SubscriptionAwareInterface) { + $errors->add(new InvalidPaymentMethodError()); + } + } + + private function clearError(Cart $cart): void + { + $list = new ErrorCollection(); + + foreach ($cart->getErrors() as $error) { + if (! $error instanceof InvalidGuestAccountError + && ! $error instanceof MixedCartBlockError + && ! $error instanceof InvalidPaymentMethodError) { + $list->add($error); + } + } + + $cart->setErrors($list); + } +} diff --git a/shopware/Component/Subscription/Controller/ApiController.php b/shopware/Component/Subscription/Controller/ApiController.php new file mode 100644 index 000000000..ff581a6a3 --- /dev/null +++ b/shopware/Component/Subscription/Controller/ApiController.php @@ -0,0 +1,51 @@ + [ApiRouteScope::ID]])] +final class ApiController extends AbstractController +{ + public function __construct( + private readonly SubscriptionActionHandler $actionHandler + ) { + } + + #[Route(path: '/api/_action/mollie/subscriptions/pause', name: 'api.action.mollie.subscription.pause', defaults: ['action' => 'pause'], methods: ['POST'])] + #[Route(path: '/api/_action/mollie/subscriptions/resume', name: 'api.action.mollie.subscription.resume', defaults: ['action' => 'resume'], methods: ['POST'])] + #[Route(path: '/api/_action/mollie/subscriptions/skip', name: 'api.action.mollie.subscription.skip', defaults: ['action' => 'skip'], methods: ['POST'])] + #[Route(path: '/api/_action/mollie/subscriptions/cancel', name: 'api.action.mollie.subscription.cancel', defaults: ['action' => 'cancel'], methods: ['POST'])] + #[Route(path: '/api/_action/mollie/subscriptions/{action}', name: 'api.action.mollie.subscription.changeState', methods: ['POST'])] + public function changeState(Request $request, Context $context): Response + { + $subscriptionId = (string) $request->request->get('id'); + $action = $request->attributes->get('action'); + $status = 500; + $success = false; + $data = []; + try { + $response = $this->actionHandler->handle($action, $subscriptionId, $context); + $data = ['subscription' => $response->toArray()]; + $status = 200; + $success = true; + } catch (\Throwable $exception) { + $data['error'] = $exception->getMessage(); + } + + $data['success'] = $success; + + return new JsonResponse($data, $status); + } +} diff --git a/shopware/Component/Subscription/Controller/SubscriptionController.php b/shopware/Component/Subscription/Controller/SubscriptionController.php new file mode 100644 index 000000000..c65f8f6a3 --- /dev/null +++ b/shopware/Component/Subscription/Controller/SubscriptionController.php @@ -0,0 +1,100 @@ + [StorefrontRouteScope::ID], 'csrf_protected' => false])] +final class SubscriptionController extends StorefrontController +{ + public function __construct( + #[Autowire(service: WebhookRoute::class)] + private readonly AbstractWebhookRoute $webhookRoute, + private readonly SubscriptionActionHandler $actionHandler, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + #[Route(path: '/mollie/webhook/subscription/{subscriptionId}', name: 'frontend.mollie.webhook.subscription', options: ['seo' => false], methods: ['GET', 'POST'])] + public function webhook(string $subscriptionId, Request $request, SalesChannelContext $context): Response + { + try { + $this->logger->debug('Subscription Webhook received', [ + 'transactionId' => $subscriptionId, + ]); + $response = $this->webhookRoute->notify($subscriptionId, $request,$context->getContext()); + + return new JsonResponse($response->getObject()); + } catch (ShopwareHttpException $exception) { + $this->logger->warning( + 'Subscription Webhook request failed with warning', + [ + 'transactionId' => $subscriptionId, + 'message' => $exception->getMessage(), + ] + ); + + return new JsonResponse(['success' => false, 'error' => $exception->getMessage()], $exception->getStatusCode()); + } catch (\Throwable $exception) { + $this->logger->error( + 'Subscription Webhook request failed', + [ + 'transactionId' => $subscriptionId, + 'message' => $exception->getMessage(), + ] + ); + + return new JsonResponse(['success' => false, 'error' => $exception->getMessage()], 422); + } + } + + #[Route(path: '/account/mollie/subscriptions/{subscriptionId}/pause', name: 'frontend.account.mollie.subscriptions.pause', defaults: ['action' => 'pause'],methods: ['POST'])] + #[Route(path: '/account/mollie/subscriptions/{subscriptionId}/resume', name: 'frontend.account.mollie.subscriptions.resume', defaults: ['action' => 'resume'],methods: ['POST'])] + #[Route(path: '/account/mollie/subscriptions/{subscriptionId}/skip', name: 'frontend.account.mollie.subscriptions.skip', defaults: ['action' => 'skip'],methods: ['POST'])] + #[Route(path: '/account/mollie/subscriptions/{subscriptionId}/cancel', name: 'frontend.account.mollie.subscriptions.cancel', defaults: ['action' => 'cancel'],methods: ['POST'])] + #[Route(path: '/account/mollie/subscriptions/{subscriptionId}/{action}', name: 'frontend.account.mollie.subscriptions.changeState', methods: ['POST'])] + public function changeState(string $subscriptionId, Request $request, SalesChannelContext $salesChannelContext): Response + { + if ($salesChannelContext->getCustomer() === null) { + return $this->redirectToRoute('frontend.account.login.page'); + } + + $action = $request->attributes->get('action'); + + $translationKey = 'molliePayments.subscriptions.account.%s%s'; + + try { + $this->actionHandler->handle($action, $subscriptionId, $salesChannelContext->getContext()); + $translationKey = sprintf($translationKey, 'success', ucfirst($action)); + $this->addFlash(self::SUCCESS, $this->trans($translationKey)); + } catch (\Throwable $exception) { + $translationKey = sprintf($translationKey, 'error', ucfirst($action)); + $this->logger->error('Error when changing subscription state', [ + 'subscriptionId' => $subscriptionId, + 'action' => $action, + 'message' => $exception->getMessage(), + ]); + + $this->addFlash(self::DANGER, $this->trans($translationKey)); + } + + return $this->redirectToRoute('frontend.account.mollie.subscriptions.page'); + } +} diff --git a/shopware/Component/Subscription/CopyOrderService.php b/shopware/Component/Subscription/CopyOrderService.php new file mode 100644 index 000000000..7dcb689f6 --- /dev/null +++ b/shopware/Component/Subscription/CopyOrderService.php @@ -0,0 +1,196 @@ +> $orderRepository + */ + public function __construct( + #[Autowire(service: 'order.repository')] + private readonly EntityRepository $orderRepository, + private readonly OrderConverter $orderConverter, + #[Autowire(service: CartOrderRoute::class)] + private readonly AbstractCartOrderRoute $cartOrderRoute, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + } + + public function copy(SubscriptionDataStruct $subscriptionData, Payment $payment, Context $context): OrderTransactionEntity + { + $order = $subscriptionData->getOrder(); + $subscriptionId = $subscriptionData->getSubscription()->getId(); + $subscriptionBillingAddress = $subscriptionData->getBillingAddress(); + $subscriptionShippingAddress = $subscriptionData->getShippingAddress(); + + $logData = [ + 'orderId' => $order->getId(), + 'orderNumber' => $order->getOrderNumber(), + ]; + + $this->logger->info('Start to copy old order', $logData); + $newOrder = $this->copyOrder($order, $context); + + $orderNumber = (string) $newOrder->getOrderNumber(); + $logData['newOrderNumber'] = $orderNumber; + + $this->logger->info('New order was created', $logData); + + $firstTransaction = $newOrder->getTransactions()?->first(); + + if (! $firstTransaction instanceof OrderTransactionEntity) { + $this->logger->error('The order transaction entity was not found', $logData); + throw new OrderWithoutTransactionException($newOrder->getId()); + } + $orderDeliveries = $order->getDeliveries(); + if (! $orderDeliveries instanceof OrderDeliveryCollection) { + throw new OrderWithoutDeliveriesException($newOrder->getId()); + } + + $orderData = $this->getOrderData($subscriptionId, $newOrder, $orderDeliveries, $firstTransaction, $subscriptionBillingAddress, $subscriptionShippingAddress, $payment); + + $this->orderRepository->upsert([$orderData], $context); + + $payment->setShopwareTransaction($firstTransaction); + + return $firstTransaction; + } + + private function copyOrder(OrderEntity $order, Context $context): OrderEntity + { + $salesChannelContext = $this->orderConverter->assembleSalesChannelContext($order, $context); + + $cart = $this->orderConverter->convertToCart($order, $context); + + $cart->removeExtension(OrderConverter::ORIGINAL_ID); + $cart->removeExtension(OrderConverter::ORIGINAL_ORDER_NUMBER); + + $cart->removeExtension('originalPrimaryOrderDelivery'); + $cart->removeExtension('originalPrimaryOrderTransaction'); + + $deliveries = new DeliveryCollection(); + + foreach ($cart->getDeliveries() as $delivery) { + foreach ($delivery->getPositions() as $position) { + $position->removeExtension(OrderConverter::ORIGINAL_ID); + $position->getLineItem()->removeExtension(OrderConverter::ORIGINAL_ID); + } + + $delivery = new Delivery( + $delivery->getPositions(), + $delivery->getDeliveryDate(), + $delivery->getShippingMethod(), + $salesChannelContext->getShippingLocation(), + $delivery->getShippingCosts() + ); + $deliveries->add($delivery); + } + $cart->setDeliveries($deliveries); + + foreach ($cart->getLineItems() as $lineItem) { + $lineItem->removeExtension(OrderConverter::ORIGINAL_ID); + } + + $orderResponse = $this->cartOrderRoute->order($cart, $salesChannelContext, (new DataBag())->toRequestDataBag()); + + return $orderResponse->getOrder(); + } + + /** + * @return array + */ + private function getOrderData(string $subscriptionId, OrderEntity $newOrder, OrderDeliveryCollection $deliveryCollection, OrderTransactionEntity $firstTransaction, SubscriptionAddressEntity $subscriptionBillingAddress, SubscriptionAddressEntity $subscriptionShippingAddress, Payment $molliePayment): array + { + $billingAddress = $this->getAddressData($subscriptionBillingAddress); + $billingAddress['id'] = $newOrder->getBillingAddressId(); + $shippingAddress = $this->getAddressData($subscriptionShippingAddress); + + $deliveries = []; + + foreach ($deliveryCollection as $delivery) { + $shippingAddress['id'] = $delivery->getShippingOrderAddressId(); + $deliveries[] = [ + 'id' => $delivery->getId(), + 'shippingOrderAddress' => $shippingAddress + ]; + } + + return [ + 'id' => $firstTransaction->getOrderId(), + 'transactions' => [ + [ + 'id' => $firstTransaction->getId(), + 'customFields' => [ + Mollie::EXTENSION => $molliePayment->toArray() + ] + ] + ], + 'billingAddress' => $billingAddress, + 'deliveries' => $deliveries, + 'tags' => [ + [ + 'id' => SubscriptionTag::ID + ] + ], + 'customFields' => [ + Mollie::EXTENSION => [ + 'swSubscriptionId' => $subscriptionId, + ] + ] + ]; + } + + /** + * @return array + */ + private function getAddressData(SubscriptionAddressEntity $address): array + { + $addressData = [ + 'title' => $address->getTitle(), + 'firstName' => $address->getFirstName(), + 'lastName' => $address->getLastName(), + 'salutationId' => $address->getSalutationId(), + 'countryId' => $address->getCountryId(), + 'countryStateId' => $address->getCountryStateId(), + 'company' => $address->getCompany(), + 'department' => $address->getDepartment(), + 'street' => $address->getStreet(), + 'zipcode' => $address->getZipcode(), + 'city' => $address->getCity(), + 'vatId' => $address->getVatId(), + 'phoneNumber' => $address->getPhoneNumber(), + 'additionalAddressLine1' => $address->getAdditionalAddressLine1(), + 'additionalAddressLine2' => $address->getAdditionalAddressLine2(), + ]; + $addressData['customFields'] = [ + Mollie::EXTENSION => [ + 'subscriptionAddressId' => $address->getId(), + ] + ]; + + return $addressData; + } +} diff --git a/shopware/Component/Subscription/CopyOrderServiceInterface.php b/shopware/Component/Subscription/CopyOrderServiceInterface.php new file mode 100644 index 000000000..8e9997108 --- /dev/null +++ b/shopware/Component/Subscription/CopyOrderServiceInterface.php @@ -0,0 +1,13 @@ +add(new OneToManyAssociationField('mollieSubscriptions', SubscriptionDefinition::class, 'order_id')); + } + + public function getEntityName(): string + { + return OrderDefinition::ENTITY_NAME; + } +} diff --git a/src/Components/Subscription/DAL/Salutation/SalutationExtension.php b/shopware/Component/Subscription/DAL/Salutation/SalutationExtension.php similarity index 74% rename from src/Components/Subscription/DAL/Salutation/SalutationExtension.php rename to shopware/Component/Subscription/DAL/Salutation/SalutationExtension.php index 338031488..cd9a8da41 100644 --- a/src/Components/Subscription/DAL/Salutation/SalutationExtension.php +++ b/shopware/Component/Subscription/DAL/Salutation/SalutationExtension.php @@ -1,15 +1,17 @@ 'mollie_subscription_address'])] class SubscriptionAddressDefinition extends EntityDefinition { public const ENTITY_NAME = 'mollie_subscription_address'; diff --git a/src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php b/shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php similarity index 96% rename from src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php rename to shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php index cb0cfed8a..0b0294c3f 100644 --- a/src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php +++ b/shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionAddress/SubscriptionAddressEntity.php @@ -1,10 +1,10 @@ 'mollie_subscription_history'])] class SubscriptionHistoryDefinition extends EntityDefinition { public const ENTITY_NAME = 'mollie_subscription_history'; diff --git a/src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php b/shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php similarity index 91% rename from src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php rename to shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php index 8b33d8963..dc5e24710 100644 --- a/src/Components/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php +++ b/shopware/Component/Subscription/DAL/Subscription/Aggregate/SubscriptionHistory/SubscriptionHistoryEntity.php @@ -1,9 +1,9 @@ 'mollie_subscription'])] +#[AutoconfigureTag('shopware.composite_search.definition',['priority' => '1500'])] class SubscriptionDefinition extends EntityDefinition { public const ENTITY_NAME = 'mollie_subscription'; @@ -61,7 +63,6 @@ protected function defineFields(): FieldCollection (new StringField('status', 'status'))->addFlags(new ApiAware()), (new StringField('description', 'description'))->addFlags(new ApiAware()), (new FloatField('amount', 'amount'))->addFlags(new ApiAware()), - (new IntField('quantity', 'quantity'))->addFlags(new ApiAware()), (new FkField('currency_id', 'currencyId', CurrencyDefinition::class))->addFlags(new ApiAware(), new Required()), new JsonField('metadata', 'metadata'), @@ -78,8 +79,8 @@ protected function defineFields(): FieldCollection (new DateTimeField('last_reminded_at', 'lastRemindedAt'))->addFlags(new ApiAware()), (new DateTimeField('canceled_at', 'canceledAt'))->addFlags(new ApiAware()), - (new FkField('product_id', 'productId', ProductDefinition::class))->addFlags(new ApiAware()), - (new FkField('order_id', 'orderId', OrderDefinition::class))->addFlags(new ApiAware()), + (new FkField('order_id', 'orderId', OrderDefinition::class))->addFlags(new ApiAware(),new Required()), + (new ReferenceVersionField(OrderDefinition::class))->addFlags(new ApiAware(), new Required()), (new FkField('sales_channel_id', 'salesChannelId', SalesChannelDefinition::class))->addFlags(new ApiAware()), (new FkField('billing_address_id', 'billingAddressId', SalesChannelDefinition::class))->addFlags(new ApiAware()), @@ -97,6 +98,7 @@ protected function defineFields(): FieldCollection new ManyToOneAssociationField('customer', 'customer_id', CustomerDefinition::class, 'id', false), new ManyToOneAssociationField('currency', 'currency_id', CurrencyDefinition::class, 'id', false), + new ManyToOneAssociationField('order', 'order_id', OrderDefinition::class, 'id', false), new OneToManyAssociationField('addresses', SubscriptionAddressDefinition::class, 'subscription_id'), new OneToManyAssociationField('historyEntries', SubscriptionHistoryDefinition::class, 'subscription_id'), diff --git a/src/Components/Subscription/DAL/Subscription/SubscriptionEntity.php b/shopware/Component/Subscription/DAL/Subscription/SubscriptionEntity.php similarity index 91% rename from src/Components/Subscription/DAL/Subscription/SubscriptionEntity.php rename to shopware/Component/Subscription/DAL/Subscription/SubscriptionEntity.php index e04c6db45..475e34869 100644 --- a/src/Components/Subscription/DAL/Subscription/SubscriptionEntity.php +++ b/shopware/Component/Subscription/DAL/Subscription/SubscriptionEntity.php @@ -1,13 +1,14 @@ order; + } + + public function setOrder(OrderEntity $order): void + { + $this->order = $order; + } // -------------------------------------------------------------------------------- public function setMetadata(SubscriptionMetadata $metadata): void @@ -231,16 +236,6 @@ public function setAmount(float $amount): void $this->amount = $amount; } - public function getQuantity(): int - { - return $this->quantity; - } - - public function setQuantity(int $quantity): void - { - $this->quantity = $quantity; - } - public function getCurrency(): ?CurrencyEntity { return $this->currency; @@ -251,24 +246,24 @@ public function setCurrency(CurrencyEntity $currency): void $this->currency = $currency; } - public function getProductId(): string + public function getOrderId(): string { - return (string) $this->productId; + return (string) $this->orderId; } - public function setProductId(string $productId): void + public function setOrderId(string $orderId): void { - $this->productId = $productId; + $this->orderId = $orderId; } - public function getOrderId(): string + public function getOrderVersionId(): string { - return (string) $this->orderId; + return $this->orderVersionId; } - public function setOrderId(string $orderId): void + public function setOrderVersionId(string $orderVersionId): void { - $this->orderId = $orderId; + $this->orderVersionId = $orderVersionId; } public function getMandateId(): string diff --git a/src/Components/Subscription/DAL/Subscription/SubscriptionEvents.php b/shopware/Component/Subscription/DAL/Subscription/SubscriptionEvents.php similarity index 65% rename from src/Components/Subscription/DAL/Subscription/SubscriptionEvents.php rename to shopware/Component/Subscription/DAL/Subscription/SubscriptionEvents.php index 58cc86a25..cc464d7a2 100644 --- a/src/Components/Subscription/DAL/Subscription/SubscriptionEvents.php +++ b/shopware/Component/Subscription/DAL/Subscription/SubscriptionEvents.php @@ -1,7 +1,7 @@ createSubscription; + } + + public function getContext(): Context + { + return $this->context; + } +} diff --git a/shopware/Component/Subscription/Event/SubscriptionActionEvent.php b/shopware/Component/Subscription/Event/SubscriptionActionEvent.php new file mode 100644 index 000000000..36f6393f9 --- /dev/null +++ b/shopware/Component/Subscription/Event/SubscriptionActionEvent.php @@ -0,0 +1,73 @@ +add('subscription', new EntityType(SubscriptionDefinition::class)) + ->add('customer', new EntityType(CustomerDefinition::class)) + ; + } + + public function getName(): string + { + return 'mollie.subscription.' . $this->getEventName(); + } + + public function getMailStruct(): MailRecipientStruct + { + return new MailRecipientStruct([ + $this->customer->getEmail() => sprintf('%s %s', $this->customer->getFirstName(), $this->customer->getLastName()), + ]); + } + + public function getSalesChannelId(): string + { + return $this->subscription->getSalesChannelId(); + } + + public function getSubscription(): SubscriptionEntity + { + return $this->subscription; + } + + public function getSubscriptionId(): string + { + return $this->subscription->getId(); + } + + public function getCustomer(): CustomerEntity + { + return $this->customer; + } + + public function getContext(): Context + { + return $this->context; + } + + abstract protected function getEventName(): string; +} diff --git a/shopware/Component/Subscription/Event/SubscriptionAware.php b/shopware/Component/Subscription/Event/SubscriptionAware.php new file mode 100644 index 000000000..d402b2c7e --- /dev/null +++ b/shopware/Component/Subscription/Event/SubscriptionAware.php @@ -0,0 +1,15 @@ +getFirstSubscriptionProduct($lineItems) instanceof Struct; + } + + /** + * @param LineItemCollection|OrderLineItemCollection $lineItems + * + * @return null|LineItem|OrderLineItemEntity + */ + public function getFirstSubscriptionProduct(Collection $lineItems): ?Struct + { + foreach ($lineItems as $lineItem) { + /** @var ?Product $extension */ + $extension = $lineItem->getExtension(Mollie::EXTENSION); + if ($extension instanceof Product && $extension->isSubscription() === true) { + return $lineItem; + } + } + + return null; + } + + /** + * @param LineItemCollection|OrderLineItemCollection $lineItems + */ + public function hasMixedLineItems(Collection $lineItems): bool + { + $subscriptions = 0; + $others = 0; + /** @var LineItem|OrderLineItemEntity $lineItem */ + foreach ($lineItems as $lineItem) { + if ($lineItem->getType() === PromotionProcessor::LINE_ITEM_TYPE) { + // TODO: figure out what to do with promotions + // continue; + } + /** @var ?Product $extension */ + $extension = $lineItem->getExtension(Mollie::EXTENSION); + if ($extension instanceof Product && $extension->isSubscription() === true) { + ++$subscriptions; + continue; + } + + ++$others; + } + + return $subscriptions > 1 || $others > 0; + } +} diff --git a/shopware/Component/Subscription/Route/AbstractRenewRoute.php b/shopware/Component/Subscription/Route/AbstractRenewRoute.php new file mode 100644 index 000000000..1c3c3237b --- /dev/null +++ b/shopware/Component/Subscription/Route/AbstractRenewRoute.php @@ -0,0 +1,15 @@ + $subscriptionId, + ] + ); + } + + public static function subscriptionsDisabled(string $subscriptionId, string $salesChannelId): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::SUBSCRIPTIONS_DISABLED, + 'Failed to renew {{subscriptionId}}, subscriptions are disabled for the sales channel {{salesChannelId}}',[ + 'subscriptionId' => $subscriptionId, + 'salesChannelId' => $salesChannelId, + ] + ); + } + + public static function invalidPaymentId(string $subscriptionId, string $molliePaymentId): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::INVALID_PAYMENT_ID, + 'Failed to renew {{subscriptionId}}, payment id {{paymentId}} does not belong to this subscription',[ + 'subscriptionId' => $subscriptionId, + 'paymentId' => $molliePaymentId, + ] + ); + } + + public static function orderWithoutTransaction(string $subscriptionId,string $orderNumber): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::INVALID_PAYMENT_ID, + 'Failed to renew {{subscriptionId}}, new created order {{orderNumber}} is without transactions',[ + 'subscriptionId' => $subscriptionId, + 'orderNumber' => $orderNumber, + ] + ); + } + + public static function subscriptionWithoutAddress(string $subscriptionId): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::SUBSCRIPTION_WITHOUT_ADDRESS, + 'Failed to renew {{subscriptionId}}, subscription was loaded without address',[ + 'subscriptionId' => $subscriptionId, + ] + ); + } + + public static function orderWithoutDeliveries(string $subscriptionId, string $orderNumber): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_WITHOUT_DELIVERIES, + 'Failed to renew {{subscriptionId}}, new created order {{orderNumber}} is without deliveries',[ + 'subscriptionId' => $subscriptionId, + 'orderNumber' => $orderNumber, + ] + ); + } + + public static function subscriptionWithoutCustomer(string $subscriptionId): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::SUBSCRIPTION_WITHOUT_CUSTOMER, + 'Failed to renew {{subscriptionId}}, subscription order has no customer ',[ + 'subscriptionId' => $subscriptionId, + ] + ); + } +} diff --git a/shopware/Component/Subscription/Route/RenewRoute.php b/shopware/Component/Subscription/Route/RenewRoute.php new file mode 100644 index 000000000..c2e7ae1f2 --- /dev/null +++ b/shopware/Component/Subscription/Route/RenewRoute.php @@ -0,0 +1,190 @@ + ['api']])] +final class RenewRoute extends AbstractRenewRoute +{ + /** + * @param EntityRepository> $subscriptionRepository + */ + public function __construct( + #[Autowire(service: SettingsService::class)] + private readonly AbstractSettingsService $settingsService, + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: SubscriptionDataService::class)] + private readonly SubscriptionDataServiceInterface $subscriptionDataService, + #[Autowire(service: CopyOrderService::class)] + private readonly CopyOrderServiceInterface $copyOrderService, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $subscriptionGateway, + #[Autowire(service: MollieGateway::class)] + private readonly MollieGatewayInterface $mollieGateway, + #[Autowire(service: PaymentWebhookRoute::class)] + private readonly AbstractPaymentWebhookRoute $paymentWebhookRoute, + private readonly SubscriptionActionHandler $subscriptionActionHandler, + #[Autowire(service: 'event_dispatcher')] + private readonly EventDispatcherInterface $eventDispatcher, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public function getDecorated(): AbstractRenewRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/api/mollie/webhook/subscription/{subscriptionId}/renew', name: 'api.mollie.webhook.subscription.renew', methods: ['GET', 'POST'])] + public function renew(string $subscriptionId, Request $request, Context $context): WebhookResponse + { + $subscriptionId = strtolower($subscriptionId); + $molliePaymentId = (string) $request->get('id', ''); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'molliePaymentId' => $molliePaymentId, + 'data' => [ + 'postData' => $request->request->all(), + 'queryData' => $request->query->all(), + ] + ]; + + $this->logger->debug('Subscription renew requested', $logData); + + if (strlen($molliePaymentId) === 0) { + $this->logger->error('Subscription renew was triggered without required data', $logData); + throw WebhookException::paymentIdNotProvided($subscriptionId); + } + + $subscriptionData = $this->subscriptionDataService->findById($subscriptionId,$context); + $subscriptionEntity = $subscriptionData->getSubscription(); + $order = $subscriptionData->getOrder(); + $customer = $subscriptionData->getCustomer(); + + $salesChannelId = $subscriptionEntity->getSalesChannelId(); + $mollieCustomerId = $subscriptionEntity->getMollieCustomerId(); + $mollieSubscriptionId = $subscriptionEntity->getMollieId(); + $shopwareSubscriptionStatus = SubscriptionStatus::from($subscriptionEntity->getStatus()); + + $afterRenewalAction = $shopwareSubscriptionStatus->getAction(); + + $orderNumber = (string) $order->getOrderNumber(); + + $logData = array_merge($logData, [ + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannelId, + 'mollieCustomerId' => $mollieCustomerId, + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'shopwareSubscriptionStatus' => $shopwareSubscriptionStatus->value, + ]); + + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($salesChannelId); + + if (! $subscriptionSettings->isEnabled()) { + $this->logger->error('Subscription renew not possible, subscriptions are disabled for this sales channel', $logData); + throw RenewException::subscriptionsDisabled($subscriptionId, $salesChannelId); + } + + $this->logger->info('Subscription renew - Start', $logData); + $subscription = $this->subscriptionGateway->getSubscription($mollieSubscriptionId, $mollieCustomerId, $orderNumber, $salesChannelId); + $molliePayment = $this->mollieGateway->getPayment($molliePaymentId, $orderNumber, $salesChannelId); + $environmentSettings = $this->settingsService->getEnvironmentSettings(); + + if (! $environmentSettings->isDevMode() && $molliePayment->getSubscriptionId() !== $subscription->getId()) { + $this->logger->error('The provided mollie payments ID does not belong to the subscription', $logData); + throw RenewException::invalidPaymentId($subscriptionId, $molliePaymentId); + } + + if ($molliePayment->getStatus()->isFailed() && $subscriptionSettings->isSkipIfFailed()) { + return new WebhookResponse($molliePayment); + } + + $subscriptionHistories = []; + + if ($shopwareSubscriptionStatus->isInterrupted()) { + $this->logger->info('Subscription was skipped or paused, changed to resumed', $logData); + $subscriptionHistories[] = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => SubscriptionStatus::RESUMED->value, + 'mollieId' => $subscription->getId(), + 'comment' => 'resumed' + ]; + $shopwareSubscriptionStatus = SubscriptionStatus::RESUMED; + } + + $transaction = $this->copyOrderService->copy($subscriptionData,$molliePayment,$context); + + $today = new \DateTime(); + $nextPaymentDate = $subscription->getNextPaymentDate() ?? $today; + $nextPaymentDate = max($nextPaymentDate, $today); + + $subscriptionHistories[] = [ + 'statusFrom' => $shopwareSubscriptionStatus->value, + 'statusTo' => SubscriptionStatus::ACTIVE->value, + 'mollieId' => $subscription->getId(), + 'comment' => 'renewed' + ]; + + $this->subscriptionRepository->upsert([[ + 'id' => $subscriptionId, + 'mandateId' => (string) $molliePayment->getMandateId(), + 'nextPaymentAt' => $nextPaymentDate->format('Y-m-d'), + 'historyEntries' => $subscriptionHistories + ]], $context); + + $renewEvent = new SubscriptionRenewedEvent($subscriptionEntity, $customer, $context); + $this->eventDispatcher->dispatch($renewEvent); + + if ($subscription->getStatus() === SubscriptionStatus::COMPLETED) { + $this->logger->info('Subscription had limited amount, it is finished completely now', $logData); + $endedEvent = new SubscriptionEndedEvent($subscriptionEntity, $customer, $context); + $this->eventDispatcher->dispatch($endedEvent); + } + + if ($afterRenewalAction !== null) { + try { + $this->logger->info('Subscription was cancelled after renewal, changed to cancelled', $logData); + $this->subscriptionActionHandler->handle($afterRenewalAction, $subscriptionId, $context); + } catch (\Throwable $exception) { + $logData['message'] = $exception->getMessage(); + $this->logger->error('Failed to execute after renewal action: ' . $afterRenewalAction, $logData); + } + } + + $this->logger->info('Subscription renew - Finished, call Webhook', $logData); + + return $this->paymentWebhookRoute->notify($transaction->getId(), $context); + } +} diff --git a/shopware/Component/Subscription/Route/SubscriptionException.php b/shopware/Component/Subscription/Route/SubscriptionException.php new file mode 100644 index 000000000..6976ea624 --- /dev/null +++ b/shopware/Component/Subscription/Route/SubscriptionException.php @@ -0,0 +1,23 @@ + $subscriptionId, + ] + ); + } +} diff --git a/shopware/Component/Subscription/Route/WebhookException.php b/shopware/Component/Subscription/Route/WebhookException.php new file mode 100644 index 000000000..fc639d923 --- /dev/null +++ b/shopware/Component/Subscription/Route/WebhookException.php @@ -0,0 +1,23 @@ + $subscriptionId, + ] + ); + } +} diff --git a/shopware/Component/Subscription/Route/WebhookRoute.php b/shopware/Component/Subscription/Route/WebhookRoute.php new file mode 100644 index 000000000..7239135a2 --- /dev/null +++ b/shopware/Component/Subscription/Route/WebhookRoute.php @@ -0,0 +1,82 @@ + ['api'], 'auth_required' => false, 'auth_enabled' => false])] +final class WebhookRoute extends AbstractWebhookRoute +{ + /** + * @param EntityRepository> $transactionRepository + */ + public function __construct( + #[Autowire(service: 'order_transaction.repository')] + private readonly EntityRepository $transactionRepository, + #[Autowire(service: PaymentWebhookRoute::class)] + private AbstractPaymentWebhookRoute $abstractWebhookRoute, + #[Autowire(service: RenewRoute::class)] + private AbstractRenewRoute $abstractRenewRoute, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public function getDecorated(): AbstractWebhookRoute + { + throw new DecorationPatternException(self::class); + } + + #[Route(path: '/api/mollie/webhook/subscription/{subscriptionId}', name: 'api.mollie.webhook.subscription', methods: ['GET', 'POST'])] + public function notify(string $subscriptionId, Request $request, Context $context): WebhookResponse + { + $molliePaymentId = $request->get('id'); + $subscriptionId = strtolower($subscriptionId); + $logData = [ + 'subscriptionId' => $subscriptionId, + 'data' => [ + 'postData' => $request->request->all(), + 'queryData' => $request->query->all(), + ] + ]; + $this->logger->info('Subscription webhook received', $logData); + + if ($molliePaymentId === null) { + $this->logger->error('Subscription webhook was triggered without required data', $logData); + throw WebhookException::paymentIdNotProvided($subscriptionId); + } + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('customFields.' . Mollie::EXTENSION . '.id', $molliePaymentId)); + $criteria->addFilter(new EqualsFilter('order.customFields.' . Mollie::EXTENSION . '.swSubscriptionId', $subscriptionId)); + + $searchIdResult = $this->transactionRepository->searchIds($criteria, $context); + $transactionId = $searchIdResult->firstId(); + + if ($transactionId !== null) { + $this->logger->info('Subscription status updated', $logData); + + return $this->abstractWebhookRoute->notify($transactionId, $context); + } + + $this->logger->info('Subscription will be renewed', $logData); + + return $this->abstractRenewRoute->renew($subscriptionId, $request, $context); + } +} diff --git a/shopware/Component/Subscription/Subscriber/PaymentSubscriber.php b/shopware/Component/Subscription/Subscriber/PaymentSubscriber.php new file mode 100644 index 000000000..53a70067f --- /dev/null +++ b/shopware/Component/Subscription/Subscriber/PaymentSubscriber.php @@ -0,0 +1,210 @@ +> $subscriptionRepository + */ + public function __construct( + #[Autowire(service: SettingsService::class)] + private readonly AbstractSettingsService $settingsService, + private readonly LineItemAnalyzer $lineItemAnalyzer, + #[Autowire(service: 'mollie_subscription.repository')] + private readonly EntityRepository $subscriptionRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public static function getSubscribedEvents(): array + { + return [ + PaymentCreatedEvent::class => ['onPaymentCreated', self::PRIORITY], + ]; + } + + public function onPaymentCreated(PaymentCreatedEvent $event): void + { + $transactionData = $event->getTransactionDataStruct(); + + $order = $transactionData->getOrder(); + + $salesChannelId = $order->getSalesChannelId(); + $context = $event->getContext(); + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($salesChannelId); + if (! $subscriptionSettings->isEnabled()) { + return; + } + + $subscriptionCollection = $order->getExtension('mollieSubscriptions'); + if ($subscriptionCollection instanceof SubscriptionCollection && $subscriptionCollection->count() > 0) { + return; + } + + $lineItems = $order->getLineItems(); + if ($lineItems === null) { + return; + } + /** @var ?OrderLineItemEntity $firstSubscriptionProduct */ + $firstSubscriptionProduct = $this->lineItemAnalyzer->getFirstSubscriptionProduct($lineItems); + + if ($firstSubscriptionProduct === null) { + return; + } + + $logData = [ + 'orderNumber' => (string) $order->getOrderNumber(), + ]; + $shippingAddress = $transactionData->getShippingOrderAddress(); + $billingAddress = $transactionData->getBillingOrderAddress(); + $subscriptionData = $this->getSubscriptionData($order, $firstSubscriptionProduct, $transactionData->getCustomer()); + $subscriptionData['billingAddress'] = $this->getAddressData($billingAddress, $subscriptionData['id']); + $subscriptionData['shippingAddress'] = $this->getAddressData($shippingAddress, $subscriptionData['id']); + + $subscriptionData['historyEntries'][] = [ + 'statusFrom' => '', + 'statusTo' => SubscriptionStatus::PENDING->value, + 'comment' => 'created' + ]; + + $this->logger->info('Pending subscription created', $logData); + $this->subscriptionRepository->upsert([$subscriptionData], $context); + } + + /** + * @return array + */ + private function getSubscriptionData(OrderEntity $order, OrderLineItemEntity $lineItem, CustomerEntity $customer): array + { + $description = 'Order #' . $order->getOrderNumber(); + $totalRoundingValue = null; + $totalRounding = $order->getTotalRounding(); + if ($totalRounding instanceof CashRoundingConfig) { + $totalRoundingValue = $totalRounding->jsonSerialize(); + } + $itemRoundingValue = null; + $itemRounding = $order->getItemRounding(); + if ($itemRounding instanceof CashRoundingConfig) { + $itemRoundingValue = $itemRounding->jsonSerialize(); + } + $subscriptionId = Uuid::randomHex(); + + return [ + 'id' => $subscriptionId, + 'customerId' => $customer->getId(), + 'mollieCustomerId' => null, + 'mollieSubscriptionId' => null, + 'lastRemindedAt' => null, + 'canceledAt' => null, + 'status' => SubscriptionStatus::PENDING->value, + 'description' => $description, + 'amount' => $order->getAmountTotal(), + 'currencyId' => $order->getCurrencyId(), + 'metadata' => $this->getMetaDataArray($lineItem, $order->getOrderDate()), + 'orderId' => $order->getId(), + 'orderVersionId' => $order->getVersionId(), + 'salesChannelId' => $order->getSalesChannelId(), + 'totalRounding' => $totalRoundingValue, + 'itemRounding' => $itemRoundingValue, + 'order' => [ + 'id' => $order->getId(), + 'orderVersionId' => $order->getVersionId(), + 'tags' => [ + [ + 'id' => SubscriptionTag::ID + ] + ], + 'customFields' => [ + Mollie::EXTENSION => [ + 'swSubscriptionId' => $subscriptionId + ] + ] + ] + ]; + } + + /** + * @return array + */ + private function getAddressData(OrderAddressEntity $address, string $subscriptionId): array + { + $address = [ + 'subscriptionId' => $subscriptionId, + 'salutationId' => $address->getSalutationId(), + 'firstName' => $address->getFirstName(), + 'lastName' => $address->getLastName(), + 'company' => $address->getCompany(), + 'department' => $address->getDepartment(), + 'vatId' => $address->getVatId(), + 'street' => $address->getStreet(), + 'zipcode' => (string) $address->getZipcode(), + 'city' => $address->getCity(), + 'countryId' => $address->getCountryId(), + 'countryStateId' => $address->getCountryStateId(), + 'phoneNumber' => $address->getPhoneNumber(), + 'additionalAddressLine1' => $address->getAdditionalAddressLine1(), + 'additionalAddressLine2' => $address->getAdditionalAddressLine2(), + ]; + $address['id'] = Uuid::fromStringToHex(implode('-',array_values($address))); + + return $address; + } + + /** + * @return array + */ + private function getMetaDataArray(OrderLineItemEntity $lineItem, \DateTimeInterface $orderDate): array + { + /** @var ?Product $productExtension */ + $productExtension = $lineItem->getExtension(Mollie::EXTENSION); + if (! $productExtension instanceof Product) { + return []; + } + + $repetitions = 0; + $hasRepetitions = $productExtension->getRepetition() > 0; + if ($hasRepetitions) { + // Since we already paid once, we get then the next start date as first date and also reduce the amount of repetitions + $repetitions = $productExtension->getRepetition() - 1; + } + + $startDate = \DateTime::createFromFormat('Y-m-d', $orderDate->format('Y-m-d')); + + if (! $startDate instanceof \DateTimeInterface) { + throw new \RuntimeException('Failed to create date object'); + } + $interval = $productExtension->getInterval(); + + $startDate->modify('+' . (string) $interval); + $metaData = new SubscriptionMetadata($startDate->format('Y-m-d'), $interval->getIntervalValue(), $interval->getIntervalUnit(), $repetitions); + + return $metaData->toArray(); + } +} diff --git a/shopware/Component/Subscription/Subscriber/PendingSubscriptionSubscriber.php b/shopware/Component/Subscription/Subscriber/PendingSubscriptionSubscriber.php new file mode 100644 index 000000000..03792e097 --- /dev/null +++ b/shopware/Component/Subscription/Subscriber/PendingSubscriptionSubscriber.php @@ -0,0 +1,250 @@ +> $subscriptionRepository + */ + public function __construct( + #[Autowire(service: SettingsService::class)] + private readonly AbstractSettingsService $settingsService, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $subscriptionGateway, + #[Autowire(service: RouteBuilder::class)] + private RouteBuilderInterface $routeBuilder, + #[Autowire(service: 'mollie_subscription.repository')] + private EntityRepository $subscriptionRepository, + #[Autowire(service: 'event_dispatcher')] + private EventDispatcherInterface $eventDispatcher, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + } + + public static function getSubscribedEvents(): array + { + return [ + WebhookStatusPaidEvent::class => ['onPaidWebhook', self::PRIORITY], + WebhookStatusCancelledEvent::class => ['onCancelledWebhook', self::PRIORITY], + ]; + } + + public function onCancelledWebhook(WebhookStatusCancelledEvent $event): void + { + $order = $event->getOrder(); + + $subscriptionEntity = $this->getSubscription($order); + if (! $subscriptionEntity instanceof SubscriptionEntity) { + return; + } + + $subscriptionId = $subscriptionEntity->getId(); + $subscriptionStatus = $subscriptionEntity->getStatus(); + $orderNumber = (string) $order->getOrderNumber(); + + $logData = [ + 'orderNumber' => $orderNumber, + 'subscriptionId' => $subscriptionId, + 'subscriptionStatus' => $subscriptionStatus + ]; + + $this->logger->info('Payment was cancelled, cancel subscription', $logData); + + if ($subscriptionStatus !== SubscriptionStatus::PENDING->value) { + $this->logger->warning('Subscription is not pending, nothing to do', $logData); + + return; + } + + $newSubscriptionStatus = SubscriptionStatus::CANCELED->value; + $subscriptionData = [ + 'id' => $subscriptionId, + 'status' => $newSubscriptionStatus, + 'canceledAt' => (new \DateTime())->format('Y-m-d H:i:s'), + 'historyEntries' => [ + [ + 'statusFrom' => $subscriptionStatus, + 'statusTo' => $newSubscriptionStatus, + 'comment' => 'canceled' + ] + ] + ]; + + $context = $event->getContext(); + + $this->subscriptionRepository->upsert([$subscriptionData], $context); + } + + public function onPaidWebhook(WebhookStatusPaidEvent $event): void + { + $order = $event->getOrder(); + $payment = $event->getPayment(); + + $subscriptionEntity = $this->getSubscription($order); + if (! $subscriptionEntity instanceof SubscriptionEntity) { + return; + } + + $subscriptionId = $subscriptionEntity->getId(); + $subscriptionStatus = $subscriptionEntity->getStatus(); + $orderNumber = (string) $order->getOrderNumber(); + + $logData = [ + 'orderNumber' => $orderNumber, + 'subscriptionId' => $subscriptionId, + 'subscriptionStatus' => $subscriptionStatus + ]; + + $this->logger->info('Start finalize subscription', $logData); + + if ($subscriptionStatus !== SubscriptionStatus::PENDING->value) { + $this->logger->warning('Subscription is not pending, nothing to do', $logData); + + return; + } + + $mollieCustomerId = $payment->getCustomerId(); + + if ($mollieCustomerId === null) { + $this->logger->error('Failed to get mollie customer id from payment', $logData); + throw new \Exception('Failed to get mollie customer id'); + } + + $customer = $order->getOrderCustomer()?->getCustomer(); + if (! $customer instanceof CustomerEntity) { + $this->logger->error('Failed to get order customer', $logData); + throw new \Exception('Customer not loaded for Order'); + } + + $currency = $order->getCurrency(); + if ($currency === null) { + $this->logger->error('Currency is not set', $logData); + throw new \Exception('Currency is not set'); + } + + $mandateId = $payment->getMandateId(); + + if ($mandateId === null) { + $this->logger->error('Failed to get mollie mandate id from payment', $logData); + throw new \Exception('Failed to get mollie mandate id'); + } + + $context = $event->getContext(); + $subscription = $this->createSubscription($subscriptionEntity, $order, $currency, $mandateId, $logData, $mollieCustomerId, $context); + $nextPaymentDate = $subscription->getNextPaymentDate(); + if (! $nextPaymentDate instanceof \DateTimeInterface) { + $this->logger->error('Subscription created without next payment date', $logData); + throw new \Exception('Subscription created without next payment date'); + } + $newSubscriptionStatus = $subscription->getStatus()->value; + + $subscriptionData = [ + 'id' => $subscriptionId, + 'status' => $subscription->getStatus()->value, + 'mollieId' => $subscription->getId(), + 'mollieCustomerId' => $mollieCustomerId, + 'mandateId' => $mandateId, + 'nextPaymentAt' => $nextPaymentDate->format('Y-m-d'), + 'canceledAt' => null, + 'historyEntries' => [ + [ + 'statusFrom' => $subscriptionStatus, + 'statusTo' => $newSubscriptionStatus, + 'mollieId' => $subscription->getId(), + 'comment' => 'confirmed' + ] + ] + ]; + + $this->subscriptionRepository->upsert([$subscriptionData], $context); + $startedEvent = new SubscriptionStartedEvent($subscriptionEntity, $customer, $context); + $this->eventDispatcher->dispatch($startedEvent); + } + + /** + * @param array $logData + */ + private function createSubscription(SubscriptionEntity $subscriptionEntity, OrderEntity $order, CurrencyEntity $currency, string $mandateId, array $logData, string $mollieCustomerId, Context $context): Subscription + { + $metaData = $subscriptionEntity->getMetadata(); + $subscriptionId = $subscriptionEntity->getId(); + + $createSubscription = new CreateSubscription( + $subscriptionEntity->getDescription(), + $metaData->getInterval(), + new Money($order->getAmountTotal(), $currency->getIsoCode()) + ); + + $createSubscription->setWebhookUrl($this->routeBuilder->getSubscriptionWebhookUrl($subscriptionId)); + $createSubscription->setMandateId($mandateId); + $createSubscription->setStartDate($metaData->getStartDate()); + + $createSubscription->setMetadata([ + 'subscriptionId' => $subscriptionId, + ]); + + $repetition = (int) $metaData->getTimes(); + if ($repetition > 0) { + $createSubscription->setTimes($repetition); + } + + $orderNumber = (string) $order->getOrderNumber(); + $salesChannelId = $order->getSalesChannelId(); + + /** @var ModifyCreateSubscriptionPayloadEvent $event */ + $event = $this->eventDispatcher->dispatch(new ModifyCreateSubscriptionPayloadEvent($createSubscription, $context)); + $createSubscription = $event->getCreateSubscription(); + $logData['payload'] = $createSubscription->toArray(); + + $this->logger->info('Send create subscription payload to mollie API', $logData); + + return $this->subscriptionGateway->createSubscription($createSubscription, $mollieCustomerId, $orderNumber, $salesChannelId); + } + + private function getSubscription(OrderEntity $order): ?SubscriptionEntity + { + $salesChannelId = $order->getSalesChannelId(); + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($salesChannelId); + if (! $subscriptionSettings->isEnabled()) { + return null; + } + + $subscriptionCollection = $order->getExtension('mollieSubscriptions'); + if (! $subscriptionCollection instanceof SubscriptionCollection) { + return null; + } + + return $subscriptionCollection->first(); + } +} diff --git a/shopware/Component/Subscription/SubscriptionActionHandler.php b/shopware/Component/Subscription/SubscriptionActionHandler.php new file mode 100644 index 000000000..76254e7ca --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionActionHandler.php @@ -0,0 +1,129 @@ + $actions + */ + public function __construct( + #[Autowire(service: SettingsService::class)] + private readonly AbstractSettingsService $settingsService, + #[Autowire(service: SubscriptionGateway::class)] + private readonly SubscriptionGatewayInterface $subscriptionGateway, + #[Autowire(service: SubscriptionDataService::class)] + private readonly SubscriptionDataServiceInterface $subscriptionDataService, + #[AutowireIterator('mollie.subscription.action')] + iterable $actions, + #[Autowire(service: 'event_dispatcher')] + private readonly EventDispatcherInterface $eventDispatcher, + #[Autowire(service: 'monolog.logger.mollie')] + private readonly LoggerInterface $logger + ) { + foreach ($actions as $action) { + $this->registerAction($action); + } + } + + public function handle(string $action, string $subscriptionId, Context $context): Subscription + { + $logData = [ + 'subscriptionId' => $subscriptionId, + 'action' => $action, + ]; + + $subscriptionId = strtolower($subscriptionId); + $this->logger->debug('Subscription Action Handler called', $logData); + + $subscriptionData = $this->subscriptionDataService->findById($subscriptionId, $context); + + $order = $subscriptionData->getOrder(); + + $subscriptionEntity = $subscriptionData->getSubscription(); + $mollieSubscriptionId = $subscriptionEntity->getMollieId(); + $mollieCustomerId = $subscriptionEntity->getMollieCustomerId(); + $salesChannelId = $subscriptionEntity->getSalesChannelId(); + $orderNumber = (string) $order->getOrderNumber(); + $customer = $subscriptionData->getCustomer(); + + $logData = array_merge($logData, [ + 'mollieSubscriptionId' => $mollieSubscriptionId, + 'mollieCustomerId' => $mollieCustomerId, + 'salesChannelId' => $salesChannelId, + 'orderNumber' => $orderNumber, + ]); + + $this->logger->info('Subscription Action Handler - Started', $logData); + + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($salesChannelId); + if (! $subscriptionSettings->isEnabled()) { + $this->logger->error('Subscription Action Handler - Failed to execute subscription action, subscriptions disabled for saleschannel', $logData); + throw new SubscriptionDisabledException($salesChannelId); + } + + $foundAction = null; + + foreach ($this->actions as $actionHandler) { + if ($actionHandler->supports($action)) { + $foundAction = $actionHandler; + break; + } + } + + if ($foundAction === null) { + $this->logger->error('Subscription Action Handler - No action handler found for action', $logData); + throw new \Exception('No action handler found for action: ' . $action); + } + + $mollieSubscription = $this->subscriptionGateway->getSubscription($mollieSubscriptionId, $mollieCustomerId, $orderNumber, $salesChannelId); + $mollieSubscription = $foundAction->execute($subscriptionData, $subscriptionSettings, $mollieSubscription, $orderNumber, $context); + + $event = $foundAction->getEvent($subscriptionEntity, $customer, $context); + $logData['event'] = get_class($event); + + $this->eventDispatcher->dispatch($event); + + $this->logger->info('Subscription Action Handler - Finished', $logData); + + return $mollieSubscription; + } + + /** + * @return array> + */ + public function getActionEvents(): array + { + $result = []; + foreach ($this->actions as $action) { + $result[] = $action->getEventClass(); + } + + return $result; + } + + private function registerAction(AbstractAction $action): void + { + $this->actions[] = $action; + } +} diff --git a/shopware/Component/Subscription/SubscriptionDataService.php b/shopware/Component/Subscription/SubscriptionDataService.php new file mode 100644 index 000000000..b5458fe43 --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionDataService.php @@ -0,0 +1,100 @@ +> $subscriptionRepository + */ + public function __construct( + #[Autowire(service: 'mollie_subscription.repository')] + private EntityRepository $subscriptionRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + } + + public function findById(string $subscriptionId, Context $context): SubscriptionDataStruct + { + $logData = [ + 'subscriptionId' => $subscriptionId, + ]; + + $criteria = new Criteria([$subscriptionId]); + $criteria->addAssociation('billingAddress'); + $criteria->addAssociation('shippingAddress'); + $criteria->addAssociation('order.transactions'); + $criteria->addAssociation('order.lineItems'); + $criteria->addAssociation('order.deliveries.positions.orderLineItem'); + $criteria->addAssociation('order.deliveries.shippingMethod'); + $criteria->addAssociation('order.deliveries.shippingOrderAddress.country'); + $criteria->addAssociation('order.orderCustomer.customer'); + $criteria->getAssociation('order.transactions') + ->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING)) + ->setLimit(1) + ; + + $criteria->setLimit(1); + + $searchResult = $this->subscriptionRepository->search($criteria, $context); + + $subscriptionEntity = $searchResult->first(); + if (! $subscriptionEntity instanceof SubscriptionEntity) { + $this->logger->error('Subscription was not found', $logData); + throw new SubscriptionNotFoundException($subscriptionId); + } + + $order = $subscriptionEntity->getOrder(); + if (! $order instanceof OrderEntity) { + $this->logger->error('Subscription without order loaded', $logData); + throw new SubscriptionWithoutOrderException($subscriptionId); + } + $orderNumber = (string) $order->getOrderNumber(); + $orderId = $order->getId(); + + $logData['orderNumber'] = $orderNumber; + + $customer = $order->getOrderCustomer()?->getCustomer(); + if (! $customer instanceof CustomerEntity) { + $this->logger->error('Subscription order has no customer', $logData); + throw new OrderWithoutCustomerException($orderId); + } + + $subscriptionBillingAddress = $subscriptionEntity->getBillingAddress(); + if (! $subscriptionBillingAddress instanceof SubscriptionAddressEntity) { + $this->logger->error('Subscription billing address was not found', $logData); + throw new SubscriptionWithoutAddressException($subscriptionId); + } + $subscriptionShippingAddress = $subscriptionEntity->getShippingAddress(); + if (! $subscriptionShippingAddress instanceof SubscriptionAddressEntity) { + $this->logger->error('Subscription shipping address was not found', $logData); + throw new SubscriptionWithoutAddressException($subscriptionId); + } + + return new SubscriptionDataStruct( + $subscriptionEntity, + $order, + $customer, + $subscriptionBillingAddress, + $subscriptionShippingAddress + ); + } +} diff --git a/shopware/Component/Subscription/SubscriptionDataServiceInterface.php b/shopware/Component/Subscription/SubscriptionDataServiceInterface.php new file mode 100644 index 000000000..e12083afa --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionDataServiceInterface.php @@ -0,0 +1,11 @@ +subscription; + } + + public function getOrder(): OrderEntity + { + return $this->order; + } + + public function getCustomer(): CustomerEntity + { + return $this->customer; + } + + public function getBillingAddress(): SubscriptionAddressEntity + { + return $this->billingAddress; + } + + public function getShippingAddress(): SubscriptionAddressEntity + { + return $this->shippingAddress; + } +} diff --git a/shopware/Component/Subscription/SubscriptionMetadata.php b/shopware/Component/Subscription/SubscriptionMetadata.php new file mode 100644 index 000000000..218e48f5c --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionMetadata.php @@ -0,0 +1,114 @@ + $metadata + */ + public static function fromArray(array $metadata): SubscriptionMetadata + { + $startDate = $metadata['start_date'] ?? ''; + $intervalValue = $metadata['interval_value'] ?? 0; + $intervalUnit = IntervalUnit::from($metadata['interval_unit'] ?? ''); + $times = $metadata['times'] ?? 0; + $tmpTransactionId = $metadata['tmp_transaction'] ?? ''; + $nextPossiblePaymentDate = $metadata['nextPossiblePaymentDate'] ?? ''; + + return new SubscriptionMetadata( + $startDate, + $intervalValue, + $intervalUnit, + $times, + $tmpTransactionId, + $nextPossiblePaymentDate + ); + } + + public function getInterval(): Interval + { + return new Interval($this->intervalValue, $this->intervalUnit); + } + + /** + * @return array + */ + public function toArray(): array + { + $data = [ + 'start_date' => $this->startDate, + 'interval_value' => $this->intervalValue, + 'interval_unit' => $this->intervalUnit->value, + 'times' => $this->times, + 'nextPossiblePaymentDate' => $this->nextPossiblePaymentDate, + ]; + + if (strlen($this->tmpTransactionId) > 0) { + $data['tmp_transaction'] = $this->tmpTransactionId; + } + + return $data; + } + + public function getStartDate(): string + { + return $this->startDate; + } + + public function getIntervalValue(): int + { + return $this->intervalValue; + } + + public function getIntervalUnit(): IntervalUnit + { + return $this->intervalUnit; + } + + public function getTimes(): int + { + return $this->times; + } + + public function getTmpTransaction(): string + { + return $this->tmpTransactionId; + } + + public function setTmpTransaction(string $tmpTransaction): void + { + $this->tmpTransactionId = $tmpTransaction; + } + + public function setNextPossiblePaymentDate(string $nextPossiblePaymentDate): void + { + $this->nextPossiblePaymentDate = $nextPossiblePaymentDate; + } + + public function getNextPossiblePaymentDate(): \DateTimeInterface + { + if ($this->nextPossiblePaymentDate === '') { + return new \DateTime(); + } + $nextPossiblePaymentDate = \DateTime::createFromFormat('Y-m-d', $this->nextPossiblePaymentDate); + if (! $nextPossiblePaymentDate instanceof \DateTimeInterface) { + throw new \RuntimeException('Invalid next possible payment date format: ' . $this->nextPossiblePaymentDate); + } + + return $nextPossiblePaymentDate; + } +} diff --git a/shopware/Component/Subscription/SubscriptionRemover.php b/shopware/Component/Subscription/SubscriptionRemover.php new file mode 100644 index 000000000..a62e6e434 --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionRemover.php @@ -0,0 +1,87 @@ +> $orderRepository + */ + public function __construct( + private CartService $cartService, + #[Autowire(service: 'order.repository')] + private EntityRepository $orderRepository, + private PaymentHandlerLocator $paymentHandlerLocator, + private LineItemAnalyzer $lineItemAnalyzer, + #[Autowire(service: SettingsService::class)] + private AbstractSettingsService $settingsService, + ) { + } + + public function remove(PaymentMethodCollection $paymentMethods, string $orderId, SalesChannelContext $salesChannelContext): PaymentMethodCollection + { + $subscriptionSettings = $this->settingsService->getSubscriptionSettings($salesChannelContext->getSalesChannelId()); + if (! $subscriptionSettings->isEnabled()) { + return $paymentMethods; + } + $hasSubscriptionProducts = false; + if (mb_strlen($orderId) === 0) { + $cart = $this->cartService->getCart($salesChannelContext->getToken(), $salesChannelContext); + $hasSubscriptionProducts = $this->hasSubscriptionProductInCart($cart); + } else { + $criteria = new Criteria([$orderId]); + $criteria->addAssociation('lineItems'); + $orderSearchResult = $this->orderRepository->search($criteria, $salesChannelContext->getContext()); + $orderEntity = $orderSearchResult->first(); + if ($orderEntity instanceof OrderEntity) { + $hasSubscriptionProducts = $this->hasSubscriptionProductInOrder($orderEntity); + } + } + if (! $hasSubscriptionProducts) { + return $paymentMethods; + } + + foreach ($paymentMethods as $paymentMethod) { + $paymentMethodHandler = $this->paymentHandlerLocator->findByIdentifier($paymentMethod->getHandlerIdentifier()); + if (! $paymentMethodHandler instanceof SubscriptionAwareInterface) { + $paymentMethods->remove($paymentMethod->getId()); + } + } + + return $paymentMethods; + } + + private function hasSubscriptionProductInCart(Cart $cart): bool + { + $lineItems = new LineItemCollection($cart->getLineItems()->getFlat()); + + return $this->lineItemAnalyzer->hasSubscriptionProduct($lineItems); + } + + private function hasSubscriptionProductInOrder(OrderEntity $order): bool + { + $lineItems = $order->getLineItems(); + if ($lineItems === null) { + return false; + } + + return $this->lineItemAnalyzer->hasSubscriptionProduct($lineItems); + } +} diff --git a/shopware/Component/Subscription/SubscriptionTag.php b/shopware/Component/Subscription/SubscriptionTag.php new file mode 100644 index 000000000..8cf2ca6a7 --- /dev/null +++ b/shopware/Component/Subscription/SubscriptionTag.php @@ -0,0 +1,10 @@ + - - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Component/Transaction/TransactionConverter.php b/shopware/Component/Transaction/TransactionConverter.php index bc5451a79..6d3713b8d 100644 --- a/shopware/Component/Transaction/TransactionConverter.php +++ b/shopware/Component/Transaction/TransactionConverter.php @@ -5,7 +5,6 @@ use Kiener\MolliePayments\Service\OrderService; use Kiener\MolliePayments\Service\TransactionService; -use Shopware\Core\Checkout\Payment\Cart\AsyncPaymentTransactionStruct; use Shopware\Core\Checkout\Payment\Cart\PaymentTransactionStruct as ShopwarePaymentTransactionStruct; use Shopware\Core\Framework\Context; @@ -18,41 +17,21 @@ final class TransactionConverter implements TransactionConverterInterface private OrderService $orderService; private TransactionService $transactionService; - public function __construct(OrderService $orderService, TransactionService $transactionService) + public function __construct( + OrderService $orderService, + TransactionService $transactionService) { $this->orderService = $orderService; $this->transactionService = $transactionService; } - /** - * @param AsyncPaymentTransactionStruct|ShopwarePaymentTransactionStruct $transactionStruct - */ - public function convert($transactionStruct, Context $context): PaymentTransactionStruct + public function convert(ShopwarePaymentTransactionStruct $transactionStruct, Context $context): PaymentTransactionStruct { - $orderTransactionId = $this->getTransactionId($transactionStruct); + $orderTransactionId = $transactionStruct->getOrderTransactionId(); $transaction = $this->transactionService->getTransactionById($orderTransactionId, $context->getVersionId(), $context); $order = $this->orderService->getOrder($transaction->getOrderId(), $context); return new PaymentTransactionStruct($orderTransactionId, (string) $transactionStruct->getReturnUrl(), $order, $transaction); } - - /** - * @param AsyncPaymentTransactionStruct|ShopwarePaymentTransactionStruct $transactionStruct - */ - private function getTransactionId($transactionStruct): string - { - $orderTransactionId = null; - if ($transactionStruct instanceof ShopwarePaymentTransactionStruct) { - $orderTransactionId = $transactionStruct->getOrderTransactionId(); - } - if ($transactionStruct instanceof AsyncPaymentTransactionStruct) { - $orderTransactionId = $transactionStruct->getOrderTransaction()->getId(); - } - if ($orderTransactionId === null) { - throw new \Exception(sprintf('Invalid transaction struct. OrderTransaction Id could not be found in class %s', get_class($transactionStruct))); - } - - return $orderTransactionId; - } } diff --git a/shopware/Component/Transaction/TransactionConverterInterface.php b/shopware/Component/Transaction/TransactionConverterInterface.php index 0c2494f0e..4b97e4c8c 100644 --- a/shopware/Component/Transaction/TransactionConverterInterface.php +++ b/shopware/Component/Transaction/TransactionConverterInterface.php @@ -8,8 +8,5 @@ interface TransactionConverterInterface { - /** - * @param AsyncPaymentTransactionStruct|ShopwarePaymentTransactionStruct $transactionStruct - */ - public function convert($transactionStruct, Context $context): PaymentTransactionStruct; + public function convert(ShopwarePaymentTransactionStruct $transactionStruct, Context $context): PaymentTransactionStruct; } diff --git a/shopware/Component/Transaction/TransactionDataException.php b/shopware/Component/Transaction/TransactionDataException.php new file mode 100644 index 000000000..04e5b5055 --- /dev/null +++ b/shopware/Component/Transaction/TransactionDataException.php @@ -0,0 +1,117 @@ + $transactionId], + $exception + ); + } + + public static function oderNotExists(string $transactionId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::TRANSACTION_ORDER_NOT_FOUND, + 'Transaction {{transactionId}} does not have an Order in Shopware', + ['transactionId' => $transactionId], + $exception + ); + } + + public static function orderWithoutDeliveries(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_WITHOUT_DELIVERIES, + 'Order {{orderId}} does not have delivery addresses in Shopware', + ['orderId' => $orderId], + $exception + ); + } + + public static function orderWithoutLanguage(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_WITHOUT_LANGUAGE, + 'Order {{orderId}} does not have language in Shopware', + ['orderId' => $orderId], + $exception + ); + } + + public static function orderWithoutCurrency(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_WITHOUT_CURRENCY, + 'Order {{orderId}} does not have a currency in Shopware', + ['orderId' => $orderId], + $exception + ); + } + + public static function orderDeliveryWithoutShippingAddress(string $orderId, string $deliveryAddressId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_DELIVERY_WITHOUT_ADDRESS, + 'Delivery address {{deliveryAddressId}} from order {{orderId}} without shipping address in Shopware', + ['orderId' => $orderId, 'deliveryAddressId' => $deliveryAddressId], + $exception + ); + } + + public static function orderWithoutCustomer(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_DELIVERY_WITHOUT_ADDRESS, + 'Order {{orderId}} does not have a customer in Shopware', + ['orderId' => $orderId], + $exception + ); + } + + public static function orderWithoutSalesChannel(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_DELIVERY_WITHOUT_ADDRESS, + 'Order {{orderId}} does not have a sales channel in Shopware', + ['orderId' => $orderId], + $exception + ); + } + + public static function orderWithoutBillingAddress(string $orderId, ?\Throwable $exception = null): self + { + return new self( + Response::HTTP_UNPROCESSABLE_ENTITY, + self::ORDER_WITHOUT_BILLING_ADDRESS, + 'Order {{orderId}} does not have a billing address in Shopware', + ['orderId' => $orderId], + $exception + ); + } +} diff --git a/shopware/Component/Transaction/TransactionDataStruct.php b/shopware/Component/Transaction/TransactionDataStruct.php new file mode 100644 index 000000000..538186a24 --- /dev/null +++ b/shopware/Component/Transaction/TransactionDataStruct.php @@ -0,0 +1,74 @@ +transaction; + } + + public function getOrder(): OrderEntity + { + return $this->order; + } + + public function getSalesChannel(): SalesChannelEntity + { + return $this->salesChannel; + } + + public function getCustomer(): CustomerEntity + { + return $this->customer; + } + + public function getShippingOrderAddress(): OrderAddressEntity + { + return $this->shippingOrderAddress; + } + + public function getBillingOrderAddress(): OrderAddressEntity + { + return $this->billingOrderAddress; + } + + public function getCurrency(): CurrencyEntity + { + return $this->currency; + } + + public function getLanguage(): LanguageEntity + { + return $this->language; + } + + public function getDeliveries(): OrderDeliveryCollection + { + return $this->deliveries; + } +} diff --git a/shopware/Component/Transaction/TransactionService.php b/shopware/Component/Transaction/TransactionService.php new file mode 100644 index 000000000..489d651a0 --- /dev/null +++ b/shopware/Component/Transaction/TransactionService.php @@ -0,0 +1,155 @@ +> $orderTransactionRepository + */ + public function __construct( + #[Autowire(service: 'order_transaction.repository')] + private EntityRepository $orderTransactionRepository, + #[Autowire(service: 'monolog.logger.mollie')] + private LoggerInterface $logger + ) { + } + + public function findById(string $transactionId, Context $context): TransactionDataStruct + { + $criteria = new Criteria([$transactionId]); + $criteria->addAssociation('order.orderCustomer.salutation'); + $criteria->addAssociation('order.orderCustomer.customer.salutation'); + $criteria->addAssociation('order.orderCustomer.customer.country'); + $criteria->addAssociation('order.addresses.country'); + $criteria->addAssociation('order.primaryOrderDelivery.shippingOrderAddress.country'); + $criteria->addAssociation('order.deliveries.shippingOrderAddress.country'); + $criteria->addAssociation('order.deliveries.shippingMethod'); + $criteria->addAssociation('order.billingAddress.country'); + $criteria->addAssociation('order.language.locale'); + $criteria->addAssociation('order.customer.language'); + $criteria->addAssociation('order.currency'); + $criteria->addAssociation('order.salesChannel'); + $criteria->addAssociation('order.lineItems.product.media'); + $criteria->addAssociation('order.stateMachineState.stateMachine'); + $criteria->addAssociation('order.mollieSubscriptions'); + $criteria->addAssociation('paymentMethod'); + + $searchResult = $this->orderTransactionRepository->search($criteria, $context); + $transactionEntity = $searchResult->first(); + + if (! $transactionEntity instanceof OrderTransactionEntity) { + throw TransactionDataException::transactionNotFound($transactionId); + } + + $order = $transactionEntity->getOrder(); + if (! $order instanceof OrderEntity) { + throw TransactionDataException::oderNotExists($transactionId); + } + $salesChannel = $order->getSalesChannel(); + if (! $salesChannel instanceof SalesChannelEntity) { + throw TransactionDataException::orderWithoutSalesChannel($order->getId()); + } + $deliveries = $order->getDeliveries(); + if (! $deliveries instanceof OrderDeliveryCollection) { + throw TransactionDataException::orderWithoutDeliveries($order->getId()); + } + /** @var ?OrderDeliveryEntity $firstDeliveryLine */ + $firstDeliveryLine = $deliveries->first(); + + if (method_exists($order,'getPrimaryOrderDelivery')) { + $firstDeliveryLine = $order->getPrimaryOrderDelivery(); + } + + if (! $firstDeliveryLine instanceof OrderDeliveryEntity) { + throw TransactionDataException::orderWithoutDeliveries($order->getId()); + } + + $language = $order->getLanguage(); + if (! $language instanceof LanguageEntity) { + throw TransactionDataException::orderWithoutLanguage($order->getId()); + } + + $currency = $order->getCurrency(); + if (! $currency instanceof CurrencyEntity) { + throw TransactionDataException::orderWithoutCurrency($order->getId()); + } + + $shippingOrderAddress = $firstDeliveryLine->getShippingOrderAddress(); + if (! $shippingOrderAddress instanceof OrderAddressEntity) { + throw TransactionDataException::orderDeliveryWithoutShippingAddress($order->getId(), $firstDeliveryLine->getId()); + } + $billingAddress = $order->getBillingAddress(); + if (! $billingAddress instanceof OrderAddressEntity) { + throw TransactionDataException::orderWithoutBillingAddress($order->getId()); + } + $orderCustomer = $order->getOrderCustomer(); + if (! $orderCustomer instanceof OrderCustomerEntity) { + throw TransactionDataException::orderWithoutCustomer($order->getId()); + } + $customer = $orderCustomer->getCustomer(); + if (! $customer instanceof CustomerEntity) { + throw TransactionDataException::orderWithoutCustomer($order->getId()); + } + + return new TransactionDataStruct( + $transactionEntity, + $order, + $salesChannel, + $customer, + $shippingOrderAddress, + $billingAddress, + $currency, + $language, + $deliveries + ); + } + + public function savePaymentExtension(string $transactionId,OrderEntity $order, Payment $payment, Context $context): EntityWrittenContainerEvent + { + $salesChannel = $order->getSalesChannelId(); + $orderNumber = $order->getOrderNumber(); + + $this->logger->debug('Save payment information in Order Transaction', [ + 'transactionId' => $transactionId, + 'data' => $payment->toArray(), + 'orderNumber' => $orderNumber, + 'salesChannelId' => $salesChannel, + ]); + + return $this->orderTransactionRepository->upsert([ + [ + 'id' => $transactionId, + 'customFields' => [ + Mollie::EXTENSION => $payment->toArray() + ] + ] + ], $context); + } +} diff --git a/shopware/Component/Transaction/TransactionServiceInterface.php b/shopware/Component/Transaction/TransactionServiceInterface.php new file mode 100644 index 000000000..0d1ca715a --- /dev/null +++ b/shopware/Component/Transaction/TransactionServiceInterface.php @@ -0,0 +1,16 @@ + + */ private array $keyMappings = [ 'card.payments.shopwareFailedPayments.label' => 'card.payments.shopwareFailedPayment.label', 'card.payments.shopwareFailedPayments.helpText' => 'card.payments.shopwareFailedPayment.helpText', @@ -26,9 +35,15 @@ final class ImportCSVCommand extends Command 'card.subscriptions.subscriptionsSkipRenewalsOnFailedPayments.helpText' => 'card.subscriptions.subscriptionSkipRenewalsOnFailedPayments.helpText', ]; - public function __construct(Filesystem $fileSystem, AppenderInterface $appender, Plugin $plugin) + public function __construct( + #[Autowire(service: 'shopware.filesystem.private')] + Filesystem $fileSystem, + #[Autowire(service: TranslationAppender::class)] + AppenderInterface $appender, + #[Autowire(service: MolliePayments::class)] + Plugin $plugin) { - parent::__construct('mollie:translation:import'); + parent::__construct(); $this->fileSystem = $fileSystem; $this->appender = $appender; $this->plugin = $plugin; @@ -58,15 +73,22 @@ protected function execute(InputInterface $input, OutputInterface $output): int return Command::FAILURE; } + $fileContent = file_get_contents($pathToConfigXml); + + if ($fileContent === false) { + $output->writeln('Config file not found: ' . $path . ''); + + return Command::FAILURE; + } $stream = $this->fileSystem->readStream($path); $domDocument = new \DOMDocument(); - $domDocument->loadXML(file_get_contents($pathToConfigXml)); + $domDocument->loadXML($fileContent); $row = fgetcsv($stream, null, ';'); // skip header while ($row = fgetcsv($stream, null, ';')) { - $key = $row[0]; + $key = (string) $row[0]; $key = $this->keyMappings[$key] ?? $key; - $text = $row[2]; + $text = (string) $row[2]; $result = $this->appender->append($domDocument, $key, $text, $localeCode); $output->writeln('<' . $result->getStatus() . '>' . $result->getMessage() . 'getStatus() . '>'); } diff --git a/shopware/Component/TranslationImporter/Resources/config/services.xml b/shopware/Component/TranslationImporter/Resources/config/services.xml deleted file mode 100644 index dc97ab5bd..000000000 --- a/shopware/Component/TranslationImporter/Resources/config/services.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Component/TranslationImporter/TranslationAppender.php b/shopware/Component/TranslationImporter/TranslationAppender.php index fa1d9b78a..ae4810381 100644 --- a/shopware/Component/TranslationImporter/TranslationAppender.php +++ b/shopware/Component/TranslationImporter/TranslationAppender.php @@ -35,7 +35,9 @@ public function append(\DOMDocument $config, string $key, string $text, string $ foreach ($searchParts as $searchPart) { $result = $domXpath->query($path . '/' . $searchPart); - + if ($result === false) { + continue; + } if ($result->count() === 0) { continue; } @@ -46,20 +48,20 @@ public function append(\DOMDocument $config, string $key, string $text, string $ $replaceXpathQuery = $path . '/' . $lastKeyPart . '[@lang="' . $languageCode . '"]'; $domElement = $domXpath->query($replaceXpathQuery); - if ($domElement->count() === 0) { + if ($domElement !== false && $domElement->count() === 0) { $replaceXpathQuery = $path . '/following-sibling::' . $lastKeyPart . '[@lang="' . $languageCode . '"]'; $domElement = $domXpath->query($replaceXpathQuery); - if ($domElement->count() === 0) { + if ($domElement !== false && $domElement->count() === 0) { $replaceXpathQuery = $path . '/following::' . $lastKeyPart . '[@lang="' . $languageCode . '"]'; $domElement = $domXpath->query($replaceXpathQuery); } } - if ($domElement->count() === 1) { + if ($domElement !== false && $domElement->count() === 1) { $oldElement = $domElement->item(0); - if ($oldElement !== null) { + if ($oldElement instanceof \DOMNode) { $textElement = $oldElement->firstChild; if ($textElement instanceof \DOMText) { $textElement->data = $text; @@ -72,7 +74,7 @@ public function append(\DOMDocument $config, string $key, string $text, string $ $domElement = $domXpath->query($path); // we expect to find exactly one node, not multiple - if ($domElement->count() === 0) { + if ($domElement === false || $domElement->count() === 0) { return new AppenderResult(sprintf('Failed to find entry for key "%s" with the path "%s"', $key, $path), AppenderResult::STATUS_ERROR); } @@ -84,21 +86,26 @@ public function append(\DOMDocument $config, string $key, string $text, string $ $targetChildren = $domXpath->query($targetNodePath); - if ($targetChildren->count() === 0) { + if ($targetChildren !== false && $targetChildren->count() === 0) { $targetNodePath = $path . '/following-sibling::' . $lastKeyPart . '[last()]'; } $targetChildren = $domXpath->query($targetNodePath); - if ($targetChildren->count() === 1) { + if ($targetChildren !== false && $targetChildren->count() === 1) { + /** @var \DOMNode $targetNode */ $targetNode = $targetChildren->item(0); - $targetNode->parentNode->insertBefore($newNode, $targetNode->nextSibling); + /** @var \DOMNode $parentNode */ + $parentNode = $targetNode->parentNode; + $parentNode->insertBefore($newNode, $targetNode->nextSibling); return new AppenderResult(sprintf('Appended "%s" with the key %s', $text, $key)); } - if ($targetChildren->count() === 0) { - $domElement->item(0)->appendChild($newNode); + if ($targetChildren !== false && $targetChildren->count() === 0) { + /** @var \DOMNode $firstNode */ + $firstNode = $domElement->item(0); + $firstNode->appendChild($newNode); } return new AppenderResult(sprintf('Created new entry "%s" with the key %s', $text, $key)); diff --git a/shopware/Entity/Cart/MollieShopwareCart.php b/shopware/Entity/Cart/MollieShopwareCart.php index 1287e4094..9bac03e8a 100644 --- a/shopware/Entity/Cart/MollieShopwareCart.php +++ b/shopware/Entity/Cart/MollieShopwareCart.php @@ -6,18 +6,18 @@ use Kiener\MolliePayments\Service\CustomFieldsInterface; use Shopware\Core\Checkout\Cart\Cart; use Shopware\Core\Framework\Struct\ArrayStruct; -use Shopware\Core\Framework\Struct\Struct; class MollieShopwareCart { private Cart $cart; - private ?Struct $cartExtension; + private ArrayStruct $cartExtension; public function __construct(Cart $cart) { $this->cart = $cart; - $this->cartExtension = $cart->getExtension(CustomFieldsInterface::MOLLIE_KEY); + $extension = $cart->getExtension(CustomFieldsInterface::MOLLIE_KEY) ?? new ArrayStruct(); + $this->cartExtension = new ArrayStruct($extension->getVars()); } public function getCart(): Cart @@ -42,7 +42,7 @@ public function isDataProtectionAccepted(): int public function setDataProtectionAccepted(int $accepted): void { - $this->cartExtension[CustomFieldsInterface::ACCEPTED_DATA_PROTECTION] = $accepted; + $this->setExtensionKey(CustomFieldsInterface::ACCEPTED_DATA_PROTECTION, (string) $accepted); } // @@ -100,12 +100,13 @@ public function clearPayPalExpress(): void // + /** + * @param mixed $defaultValue + * + * @return mixed + */ private function getExtensionKey(string $key, $defaultValue) { - if (! $this->cartExtension instanceof Struct) { - return $defaultValue; - } - if (! array_key_exists($key, $this->cartExtension->getVars())) { return $defaultValue; } @@ -113,7 +114,7 @@ private function getExtensionKey(string $key, $defaultValue) return $this->cartExtension[$key]; } - private function setExtensionKey(string $key, string $value): void + private function setExtensionKey(string $key,string $value): void { $this->prepareExtension(); @@ -122,10 +123,6 @@ private function setExtensionKey(string $key, string $value): void private function clearExtensionKey(string $key): void { - if (! $this->cartExtension instanceof Struct) { - return; - } - if (! array_key_exists($key, $this->cartExtension->getVars())) { return; } @@ -135,12 +132,6 @@ private function clearExtensionKey(string $key): void private function prepareExtension(): void { - if ($this->cartExtension instanceof Struct) { - return; - } - - $this->cartExtension = new ArrayStruct([]); - $this->cart->addExtension(CustomFieldsInterface::MOLLIE_KEY, $this->cartExtension); } } diff --git a/shopware/Entity/Customer/Customer.php b/shopware/Entity/Customer/Customer.php new file mode 100644 index 000000000..7c0bc7afa --- /dev/null +++ b/shopware/Entity/Customer/Customer.php @@ -0,0 +1,45 @@ + $customerIds + */ + public function __construct(private array $customerIds = []) + { + } + + /** + * @return array + */ + public function getCustomerIds(): array + { + return $this->customerIds; + } + + public function setCustomerId(string $profileId, Mode $mode, string $customerId): void + { + $this->customerIds[$profileId][$mode->value] = $customerId; + } + + public function getForProfileId(string $profileId, Mode $mode): ?string + { + return $this->customerIds[$profileId][$mode->value] ?? null; + } + + /** + * @return array + */ + public function toArray(): array + { + return [ + 'customer_ids' => $this->customerIds, + ]; + } +} diff --git a/shopware/Entity/PaymentMethod/PaymentMethod.php b/shopware/Entity/PaymentMethod/PaymentMethod.php new file mode 100644 index 000000000..02193a158 --- /dev/null +++ b/shopware/Entity/PaymentMethod/PaymentMethod.php @@ -0,0 +1,24 @@ +paymentMethod; + } + + public function getId(): string + { + return $this->id; + } +} diff --git a/shopware/Entity/Product/Product.php b/shopware/Entity/Product/Product.php new file mode 100644 index 000000000..cc879ece7 --- /dev/null +++ b/shopware/Entity/Product/Product.php @@ -0,0 +1,104 @@ +voucherCategories = new VoucherCategoryCollection(); + } + + public function getVoucherCategories(): VoucherCategoryCollection + { + return $this->voucherCategories; + } + + public function setVoucherCategories(VoucherCategoryCollection $voucherCategories): void + { + $this->voucherCategories = $voucherCategories; + } + + public function isSubscription(): bool + { + return $this->isSubscription; + } + + public function setIsSubscription(bool $isSubscription): void + { + $this->isSubscription = $isSubscription; + } + + public function getInterval(): Interval + { + return $this->interval; + } + + public function setInterval(Interval $interval): void + { + $this->interval = $interval; + } + + public function getRepetition(): int + { + return $this->repetition; + } + + public function setRepetition(int $repetition): void + { + $this->repetition = $repetition; + } + + /** + * @param array $customFields + */ + public static function createFromCustomFields(array $customFields): Product + { + $productExtension = new Product(); + $voucherTypes = $customFields['mollie_payments_product_voucher_type'] ?? null; + + if ($voucherTypes !== null) { + if (! is_array($voucherTypes)) { + $voucherTypes = [$voucherTypes]; + } + + $collection = new VoucherCategoryCollection(); + foreach ($voucherTypes as $voucherType) { + $voucher = VoucherCategory::tryFromNumber((int) $voucherType); + if ($voucher === null) { + continue; + } + $collection->add($voucher); + } + + if ($collection->count() > 0) { + $productExtension->setVoucherCategories($collection); + } + } + + $subscriptionEnabled = $customFields['mollie_payments_product_subscription_enabled'] ?? false; + $subscriptionInterval = $customFields['mollie_payments_product_subscription_interval'] ?? 0; + $subscriptionUnit = $customFields['mollie_payments_product_subscription_interval_unit'] ?? ''; + if ((bool) $subscriptionEnabled && (int) $subscriptionInterval > 0 && mb_strlen($subscriptionUnit) > 0) { + $subscriptionRepetitions = $customFields['mollie_payments_product_subscription_repetition'] ?? 0; + $productExtension->setIsSubscription(true); + $productExtension->setInterval(new Interval($subscriptionInterval,IntervalUnit::from($subscriptionUnit))); + $productExtension->setRepetition((int) $subscriptionRepetitions); + } + + return $productExtension; + } +} diff --git a/shopware/Mollie.php b/shopware/Mollie.php new file mode 100644 index 000000000..c5bd829ea --- /dev/null +++ b/shopware/Mollie.php @@ -0,0 +1,9 @@ + */ - private $orderTransactionRepository; + /** @var EntityRepository> */ + private EntityRepository $orderTransactionRepository; private LoggerInterface $logger; /** - * @param EntityRepository $orderTransactionRepository + * @param EntityRepository> $orderTransactionRepository */ - public function __construct($orderTransactionRepository, LoggerInterface $logger) + public function __construct( + #[Autowire(service: 'order_transaction.repository')] + EntityRepository $orderTransactionRepository, + #[Autowire(service: 'monolog.logger.mollie')] + LoggerInterface $logger) { $this->orderTransactionRepository = $orderTransactionRepository; $this->logger = $logger; @@ -43,7 +47,7 @@ public function findOpenTransactions(?Context $context = null): IdSearchResult } $date = new \DateTimeImmutable(); - $start = $date->modify(sprintf('-%d days', BankTransferPayment::DUE_DATE_MAX_DAYS + 1)); + $start = $date->modify(sprintf('-%d days', 101)); $end = $date->modify('-5 minutes'); $orFilterArray = [ new EqualsFilter('stateMachineState.technicalName', OrderTransactionStates::STATE_IN_PROGRESS), @@ -58,7 +62,12 @@ public function findOpenTransactions(?Context $context = null): IdSearchResult $criteria->addFilter(new OrFilter($orFilterArray)); - $criteria->addFilter(new ContainsFilter('order.customFields', CustomFieldsInterface::MOLLIE_KEY)); + $customFieldsFilter = [ + new ContainsFilter('order.customFields', Mollie::EXTENSION), + new ContainsFilter('customFields', Mollie::EXTENSION) + ]; + + $criteria->addFilter(new OrFilter($customFieldsFilter)); $criteria->addFilter(new RangeFilter('order.orderDateTime', [ RangeFilter::GTE => $start->format(Defaults::STORAGE_DATE_TIME_FORMAT), RangeFilter::LTE => $end->format(Defaults::STORAGE_DATE_TIME_FORMAT)])); diff --git a/shopware/Resources/config/repositories.xml b/shopware/Resources/config/repositories.xml deleted file mode 100644 index abf46d6e4..000000000 --- a/shopware/Resources/config/repositories.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/shopware/Resources/config/routes.xml b/shopware/Resources/config/routes.xml new file mode 100644 index 000000000..9b2f5566f --- /dev/null +++ b/shopware/Resources/config/routes.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/shopware/Resources/config/services.xml b/shopware/Resources/config/services.xml index 8858ffce0..774d72d89 100644 --- a/shopware/Resources/config/services.xml +++ b/shopware/Resources/config/services.xml @@ -4,8 +4,11 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services https://symfony.com/schema/dic/services/services-1.0.xsd"> - - - - + + + + + + + \ No newline at end of file diff --git a/shopware/Subscriber/CustomerSubscriber.php b/shopware/Subscriber/CustomerSubscriber.php new file mode 100644 index 000000000..51ef5fef1 --- /dev/null +++ b/shopware/Subscriber/CustomerSubscriber.php @@ -0,0 +1,47 @@ + 'onCustomerLoaded', + ]; + } + + /** + * @param EntityLoadedEvent $event + */ + public function onCustomerLoaded(EntityLoadedEvent $event): void + { + /** @var CustomerEntity $customerEntity */ + foreach ($event->getEntities() as $customerEntity) { + if ($customerEntity->hasExtension(Mollie::EXTENSION)) { + continue; + } + $mollieCustomFields = $customerEntity->getTranslated()['customFields'][Mollie::EXTENSION] ?? null; + if ($mollieCustomFields === null) { + $mollieCustomFields = $customerEntity->getCustomFields()[Mollie::EXTENSION] ?? null; + if ($mollieCustomFields === null) { + continue; + } + } + $customerIds = $mollieCustomFields['customer_ids'] ?? null; + if ($customerIds === null) { + continue; + } + + $customerEntity->addExtension(Mollie::EXTENSION, new Customer($customerIds)); + } + } +} diff --git a/shopware/Subscriber/DevWebHookSubscriber.php b/shopware/Subscriber/DevWebHookSubscriber.php new file mode 100644 index 000000000..e32568ad4 --- /dev/null +++ b/shopware/Subscriber/DevWebHookSubscriber.php @@ -0,0 +1,66 @@ + 'handleFinalizeEvent', + OrderShippedEvent::class => 'onOrderShipped', + ]; + } + + public function handleFinalizeEvent(PaymentFinalizeEvent $event): void + { + $environmentSettings = $this->settingsService->getEnvironmentSettings(); + + if (! $environmentSettings->isDevMode() && ! $environmentSettings->isCypressMode()) { + return; + } + $this->logger->warning('Executing Webhook in Dev mode'); + $payment = $event->getPayment(); + $transaction = $payment->getShopwareTransaction(); + $this->webhookRoute->notify($transaction->getId(), $event->getContext()); + } + + public function onOrderShipped(OrderShippedEvent $event): void + { + $environmentSettings = $this->settingsService->getEnvironmentSettings(); + + if (! $environmentSettings->isDevMode() && ! $environmentSettings->isCypressMode()) { + return; + } + $this->logger->warning('Executing Webhook in Dev mode'); + sleep(2); + $this->webhookRoute->notify($event->getTransactionId(), $event->getContext()); + } +} diff --git a/shopware/Subscriber/LineItemSubscriber.php b/shopware/Subscriber/LineItemSubscriber.php new file mode 100644 index 000000000..8eaca12b9 --- /dev/null +++ b/shopware/Subscriber/LineItemSubscriber.php @@ -0,0 +1,62 @@ + 'onCartLoaded', + OrderEvents::ORDER_LINE_ITEM_LOADED_EVENT => 'onOrderLineItemLoaded', + ]; + } + + public function onCartLoaded(CartLoadedEvent $event): void + { + $cart = $event->getCart(); + foreach ($cart->getLineItems() as $lineItem) { + if ($lineItem->hasExtension(Mollie::EXTENSION)) { + continue; + } + $customFields = $lineItem->getPayloadValue('customFields'); + + if ($customFields === null) { + continue; + } + + $extension = Product::createFromCustomFields($customFields); + + $lineItem->addExtension(Mollie::EXTENSION, $extension); + } + } + + /** + * @param EntityLoadedEvent $event + */ + public function onOrderLineItemLoaded(EntityLoadedEvent $event): void + { + /** @var OrderLineItemEntity $lineItem */ + foreach ($event->getEntities() as $lineItem) { + if ($lineItem->hasExtension(Mollie::EXTENSION)) { + continue; + } + $customFields = $lineItem->getPayload()['customFields'] ?? null; + if ($customFields === null) { + continue; + } + $extension = Product::createFromCustomFields($customFields); + + $lineItem->addExtension(Mollie::EXTENSION, $extension); + } + } +} diff --git a/shopware/Subscriber/OrderTransactionSubscriber.php b/shopware/Subscriber/OrderTransactionSubscriber.php new file mode 100644 index 000000000..39c2e423d --- /dev/null +++ b/shopware/Subscriber/OrderTransactionSubscriber.php @@ -0,0 +1,77 @@ + 'onOrderTransaction', + ]; + } + + /** + * @param EntityLoadedEvent $event + */ + public function onOrderTransaction(EntityLoadedEvent $event): void + { + /** @var OrderTransactionEntity $orderTransaction */ + foreach ($event->getEntities() as $orderTransaction) { + if (! $orderTransaction instanceof OrderTransactionEntity) { + continue; + } + if ($orderTransaction->hasExtension(Mollie::EXTENSION)) { + continue; + } + $mollieCustomFields = $orderTransaction->getTranslated()['customFields'][Mollie::EXTENSION] ?? null; + + if ($mollieCustomFields === null) { + $mollieCustomFields = $orderTransaction->getCustomFields()[Mollie::EXTENSION] ?? null; + } + + if ($mollieCustomFields === null) { + continue; + } + + $paymentId = $mollieCustomFields['id'] ?? null; + + if ($paymentId === null) { + continue; + } + + $method = $mollieCustomFields['method'] ?? null; + $countPayments = $mollieCustomFields['countPayments'] ?? 1; + $thirdPartyPaymentId = $mollieCustomFields['thirdPartyPaymentId'] ?? null; + $authenticationId = $mollieCustomFields['authenticationId'] ?? null; + $finalizeUrl = $mollieCustomFields['finalizeUrl'] ?? null; + + $transactionExtension = new Payment($paymentId); + $transactionExtension->setCountPayments($countPayments); + if ($finalizeUrl !== null) { + $transactionExtension->setFinalizeUrl($finalizeUrl); + } + + if ($method !== null) { + $transactionExtension->setMethod(PaymentMethod::from($method)); + } + if ($thirdPartyPaymentId !== null) { + $transactionExtension->setThirdPartyPaymentId($thirdPartyPaymentId); + } + if ($authenticationId !== null) { + $transactionExtension->setAuthenticationId($authenticationId); + } + + $orderTransaction->addExtension(Mollie::EXTENSION, $transactionExtension); + } + } +} diff --git a/shopware/Subscriber/PaymentMethodSubscriber.php b/shopware/Subscriber/PaymentMethodSubscriber.php new file mode 100644 index 000000000..b09305312 --- /dev/null +++ b/shopware/Subscriber/PaymentMethodSubscriber.php @@ -0,0 +1,47 @@ + 'onPaymentMethodLoaded', + ]; + } + + /** + * @param EntityLoadedEvent $event + */ + public function onPaymentMethodLoaded(EntityLoadedEvent $event): void + { + /** @var PaymentMethodEntity $paymentMethod */ + foreach ($event->getEntities() as $paymentMethod) { + if ($paymentMethod->hasExtension(Mollie::EXTENSION)) { + continue; + } + + $customFields = $paymentMethod->getTranslated()['customFields']; + $molliePaymentMethod = $customFields['mollie_payment_method_name'] ?? null; + if ($molliePaymentMethod === null) { + continue; + } + $molliePaymentMethod = PaymentMethod::tryFrom($molliePaymentMethod); + if ($molliePaymentMethod === null) { + continue; + } + $paymentMethodExtension = new PaymentMethodExtension($paymentMethod->getId(),$molliePaymentMethod); + $paymentMethod->addExtension(Mollie::EXTENSION, $paymentMethodExtension); + } + } +} diff --git a/shopware/Subscriber/ProductSubscriber.php b/shopware/Subscriber/ProductSubscriber.php new file mode 100644 index 000000000..bf09d95c5 --- /dev/null +++ b/shopware/Subscriber/ProductSubscriber.php @@ -0,0 +1,42 @@ + 'onProductLoaded', + ]; + } + + /** + * @param EntityLoadedEvent $event + */ + public function onProductLoaded(EntityLoadedEvent $event): void + { + /** @var ProductEntity $product */ + foreach ($event->getEntities() as $product) { + if ($product->hasExtension(Mollie::EXTENSION)) { + continue; + } + $customFields = $product->getTranslated()['customFields']; + if ($customFields === null) { + continue; + } + + $extension = Product::createFromCustomFields($customFields); + + $product->addExtension(Mollie::EXTENSION, $extension); + } + } +} diff --git a/shopware/Subscriber/StoreFrontDataSubscriber.php b/shopware/Subscriber/StoreFrontDataSubscriber.php new file mode 100644 index 000000000..87aae40b3 --- /dev/null +++ b/shopware/Subscriber/StoreFrontDataSubscriber.php @@ -0,0 +1,136 @@ + ['addDataToPage', 10], + AccountEditOrderPageLoadedEvent::class => ['addDataToPage', 10], + ]; + } + + public function addDataToPage(PageLoadedEvent $event): void + { + $salesChannelContext = $event->getSalesChannelContext(); + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $selectedPaymentMethod = $salesChannelContext->getPaymentMethod(); + /** @var ?PaymentMethodExtension $mollieExtension */ + $mollieExtension = $selectedPaymentMethod->getExtension(Mollie::EXTENSION); + + if ($mollieExtension === null) { + return; + } + /** @var Page $page */ + $page = $event->getPage(); + try { + $apiSettings = $this->settings->getApiSettings($salesChannelId); + + $languageInfo = $salesChannelContext->getLanguageInfo(); + /** @phpstan-ignore-next-line */ + if ($languageInfo instanceof LanguageInfo) { + $this->addMollieLocale($page, $languageInfo); + } + + $this->addTestMode($page, $apiSettings); + $this->addProfileId($page, $apiSettings); + $this->addCreditCardSettings($page, $mollieExtension, $salesChannelContext); + $this->addPosTerminals($page, $mollieExtension, $salesChannelContext); + } catch (\Throwable $exception) { + $this->logger->error('Failed to assign custom template data to pages', [ + 'error' => $exception->getMessage(), + 'salesChannelId' => $salesChannelId, + ]); + } + } + + private function addCreditCardSettings(Page $page, PaymentMethodExtension $paymentMethod, SalesChannelContext $salesChannelContext): void + { + if ($paymentMethod->getPaymentMethod() !== PaymentMethod::CREDIT_CARD) { + return; + } + $listMandatesResponse = $this->listMandatesRoute->list('', $salesChannelContext); + $mandates = $listMandatesResponse->getMandates(); + $creditCardMandates = $mandates->filterByPaymentMethod(PaymentMethod::CREDIT_CARD); + + $salesChannelId = $salesChannelContext->getSalesChannelId(); + $creditCardSettings = $this->settings->getCreditCardSettings($salesChannelId); + $paymentSettings = $this->settings->getPaymentSettings($salesChannelId); + $page->addExtension('MollieCreditCardMandateCollection', $creditCardMandates); + + $page->assign([ + 'enable_credit_card_components' => $creditCardSettings->isCreditCardComponentsEnabled(), + 'enable_one_click_payments' => $paymentSettings->isOneClickPayment(), + 'enable_one_click_payments_compact_view' => $paymentSettings->isOneClickCompactView() + ]); + } + + private function addPosTerminals(Page $page, PaymentMethodExtension $paymentMethod, SalesChannelContext $salesChannelContext): void + { + if ($paymentMethod->getPaymentMethod() !== PaymentMethod::POS) { + return; + } + $listTerminalsResponse = $this->listTerminalsRoute->list($salesChannelContext); + $terminals = $listTerminalsResponse->getTerminals(); + $page->assign([ + 'mollie_terminals' => $terminals + ]); + } + + private function addProfileId(Page $page, ApiSettings $apiSettings): void + { + $page->assign([ + 'mollie_profile_id' => $apiSettings->getProfileId() + ]); + } + + private function addTestMode(Page $page, ApiSettings $apiSettings): void + { + $page->assign([ + 'mollie_test_mode' => $apiSettings->isTestMode() ? 'true' : 'false', + ]); + } + + private function addMollieLocale(Page $page, LanguageInfo $languageInfo): void + { + $page->assign([ + 'mollie_locale' => Locale::fromLocaleCode($languageInfo->localeCode) + ]); + } +} diff --git a/src/Command/Fixtures/FixturesInstallCommand.php b/src/Command/Fixtures/FixturesInstallCommand.php deleted file mode 100644 index 518b581b2..000000000 --- a/src/Command/Fixtures/FixturesInstallCommand.php +++ /dev/null @@ -1,103 +0,0 @@ -appEnv = $appEnv; - $this->fixturesInstaller = $fixturesInstaller; - $this->logger = $logger; - - parent::__construct(); - } - - protected function configure(): void - { - $this - ->setName(self::$defaultName) - ->setDescription('Sets up the Mollie Payments demo data fixtures.') - ->addOption('setup', null, null, 'Only prepares payment methods for your sales channels. No demo data is installed with this option.') - ->addOption('data', null, null, 'Only install sample demo data like products and categories to easily test features.') - ->addOption('force', null, InputOption::VALUE_NONE, 'Skip environment safety question') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $io->title('Mollie Payments - Setting up Fixtures'); - - try { - $modeSetup = $input->getOption('setup'); - $modeDemoData = $input->getOption('data'); - $force = (bool) $input->getOption('force'); - - if ($modeSetup) { - $io->note('Mode: SETUP'); - } elseif ($modeDemoData) { - $io->note('Mode: DEMO DATA'); - } else { - $io->note('Mode: ALL'); - } - - if (strtolower($this->appEnv) !== 'dev' && ! $force) { - /** @var QuestionHelper $helper */ - $helper = $this->getHelper('question'); - $question = new ConfirmationQuestion('APP_ENV is ' . $this->appEnv . '. Continue anyway? (y/n) ', false); - - if (! $helper->ask($input, $output, $question)) { - $io->writeln('Aborting.'); - - return Command::FAILURE; - } - $io->writeln('Continuing with fixture setup...'); - } - - $this->logger->info('Installing Mollie Payments fixtures via CLI command.', - [ - 'setupMode' => $modeSetup, - 'demoDataMode' => $modeDemoData - ] - ); - - $this->fixturesInstaller->install($modeSetup, $modeDemoData); - - $io->success('Mollie Payments fixtures have been set up successfully.'); - - $this->logger->info('Mollie Payments fixtures installation completed successfully.'); - - return Command::SUCCESS; - } catch (\Throwable $ex) { - $this->logger->error($ex->getMessage(), ['exception' => $ex]); - - return Command::FAILURE; - } - } -} diff --git a/src/Command/Fixtures/FixturesUninstallCommand.php b/src/Command/Fixtures/FixturesUninstallCommand.php deleted file mode 100644 index 04444e5f7..000000000 --- a/src/Command/Fixtures/FixturesUninstallCommand.php +++ /dev/null @@ -1,64 +0,0 @@ -fixturesInstaller = $fixturesInstaller; - $this->logger = $logger; - - parent::__construct(); - } - - protected function configure(): void - { - $this - ->setName(self::$defaultName) - ->setDescription('Removes the Mollie Payments demo data fixtures.') - ; - } - - protected function execute(InputInterface $input, OutputInterface $output): int - { - $io = new SymfonyStyle($input, $output); - - $io->title('Mollie Payments - Uninstalling Fixtures'); - - try { - $this->logger->info('Uninstalling Mollie Payments fixtures via CLI command.'); - - $this->fixturesInstaller->uninstall(); - - $io->success('Mollie Payments fixtures have been uninstalled successfully.'); - - $this->logger->info('Mollie Payments fixtures uninstallation completed successfully.'); - - return Command::SUCCESS; - } catch (\Throwable $ex) { - $this->logger->error($ex->getMessage(), ['exception' => $ex]); - - return Command::FAILURE; - } - } -} diff --git a/src/Compatibility/Bundles/FlowBuilder/Actions/RefundOrderAction.php b/src/Compatibility/Bundles/FlowBuilder/Actions/RefundOrderAction.php index 5877e1ec1..6e190e2b9 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Actions/RefundOrderAction.php +++ b/src/Compatibility/Bundles/FlowBuilder/Actions/RefundOrderAction.php @@ -10,7 +10,6 @@ use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction; use Shopware\Core\Content\Flow\Dispatching\StorableFlow; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\FlowEvent; use Shopware\Core\Framework\Event\OrderAware; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -49,7 +48,7 @@ public static function getName(): string public static function getSubscribedEvents(): array { return [ - self::getName() => 'handle', + self::getName() => 'handleFlow', ]; } @@ -71,31 +70,6 @@ public function handleFlow(StorableFlow $flow): void $this->refundOrder($orderId, $flow->getContext()); } - /** - * @throws \Exception - * - * @phpstan-ignore class.notFound - */ - public function handle(FlowEvent $event): void - { - /** @phpstan-ignore class.notFound */ - $config = $event->getConfig(); - - if (empty($config)) { - return; - } - /** @phpstan-ignore class.notFound */ - $baseEvent = $event->getEvent(); - - if (! $baseEvent instanceof OrderAware) { - return; - } - - $orderId = $baseEvent->getOrderId(); - - $this->refundOrder($orderId, $baseEvent->getContext()); - } - /** * @throws \Exception */ diff --git a/src/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderAction.php b/src/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderAction.php index 3f7617d62..e6ae00bc8 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderAction.php +++ b/src/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderAction.php @@ -9,7 +9,6 @@ use Shopware\Core\Content\Flow\Dispatching\Action\FlowAction; use Shopware\Core\Content\Flow\Dispatching\StorableFlow; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\FlowEvent; use Shopware\Core\Framework\Event\OrderAware; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -48,7 +47,7 @@ public static function getName(): string public static function getSubscribedEvents(): array { return [ - self::getName() => 'handle', + self::getName() => 'handleFlow', ]; } @@ -70,32 +69,6 @@ public function handleFlow(StorableFlow $flow): void $this->shipOrder($orderId, $flow->getContext()); } - /** - * @throws \Exception - * - * @phpstan-ignore class.notFound - */ - public function handle(FlowEvent $event): void - { - /** @phpstan-ignore class.notFound */ - $config = $event->getConfig(); - - if (empty($config)) { - return; - } - - /** @phpstan-ignore class.notFound */ - $baseEvent = $event->getEvent(); - - if (! $baseEvent instanceof OrderAware) { - return; - } - - $orderId = $baseEvent->getOrderId(); - - $this->shipOrder($orderId, $baseEvent->getContext()); - } - /** * @throws \Exception */ diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderCanceled/OrderCanceledEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderCanceled/OrderCanceledEvent.php index 64f712ccd..e12152b60 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderCanceled/OrderCanceledEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderCanceled/OrderCanceledEvent.php @@ -8,18 +8,18 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class OrderCanceledEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +class OrderCanceledEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderFailed/OrderFailedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderFailed/OrderFailedEvent.php index 7a7dc955f..efe1c5cb4 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderFailed/OrderFailedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderFailed/OrderFailedEvent.php @@ -8,18 +8,18 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class OrderFailedEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +class OrderFailedEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderSuccess/OrderSuccessEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderSuccess/OrderSuccessEvent.php index 69c9b3daf..8587bf0e1 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderSuccess/OrderSuccessEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Checkout/OrderSuccess/OrderSuccessEvent.php @@ -8,18 +8,18 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class OrderSuccessEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +class OrderSuccessEvent extends Event implements CustomerAware, OrderAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Refund/RefundStarted/RefundStartedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Refund/RefundStarted/RefundStartedEvent.php index 5dcc95d00..6765a220c 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Refund/RefundStarted/RefundStartedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Refund/RefundStarted/RefundStartedEvent.php @@ -7,17 +7,17 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; use Shopware\Core\Framework\Event\EventData\ScalarValueType; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Symfony\Contracts\EventDispatcher\Event; -class RefundStartedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +class RefundStartedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, FlowEventAware { /** * @var OrderEntity diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionCancelled/SubscriptionCancelledEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionCancelled/SubscriptionCancelledEvent.php index 2dbd4cde1..d68f98fff 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionCancelled/SubscriptionCancelledEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionCancelled/SubscriptionCancelledEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionCancelled; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionCancelledEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionCancelledEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionEnded/SubscriptionEndedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionEnded/SubscriptionEndedEvent.php index 2a9523d4f..46cf316a4 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionEnded/SubscriptionEndedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionEnded/SubscriptionEndedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionEnded; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionEndedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionEndedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionPaused/SubscriptionPausedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionPaused/SubscriptionPausedEvent.php index f07b6abbb..e003b7338 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionPaused/SubscriptionPausedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionPaused/SubscriptionPausedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionPaused; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionPausedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionPausedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionReminded/SubscriptionRemindedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionReminded/SubscriptionRemindedEvent.php index 1b352096f..700beceae 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionReminded/SubscriptionRemindedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionReminded/SubscriptionRemindedEvent.php @@ -3,16 +3,16 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionReminded; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; @@ -20,7 +20,7 @@ use Shopware\Core\System\SalesChannel\SalesChannelEntity; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionRemindedEvent extends Event implements CustomerAware, SalesChannelAware, MailAware, BusinessEventInterface +class SubscriptionRemindedEvent extends Event implements CustomerAware, SalesChannelAware, MailAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionRenewed/SubscriptionRenewedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionRenewed/SubscriptionRenewedEvent.php index c3401211b..ac9da0f1f 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionRenewed/SubscriptionRenewedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionRenewed/SubscriptionRenewedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionRenewed; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionRenewedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionRenewedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionResumed/SubscriptionResumedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionResumed/SubscriptionResumedEvent.php index 572fd30f0..8a26583d8 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionResumed/SubscriptionResumedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionResumed/SubscriptionResumedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionResumed; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionResumedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionResumedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionSkipped/SubscriptionSkippedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionSkipped/SubscriptionSkippedEvent.php index 68e88324f..2847b535b 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionSkipped/SubscriptionSkippedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionSkipped/SubscriptionSkippedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionSkipped; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionSkippedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionSkippedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionStarted/SubscriptionStartedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionStarted/SubscriptionStartedEvent.php index 909b1312b..ba2d09bb8 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionStarted/SubscriptionStartedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/Subscription/SubscriptionStarted/SubscriptionStartedEvent.php @@ -3,22 +3,22 @@ namespace Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\Subscription\SubscriptionStarted; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerDefinition; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\CustomerAware; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Shopware\Core\Framework\Struct\JsonSerializableTrait; use Symfony\Contracts\EventDispatcher\Event; -class SubscriptionStartedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, BusinessEventInterface +class SubscriptionStartedEvent extends Event implements CustomerAware, MailAware, SalesChannelAware, FlowEventAware { use JsonSerializableTrait; diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/WebhookReceivedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/WebhookReceivedEvent.php index 76dc0c9fc..6e6f52c9d 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/WebhookReceivedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/WebhookReceivedEvent.php @@ -7,17 +7,17 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; use Shopware\Core\Framework\Event\EventData\ScalarValueType; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Symfony\Contracts\EventDispatcher\Event; -class WebhookReceivedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +class WebhookReceivedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, FlowEventAware { /** * @var OrderEntity diff --git a/src/Compatibility/Bundles/FlowBuilder/Events/WebhookStatusReceived/AbstractWebhookReceivedEvent.php b/src/Compatibility/Bundles/FlowBuilder/Events/WebhookStatusReceived/AbstractWebhookReceivedEvent.php index 2c4b1e907..52599f809 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Events/WebhookStatusReceived/AbstractWebhookReceivedEvent.php +++ b/src/Compatibility/Bundles/FlowBuilder/Events/WebhookStatusReceived/AbstractWebhookReceivedEvent.php @@ -7,17 +7,17 @@ use Shopware\Core\Checkout\Order\OrderDefinition; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; -use Shopware\Core\Framework\Event\BusinessEventInterface; use Shopware\Core\Framework\Event\EventData\EntityType; use Shopware\Core\Framework\Event\EventData\EventDataCollection; use Shopware\Core\Framework\Event\EventData\MailRecipientStruct; use Shopware\Core\Framework\Event\EventData\ScalarValueType; +use Shopware\Core\Framework\Event\FlowEventAware; use Shopware\Core\Framework\Event\MailAware; use Shopware\Core\Framework\Event\OrderAware; use Shopware\Core\Framework\Event\SalesChannelAware; use Symfony\Contracts\EventDispatcher\Event; -abstract class AbstractWebhookReceivedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, BusinessEventInterface +abstract class AbstractWebhookReceivedEvent extends Event implements OrderAware, MailAware, SalesChannelAware, FlowEventAware { /** * @var OrderEntity diff --git a/src/Compatibility/Bundles/FlowBuilder/FlowBuilderEventFactory.php b/src/Compatibility/Bundles/FlowBuilder/FlowBuilderEventFactory.php index 4639e8fba..63cf7994b 100644 --- a/src/Compatibility/Bundles/FlowBuilder/FlowBuilderEventFactory.php +++ b/src/Compatibility/Bundles/FlowBuilder/FlowBuilderEventFactory.php @@ -40,7 +40,7 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\WebhookStatusReceived\WebhookReceivedPendingEvent; use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\Events\WebhookStatusReceived\WebhookReceivedRefundedEvent; use Kiener\MolliePayments\Compatibility\VersionCompare; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Checkout\Order\OrderEntity; diff --git a/src/Compatibility/Bundles/FlowBuilder/Subscriber/BusinessEventCollectorSubscriber.php b/src/Compatibility/Bundles/FlowBuilder/Subscriber/BusinessEventCollectorSubscriber.php index 2395164c9..d23b15950 100644 --- a/src/Compatibility/Bundles/FlowBuilder/Subscriber/BusinessEventCollectorSubscriber.php +++ b/src/Compatibility/Bundles/FlowBuilder/Subscriber/BusinessEventCollectorSubscriber.php @@ -67,7 +67,7 @@ public function __construct(string $shopwareVersion, BusinessEventCollector $bus /** * @return array */ - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ BusinessEventCollectorEvent::NAME => ['onAddEvent', 1000], diff --git a/src/Compatibility/DependencyLoader.php b/src/Compatibility/DependencyLoader.php index 1d1918fe0..0991993c1 100644 --- a/src/Compatibility/DependencyLoader.php +++ b/src/Compatibility/DependencyLoader.php @@ -3,7 +3,6 @@ namespace Kiener\MolliePayments\Compatibility; -use Composer\Autoload\ClassLoader; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -47,20 +46,6 @@ public function loadServices(): void if ($this->versionCompare->gte('6.4.6.0')) { $loader->load('compatibility/flowbuilder/6.4.6.0.xml'); } - - if ($this->shouldLoadFixtures()) { - $loader->load('services/fixtures/fixtures.xml'); - } - } - - public function registerDependencies(): void - { - $classLoader = new ClassLoader(); - - $this->registerPolyfillsAutoloader($classLoader); - $this->registerFixturesAutoloader($classLoader); - - $classLoader->register(); } public function prepareStorefrontBuild(): void @@ -88,32 +73,4 @@ public function prepareStorefrontBuild(): void // copy($file, $target); } } - - private function registerPolyfillsAutoloader(ClassLoader $classLoader): void - { - $classLoader->addPsr4('Shopware\Core\\', __DIR__ . '/../../polyfill/Shopware/Core', true); - } - - private function registerFixturesAutoloader(ClassLoader $classLoader): void - { - if ($this->shouldLoadFixtures() === false) { - return; - } - - $dirFixtures = (string) realpath(__DIR__ . '/../../tests/Fixtures/'); - // we need to tell Shopware to load our custom fixtures - // from our TEST autoload-dev area.... - $classLoader->addPsr4('MolliePayments\Fixtures\\', $dirFixtures, true); - } - - private function shouldLoadFixtures(): bool - { - $composerDevReqsInstalled = file_exists(__DIR__ . '/../../vendor/bin/phpunit'); - if ($composerDevReqsInstalled === false) { - return false; - } - $dirFixtures = (string) realpath(__DIR__ . '/../../tests/Fixtures/'); - - return is_dir($dirFixtures); - } } diff --git a/src/Compatibility/Storefront/Route/PaymentMethodRoute/Cache/CachedPaymentMethodRoute64.php b/src/Compatibility/Storefront/Route/PaymentMethodRoute/Cache/CachedPaymentMethodRoute64.php index a32748e01..f35d998a7 100644 --- a/src/Compatibility/Storefront/Route/PaymentMethodRoute/Cache/CachedPaymentMethodRoute64.php +++ b/src/Compatibility/Storefront/Route/PaymentMethodRoute/Cache/CachedPaymentMethodRoute64.php @@ -62,7 +62,7 @@ public function onGenerateCacheKey(PaymentMethodRouteCacheKeyEvent $event): void $parts = $event->getParts(); $cacheParts = []; - $cacheParts = $this->addVoucherKey($cart, $cacheParts); + // s $cacheParts = $this->addVoucherKey($cart, $cacheParts); $cacheParts = $this->addMollieLimitsKey($cacheParts); $cacheParts = $this->addSubscriptionKey($cart, $cacheParts); $cacheParts = $this->addCartAmountKey($cart, $cacheParts); @@ -77,9 +77,12 @@ public function onGenerateCacheKey(PaymentMethodRouteCacheKeyEvent $event): void * @param array $parts * * @return array + * + * @phpstan-ignore method.unused */ private function addVoucherKey(Cart $cart, array $parts): array { + // TODO: check cache key for cart!! $voucherPermitted = (bool) $cart->getData()->get(VoucherCartCollector::VOUCHER_PERMITTED); if ($voucherPermitted) { diff --git a/src/Components/ApplePayDirect/ApplePayDirect.php b/src/Components/ApplePayDirect/ApplePayDirect.php index af575875c..acfb75cde 100644 --- a/src/Components/ApplePayDirect/ApplePayDirect.php +++ b/src/Components/ApplePayDirect/ApplePayDirect.php @@ -15,7 +15,6 @@ use Kiener\MolliePayments\Factory\MollieApiFactory; use Kiener\MolliePayments\Handler\Method\ApplePayPayment; use Kiener\MolliePayments\Repository\PaymentMethodRepository; -use Kiener\MolliePayments\Service\Cart\CartBackupService; use Kiener\MolliePayments\Service\CartServiceInterface; use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\DomainExtractor; @@ -24,6 +23,7 @@ use Kiener\MolliePayments\Service\ShopService; use Kiener\MolliePayments\Struct\Address\AddressStruct; use Mollie\Api\Exceptions\ApiException; +use Mollie\Shopware\Component\Payment\ExpressMethod\AbstractCartBackupService; use Mollie\Shopware\Component\Transaction\PaymentTransactionStruct; use Shopware\Core\Checkout\Cart\Cart; use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection; @@ -90,7 +90,7 @@ class ApplePayDirect private $repoPaymentMethods; /** - * @var CartBackupService + * @var AbstractCartBackupService */ private $cartBackupService; @@ -127,7 +127,19 @@ class ApplePayDirect /** * @param EntityRepository> $repoOrderAdresses */ - public function __construct(ApplePayDomainVerificationService $domainFileDownloader, ApplePayPayment $paymentHandler, MolliePaymentDoPay $molliePayments, CartServiceInterface $cartService, ApplePayFormatter $formatter, ApplePayShippingBuilder $shippingBuilder, SettingsService $pluginSettings, CustomerService $customerService, PaymentMethodRepository $repoPaymentMethods, CartBackupService $cartBackupService, MollieApiFactory $mollieApiFactory, ShopService $shopService, OrderService $orderService, $repoOrderAdresses, ApplePayDirectDomainAllowListGateway $domainAllowListGateway, ApplePayDirectDomainSanitizer $domainSanitizer) + public function __construct( + ApplePayDomainVerificationService $domainFileDownloader, + ApplePayPayment $paymentHandler, + MolliePaymentDoPay $molliePayments, + CartServiceInterface $cartService, + ApplePayFormatter $formatter, + ApplePayShippingBuilder $shippingBuilder, + SettingsService $pluginSettings, + CustomerService $customerService, + PaymentMethodRepository $repoPaymentMethods, + AbstractCartBackupService $cartBackupService, + MollieApiFactory $mollieApiFactory, + ShopService $shopService, OrderService $orderService, $repoOrderAdresses, ApplePayDirectDomainAllowListGateway $domainAllowListGateway, ApplePayDirectDomainSanitizer $domainSanitizer) { $this->domainFileDownloader = $domainFileDownloader; $this->paymentHandler = $paymentHandler; diff --git a/src/Components/Fixtures/FixtureUtils.php b/src/Components/Fixtures/FixtureUtils.php deleted file mode 100644 index 8b026d414..000000000 --- a/src/Components/Fixtures/FixtureUtils.php +++ /dev/null @@ -1,37 +0,0 @@ -mediaUtils = $mediaUtils; - $this->taxUtils = $taxUtils; - $this->salesChannelUtils = $salesChannelUtils; - } - - public function getMedia(): MediaUtils - { - return $this->mediaUtils; - } - - public function getTaxes(): TaxUtils - { - return $this->taxUtils; - } - - public function getSalesChannels(): SalesChannelUtils - { - return $this->salesChannelUtils; - } -} diff --git a/src/Components/Fixtures/FixturesInstaller.php b/src/Components/Fixtures/FixturesInstaller.php deleted file mode 100644 index a1d8f391c..000000000 --- a/src/Components/Fixtures/FixturesInstaller.php +++ /dev/null @@ -1,107 +0,0 @@ -categoryFixture = $categoryFixture; - $this->salesChannelFixture = $salesChannelFixture; - $this->shipmentFixture = $shipmentFixture; - $this->subscriptionFixture = $subscriptionFixture; - $this->voucherFixture = $voucherFixture; - $this->cheapProducts = $cheapProducts; - $this->failureProducts = $failureProducts; - $this->roundingProducts = $roundingProducts; - $this->customerFixture = $customerFixture; - } - - public function install(bool $onlySetupMode, bool $onlyDemoData): void - { - if ($onlySetupMode) { - $this->installSetup(); - - return; - } - - if ($onlyDemoData) { - $this->installDemoData(); - - return; - } - - // -------------------------------- - // default, install ALL - $this->installSetup(); - $this->installDemoData(); - } - - public function uninstall(): void - { - $this->shipmentFixture->uninstall(); - $this->categoryFixture->uninstall(); - - $this->customerFixture->uninstall(); - $this->cheapProducts->uninstall(); - $this->failureProducts->uninstall(); - $this->roundingProducts->uninstall(); - $this->voucherFixture->uninstall(); - $this->subscriptionFixture->uninstall(); - } - - private function installSetup(): void - { - $this->salesChannelFixture->install(); - } - - private function installDemoData(): void - { - // ------------------------------------------ - // customers - $this->customerFixture->install(); - // ------------------------------------------ - // categories - $this->categoryFixture->install(); - // ------------------------------------------ - // shipment - $this->shipmentFixture->install(); - // ------------------------------------------ - // products - $this->subscriptionFixture->install(); - $this->voucherFixture->install(); - $this->cheapProducts->install(); - $this->failureProducts->install(); - $this->roundingProducts->install(); - } -} diff --git a/src/Components/Fixtures/Handler/Category/CategoryFixture.php b/src/Components/Fixtures/Handler/Category/CategoryFixture.php deleted file mode 100644 index 8d3a8c16a..000000000 --- a/src/Components/Fixtures/Handler/Category/CategoryFixture.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ - private $categoryRepository; - - /** - * @param EntityRepository $categoryRepository - */ - public function __construct($categoryRepository) - { - $this->categoryRepository = $categoryRepository; - } - - public function install(): void - { - $context = new Context(new SystemSource()); - - $criteria = new Criteria(); - $criteria->addFilter(new EqualsFilter('parentId', null)); - $categorySearchResult = $this->categoryRepository->search($criteria, $context); - - /** @var CategoryEntity $rootCategory */ - $rootCategory = $categorySearchResult->first(); - - $afterCatId = null; - $cmsPageId = null; - - $this->createCategory($this->CATEGORY_ROOT_ID, 'Mollie', $context, $afterCatId, $rootCategory->getId(), $cmsPageId); - - $this->createCategory($this->CATEGORY_VOUCHER_ID, 'Voucher', $context, $afterCatId, $this->CATEGORY_ROOT_ID, $cmsPageId); - $this->createCategory($this->CATEGORY_SUBSCRIPTIONS_ID, 'Subscriptions', $context, $afterCatId, $this->CATEGORY_ROOT_ID, $cmsPageId); - $this->createCategory($this->CATEGORY_FAILURES_ID, 'Failures', $context, $afterCatId, $this->CATEGORY_ROOT_ID, $cmsPageId); - $this->createCategory($this->CATEGORY_ROUNDING_ID, 'Rounding', $context, $afterCatId, $this->CATEGORY_ROOT_ID, $cmsPageId); - $this->createCategory($this->CATEGORY_CHEAP_ID, 'Regular Products', $context, $afterCatId, $this->CATEGORY_ROOT_ID, $cmsPageId); - } - - public function uninstall(): void - { - $this->categoryRepository->delete( - [ - ['id' => $this->CATEGORY_ROOT_ID], - ['id' => $this->CATEGORY_VOUCHER_ID], - ['id' => $this->CATEGORY_SUBSCRIPTIONS_ID], - ['id' => $this->CATEGORY_FAILURES_ID], - ['id' => $this->CATEGORY_ROUNDING_ID], - ['id' => $this->CATEGORY_CHEAP_ID], - ], - Context::createDefaultContext() - ); - } - - private function createCategory(string $id, string $name, Context $context, ?string $afterCategoryId, ?string $parentId, ?string $cmsPageId): void - { - $this->categoryRepository->upsert([ - [ - 'id' => $id, - 'translations' => [ - 'de-DE' => [ - 'name' => $name, - ], - 'en-GB' => [ - 'name' => $name, - ], - ], - 'productAssignmentType' => 'product', - 'level' => 2, - 'active' => true, - 'displayNestedProducts' => true, - 'visible' => true, - 'type' => 'page', - 'cmsPageId' => $cmsPageId, - 'parentId' => $parentId, - 'afterCategoryId' => $afterCategoryId, - ], - ], $context); - } -} diff --git a/src/Components/Fixtures/Handler/Customer/CustomerFixture.php b/src/Components/Fixtures/Handler/Customer/CustomerFixture.php deleted file mode 100644 index a537e9844..000000000 --- a/src/Components/Fixtures/Handler/Customer/CustomerFixture.php +++ /dev/null @@ -1,131 +0,0 @@ - - */ - private $repoCustomers; - - /** - * @var EntityRepository - */ - private $repoCustomerGroups; - - /** - * @var EntityRepository - */ - private $repoSalutations; - - /** - * @var EntityRepository - */ - private $repoSalesChannels; - - /** - * @var EntityRepository - */ - private $repoPaymentMethods; - - /** - * @var EntityRepository - */ - private $repoCountries; - - /** - * @param EntityRepository $repoCustomers - * @param EntityRepository $repoCustomerGroups - * @param EntityRepository $repoSalutations - * @param EntityRepository $repoSalesChannels - * @param EntityRepository $repoPaymentMethods - * @param EntityRepository $repoCountries - */ - public function __construct($repoCustomers, $repoCustomerGroups, $repoSalutations, $repoSalesChannels, $repoPaymentMethods, $repoCountries) - { - $this->repoCustomers = $repoCustomers; - $this->repoCustomerGroups = $repoCustomerGroups; - $this->repoSalutations = $repoSalutations; - $this->repoSalesChannels = $repoSalesChannels; - $this->repoPaymentMethods = $repoPaymentMethods; - $this->repoCountries = $repoCountries; - } - - public function install(): void - { - $context = Context::createDefaultContext(); - - $email = 'cypress@mollie.com'; - $password = 'cypress123'; - - $salesChannelId = $this->repoSalesChannels->searchIds((new Criteria())->setLimit(1), $context)->firstId(); - - if (! $salesChannelId) { - throw new \RuntimeException('No sales channel found.'); - } - - $defaultPaymentMethodId = $this->repoPaymentMethods->searchIds((new Criteria())->setLimit(1), $context)->firstId(); - - $firstSalutationId = $this->repoSalutations->searchIds((new Criteria())->setLimit(1), $context)->firstId(); - $firstCountryId = $this->repoCountries->searchIds((new Criteria())->setLimit(1), $context)->firstId(); - $firstCustomerGroupId = $this->repoCustomerGroups->searchIds((new Criteria())->setLimit(1), $context)->firstId(); - - $addressId = Uuid::fromStringToHex('address-' . $firstCountryId); - $payload = [[ - 'id' => self::CYPRESS_CUSTOMER_ID, - 'salesChannelId' => $salesChannelId, - 'salutationId' => $firstSalutationId, - 'customerNumber' => 'CYPRESS-' . date('YmdHis'), - 'email' => $email, - 'password' => $password, - 'accountType' => 'commercial', - 'firstName' => 'Cypress', - 'lastName' => 'TestUser', - 'groupId' => $firstCustomerGroupId, - 'defaultPaymentMethodId' => $defaultPaymentMethodId, - 'defaultBillingAddressId' => $addressId, - 'defaultShippingAddressId' => $addressId, - 'addresses' => [[ - 'id' => $addressId, - 'salutationId' => $firstSalutationId, - 'company' => 'Mollie B.V.', - 'firstName' => 'Cypress', - 'lastName' => 'User', - 'street' => 'Cypress Street 1', - 'zipcode' => '10115', - 'city' => 'Berlin', - 'countryId' => $firstCountryId, - 'phoneNumber' => '+49123456789', - ]], - ]]; - - $this->repoCustomers->upsert($payload, $context); - } - - public function uninstall(): void - { - $context = Context::createDefaultContext(); - - $this->repoCustomers->delete([ - [ - 'id' => self::CYPRESS_CUSTOMER_ID - ] - ], $context); - } -} diff --git a/src/Components/Fixtures/Handler/PaymentMethod/PaymentMethodsFixture.php b/src/Components/Fixtures/Handler/PaymentMethod/PaymentMethodsFixture.php deleted file mode 100644 index de9d2309a..000000000 --- a/src/Components/Fixtures/Handler/PaymentMethod/PaymentMethodsFixture.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ - private $repoSalesChannels; - - /** - * @var EntityRepository - */ - private $repoPaymentMethods; - - /** - * @param EntityRepository $repoSalesChannels - * @param EntityRepository $repoPaymentMethods - */ - public function __construct($repoSalesChannels, $repoPaymentMethods) - { - $this->repoSalesChannels = $repoSalesChannels; - $this->repoPaymentMethods = $repoPaymentMethods; - } - - public function install(): void - { - $ctx = Context::createDefaultContext(); - - // first delete all existing configurations - // of the specific sales channels - $salesChannelIds = $this->repoSalesChannels->searchIds(new Criteria(), $ctx)->getIds(); - - $this->activatePaymentMethods($ctx); - $this->assignPaymentMethods($salesChannelIds, $ctx); - } - - public function uninstall(): void - { - // do nothing in this case - // we dont want to unassign things again - } - - private function activatePaymentMethods(Context $ctx): void - { - $paymentUpdates = []; - - $mollieCriteria = new Criteria(); - $mollieCriteria->addFilter( - new ContainsFilter('handlerIdentifier', 'MolliePayments') - ); - - $molliePaymentMethodIds = $this->repoPaymentMethods->searchIds($mollieCriteria, $ctx)->getIds(); - - foreach ($molliePaymentMethodIds as $id) { - $paymentUpdates[] = [ - 'id' => $id, - 'active' => true, - ]; - } - - $this->repoPaymentMethods->update($paymentUpdates, $ctx); - } - - /** - * @param array $salesChannelIds - */ - private function assignPaymentMethods(array $salesChannelIds, Context $ctx): void - { - $paymentUpdates = []; - $molliePaymentMethodIdsPrepared = []; - - $molliePaymentMethodIds = $this->repoPaymentMethods->searchIds(new Criteria(), $ctx)->getIds(); - - foreach ($molliePaymentMethodIds as $id) { - $molliePaymentMethodIdsPrepared[] = [ - 'id' => $id, - ]; - } - - foreach ($salesChannelIds as $id) { - $paymentUpdates[] = [ - 'id' => $id, - 'paymentMethods' => $molliePaymentMethodIdsPrepared, - ]; - } - - $this->repoSalesChannels->update($paymentUpdates, $ctx); - } -} diff --git a/src/Components/Fixtures/Handler/Product/CheapProductsFixture.php b/src/Components/Fixtures/Handler/Product/CheapProductsFixture.php deleted file mode 100644 index 6414e111f..000000000 --- a/src/Components/Fixtures/Handler/Product/CheapProductsFixture.php +++ /dev/null @@ -1,51 +0,0 @@ - - */ - private $repoProducts; - - /** - * @param EntityRepository $repoProducts - */ - public function __construct(FixtureUtils $utils, $repoProducts) - { - $this->utils = $utils; - $this->repoProducts = $repoProducts; - } - - public function install(): void - { - $category = 'Cheap'; - $image = 'tshirt-black.png'; - $description = 'Mollie Product for testing purpose in development environment. You can use this cheap products for LIVE tests or other scenarios'; - - $this->createProduct('1d3eefdd2d22436385580e2fb43431b9', 'Cheap Mollie Shirt', 'MOL_CHEAP_1', $category, $description, 1, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('1d3eefdd2d22436385580e2fb53432b2', 'Regular Mollie Shirt', 'MOL_CHEAP_2', $category, $description, 29.90, $image, false, [], $this->repoProducts, $this->utils); - } - - public function uninstall(): void - { - $this->repoProducts->delete( - [ - ['id' => '1d3eefdd2d22436385580e2fb43431b9'], - ['id' => '1d3eefdd2d22436385580e2fb53432b2'], - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Product/FailureProductsFixture.php b/src/Components/Fixtures/Handler/Product/FailureProductsFixture.php deleted file mode 100644 index a90cf7281..000000000 --- a/src/Components/Fixtures/Handler/Product/FailureProductsFixture.php +++ /dev/null @@ -1,91 +0,0 @@ - - */ - private $repoProducts; - - /** - * @param EntityRepository $repoProducts - */ - public function __construct(FixtureUtils $utils, $repoProducts) - { - $this->utils = $utils; - $this->repoProducts = $repoProducts; - } - - /** - * @return string[] - */ - public function groups(): array - { - return [ - 'mollie', - 'mollie-demodata', - ]; - } - - /** - * @return string[] - */ - public function dependsOn(): array - { - return [ - CategoryFixture::class - ]; - } - - public function install(): void - { - $category = 'Failures'; - $image = 'tshirt-black-fail.png'; - $description = 'Mollie Product for testing purpose in development environment. Use "failed" on the Mollie Payment Sandbox page to force the special error reason of this product.'; - - $this->createProduct('0d1eeedd6d22436385580e2ff42431b9', 'Invalid Card Number', 'MOL_ERROR_1', $category, $description, 1001, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d2eeedd6d22436385580e2ff42431b9', 'Invalid CVV', 'MOL_ERROR_2', $category, $description, 1002, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d3eeedd6d22436385580e2ff42431b9', 'Invalid Card Holder Name', 'MOL_ERROR_3', $category, $description, 1003, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d4eeedd6d22436385580e2ff42431b9', 'Card Expired', 'MOL_ERROR_4', $category, $description, 1004, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d5eeedd6d22436385580e2ff42431b9', 'Invalid Card Type', 'MOL_ERROR_5', $category, $description, 1005, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d6eeedd6d22436385580e2ff42431b9', 'Refused by Issuer', 'MOL_ERROR_6', $category, $description, 1006, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d7eeedd6d22436385580e2ff42431b9', 'Insufficient Funds', 'MOL_ERROR_7', $category, $description, 1007, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d8eeedd6d22436385580e2ff42431b9', 'Inactive Card', 'MOL_ERROR_8', $category, $description, 1008, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d9eeedd6d22436385580e2ff42431b9', 'Possible Fraud', 'MOL_ERROR_9', $category, $description, 1009, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d3eeedd6d10436385580e2ff42431b9', 'Authentication Failed', 'MOL_ERROR_10', $category, $description, 1010, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('0d3eeedd6d11436385580e2ff42431b9', 'Card Declined', 'MOL_ERROR_11', $category, $description, 1011, $image, false, [], $this->repoProducts, $this->utils); - } - - public function uninstall(): void - { - $this->repoProducts->delete( - [ - ['id' => '0d1eeedd6d22436385580e2ff42431b9'], - ['id' => '0d2eeedd6d22436385580e2ff42431b9'], - ['id' => '0d3eeedd6d22436385580e2ff42431b9'], - ['id' => '0d4eeedd6d22436385580e2ff42431b9'], - ['id' => '0d5eeedd6d22436385580e2ff42431b9'], - ['id' => '0d6eeedd6d22436385580e2ff42431b9'], - ['id' => '0d7eeedd6d22436385580e2ff42431b9'], - ['id' => '0d8eeedd6d22436385580e2ff42431b9'], - ['id' => '0d9eeedd6d22436385580e2ff42431b9'], - ['id' => '0d3eeedd6d10436385580e2ff42431b9'], - ['id' => '0d3eeedd6d11436385580e2ff42431b9'], - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Product/RoundingProductsFixture.php b/src/Components/Fixtures/Handler/Product/RoundingProductsFixture.php deleted file mode 100644 index db8b9cc90..000000000 --- a/src/Components/Fixtures/Handler/Product/RoundingProductsFixture.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - private $repoProducts; - - /** - * @param EntityRepository $repoProducts - */ - public function __construct(FixtureUtils $utils, $repoProducts) - { - $this->utils = $utils; - $this->repoProducts = $repoProducts; - } - - public function install(): void - { - $category = 'Rounding'; - $image = 'tshirt-white.png'; - $description = 'Product to test rounding issues.'; - - $this->createProduct('7d1abedd2d22436385580e2ff42431b9', 'Product A 4 Decimals', 'MOL_ROUNDING_1', $category, $description, 2.7336, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('6d1abedd2d22436485580f3ff42431b9', 'Product B 4 Decimals', 'MOL_ROUNDING_2', $category, $description, 2.9334, $image, false, [], $this->repoProducts, $this->utils); - $this->createProduct('1a2abeed2d22436485580f3ff42431b9', 'Product C 4 Decimals', 'MOL_ROUNDING_3', $category, $description, 1.6494, $image, false, [], $this->repoProducts, $this->utils); - } - - public function uninstall(): void - { - $this->repoProducts->delete( - [ - ['id' => '7d1abedd2d22436385580e2ff42431b9'], - ['id' => '6d1abedd2d22436485580f3ff42431b9'], - ['id' => '1a2abeed2d22436485580f3ff42431b9'] - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Product/SubscriptionProductsFixture.php b/src/Components/Fixtures/Handler/Product/SubscriptionProductsFixture.php deleted file mode 100644 index eac6860cb..000000000 --- a/src/Components/Fixtures/Handler/Product/SubscriptionProductsFixture.php +++ /dev/null @@ -1,71 +0,0 @@ - - */ - private $repoProducts; - - /** - * @param EntityRepository $repoProducts - */ - public function __construct(FixtureUtils $utils, $repoProducts) - { - $this->utils = $utils; - $this->repoProducts = $repoProducts; - } - - public function install(): void - { - $category = 'Subscriptions'; - $image = 'champagne.png'; - $description = 'Mollie Subscription Product for testing purpose in development environment.'; - - $customFieldsDaily = [ - 'mollie_payments_product_subscription_enabled' => true, - 'mollie_payments_product_subscription_interval' => 1, - 'mollie_payments_product_subscription_interval_unit' => 'days' - ]; - - $customFieldsWeekly = [ - 'mollie_payments_product_subscription_enabled' => true, - 'mollie_payments_product_subscription_interval' => 1, - 'mollie_payments_product_subscription_interval_unit' => 'weeks' - ]; - - $customFieldsThreeWeekly = [ - 'mollie_payments_product_subscription_enabled' => true, - 'mollie_payments_product_subscription_interval' => 3, - 'mollie_payments_product_subscription_interval_unit' => 'weeks' - ]; - - $this->createProduct('1d1eeedd6d22436385580e2ff42431b9', 'Subscription (1x Daily)', 'MOL_SUB_1', $category, $description, 19, $image, false, $customFieldsDaily, $this->repoProducts, $this->utils); - $this->createProduct('1d2eeedd6d22436385580e2ff42431b9', 'Subscription (1x Weekly)', 'MOL_SUB_2', $category, $description, 29, $image, false, $customFieldsWeekly, $this->repoProducts, $this->utils); - $this->createProduct('1d2eeedd6d22436385580e2ff42431c6', 'Subscription (3x Weekly)', 'MOL_SUB_3', $category, $description, 29, $image, false, $customFieldsThreeWeekly, $this->repoProducts, $this->utils); - } - - public function uninstall(): void - { - $this->repoProducts->delete( - [ - ['id' => '1d1eeedd6d22436385580e2ff42431b9'], - ['id' => '1d2eeedd6d22436385580e2ff42431b9'], - ['id' => '1d2eeedd6d22436385580e2ff42431c6'] - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Product/Traits/ProductFixtureTrait.php b/src/Components/Fixtures/Handler/Product/Traits/ProductFixtureTrait.php deleted file mode 100644 index ed14433fe..000000000 --- a/src/Components/Fixtures/Handler/Product/Traits/ProductFixtureTrait.php +++ /dev/null @@ -1,111 +0,0 @@ - $customFields - * @param EntityRepository $repoProducts - */ - protected function createProduct(string $id, string $name, string $number, string $categoryName, string $description, float $price, string $image, bool $shippingFree, array $customFields, $repoProducts, FixtureUtils $fixtureUtils): void - { - $this->utils = $fixtureUtils; - - // just reuse the product one ;) - $mediaId = $id; - $visibilityID = $id; - $coverId = $id; - - // we have to avoid duplicate images (shopware has a problem with it in media) - // so lets copy it for our id - $imageSource = __DIR__ . '/../Assets/' . $image; - $imagePath = __DIR__ . '/../Assets/' . $id . '_' . $image; - copy($imageSource, $imagePath); - - $defaultFolder = $this->utils->getMedia()->getDefaultFolder('product'); - - if (! $defaultFolder instanceof MediaFolderEntity) { - throw new \RuntimeException('Could not find default media folder for products.'); - } - - $this->utils->getMedia()->upload( - $mediaId, - $defaultFolder->getId(), - $imagePath, - 'png', - 'image/png', - ); - - // delete our temp file again - unlink($imagePath); - - $salesChannel = $this->utils->getSalesChannels()->getStorefrontSalesChannel(); - - if (! $salesChannel instanceof SalesChannelEntity) { - throw new \RuntimeException('Could not find storefront sales channel.'); - } - - $taxRate = $this->utils->getTaxes()->getTax19(); - - if (! $taxRate instanceof TaxEntity) { - throw new \RuntimeException('Could not find 19% tax rate for products.'); - } - - $repoProducts->upsert( - [ - [ - 'id' => $id, - 'name' => $name, - 'taxId' => $taxRate->getId(), - 'productNumber' => $number, - 'description' => $description, - 'visibilities' => [ - [ - 'id' => $visibilityID, - 'salesChannelId' => $salesChannel->getId(), - 'visibility' => 30, - ] - ], - 'categories' => [ - [ - 'id' => Uuid::fromStringToHex($categoryName), - ] - ], - 'stock' => 10, - 'price' => [ - [ - 'currencyId' => Defaults::CURRENCY, - 'gross' => $price, - 'net' => $price, - 'linked' => true, - ] - ], - 'media' => [ - [ - 'id' => $coverId, - 'mediaId' => $mediaId, - ] - ], - 'coverId' => $coverId, - 'customFields' => $customFields, - 'shippingFree' => $shippingFree, - ] - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Product/VoucherProductsFixture.php b/src/Components/Fixtures/Handler/Product/VoucherProductsFixture.php deleted file mode 100644 index 4a61815af..000000000 --- a/src/Components/Fixtures/Handler/Product/VoucherProductsFixture.php +++ /dev/null @@ -1,65 +0,0 @@ - - */ - private $repoProducts; - - /** - * @param EntityRepository $repoProducts - */ - public function __construct(FixtureUtils $utils, $repoProducts) - { - $this->utils = $utils; - $this->repoProducts = $repoProducts; - } - - public function install(): void - { - $category = 'Voucher'; - $image = 'tshirt-white.png'; - $description = 'Mollie Voucher Product for testing purpose in development environment.'; - - $customFieldsEco = [ - 'mollie_payments_product_voucher_type' => '1', - ]; - - $customFieldsMeal = [ - 'mollie_payments_product_voucher_type' => '2', - ]; - - $customFieldsGift = [ - 'mollie_payments_product_voucher_type' => '3', - ]; - - $this->createProduct('4d1eeedd6d22436385580e2ff42431b9', 'Voucher ECO', 'MOL_VOUCHER_1', $category, $description, 19, $image, false, $customFieldsEco, $this->repoProducts, $this->utils); - $this->createProduct('5d1eeedd6d22436385580e2ff42431b9', 'Voucher MEAL', 'MOL_VOUCHER_2', $category, $description, 19, 'champagne.png', false, $customFieldsMeal, $this->repoProducts, $this->utils); - $this->createProduct('6d1eeedd6d22436385580e2ff42431b9', 'Voucher GIFT', 'MOL_VOUCHER_3', $category, $description, 19, $image, false, $customFieldsGift, $this->repoProducts, $this->utils); - } - - public function uninstall(): void - { - $this->repoProducts->delete( - [ - ['id' => '4d1eeedd6d22436385580e2ff42431b9'], - ['id' => '5d1eeedd6d22436385580e2ff42431b9'], - ['id' => '6d1eeedd6d22436385580e2ff42431b9'] - ], - Context::createDefaultContext() - ); - } -} diff --git a/src/Components/Fixtures/Handler/Shipment/ShipmentFixture.php b/src/Components/Fixtures/Handler/Shipment/ShipmentFixture.php deleted file mode 100644 index 3fe7bcd10..000000000 --- a/src/Components/Fixtures/Handler/Shipment/ShipmentFixture.php +++ /dev/null @@ -1,155 +0,0 @@ - - */ - private $repoShipments; - - /** - * @var EntityRepository - */ - private $repoSalesChannels; - - /** - * @var EntityRepository - */ - private $repoRules; - - private CurrencyUtils $currencyUtils; - - private DeliveryTimesUtils $deliveryTimesUtils; - - /** - * @param EntityRepository $repoShipments - * @param EntityRepository $repoSalesChannels - * @param EntityRepository $repoRules - */ - public function __construct($repoShipments, $repoSalesChannels, $repoRules, CurrencyUtils $currencyUtils, DeliveryTimesUtils $deliveryTimesUtils) - { - $this->repoShipments = $repoShipments; - $this->repoSalesChannels = $repoSalesChannels; - $this->repoRules = $repoRules; - $this->currencyUtils = $currencyUtils; - $this->deliveryTimesUtils = $deliveryTimesUtils; - } - - public function install(): void - { - $ctx = Context::createDefaultContext(); - - // load all-customer rules - // because in old shopware versions this had to be assigned, NULL was not possible as ruleId - $allCustomersRule = $this->getAllCustomersRule($ctx); - - $ruleId = ($allCustomersRule instanceof RuleEntity) ? $allCustomersRule->getId() : null; - - $this->createShipment(self::SHIPMENT_ID, 'Mollie Test Shipment', $ruleId, $ctx); - } - - public function uninstall(): void - { - $ctx = Context::createDefaultContext(); - - $this->repoShipments->delete([['id' => self::SHIPMENT_ID]], $ctx); - } - - private function createShipment(string $id, string $name, ?string $ruleId, Context $context): void - { - $currencyEuro = $this->currencyUtils->getCurrency('EUR'); - $deliveryTime = $this->deliveryTimesUtils->getRandomDeliveryTime(); - - $this->repoShipments->upsert([ - [ - 'id' => $id, - 'active' => true, - 'name' => $name, - 'availabilityRuleId' => $ruleId, - 'technicalName' => 'mollie_fixture_shipment', - 'deliveryTimeId' => $deliveryTime->getId(), - 'prices' => [ - [ - 'id' => '021eeedd6d22436385580e2ff42431b3', - 'calculation' => 2, - 'quantityStart' => 0, - 'currencyPrice' => [ - [ - 'currencyId' => $currencyEuro->getId(), - 'net' => 4.19, - 'gross' => 4.99, - 'linked' => false - ] - ] - ] - ], - 'translations' => [ - 'de-DE' => [ - 'trackingUrl' => 'https://www.carrier.com/de/tracking/%s' - ], - 'en-GB' => [ - 'trackingUrl' => 'https://www.carrier.com/en/tracking/%s' - ] - ] - ], - ], $context); - - $salesChannelIds = $this->repoSalesChannels->searchIds(new Criteria(), $context)->getIds(); - - $this->assignShippingMethod($id, $salesChannelIds, $context); - } - - /** - * @param array $salesChannelIds - */ - private function assignShippingMethod(string $shippingId, array $salesChannelIds, Context $ctx): void - { - $paymentUpdates = []; - $scShippingIds = []; - - $scShippingIds[] = [ - 'id' => $shippingId, - ]; - - foreach ($salesChannelIds as $id) { - $paymentUpdates[] = [ - 'id' => $id, - 'shippingMethods' => $scShippingIds, - ]; - } - - $this->repoSalesChannels->update($paymentUpdates, $ctx); - } - - private function getAllCustomersRule(Context $ctx): ?RuleEntity - { - $allRules = $this->repoRules->search(new Criteria(), $ctx); - - /** @var RuleEntity $rule */ - foreach ($allRules->getElements() as $rule) { - $name = $rule->getName(); - - if ($name === 'All customers' || str_contains($name, 'Alle Kunden')) { - return $rule; - } - } - - return null; - } -} diff --git a/src/Components/Fixtures/MollieFixtureHandlerInterface.php b/src/Components/Fixtures/MollieFixtureHandlerInterface.php deleted file mode 100644 index a447f1152..000000000 --- a/src/Components/Fixtures/MollieFixtureHandlerInterface.php +++ /dev/null @@ -1,11 +0,0 @@ - - */ - private $currencyRepository; - - /** - * @param EntityRepository $currencyRepository - */ - public function __construct($currencyRepository) - { - $this->currencyRepository = $currencyRepository; - } - - public function getCurrency(string $iso): CurrencyEntity - { - $criteria = (new Criteria()) - ->addFilter(new EqualsFilter('isoCode', $iso)) - ->setLimit(1) - ; - - $currency = $this->currencyRepository - ->search($criteria, Context::createDefaultContext()) - ->first() - ; - - if (! $currency instanceof CurrencyEntity) { - throw new \RuntimeException(sprintf('Currency with ISO code "%s" not found.', $iso)); - } - - return $currency; - } -} diff --git a/src/Components/Fixtures/Utils/DeliveryTimesUtils.php b/src/Components/Fixtures/Utils/DeliveryTimesUtils.php deleted file mode 100644 index 1075b0aca..000000000 --- a/src/Components/Fixtures/Utils/DeliveryTimesUtils.php +++ /dev/null @@ -1,42 +0,0 @@ - - */ - private $repoDeliveryTimes; - - /** - * @param EntityRepository $repoDeliveryTimes - */ - public function __construct($repoDeliveryTimes) - { - $this->repoDeliveryTimes = $repoDeliveryTimes; - } - - public function getRandomDeliveryTime(): DeliveryTimeEntity - { - $criteria = new Criteria(); - - $deliveryTime = $this->repoDeliveryTimes - ->search($criteria, Context::createDefaultContext()) - ->first() - ; - - if (! $deliveryTime instanceof DeliveryTimeEntity) { - throw new \RuntimeException('No delivery times found in the system. Please create at least one delivery time before installing the Mollie Payments fixtures.'); - } - - return $deliveryTime; - } -} diff --git a/src/Components/Fixtures/Utils/MediaUtils.php b/src/Components/Fixtures/Utils/MediaUtils.php deleted file mode 100644 index 3c2d017f5..000000000 --- a/src/Components/Fixtures/Utils/MediaUtils.php +++ /dev/null @@ -1,100 +0,0 @@ - - */ - private $mediaRepository; - - /** - * @var EntityRepository - */ - private $mediaFolderRepository; - - private FileSaver $fileSaver; - private FileFetcher $fileFetcher; - - /** - * @param EntityRepository $mediaRepository - * @param EntityRepository $mediaFolderRepository - */ - public function __construct( - $mediaRepository, - $mediaFolderRepository, - FileSaver $fileSaver, - FileFetcher $fileFetcher - ) { - $this->fileFetcher = $fileFetcher; - $this->fileSaver = $fileSaver; - $this->mediaFolderRepository = $mediaFolderRepository; - $this->mediaRepository = $mediaRepository; - } - - /** - * Copied from "vendor/shopware/core/Content/Media/MediaService.php". - * - * Extended it to include simple cache - */ - public function getDefaultFolder(string $folderName): ?MediaFolderEntity - { - $criteria = (new Criteria()) - ->addFilter(new EqualsFilter('media_folder.defaultFolder.entity', $folderName)) - ->addAssociation('defaultFolder') - ->setLimit(1) - ; - - $criteria->setTitle(\sprintf('%s::%s()', __CLASS__, __FUNCTION__)); - - $mediaFolder = $this->mediaFolderRepository - ->search($criteria, Context::createDefaultContext()) - ->first() - ; - - return $mediaFolder instanceof MediaFolderEntity ? $mediaFolder : null; - } - - /** - * "Upload" a file within shopware. It takes a real file path ($filename) and uploads it as a full media. - */ - public function upload(string $mediaId, string $folderId, string $filename, string $extension, string $contentType): void - { - $ctx = Context::createDefaultContext(); - - $this->mediaRepository->upsert( - [ - [ - 'id' => $mediaId, - 'mediaFolderId' => $folderId, - ], - ], - $ctx, - ); - - $uploadedFile = $this->fileFetcher->fetchBlob( - (string) file_get_contents($filename), - $extension, - $contentType, - ); - - $this->fileSaver->persistFileToMedia( - $uploadedFile, - basename($filename, '.' . $extension), - $mediaId, - $ctx, - ); - } -} diff --git a/src/Components/Fixtures/Utils/SalesChannelUtils.php b/src/Components/Fixtures/Utils/SalesChannelUtils.php deleted file mode 100644 index e814bda5c..000000000 --- a/src/Components/Fixtures/Utils/SalesChannelUtils.php +++ /dev/null @@ -1,53 +0,0 @@ - - */ - private $salesChannelRepository; - - /** - * @param EntityRepository $salesChannelRepository - */ - public function __construct($salesChannelRepository) - { - $this->salesChannelRepository = $salesChannelRepository; - } - - /** - * Return the first sales channel with type "Storefront" or null if non was found. - */ - public function getStorefrontSalesChannel(): ?SalesChannelEntity - { - return $this->getSalesChannelByType(Defaults::SALES_CHANNEL_TYPE_STOREFRONT); - } - - public function getSalesChannelByType(string $salesChannelType): ?SalesChannelEntity - { - $criteria = (new Criteria()) - ->addFilter(new EqualsFilter('typeId', $salesChannelType)) - ->setLimit(1) - ; - - $criteria->setTitle(\sprintf('%s::%s()', __CLASS__, __FUNCTION__)); - - $salesChannel = $this->salesChannelRepository - ->search($criteria, Context::createDefaultContext()) - ->first() - ; - - return $salesChannel instanceof SalesChannelEntity ? $salesChannel : null; - } -} diff --git a/src/Components/Fixtures/Utils/TaxUtils.php b/src/Components/Fixtures/Utils/TaxUtils.php deleted file mode 100644 index 731208d4b..000000000 --- a/src/Components/Fixtures/Utils/TaxUtils.php +++ /dev/null @@ -1,55 +0,0 @@ - - */ - private $taxRepository; - - /** - * @param EntityRepository $taxRepository - */ - public function __construct($taxRepository) - { - $this->taxRepository = $taxRepository; - } - - /** - * Return the tax entity with a tax rate of 19% or null if none exists. - */ - public function getTax19(): ?TaxEntity - { - return $this->getTax(19); - } - - /** - * Return a tax entity with a specific tax rate or null if none exists. - */ - public function getTax(float $taxRate): ?TaxEntity - { - $criteria = (new Criteria()) - ->addFilter(new EqualsFilter('taxRate', $taxRate)) - ->setLimit(1) - ; - - $criteria->setTitle(\sprintf('%s::%s()', __CLASS__, __FUNCTION__)); - - $tax = $this->taxRepository - ->search($criteria, Context::createDefaultContext()) - ->first() - ; - - return $tax instanceof TaxEntity ? $tax : null; - } -} diff --git a/src/Components/Installer/PluginInstaller.php b/src/Components/Installer/PluginInstaller.php index 1aced5f0a..c6e8b1fac 100644 --- a/src/Components/Installer/PluginInstaller.php +++ b/src/Components/Installer/PluginInstaller.php @@ -7,6 +7,7 @@ use Kiener\MolliePayments\Components\Subscription\Services\Installer\MailTemplateInstaller; use Kiener\MolliePayments\Service\Installer\CustomFieldsInstaller; use Kiener\MolliePayments\Service\PaymentMethodService; +use Mollie\Shopware\Component\Payment\PaymentMethodInstaller; use Shopware\Core\Framework\Context; class PluginInstaller @@ -26,13 +27,19 @@ class PluginInstaller */ private $subscriptionMailInstaller; private ApplePayDomainVerificationService $domainFileDownloader; + private PaymentMethodInstaller $paymentMethodInstaller; - public function __construct(CustomFieldsInstaller $customFieldsInstaller, PaymentMethodService $paymentMethodService, ApplePayDomainVerificationService $domainFileDownloader, MailTemplateInstaller $subscriptionMailInstaller) + public function __construct(CustomFieldsInstaller $customFieldsInstaller, + PaymentMethodService $paymentMethodService, + PaymentMethodInstaller $paymentMethodInstaller, + ApplePayDomainVerificationService $domainFileDownloader, + MailTemplateInstaller $subscriptionMailInstaller) { $this->customFieldsInstaller = $customFieldsInstaller; $this->paymentMethodService = $paymentMethodService; $this->subscriptionMailInstaller = $subscriptionMailInstaller; $this->domainFileDownloader = $domainFileDownloader; + $this->paymentMethodInstaller = $paymentMethodInstaller; } /** @@ -43,7 +50,7 @@ public function install(Context $context): void $this->customFieldsInstaller->install($context); $this->paymentMethodService->installAndActivatePaymentMethods($context); - + $this->paymentMethodInstaller->install($context); $this->subscriptionMailInstaller->install($context); $this->domainFileDownloader->downloadDomainAssociationFile(); } diff --git a/src/Components/OrderExpiration/ExpireAction.php b/src/Components/OrderExpiration/ExpireAction.php index 1adc1cca0..17c84aeb3 100644 --- a/src/Components/OrderExpiration/ExpireAction.php +++ b/src/Components/OrderExpiration/ExpireAction.php @@ -3,7 +3,6 @@ namespace Kiener\MolliePayments\Components\OrderExpiration; -use Kiener\MolliePayments\Handler\Method\BankTransferPayment; use Kiener\MolliePayments\Service\Order\OrderExpireService; use Kiener\MolliePayments\Service\SettingsService; use Psr\Log\LoggerInterface; @@ -83,7 +82,7 @@ private function expireOrdersInSalesChannel(SalesChannelEntity $salesChannelEnti $this->logger->info('Start expire orders for saleschannel', ['salesChannel' => $salesChannelEntity->getName()]); $date = new \DateTime(); - $date->modify(sprintf('-%d days', BankTransferPayment::DUE_DATE_MAX_DAYS + 1)); + $date->modify(sprintf('-%d days', 101)); $orFilterArray = [ new EqualsFilter('transactions.stateMachineState.technicalName', OrderTransactionStates::STATE_IN_PROGRESS), diff --git a/src/Components/PaypalExpress/PayPalExpress.php b/src/Components/PaypalExpress/PayPalExpress.php deleted file mode 100644 index 55ac43cf6..000000000 --- a/src/Components/PaypalExpress/PayPalExpress.php +++ /dev/null @@ -1,200 +0,0 @@ -repoPaymentMethods = $repoPaymentMethods; - $this->mollieApiFactory = $mollieApiFactory; - $this->priceBuilder = $priceBuilder; - $this->urlBuilder = $urlBuilder; - $this->customerService = $customerService; - $this->cartService = $cartService; - } - - public function isPaypalExpressPaymentMethodEnabled(SalesChannelContext $context): bool - { - try { - $methodID = $this->getActivePaypalExpressID($context); - - return ! empty($methodID); - } catch (\Exception $ex) { - return false; - } - } - - /** - * @throws \Exception - */ - public function getActivePaypalExpressID(SalesChannelContext $context): string - { - $criteria = new Criteria(); - $criteria->addAssociation('salesChannels'); - $criteria->addFilter(new EqualsFilter('handlerIdentifier', PayPalExpressPayment::class)); - $criteria->addFilter(new EqualsFilter('active', true)); - $criteria->addFilter(new EqualsFilter('salesChannels.id', $context->getSalesChannelId())); - - /** @var array $paymentMethods */ - $paymentMethods = $this->repoPaymentMethods->getRepository()->searchIds($criteria, $context->getContext())->getIds(); - - if (count($paymentMethods) <= 0) { - throw new \Exception('Payment Method PayPal Express not found in system'); - } - - return (string) $paymentMethods[0]; - } - - /** - * @throws \Mollie\Api\Exceptions\ApiException - */ - public function startSession(Cart $cart, SalesChannelContext $context): Session - { - $mollie = $this->mollieApiFactory->getLiveClient($context->getSalesChannelId()); - - $params = [ - 'method' => 'paypal', - 'methodDetails' => [ - 'checkoutFlow' => 'express', - ], - 'description' => 'Paypal Express', - 'amount' => $this->priceBuilder->build( - $cart->getPrice()->getTotalPrice(), - $context->getCurrency()->getIsoCode() - ), - 'redirectUrl' => $this->urlBuilder->buildPaypalExpressRedirectUrl(), - 'cancelUrl' => $this->urlBuilder->buildPaypalExpressCancelUrl(), - ]; - - return $mollie->sessions->create($params); - } - - public function loadSession(string $sessionId, SalesChannelContext $context): Session - { - $mollie = $this->mollieApiFactory->getLiveClient($context->getSalesChannelId()); - /* - * if we load the session from mollie api, we dont get the shipping address at first time. usually it takes several seconds until the data from paypal is transfered to mollie - * so we try to load the session at least 5 times with increased waiting time. - */ - for ($i = 0; $i < self::SESSION_MAX_RETRY; ++$i) { - $sleepTimer = self::SESSION_BASE_TIMEOUT * ($i + 1); - usleep($sleepTimer); - $session = $mollie->sessions->get($sessionId); - if ($session->methodDetails !== null && property_exists($session->methodDetails, 'shippingAddress') && $session->methodDetails->shippingAddress !== null) { - break; - } - } - - return $session; - } - - /** - * @throws \Exception - */ - public function prepareCustomer(AddressStruct $shippingAddress, SalesChannelContext $context, ?int $acceptedDataProtection, ?AddressStruct $billingAddress = null): SalesChannelContext - { - $updateShippingAddress = true; - $paypalExpressId = $this->getActivePaypalExpressID($context); - - $customer = $context->getCustomer(); - - // if we are not logged in, - // then we have to create a new guest customer for our express order - // check here for instance because of phpstan - if ($customer === null) { - // find existing customer by email - $customer = $this->customerService->findCustomerByEmail($shippingAddress->getEmail(), $context); - - if ($customer === null) { - $updateShippingAddress = false; - $customer = $this->customerService->createGuestAccount( - $shippingAddress, - $paypalExpressId, - $context, - $acceptedDataProtection, - $billingAddress - ); - } - - if (! $customer instanceof CustomerEntity) { - throw new \Exception('Error when creating customer!'); - } - - // now start the login of our customer. - // Our SalesChannelContext will be correctly updated after our - // forward to the finish-payment page. - $this->customerService->loginCustomer($customer, $context); - } - - // if we have an existing customer, we want reuse his shipping address instead of creating new one - if ($updateShippingAddress) { - $this->customerService->reuseOrCreateAddresses($customer, $shippingAddress, $context->getContext(), $billingAddress); - } - - // also (always) update our payment method to use Apple Pay for our cart - return $this->cartService->updatePaymentMethod($context, $paypalExpressId); - } - - public function cancelSession(string $sessionId, SalesChannelContext $context): Session - { - $mollie = $this->mollieApiFactory->getLiveClient($context->getSalesChannelId()); - - return $mollie->sessions->cancel($sessionId); - } -} diff --git a/src/Components/PaypalExpress/Route/AbstractCancelCheckoutRoute.php b/src/Components/PaypalExpress/Route/AbstractCancelCheckoutRoute.php deleted file mode 100644 index 052fdc819..000000000 --- a/src/Components/PaypalExpress/Route/AbstractCancelCheckoutRoute.php +++ /dev/null @@ -1,13 +0,0 @@ -settingsService = $settingsService; - $this->paypalExpress = $paypalExpress; - $this->cartService = $cartService; - } - - public function getDecorated(): AbstractStartCheckoutRoute - { - throw new DecorationPatternException(self::class); - } - - public function cancelCheckout(SalesChannelContext $context): CancelCheckoutResponse - { - $settings = $this->settingsService->getSettings($context->getSalesChannelId()); - - if ($settings->isPaypalExpressEnabled() === false) { - throw PaypalExpressException::paymentNotEnabled($context->getSalesChannelId()); - } - - $cart = $this->cartService->getCalculatedMainCart($context); - $mollieShopwareCart = new MollieShopwareCart($cart); - - // get the existing session ID - $sessionId = $mollieShopwareCart->getPayPalExpressSessionID(); - - // clear the Auth-ID and save the cart - // this is important, the rest of the handling is done in the PaypalExpressSubscriber - $mollieShopwareCart->setPayPalExpressAuthenticateId(''); - $cart = $mollieShopwareCart->getCart(); - $this->cartService->persistCart($cart, $context); - - if ($sessionId === '') { - throw PaypalExpressException::cartSessionIdIsEmpty(); - } - - try { - $this->paypalExpress->cancelSession($sessionId, $context); - } catch (\Throwable $e) { - // todo: remove try catch once cancel is possible from mollie - } - - return new CancelCheckoutResponse($sessionId); - } -} diff --git a/src/Components/PaypalExpress/Route/FinishCheckoutRoute.php b/src/Components/PaypalExpress/Route/FinishCheckoutRoute.php deleted file mode 100644 index 1fa590a2b..000000000 --- a/src/Components/PaypalExpress/Route/FinishCheckoutRoute.php +++ /dev/null @@ -1,122 +0,0 @@ -settingsService = $settingsService; - $this->cartService = $cartService; - $this->paypalExpress = $paypalExpress; - } - - public function getDecorated(): AbstractStartCheckoutRoute - { - throw new DecorationPatternException(self::class); - } - - public function finishCheckout(SalesChannelContext $context): FinishCheckoutResponse - { - $settings = $this->settingsService->getSettings($context->getSalesChannelId()); - - if ($settings->isPaypalExpressEnabled() === false) { - throw PaypalExpressException::paymentNotEnabled($context->getSalesChannelId()); - } - - $cart = $this->cartService->getCalculatedMainCart($context); - $mollieShopwareCart = new MollieShopwareCart($cart); - - $payPalExpressSessionId = $mollieShopwareCart->getPayPalExpressSessionID(); - $acceptedDataProtection = $mollieShopwareCart->isDataProtectionAccepted(); - - if ($payPalExpressSessionId === '') { - throw PaypalExpressException::cartSessionIdIsEmpty(); - } - - $payPalExpressSession = $this->paypalExpress->loadSession($payPalExpressSessionId, $context); - - $methodDetails = $payPalExpressSession->methodDetails; - - if (! property_exists($methodDetails, 'shippingAddress') || $methodDetails->shippingAddress === null) { - throw PaypalExpressException::shippingAddressMissing(); - } - if (! property_exists($methodDetails, 'billingAddress') || $methodDetails->billingAddress === null) { - throw PaypalExpressException::billingAddressMissing(); - } - - $billingAddress = null; - - $mollieShippingAddress = $methodDetails->shippingAddress; - if (! property_exists($mollieShippingAddress, 'phone')) { - $mollieShippingAddress->phone = ''; - } - if (! property_exists($mollieShippingAddress, 'streetAdditional')) { - $mollieShippingAddress->streetAdditional = ''; - } - if (! property_exists($mollieShippingAddress, 'email')) { - $mollieShippingAddress->email = ''; - } - - if ($methodDetails->billingAddress->streetAdditional !== null) { - $mollieShippingAddress->streetAdditional = $methodDetails->billingAddress->streetAdditional; - } - if ($methodDetails->billingAddress->phone !== null) { - $mollieShippingAddress->phone = $methodDetails->billingAddress->phone; - } - if ($methodDetails->billingAddress->email !== null) { - $mollieShippingAddress->email = $methodDetails->billingAddress->email; - } - if ($methodDetails->billingAddress->streetAndNumber !== null) { - try { - $billingAddress = AddressStruct::createFromApiResponse($methodDetails->billingAddress); - } catch (\Throwable $e) { - throw PaypalExpressException::billingAddressError($e->getMessage(), $methodDetails->billingAddress); - } - } - - try { - $shippingAddress = AddressStruct::createFromApiResponse($mollieShippingAddress); - } catch (\Throwable $e) { - throw PaypalExpressException::shippingAddressError($e->getMessage(), $mollieShippingAddress); - } - $oldToken = $context->getToken(); - // create new account or find existing and login - $context = $this->paypalExpress->prepareCustomer($shippingAddress, $context, $acceptedDataProtection, $billingAddress); - - // read a new card after login - if ($context->getToken() !== $oldToken) { - $cart = $this->cartService->getCalculatedMainCart($context); - } - - // we have to update the cart extension before a new user is created and logged in, otherwise the extension is not saved - $mollieShopwareCart = new MollieShopwareCart($cart); - $mollieShopwareCart->setPayPalExpressAuthenticateId($payPalExpressSession->authenticationId); - - $cart = $mollieShopwareCart->getCart(); - $this->cartService->updateCart($cart); - $this->cartService->persistCart($cart, $context); - - return new FinishCheckoutResponse($payPalExpressSession->id, $payPalExpressSession->authenticationId); - } -} diff --git a/src/Components/PaypalExpress/Route/StartCheckoutRoute.php b/src/Components/PaypalExpress/Route/StartCheckoutRoute.php deleted file mode 100644 index 2fd4efe14..000000000 --- a/src/Components/PaypalExpress/Route/StartCheckoutRoute.php +++ /dev/null @@ -1,88 +0,0 @@ -settingsService = $settingsService; - $this->cartService = $cartService; - $this->paypalExpress = $paypalExpress; - } - - public function getDecorated(): AbstractStartCheckoutRoute - { - throw new DecorationPatternException(self::class); - } - - /** - * @throws \Mollie\Api\Exceptions\ApiException - * @throws PaymentException - */ - public function startCheckout(Request $request, SalesChannelContext $context): StartCheckoutResponse - { - $settings = $this->settingsService->getSettings($context->getSalesChannelId()); - - if ($settings->isPaypalExpressEnabled() === false) { - throw PaypalExpressException::paymentNotEnabled($context->getSalesChannelId()); - } - - $cart = $this->cartService->getCalculatedMainCart($context); - - if ($cart->getLineItems()->count() === 0) { - throw PaypalExpressException::cartIsEmpty(); - } - - $mollieShopwareCart = new MollieShopwareCart($cart); - - $sessionId = $mollieShopwareCart->getPayPalExpressSessionID(); - - if ($sessionId === '') { - $session = $this->paypalExpress->startSession($cart, $context); - } else { - $session = $this->paypalExpress->loadSession($sessionId, $context); - } - - if ($session->id === null) { - throw PaypalExpressException::missingSessionId(); - } - - $mollieShopwareCart->setPayPalExpressSessionID($session->id); - - if ($settings->isRequireDataProtectionCheckbox()) { - $mollieShopwareCart->setDataProtectionAccepted((int) $request->get(CustomFieldsInterface::ACCEPTED_DATA_PROTECTION, 0)); - } - - $cart = $mollieShopwareCart->getCart(); - - $this->cartService->persistCart($cart, $context); - - return new StartCheckoutResponse( - $session->id, - $session->getRedirectUrl() - ); - } -} diff --git a/src/Components/ShipmentManager/ShipmentManager.php b/src/Components/ShipmentManager/ShipmentManager.php index aec96b481..a203539ca 100644 --- a/src/Components/ShipmentManager/ShipmentManager.php +++ b/src/Components/ShipmentManager/ShipmentManager.php @@ -6,7 +6,6 @@ use Kiener\MolliePayments\Components\ShipmentManager\Exceptions\NoDeliveriesFoundException; use Kiener\MolliePayments\Components\ShipmentManager\Exceptions\NoLineItemsProvidedException; use Kiener\MolliePayments\Components\ShipmentManager\Models\TrackingData; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Struct\MollieStatus; use Kiener\MolliePayments\Exception\OrderLineItemFoundManyException; use Kiener\MolliePayments\Exception\OrderLineItemNotFoundException; use Kiener\MolliePayments\Service\CustomFieldsInterface; @@ -21,6 +20,7 @@ use Kiener\MolliePayments\Struct\MollieApi\ShipmentTrackingInfoStruct; use Kiener\MolliePayments\Struct\Order\OrderAttributes; use Kiener\MolliePayments\Struct\OrderLineItemEntity\OrderLineItemEntityAttributes; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Struct\MollieStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Cart\LineItem\LineItem; use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemCollection; diff --git a/src/Components/Subscription/Actions/Base/BaseAction.php b/src/Components/Subscription/Actions/Base/BaseAction.php index f1c86b72e..005b0bd68 100644 --- a/src/Components/Subscription/Actions/Base/BaseAction.php +++ b/src/Components/Subscription/Actions/Base/BaseAction.php @@ -7,7 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderEventFactory; use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\SubscriptionCancellation\CancellationValidator; @@ -16,6 +15,7 @@ use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Setting\MollieSettingStruct; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; diff --git a/src/Components/Subscription/Actions/CancelAction.php b/src/Components/Subscription/Actions/CancelAction.php index a7fdea77c..c5dc88de4 100644 --- a/src/Components/Subscription/Actions/CancelAction.php +++ b/src/Components/Subscription/Actions/CancelAction.php @@ -4,8 +4,8 @@ namespace Kiener\MolliePayments\Components\Subscription\Actions; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Shopware\Core\Framework\Context; class CancelAction extends BaseAction diff --git a/src/Components/Subscription/Actions/ConfirmAction.php b/src/Components/Subscription/Actions/ConfirmAction.php index 6c69cad6d..1133b701c 100644 --- a/src/Components/Subscription/Actions/ConfirmAction.php +++ b/src/Components/Subscription/Actions/ConfirmAction.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Components\Subscription\Actions; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Exception\CustomerCouldNotBeFoundException; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; @@ -77,7 +77,7 @@ public function confirmSubscription(OrderEntity $order, string $mandateId, Conte $pendingSubscription, $metaData->getStartDate(), (string) $metaData->getInterval(), - $metaData->getIntervalUnit(), + $metaData->getIntervalUnit()->value, (int) $metaData->getTimes(), $mandateId ); diff --git a/src/Components/Subscription/Actions/CreateAction.php b/src/Components/Subscription/Actions/CreateAction.php index 82a8debc7..ab966b9c1 100644 --- a/src/Components/Subscription/Actions/CreateAction.php +++ b/src/Components/Subscription/Actions/CreateAction.php @@ -7,7 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\SubscriptionCancellation\CancellationValidator; @@ -19,6 +18,7 @@ use Kiener\MolliePayments\Service\Tags\Exceptions\CouldNotTagOrderException; use Kiener\MolliePayments\Service\Tags\OrderTagService; use Kiener\MolliePayments\Struct\OrderLineItemEntity\OrderLineItemEntityAttributes; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity; use Shopware\Core\Checkout\Order\OrderEntity; diff --git a/src/Components/Subscription/Actions/PauseAction.php b/src/Components/Subscription/Actions/PauseAction.php index 2c4ee3996..13411451b 100644 --- a/src/Components/Subscription/Actions/PauseAction.php +++ b/src/Components/Subscription/Actions/PauseAction.php @@ -4,7 +4,7 @@ namespace Kiener\MolliePayments\Components\Subscription\Actions; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Shopware\Core\Framework\Context; class PauseAction extends BaseAction diff --git a/src/Components/Subscription/Actions/RemindAction.php b/src/Components/Subscription/Actions/RemindAction.php index b4c8dab56..b05f48cbf 100644 --- a/src/Components/Subscription/Actions/RemindAction.php +++ b/src/Components/Subscription/Actions/RemindAction.php @@ -7,8 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\SubscriptionCancellation\CancellationValidator; @@ -17,6 +15,8 @@ use Kiener\MolliePayments\Gateway\MollieGatewayInterface; use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Context; diff --git a/src/Components/Subscription/Actions/RenewAction.php b/src/Components/Subscription/Actions/RenewAction.php index c92a6ba5a..ae538750c 100644 --- a/src/Components/Subscription/Actions/RenewAction.php +++ b/src/Components/Subscription/Actions/RenewAction.php @@ -3,13 +3,10 @@ namespace Kiener\MolliePayments\Components\Subscription\Actions; -use Exception; use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderEventFactory; use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Struct\SubscriptionMetadata; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Exception\SubscriptionSkippedException; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; @@ -21,6 +18,8 @@ use Kiener\MolliePayments\Service\Mollie\MolliePaymentStatus; use Kiener\MolliePayments\Service\Mollie\OrderStatusConverter; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; +use Mollie\Shopware\Component\Subscription\SubscriptionMetadata; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; diff --git a/src/Components/Subscription/Actions/ResumeAction.php b/src/Components/Subscription/Actions/ResumeAction.php index 05ca4c386..02356193d 100644 --- a/src/Components/Subscription/Actions/ResumeAction.php +++ b/src/Components/Subscription/Actions/ResumeAction.php @@ -7,9 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Interval\IntervalCalculator; @@ -18,6 +15,9 @@ use Kiener\MolliePayments\Gateway\MollieGatewayInterface; use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Framework\Context; @@ -87,7 +87,7 @@ public function resumeSubscription(string $subscriptionId, \DateTimeInterface $t $subscription, $nextPaymentDate->format('Y-m-d'), (string) $metaData->getInterval(), - $metaData->getIntervalUnit(), + (string) $metaData->getIntervalUnit()->value, (int) $metaData->getTimes(), $subscription->getMandateId() ); diff --git a/src/Components/Subscription/Actions/SkipAction.php b/src/Components/Subscription/Actions/SkipAction.php index 6dbbb44d0..458604b44 100644 --- a/src/Components/Subscription/Actions/SkipAction.php +++ b/src/Components/Subscription/Actions/SkipAction.php @@ -4,8 +4,8 @@ namespace Kiener\MolliePayments\Components\Subscription\Actions; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Services\Interval\IntervalCalculator; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Shopware\Core\Framework\Context; class SkipAction extends BaseAction @@ -71,15 +71,15 @@ public function skipSubscription(string $subscriptionId, int $skipCount, Context $nextPaymentDate = $intervalCalculator->getNextIntervalDate( $currentSubscriptionNextPaymentAt, - (int) $metaData->getInterval(), - $metaData->getIntervalUnit() + (int) $metaData->getIntervalValue(), + (string) $metaData->getIntervalUnit()->value ); $jsonPayload = $this->getPayloadBuilder()->buildRequestPayload( $subscription, $nextPaymentDate, - (string) $metaData->getInterval(), - $metaData->getIntervalUnit(), + (string) $metaData->getIntervalValue(), + (string) $metaData->getIntervalUnit()->value, (int) $metaData->getTimes(), $subscription->getMandateId() ); diff --git a/src/Components/Subscription/Actions/UpdateAddressAction.php b/src/Components/Subscription/Actions/UpdateAddressAction.php index 1b73a7e19..037cd48c4 100644 --- a/src/Components/Subscription/Actions/UpdateAddressAction.php +++ b/src/Components/Subscription/Actions/UpdateAddressAction.php @@ -7,8 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\SubscriptionCancellation\CancellationValidator; @@ -17,6 +15,8 @@ use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\OrderService; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressEntity; use Shopware\Core\Framework\Context; diff --git a/src/Components/Subscription/Actions/UpdatePaymentAction.php b/src/Components/Subscription/Actions/UpdatePaymentAction.php index f6642774c..4bf3f4773 100644 --- a/src/Components/Subscription/Actions/UpdatePaymentAction.php +++ b/src/Components/Subscription/Actions/UpdatePaymentAction.php @@ -7,7 +7,6 @@ use Kiener\MolliePayments\Compatibility\Bundles\FlowBuilder\FlowBuilderFactory; use Kiener\MolliePayments\Components\Subscription\Actions\Base\BaseAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\Services\Builder\MollieDataBuilder; use Kiener\MolliePayments\Components\Subscription\Services\Builder\SubscriptionBuilder; use Kiener\MolliePayments\Components\Subscription\Services\PaymentMethodRemover\SubscriptionRemover; @@ -22,6 +21,7 @@ use Kiener\MolliePayments\Service\Router\RoutingBuilder; use Kiener\MolliePayments\Service\SettingsService; use Mollie\Api\Resources\Payment; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Framework\Context; diff --git a/src/Components/Subscription/Cart/Validator/AvailabilityInformationValidator.php b/src/Components/Subscription/Cart/Validator/AvailabilityInformationValidator.php deleted file mode 100644 index b4cb49667..000000000 --- a/src/Components/Subscription/Cart/Validator/AvailabilityInformationValidator.php +++ /dev/null @@ -1,68 +0,0 @@ -pluginSettings = $pluginSettings; - } - - public function validate(Cart $cart, ErrorCollection $errorCollection, SalesChannelContext $salesChannelContext): void - { - $settings = $this->pluginSettings->getSettings($salesChannelContext->getSalesChannel()->getId()); - - if (! $settings->isSubscriptionsEnabled()) { - $this->clearError($cart); - - return; - } - - $foundSubscriptionItem = null; - - foreach ($cart->getLineItems()->getFlat() as $lineItem) { - $attributes = new LineItemAttributes($lineItem); - - if (! $attributes->isSubscriptionProduct()) { - continue; - } - - $foundSubscriptionItem = $lineItem; - } - - if ($foundSubscriptionItem instanceof LineItem) { - $errorCollection->add(new PaymentMethodAvailabilityNotice($foundSubscriptionItem->getId())); - } else { - $this->clearError($cart); - } - } - - private function clearError(Cart $cart): void - { - $list = new ErrorCollection(); - - foreach ($cart->getErrors() as $error) { - if (! $error instanceof PaymentMethodAvailabilityNotice) { - $list->add($error); - } - } - - $cart->setErrors($list); - } -} diff --git a/src/Components/Subscription/Cart/Validator/SubscriptionCartValidator.php b/src/Components/Subscription/Cart/Validator/SubscriptionCartValidator.php deleted file mode 100644 index 104cae4e6..000000000 --- a/src/Components/Subscription/Cart/Validator/SubscriptionCartValidator.php +++ /dev/null @@ -1,120 +0,0 @@ -pluginSettings = $pluginSettings; - - $this->mixedCartValidator = new MixedCartValidator(); - } - - public function validate(Cart $cart, ErrorCollection $errorCollection, SalesChannelContext $salesChannelContext): void - { - // always clear previous errors first - $this->clearError($cart); - - $settings = $this->pluginSettings->getSettings($salesChannelContext->getSalesChannelId()); - - if (! $settings->isSubscriptionsEnabled()) { - return; - } - - // -------------------------------------------------------------------------------------------- - // first verify if we have a customer - // if we do not have one yet, then we do NOT block the cart - // this would just lead to weird errors, while the customer is not yet logged in - if ($salesChannelContext->getCustomer() === null) { - return; - } - - // -------------------------------------------------------------------------------------------- - // now verify if we even have a subscription cart - // if we don't have one, then just do nothing - if (! $this->isSubscriptionCart($cart)) { - return; - } - - // -------------------------------------------------------------------------------------------- - // now check if we have a mixed cart. - // this is not allowed! - $isMixedCart = $this->mixedCartValidator->isMixedCart($cart); - - if ($isMixedCart) { - $errorCollection->add(new MixedCartBlockError()); - } - - // -------------------------------------------------------------------------------------------- - // check if our customer is NO guest - // only real users and accounts are allowed for subscriptions - if ($salesChannelContext->getCustomer()->getGuest()) { - $errorCollection->add(new InvalidGuestAccountError()); - } - - // -------------------------------------------------------------------------------------------- - // verify that our selected payment method is - // indeed correct and the one from our list of available method. - $paymentMethod = $salesChannelContext->getPaymentMethod(); - $paymentAttributes = new PaymentMethodAttributes($paymentMethod); - - $isAllowed = in_array($paymentAttributes->getMollieIdentifier(), SubscriptionRemover::ALLOWED_METHODS); - - if (! $isAllowed) { - $errorCollection->add(new InvalidPaymentMethodError()); - } - } - - private function clearError(Cart $cart): void - { - $list = new ErrorCollection(); - - foreach ($cart->getErrors() as $error) { - if (! $error instanceof InvalidGuestAccountError - && ! $error instanceof MixedCartBlockError - && ! $error instanceof InvalidPaymentMethodError) { - $list->add($error); - } - } - - $cart->setErrors($list); - } - - private function isSubscriptionCart(Cart $cart): bool - { - foreach ($cart->getLineItems() as $lineItem) { - $attribute = new LineItemAttributes($lineItem); - - if ($attribute->isSubscriptionProduct()) { - return true; - } - } - - return false; - } -} diff --git a/src/Components/Subscription/DAL/Repository/SubscriptionRepository.php b/src/Components/Subscription/DAL/Repository/SubscriptionRepository.php index 0e37eef66..9affb1928 100644 --- a/src/Components/Subscription/DAL/Repository/SubscriptionRepository.php +++ b/src/Components/Subscription/DAL/Repository/SubscriptionRepository.php @@ -3,13 +3,13 @@ namespace Kiener\MolliePayments\Components\Subscription\DAL\Repository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Struct\SubscriptionMetadata; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Components\Subscription\Exception\SubscriptionNotFoundException; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\SubscriptionMetadata; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Pricing\CashRoundingConfig; @@ -184,10 +184,8 @@ public function insertSubscription(SubscriptionEntity $subscription, string $sta 'status' => $status, 'description' => $subscription->getDescription(), 'amount' => $subscription->getAmount(), - 'quantity' => $subscription->getQuantity(), 'currencyId' => $subscription->getCurrencyId(), 'metadata' => $subscription->getMetadata()->toArray(), - 'productId' => $subscription->getProductId(), 'orderId' => $subscription->getOrderId(), 'salesChannelId' => $subscription->getSalesChannelId(), 'totalRounding' => $totalRoundingValue, diff --git a/src/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricher.php b/src/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricher.php index 556755810..455474c23 100644 --- a/src/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricher.php +++ b/src/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricher.php @@ -4,11 +4,11 @@ namespace Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Enricher; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEvents; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Gateway\MollieGatewayInterface; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEvents; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; diff --git a/src/Components/Subscription/DAL/Subscription/Struct/SubscriptionMetadata.php b/src/Components/Subscription/DAL/Subscription/Struct/SubscriptionMetadata.php deleted file mode 100644 index b1252c685..000000000 --- a/src/Components/Subscription/DAL/Subscription/Struct/SubscriptionMetadata.php +++ /dev/null @@ -1,113 +0,0 @@ -startDate = $startDate; - $this->interval = $interval; - $this->intervalUnit = $intervalUnit; - $this->times = $times; - $this->tmpTransaction = $tmpTransactionId; - } - - /** - * @param array $metadata - */ - public static function fromArray(array $metadata): SubscriptionMetadata - { - $startDate = (array_key_exists('start_date', $metadata)) ? (string) $metadata['start_date'] : ''; - $intervalValue = (array_key_exists('interval_value', $metadata)) ? (int) $metadata['interval_value'] : 0; - $intervalUnit = (array_key_exists('interval_unit', $metadata)) ? (string) $metadata['interval_unit'] : ''; - $times = $metadata['times'] ?? null; - $tmpTransactionId = (array_key_exists('tmp_transaction', $metadata)) ? (string) $metadata['tmp_transaction'] : ''; - - return new SubscriptionMetadata( - $startDate, - $intervalValue, - $intervalUnit, - $times, - $tmpTransactionId - ); - } - - /** - * @return array - */ - public function toArray(): array - { - $data = [ - 'start_date' => $this->startDate, - 'interval_value' => $this->interval, - 'interval_unit' => $this->intervalUnit, - 'times' => $this->times, - ]; - - if (! empty($this->tmpTransaction)) { - $data['tmp_transaction'] = $this->tmpTransaction; - } - - return $data; - } - - public function getStartDate(): string - { - return $this->startDate; - } - - public function getInterval(): int - { - return $this->interval; - } - - public function getIntervalUnit(): string - { - return $this->intervalUnit; - } - - public function getTimes(): ?int - { - return $this->times; - } - - public function getTmpTransaction(): string - { - return $this->tmpTransaction; - } - - public function setTmpTransaction(string $tmpTransaction): void - { - $this->tmpTransaction = $tmpTransaction; - } -} diff --git a/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php b/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php index 3209d14f7..57032eb01 100644 --- a/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php +++ b/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php @@ -6,13 +6,12 @@ use Doctrine\DBAL\ArrayParameterType; use Doctrine\DBAL\Connection; use Doctrine\DBAL\ParameterType; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionDefinition; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionDefinition; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Dbal\Common\IterableQuery; use Shopware\Core\Framework\DataAbstractionLayer\Dbal\Common\IteratorFactory; -use Shopware\Core\Framework\DataAbstractionLayer\Entity; use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; diff --git a/src/Components/Subscription/Page/Account/SubscriptionPage.php b/src/Components/Subscription/Page/Account/SubscriptionPage.php index ac3589393..66f1aa3b0 100644 --- a/src/Components/Subscription/Page/Account/SubscriptionPage.php +++ b/src/Components/Subscription/Page/Account/SubscriptionPage.php @@ -3,8 +3,8 @@ namespace Kiener\MolliePayments\Components\Subscription\Page\Account; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult; use Shopware\Core\System\Country\CountryCollection; use Shopware\Core\System\Salutation\SalutationCollection; diff --git a/src/Components/Subscription/Page/Account/SubscriptionPageLoader.php b/src/Components/Subscription/Page/Account/SubscriptionPageLoader.php index 3bc2fcb56..4ba3972df 100644 --- a/src/Components/Subscription/Page/Account/SubscriptionPageLoader.php +++ b/src/Components/Subscription/Page/Account/SubscriptionPageLoader.php @@ -4,10 +4,10 @@ namespace Kiener\MolliePayments\Components\Subscription\Page\Account; use Kiener\MolliePayments\Compatibility\VersionCompare; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Service\CustomerService; use Kiener\MolliePayments\Service\SettingsService; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException; diff --git a/src/Components/Subscription/Services/Builder/MollieDataBuilder.php b/src/Components/Subscription/Services/Builder/MollieDataBuilder.php index 2588510bc..7b1cf4219 100644 --- a/src/Components/Subscription/Services/Builder/MollieDataBuilder.php +++ b/src/Components/Subscription/Services/Builder/MollieDataBuilder.php @@ -3,8 +3,8 @@ namespace Kiener\MolliePayments\Components\Subscription\Services\Builder; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Service\Router\RoutingBuilder; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; class MollieDataBuilder { diff --git a/src/Components/Subscription/Services/Builder/SubscriptionBuilder.php b/src/Components/Subscription/Services/Builder/SubscriptionBuilder.php index a4cb60705..c47f0108a 100644 --- a/src/Components/Subscription/Services/Builder/SubscriptionBuilder.php +++ b/src/Components/Subscription/Services/Builder/SubscriptionBuilder.php @@ -3,11 +3,12 @@ namespace Kiener\MolliePayments\Components\Subscription\Services\Builder; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Struct\SubscriptionMetadata; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Components\Subscription\Services\Interval\IntervalCalculator; use Kiener\MolliePayments\Struct\OrderLineItemEntity\OrderLineItemEntityAttributes; +use Mollie\Shopware\Component\Mollie\IntervalUnit; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\SubscriptionMetadata; use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressEntity; use Shopware\Core\Checkout\Order\Aggregate\OrderCustomer\OrderCustomerEntity; use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryCollection; @@ -65,7 +66,7 @@ private function buildItemSubscription(OrderLineItemEntity $lineItem, OrderEntit $interval = $attributes->getSubscriptionInterval(); $intervalUnit = $attributes->getSubscriptionIntervalUnit(); - $times = $attributes->getSubscriptionRepetitionCount(); + $times = (int) $attributes->getSubscriptionRepetitionCount(); $description = $lineItem->getQuantity() . 'x ' . $lineItem->getLabel() . ' (Order #' . $order->getOrderNumber() . ', ' . $lineItem->getTotalPrice() . ' ' . $order->getCurrency()->getIsoCode() . ')'; @@ -87,10 +88,8 @@ private function buildItemSubscription(OrderLineItemEntity $lineItem, OrderEntit $subscriptionEntity->setCurrency($order->getCurrency()); - $subscriptionEntity->setQuantity($lineItem->getQuantity()); - $subscriptionEntity->setCustomerId((string) $order->getOrderCustomer()->getCustomerId()); - $subscriptionEntity->setProductId((string) $lineItem->getProductId()); + $subscriptionEntity->setOrderId($order->getId()); $subscriptionEntity->setSalesChannelId($order->getSalesChannelId()); $subscriptionEntity->setTotalRounding($order->getTotalRounding()); @@ -109,7 +108,7 @@ private function buildItemSubscription(OrderLineItemEntity $lineItem, OrderEntit new SubscriptionMetadata( $firstStartDate, $interval, - $intervalUnit, + IntervalUnit::from($intervalUnit), $times, '' ) diff --git a/src/Components/Subscription/Services/Installer/MailTemplateInstaller.php b/src/Components/Subscription/Services/Installer/MailTemplateInstaller.php index 51db3f506..3036855c6 100644 --- a/src/Components/Subscription/Services/Installer/MailTemplateInstaller.php +++ b/src/Components/Subscription/Services/Installer/MailTemplateInstaller.php @@ -5,7 +5,7 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Exception; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Content\MailTemplate\Aggregate\MailTemplateType\MailTemplateTypeEntity; use Shopware\Core\Content\MailTemplate\MailTemplateEntity; @@ -83,7 +83,6 @@ public function install(Context $context): void $subscription = new SubscriptionEntity(); $subscription->setDescription('1x Sample Product (Order #1233, 24.99 EUR)'); - $subscription->setQuantity(1); $subscription->setAmount(24.99); $subscription->setCurrency($currencyEntity); $subscription->setMollieCustomerId('cst_123456'); diff --git a/src/Components/Subscription/Services/SubscriptionHistory/SubscriptionHistoryHandler.php b/src/Components/Subscription/Services/SubscriptionHistory/SubscriptionHistoryHandler.php index bc332c142..e6f3dbf63 100644 --- a/src/Components/Subscription/Services/SubscriptionHistory/SubscriptionHistoryHandler.php +++ b/src/Components/Subscription/Services/SubscriptionHistory/SubscriptionHistoryHandler.php @@ -4,8 +4,8 @@ namespace Kiener\MolliePayments\Components\Subscription\Services\SubscriptionHistory; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionHistory\SubscriptionHistoryEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\Uuid\Uuid; diff --git a/src/Components/Subscription/Services/SubscriptionRenewing/SubscriptionRenewing.php b/src/Components/Subscription/Services/SubscriptionRenewing/SubscriptionRenewing.php index 967372459..a2dfbb5b7 100644 --- a/src/Components/Subscription/Services/SubscriptionRenewing/SubscriptionRenewing.php +++ b/src/Components/Subscription/Services/SubscriptionRenewing/SubscriptionRenewing.php @@ -3,10 +3,10 @@ namespace Kiener\MolliePayments\Components\Subscription\Services\SubscriptionRenewing; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Service\OrderService; use Mollie\Api\Resources\Payment; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Aggregate\SubscriptionAddress\SubscriptionAddressEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Order\Aggregate\OrderAddress\OrderAddressEntity; use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryCollection; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCollection; diff --git a/src/Components/Subscription/Services/Validator/MixedCartValidator.php b/src/Components/Subscription/Services/Validator/MixedCartValidator.php deleted file mode 100644 index d616003f6..000000000 --- a/src/Components/Subscription/Services/Validator/MixedCartValidator.php +++ /dev/null @@ -1,40 +0,0 @@ -getLineItems()->getFlat() as $lineItem) { - $attributes = new LineItemAttributes($lineItem); - - if ($attributes->isSubscriptionProduct()) { - ++$subscriptionItemsCount; - } else { - // promotions are ok - ++$otherItemsCount; - } - - if ($otherItemsCount > 0) { - // mixed cart with other items - $isMixedCart = true; - } - - if ($subscriptionItemsCount > 1) { - // mixed cart with multiple subscription items - $isMixedCart = true; - } - } - - return $subscriptionItemsCount >= 1 && $isMixedCart; - } -} diff --git a/src/Components/Subscription/SubscriptionManager.php b/src/Components/Subscription/SubscriptionManager.php index d81e7c6d9..7e450268e 100644 --- a/src/Components/Subscription/SubscriptionManager.php +++ b/src/Components/Subscription/SubscriptionManager.php @@ -14,9 +14,9 @@ use Kiener\MolliePayments\Components\Subscription\Actions\UpdateAddressAction; use Kiener\MolliePayments\Components\Subscription\Actions\UpdatePaymentAction; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Exception\CustomerCouldNotBeFoundException; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; use Shopware\Core\System\SalesChannel\SalesChannelContext; diff --git a/src/Components/Voucher/Service/VoucherRemover.php b/src/Components/Voucher/Service/VoucherRemover.php deleted file mode 100644 index 034abb93b..000000000 --- a/src/Components/Voucher/Service/VoucherRemover.php +++ /dev/null @@ -1,63 +0,0 @@ -voucherService = $voucherService; - } - - public function removePaymentMethods(PaymentMethodRouteResponse $originalData, SalesChannelContext $context): PaymentMethodRouteResponse - { - if (! $this->isAllowedRoute()) { - return $originalData; - } - - if ($this->isOrderRoute()) { - $order = $this->getOrder($context->getContext()); - $voucherPermitted = $this->isVoucherOrder($order, $context->getContext()); - } else { - $cart = $this->getCart($context); - $voucherPermitted = (bool) $cart->getData()->get(VoucherCartCollector::VOUCHER_PERMITTED); - } - - // if voucher is allowed, then simply continue. - // we don't have to remove a payment method in that case - if ($voucherPermitted) { - return $originalData; - } - - // now search for our voucher payment method - // so that we can remove it from our list - foreach ($originalData->getPaymentMethods() as $paymentMethod) { - if ($this->voucherService->isVoucherPaymentMethod($paymentMethod)) { - $originalData->getPaymentMethods()->remove($paymentMethod->getId()); - break; - } - } - - return $originalData; - } -} diff --git a/src/Controller/Api/PaymentMethod/PaymentMethodControllerBase.php b/src/Controller/Api/PaymentMethod/PaymentMethodControllerBase.php deleted file mode 100644 index 4d15160df..000000000 --- a/src/Controller/Api/PaymentMethod/PaymentMethodControllerBase.php +++ /dev/null @@ -1,58 +0,0 @@ -paymentMethodService = $paymentMethodService; - $this->logger = $logger; - } - - public function updatePaymentMethods(Context $context): JsonResponse - { - return $this->updatePaymentMethodsAction($context); - } - - public function updatePaymentMethodsLegacy(Context $context): JsonResponse - { - return $this->updatePaymentMethodsAction($context); - } - - private function updatePaymentMethodsAction(Context $context): JsonResponse - { - try { - $this->paymentMethodService->installAndActivatePaymentMethods($context); - - return $this->json([ - 'success' => true, - ]); - } catch (\Throwable $exception) { - $this->logger->error($exception->getMessage()); - - return $this->json( - ['message' => $exception->getMessage(), 'success' => 'false'], - $exception instanceof ShopwareHttpException ? $exception->getStatusCode() : 500 - ); - } - } -} diff --git a/src/Controller/Api/Subscription/SubscriptionControllerBase.php b/src/Controller/Api/Subscription/SubscriptionControllerBase.php index fb3be438c..19dd4a31b 100644 --- a/src/Controller/Api/Subscription/SubscriptionControllerBase.php +++ b/src/Controller/Api/Subscription/SubscriptionControllerBase.php @@ -3,13 +3,13 @@ namespace Kiener\MolliePayments\Controller\Api\Subscription; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionStatus; use Kiener\MolliePayments\Components\Subscription\SubscriptionManager; use Kiener\MolliePayments\Factory\MollieApiFactory; use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Traits\Api\ApiTrait; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionStatus; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Customer\CustomerCollection; use Shopware\Core\Checkout\Customer\CustomerEntity; diff --git a/src/Controller/StoreApi/ApplePayDirect/ApplePayDirectControllerBase.php b/src/Controller/StoreApi/ApplePayDirect/ApplePayDirectControllerBase.php deleted file mode 100644 index 3e476efb3..000000000 --- a/src/Controller/StoreApi/ApplePayDirect/ApplePayDirectControllerBase.php +++ /dev/null @@ -1,244 +0,0 @@ -applePay = $applePay; - $this->logger = $logger; - } - - /** - * @throws \Exception - * - * @return IsApplePayEnabledResponse - */ - public function isEnabled(SalesChannelContext $context): StoreApiResponse - { - $isEnabled = $this->applePay->isApplePayDirectEnabled($context); - - return new IsApplePayEnabledResponse($isEnabled); - } - - /** - * @throws \Exception - * - * @return GetIDResponse - */ - public function getId(SalesChannelContext $context): StoreApiResponse - { - $success = true; - $id = ''; - - try { - $id = $this->applePay->getActiveApplePayID($context); - } catch (\Throwable $ex) { - $success = false; - - $this->logger->warning('Error when fetching Apple Pay ID in Store API. ' . $ex->getMessage()); - } - - return new GetIDResponse($success, $id); - } - - /** - * @throws \Throwable - * - * @return AddProductResponse - */ - public function addProduct(RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $productId = $data->getAlnum('productId'); - $quantity = (int) $data->getAlnum('quantity', '0'); - - if (empty($productId)) { - throw new \Exception('Please provide a product ID!'); - } - - if ($quantity <= 0) { - throw new \Exception('Please provide a valid quantity > 0!'); - } - - $swCart = $this->applePay->addProduct($productId, $quantity, $context); - - return new AddProductResponse($swCart); - } - - /** - * @throws \Throwable - * - * @return CreateSessionResponse - */ - public function createPaymentSession(RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $validationURL = $data->get('validationUrl'); - $domain = (string) $data->get('domain'); - - if (empty($validationURL)) { - throw new \Exception('Please provide a validation url!'); - } - - $session = $this->applePay->createPaymentSession($validationURL, $domain, $context); - - return new CreateSessionResponse($session); - } - - /** - * @throws \Throwable - * - * @return GetCartResponse - */ - public function getCart(SalesChannelContext $context): StoreApiResponse - { - $formattedCart = $this->applePay->getCartFormatted($context); - - return new GetCartResponse($formattedCart); - } - - /** - * @throws \Throwable - * - * @return GetShippingMethodsResponse - */ - public function getShippingMethods(RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $countryCode = $data->getAlnum('countryCode'); - - if (empty($countryCode)) { - throw new \Exception('No Country Code provided!'); - } - - $methods = $this->applePay->getShippingMethods($countryCode, $context); - - return new GetShippingMethodsResponse($methods); - } - - /** - * @throws \Throwable - * - * @return SetShippingMethodResponse - */ - public function setShippingMethod(RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $shippingMethodID = $data->getAlnum('identifier'); - - if (empty($shippingMethodID)) { - throw new \Exception('Please provide a Shipping Method identifier!'); - } - - $this->applePay->setShippingMethod($shippingMethodID, $context); - - return new SetShippingMethodResponse(true); - } - - /** - * @throws \Exception - * - * @return PaymentResponse - */ - public function pay(RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $email = (string) $data->get('email', ''); - $firstname = (string) $data->get('firstname', ''); - $lastname = (string) $data->get('lastname', ''); - $street = (string) $data->get('street', ''); - $city = (string) $data->get('city', ''); - $zipcode = (string) $data->get('postalCode', ''); - $countryCode = (string) $data->get('countryCode', ''); - $phone = (string) $data->get('phone', ''); - - $acceptedDataProtection = (int) $data->get('acceptedDataProtection', '0'); - - $paymentToken = (string) $data->get('paymentToken', ''); - $finishUrl = (string) $data->get('finishUrl', ''); - $errorUrl = (string) $data->get('errorUrl', ''); - - if (empty($paymentToken)) { - throw new \Exception('PaymentToken not found!'); - } - try { - // make sure to create a customer if necessary - // then update to our apple pay payment method - // and return the new context - $newContext = $this->applePay->prepareCustomer( - $firstname, - $lastname, - $email, - $street, - $zipcode, - $city, - $countryCode, - $phone, - $paymentToken, - $acceptedDataProtection, - $context - ); - - // we only start our TRY/CATCH here! - // we always need to throw exceptions on an API level - // but if something BELOW breaks, we want to navigate to the error page. - // customers are ready, data is ready, but the handling has a problem. - - // create our new Shopware Order - $order = $this->applePay->createOrder($newContext); - - // now create the Mollie payment for it - // there should not be a checkout URL required for apple pay, - // so we just create the payment and redirect. - $this->applePay->createPayment( - $order, - $finishUrl, - $firstname, - $lastname, - $street, - $zipcode, - $city, - $countryCode, - $paymentToken, - $newContext - ); - - return new PaymentResponse(true, $finishUrl, '', $order->getId()); - } catch (\Throwable $ex) { - return new PaymentResponse(false, $errorUrl, $ex->getMessage(), ''); - } - } - - /** - * @return RestoreCartResponse - */ - public function restoreCart(SalesChannelContext $context): StoreApiResponse - { - $this->applePay->restoreCart($context); - - return new RestoreCartResponse(true); - } -} diff --git a/src/Controller/StoreApi/CreditCard/CreditCardControllerBase.php b/src/Controller/StoreApi/CreditCard/CreditCardControllerBase.php deleted file mode 100644 index 48d91cfe0..000000000 --- a/src/Controller/StoreApi/CreditCard/CreditCardControllerBase.php +++ /dev/null @@ -1,110 +0,0 @@ -customerService = $customerService; - $this->mandateService = $mandateService; - } - - /** - * @throws \Exception - * - * @return StoreCardTokenResponse - */ - public function saveCardToken(string $cardToken, RequestDataBag $data, SalesChannelContext $context): StoreApiResponse - { - $customerId = (string) $context->getCustomerId(); - /** @var ?CustomerEntity $customer */ - $customer = $this->customerService->getCustomer($customerId, $context->getContext()); - - if (! $customer instanceof CustomerEntity) { - throw new \Exception('Customer with ID ' . $customerId . ' not found in Shopware'); - } - - $result = $this->customerService->setCardToken( - $customer, - $cardToken, - $context, - $data->getBoolean('shouldSaveCardDetail') - ); - $success = count($result->getErrors()) === 0; - - return new StoreCardTokenResponse($success); - } - - /** - * @throws \Exception - * - * @return StoreMandateIdResponse - */ - public function saveMandateId(string $mandateId, SalesChannelContext $context): StoreApiResponse - { - $customerId = (string) $context->getCustomerId(); - $customer = $this->customerService->getCustomer($customerId, $context->getContext()); - if (! $customer instanceof CustomerEntity) { - throw new \Exception('Customer with ID ' . $customerId . ' not found in Shopware'); - } - - $result = $this->customerService->setMandateId( - $customer, - $mandateId, - $context->getContext() - ); - $success = count($result->getErrors()) === 0; - - return new StoreMandateIdResponse($success); - } - - /** - * @throws \Exception - * - * @return RevokeMandateResponse - */ - public function revokeMandate(string $mandateId, SalesChannelContext $context): StoreApiResponse - { - $customerId = (string) $context->getCustomerId(); - $this->mandateService->revokeMandateByCustomerId($customerId, $mandateId, $context); - - return new RevokeMandateResponse(); - } - - /** - * @throws \Exception - * - * @return CreditCardMandatesResponse - */ - public function getMandates(SalesChannelContext $context): StoreApiResponse - { - $customerId = (string) $context->getCustomerId(); - - $mandate = $this->mandateService->getCreditCardMandatesByCustomerId($customerId, $context); - - return new CreditCardMandatesResponse($mandate); - } -} diff --git a/src/Controller/StoreApi/CreditCard/Response/CreditCardMandatesResponse.php b/src/Controller/StoreApi/CreditCard/Response/CreditCardMandatesResponse.php deleted file mode 100644 index ce13e0dba..000000000 --- a/src/Controller/StoreApi/CreditCard/Response/CreditCardMandatesResponse.php +++ /dev/null @@ -1,26 +0,0 @@ -> - */ -class CreditCardMandatesResponse extends StoreApiResponse -{ - public function __construct(MandateCollection $mandates) - { - $object = new ArrayStruct( - [ - 'mandates' => $mandates->jsonSerialize(), - ], - 'mollie_payments_credit_card_mandates' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/CreditCard/Response/RevokeMandateResponse.php b/src/Controller/StoreApi/CreditCard/Response/RevokeMandateResponse.php deleted file mode 100644 index 665b2c1ac..000000000 --- a/src/Controller/StoreApi/CreditCard/Response/RevokeMandateResponse.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -class RevokeMandateResponse extends StoreApiResponse -{ - public function __construct() - { - $object = new SuccessStruct( - true, - 'mollie_payments_mandate_revoke' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/CreditCard/Response/StoreCardTokenResponse.php b/src/Controller/StoreApi/CreditCard/Response/StoreCardTokenResponse.php deleted file mode 100644 index deb68d329..000000000 --- a/src/Controller/StoreApi/CreditCard/Response/StoreCardTokenResponse.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -class StoreCardTokenResponse extends StoreApiResponse -{ - public function __construct(bool $success) - { - $object = new SuccessStruct( - $success, - 'mollie_payments_creditcard_token_stored' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/CreditCard/Response/StoreMandateIdResponse.php b/src/Controller/StoreApi/CreditCard/Response/StoreMandateIdResponse.php deleted file mode 100644 index d7daf52ac..000000000 --- a/src/Controller/StoreApi/CreditCard/Response/StoreMandateIdResponse.php +++ /dev/null @@ -1,23 +0,0 @@ - - */ -class StoreMandateIdResponse extends StoreApiResponse -{ - public function __construct(bool $success) - { - $object = new SuccessStruct( - $success, - 'mollie_payments_creditcard_mandate_id_stored' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/POS/PosControllerBase.php b/src/Controller/StoreApi/POS/PosControllerBase.php deleted file mode 100644 index 49e5426d2..000000000 --- a/src/Controller/StoreApi/POS/PosControllerBase.php +++ /dev/null @@ -1,76 +0,0 @@ -customerService = $customerService; - $this->mollieGateway = $mollieGateway; - } - - /** - * @return TerminalsResponse - */ - public function getIssuers(SalesChannelContext $context): StoreApiResponse - { - $this->mollieGateway->switchClient($context->getSalesChannelId()); - - $terminalsArray = []; - - $terminals = $this->mollieGateway->getPosTerminals(); - - foreach ($terminals as $terminal) { - $terminalsArray[] = [ - 'id' => $terminal->id, - 'name' => $terminal->description, - ]; - } - - return new TerminalsResponse($terminalsArray); - } - - /** - * @throws \Exception - * - * @return StoreTerminalResponse - */ - public function saveTerminalId(string $terminalID, SalesChannelContext $context): StoreApiResponse - { - $customerId = (string) $context->getCustomerId(); - $customer = $this->customerService->getCustomer($customerId, $context->getContext()); - - if (! $customer instanceof CustomerEntity) { - throw new \Exception('Customer with ID ' . $customerId . ' not found in Shopware'); - } - - $result = $this->customerService->setPosTerminal( - $customer, - $terminalID, - $context->getContext() - ); - $success = count($result->getErrors()) === 0; - - return new StoreTerminalResponse($success); - } -} diff --git a/src/Controller/StoreApi/POS/Response/StoreTerminalResponse.php b/src/Controller/StoreApi/POS/Response/StoreTerminalResponse.php deleted file mode 100644 index 050e4c0a9..000000000 --- a/src/Controller/StoreApi/POS/Response/StoreTerminalResponse.php +++ /dev/null @@ -1,25 +0,0 @@ -> - */ -class StoreTerminalResponse extends StoreApiResponse -{ - public function __construct(bool $success) - { - $object = new ArrayStruct( - [ - 'success' => $success, - ], - 'mollie_payments_pos_terminal_stored' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/POS/Response/TerminalsResponse.php b/src/Controller/StoreApi/POS/Response/TerminalsResponse.php deleted file mode 100644 index 168840369..000000000 --- a/src/Controller/StoreApi/POS/Response/TerminalsResponse.php +++ /dev/null @@ -1,28 +0,0 @@ -}>> - */ -class TerminalsResponse extends StoreApiResponse -{ - /** - * @param array $terminals - */ - public function __construct(array $terminals) - { - $object = new ArrayStruct( - [ - 'terminals' => $terminals, - ], - 'mollie_payments_pos_terminals' - ); - - parent::__construct($object); - } -} diff --git a/src/Controller/StoreApi/Subscription/Response/SubscriptionsListResponse.php b/src/Controller/StoreApi/Subscription/Response/SubscriptionsListResponse.php index cecfde200..5adb56481 100644 --- a/src/Controller/StoreApi/Subscription/Response/SubscriptionsListResponse.php +++ b/src/Controller/StoreApi/Subscription/Response/SubscriptionsListResponse.php @@ -3,7 +3,7 @@ namespace Kiener\MolliePayments\Controller\StoreApi\Subscription\Response; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Framework\Struct\ArrayStruct; use Shopware\Core\System\SalesChannel\StoreApiResponse; diff --git a/src/Controller/StoreApi/Subscription/SubscriptionControllerBase.php b/src/Controller/StoreApi/Subscription/SubscriptionControllerBase.php index 6a0d5a559..a8b4b16c2 100644 --- a/src/Controller/StoreApi/Subscription/SubscriptionControllerBase.php +++ b/src/Controller/StoreApi/Subscription/SubscriptionControllerBase.php @@ -4,8 +4,6 @@ namespace Kiener\MolliePayments\Controller\StoreApi\Subscription; use Kiener\MolliePayments\Components\Subscription\DAL\Repository\SubscriptionRepository; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionCollection; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Components\Subscription\SubscriptionManager; use Kiener\MolliePayments\Controller\StoreApi\Subscription\Response\SubscriptionCancelResponse; use Kiener\MolliePayments\Controller\StoreApi\Subscription\Response\SubscriptionPauseResponse; @@ -16,6 +14,8 @@ use Kiener\MolliePayments\Controller\StoreApi\Subscription\Response\SubscriptionUpdateBillingResponse; use Kiener\MolliePayments\Controller\StoreApi\Subscription\Response\SubscriptionUpdateShippingResponse; use Kiener\MolliePayments\Exception\CustomerCouldNotBeFoundException; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionCollection; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Customer\CustomerEntity; use Shopware\Core\Framework\Validation\DataBag\RequestDataBag; diff --git a/src/Controller/Storefront/ApplePayDirect/ApplePayDirectControllerBase.php b/src/Controller/Storefront/ApplePayDirect/ApplePayDirectControllerBase.php deleted file mode 100644 index ec045e019..000000000 --- a/src/Controller/Storefront/ApplePayDirect/ApplePayDirectControllerBase.php +++ /dev/null @@ -1,446 +0,0 @@ -> - */ - private $repoCustomers; - - /** - * @var OrderService - */ - private $orderService; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * @param EntityRepository> $repoCustomers - * - * @throws \Exception - */ - public function __construct(ApplePayDirect $applePay, RouterInterface $router, LoggerInterface $logger, FlowBuilderFactory $flowBuilderFactory, FlowBuilderEventFactory $flowBuilderEventFactory, $repoCustomers, OrderService $orderService) - { - $this->applePay = $applePay; - $this->router = $router; - $this->logger = $logger; - - $this->repoCustomers = $repoCustomers; - $this->orderService = $orderService; - - $this->flowBuilderEventFactory = $flowBuilderEventFactory; - $this->flowBuilderDispatcher = $flowBuilderFactory->createDispatcher(); - } - - public function isPaymentAvailable(SalesChannelContext $context): JsonResponse - { - try { - $isEnabled = $this->applePay->isApplePayDirectEnabled($context); - - return new JsonResponse([ - 'available' => $isEnabled, - ]); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct available: ' . $ex->getMessage()); - - return new JsonResponse([ - 'available' => false, - ]); - } - } - - /** - * Gets the ID of the ApplePay payment method. - * We need this in the storefront for some selectors in use cases like - * hiding the payment method if its not available in the browser. - * - * ATTENTION: - * this is not about Apple Pay Direct - but the namespace of the URL is a good one (/apple-pay) - * and I don't want to create all kinds of new controllers - */ - public function getApplePayID(SalesChannelContext $context): JsonResponse - { - try { - $id = $this->applePay->getActiveApplePayID($context); - - return new JsonResponse([ - 'id' => $id, - ]); - } catch (\Throwable $ex) { - // ! WE DO NOT LOG IN HERE! - // otherwise we would always get logs if its just not enabled - // so this is either a valid response or invalid one...that's it - - return new JsonResponse([ - 'id' => 'not-found', - ]); - } - } - - public function addProduct(SalesChannelContext $context, Request $request): JsonResponse - { - // we do only allow a few errors from within here - // the rest should only be visible in the LOG files - $allowErrorMessage = false; - - try { - $content = json_decode((string) $request->getContent(), true); - - $productId = (isset($content['id'])) ? (string) $content['id'] : ''; - $quantity = (isset($content['quantity'])) ? (int) $content['quantity'] : 0; - - if (empty($productId)) { - $allowErrorMessage = true; - throw new \Exception('Please provide a product ID!'); - } - - if ($quantity <= 0) { - $allowErrorMessage = true; - throw new \Exception('Please provide a valid quantity > 0!'); - } - - $this->applePay->addProduct($productId, $quantity, $context); - - return new JsonResponse(['success' => true]); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct error when adding product: ' . $ex->getMessage()); - - $viewJson = ['success' => false]; - - if ($allowErrorMessage) { - $viewJson['error'] = $ex->getMessage(); - } - - return new JsonResponse($viewJson, 500); - } - } - - public function createPaymentSession(SalesChannelContext $context, Request $request): JsonResponse - { - try { - $content = json_decode((string) $request->getContent(), true); - - $validationURL = (string) $content['validationUrl']; - - $session = $this->applePay->createPaymentSession($validationURL, '', $context); - - return new JsonResponse([ - 'session' => $session, - ]); - } catch (\Throwable $ex) { - $this->logger->error( - 'Apple Pay Direct error when creating payment session: ' . $ex->getMessage(), - [ - 'error' => $ex, - ] - ); - - return new JsonResponse(['success' => false], 500); - } - } - - public function getShippingMethods(SalesChannelContext $context, Request $request): JsonResponse - { - $allowErrorMessage = false; - - try { - $content = json_decode((string) $request->getContent(), true); - - $countryCode = (isset($content['countryCode'])) ? (string) $content['countryCode'] : ''; - - if (empty($countryCode)) { - $allowErrorMessage = true; - throw new \Exception('No Country Code provided!'); - } - - $methods = $this->applePay->getShippingMethods($countryCode, $context); - $formattedCart = $this->applePay->getCartFormatted($context); - - return new JsonResponse([ - 'success' => true, - 'cart' => $formattedCart, - 'shippingmethods' => $methods, - ]); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct error when loading shipping methods: ' . $ex->getMessage()); - - $viewJson = ['success' => false]; - - if ($allowErrorMessage) { - $viewJson['error'] = $ex->getMessage(); - } - - return new JsonResponse($viewJson, 500); - } - } - - public function setShippingMethod(SalesChannelContext $context, Request $request): JsonResponse - { - $allowErrorMessage = false; - - try { - $json = json_decode((string) $request->getContent(), true); - - $shippingMethodID = (isset($json['identifier'])) ? (string) $json['identifier'] : ''; - - if (empty($shippingMethodID)) { - $allowErrorMessage = true; - throw new \Exception('Please provide a Shipping Method identifier!'); - } - - $newContext = $this->applePay->setShippingMethod($shippingMethodID, $context); - - $cart = $this->applePay->getCartFormatted($newContext); - - return new JsonResponse([ - 'success' => true, - 'cart' => $cart, - ]); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct error when setting shipping method: ' . $ex->getMessage()); - - $viewJson = ['success' => false]; - - if ($allowErrorMessage) { - $viewJson['error'] = $ex->getMessage(); - } - - return new JsonResponse($viewJson, 500); - } - } - - public function startPayment(SalesChannelContext $context, Request $request): Response - { - try { - $email = (string) $request->get('email', ''); - $firstname = (string) $request->get('firstname', ''); - $lastname = (string) $request->get('lastname', ''); - $street = (string) $request->get('street', ''); - $zipcode = (string) $request->get('postalCode', ''); - $city = (string) $request->get('city', ''); - $countryCode = (string) $request->get('countryCode', ''); - $phone = (string) $request->get('phone', ''); - $acceptedDataProtection = (int) $request->get('acceptedDataProtection', '0'); - - $paymentToken = (string) $request->get('paymentToken', ''); - - if (empty($paymentToken)) { - throw new \Exception('PaymentToken not found!'); - } - - $this->applePay->prepareCustomer( - $firstname, - $lastname, - $email, - $street, - $zipcode, - $city, - $countryCode, - $phone, - $paymentToken, - $acceptedDataProtection, - $context - ); - - // forward to the finish-payment page, - // where our customer is correctly known, and where we - // can continue with our correct sales channel context. - return $this->forwardToRoute('frontend.mollie.apple-pay.finish-payment', []); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct error when starting payment: ' . $ex->getMessage()); - - // if we have an error here, we have to redirect to the confirm page - $returnUrl = $this->getCheckoutConfirmPage($this->router); - // also add an error for our target page - - $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); - - return new RedirectResponse($returnUrl); - } - } - - /** - * @throws \Exception - */ - public function finishPayment(SalesChannelContext $context, Request $request): RedirectResponse - { - $firstname = $request->get('firstname', ''); - $lastname = $request->get('lastname', ''); - $street = $request->get('street', ''); - $zipcode = $request->get('postalCode', ''); - $city = $request->get('city', ''); - $countryCode = $request->get('countryCode', ''); - $paymentToken = $request->get('paymentToken', ''); - - // ---------------------------------------------------------------------------- - // STEP 1: Create Order - try { - if (empty($paymentToken)) { - throw new \Exception('PaymentToken not found!'); - } - - $order = $this->applePay->createOrder($context); - } catch (\Throwable $ex) { - $this->logger->error( - 'Apple Pay Direct error when finishing payment: ' . $ex->getMessage(), - [ - 'error' => $ex, - ] - ); - - // if we have an error here, we have to redirect to the confirm page - $returnUrl = $this->getCheckoutConfirmPage($this->router); - // also add an error for our target page - - $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); - - return new RedirectResponse($returnUrl); - } - - // ---------------------------------------------------------------------------- - // STEP 2: Start Payment (CHECKPOINT: we have a valid shopware order now) - try { - $returnUrl = $this->getCheckoutFinishPage($order->getId(), $this->router); - - $this->applePay->createPayment( - $order, - $this->getCheckoutFinishPage($order->getId(), $this->router), - $firstname, - $lastname, - $street, - $zipcode, - $city, - $countryCode, - $paymentToken, - $context - ); - - // fire our custom storefront event - $this->fireFlowBuilderStorefrontEvent(self::FLOWBUILDER_SUCCESS, $order, $context->getContext()); - - return new RedirectResponse($returnUrl); - } catch (\Throwable $ex) { - $this->logger->error( - 'Apple Pay Direct error when finishing Mollie payment: ' . $ex->getMessage(), - [ - 'error' => $ex, - ] - ); - - // we already have a valid Order ID. - // so we just need to make sure to edit that order - $returnUrl = $this->getEditOrderPage($order->getId(), $this->router); - - // also add an error for our target page - $this->addFlash('danger', $this->trans(self::SNIPPET_ERROR)); - - // fire our custom storefront event - $this->fireFlowBuilderStorefrontEvent(self::FLOWBUILDER_FAILED, $order, $context->getContext()); - - return new RedirectResponse($returnUrl); - } - } - - public function restoreCart(SalesChannelContext $context): JsonResponse - { - try { - $this->applePay->restoreCart($context); - - return new JsonResponse(['success' => true]); - } catch (\Throwable $ex) { - $this->logger->error('Apple Pay Direct restoring cart error: ' . $ex->getMessage()); - - return new JsonResponse(['success' => false], 500); - } - } - - /** - * @throws \Exception - */ - private function fireFlowBuilderStorefrontEvent(string $status, OrderEntity $order, Context $context): void - { - $orderCustomer = $order->getOrderCustomer(); - - if (! $orderCustomer instanceof OrderCustomerEntity) { - return; - } - - $criteria = new Criteria([(string) $orderCustomer->getCustomerId()]); - - $customers = $this->repoCustomers->search($criteria, $context); - - if ($customers->count() <= 0) { - return; - } - /** @var CustomerEntity $customer */ - $customer = $customers->first(); - // we also have to reload the order because data is missing - $finalOrder = $this->orderService->getOrder($order->getId(), $context); - - switch ($status) { - case self::FLOWBUILDER_FAILED: - $event = $this->flowBuilderEventFactory->buildOrderFailedEvent($customer, $finalOrder, $context); - break; - - default: - $event = $this->flowBuilderEventFactory->buildOrderSuccessEvent($customer, $finalOrder, $context); - } - - $this->flowBuilderDispatcher->dispatch($event); - } -} diff --git a/src/Controller/Storefront/POS/PosControllerBase.php b/src/Controller/Storefront/POS/PosControllerBase.php deleted file mode 100644 index 2d468de77..000000000 --- a/src/Controller/Storefront/POS/PosControllerBase.php +++ /dev/null @@ -1,146 +0,0 @@ -customerService = $customerService; - $this->mollieGateway = $mollieGateway; - $this->router = $router; - $this->statusUpdater = $orderStatusUpdater; - $this->statusConverter = $statusConverter; - $this->repoTransactions = $repoTransactions; - } - - public function storeTerminal(SalesChannelContext $context, string $terminalId): JsonResponse - { - $result = null; - $customerId = (string) $context->getCustomerId(); - $customer = $this->customerService->getCustomer($customerId, $context->getContext()); - - if ($customer instanceof CustomerEntity) { - $writtenEvent = $this->customerService->setPosTerminal( - $customer, - $terminalId, - $context->getContext() - ); - - $result = $writtenEvent->getErrors(); - } - - return new JsonResponse([ - 'success' => (bool) $result, - 'customerId' => $customerId, - 'result' => $result, - ]); - } - - public function checkoutAction(Request $request, SalesChannelContext $salesChannelContext): Response - { - $orderId = $request->get('sw'); - $mollieId = $request->get('mo'); - $changeStatusUrl = (string) $request->get('cs'); - - $params = [ - 'swOrderId' => $orderId, - 'molliePaymentId' => $mollieId, - ]; - - if (! empty($changeStatusUrl)) { - $params['changeStatusUrl'] = $changeStatusUrl; - } - - return $this->renderStorefront('@Storefront/mollie/pos/checkout.html.twig', $params); - } - - public function statusAction(SalesChannelContext $context, string $orderId, string $molliePaymentId): JsonResponse - { - $this->mollieGateway->switchClient($context->getSalesChannelId()); - - $molliePayment = $this->mollieGateway->getPayment($molliePaymentId); - - $ready = false; - - $status = $this->statusConverter->getMolliePaymentStatus($molliePayment); - - if ($status !== MolliePaymentStatus::MOLLIE_PAYMENT_OPEN) { - $ready = true; - } - - $url = ''; - - if ($ready) { - if (MolliePaymentStatus::isApprovedStatus($molliePayment->status)) { - $url = $this->getCheckoutFinishPage($orderId, $this->router); - } else { - $url = $this->getEditOrderPage($orderId, $this->router); - } - - $latestTransaction = $this->repoTransactions->getLatestOrderTransaction($orderId, $context->getContext()); - - $this->statusUpdater->updatePaymentStatus( - $latestTransaction, - $status, - $context->getContext() - ); - } - - $isSuccess = MolliePaymentStatus::isApprovedStatus($molliePayment->status); - - return new JsonResponse([ - 'ready' => $ready, - 'redirectUrl' => $url, - 'success' => $isSuccess, - ]); - } -} diff --git a/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php b/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php index 52c52b5cc..716576868 100644 --- a/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php +++ b/src/Controller/Storefront/PaypalExpress/PaypalExpressControllerBase.php @@ -4,10 +4,10 @@ namespace Kiener\MolliePayments\Controller\Storefront\PaypalExpress; use Kiener\MolliePayments\Components\PaypalExpress\Route\AbstractCancelCheckoutRoute; -use Kiener\MolliePayments\Components\PaypalExpress\Route\AbstractFinishCheckoutRoute; -use Kiener\MolliePayments\Components\PaypalExpress\Route\AbstractStartCheckoutRoute; use Kiener\MolliePayments\Traits\Storefront\RedirectTrait; use Mollie\Api\Exceptions\ApiException; +use Mollie\Shopware\Component\Payment\PayPalExpress\Route\AbstractFinishCheckoutRoute; +use Mollie\Shopware\Component\Payment\PayPalExpress\Route\AbstractStartCheckoutRoute; use Psr\Log\LoggerInterface; use Shopware\Core\System\SalesChannel\SalesChannelContext; use Shopware\Storefront\Controller\StorefrontController; diff --git a/src/Exception/PaymentUrlException.php b/src/Exception/PaymentUrlException.php index 5981c7419..631eb6fac 100644 --- a/src/Exception/PaymentUrlException.php +++ b/src/Exception/PaymentUrlException.php @@ -3,16 +3,20 @@ namespace Kiener\MolliePayments\Exception; -use Shopware\Core\Checkout\Payment\Exception\PaymentProcessException; +use Shopware\Core\Checkout\Payment\PaymentException; +use Symfony\Component\HttpFoundation\Response; -class PaymentUrlException extends PaymentProcessException +class PaymentUrlException extends PaymentException { public function __construct(string $orderTransactionId, string $errorMessage) { parent::__construct( - $orderTransactionId, - 'Could not create a Mollie payment url due to the following error: {{ errorMessage }}', - ['errorMessage' => $errorMessage] + Response::HTTP_BAD_REQUEST, + $this->getErrorCode(), + 'Could not create a Mollie payment url for transaction {{transactionId}} due to the following error: {{ errorMessage }}', + ['transactionId' => $orderTransactionId, + 'errorMessage' => $errorMessage + ] ); } diff --git a/src/Handler/Method/AlmaPayment.php b/src/Handler/Method/AlmaPayment.php deleted file mode 100644 index 343313ac7..000000000 --- a/src/Handler/Method/AlmaPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/BanContactPayment.php b/src/Handler/Method/BanContactPayment.php deleted file mode 100644 index 737ecaf68..000000000 --- a/src/Handler/Method/BanContactPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/BancomatPayment.php b/src/Handler/Method/BancomatPayment.php deleted file mode 100644 index 10229de02..000000000 --- a/src/Handler/Method/BancomatPayment.php +++ /dev/null @@ -1,32 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $orderCustomFields = new OrderAttributes($orderEntity); - $orderData['billingAddress']['phone'] = $orderCustomFields->getPayPhoneNumber(); - - return $orderData; - } -} diff --git a/src/Handler/Method/BankTransferPayment.php b/src/Handler/Method/BankTransferPayment.php deleted file mode 100644 index 6819d5c9c..000000000 --- a/src/Handler/Method/BankTransferPayment.php +++ /dev/null @@ -1,52 +0,0 @@ -settingsService = $settingsService; - } - - /** - * @param array $orderData - * - * @throws \Exception - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $settings = $this->settingsService->getSettings($salesChannelContext->getSalesChannel()->getId()); - - $dueDateDays = (int) $settings->getPaymentMethodBankTransferDueDateDays(); - - if ($dueDateDays > 0) { - $dueDate = $settings->getPaymentMethodBankTransferDueDate(); - $orderData['expiresAt'] = $dueDate; - } - - return $orderData; - } -} diff --git a/src/Handler/Method/BelfiusPayment.php b/src/Handler/Method/BelfiusPayment.php deleted file mode 100644 index d77192b43..000000000 --- a/src/Handler/Method/BelfiusPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/BilliePayment.php b/src/Handler/Method/BilliePayment.php deleted file mode 100644 index 4dd67e9be..000000000 --- a/src/Handler/Method/BilliePayment.php +++ /dev/null @@ -1,27 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/BizumPayment.php b/src/Handler/Method/BizumPayment.php deleted file mode 100644 index 658fba8e2..000000000 --- a/src/Handler/Method/BizumPayment.php +++ /dev/null @@ -1,32 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $orderCustomFields = new OrderAttributes($orderEntity); - $orderData['billingAddress']['phone'] = $orderCustomFields->getPayPhoneNumber(); - - return $orderData; - } -} diff --git a/src/Handler/Method/BlikPayment.php b/src/Handler/Method/BlikPayment.php deleted file mode 100644 index c694ddfdc..000000000 --- a/src/Handler/Method/BlikPayment.php +++ /dev/null @@ -1,27 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/CreditCardPayment.php b/src/Handler/Method/CreditCardPayment.php deleted file mode 100644 index 49a64d713..000000000 --- a/src/Handler/Method/CreditCardPayment.php +++ /dev/null @@ -1,80 +0,0 @@ -customerService = $customerService; - } - - /** - * @param array $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $customFields = $customer->getCustomFields() ?? []; - $cardToken = $customFields[CustomFieldsInterface::MOLLIE_KEY]['credit_card_token'] ?? ''; - $shouldSaveCardDetail = $customFields[CustomFieldsInterface::MOLLIE_KEY]['shouldSaveCardDetail'] ?? false; - if (! empty($cardToken)) { - $orderData['payment']['cardToken'] = $cardToken; - $this->customerService->setCardToken($customer, '', $salesChannelContext, $shouldSaveCardDetail); - - $isSaveCardToken = $customFields[CustomFieldsInterface::MOLLIE_KEY][CustomerService::CUSTOM_FIELDS_KEY_SHOULD_SAVE_CARD_DETAIL] ?? false; - // change payment sequenceType to first if this is a single-click payment - if ($this->enableSingleClickPayment && $isSaveCardToken) { - $orderData['payment']['sequenceType'] = PaymentHandler::PAYMENT_SEQUENCE_TYPE_FIRST; - } - - return $orderData; - } - - // if single click payment is disabled, return orderData - // if single click payment is enabled, we need to change the payment sequenceType and provide the mandateId - if (! $this->enableSingleClickPayment) { - return $orderData; - } - - $mandateId = $customFields[CustomFieldsInterface::MOLLIE_KEY][CustomerService::CUSTOM_FIELDS_KEY_MANDATE_ID] ?? ''; - if (empty($mandateId)) { - return $orderData; - } - - // if mandateId is not empty, it means this is recurring payment - $orderData['payment']['sequenceType'] = PaymentHandler::PAYMENT_SEQUENCE_TYPE_RECURRING; - $orderData['payment']['mandateId'] = $mandateId; - $this->customerService->setMandateId($customer, '', $salesChannelContext->getContext()); - - return $orderData; - } - - public function setEnableSingleClickPayment(bool $enableSingleClickPayment): void - { - $this->enableSingleClickPayment = $enableSingleClickPayment; - } -} diff --git a/src/Handler/Method/DirectDebitPayment.php b/src/Handler/Method/DirectDebitPayment.php deleted file mode 100644 index a1e89ac15..000000000 --- a/src/Handler/Method/DirectDebitPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/EpsPayment.php b/src/Handler/Method/EpsPayment.php deleted file mode 100644 index e0cef23e9..000000000 --- a/src/Handler/Method/EpsPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/GiftCardPayment.php b/src/Handler/Method/GiftCardPayment.php deleted file mode 100644 index 3730a2f65..000000000 --- a/src/Handler/Method/GiftCardPayment.php +++ /dev/null @@ -1,31 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/GiroPayPayment.php b/src/Handler/Method/GiroPayPayment.php deleted file mode 100644 index e245e5de6..000000000 --- a/src/Handler/Method/GiroPayPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/In3Payment.php b/src/Handler/Method/In3Payment.php deleted file mode 100644 index b432ed0e2..000000000 --- a/src/Handler/Method/In3Payment.php +++ /dev/null @@ -1,16 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/KbcPayment.php b/src/Handler/Method/KbcPayment.php deleted file mode 100644 index cb44e045a..000000000 --- a/src/Handler/Method/KbcPayment.php +++ /dev/null @@ -1,29 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/KlarnaOnePayment.php b/src/Handler/Method/KlarnaOnePayment.php deleted file mode 100644 index bb42c41b3..000000000 --- a/src/Handler/Method/KlarnaOnePayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/KlarnaPayLaterPayment.php b/src/Handler/Method/KlarnaPayLaterPayment.php deleted file mode 100644 index 1f3473aad..000000000 --- a/src/Handler/Method/KlarnaPayLaterPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/KlarnaPayNowPayment.php b/src/Handler/Method/KlarnaPayNowPayment.php deleted file mode 100644 index 27b695a78..000000000 --- a/src/Handler/Method/KlarnaPayNowPayment.php +++ /dev/null @@ -1,29 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/KlarnaSliceItPayment.php b/src/Handler/Method/KlarnaSliceItPayment.php deleted file mode 100644 index ed3336550..000000000 --- a/src/Handler/Method/KlarnaSliceItPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/MbWayPayment.php b/src/Handler/Method/MbWayPayment.php deleted file mode 100644 index f52e32b1a..000000000 --- a/src/Handler/Method/MbWayPayment.php +++ /dev/null @@ -1,14 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/PayByBankPayment.php b/src/Handler/Method/PayByBankPayment.php deleted file mode 100644 index c238e63e3..000000000 --- a/src/Handler/Method/PayByBankPayment.php +++ /dev/null @@ -1,31 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/PayPalExpressPayment.php b/src/Handler/Method/PayPalExpressPayment.php deleted file mode 100644 index 15a182686..000000000 --- a/src/Handler/Method/PayPalExpressPayment.php +++ /dev/null @@ -1,32 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $orderData['authenticationId'] = $orderEntity->getCustomFields()[CustomFieldsInterface::MOLLIE_KEY][CustomFieldsInterface::PAYPAL_EXPRESS_AUTHENTICATE_ID] ?? null; - - return $orderData; - } -} diff --git a/src/Handler/Method/PayPalPayment.php b/src/Handler/Method/PayPalPayment.php deleted file mode 100644 index 65edbf2c1..000000000 --- a/src/Handler/Method/PayPalPayment.php +++ /dev/null @@ -1,41 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - - // @todo find error and fix it - // if (!array_key_exists(static::FIELD_PAYPAL_DESCRIPTION, $orderData[static::FIELD_PAYMENT]) || in_array($orderData[static::FIELD_PAYMENT][static::FIELD_PAYPAL_DESCRIPTION], [null, ''], true)) { - // $orderData[static::FIELD_PAYMENT][static::FIELD_PAYPAL_DESCRIPTION] = sprintf('Order %s', $orderData[PaymentHandler::FIELD_ORDER_NUMBER]); - // } - // - // if (!array_key_exists(static::FIELD_PAYPAL_DIGITAL_GOODS, $orderData[static::FIELD_PAYMENT]) || in_array($orderData[static::FIELD_PAYMENT][static::FIELD_PAYPAL_DIGITAL_GOODS], [null, ''], true)) { - // // ToDo: Digital downloads zitten nog niet in Shopware 6 - // } - // - // return $orderData; - } -} diff --git a/src/Handler/Method/PaySafeCardPayment.php b/src/Handler/Method/PaySafeCardPayment.php deleted file mode 100644 index 494a28eef..000000000 --- a/src/Handler/Method/PaySafeCardPayment.php +++ /dev/null @@ -1,34 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $reference = $orderData['payment']['customerReference'] ?? ''; - - if (empty($reference)) { - $orderData['payment']['customerReference'] = $customer->getCustomerNumber(); - } - - return $orderData; - } -} diff --git a/src/Handler/Method/PayconiqPayment.php b/src/Handler/Method/PayconiqPayment.php deleted file mode 100644 index 660f3463d..000000000 --- a/src/Handler/Method/PayconiqPayment.php +++ /dev/null @@ -1,14 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $customFields = $customer->getCustomFields() ?? []; - - $this->selectedTerminalId = $customFields[CustomFieldsInterface::MOLLIE_KEY][CustomerService::CUSTOM_FIELDS_KEY_PREFERRED_POS_TERMINAL] ?? ''; - - return $orderData; - } - - public function getTerminalId(): string - { - return $this->selectedTerminalId; - } -} diff --git a/src/Handler/Method/Przelewy24Payment.php b/src/Handler/Method/Przelewy24Payment.php deleted file mode 100644 index 61772c935..000000000 --- a/src/Handler/Method/Przelewy24Payment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/RivertyPayment.php b/src/Handler/Method/RivertyPayment.php deleted file mode 100644 index 1948afad1..000000000 --- a/src/Handler/Method/RivertyPayment.php +++ /dev/null @@ -1,14 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/SwishPayment.php b/src/Handler/Method/SwishPayment.php deleted file mode 100644 index 11ecd666b..000000000 --- a/src/Handler/Method/SwishPayment.php +++ /dev/null @@ -1,14 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/Method/VoucherPayment.php b/src/Handler/Method/VoucherPayment.php deleted file mode 100644 index 752421c4d..000000000 --- a/src/Handler/Method/VoucherPayment.php +++ /dev/null @@ -1,83 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - $lineItems = $orderData['lines']; - - // add the category as mentioned here - // https://docs.mollie.com/reference/v2/orders-api/create-order - foreach ($lineItems as &$line) { - $orderLineItemID = $line['metadata']['orderLineItemId']; - - $category = $this->getProductCategory($orderEntity, $orderLineItemID); - - if (! empty($category)) { - $line['category'] = $category; - } - } - - $orderData['lines'] = $lineItems; - - return $orderData; - } - - /** - * Searches the order line item with the provided ID and tries - * to find out if any voucherType has been set for that product. - * Depending on the configuration, a matching category for Mollie will be returned. - */ - private function getProductCategory(OrderEntity $orderEntity, string $lineItemId): string - { - if (! $orderEntity->getLineItems() instanceof OrderLineItemCollection) { - return ''; - } - - foreach ($orderEntity->getLineItems() as $lineItem) { - if ($lineItem->getId() !== $lineItemId) { - continue; - } - - // try to get the voucher type from the line item - $attributes = new OrderLineItemEntityAttributes($lineItem); - $voucherType = $attributes->getVoucherType(); - - if ($voucherType === VoucherType::TYPE_ECO) { - return 'eco'; - } - - if ($voucherType === VoucherType::TYPE_MEAL) { - return 'meal'; - } - - if ($voucherType === VoucherType::TYPE_GIFT) { - return 'gift'; - } - } - - return ''; - } -} diff --git a/src/Handler/Method/iDealPayment.php b/src/Handler/Method/iDealPayment.php deleted file mode 100644 index 4bab4a702..000000000 --- a/src/Handler/Method/iDealPayment.php +++ /dev/null @@ -1,28 +0,0 @@ - $orderData - * - * @return array - */ - public function processPaymentMethodSpecificParameters(array $orderData, OrderEntity $orderEntity, SalesChannelContext $salesChannelContext, CustomerEntity $customer): array - { - return $orderData; - } -} diff --git a/src/Handler/PaymentHandler.php b/src/Handler/PaymentHandler.php index 56b3ee4ea..3c66dece4 100644 --- a/src/Handler/PaymentHandler.php +++ b/src/Handler/PaymentHandler.php @@ -3,27 +3,13 @@ namespace Kiener\MolliePayments\Handler; -use Mollie\Shopware\Component\Payment\PaymentHandlerLegacyTrait; use Mollie\Shopware\Component\Payment\PaymentHandlerTrait; use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\AbstractPaymentHandler; -use Shopware\Core\Checkout\Payment\Cart\PaymentHandler\AsynchronousPaymentHandlerInterface; -if (class_exists(AbstractPaymentHandler::class)) { - class PaymentHandler extends AbstractPaymentHandler - { - use PaymentHandlerTrait; - public const PAYMENT_SEQUENCE_TYPE_FIRST = 'first'; - public const PAYMENT_SEQUENCE_TYPE_RECURRING = 'recurring'; - } +class PaymentHandler extends AbstractPaymentHandler +{ + use PaymentHandlerTrait; - return; -} -/** @phpstan-ignore-next-line */ -if (interface_exists(AsynchronousPaymentHandlerInterface::class) && ! class_exists(AbstractPaymentHandler::class)) { - class PaymentHandler implements AsynchronousPaymentHandlerInterface - { - use PaymentHandlerLegacyTrait; - public const PAYMENT_SEQUENCE_TYPE_FIRST = 'first'; - public const PAYMENT_SEQUENCE_TYPE_RECURRING = 'recurring'; - } + public const PAYMENT_SEQUENCE_TYPE_FIRST = 'first'; + public const PAYMENT_SEQUENCE_TYPE_RECURRING = 'recurring'; } diff --git a/src/Migration/Migration1764575745UpdatePaymentMethods.php b/src/Migration/Migration1764575745UpdatePaymentMethods.php new file mode 100644 index 000000000..96449e1bc --- /dev/null +++ b/src/Migration/Migration1764575745UpdatePaymentMethods.php @@ -0,0 +1,67 @@ + \Mollie\Shopware\Component\Payment\Method\AlmaPayment::class, + 'Kiener\MolliePayments\Handler\Method\BanContactPayment' => \Mollie\Shopware\Component\Payment\Method\BanContactPayment::class, + 'Kiener\MolliePayments\Handler\Method\BelfiusPayment' => \Mollie\Shopware\Component\Payment\Method\BelfiusPayment::class, + 'Kiener\MolliePayments\Handler\Method\BilliePayment' => \Mollie\Shopware\Component\Payment\Method\BilliePayment::class, + 'Kiener\MolliePayments\Handler\Method\BizumPayment' => \Mollie\Shopware\Component\Payment\Method\BizumPayment::class, + 'Kiener\MolliePayments\Handler\Method\BlikPayment' => \Mollie\Shopware\Component\Payment\Method\BlikPayment::class, + 'Kiener\MolliePayments\Handler\Method\CreditCardPayment' => \Mollie\Shopware\Component\Payment\Method\CardPayment::class, + 'Kiener\MolliePayments\Handler\Method\DirectDebitPayment' => \Mollie\Shopware\Component\Payment\Method\DirectDebitPayment::class, + 'Kiener\MolliePayments\Handler\Method\EpsPayment' => \Mollie\Shopware\Component\Payment\Method\EpsPayment::class, + 'Kiener\MolliePayments\Handler\Method\GiftCardPayment' => \Mollie\Shopware\Component\Payment\Method\GiftCardPayment::class, + 'Kiener\MolliePayments\Handler\Method\iDealPayment' => \Mollie\Shopware\Component\Payment\Method\IdealPayment::class, + 'Kiener\MolliePayments\Handler\Method\In3Payment' => \Mollie\Shopware\Component\Payment\Method\In3Payment::class, + 'Kiener\MolliePayments\Handler\Method\KbcPayment' => \Mollie\Shopware\Component\Payment\Method\KbcPayment::class, + 'Kiener\MolliePayments\Handler\Method\KlarnaOnePayment' => \Mollie\Shopware\Component\Payment\Method\KlarnaPayment::class, + 'Kiener\MolliePayments\Handler\Method\MbWayPayment' => \Mollie\Shopware\Component\Payment\Method\MbWayPayment::class, + 'Kiener\MolliePayments\Handler\Method\MultibancoPayment' => \Mollie\Shopware\Component\Payment\Method\MultiBancoPayment::class, + 'Kiener\MolliePayments\Handler\Method\MyBankPayment' => \Mollie\Shopware\Component\Payment\Method\MyBankPayment::class, + 'Kiener\MolliePayments\Handler\Method\PayByBankPayment' => \Mollie\Shopware\Component\Payment\Method\PayByBankPayment::class, + 'Kiener\MolliePayments\Handler\Method\PayPalPayment' => \Mollie\Shopware\Component\Payment\Method\PayPalPayment::class, + 'Kiener\MolliePayments\Handler\Method\Przelewy24Payment' => \Mollie\Shopware\Component\Payment\Method\Przelewy24Payment::class, + 'Kiener\MolliePayments\Handler\Method\RivertyPayment' => \Mollie\Shopware\Component\Payment\Method\RivertyPayment::class, + 'Kiener\MolliePayments\Handler\Method\SatispayPayment' => \Mollie\Shopware\Component\Payment\Method\SatisPayPayment::class, + 'Kiener\MolliePayments\Handler\Method\SwishPayment' => \Mollie\Shopware\Component\Payment\Method\SwishPayment::class, + 'Kiener\MolliePayments\Handler\Method\TrustlyPayment' => \Mollie\Shopware\Component\Payment\Method\TrustlyPayment::class, + 'Kiener\MolliePayments\Handler\Method\TwintPayment' => \Mollie\Shopware\Component\Payment\Method\TwintPayment::class, + 'Kiener\MolliePayments\Handler\Method\PayconiqPayment' => \Mollie\Shopware\Component\Payment\Method\PayconiqPayment::class, + 'Kiener\MolliePayments\Handler\Method\ApplePayPayment' => \Mollie\Shopware\Component\Payment\Method\ApplePayPayment::class, + 'Kiener\MolliePayments\Handler\Method\BankTransferPayment' => \Mollie\Shopware\Component\Payment\Method\BankTransferPayment::class, + 'Kiener\MolliePayments\Handler\Method\BancomatPayment' => \Mollie\Shopware\Component\Payment\Method\BancomatPayPayment::class, + 'Kiener\MolliePayments\Handler\Method\PaySafeCardPayment' => \Mollie\Shopware\Component\Payment\Method\PaySafeCardPayment::class, + 'Kiener\MolliePayments\Handler\Method\PosPayment' => \Mollie\Shopware\Component\Payment\Method\PosPayment::class, + 'Kiener\MolliePayments\Handler\Method\VoucherPayment' => \Mollie\Shopware\Component\Payment\Method\VoucherPayment::class, + 'Kiener\MolliePayments\Handler\Method\PayPalExpressPayment' => \Mollie\Shopware\Component\Payment\Method\PayPalExpressPayment::class, + ]; + foreach ($replacementClasses as $class => $replacementClass) { + $replacementClass = addslashes($replacementClass); + $class = addslashes($class); + $sql = <<executeStatement($sql); + } + } +} diff --git a/src/Migration/Migration1768084646SubscriptionOrderVersionId.php b/src/Migration/Migration1768084646SubscriptionOrderVersionId.php new file mode 100644 index 000000000..9f948c45e --- /dev/null +++ b/src/Migration/Migration1768084646SubscriptionOrderVersionId.php @@ -0,0 +1,44 @@ +executeQuery($sql); + + $sql = 'ALTER TABLE `mollie_subscription_history` + ADD CONSTRAINT `fk.mollie_subscription_history.mollie_subscription` FOREIGN KEY (`subscription_id`) + REFERENCES `mollie_subscription` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +'; + $connection->executeQuery($sql); + + $sql = 'ALTER TABLE `mollie_subscription_address` + ADD CONSTRAINT `fk.mollie_subscription_history.mollie_subscription_address` FOREIGN KEY (`subscription_id`) + REFERENCES `mollie_subscription` (`id`) ON DELETE CASCADE ON UPDATE CASCADE +'; + $connection->executeQuery($sql); + } +} diff --git a/src/MolliePayments.php b/src/MolliePayments.php index 877a5b8ec..4e62bd5a3 100644 --- a/src/MolliePayments.php +++ b/src/MolliePayments.php @@ -13,12 +13,11 @@ use Shopware\Core\Framework\Plugin\Context\InstallContext; use Shopware\Core\Framework\Plugin\Context\UpdateContext; use Shopware\Core\Kernel; -use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerBuilder; class MolliePayments extends Plugin { - public const PLUGIN_VERSION = '4.23.0'; + public const PLUGIN_VERSION = '5.0.0-beta3'; /** * @throws \Exception @@ -57,12 +56,11 @@ public function update(UpdateContext $context): void parent::update($context); if ($context->getPlugin()->isActive() === true) { + $this->runDbMigrations($context->getMigrationCollection()); // only prepare our whole plugin // if it is indeed active at the moment. // otherwise service would not be found of course $this->preparePlugin($context->getContext()); - - $this->runDbMigrations($context->getMigrationCollection()); } } @@ -78,27 +76,6 @@ public function activate(ActivateContext $context): void $this->preparePlugin($context->getContext()); } - public function boot(): void - { - parent::boot(); - - if ($this->container === null) { - return; - } - /** @var Container $container */ - $container = $this->container; - - $shopwareVersion = $container->getParameter('kernel.shopware_version'); - if (! is_string($shopwareVersion)) { - $shopwareVersion = Kernel::SHOPWARE_FALLBACK_VERSION; - } - // load the dependencies that are compatible - // with our current shopware version - - $loader = new DependencyLoader($container, new VersionCompare($shopwareVersion)); - $loader->registerDependencies(); - } - /** * @throws \Doctrine\DBAL\Exception */ diff --git a/src/Resources/app/administration/package-lock.json b/src/Resources/app/administration/package-lock.json deleted file mode 100644 index a57df6a4b..000000000 --- a/src/Resources/app/administration/package-lock.json +++ /dev/null @@ -1,1923 +0,0 @@ -{ - "name": "mollie-shopware6-administration", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "mollie-shopware6-administration", - "version": "1.0.0", - "dependencies": { - "core-js": "^3.40.0", - "raw-loader": "^4.0.2", - "regenerator-runtime": "^0.14.1" - }, - "devDependencies": {} - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "peer": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "peer": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "peer": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "node_modules/@types/node": { - "version": "25.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", - "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", - "peer": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "peer": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "peer": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "peer": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "peer": true - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "peer": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-formats/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - }, - "node_modules/ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "peer": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", - "engines": { - "node": "*" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "peer": true - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001769", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", - "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "peer": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "peer": true - }, - "node_modules/core-js": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", - "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==", - "hasInstallScript": true, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "peer": true - }, - "node_modules/emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", - "engines": { - "node": ">= 4" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "peer": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "peer": true - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "peer": true - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "peer": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "peer": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "peer": true, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "peer": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "peer": true - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "peer": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "peer": true - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "engines": { - "node": ">=6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true - }, - "node_modules/schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "peer": true - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - } - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "peer": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "peer": true - }, - "@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "peer": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "peer": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "peer": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "peer": true - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==" - }, - "@types/node": { - "version": "25.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", - "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", - "peer": true, - "requires": { - "undici-types": "~7.16.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "peer": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "peer": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "peer": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "peer": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "peer": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "peer": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "peer": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "peer": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "peer": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "peer": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "peer": true - }, - "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "peer": true - }, - "acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "peer": true, - "requires": {} - }, - "ajv": { - "version": "6.14.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", - "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", - "requires": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "peer": true, - "requires": { - "ajv": "^8.0.0" - }, - "dependencies": { - "ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - } - } - }, - "ajv-keywords": { - "version": "3.5.2", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", - "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", - "requires": {} - }, - "baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "peer": true - }, - "big.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", - "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==" - }, - "browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "peer": true, - "requires": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "peer": true - }, - "caniuse-lite": { - "version": "1.0.30001769", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", - "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", - "peer": true - }, - "chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "peer": true - }, - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "peer": true - }, - "core-js": { - "version": "3.42.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.42.0.tgz", - "integrity": "sha512-Sz4PP4ZA+Rq4II21qkNqOEDTDrCvcANId3xpIgB34NDkWc3UduWj2dqEtN9yZIq8Dk3HyPI33x9sqqU5C8sr0g==" - }, - "electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "peer": true - }, - "emojis-list": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", - "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==" - }, - "enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "peer": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - } - }, - "es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "peer": true - }, - "escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "peer": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "peer": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "peer": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "peer": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "peer": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "peer": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" - }, - "fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" - }, - "fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "peer": true - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "peer": true - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "peer": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "peer": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "peer": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "peer": true - }, - "json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" - }, - "json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==" - }, - "loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "peer": true - }, - "loader-utils": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", - "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", - "requires": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "peer": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "peer": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "peer": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "peer": true - }, - "node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "peer": true - }, - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "peer": true - }, - "punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==" - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "peer": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "raw-loader": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", - "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", - "requires": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - } - }, - "regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==" - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "peer": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "peer": true - }, - "schema-utils": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", - "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", - "requires": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "peer": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "peer": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "peer": true - }, - "terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "peer": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - } - }, - "terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "dependencies": { - "ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - }, - "schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "peer": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "peer": true - }, - "update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "peer": true, - "requires": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - } - }, - "uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "requires": { - "punycode": "^2.1.0" - } - }, - "watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "peer": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", - "peer": true, - "requires": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - }, - "dependencies": { - "ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "peer": true - }, - "schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "peer": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - } - } - }, - "webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "peer": true - } - } -} diff --git a/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/index.js b/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/index.js index 29a620117..9e70bb3b3 100644 --- a/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/index.js +++ b/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/index.js @@ -90,7 +90,6 @@ Shopware.Component.register('sw-product-detail-mollie', { */ voucherTypes() { return [ - { value: 0, label: this.$tc('mollie-payments.vouchers.VOUCHER_TYPE_VALUE_NONE') }, { value: 1, label: this.$tc('mollie-payments.vouchers.VOUCHER_TYPE_VALUE_ECO') }, { value: 2, label: this.$tc('mollie-payments.vouchers.VOUCHER_TYPE_VALUE_MEAL') }, { value: 3, label: this.$tc('mollie-payments.vouchers.VOUCHER_TYPE_VALUE_VOUCHER') }, @@ -132,11 +131,25 @@ Shopware.Component.register('sw-product-detail-mollie', { if (!this.product.customFields) { this.product.customFields = {}; } + if (this.product.customFields.mollie_payments_product_voucher_type) { + if (!Array.isArray(this.product.customFields.mollie_payments_product_voucher_type)) { + this.product.customFields.mollie_payments_product_voucher_type = [ + this.product.customFields.mollie_payments_product_voucher_type, + ]; + } + } } if (this.parentProduct) { if (!this.parentProduct.customFields) { this.parentProduct.customFields = {}; } + if (this.parentProduct.customFields.mollie_payments_product_voucher_type) { + if (!Array.isArray(this.parentProduct.customFields.mollie_payments_product_voucher_type)) { + this.parentProduct.customFields.mollie_payments_product_voucher_type = [ + this.parentProduct.customFields.mollie_payments_product_voucher_type, + ]; + } + } } }, }, diff --git a/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/sw-product-detail-mollie.html.twig b/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/sw-product-detail-mollie.html.twig index 29bfe0a3e..2269f7bcd 100644 --- a/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/sw-product-detail-mollie.html.twig +++ b/src/Resources/app/administration/src/module/sw-product/view/sw-product-detail-mollie/sw-product-detail-mollie.html.twig @@ -36,7 +36,7 @@ :has-parent="!!parentProduct.id" :inherited-value="parentProduct.customFields.mollie_payments_product_voucher_type"> diff --git a/src/Resources/app/storefront/package-lock.json b/src/Resources/app/storefront/package-lock.json deleted file mode 100644 index b58935e81..000000000 --- a/src/Resources/app/storefront/package-lock.json +++ /dev/null @@ -1,2553 +0,0 @@ -{ - "name": "mollie-shopware6-storefront", - "version": "1.0.0", - "lockfileVersion": 2, - "requires": true, - "packages": { - "": { - "name": "mollie-shopware6-storefront", - "version": "1.0.0", - "devDependencies": { - "deepmerge": "^4.2.2", - "webpack-cli": "^6.0.1" - } - }, - "node_modules/@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", - "dev": true, - "engines": { - "node": ">=14.17.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "peer": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "peer": true, - "dependencies": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "node_modules/@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "peer": true - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "peer": true - }, - "node_modules/@types/node": { - "version": "25.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", - "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", - "dev": true, - "peer": true, - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "peer": true, - "dependencies": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "peer": true, - "dependencies": { - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "peer": true - }, - "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "peer": true, - "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "node_modules/@webpack-cli/configtest": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", - "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", - "dev": true, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "webpack": "^5.82.0", - "webpack-cli": "6.x.x" - } - }, - "node_modules/@webpack-cli/info": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", - "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", - "dev": true, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "webpack": "^5.82.0", - "webpack-cli": "6.x.x" - } - }, - "node_modules/@webpack-cli/serve": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", - "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", - "dev": true, - "engines": { - "node": ">=18.12.0" - }, - "peerDependencies": { - "webpack": "^5.82.0", - "webpack-cli": "6.x.x" - }, - "peerDependenciesMeta": { - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true - }, - "node_modules/@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - }, - "peerDependencies": { - "acorn": "^8.14.0" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "peer": true, - "dependencies": { - "ajv": "^8.0.0" - }, - "peerDependencies": { - "ajv": "^8.0.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "dev": true, - "peer": true, - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "peer": true - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001769", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", - "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true - }, - "node_modules/chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.0" - } - }, - "node_modules/clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "dependencies": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "dev": true, - "peer": true - }, - "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "dev": true, - "peer": true, - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", - "dev": true, - "bin": { - "envinfo": "dist/cli.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, - "peer": true - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "peer": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "peer": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "peer": true - }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, - "engines": { - "node": ">= 4.9.1" - } - }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "peer": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "peer": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "dependencies": { - "isobject": "^3.0.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "peer": true, - "dependencies": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "peer": true - }, - "node_modules/kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "peer": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "peer": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "peer": true - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "peer": true - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "peer": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "dependencies": { - "resolve": "^1.20.0" - }, - "engines": { - "node": ">= 10.13.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "peer": true - }, - "node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "peer": true, - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "peer": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "dependencies": { - "kind-of": "^6.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "peer": true, - "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "bin": { - "terser": "bin/terser" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, - "peer": true, - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.1.0" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "esbuild": { - "optional": true - }, - "uglify-js": { - "optional": true - } - } - }, - "node_modules/terser/node_modules/commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "peer": true - }, - "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "peer": true, - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, - "peer": true, - "dependencies": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", - "dev": true, - "peer": true, - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - }, - "bin": { - "webpack": "bin/webpack.js" - }, - "engines": { - "node": ">=10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependenciesMeta": { - "webpack-cli": { - "optional": true - } - } - }, - "node_modules/webpack-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", - "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@discoveryjs/json-ext": "^0.6.1", - "@webpack-cli/configtest": "^3.0.1", - "@webpack-cli/info": "^3.0.1", - "@webpack-cli/serve": "^3.0.1", - "colorette": "^2.0.14", - "commander": "^12.1.0", - "cross-spawn": "^7.0.3", - "envinfo": "^7.14.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^6.0.1" - }, - "bin": { - "webpack-cli": "bin/cli.js" - }, - "engines": { - "node": ">=18.12.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^5.82.0" - }, - "peerDependenciesMeta": { - "webpack-bundle-analyzer": { - "optional": true - }, - "webpack-dev-server": { - "optional": true - } - } - }, - "node_modules/webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "dev": true, - "dependencies": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, - "peer": true, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - } - }, - "dependencies": { - "@discoveryjs/json-ext": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.6.3.tgz", - "integrity": "sha512-4B4OijXeVNOPZlYA2oEwWOTkzyltLao+xbotHQeqN++Rv27Y6s818+n2Qkp8q+Fxhn0t/5lA5X1Mxktud8eayQ==", - "dev": true - }, - "@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "peer": true - }, - "@jridgewell/source-map": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", - "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "peer": true - }, - "@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "@types/eslint": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", - "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", - "dev": true, - "peer": true, - "requires": { - "@types/estree": "*", - "@types/json-schema": "*" - } - }, - "@types/eslint-scope": { - "version": "3.7.7", - "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", - "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", - "dev": true, - "peer": true, - "requires": { - "@types/eslint": "*", - "@types/estree": "*" - } - }, - "@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "peer": true - }, - "@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "peer": true - }, - "@types/node": { - "version": "25.2.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-25.2.1.tgz", - "integrity": "sha512-CPrnr8voK8vC6eEtyRzvMpgp3VyVRhgclonE7qYi6P9sXwYb59ucfrnmFBTaP0yUi8Gk4yZg/LlTJULGxvTNsg==", - "dev": true, - "peer": true, - "requires": { - "undici-types": "~7.16.0" - } - }, - "@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" - } - }, - "@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "dev": true, - "peer": true - }, - "@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" - } - }, - "@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "dev": true, - "peer": true, - "requires": { - "@xtuc/ieee754": "^1.2.0" - } - }, - "@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "dev": true, - "peer": true, - "requires": { - "@xtuc/long": "4.2.2" - } - }, - "@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "dev": true, - "peer": true - }, - "@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" - } - }, - "@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" - } - }, - "@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" - } - }, - "@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "dev": true, - "peer": true, - "requires": { - "@webassemblyjs/ast": "1.14.1", - "@xtuc/long": "4.2.2" - } - }, - "@webpack-cli/configtest": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-3.0.1.tgz", - "integrity": "sha512-u8d0pJ5YFgneF/GuvEiDA61Tf1VDomHHYMjv/wc9XzYj7nopltpG96nXN5dJRstxZhcNpV1g+nT6CydO7pHbjA==", - "dev": true, - "requires": {} - }, - "@webpack-cli/info": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-3.0.1.tgz", - "integrity": "sha512-coEmDzc2u/ffMvuW9aCjoRzNSPDl/XLuhPdlFRpT9tZHmJ/039az33CE7uH+8s0uL1j5ZNtfdv0HkfaKRBGJsQ==", - "dev": true, - "requires": {} - }, - "@webpack-cli/serve": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-3.0.1.tgz", - "integrity": "sha512-sbgw03xQaCLiT6gcY/6u3qBDn01CWw/nbaXl3gTdTFuJJ75Gffv3E3DBpgvY2fkkrdS1fpjaXNOmJlnbtKauKg==", - "dev": true, - "requires": {} - }, - "@xtuc/ieee754": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "dev": true, - "peer": true - }, - "@xtuc/long": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "dev": true, - "peer": true - }, - "acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, - "peer": true - }, - "acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "dev": true, - "peer": true, - "requires": {} - }, - "ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "dev": true, - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - } - }, - "ajv-formats": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", - "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", - "dev": true, - "peer": true, - "requires": { - "ajv": "^8.0.0" - } - }, - "ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "dev": true, - "peer": true, - "requires": { - "fast-deep-equal": "^3.1.3" - } - }, - "baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "dev": true, - "peer": true - }, - "browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "peer": true, - "requires": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - } - }, - "buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "dev": true, - "peer": true - }, - "caniuse-lite": { - "version": "1.0.30001769", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001769.tgz", - "integrity": "sha512-BCfFL1sHijQlBGWBMuJyhZUhzo7wer5sVj9hqekB/7xn0Ypy+pER/edCYQm4exbXj4WiySGp40P8UuTh6w1srg==", - "dev": true, - "peer": true - }, - "chrome-trace-event": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", - "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", - "dev": true, - "peer": true - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, - "deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true - }, - "electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "dev": true, - "peer": true - }, - "enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "dev": true, - "peer": true, - "requires": { - "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" - } - }, - "envinfo": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", - "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", - "dev": true - }, - "es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "dev": true, - "peer": true - }, - "escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "peer": true - }, - "eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "peer": true, - "requires": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - } - }, - "esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "peer": true, - "requires": { - "estraverse": "^5.2.0" - }, - "dependencies": { - "estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "peer": true - } - } - }, - "estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "peer": true - }, - "events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "dev": true, - "peer": true - }, - "fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "peer": true - }, - "fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "dev": true, - "peer": true - }, - "fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true - }, - "function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true - }, - "glob-to-regexp": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", - "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", - "dev": true, - "peer": true - }, - "graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "peer": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "peer": true - }, - "hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "requires": { - "function-bind": "^1.1.2" - } - }, - "import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", - "dev": true, - "requires": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - } - }, - "interpret": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", - "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", - "dev": true - }, - "is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "requires": { - "hasown": "^2.0.2" - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", - "dev": true - }, - "jest-worker": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", - "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", - "dev": true, - "peer": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" - } - }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true, - "peer": true - }, - "json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "dev": true, - "peer": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "dev": true, - "peer": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true, - "peer": true - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "peer": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "peer": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "neo-async": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", - "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", - "dev": true, - "peer": true - }, - "node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "peer": true - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "peer": true - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "peer": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "rechoir": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", - "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", - "dev": true, - "requires": { - "resolve": "^1.20.0" - } - }, - "require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "dev": true, - "peer": true - }, - "resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "requires": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - } - }, - "resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "requires": { - "resolve-from": "^5.0.0" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "peer": true - }, - "schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "dev": true, - "peer": true, - "requires": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - } - }, - "serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "peer": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "peer": true - }, - "source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", - "dev": true, - "peer": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - } - }, - "supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "peer": true, - "requires": { - "has-flag": "^4.0.0" - } - }, - "supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true - }, - "tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "dev": true, - "peer": true - }, - "terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", - "commander": "^2.20.0", - "source-map-support": "~0.5.20" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true, - "peer": true - } - } - }, - "terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "dev": true, - "peer": true, - "requires": { - "@jridgewell/trace-mapping": "^0.3.25", - "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" - } - }, - "undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "dev": true, - "peer": true - }, - "update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", - "dev": true, - "peer": true, - "requires": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - } - }, - "watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "dev": true, - "peer": true, - "requires": { - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.1.2" - } - }, - "webpack": { - "version": "5.105.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.0.tgz", - "integrity": "sha512-gX/dMkRQc7QOMzgTe6KsYFM7DxeIONQSui1s0n/0xht36HvrgbxtM1xBlgx596NbpHuQU8P7QpKwrZYwUX48nw==", - "dev": true, - "peer": true, - "requires": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", - "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", - "eslint-scope": "5.1.1", - "events": "^3.2.0", - "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", - "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", - "mime-types": "^2.1.27", - "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" - } - }, - "webpack-cli": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-6.0.1.tgz", - "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", - "dev": true, - "requires": { - "@discoveryjs/json-ext": "^0.6.1", - "@webpack-cli/configtest": "^3.0.1", - "@webpack-cli/info": "^3.0.1", - "@webpack-cli/serve": "^3.0.1", - "colorette": "^2.0.14", - "commander": "^12.1.0", - "cross-spawn": "^7.0.3", - "envinfo": "^7.14.0", - "fastest-levenshtein": "^1.0.12", - "import-local": "^3.0.2", - "interpret": "^3.1.1", - "rechoir": "^0.8.0", - "webpack-merge": "^6.0.1" - } - }, - "webpack-merge": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz", - "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "flat": "^5.0.2", - "wildcard": "^2.0.1" - } - }, - "webpack-sources": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.3.tgz", - "integrity": "sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==", - "dev": true, - "peer": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "wildcard": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", - "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", - "dev": true - } - } -} diff --git a/src/Resources/app/storefront/package.json b/src/Resources/app/storefront/package.json index d0c9dd9b6..ee37867a1 100644 --- a/src/Resources/app/storefront/package.json +++ b/src/Resources/app/storefront/package.json @@ -5,6 +5,7 @@ "author": "Mollie B.V.", "devDependencies": { "deepmerge": "^4.2.2", + "webpack": "^5.102.1", "webpack-cli": "^6.0.1" } } diff --git a/src/Resources/app/storefront/src/mollie-payments/core/creditcard-mandate.plugin.js b/src/Resources/app/storefront/src/mollie-payments/core/creditcard-mandate.plugin.js index 86f1eff96..f15ab0165 100644 --- a/src/Resources/app/storefront/src/mollie-payments/core/creditcard-mandate.plugin.js +++ b/src/Resources/app/storefront/src/mollie-payments/core/creditcard-mandate.plugin.js @@ -11,7 +11,7 @@ export default class MollieCreditCardMandate extends Plugin { static options = { newCardMandateOption: null, mollieCreditCardFormClass: '.mollie-components-credit-card', - mollieCreditCardMandateInput: 'input[name="mollieCreditCardMandate"]', + mollieCreditCardMandateInput: 'input[name="mandateId"]', mollieShouldSaveCardDetailInput: 'input[name="mollieShouldSaveCardDetail"]', }; diff --git a/src/Resources/app/storefront/src/mollie-payments/plugins/creditcard-components-sw64.plugin.js b/src/Resources/app/storefront/src/mollie-payments/plugins/creditcard-components-sw64.plugin.js index 38ca561a5..6a96f62e5 100644 --- a/src/Resources/app/storefront/src/mollie-payments/plugins/creditcard-components-sw64.plugin.js +++ b/src/Resources/app/storefront/src/mollie-payments/plugins/creditcard-components-sw64.plugin.js @@ -233,17 +233,7 @@ export default class MollieCreditCardComponentsSw64 extends MollieCreditCardMand // so we have to call the API to save it // and then we continue by submitting our original payment form. if (this.isValidSelectedMandate(mandateId)) { - this.client.post( - me.options.shopUrl + '/mollie/components/store-mandate-id/' + me.options.customerId + '/' + mandateId, - () => { - me.continueShopwareCheckout(paymentForm); - }, - () => { - me.continueShopwareCheckout(paymentForm); - }, - 'application/json; charset=utf-8', - ); - + me.continueShopwareCheckout(paymentForm); return; } @@ -260,23 +250,10 @@ export default class MollieCreditCardComponentsSw64 extends MollieCreditCardMand verificationErrors.scrollIntoView(); return; } - - // now we finish by first calling our URL to store - // the credit card token for the user and the current checkout - // and then we continue by submitting our original payment form. - this.client.post( - me.options.shopUrl + '/mollie/components/store-card-token/' + token, - JSON.stringify({ - shouldSaveCardDetail: this.shouldSaveCardDetail(), - }), - function () { - me.continueShopwareCheckout(paymentForm); - }, - function () { - me.continueShopwareCheckout(paymentForm); - }, - 'application/json; charset=utf-8', - ); + /** @type HTMLInputElement **/ + const tokenInput = document.getElementById('cardToken'); + tokenInput.value = token; + me.continueShopwareCheckout(paymentForm); } /** diff --git a/src/Resources/config/packages/monolog.xml b/src/Resources/config/packages/monolog.xml index 3f3cd7ce1..2d1a658f1 100644 --- a/src/Resources/config/packages/monolog.xml +++ b/src/Resources/config/packages/monolog.xml @@ -10,6 +10,15 @@ mollie + + + diff --git a/src/Resources/config/routes/admin-api/payment_method.xml b/src/Resources/config/routes/admin-api/payment_method.xml deleted file mode 100644 index 4f6a725d0..000000000 --- a/src/Resources/config/routes/admin-api/payment_method.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Api\PaymentMethod\PaymentMethodControllerBase::updatePaymentMethods - api - true - true - - - - Kiener\MolliePayments\Controller\Api\PaymentMethod\PaymentMethodControllerBase::updatePaymentMethodsLegacy - api - true - true - - - diff --git a/src/Resources/config/routes/admin-api/return.xml b/src/Resources/config/routes/admin-api/return.xml deleted file mode 100644 index 88119e9ae..000000000 --- a/src/Resources/config/routes/admin-api/return.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - Kiener\MolliePayments\Controller\Api\Payment\ReturnControllerBase::returnAction - api - false - false - - - - Kiener\MolliePayments\Controller\Api\Payment\ReturnControllerBase::returnActionLegacy - api - false - false - - diff --git a/src/Resources/config/routes/admin-api/shipping.xml b/src/Resources/config/routes/admin-api/shipping.xml index 908410c9a..ec8466172 100644 --- a/src/Resources/config/routes/admin-api/shipping.xml +++ b/src/Resources/config/routes/admin-api/shipping.xml @@ -68,12 +68,6 @@ true - - Kiener\MolliePayments\Controller\Api\Order\ShippingControllerBase::shipOrderAdmin - api - true - true - Kiener\MolliePayments\Controller\Api\Order\ShippingControllerBase::shipOrderAdminLegacy diff --git a/src/Resources/config/routes/admin-api/subscription.xml b/src/Resources/config/routes/admin-api/subscription.xml index 27e826197..2b4ab6878 100644 --- a/src/Resources/config/routes/admin-api/subscription.xml +++ b/src/Resources/config/routes/admin-api/subscription.xml @@ -4,61 +4,6 @@ xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::cancel - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::cancelLegacy - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::pause - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::pauseLegacy - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::resume - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::resumeLegacy - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::skip - api - true - true - - - - Kiener\MolliePayments\Controller\Api\Subscription\SubscriptionControllerBase::skipLegacy - api - true - true - diff --git a/src/Resources/config/routes/admin-api/webhook.xml b/src/Resources/config/routes/admin-api/webhook.xml index 49f105196..dd04b7abf 100644 --- a/src/Resources/config/routes/admin-api/webhook.xml +++ b/src/Resources/config/routes/admin-api/webhook.xml @@ -4,47 +4,11 @@ xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookAction - api - false - false - - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookLegacyAction - api - false - false - - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookSubscriptionAction - api - false - false - - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookSubscriptionLegacyAction - api - false - false - - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookSubscriptionRenewAction - api - false - false - - - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookSubscriptionRenewLegacyAction - api - false - false - Kiener\MolliePayments\Controller\Api\Webhook\WebhookControllerBase::webhookSubscriptionMandateUpdatedAction diff --git a/src/Resources/config/routes/store-api/apple_pay_direct.xml b/src/Resources/config/routes/store-api/apple_pay_direct.xml deleted file mode 100644 index f5ecfaa2b..000000000 --- a/src/Resources/config/routes/store-api/apple_pay_direct.xml +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::isEnabled - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::getId - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::addProduct - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::createPaymentSession - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::getCart - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::getShippingMethods - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::setShippingMethod - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::pay - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\ApplePayDirect\ApplePayDirectControllerBase::restoreCart - store-api - - - diff --git a/src/Resources/config/routes/store-api/credit_card.xml b/src/Resources/config/routes/store-api/credit_card.xml deleted file mode 100644 index 1e968aad2..000000000 --- a/src/Resources/config/routes/store-api/credit_card.xml +++ /dev/null @@ -1,42 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\StoreApi\CreditCard\CreditCardControllerBase::saveCardToken - store-api - true - true - - - - Kiener\MolliePayments\Controller\StoreApi\CreditCard\CreditCardControllerBase::saveMandateId - store-api - true - true - - - - Kiener\MolliePayments\Controller\StoreApi\CreditCard\CreditCardControllerBase::revokeMandate - store-api - true - true - - - - Kiener\MolliePayments\Controller\StoreApi\CreditCard\CreditCardControllerBase::getMandates - store-api - true - true - - diff --git a/src/Resources/config/routes/store-api/paypal_express.xml b/src/Resources/config/routes/store-api/paypal_express.xml deleted file mode 100644 index 36d1f4bd4..000000000 --- a/src/Resources/config/routes/store-api/paypal_express.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - Kiener\MolliePayments\Components\PaypalExpress\Route\StartCheckoutRoute::startCheckout - store-api - - - - Kiener\MolliePayments\Components\PaypalExpress\Route\FinishCheckoutRoute::finishCheckout - store-api - - - - Kiener\MolliePayments\Components\PaypalExpress\Route\CancelCheckoutRoute::cancelCheckout - store-api - - - diff --git a/src/Resources/config/routes/store-api/pos.xml b/src/Resources/config/routes/store-api/pos.xml deleted file mode 100644 index 8002a84b1..000000000 --- a/src/Resources/config/routes/store-api/pos.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\StoreApi\POS\PosControllerBase::getIssuers - store-api - - - - Kiener\MolliePayments\Controller\StoreApi\POS\PosControllerBase::saveTerminalId - store-api - true - true - - diff --git a/src/Resources/config/routes/storefront/account.xml b/src/Resources/config/routes/storefront/account.xml index c0e5ab74e..81ac13845 100644 --- a/src/Resources/config/routes/storefront/account.xml +++ b/src/Resources/config/routes/storefront/account.xml @@ -50,33 +50,5 @@ storefront - - Kiener\MolliePayments\Controller\Storefront\Account\AccountControllerBase::pauseSubscription - storefront - - - - Kiener\MolliePayments\Controller\Storefront\Account\AccountControllerBase::skipSubscription - storefront - - - - Kiener\MolliePayments\Controller\Storefront\Account\AccountControllerBase::resumeSubscription - storefront - - - - Kiener\MolliePayments\Controller\Storefront\Account\AccountControllerBase::cancelSubscription - storefront - - diff --git a/src/Resources/config/routes/storefront/apple_pay_direct.xml b/src/Resources/config/routes/storefront/apple_pay_direct.xml deleted file mode 100644 index 25cefeb34..000000000 --- a/src/Resources/config/routes/storefront/apple_pay_direct.xml +++ /dev/null @@ -1,74 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::isPaymentAvailable - storefront - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::getApplePayID - storefront - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::addProduct - storefront - false - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::createPaymentSession - storefront - false - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::getShippingMethods - storefront - false - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::setShippingMethod - storefront - false - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::startPayment - storefront - false - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::finishPayment - storefront - false - true - - - - - Kiener\MolliePayments\Controller\Storefront\ApplePayDirect\ApplePayDirectControllerBase::restoreCart - storefront - false - - - - diff --git a/src/Resources/config/routes/storefront/credit_card.xml b/src/Resources/config/routes/storefront/credit_card.xml deleted file mode 100644 index 8598492f1..000000000 --- a/src/Resources/config/routes/storefront/credit_card.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Storefront\CreditCard\CreditCardControllerBase::storeCardToken - storefront - true - true - - - - - Kiener\MolliePayments\Controller\Storefront\CreditCard\CreditCardControllerBase::storeMandateId - storefront - true - true - - - - - Kiener\MolliePayments\Controller\Storefront\CreditCard\CreditCardControllerBase::revokeMandate - storefront - true - true - - - diff --git a/src/Resources/config/routes/storefront/paypal_express.xml b/src/Resources/config/routes/storefront/paypal_express.xml deleted file mode 100644 index 03dfe80f0..000000000 --- a/src/Resources/config/routes/storefront/paypal_express.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Storefront\PaypalExpress\PaypalExpressControllerBase::startCheckout - storefront - true - - - - - Kiener\MolliePayments\Controller\Storefront\PaypalExpress\PaypalExpressControllerBase::finishCheckout - storefront - true - - - - - Kiener\MolliePayments\Controller\Storefront\PaypalExpress\PaypalExpressControllerBase::cancelCheckout - storefront - true - - - diff --git a/src/Resources/config/routes/storefront/pos.xml b/src/Resources/config/routes/storefront/pos.xml deleted file mode 100644 index a4f1a4d4a..000000000 --- a/src/Resources/config/routes/storefront/pos.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Storefront\POS\PosControllerBase::storeTerminal - storefront - - true - true - - - - Kiener\MolliePayments\Controller\Storefront\POS\PosControllerBase::checkoutAction - storefront - - true - true - - - - Kiener\MolliePayments\Controller\Storefront\POS\PosControllerBase::statusAction - storefront - - true - true - - - diff --git a/src/Resources/config/routes/storefront/return.xml b/src/Resources/config/routes/storefront/return.xml deleted file mode 100644 index ddb191907..000000000 --- a/src/Resources/config/routes/storefront/return.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - .* - Kiener\MolliePayments\Controller\Storefront\Payment\ReturnControllerBase::payment - false - storefront - - - diff --git a/src/Resources/config/routes/storefront/webhook.xml b/src/Resources/config/routes/storefront/webhook.xml deleted file mode 100644 index 1f4f94a81..000000000 --- a/src/Resources/config/routes/storefront/webhook.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - - - Kiener\MolliePayments\Controller\Storefront\Webhook\WebhookControllerBase::onWebhookReceived - storefront - false - - - - - Kiener\MolliePayments\Controller\Storefront\Webhook\WebhookControllerBase::onWebhookSubscriptionReceived - storefront - false - - - - - Kiener\MolliePayments\Controller\Storefront\Webhook\WebhookControllerBase::onWebhookSubscriptionLegacyReceived - storefront - false - - - diff --git a/src/Resources/config/services.xml b/src/Resources/config/services.xml index 8efb3cbc3..8a125a110 100644 --- a/src/Resources/config/services.xml +++ b/src/Resources/config/services.xml @@ -23,14 +23,12 @@ - - @@ -42,6 +40,7 @@ + @@ -101,31 +100,17 @@ - - - - - - - - - - - %env(default::MOLLIE_PAYPAL_EXPRESS_BETA)% - %env(default::MOLLIE_PAYPAL_EXPRESS_BUTTON_STYLE)% - %env(default::MOLLIE_PAYPAL_EXPRESS_BUTTON_SHAPE)% - %env(default::MOLLIE_PAYPAL_EXPRESS_BUTTON_RESTRICTIONS)% - + - + %env(default::MOLLIE_SHOP_DOMAIN)% %env(default::MOLLIE_DEV_MODE)% %env(default::MOLLIE_CYPRESS_MODE)% @@ -144,10 +129,6 @@ - - - - @@ -182,12 +163,6 @@ - - - - - - @@ -213,12 +188,6 @@ - - - - - @@ -247,10 +216,7 @@ - - - - + diff --git a/src/Resources/config/services/commands.xml b/src/Resources/config/services/commands.xml index 0bc6977b8..99e72a381 100644 --- a/src/Resources/config/services/commands.xml +++ b/src/Resources/config/services/commands.xml @@ -1,48 +1,35 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %env(APP_ENV)% - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Resources/config/services/components.xml b/src/Resources/config/services/components.xml index dcdf20a1f..0733fe84b 100644 --- a/src/Resources/config/services/components.xml +++ b/src/Resources/config/services/components.xml @@ -43,7 +43,7 @@ - + @@ -52,14 +52,7 @@ - - - - - - - - + diff --git a/src/Resources/config/services/controller.xml b/src/Resources/config/services/controller.xml index 5b1493369..4b1194fd7 100644 --- a/src/Resources/config/services/controller.xml +++ b/src/Resources/config/services/controller.xml @@ -48,15 +48,6 @@ - - - - - - - - - @@ -184,44 +175,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -236,17 +190,7 @@ - - - - - - - - - - - + @@ -260,18 +204,6 @@ - - - - - - - - - - - - @@ -280,32 +212,10 @@ - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/src/Resources/config/services/fixtures/fixtures.xml b/src/Resources/config/services/fixtures/fixtures.xml deleted file mode 100644 index 81d6f6731..000000000 --- a/src/Resources/config/services/fixtures/fixtures.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/services/handlers.xml b/src/Resources/config/services/handlers.xml index 349f0b081..affa93540 100644 --- a/src/Resources/config/services/handlers.xml +++ b/src/Resources/config/services/handlers.xml @@ -14,313 +14,27 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/services/payment.xml b/src/Resources/config/services/payment.xml index b97d85cd0..a297997b1 100644 --- a/src/Resources/config/services/payment.xml +++ b/src/Resources/config/services/payment.xml @@ -30,42 +30,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Resources/config/services/services.xml b/src/Resources/config/services/services.xml index 3d49dc7b1..3832d9c4b 100644 --- a/src/Resources/config/services/services.xml +++ b/src/Resources/config/services/services.xml @@ -35,7 +35,6 @@ - @@ -139,10 +138,6 @@ - - - - @@ -150,12 +145,7 @@ - - - - - - + diff --git a/src/Resources/config/services/subscriber.xml b/src/Resources/config/services/subscriber.xml index 413d7d02c..308eac710 100644 --- a/src/Resources/config/services/subscriber.xml +++ b/src/Resources/config/services/subscriber.xml @@ -6,14 +6,7 @@ - - - - - - - - + @@ -53,14 +46,7 @@ - - - - - - - - + @@ -81,7 +67,7 @@ - + @@ -94,7 +80,5 @@ - - diff --git a/src/Resources/config/services/subscription/services.xml b/src/Resources/config/services/subscription/services.xml index 8b8b99b28..ae87aee2e 100644 --- a/src/Resources/config/services/subscription/services.xml +++ b/src/Resources/config/services/subscription/services.xml @@ -8,38 +8,15 @@ - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -270,15 +247,8 @@ - - - - - - - - + diff --git a/src/Resources/public/administration/assets/mollie-payments-9-lkyVmo.css b/src/Resources/public/administration/assets/mollie-payments-9-lkyVmo.css new file mode 100644 index 000000000..21c90a1c1 --- /dev/null +++ b/src/Resources/public/administration/assets/mollie-payments-9-lkyVmo.css @@ -0,0 +1 @@ +.mollie-pluginconfig-info .title{font-size:16px;font-weight:700}.mollie-pluginconfig-info .description{margin-top:20px}.mollie-pluginconfig-info .description-footer{margin-top:10px;font-size:12px}.mollie-pluginconfig-info .list{margin-left:30px}.mollie-pluginconfig-info .list .list-item{margin-bottom:15px}.mollie-pluginconfig-info .btn-action{width:100%;margin-bottom:10px;text-align:left}.mollie-pluginconfig-info .link-troubleshooting{margin-top:10px}.mollie-pluginconfig-info .col-right{display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:flex-end}.mollie-pluginconfig-payments-link-limits{position:absolute!important;right:45px}.mollie-pluginconfig-payments-format-preview{background-color:#f8f8f8;border:solid 1px #189eff;border-radius:9px;padding:20px;margin-bottom:20px}.mollie-pluginconfig-payments-format-preview .mollie-pluginconfig-payments-format-text{font-size:14px;margin-left:5px}.mollie-roundingconfig{margin-top:15px;margin-bottom:15px}.mollie-support-modal__form :last-child{margin-bottom:0}.mollie-support-modal .sw-description-list{position:relative}.mollie-support-modal .sw-description-list dt,.mollie-support-modal .sw-description-list dd{border-bottom:none}.mollie-support-modal .sw-description-list dt{padding:16px 4px 4px}.mollie-support-modal .sw-description-list dt:first-child{padding-top:0}.mollie-support-modal .sw-description-list dd{padding:1px 4px}.mollie-support-modal .sw-text-editor .sw-text-editor__content-editor p{margin-top:0;margin-bottom:1em}.mollie-support-modal .sw-text-editor .sw-text-editor__content-editor div{margin-top:0}.mollie-btn-action-custom{display:flex!important;align-items:center;gap:4px}.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__description-title{font-weight:700;font-size:14px;text-align:center}.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__image-container{display:flex!important;flex-direction:column!important;justify-content:center!important;align-items:center!important;margin-top:20px}.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__image-container .mollie-payments-flowsequence-action-order-ship-modal__image{width:80px}.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__description-title{font-weight:700;font-size:14px;text-align:center}.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__image-container{display:flex!important;flex-direction:column!important;justify-content:center!important;align-items:center!important;margin-top:20px}.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__image-container .mollie-payments-flowsequence-action-order-refund-modal__image{width:80px}.mollie-credit-card-logo,.mollie-credit-card-text{vertical-align:middle;display:inline-block;font-size:14px}.mollie-subscriptions-grid-btn-edit a{color:#3d4c5c;text-decoration:none}.mollie-subscriptions-detail .mollie-subscriptions-detail-link-button a{color:#fff;text-decoration:none}.mollie-subscriptions-detail .mollie-subscriptions-detail-status-action-row{margin-bottom:20px}.mollie-subscriptions-detail .cy-btn-pause,.mollie-subscriptions-detail .cy-btn-skip,.mollie-subscriptions-detail .danger{background:#de294c;color:#fff;line-height:36px}.sw-product-detail-mollie-subscription-form__subscriptionInterval,.sw-product-detail-mollie-subscription-form__subscriptionRepetition{display:inline-flex}.sw-product-detail-mollie-subscription-form__subscriptionInterval .subscription-form-field,.sw-product-detail-mollie-subscription-form__subscriptionRepetition .subscription-form-field{width:49%;margin-right:10px}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-subscription__description-title,.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__description-title,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-subscription__description-title,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__description-title{font-weight:700;font-size:14px;text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__image-container,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__image-container{display:flex!important;flex-direction:column!important;justify-content:center!important;align-items:center!important;margin-top:20px}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__image-container .sw-product-detail-mollie-vouchers__image,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__image-container .sw-product-detail-mollie-vouchers__image{width:80px}.sw-product-detail-mollie-subscription-form__container .sw-product-feature-set-form__description-body,.sw-product-detail-mollie-vouchers-form__container .sw-product-feature-set-form__description-body{font-size:12px;margin-top:20px;margin-bottom:30px;text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__button-readmore,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__button-readmore{text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__inheritance-warning,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__inheritance-warning{margin-top:20px;font-size:14px}.mollie-ship-order-grid.sw-data-grid.is--compact .sw-data-grid__cell-content{padding:10px 20px;height:42px}.mollie-modal-refund-manager .sw-modal__body{padding:0}.mollie-order-user-card-subscription-badge{margin-top:10px}.mollie-order-user-card-subscription-badge a{text-decoration:none}.sw-order-detail-base__mollie-info .mollie-property-column-left{float:left}.sw-order-detail-base__mollie-info .mollie-property-column-right{float:right}.sw-order-detail-base__mollie-info .mollie-property-section{margin-bottom:20px}.sw-order-detail-base__mollie-info .mollie-property-title{font-weight:600;color:#52667a;font-size:14px}.sw-order-detail-base__mollie-info .mollie-property-creditcard-section{margin-top:6px}.sw-order-detail-base__mollie-info .mollie-property-content{font-size:14px}.sw-order-detail-base__mollie-info .mollie-property-paymentlink-button{margin-top:10px}.mollie-tracking-info__tracking-code-button{margin-bottom:.25rem}.mollie-tracking-info__tracking-code-button:not(:last-child){margin-right:.25rem}.mollie-refund-manager{width:100%;background-color:#f0f2f5;padding:20px;display:inline-table}.mollie-refund-manager .color-delivery{color:#189eff}.mollie-refund-manager .color-refund{color:#1abc9c}.mollie-refund-manager .color-stock{color:#ca5208}.mollie-refund-manager .color-promotion{color:gold}.mollie-refund-manager .color-product-discounted{color:#d2d2d2}.mollie-refund-manager .color-refunded{color:#1abc9c}.mollie-refund-manager .color-rounding-item{color:#ca5208}.mollie-refund-manager .sw-card--large{margin-left:20px;margin-right:20px;max-width:100%}.mollie-refund-manager .tutorial-active{border:red solid 4px;padding:6px}.mollie-refund-manager .danger{background:#de294c;color:#fff;line-height:36px}.mollie-refund-manager .warning{background:gold;color:#52667a;line-height:36px}.mollie-refund-manager .mollie-refund-manager-order-container .order-container-top .order-container-top-left{text-align:left}.mollie-refund-manager .mollie-refund-manager-order-container .order-container-top .order-container-top-right{text-align:right}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid .order-item-icon{margin-right:10px}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid input{padding:6px;text-align:center}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid .sw-field__addition{padding:6px}.mollie-refund-manager .mollie-refund-manager-order-container .input-mode-active input{background:#faebd7}.mollie-refund-manager .mollie-refund-manager-order-container .input-mode-inactive input{background:initial}.mollie-refund-manager .mollie-refund-manager-order-container .check-deduct-promotion label,.mollie-refund-manager .mollie-refund-manager-order-container .check-refund-tax label{font-size:12px}.mollie-refund-manager .mollie-refund-manager-order-container .rounding-item-info-container{margin-top:20px;margin-left:20px}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-top{text-align:left}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-content .instructions-block{margin-bottom:30px}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-content .instructions-block-icon{margin-right:10px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-loading-container{margin-bottom:50px;text-align:center}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content{margin-bottom:20px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value{text-align:right;padding-right:0}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value.heading{font-weight:700}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value.no-border{border-bottom-color:transparent}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value-remaining{margin:0;padding-right:5px;font-size:14px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-fix-available{color:red;font-size:16px}.mollie-refund-manager .mollie-refund-manager-summary-container .btn-fix-diff{margin-bottom:5px;margin-left:1px}.mollie-refund-manager .mollie-refund-manager-summary-container input{padding:6px;text-align:center}.mollie-refund-manager .mollie-refund-manager-summary-container .field-description{margin-bottom:10px}.mollie-refund-manager .mollie-refund-manager-refunds .instructions-bar{display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:flex-end;margin-bottom:30px}.mollie-ship-order .mollie-ship-order-grid .mollie-ship-order-grid-quantity input:not([disabled]){background-color:#fff5e0} diff --git a/src/Resources/public/administration/assets/mollie-payments-CovvkgK6.js b/src/Resources/public/administration/assets/mollie-payments-CovvkgK6.js new file mode 100644 index 000000000..4ac4f3936 --- /dev/null +++ b/src/Resources/public/administration/assets/mollie-payments-CovvkgK6.js @@ -0,0 +1,8 @@ +var od=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{},Za={exports:{}},sd;function AT(){return sd||(sd=1,(function(e){var t=(function(r){var a=Object.prototype,i=a.hasOwnProperty,n=Object.defineProperty||function(j,O,D){j[O]=D.value},o,l=typeof Symbol=="function"?Symbol:{},s=l.iterator||"@@iterator",u=l.asyncIterator||"@@asyncIterator",d=l.toStringTag||"@@toStringTag";function c(j,O,D){return Object.defineProperty(j,O,{value:D,enumerable:!0,configurable:!0,writable:!0}),j[O]}try{c({},"")}catch{c=function(O,D,$){return O[D]=$}}function p(j,O,D,$){var U=O&&O.prototype instanceof k?O:k,ae=Object.create(U.prototype),Me=new q($||[]);return n(ae,"_invoke",{value:M(j,D,Me)}),ae}r.wrap=p;function v(j,O,D){try{return{type:"normal",arg:j.call(O,D)}}catch($){return{type:"throw",arg:$}}}var m="suspendedStart",h="suspendedYield",b="executing",f="completed",g={};function k(){}function y(){}function _(){}var S={};c(S,s,function(){return this});var R=Object.getPrototypeOf,w=R&&R(R(V([])));w&&w!==a&&i.call(w,s)&&(S=w);var E=_.prototype=k.prototype=Object.create(S);y.prototype=_,n(E,"constructor",{value:_,configurable:!0}),n(_,"constructor",{value:y,configurable:!0}),y.displayName=c(_,d,"GeneratorFunction");function P(j){["next","throw","return"].forEach(function(O){c(j,O,function(D){return this._invoke(O,D)})})}r.isGeneratorFunction=function(j){var O=typeof j=="function"&&j.constructor;return O?O===y||(O.displayName||O.name)==="GeneratorFunction":!1},r.mark=function(j){return Object.setPrototypeOf?Object.setPrototypeOf(j,_):(j.__proto__=_,c(j,d,"GeneratorFunction")),j.prototype=Object.create(E),j},r.awrap=function(j){return{__await:j}};function A(j,O){function D(ae,Me,he,fe){var K=v(j[ae],j,Me);if(K.type==="throw")fe(K.arg);else{var le=K.arg,ge=le.value;return ge&&typeof ge=="object"&&i.call(ge,"__await")?O.resolve(ge.__await).then(function(_e){D("next",_e,he,fe)},function(_e){D("throw",_e,he,fe)}):O.resolve(ge).then(function(_e){le.value=_e,he(le)},function(_e){return D("throw",_e,he,fe)})}}var $;function U(ae,Me){function he(){return new O(function(fe,K){D(ae,Me,fe,K)})}return $=$?$.then(he,he):he()}n(this,"_invoke",{value:U})}P(A.prototype),c(A.prototype,u,function(){return this}),r.AsyncIterator=A,r.async=function(j,O,D,$,U){U===void 0&&(U=Promise);var ae=new A(p(j,O,D,$),U);return r.isGeneratorFunction(O)?ae:ae.next().then(function(Me){return Me.done?Me.value:ae.next()})};function M(j,O,D){var $=m;return function(ae,Me){if($===b)throw new Error("Generator is already running");if($===f){if(ae==="throw")throw Me;return F()}for(D.method=ae,D.arg=Me;;){var he=D.delegate;if(he){var fe=T(he,D);if(fe){if(fe===g)continue;return fe}}if(D.method==="next")D.sent=D._sent=D.arg;else if(D.method==="throw"){if($===m)throw $=f,D.arg;D.dispatchException(D.arg)}else D.method==="return"&&D.abrupt("return",D.arg);$=b;var K=v(j,O,D);if(K.type==="normal"){if($=D.done?f:h,K.arg===g)continue;return{value:K.arg,done:D.done}}else K.type==="throw"&&($=f,D.method="throw",D.arg=K.arg)}}}function T(j,O){var D=O.method,$=j.iterator[D];if($===o)return O.delegate=null,D==="throw"&&j.iterator.return&&(O.method="return",O.arg=o,T(j,O),O.method==="throw")||D!=="return"&&(O.method="throw",O.arg=new TypeError("The iterator does not provide a '"+D+"' method")),g;var U=v($,j.iterator,O.arg);if(U.type==="throw")return O.method="throw",O.arg=U.arg,O.delegate=null,g;var ae=U.arg;if(!ae)return O.method="throw",O.arg=new TypeError("iterator result is not an object"),O.delegate=null,g;if(ae.done)O[j.resultName]=ae.value,O.next=j.nextLoc,O.method!=="return"&&(O.method="next",O.arg=o);else return ae;return O.delegate=null,g}P(E),c(E,d,"Generator"),c(E,s,function(){return this}),c(E,"toString",function(){return"[object Generator]"});function C(j){var O={tryLoc:j[0]};1 in j&&(O.catchLoc=j[1]),2 in j&&(O.finallyLoc=j[2],O.afterLoc=j[3]),this.tryEntries.push(O)}function z(j){var O=j.completion||{};O.type="normal",delete O.arg,j.completion=O}function q(j){this.tryEntries=[{tryLoc:"root"}],j.forEach(C,this),this.reset(!0)}r.keys=function(j){var O=Object(j),D=[];for(var $ in O)D.push($);return D.reverse(),function U(){for(;D.length;){var ae=D.pop();if(ae in O)return U.value=ae,U.done=!1,U}return U.done=!0,U}};function V(j){if(j!=null){var O=j[s];if(O)return O.call(j);if(typeof j.next=="function")return j;if(!isNaN(j.length)){var D=-1,$=function U(){for(;++D=0;--$){var U=this.tryEntries[$],ae=U.completion;if(U.tryLoc==="root")return D("end");if(U.tryLoc<=this.prev){var Me=i.call(U,"catchLoc"),he=i.call(U,"finallyLoc");if(Me&&he){if(this.prev=0;--D){var $=this.tryEntries[D];if($.tryLoc<=this.prev&&i.call($,"finallyLoc")&&this.prev<$.finallyLoc){var U=$;break}}U&&(j==="break"||j==="continue")&&U.tryLoc<=O&&O<=U.finallyLoc&&(U=null);var ae=U?U.completion:{};return ae.type=j,ae.arg=O,U?(this.method="next",this.next=U.finallyLoc,g):this.complete(ae)},complete:function(j,O){if(j.type==="throw")throw j.arg;return j.type==="break"||j.type==="continue"?this.next=j.arg:j.type==="return"?(this.rval=this.arg=j.arg,this.method="return",this.next="end"):j.type==="normal"&&O&&(this.next=O),g},finish:function(j){for(var O=this.tryEntries.length-1;O>=0;--O){var D=this.tryEntries[O];if(D.finallyLoc===j)return this.complete(D.completion,D.afterLoc),z(D),g}},catch:function(j){for(var O=this.tryEntries.length-1;O>=0;--O){var D=this.tryEntries[O];if(D.tryLoc===j){var $=D.completion;if($.type==="throw"){var U=$.arg;z(D)}return U}}throw new Error("illegal catch attempt")},delegateYield:function(j,O,D){return this.delegate={iterator:V(j),resultName:O,nextLoc:D},this.method==="next"&&(this.arg=o),g}},r})(e.exports);try{regeneratorRuntime=t}catch{typeof globalThis=="object"?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}})(Za)),Za.exports}AT();var ld={},ud={},$r,dd;function se(){if(dd)return $r;dd=1;var e=function(t){return t&&t.Math===Math&&t};return $r=e(typeof globalThis=="object"&&globalThis)||e(typeof window=="object"&&window)||e(typeof self=="object"&&self)||e(typeof od=="object"&&od)||e(typeof $r=="object"&&$r)||(function(){return this})()||Function("return this")(),$r}var Ja={},Xa,cd;function X(){return cd||(cd=1,Xa=function(e){try{return!!e()}catch{return!0}}),Xa}var ei,pd;function Ae(){if(pd)return ei;pd=1;var e=X();return ei=!e(function(){return Object.defineProperty({},1,{get:function(){return 7}})[1]!==7}),ei}var ti,md;function Wr(){if(md)return ti;md=1;var e=X();return ti=!e(function(){var t=(function(){}).bind();return typeof t!="function"||t.hasOwnProperty("prototype")}),ti}var ri,vd;function ye(){if(vd)return ri;vd=1;var e=Wr(),t=Function.prototype.call;return ri=e?t.bind(t):function(){return t.apply(t,arguments)},ri}var ai={},fd;function da(){if(fd)return ai;fd=1;var e={}.propertyIsEnumerable,t=Object.getOwnPropertyDescriptor,r=t&&!e.call({1:2},1);return ai.f=r?function(i){var n=t(this,i);return!!n&&n.enumerable}:e,ai}var ii,gd;function It(){return gd||(gd=1,ii=function(e,t){return{enumerable:!(e&1),configurable:!(e&2),writable:!(e&4),value:t}}),ii}var ni,hd;function te(){if(hd)return ni;hd=1;var e=Wr(),t=Function.prototype,r=t.call,a=e&&t.bind.bind(r,r);return ni=e?a:function(i){return function(){return r.apply(i,arguments)}},ni}var oi,bd;function St(){if(bd)return oi;bd=1;var e=te(),t=e({}.toString),r=e("".slice);return oi=function(a){return r(t(a),8,-1)},oi}var si,kd;function Mr(){if(kd)return si;kd=1;var e=te(),t=X(),r=St(),a=Object,i=e("".split);return si=t(function(){return!a("z").propertyIsEnumerable(0)})?function(n){return r(n)==="String"?i(n,""):a(n)}:a,si}var li,yd;function Jt(){return yd||(yd=1,li=function(e){return e==null}),li}var ui,_d;function rt(){if(_d)return ui;_d=1;var e=Jt(),t=TypeError;return ui=function(r){if(e(r))throw new t("Can't call method on "+r);return r},ui}var di,Sd;function mt(){if(Sd)return di;Sd=1;var e=Mr(),t=rt();return di=function(r){return e(t(r))},di}var ci,wd;function Ue(){if(wd)return ci;wd=1;var e=typeof document=="object"&&document.all;return ci=typeof e>"u"&&e!==void 0?function(t){return typeof t=="function"||t===e}:function(t){return typeof t=="function"},ci}var pi,Rd;function Ie(){if(Rd)return pi;Rd=1;var e=Ue();return pi=function(t){return typeof t=="object"?t!==null:e(t)},pi}var mi,Ed;function Le(){if(Ed)return mi;Ed=1;var e=se(),t=Ue(),r=function(a){return t(a)?a:void 0};return mi=function(a,i){return arguments.length<2?r(e[a]):e[a]&&e[a][i]},mi}var vi,Ad;function At(){if(Ad)return vi;Ad=1;var e=te();return vi=e({}.isPrototypeOf),vi}var fi,Md;function Kt(){if(Md)return fi;Md=1;var e=se(),t=e.navigator,r=t&&t.userAgent;return fi=r?String(r):"",fi}var gi,Pd;function Wt(){if(Pd)return gi;Pd=1;var e=se(),t=Kt(),r=e.process,a=e.Deno,i=r&&r.versions||a&&a.version,n=i&&i.v8,o,l;return n&&(o=n.split("."),l=o[0]>0&&o[0]<4?1:+(o[0]+o[1])),!l&&t&&(o=t.match(/Edge\/(\d+)/),(!o||o[1]>=74)&&(o=t.match(/Chrome\/(\d+)/),o&&(l=+o[1]))),gi=l,gi}var hi,Td;function Pr(){if(Td)return hi;Td=1;var e=Wt(),t=X(),r=se(),a=r.String;return hi=!!Object.getOwnPropertySymbols&&!t(function(){var i=Symbol("symbol detection");return!a(i)||!(Object(i)instanceof Symbol)||!Symbol.sham&&e&&e<41}),hi}var bi,Id;function JM(){if(Id)return bi;Id=1;var e=Pr();return bi=e&&!Symbol.sham&&typeof Symbol.iterator=="symbol",bi}var ki,jd;function ur(){if(jd)return ki;jd=1;var e=Le(),t=Ue(),r=At(),a=JM(),i=Object;return ki=a?function(n){return typeof n=="symbol"}:function(n){var o=e("Symbol");return t(o)&&r(o.prototype,i(n))},ki}var yi,Cd;function dr(){if(Cd)return yi;Cd=1;var e=String;return yi=function(t){try{return e(t)}catch{return"Object"}},yi}var _i,Od;function Fe(){if(Od)return _i;Od=1;var e=Ue(),t=dr(),r=TypeError;return _i=function(a){if(e(a))return a;throw new r(t(a)+" is not a function")},_i}var Si,zd;function ft(){if(zd)return Si;zd=1;var e=Fe(),t=Jt();return Si=function(r,a){var i=r[a];return t(i)?void 0:e(i)},Si}var wi,Dd;function XM(){if(Dd)return wi;Dd=1;var e=ye(),t=Ue(),r=Ie(),a=TypeError;return wi=function(i,n){var o,l;if(n==="string"&&t(o=i.toString)&&!r(l=e(o,i))||t(o=i.valueOf)&&!r(l=e(o,i))||n!=="string"&&t(o=i.toString)&&!r(l=e(o,i)))return l;throw new a("Can't convert object to primitive value")},wi}var Ri={exports:{}},Ei,xd;function Ye(){return xd||(xd=1,Ei=!1),Ei}var Ai,qd;function hu(){if(qd)return Ai;qd=1;var e=se(),t=Object.defineProperty;return Ai=function(r,a){try{t(e,r,{value:a,configurable:!0,writable:!0})}catch{e[r]=a}return a},Ai}var Nd;function ca(){if(Nd)return Ri.exports;Nd=1;var e=Ye(),t=se(),r=hu(),a="__core-js_shared__",i=Ri.exports=t[a]||r(a,{});return(i.versions||(i.versions=[])).push({version:"3.46.0",mode:e?"pure":"global",copyright:"© 2014-2025 Denis Pushkarev (zloirock.ru), 2025 CoreJS Company (core-js.io)",license:"https://github.com/zloirock/core-js/blob/v3.46.0/LICENSE",source:"https://github.com/zloirock/core-js"}),Ri.exports}var Mi,Ld;function Tr(){if(Ld)return Mi;Ld=1;var e=ca();return Mi=function(t,r){return e[t]||(e[t]=r||{})},Mi}var Pi,Fd;function Ge(){if(Fd)return Pi;Fd=1;var e=rt(),t=Object;return Pi=function(r){return t(e(r))},Pi}var Ti,Vd;function Ve(){if(Vd)return Ti;Vd=1;var e=te(),t=Ge(),r=e({}.hasOwnProperty);return Ti=Object.hasOwn||function(i,n){return r(t(i),n)},Ti}var Ii,Bd;function Ir(){if(Bd)return Ii;Bd=1;var e=te(),t=0,r=Math.random(),a=e(1.1.toString);return Ii=function(i){return"Symbol("+(i===void 0?"":i)+")_"+a(++t+r,36)},Ii}var ji,Ud;function je(){if(Ud)return ji;Ud=1;var e=se(),t=Tr(),r=Ve(),a=Ir(),i=Pr(),n=JM(),o=e.Symbol,l=t("wks"),s=n?o.for||o:o&&o.withoutSetter||a;return ji=function(u){return r(l,u)||(l[u]=i&&r(o,u)?o[u]:s("Symbol."+u)),l[u]},ji}var Ci,$d;function pa(){if($d)return Ci;$d=1;var e=ye(),t=Ie(),r=ur(),a=ft(),i=XM(),n=je(),o=TypeError,l=n("toPrimitive");return Ci=function(s,u){if(!t(s)||r(s))return s;var d=a(s,l),c;if(d){if(u===void 0&&(u="default"),c=e(d,s,u),!t(c)||r(c))return c;throw new o("Can't convert object to primitive value")}return u===void 0&&(u="number"),i(s,u)},Ci}var Oi,Hd;function ir(){if(Hd)return Oi;Hd=1;var e=pa(),t=ur();return Oi=function(r){var a=e(r,"string");return t(a)?a:a+""},Oi}var zi,Kd;function ma(){if(Kd)return zi;Kd=1;var e=se(),t=Ie(),r=e.document,a=t(r)&&t(r.createElement);return zi=function(i){return a?r.createElement(i):{}},zi}var Di,Wd;function eP(){if(Wd)return Di;Wd=1;var e=Ae(),t=X(),r=ma();return Di=!e&&!t(function(){return Object.defineProperty(r("div"),"a",{get:function(){return 7}}).a!==7}),Di}var Gd;function gt(){if(Gd)return Ja;Gd=1;var e=Ae(),t=ye(),r=da(),a=It(),i=mt(),n=ir(),o=Ve(),l=eP(),s=Object.getOwnPropertyDescriptor;return Ja.f=e?s:function(d,c){if(d=i(d),c=n(c),l)try{return s(d,c)}catch{}if(o(d,c))return a(!t(r.f,d,c),d[c])},Ja}var xi={},qi,Yd;function tP(){if(Yd)return qi;Yd=1;var e=Ae(),t=X();return qi=e&&t(function(){return Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype!==42}),qi}var Ni,Qd;function Re(){if(Qd)return Ni;Qd=1;var e=Ie(),t=String,r=TypeError;return Ni=function(a){if(e(a))return a;throw new r(t(a)+" is not an object")},Ni}var Zd;function et(){if(Zd)return xi;Zd=1;var e=Ae(),t=eP(),r=tP(),a=Re(),i=ir(),n=TypeError,o=Object.defineProperty,l=Object.getOwnPropertyDescriptor,s="enumerable",u="configurable",d="writable";return xi.f=e?r?function(p,v,m){if(a(p),v=i(v),a(m),typeof p=="function"&&v==="prototype"&&"value"in m&&d in m&&!m[d]){var h=l(p,v);h&&h[d]&&(p[v]=m.value,m={configurable:u in m?m[u]:h[u],enumerable:s in m?m[s]:h[s],writable:!1})}return o(p,v,m)}:o:function(p,v,m){if(a(p),v=i(v),a(m),t)try{return o(p,v,m)}catch{}if("get"in m||"set"in m)throw new n("Accessors not supported");return"value"in m&&(p[v]=m.value),p},xi}var Li,Jd;function ht(){if(Jd)return Li;Jd=1;var e=Ae(),t=et(),r=It();return Li=e?function(a,i,n){return t.f(a,i,r(1,n))}:function(a,i,n){return a[i]=n,a},Li}var Fi={exports:{}},Vi,Xd;function jr(){if(Xd)return Vi;Xd=1;var e=Ae(),t=Ve(),r=Function.prototype,a=e&&Object.getOwnPropertyDescriptor,i=t(r,"name"),n=i&&(function(){}).name==="something",o=i&&(!e||e&&a(r,"name").configurable);return Vi={EXISTS:i,PROPER:n,CONFIGURABLE:o},Vi}var Bi,ec;function bu(){if(ec)return Bi;ec=1;var e=te(),t=Ue(),r=ca(),a=e(Function.toString);return t(r.inspectSource)||(r.inspectSource=function(i){return a(i)}),Bi=r.inspectSource,Bi}var Ui,tc;function rP(){if(tc)return Ui;tc=1;var e=se(),t=Ue(),r=e.WeakMap;return Ui=t(r)&&/native code/.test(String(r)),Ui}var $i,rc;function va(){if(rc)return $i;rc=1;var e=Tr(),t=Ir(),r=e("keys");return $i=function(a){return r[a]||(r[a]=t(a))},$i}var Hi,ac;function Gr(){return ac||(ac=1,Hi={}),Hi}var Ki,ic;function at(){if(ic)return Ki;ic=1;var e=rP(),t=se(),r=Ie(),a=ht(),i=Ve(),n=ca(),o=va(),l=Gr(),s="Object already initialized",u=t.TypeError,d=t.WeakMap,c,p,v,m=function(g){return v(g)?p(g):c(g,{})},h=function(g){return function(k){var y;if(!r(k)||(y=p(k)).type!==g)throw new u("Incompatible receiver, "+g+" required");return y}};if(e||n.state){var b=n.state||(n.state=new d);b.get=b.get,b.has=b.has,b.set=b.set,c=function(g,k){if(b.has(g))throw new u(s);return k.facade=g,b.set(g,k),k},p=function(g){return b.get(g)||{}},v=function(g){return b.has(g)}}else{var f=o("state");l[f]=!0,c=function(g,k){if(i(g,f))throw new u(s);return k.facade=g,a(g,f,k),k},p=function(g){return i(g,f)?g[f]:{}},v=function(g){return i(g,f)}}return Ki={set:c,get:p,has:v,enforce:m,getterFor:h},Ki}var nc;function ku(){if(nc)return Fi.exports;nc=1;var e=te(),t=X(),r=Ue(),a=Ve(),i=Ae(),n=jr().CONFIGURABLE,o=bu(),l=at(),s=l.enforce,u=l.get,d=String,c=Object.defineProperty,p=e("".slice),v=e("".replace),m=e([].join),h=i&&!t(function(){return c(function(){},"length",{value:8}).length!==8}),b=String(String).split("String"),f=Fi.exports=function(g,k,y){p(d(k),0,7)==="Symbol("&&(k="["+v(d(k),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),y&&y.getter&&(k="get "+k),y&&y.setter&&(k="set "+k),(!a(g,"name")||n&&g.name!==k)&&(i?c(g,"name",{value:k,configurable:!0}):g.name=k),h&&y&&a(y,"arity")&&g.length!==y.arity&&c(g,"length",{value:y.arity});try{y&&a(y,"constructor")&&y.constructor?i&&c(g,"prototype",{writable:!1}):g.prototype&&(g.prototype=void 0)}catch{}var _=s(g);return a(_,"source")||(_.source=m(b,typeof k=="string"?k:"")),g};return Function.prototype.toString=f(function(){return r(this)&&u(this).source||o(this)},"toString"),Fi.exports}var Wi,oc;function Qe(){if(oc)return Wi;oc=1;var e=Ue(),t=et(),r=ku(),a=hu();return Wi=function(i,n,o,l){l||(l={});var s=l.enumerable,u=l.name!==void 0?l.name:n;if(e(o)&&r(o,u,l),l.global)s?i[n]=o:a(n,o);else{try{l.unsafe?i[n]&&(s=!0):delete i[n]}catch{}s?i[n]=o:t.f(i,n,{value:o,enumerable:!1,configurable:!l.nonConfigurable,writable:!l.nonWritable})}return i},Wi}var Gi={},Yi,sc;function aP(){if(sc)return Yi;sc=1;var e=Math.ceil,t=Math.floor;return Yi=Math.trunc||function(a){var i=+a;return(i>0?t:e)(i)},Yi}var Qi,lc;function it(){if(lc)return Qi;lc=1;var e=aP();return Qi=function(t){var r=+t;return r!==r||r===0?0:e(r)},Qi}var Zi,uc;function Xt(){if(uc)return Zi;uc=1;var e=it(),t=Math.max,r=Math.min;return Zi=function(a,i){var n=e(a);return n<0?t(n+i,0):r(n,i)},Zi}var Ji,dc;function jt(){if(dc)return Ji;dc=1;var e=it(),t=Math.min;return Ji=function(r){var a=e(r);return a>0?t(a,9007199254740991):0},Ji}var Xi,cc;function Ze(){if(cc)return Xi;cc=1;var e=jt();return Xi=function(t){return e(t.length)},Xi}var en,pc;function Yr(){if(pc)return en;pc=1;var e=mt(),t=Xt(),r=Ze(),a=function(i){return function(n,o,l){var s=e(n),u=r(s);if(u===0)return!i&&-1;var d=t(l,u),c;if(i&&o!==o){for(;u>d;)if(c=s[d++],c!==c)return!0}else for(;u>d;d++)if((i||d in s)&&s[d]===o)return i||d||0;return!i&&-1}};return en={includes:a(!0),indexOf:a(!1)},en}var tn,mc;function iP(){if(mc)return tn;mc=1;var e=te(),t=Ve(),r=mt(),a=Yr().indexOf,i=Gr(),n=e([].push);return tn=function(o,l){var s=r(o),u=0,d=[],c;for(c in s)!t(i,c)&&t(s,c)&&n(d,c);for(;l.length>u;)t(s,c=l[u++])&&(~a(d,c)||n(d,c));return d},tn}var rn,vc;function yu(){return vc||(vc=1,rn=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]),rn}var fc;function cr(){if(fc)return Gi;fc=1;var e=iP(),t=yu(),r=t.concat("length","prototype");return Gi.f=Object.getOwnPropertyNames||function(i){return e(i,r)},Gi}var an={},gc;function fa(){return gc||(gc=1,an.f=Object.getOwnPropertySymbols),an}var nn,hc;function _u(){if(hc)return nn;hc=1;var e=Le(),t=te(),r=cr(),a=fa(),i=Re(),n=t([].concat);return nn=e("Reflect","ownKeys")||function(l){var s=r.f(i(l)),u=a.f;return u?n(s,u(l)):s},nn}var on,bc;function Cr(){if(bc)return on;bc=1;var e=Ve(),t=_u(),r=gt(),a=et();return on=function(i,n,o){for(var l=t(n),s=a.f,u=r.f,d=0;dp;)r.f(l,v=d[p++],u[v]);return l},pn}var vn,Ac;function nP(){if(Ac)return vn;Ac=1;var e=Le();return vn=e("document","documentElement"),vn}var fn,Mc;function bt(){if(Mc)return fn;Mc=1;var e=Re(),t=wu(),r=yu(),a=Gr(),i=nP(),n=ma(),o=va(),l=">",s="<",u="prototype",d="script",c=o("IE_PROTO"),p=function(){},v=function(g){return s+d+l+g+s+"/"+d+l},m=function(g){g.write(v("")),g.close();var k=g.parentWindow.Object;return g=null,k},h=function(){var g=n("iframe"),k="java"+d+":",y;return g.style.display="none",i.appendChild(g),g.src=String(k),y=g.contentWindow.document,y.open(),y.write(v("document.F=Object")),y.close(),y.F},b,f=function(){try{b=new ActiveXObject("htmlfile")}catch{}f=typeof document<"u"?document.domain&&b?m(b):h():m(b);for(var g=r.length;g--;)delete f[u][r[g]];return f()};return a[c]=!0,fn=Object.create||function(k,y){var _;return k!==null?(p[u]=e(k),_=new p,p[u]=null,_[c]=k):_=f(),y===void 0?_:t.f(_,y)},fn}var gn={},hn,Pc;function Ft(){if(Pc)return hn;Pc=1;var e=te();return hn=e([].slice),hn}var Tc;function Ru(){if(Tc)return gn;Tc=1;var e=St(),t=mt(),r=cr().f,a=Ft(),i=typeof window=="object"&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],n=function(o){try{return r(o)}catch{return a(i)}};return gn.f=function(l){return i&&e(l)==="Window"?n(l):r(t(l))},gn}var bn,Ic;function ot(){if(Ic)return bn;Ic=1;var e=ku(),t=et();return bn=function(r,a,i){return i.get&&e(i.get,a,{getter:!0}),i.set&&e(i.set,a,{setter:!0}),t.f(r,a,i)},bn}var kn={},jc;function oP(){if(jc)return kn;jc=1;var e=je();return kn.f=e,kn}var yn,Cc;function ga(){if(Cc)return yn;Cc=1;var e=se();return yn=e,yn}var _n,Oc;function wt(){if(Oc)return _n;Oc=1;var e=ga(),t=Ve(),r=oP(),a=et().f;return _n=function(i){var n=e.Symbol||(e.Symbol={});t(n,i)||a(n,i,{value:r.f(i)})},_n}var Sn,zc;function sP(){if(zc)return Sn;zc=1;var e=ye(),t=Le(),r=je(),a=Qe();return Sn=function(){var i=t("Symbol"),n=i&&i.prototype,o=n&&n.valueOf,l=r("toPrimitive");n&&!n[l]&&a(n,l,function(s){return e(o,this)},{arity:1})},Sn}var wn,Dc;function Pt(){if(Dc)return wn;Dc=1;var e=et().f,t=Ve(),r=je(),a=r("toStringTag");return wn=function(i,n,o){i&&!o&&(i=i.prototype),i&&!t(i,a)&&e(i,a,{configurable:!0,value:n})},wn}var Rn,xc;function pr(){if(xc)return Rn;xc=1;var e=St(),t=te();return Rn=function(r){if(e(r)==="Function")return t(r)},Rn}var En,qc;function Ot(){if(qc)return En;qc=1;var e=pr(),t=Fe(),r=Wr(),a=e(e.bind);return En=function(i,n){return t(i),n===void 0?i:r?a(i,n):function(){return i.apply(n,arguments)}},En}var An,Nc;function nr(){if(Nc)return An;Nc=1;var e=St();return An=Array.isArray||function(r){return e(r)==="Array"},An}var Mn,Lc;function mr(){if(Lc)return Mn;Lc=1;var e=te(),t=X(),r=Ue(),a=Ct(),i=Le(),n=bu(),o=function(){},l=i("Reflect","construct"),s=/^\s*(?:class|function)\b/,u=e(s.exec),d=!s.test(o),c=function(m){if(!r(m))return!1;try{return l(o,[],m),!0}catch{return!1}},p=function(m){if(!r(m))return!1;switch(a(m)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return d||!!u(s,n(m))}catch{return!0}};return p.sham=!0,Mn=!l||t(function(){var v;return c(c.call)||!c(Object)||!c(function(){v=!0})||v})?p:c,Mn}var Pn,Fc;function MT(){if(Fc)return Pn;Fc=1;var e=nr(),t=mr(),r=Ie(),a=je(),i=a("species"),n=Array;return Pn=function(o){var l;return e(o)&&(l=o.constructor,t(l)&&(l===n||e(l.prototype))?l=void 0:r(l)&&(l=l[i],l===null&&(l=void 0))),l===void 0?n:l},Pn}var Tn,Vc;function Jr(){if(Vc)return Tn;Vc=1;var e=MT();return Tn=function(t,r){return new(e(t))(r===0?0:r)},Tn}var In,Bc;function kt(){if(Bc)return In;Bc=1;var e=Ot(),t=te(),r=Mr(),a=Ge(),i=Ze(),n=Jr(),o=t([].push),l=function(s){var u=s===1,d=s===2,c=s===3,p=s===4,v=s===6,m=s===7,h=s===5||v;return function(b,f,g,k){for(var y=a(b),_=r(y),S=i(_),R=e(f,g),w=0,E=k||n,P=u?E(b,S):d||m?E(b,0):void 0,A,M;S>w;w++)if((h||w in _)&&(A=_[w],M=R(A,w,y),s))if(u)P[w]=M;else if(M)switch(s){case 3:return!0;case 5:return A;case 6:return w;case 2:o(P,A)}else switch(s){case 4:return!1;case 7:o(P,A)}return v?-1:c||p?p:P}};return In={forEach:l(0),map:l(1),filter:l(2),some:l(3),every:l(4),find:l(5),findIndex:l(6),filterReject:l(7)},In}var Uc;function PT(){if(Uc)return ud;Uc=1;var e=I(),t=se(),r=ye(),a=te(),i=Ye(),n=Ae(),o=Pr(),l=X(),s=Ve(),u=At(),d=Re(),c=mt(),p=ir(),v=xe(),m=It(),h=bt(),b=Zr(),f=cr(),g=Ru(),k=fa(),y=gt(),_=et(),S=wu(),R=da(),w=Qe(),E=ot(),P=Tr(),A=va(),M=Gr(),T=Ir(),C=je(),z=oP(),q=wt(),V=sP(),F=Pt(),j=at(),O=kt().forEach,D=A("hidden"),$="Symbol",U="prototype",ae=j.set,Me=j.getterFor($),he=Object[U],fe=t.Symbol,K=fe&&fe[U],le=t.RangeError,ge=t.TypeError,_e=t.QObject,ke=y.f,Pe=_.f,He=g.f,We=R.f,qe=a([].push),Se=P("symbols"),Ne=P("op-symbols"),ze=P("wks"),Ce=!_e||!_e[U]||!_e[U].findChild,J=function(G,Q,Z){var ne=ke(he,Q);ne&&delete he[Q],Pe(G,Q,Z),ne&&G!==he&&Pe(he,Q,ne)},oe=n&&l(function(){return h(Pe({},"a",{get:function(){return Pe(this,"a",{value:7}).a}})).a!==7})?J:Pe,Ee=function(G,Q){var Z=Se[G]=h(K);return ae(Z,{type:$,tag:G,description:Q}),n||(Z.description=Q),Z},ie=function(Q,Z,ne){Q===he&&ie(Ne,Z,ne),d(Q);var H=p(Z);return d(ne),s(Se,H)?(ne.enumerable?(s(Q,D)&&Q[D][H]&&(Q[D][H]=!1),ne=h(ne,{enumerable:m(0,!1)})):(s(Q,D)||Pe(Q,D,m(1,h(null))),Q[D][H]=!0),oe(Q,H,ne)):Pe(Q,H,ne)},me=function(Q,Z){d(Q);var ne=c(Z),H=b(ne).concat(L(ne));return O(H,function(we){(!n||r(ce,ne,we))&&ie(Q,we,ne[we])}),Q},ve=function(Q,Z){return Z===void 0?h(Q):me(h(Q),Z)},ce=function(Q){var Z=p(Q),ne=r(We,this,Z);return this===he&&s(Se,Z)&&!s(Ne,Z)?!1:ne||!s(this,Z)||!s(Se,Z)||s(this,D)&&this[D][Z]?ne:!0},De=function(Q,Z){var ne=c(Q),H=p(Z);if(!(ne===he&&s(Se,H)&&!s(Ne,H))){var we=ke(ne,H);return we&&s(Se,H)&&!(s(ne,D)&&ne[D][H])&&(we.enumerable=!0),we}},Xe=function(Q){var Z=He(c(Q)),ne=[];return O(Z,function(H){!s(Se,H)&&!s(M,H)&&qe(ne,H)}),ne},L=function(G){var Q=G===he,Z=He(Q?Ne:c(G)),ne=[];return O(Z,function(H){s(Se,H)&&(!Q||s(he,H))&&qe(ne,Se[H])}),ne};return o||(fe=function(){if(u(K,this))throw new ge("Symbol is not a constructor");var Q=!arguments.length||arguments[0]===void 0?void 0:v(arguments[0]),Z=T(Q),ne=function(H){var we=this===void 0?t:this;we===he&&r(ne,Ne,H),s(we,D)&&s(we[D],Z)&&(we[D][Z]=!1);var Ke=m(1,H);try{oe(we,Z,Ke)}catch(W){if(!(W instanceof le))throw W;J(we,Z,Ke)}};return n&&Ce&&oe(he,Z,{configurable:!0,set:ne}),Ee(Z,Q)},K=fe[U],w(K,"toString",function(){return Me(this).tag}),w(fe,"withoutSetter",function(G){return Ee(T(G),G)}),R.f=ce,_.f=ie,S.f=me,y.f=De,f.f=g.f=Xe,k.f=L,z.f=function(G){return Ee(C(G),G)},n&&(E(K,"description",{configurable:!0,get:function(){return Me(this).description}}),i||w(he,"propertyIsEnumerable",ce,{unsafe:!0}))),e({global:!0,constructor:!0,wrap:!0,forced:!o,sham:!o},{Symbol:fe}),O(b(ze),function(G){q(G)}),e({target:$,stat:!0,forced:!o},{useSetter:function(){Ce=!0},useSimple:function(){Ce=!1}}),e({target:"Object",stat:!0,forced:!o,sham:!n},{create:ve,defineProperty:ie,defineProperties:me,getOwnPropertyDescriptor:De}),e({target:"Object",stat:!0,forced:!o},{getOwnPropertyNames:Xe}),V(),F(fe,$),M[D]=!0,ud}var $c={},jn,Hc;function lP(){if(Hc)return jn;Hc=1;var e=Pr();return jn=e&&!!Symbol.for&&!!Symbol.keyFor,jn}var Kc;function TT(){if(Kc)return $c;Kc=1;var e=I(),t=Le(),r=Ve(),a=xe(),i=Tr(),n=lP(),o=i("string-to-symbol-registry"),l=i("symbol-to-string-registry");return e({target:"Symbol",stat:!0,forced:!n},{for:function(s){var u=a(s);if(r(o,u))return o[u];var d=t("Symbol")(u);return o[u]=d,l[d]=u,d}}),$c}var Wc={},Gc;function IT(){if(Gc)return Wc;Gc=1;var e=I(),t=Ve(),r=ur(),a=dr(),i=Tr(),n=lP(),o=i("symbol-to-string-registry");return e({target:"Symbol",stat:!0,forced:!n},{keyFor:function(s){if(!r(s))throw new TypeError(a(s)+" is not a symbol");if(t(o,s))return o[s]}}),Wc}var Yc={},Cn,Qc;function zt(){if(Qc)return Cn;Qc=1;var e=Wr(),t=Function.prototype,r=t.apply,a=t.call;return Cn=typeof Reflect=="object"&&Reflect.apply||(e?a.bind(r):function(){return a.apply(r,arguments)}),Cn}var On,Zc;function jT(){if(Zc)return On;Zc=1;var e=te(),t=nr(),r=Ue(),a=St(),i=xe(),n=e([].push);return On=function(o){if(r(o))return o;if(t(o)){for(var l=o.length,s=[],u=0;ug&&u(M,arguments[g]),M});if(w.prototype=S,y!=="Error"?i?i(w,R):n(w,R,{name:!0}):c&&f in _&&(o(w,_,f),o(w,_,"prepareStackTrace")),n(w,_),!p)try{S.name!==y&&r(S,"name",y),S.constructor=w}catch{}return w}},Hn}var Wp;function QT(){if(Wp)return zp;Wp=1;var e=I(),t=se(),r=zt(),a=fP(),i="WebAssembly",n=t[i],o=new Error("e",{cause:7}).cause!==7,l=function(u,d){var c={};c[u]=a(u,d,o),e({global:!0,constructor:!0,arity:1,forced:o},c)},s=function(u,d){if(n&&n[u]){var c={};c[u]=a(i+"."+u,d,o),e({target:i,stat:!0,constructor:!0,arity:1,forced:o},c)}};return l("Error",function(u){return function(c){return r(u,this,arguments)}}),l("EvalError",function(u){return function(c){return r(u,this,arguments)}}),l("RangeError",function(u){return function(c){return r(u,this,arguments)}}),l("ReferenceError",function(u){return function(c){return r(u,this,arguments)}}),l("SyntaxError",function(u){return function(c){return r(u,this,arguments)}}),l("TypeError",function(u){return function(c){return r(u,this,arguments)}}),l("URIError",function(u){return function(c){return r(u,this,arguments)}}),s("CompileError",function(u){return function(c){return r(u,this,arguments)}}),s("LinkError",function(u){return function(c){return r(u,this,arguments)}}),s("RuntimeError",function(u){return function(c){return r(u,this,arguments)}}),zp}var Gp={},Yp;function ZT(){if(Yp)return Gp;Yp=1;var e=I(),t=Le(),r=Ie(),a=Ct(),i=X(),n="Error",o="DOMException",l=Object.setPrototypeOf||{}.__proto__,s=t(o),u=Error,d=u.isError,c=!d||!l||i(function(){return s&&!d(new s(o))||!d(new u(n,{cause:function(){}}))||d(t("Object","create")(u.prototype))});return e({target:"Error",stat:!0,sham:!0,forced:c},{isError:function(v){if(!r(v))return!1;var m=a(v);return m===n||m===o}}),Gp}var Qp={},Kn,Zp;function gP(){if(Zp)return Kn;Zp=1;var e=Ae(),t=X(),r=Re(),a=Or(),i=Error.prototype.toString,n=t(function(){if(e){var o=Object.create(Object.defineProperty({},"name",{get:function(){return this===o}}));if(i.call(o)!=="true")return!0}return i.call({message:1,name:2})!=="2: 1"||i.call({})!=="Error"});return Kn=n?function(){var l=r(this),s=a(l.name,"Error"),u=a(l.message);return s?u?s+": "+u:s:u}:i,Kn}var Jp;function JT(){if(Jp)return Qp;Jp=1;var e=Qe(),t=gP(),r=Error.prototype;return r.toString!==t&&e(r,"toString",t),Qp}var Xp={},em={},Wn,tm;function Mu(){if(tm)return Wn;tm=1;var e=X();return Wn=!e(function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}),Wn}var Gn,rm;function Mt(){if(rm)return Gn;rm=1;var e=Ve(),t=Ue(),r=Ge(),a=va(),i=Mu(),n=a("IE_PROTO"),o=Object,l=o.prototype;return Gn=i?o.getPrototypeOf:function(s){var u=r(s);if(e(u,n))return u[n];var d=u.constructor;return t(d)&&u instanceof d?d.prototype:u instanceof o?l:null},Gn}var Yn,am;function Xr(){return am||(am=1,Yn={}),Yn}var Qn,im;function Pu(){if(im)return Qn;im=1;var e=je(),t=Xr(),r=e("iterator"),a=Array.prototype;return Qn=function(i){return i!==void 0&&(t.Array===i||a[r]===i)},Qn}var Zn,nm;function fr(){if(nm)return Zn;nm=1;var e=Ct(),t=ft(),r=Jt(),a=Xr(),i=je(),n=i("iterator");return Zn=function(o){if(!r(o))return t(o,n)||t(o,"@@iterator")||a[e(o)]},Zn}var Jn,om;function zr(){if(om)return Jn;om=1;var e=ye(),t=Fe(),r=Re(),a=dr(),i=fr(),n=TypeError;return Jn=function(o,l){var s=arguments.length<2?i(o):l;if(t(s))return r(e(s,o));throw new n(a(o)+" is not iterable")},Jn}var Xn,sm;function yt(){if(sm)return Xn;sm=1;var e=ye(),t=Re(),r=ft();return Xn=function(a,i,n){var o,l;t(a);try{if(o=r(a,"return"),!o){if(i==="throw")throw n;return n}o=e(o,a)}catch(s){l=!0,o=s}if(i==="throw")throw n;if(l)throw o;return t(o),n},Xn}var eo,lm;function ct(){if(lm)return eo;lm=1;var e=Ot(),t=ye(),r=Re(),a=dr(),i=Pu(),n=Ze(),o=At(),l=zr(),s=fr(),u=yt(),d=TypeError,c=function(v,m){this.stopped=v,this.result=m},p=c.prototype;return eo=function(v,m,h){var b=h&&h.that,f=!!(h&&h.AS_ENTRIES),g=!!(h&&h.IS_RECORD),k=!!(h&&h.IS_ITERATOR),y=!!(h&&h.INTERRUPTED),_=e(m,b),S,R,w,E,P,A,M,T=function(z){return S&&u(S,"normal"),new c(!0,z)},C=function(z){return f?(r(z),y?_(z[0],z[1],T):_(z[0],z[1])):y?_(z,T):_(z)};if(g)S=v.iterator;else if(k)S=v;else{if(R=s(v),!R)throw new d(a(v)+" is not iterable");if(i(R)){for(w=0,E=n(v);E>w;w++)if(P=C(v[w]),P&&o(p,P))return P;return new c(!1)}S=l(v,R)}for(A=g?v.next:S.next;!(M=t(A,S)).done;){try{P=C(M.value)}catch(z){u(S,"throw",z)}if(typeof P=="object"&&P&&o(p,P))return P}return new c(!1)},eo}var um;function XT(){if(um)return em;um=1;var e=I(),t=At(),r=Mt(),a=Bt(),i=Cr(),n=bt(),o=ht(),l=It(),s=mP(),u=Au(),d=ct(),c=Or(),p=je(),v=p("toStringTag"),m=Error,h=[].push,b=function(k,y){var _=t(f,this),S;a?S=a(new m,_?r(this):f):(S=_?this:n(f),o(S,v,"Error")),y!==void 0&&o(S,"message",c(y)),u(S,b,S.stack,1),arguments.length>2&&s(S,arguments[2]);var R=[];return d(k,h,{that:R}),o(S,"errors",R),S};a?a(b,m):i(b,m,{name:!0});var f=b.prototype=n(m.prototype,{constructor:l(1,b),message:l(1,""),name:l(1,"AggregateError")});return e({global:!0,constructor:!0,arity:2},{AggregateError:b}),em}var dm;function eI(){return dm||(dm=1,XT()),Xp}var cm={},pm;function tI(){if(pm)return cm;pm=1;var e=I(),t=Le(),r=zt(),a=X(),i=fP(),n="AggregateError",o=t(n),l=!a(function(){return o([1]).errors[0]!==1})&&a(function(){return o([1],n,{cause:7}).cause!==7});return e({global:!0,constructor:!0,arity:2,forced:l},{AggregateError:i(n,function(s){return function(d,c){return r(s,this,arguments)}},l,!0)}),cm}var mm={},vm;function rI(){if(vm)return mm;vm=1;var e=I(),t=se(),r=At(),a=Mt(),i=Bt(),n=Cr(),o=bt(),l=ht(),s=It(),u=Au(),d=Or(),c=je(),p=X(),v=Ye(),m=t.SuppressedError,h=c("toStringTag"),b=Error,f=!!m&&m.length!==3,g=!!m&&p(function(){return new m(1,2,3,{cause:4}).cause===4}),k=f||g,y=function(R,w,E){var P=r(_,this),A;return i?A=k&&(!P||a(this)===_)?new m:i(new b,P?a(this):_):(A=P?this:o(_),l(A,h,"Error")),E!==void 0&&l(A,"message",d(E)),u(A,y,A.stack,1),l(A,"error",R),l(A,"suppressed",w),A};i?i(y,b):n(y,b,{name:!0});var _=y.prototype=k?m.prototype:o(b.prototype,{constructor:s(1,y),message:s(1,""),name:s(1,"SuppressedError")});return k&&!v&&(_.constructor=y),e({global:!0,constructor:!0,arity:3,forced:k},{SuppressedError:y}),mm}var fm={},to,gm;function Tt(){if(gm)return to;gm=1;var e=je(),t=bt(),r=et().f,a=e("unscopables"),i=Array.prototype;return i[a]===void 0&&r(i,a,{configurable:!0,value:t(null)}),to=function(n){i[a][n]=!0},to}var hm;function aI(){if(hm)return fm;hm=1;var e=I(),t=Ge(),r=Ze(),a=it(),i=Tt();return e({target:"Array",proto:!0},{at:function(o){var l=t(this),s=r(l),u=a(o),d=u>=0?u:s+u;return d<0||d>=s?void 0:l[d]}}),i("at"),fm}var bm={},ro,km;function gr(){if(km)return ro;km=1;var e=TypeError,t=9007199254740991;return ro=function(r){if(r>t)throw e("Maximum allowed index exceeded");return r},ro}var ao,ym;function Gt(){if(ym)return ao;ym=1;var e=Ae(),t=et(),r=It();return ao=function(a,i,n){e?t.f(a,i,r(0,n)):a[i]=n},ao}var io,_m;function ea(){if(_m)return io;_m=1;var e=X(),t=je(),r=Wt(),a=t("species");return io=function(i){return r>=51||!e(function(){var n=[],o=n.constructor={};return o[a]=function(){return{foo:1}},n[i](Boolean).foo!==1})},io}var Sm;function iI(){if(Sm)return bm;Sm=1;var e=I(),t=X(),r=nr(),a=Ie(),i=Ge(),n=Ze(),o=gr(),l=Gt(),s=Jr(),u=ea(),d=je(),c=Wt(),p=d("isConcatSpreadable"),v=c>=51||!t(function(){var b=[];return b[p]=!1,b.concat()[0]!==b}),m=function(b){if(!a(b))return!1;var f=b[p];return f!==void 0?!!f:r(b)},h=!v||!u("concat");return e({target:"Array",proto:!0,arity:1,forced:h},{concat:function(f){var g=i(this),k=s(g,0),y=0,_,S,R,w,E;for(_=-1,R=arguments.length;_2?arguments[2]:void 0,v=i((p===void 0?u:t(p,u))-c,u-d),m=1;for(c0;)c in s?s[d]=s[c]:a(s,d),d+=m,c+=m;return s},oo}var Am;function nI(){if(Am)return wm;Am=1;var e=I(),t=hP(),r=Tt();return e({target:"Array",proto:!0},{copyWithin:t}),r("copyWithin"),wm}var Mm={},so,Pm;function er(){if(Pm)return so;Pm=1;var e=X();return so=function(t,r){var a=[][t];return!!a&&e(function(){a.call(null,r||function(){return 1},1)})},so}var Tm;function oI(){if(Tm)return Mm;Tm=1;var e=I(),t=kt().every,r=er(),a=r("every");return e({target:"Array",proto:!0,forced:!a},{every:function(n){return t(this,n,arguments.length>1?arguments[1]:void 0)}}),Mm}var Im={},lo,jm;function Tu(){if(jm)return lo;jm=1;var e=Ge(),t=Xt(),r=Ze();return lo=function(i){for(var n=e(this),o=r(n),l=arguments.length,s=t(l>1?arguments[1]:void 0,o),u=l>2?arguments[2]:void 0,d=u===void 0?o:t(u,o);d>s;)n[s++]=i;return n},lo}var Cm;function sI(){if(Cm)return Im;Cm=1;var e=I(),t=Tu(),r=Tt();return e({target:"Array",proto:!0},{fill:t}),r("fill"),Im}var Om={},zm;function lI(){if(zm)return Om;zm=1;var e=I(),t=kt().filter,r=ea(),a=r("filter");return e({target:"Array",proto:!0,forced:!a},{filter:function(n){return t(this,n,arguments.length>1?arguments[1]:void 0)}}),Om}var Dm={},xm;function uI(){if(xm)return Dm;xm=1;var e=I(),t=kt().find,r=Tt(),a="find",i=!0;return a in[]&&Array(1)[a](function(){i=!1}),e({target:"Array",proto:!0,forced:i},{find:function(o){return t(this,o,arguments.length>1?arguments[1]:void 0)}}),r(a),Dm}var qm={},Nm;function dI(){if(Nm)return qm;Nm=1;var e=I(),t=kt().findIndex,r=Tt(),a="findIndex",i=!0;return a in[]&&Array(1)[a](function(){i=!1}),e({target:"Array",proto:!0,forced:i},{findIndex:function(o){return t(this,o,arguments.length>1?arguments[1]:void 0)}}),r(a),qm}var Lm={},uo,Fm;function ka(){if(Fm)return uo;Fm=1;var e=Ot(),t=Mr(),r=Ge(),a=Ze(),i=function(n){var o=n===1;return function(l,s,u){for(var d=r(l),c=t(d),p=a(c),v=e(s,u),m,h;p-- >0;)if(m=c[p],h=v(m,p,d),h)switch(n){case 0:return m;case 1:return p}return o?-1:void 0}};return uo={findLast:i(0),findLastIndex:i(1)},uo}var Vm;function cI(){if(Vm)return Lm;Vm=1;var e=I(),t=ka().findLast,r=Tt();return e({target:"Array",proto:!0},{findLast:function(i){return t(this,i,arguments.length>1?arguments[1]:void 0)}}),r("findLast"),Lm}var Bm={},Um;function pI(){if(Um)return Bm;Um=1;var e=I(),t=ka().findLastIndex,r=Tt();return e({target:"Array",proto:!0},{findLastIndex:function(i){return t(this,i,arguments.length>1?arguments[1]:void 0)}}),r("findLastIndex"),Bm}var $m={},co,Hm;function bP(){if(Hm)return co;Hm=1;var e=nr(),t=Ze(),r=gr(),a=Ot(),i=function(n,o,l,s,u,d,c,p){for(var v=u,m=0,h=c?a(c,p):!1,b,f;m0&&e(b)?(f=t(b),v=i(n,o,b,f,v,d-1)-1):(r(v+1),n[v]=b),v++),m++;return v};return co=i,co}var Km;function mI(){if(Km)return $m;Km=1;var e=I(),t=bP(),r=Ge(),a=Ze(),i=it(),n=Jr();return e({target:"Array",proto:!0},{flat:function(){var l=arguments.length?arguments[0]:void 0,s=r(this),u=a(s),d=n(s,0);return d.length=t(d,s,s,u,0,l===void 0?1:i(l)),d}}),$m}var Wm={},Gm;function vI(){if(Gm)return Wm;Gm=1;var e=I(),t=bP(),r=Fe(),a=Ge(),i=Ze(),n=Jr();return e({target:"Array",proto:!0},{flatMap:function(l){var s=a(this),u=i(s),d;return r(l),d=n(s,0),d.length=t(d,s,s,u,0,1,l,arguments.length>1?arguments[1]:void 0),d}}),Wm}var Ym={},po,Qm;function kP(){if(Qm)return po;Qm=1;var e=kt().forEach,t=er(),r=t("forEach");return po=r?[].forEach:function(i){return e(this,i,arguments.length>1?arguments[1]:void 0)},po}var Zm;function fI(){if(Zm)return Ym;Zm=1;var e=I(),t=kP();return e({target:"Array",proto:!0,forced:[].forEach!==t},{forEach:t}),Ym}var Jm={},mo,Xm;function Iu(){if(Xm)return mo;Xm=1;var e=Re(),t=yt();return mo=function(r,a,i,n){try{return n?a(e(i)[0],i[1]):a(i)}catch(o){t(r,"throw",o)}},mo}var vo,ev;function yP(){if(ev)return vo;ev=1;var e=Ot(),t=ye(),r=Ge(),a=Iu(),i=Pu(),n=mr(),o=Ze(),l=Gt(),s=zr(),u=fr(),d=Array;return vo=function(p){var v=r(p),m=n(this),h=arguments.length,b=h>1?arguments[1]:void 0,f=b!==void 0;f&&(b=e(b,h>2?arguments[2]:void 0));var g=u(v),k=0,y,_,S,R,w,E;if(g&&!(this===d&&i(g)))for(_=m?new this:[],R=s(v,g),w=R.next;!(S=t(w,R)).done;k++)E=f?a(R,b,[S.value,k],!0):S.value,l(_,k,E);else for(y=o(v),_=m?new this(y):d(y);y>k;k++)E=f?b(v[k],k):v[k],l(_,k,E);return _.length=k,_},vo}var fo,tv;function ya(){if(tv)return fo;tv=1;var e=je(),t=e("iterator"),r=!1;try{var a=0,i={next:function(){return{done:!!a++}},return:function(){r=!0}};i[t]=function(){return this},Array.from(i,function(){throw 2})}catch{}return fo=function(n,o){try{if(!o&&!r)return!1}catch{return!1}var l=!1;try{var s={};s[t]=function(){return{next:function(){return{done:l=!0}}}},n(s)}catch{}return l},fo}var rv;function gI(){if(rv)return Jm;rv=1;var e=I(),t=yP(),r=ya(),a=!r(function(i){Array.from(i)});return e({target:"Array",stat:!0,forced:a},{from:t}),Jm}var av={},iv;function hI(){if(iv)return av;iv=1;var e=I(),t=Yr().includes,r=X(),a=Tt(),i=r(function(){return!Array(1).includes()});return e({target:"Array",proto:!0,forced:i},{includes:function(o){return t(this,o,arguments.length>1?arguments[1]:void 0)}}),a("includes"),av}var nv={},ov;function bI(){if(ov)return nv;ov=1;var e=I(),t=pr(),r=Yr().indexOf,a=er(),i=t([].indexOf),n=!!i&&1/i([1],1,-0)<0,o=n||!a("indexOf");return e({target:"Array",proto:!0,forced:o},{indexOf:function(s){var u=arguments.length>1?arguments[1]:void 0;return n?i(this,s,u)||0:r(this,s,u)}}),nv}var sv={},lv;function kI(){if(lv)return sv;lv=1;var e=I(),t=nr();return e({target:"Array",stat:!0},{isArray:t}),sv}var go,uv;function Dr(){if(uv)return go;uv=1;var e=X(),t=Ue(),r=Ie(),a=bt(),i=Mt(),n=Qe(),o=je(),l=Ye(),s=o("iterator"),u=!1,d,c,p;[].keys&&(p=[].keys(),"next"in p?(c=i(i(p)),c!==Object.prototype&&(d=c)):u=!0);var v=!r(d)||e(function(){var m={};return d[s].call(m)!==m});return v?d={}:l&&(d=a(d)),t(d[s])||n(d,s,function(){return this}),go={IteratorPrototype:d,BUGGY_SAFARI_ITERATORS:u},go}var ho,dv;function ju(){if(dv)return ho;dv=1;var e=Dr().IteratorPrototype,t=bt(),r=It(),a=Pt(),i=Xr(),n=function(){return this};return ho=function(o,l,s,u){var d=l+" Iterator";return o.prototype=t(e,{next:r(+!u,s)}),a(o,d,!1,!0),i[d]=n,o},ho}var bo,cv;function Cu(){if(cv)return bo;cv=1;var e=I(),t=ye(),r=Ye(),a=jr(),i=Ue(),n=ju(),o=Mt(),l=Bt(),s=Pt(),u=ht(),d=Qe(),c=je(),p=Xr(),v=Dr(),m=a.PROPER,h=a.CONFIGURABLE,b=v.IteratorPrototype,f=v.BUGGY_SAFARI_ITERATORS,g=c("iterator"),k="keys",y="values",_="entries",S=function(){return this};return bo=function(R,w,E,P,A,M,T){n(E,w,P);var C=function(ae){if(ae===A&&j)return j;if(!f&&ae&&ae in V)return V[ae];switch(ae){case k:return function(){return new E(this,ae)};case y:return function(){return new E(this,ae)};case _:return function(){return new E(this,ae)}}return function(){return new E(this)}},z=w+" Iterator",q=!1,V=R.prototype,F=V[g]||V["@@iterator"]||A&&V[A],j=!f&&F||C(A),O=w==="Array"&&V.entries||F,D,$,U;if(O&&(D=o(O.call(new R)),D!==Object.prototype&&D.next&&(!r&&o(D)!==b&&(l?l(D,b):i(D[g])||d(D,g,S)),s(D,z,!0,!0),r&&(p[z]=S))),m&&A===y&&F&&F.name!==y&&(!r&&h?u(V,"name",y):(q=!0,j=function(){return t(F,this)})),A)if($={values:C(y),keys:M?j:C(k),entries:C(_)},T)for(U in $)(f||q||!(U in V))&&d(V,U,$[U]);else e({target:w,proto:!0,forced:f||q},$);return(!r||T)&&V[g]!==j&&d(V,g,j,{name:A}),p[w]=j,$},bo}var ko,pv;function hr(){return pv||(pv=1,ko=function(e,t){return{value:e,done:t}}),ko}var yo,mv;function _a(){if(mv)return yo;mv=1;var e=mt(),t=Tt(),r=Xr(),a=at(),i=et().f,n=Cu(),o=hr(),l=Ye(),s=Ae(),u="Array Iterator",d=a.set,c=a.getterFor(u);yo=n(Array,"Array",function(v,m){d(this,{type:u,target:e(v),index:0,kind:m})},function(){var v=c(this),m=v.target,h=v.index++;if(!m||h>=m.length)return v.target=null,o(void 0,!0);switch(v.kind){case"keys":return o(h,!1);case"values":return o(m[h],!1)}return o([h,m[h]],!1)},"values");var p=r.Arguments=r.Array;if(t("keys"),t("values"),t("entries"),!l&&s&&p.name!=="values")try{i(p,"name",{value:"values"})}catch{}return yo}var vv={},fv;function yI(){if(fv)return vv;fv=1;var e=I(),t=te(),r=Mr(),a=mt(),i=er(),n=t([].join),o=r!==Object,l=o||!i("join",",");return e({target:"Array",proto:!0,forced:l},{join:function(u){return n(a(this),u===void 0?",":u)}}),vv}var gv={},_o,hv;function _P(){if(hv)return _o;hv=1;var e=zt(),t=mt(),r=it(),a=Ze(),i=er(),n=Math.min,o=[].lastIndexOf,l=!!o&&1/[1].lastIndexOf(1,-0)<0,s=i("lastIndexOf"),u=l||!s;return _o=u?function(c){if(l)return e(o,this,arguments)||0;var p=t(this),v=a(p);if(v===0)return-1;var m=v-1;for(arguments.length>1&&(m=n(m,r(arguments[1]))),m<0&&(m=v+m);m>=0;m--)if(m in p&&p[m]===c)return m||0;return-1}:o,_o}var bv;function _I(){if(bv)return gv;bv=1;var e=I(),t=_P();return e({target:"Array",proto:!0,forced:t!==[].lastIndexOf},{lastIndexOf:t}),gv}var kv={},yv;function SI(){if(yv)return kv;yv=1;var e=I(),t=kt().map,r=ea(),a=r("map");return e({target:"Array",proto:!0,forced:!a},{map:function(n){return t(this,n,arguments.length>1?arguments[1]:void 0)}}),kv}var _v={},Sv;function wI(){if(Sv)return _v;Sv=1;var e=I(),t=X(),r=mr(),a=Gt(),i=Array,n=t(function(){function o(){}return!(i.of.call(o)instanceof o)});return e({target:"Array",stat:!0,forced:n},{of:function(){for(var l=0,s=arguments.length,u=new(r(this)?this:i)(s);s>l;)a(u,l,arguments[l++]);return u.length=s,u}}),_v}var wv={},So,Rv;function Ou(){if(Rv)return So;Rv=1;var e=Ae(),t=nr(),r=TypeError,a=Object.getOwnPropertyDescriptor,i=e&&!(function(){if(this!==void 0)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(n){return n instanceof TypeError}})();return So=i?function(n,o){if(t(n)&&!a(n,"length").writable)throw new r("Cannot set read only .length");return n.length=o}:function(n,o){return n.length=o},So}var Ev;function RI(){if(Ev)return wv;Ev=1;var e=I(),t=Ge(),r=Ze(),a=Ou(),i=gr(),n=X(),o=n(function(){return[].push.call({length:4294967296},1)!==4294967297}),l=function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(u){return u instanceof TypeError}},s=o||!l();return e({target:"Array",proto:!0,arity:1,forced:s},{push:function(d){var c=t(this),p=r(c),v=arguments.length;i(p+v);for(var m=0;m=0:m>h;h+=b)h in v&&(c=u(c,v[h],h,p));return c}};return wo={left:o(!1),right:o(!0)},wo}var Ro,Pv;function wa(){if(Pv)return Ro;Pv=1;var e=se(),t=Kt(),r=St(),a=function(i){return t.slice(0,i.length)===i};return Ro=(function(){return a("Bun/")?"BUN":a("Cloudflare-Workers")?"CLOUDFLARE":a("Deno/")?"DENO":a("Node.js/")?"NODE":e.Bun&&typeof Bun.version=="string"?"BUN":e.Deno&&typeof Deno.version=="object"?"DENO":r(e.process)==="process"?"NODE":e.window&&e.document?"BROWSER":"REST"})(),Ro}var Eo,Tv;function xr(){if(Tv)return Eo;Tv=1;var e=wa();return Eo=e==="NODE",Eo}var Iv;function EI(){if(Iv)return Av;Iv=1;var e=I(),t=Sa().left,r=er(),a=Wt(),i=xr(),n=!i&&a>79&&a<83,o=n||!r("reduce");return e({target:"Array",proto:!0,forced:o},{reduce:function(s){var u=arguments.length;return t(this,s,u,u>1?arguments[1]:void 0)}}),Av}var jv={},Cv;function AI(){if(Cv)return jv;Cv=1;var e=I(),t=Sa().right,r=er(),a=Wt(),i=xr(),n=!i&&a>79&&a<83,o=n||!r("reduceRight");return e({target:"Array",proto:!0,forced:o},{reduceRight:function(s){return t(this,s,arguments.length,arguments.length>1?arguments[1]:void 0)}}),jv}var Ov={},zv;function MI(){if(zv)return Ov;zv=1;var e=I(),t=te(),r=nr(),a=t([].reverse),i=[1,2];return e({target:"Array",proto:!0,forced:String(i)===String(i.reverse())},{reverse:function(){return r(this)&&(this.length=this.length),a(this)}}),Ov}var Dv={},xv;function PI(){if(xv)return Dv;xv=1;var e=I(),t=nr(),r=mr(),a=Ie(),i=Xt(),n=Ze(),o=mt(),l=Gt(),s=je(),u=ea(),d=Ft(),c=u("slice"),p=s("species"),v=Array,m=Math.max;return e({target:"Array",proto:!0,forced:!c},{slice:function(b,f){var g=o(this),k=n(g),y=i(b,k),_=i(f===void 0?k:f,k),S,R,w;if(t(g)&&(S=g.constructor,r(S)&&(S===v||t(S.prototype))?S=void 0:a(S)&&(S=S[p],S===null&&(S=void 0)),S===v||S===void 0))return d(g,y,_);for(R=new(S===void 0?v:S)(m(_-y,0)),w=0;y<_;y++,w++)y in g&&l(R,w,g[y]);return R.length=w,R}}),Dv}var qv={},Nv;function TI(){if(Nv)return qv;Nv=1;var e=I(),t=kt().some,r=er(),a=r("some");return e({target:"Array",proto:!0,forced:!a},{some:function(n){return t(this,n,arguments.length>1?arguments[1]:void 0)}}),qv}var Lv={},Ao,Fv;function zu(){if(Fv)return Ao;Fv=1;var e=Ft(),t=Math.floor,r=function(a,i){var n=a.length;if(n<8)for(var o=1,l,s;o0;)a[s]=a[--s];s!==o++&&(a[s]=l)}else for(var u=t(n/2),d=r(e(a,0,u),i),c=r(e(a,u),i),p=d.length,v=c.length,m=0,h=0;m3)){if(c)return!0;if(v)return v<603;var R="",w,E,P,A;for(w=65;w<76;w++){switch(E=String.fromCharCode(w),w){case 66:case 69:case 70:case 72:P=3;break;case 68:case 71:P=4;break;default:P=2}for(A=0;A<47;A++)m.push({k:E+A,v:P})}for(m.sort(function(M,T){return T.v-M.v}),A=0;Ao(E)?1:-1}};return e({target:"Array",proto:!0,forced:_},{sort:function(w){w!==void 0&&r(w);var E=a(this);if(y)return w===void 0?h(E):h(E,w);var P=[],A=i(E),M,T;for(T=0;Tg-S+_;w--)u(f,w-1)}else if(_>S)for(w=g-S;w>k;w--)E=w+S-1,P=w+_-1,E in f?f[P]=f[E]:u(f,P);for(w=0;w<_;w++)f[w+k]=arguments[w+2];return n(f,g-S+_),R}}),Gv}var Qv={},jo,Zv;function RP(){if(Zv)return jo;Zv=1;var e=Ze();return jo=function(t,r){for(var a=e(t),i=new r(a),n=0;n2?a:e(r),o=new t(n);n>i;)o[i]=r[i++];return o},Co}var Oo,tf;function EP(){if(tf)return Oo;tf=1;var e=se();return Oo=function(t,r){var a=e[t],i=a&&a.prototype;return i&&i[r]},Oo}var rf;function zI(){if(rf)return Xv;rf=1;var e=I(),t=te(),r=Fe(),a=mt(),i=ta(),n=EP(),o=Tt(),l=Array,s=t(n("Array","sort"));return e({target:"Array",proto:!0},{toSorted:function(d){d!==void 0&&r(d);var c=a(this),p=i(l,c);return s(p,d)}}),o("toSorted"),Xv}var af={},nf;function DI(){if(nf)return af;nf=1;var e=I(),t=Tt(),r=gr(),a=Ze(),i=Xt(),n=mt(),o=it(),l=Array,s=Math.max,u=Math.min;return e({target:"Array",proto:!0},{toSpliced:function(c,p){var v=n(this),m=a(v),h=i(c,m),b=arguments.length,f=0,g,k,y,_;for(b===0?g=k=0:b===1?(g=0,k=m-h):(g=b-2,k=u(s(o(p),0),m-h)),y=r(m+g-k),_=l(y);f=l||u<0)throw new r("Incorrect index");for(var d=new i(l),c=0;co||p!==p?d*(1/0):d*p},Vo}var Bo,wf;function TP(){if(wf)return Bo;wf=1;var e=PP(),t=11920928955078125e-23,r=34028234663852886e22,a=11754943508222875e-54;return Bo=Math.fround||function(n){return e(n,t,r,a)},Bo}var Uo,Rf;function FI(){if(Rf)return Uo;Rf=1;var e=Array,t=Math.abs,r=Math.pow,a=Math.floor,i=Math.log,n=Math.LN2,o=function(s,u,d){var c=e(d),p=d*8-u-1,v=(1<>1,h=u===23?r(2,-24)-r(2,-77):0,b=s<0||s===0&&1/s<0?1:0,f=0,g,k,y;for(s=t(s),s!==s||s===1/0?(k=s!==s?1:0,g=v):(g=a(i(s)/n),y=r(2,-g),s*y<1&&(g--,y*=2),g+m>=1?s+=h/y:s+=h*r(2,1-m),s*y>=2&&(g++,y/=2),g+m>=v?(k=0,g=v):g+m>=1?(k=(s*y-1)*r(2,u),g+=m):(k=s*r(2,m-1)*r(2,u),g=0));u>=8;)c[f++]=k&255,k/=256,u-=8;for(g=g<0;)c[f++]=g&255,g/=256,p-=8;return c[f-1]|=b*128,c},l=function(s,u){var d=s.length,c=d*8-u-1,p=(1<>1,m=c-7,h=d-1,b=s[h--],f=b&127,g;for(b>>=7;m>0;)f=f*256+s[h--],m-=8;for(g=f&(1<<-m)-1,f>>=-m,m+=u;m>0;)g=g*256+s[h--],m-=8;if(f===0)f=1-v;else{if(f===p)return g?NaN:b?-1/0:1/0;g+=r(2,u),f-=v}return(b?-1:1)*g*r(2,f-u)};return Uo={pack:o,unpack:l},Uo}var $o,Ef;function Aa(){if(Ef)return $o;Ef=1;var e=se(),t=te(),r=Ae(),a=Ra(),i=jr(),n=ht(),o=ot(),l=tr(),s=X(),u=Dt(),d=it(),c=jt(),p=Ea(),v=TP(),m=FI(),h=Mt(),b=Bt(),f=Tu(),g=Ft(),k=vr(),y=Cr(),_=Pt(),S=at(),R=i.PROPER,w=i.CONFIGURABLE,E="ArrayBuffer",P="DataView",A="prototype",M="Wrong length",T="Wrong index",C=S.getterFor(E),z=S.getterFor(P),q=S.set,V=e[E],F=V,j=F&&F[A],O=e[P],D=O&&O[A],$=Object.prototype,U=e.Array,ae=e.RangeError,Me=t(f),he=t([].reverse),fe=m.pack,K=m.unpack,le=function(J){return[J&255]},ge=function(J){return[J&255,J>>8&255]},_e=function(J){return[J&255,J>>8&255,J>>16&255,J>>24&255]},ke=function(J){return J[3]<<24|J[2]<<16|J[1]<<8|J[0]},Pe=function(J){return fe(v(J),23,4)},He=function(J){return fe(J,52,8)},We=function(J,oe,Ee){o(J[A],oe,{configurable:!0,get:function(){return Ee(this)[oe]}})},qe=function(J,oe,Ee,ie){var me=z(J),ve=p(Ee),ce=!!ie;if(ve+oe>me.byteLength)throw new ae(T);var De=me.bytes,Xe=ve+me.byteOffset,L=g(De,Xe,Xe+oe);return ce?L:he(L)},Se=function(J,oe,Ee,ie,me,ve){var ce=z(J),De=p(Ee),Xe=ie(+me),L=!!ve;if(De+oe>ce.byteLength)throw new ae(T);for(var G=ce.bytes,Q=De+ce.byteOffset,Z=0;Zve)throw new ae("Wrong offset");if(ie=ie===void 0?ve-ce:c(ie),ce+ie>ve)throw new ae(M);q(this,{type:P,buffer:oe,byteLength:ie,byteOffset:ce,bytes:me.bytes}),r||(this.buffer=oe,this.byteLength=ie,this.byteOffset=ce)},D=O[A],r&&(We(F,"byteLength",C),We(O,"buffer",z),We(O,"byteLength",z),We(O,"byteOffset",z)),l(D,{getInt8:function(oe){return qe(this,1,oe)[0]<<24>>24},getUint8:function(oe){return qe(this,1,oe)[0]},getInt16:function(oe){var Ee=qe(this,2,oe,arguments.length>1?arguments[1]:!1);return(Ee[1]<<8|Ee[0])<<16>>16},getUint16:function(oe){var Ee=qe(this,2,oe,arguments.length>1?arguments[1]:!1);return Ee[1]<<8|Ee[0]},getInt32:function(oe){return ke(qe(this,4,oe,arguments.length>1?arguments[1]:!1))},getUint32:function(oe){return ke(qe(this,4,oe,arguments.length>1?arguments[1]:!1))>>>0},getFloat32:function(oe){return K(qe(this,4,oe,arguments.length>1?arguments[1]:!1),23)},getFloat64:function(oe){return K(qe(this,8,oe,arguments.length>1?arguments[1]:!1),52)},setInt8:function(oe,Ee){Se(this,1,oe,le,Ee)},setUint8:function(oe,Ee){Se(this,1,oe,le,Ee)},setInt16:function(oe,Ee){Se(this,2,oe,ge,Ee,arguments.length>2?arguments[2]:!1)},setUint16:function(oe,Ee){Se(this,2,oe,ge,Ee,arguments.length>2?arguments[2]:!1)},setInt32:function(oe,Ee){Se(this,4,oe,_e,Ee,arguments.length>2?arguments[2]:!1)},setUint32:function(oe,Ee){Se(this,4,oe,_e,Ee,arguments.length>2?arguments[2]:!1)},setFloat32:function(oe,Ee){Se(this,4,oe,Pe,Ee,arguments.length>2?arguments[2]:!1)},setFloat64:function(oe,Ee){Se(this,8,oe,He,Ee,arguments.length>2?arguments[2]:!1)}});else{var Ne=R&&V.name!==E;!s(function(){V(1)})||!s(function(){new V(-1)})||s(function(){return new V,new V(1.5),new V(NaN),V.length!==1||Ne&&!w})?(F=function(oe){return u(this,j),k(new V(p(oe)),this,F)},F[A]=j,j.constructor=F,y(F,V)):Ne&&w&&n(V,"name",E),b&&h(D)!==$&&b(D,$);var ze=new O(new F(2)),Ce=t(D.setInt8);ze.setInt8(0,2147483648),ze.setInt8(1,2147483649),(ze.getInt8(0)||!ze.getInt8(1))&&l(D,{setInt8:function(oe,Ee){Ce(this,oe,Ee<<24>>24)},setUint8:function(oe,Ee){Ce(this,oe,Ee<<24>>24)}},{unsafe:!0})}return _(F,E),_(O,P),$o={ArrayBuffer:F,DataView:O},$o}var Af;function VI(){if(Af)return ff;Af=1;var e=I(),t=se(),r=Aa(),a=qr(),i="ArrayBuffer",n=r[i],o=t[i];return e({global:!0,constructor:!0,forced:o!==n},{ArrayBuffer:n}),a(i),ff}var Mf={},Ho,Pf;function $e(){if(Pf)return Ho;Pf=1;var e=Ra(),t=Ae(),r=se(),a=Ue(),i=Ie(),n=Ve(),o=Ct(),l=dr(),s=ht(),u=Qe(),d=ot(),c=At(),p=Mt(),v=Bt(),m=je(),h=Ir(),b=at(),f=b.enforce,g=b.get,k=r.Int8Array,y=k&&k.prototype,_=r.Uint8ClampedArray,S=_&&_.prototype,R=k&&p(k),w=y&&p(y),E=Object.prototype,P=r.TypeError,A=m("toStringTag"),M=h("TYPED_ARRAY_TAG"),T="TypedArrayConstructor",C=e&&!!v&&o(r.opera)!=="Opera",z=!1,q,V,F,j={Int8Array:1,Uint8Array:1,Uint8ClampedArray:1,Int16Array:2,Uint16Array:2,Int32Array:4,Uint32Array:4,Float32Array:4,Float64Array:8},O={BigInt64Array:8,BigUint64Array:8},D=function(le){if(!i(le))return!1;var ge=o(le);return ge==="DataView"||n(j,ge)||n(O,ge)},$=function(K){var le=p(K);if(i(le)){var ge=g(le);return ge&&n(ge,T)?ge[T]:$(le)}},U=function(K){if(!i(K))return!1;var le=o(K);return n(j,le)||n(O,le)},ae=function(K){if(U(K))return K;throw new P("Target is not a typed array")},Me=function(K){if(a(K)&&(!v||c(R,K)))return K;throw new P(l(K)+" is not a typed array constructor")},he=function(K,le,ge,_e){if(t){if(ge)for(var ke in j){var Pe=r[ke];if(Pe&&n(Pe.prototype,K))try{delete Pe.prototype[K]}catch{try{Pe.prototype[K]=le}catch{}}}(!w[K]||ge)&&u(w,K,ge?le:C&&y[K]||le,_e)}},fe=function(K,le,ge){var _e,ke;if(t){if(v){if(ge){for(_e in j)if(ke=r[_e],ke&&n(ke,K))try{delete ke[K]}catch{}}if(!R[K]||ge)try{return u(R,K,ge?le:C&&R[K]||le)}catch{}else return}for(_e in j)ke=r[_e],ke&&(!ke[K]||ge)&&u(ke,K,le)}};for(q in j)V=r[q],F=V&&V.prototype,F?f(F)[T]=V:C=!1;for(q in O)V=r[q],F=V&&V.prototype,F&&(f(F)[T]=V);if((!C||!a(R)||R===Function.prototype)&&(R=function(){throw new P("Incorrect invocation")},C))for(q in j)r[q]&&v(r[q],R);if((!C||!w||w===E)&&(w=R.prototype,C))for(q in j)r[q]&&v(r[q].prototype,w);if(C&&p(S)!==w&&v(S,w),t&&!n(w,A)){z=!0,d(w,A,{configurable:!0,get:function(){return i(this)?this[M]:void 0}});for(q in j)r[q]&&s(r[q],M,q)}return Ho={NATIVE_ARRAY_BUFFER_VIEWS:C,TYPED_ARRAY_TAG:z&&M,aTypedArray:ae,aTypedArrayConstructor:Me,exportTypedArrayMethod:he,exportTypedArrayStaticMethod:fe,getTypedArrayConstructor:$,isView:D,isTypedArray:U,TypedArray:R,TypedArrayPrototype:w},Ho}var Tf;function BI(){if(Tf)return Mf;Tf=1;var e=I(),t=$e(),r=t.NATIVE_ARRAY_BUFFER_VIEWS;return e({target:"ArrayBuffer",stat:!0,forced:!r},{isView:t.isView}),Mf}var If={},jf;function UI(){if(jf)return If;jf=1;var e=I(),t=pr(),r=X(),a=Aa(),i=Re(),n=Xt(),o=jt(),l=a.ArrayBuffer,s=a.DataView,u=s.prototype,d=t(l.prototype.slice),c=t(u.getUint8),p=t(u.setUint8),v=r(function(){return!new l(2).slice(1,void 0).byteLength});return e({target:"ArrayBuffer",proto:!0,unsafe:!0,forced:v},{slice:function(h,b){if(d&&b===void 0)return d(i(this),h);for(var f=i(this).byteLength,g=n(h,f),k=n(b===void 0?f:b,f),y=new l(o(k-g)),_=new s(this),S=new s(y),R=0;g>>15,c=u>>>10&a,p=u&i;return c===a?p===0?d===0?1/0:-1/0:NaN:c===0?p*(d===0?n:-n):r(2,c-15)*(d===0?1+p*o:-1-p*o)},s=t(DataView.prototype.getUint16);return e({target:"DataView",proto:!0},{getFloat16:function(d){return l(s(this,d,arguments.length>1?arguments[1]:!1))}}),xf}var Nf={},Ko,Lf;function WI(){if(Lf)return Ko;Lf=1;var e=Ct(),t=TypeError;return Ko=function(r){if(e(r)==="DataView")return r;throw new t("Argument is not a DataView")},Ko}var Wo,Ff;function IP(){if(Ff)return Wo;Ff=1;var e=Math.log,t=Math.LN2;return Wo=Math.log2||function(a){return e(a)/t},Wo}var Vf;function GI(){if(Vf)return Nf;Vf=1;var e=I(),t=te(),r=WI(),a=Ea(),i=IP(),n=MP(),o=Math.pow,l=65520,s=61005353927612305e-21,u=16777216,d=1024,c=function(v){if(v!==v)return 32256;if(v===0)return(1/v===-1/0)<<15;var m=v<0;if(m&&(v=-v),v>=l)return m<<15|31744;if(v2?arguments[2]:!1)}}),Nf}var Bf={},Go,Uf;function jP(){if(Uf)return Go;Uf=1;var e=se(),t=ha(),r=St(),a=e.ArrayBuffer,i=e.TypeError;return Go=a&&t(a.prototype,"byteLength","get")||function(n){if(r(n)!=="ArrayBuffer")throw new i("ArrayBuffer expected");return n.byteLength},Go}var Yo,$f;function CP(){if($f)return Yo;$f=1;var e=se(),t=Ra(),r=jP(),a=e.DataView;return Yo=function(i){if(!t||r(i)!==0)return!1;try{return new a(i),!1}catch{return!0}},Yo}var Hf;function YI(){if(Hf)return Bf;Hf=1;var e=Ae(),t=ot(),r=CP(),a=ArrayBuffer.prototype;return e&&!("detached"in a)&&t(a,"detached",{configurable:!0,get:function(){return r(this)}}),Bf}var Kf={},Qo,Wf;function ra(){if(Wf)return Qo;Wf=1;var e=CP(),t=TypeError;return Qo=function(r){if(e(r))throw new t("ArrayBuffer is detached");return r},Qo}var Zo,Gf;function OP(){if(Gf)return Zo;Gf=1;var e=se(),t=xr();return Zo=function(r){if(t){try{return e.process.getBuiltinModule(r)}catch{}try{return Function('return require("'+r+'")')()}catch{}}},Zo}var Jo,Yf;function qu(){if(Yf)return Jo;Yf=1;var e=se(),t=X(),r=Wt(),a=wa(),i=e.structuredClone;return Jo=!!i&&!t(function(){if(a==="DENO"&&r>92||a==="NODE"&&r>94||a==="BROWSER"&&r>97)return!1;var n=new ArrayBuffer(8),o=i(n,{transfer:[n]});return n.byteLength!==0||o.byteLength!==8}),Jo}var Xo,Qf;function zP(){if(Qf)return Xo;Qf=1;var e=se(),t=OP(),r=qu(),a=e.structuredClone,i=e.ArrayBuffer,n=e.MessageChannel,o=!1,l,s,u,d;if(r)o=function(c){a(c,{transfer:[c]})};else if(i)try{n||(l=t("worker_threads"),l&&(n=l.MessageChannel)),n&&(s=new n,u=new i(2),d=function(c){s.port1.postMessage(null,[c])},u.byteLength===2&&(d(u),u.byteLength===0&&(o=d)))}catch{}return Xo=o,Xo}var es,Zf;function DP(){if(Zf)return es;Zf=1;var e=se(),t=te(),r=ha(),a=Ea(),i=ra(),n=jP(),o=zP(),l=qu(),s=e.structuredClone,u=e.ArrayBuffer,d=e.DataView,c=Math.min,p=u.prototype,v=d.prototype,m=t(p.slice),h=r(p,"resizable","get"),b=r(p,"maxByteLength","get"),f=t(v.getInt8),g=t(v.setInt8);return es=(l||o)&&function(k,y,_){var S=n(k),R=y===void 0?S:a(y),w=!h||!h(k),E;if(i(k),l&&(k=s(k,{transfer:[k]}),S===R&&(_||w)))return k;if(S>=R&&(!_||w))E=m(k,0,R);else{var P=_&&!w&&b?{maxByteLength:b(k)}:void 0;E=new u(R,P);for(var A=new d(k),M=new d(E),T=c(R,S),C=0;C=0&&s<=99?s+1900:s;return n(this,u)}}),ng}var sg={},lg;function tj(){if(lg)return sg;lg=1;var e=I();return e({target:"Date",proto:!0},{toGMTString:Date.prototype.toUTCString}),sg}var ug={},ts,dg;function Ma(){if(dg)return ts;dg=1;var e=it(),t=xe(),r=rt(),a=RangeError;return ts=function(n){var o=t(r(this)),l="",s=e(n);if(s<0||s===1/0)throw new a("Wrong number of repetitions");for(;s>0;(s>>>=1)&&(o+=o))s&1&&(l+=o);return l},ts}var rs,cg;function Pa(){if(cg)return rs;cg=1;var e=te(),t=jt(),r=xe(),a=Ma(),i=rt(),n=e(a),o=e("".slice),l=Math.ceil,s=function(u){return function(d,c,p){var v=r(i(d)),m=t(c),h=v.length,b=p===void 0?" ":r(p),f,g;return m<=h||b===""?v:(f=m-h,g=n(b,l(f/b.length)),g.length>f&&(g=o(g,0,f)),u?v+g:g+v)}};return rs={start:s(!1),end:s(!0)},rs}var as,pg;function rj(){if(pg)return as;pg=1;var e=te(),t=X(),r=Pa().start,a=RangeError,i=isFinite,n=Math.abs,o=Date.prototype,l=o.toISOString,s=e(o.getTime),u=e(o.getUTCDate),d=e(o.getUTCFullYear),c=e(o.getUTCHours),p=e(o.getUTCMilliseconds),v=e(o.getUTCMinutes),m=e(o.getUTCMonth),h=e(o.getUTCSeconds);return as=t(function(){return l.call(new Date(-5e13-1))!=="0385-07-25T07:06:39.999Z"})||!t(function(){l.call(new Date(NaN))})?function(){if(!i(s(this)))throw new a("Invalid time value");var f=this,g=d(f),k=p(f),y=g<0?"-":g>9999?"+":"";return y+r(n(g),y?6:4,0)+"-"+r(m(f)+1,2,0)+"-"+r(u(f),2,0)+"T"+r(c(f),2,0)+":"+r(v(f),2,0)+":"+r(h(f),2,0)+"."+r(k,3,0)+"Z"}:l,as}var mg;function aj(){if(mg)return ug;mg=1;var e=I(),t=rj();return e({target:"Date",proto:!0,forced:Date.prototype.toISOString!==t},{toISOString:t}),ug}var vg={},fg;function ij(){if(fg)return vg;fg=1;var e=I(),t=X(),r=Ge(),a=pa(),i=t(function(){return new Date(NaN).toJSON()!==null||Date.prototype.toJSON.call({toISOString:function(){return 1}})!==1});return e({target:"Date",proto:!0,arity:1,forced:i},{toJSON:function(o){var l=r(this),s=a(l,"number");return typeof s=="number"&&!isFinite(s)?null:l.toISOString()}}),vg}var gg={},is,hg;function nj(){if(hg)return is;hg=1;var e=Re(),t=XM(),r=TypeError;return is=function(a){if(e(this),a==="string"||a==="default")a="string";else if(a!=="number")throw new r("Incorrect hint");return t(this,a)},is}var bg;function oj(){if(bg)return gg;bg=1;var e=Ve(),t=Qe(),r=nj(),a=je(),i=a("toPrimitive"),n=Date.prototype;return e(n,i)||t(n,i,r),gg}var kg={},yg;function sj(){if(yg)return kg;yg=1;var e=te(),t=Qe(),r=Date.prototype,a="Invalid Date",i="toString",n=e(r[i]),o=e(r.getTime);return String(new Date(NaN))!==a&&t(r,i,function(){var s=o(this);return s===s?n(this):a}),kg}var _g={},ns,Sg;function xP(){if(Sg)return ns;Sg=1;var e=Le(),t=ye(),r=te(),a=Ot(),i=Re(),n=Fe(),o=Jt(),l=ft(),s=je(),u=s("asyncDispose"),d=s("dispose"),c=r([].push),p=function(m,h){if(h==="async-dispose"){var b=l(m,u);return b!==void 0||(b=l(m,d),b===void 0)?b:function(){var f=this,g=e("Promise");return new g(function(k){t(b,f),k(void 0)})}}return l(m,d)},v=function(m,h,b){return arguments.length<3&&!o(m)&&(b=n(p(i(m),h))),b===void 0?function(){}:a(b,m)};return ns=function(m,h,b,f){var g;if(arguments.length<4){if(o(h)&&b==="sync-dispose")return;g=v(h,b)}else g=v(void 0,b,f);c(m.stack,g)},ns}var wg;function lj(){if(wg)return _g;wg=1;var e=I(),t=Ae(),r=Le(),a=Fe(),i=Dt(),n=Qe(),o=tr(),l=ot(),s=je(),u=at(),d=xP(),c=r("SuppressedError"),p=ReferenceError,v=s("dispose"),m=s("toStringTag"),h="DisposableStack",b=u.set,f=u.getterFor(h),g="sync-dispose",k="disposed",y="pending",_=function(w){var E=f(w);if(E.state===k)throw new p(h+" already disposed");return E},S=function(){b(i(this,R),{type:h,state:y,stack:[]}),t||(this.disposed=!1)},R=S.prototype;return o(R,{dispose:function(){var E=f(this);if(E.state!==k){E.state=k,t||(this.disposed=!0);for(var P=E.stack,A=P.length,M=!1,T;A;){var C=P[--A];P[A]=null;try{C()}catch(z){M?T=new c(z,T):(M=!0,T=z)}}if(E.stack=null,M)throw T}},use:function(E){return d(_(this),E,g),E},adopt:function(E,P){var A=_(this);return a(P),d(A,void 0,g,function(){P(E)}),E},defer:function(E){var P=_(this);a(E),d(P,void 0,g,E)},move:function(){var E=_(this),P=new S;return f(P).stack=E.stack,E.stack=[],E.state=k,t||(this.disposed=!0),P}}),t&&l(R,"disposed",{configurable:!0,get:function(){return f(this).state===k}}),n(R,v,R.dispose,{name:"dispose"}),n(R,m,h,{nonWritable:!0}),e({global:!0,constructor:!0},{DisposableStack:S}),_g}var Rg={},Eg;function uj(){if(Eg)return Rg;Eg=1;var e=I(),t=te(),r=xe(),a=t("".charAt),i=t("".charCodeAt),n=t(/./.exec),o=t(1.1.toString),l=t("".toUpperCase),s=/[\w*+\-./@]/,u=function(d,c){for(var p=o(d,16);p.length=0;i--)if(t[i]!==void 0)try{a=e(t[i].iterator,r,a)}catch(n){r="throw",a=n}if(r==="throw")throw a;return a},ds}var cs,$g;function Nr(){if($g)return cs;$g=1;var e=ye(),t=bt(),r=ht(),a=tr(),i=je(),n=at(),o=ft(),l=Dr().IteratorPrototype,s=hr(),u=yt(),d=gj(),c=i("toStringTag"),p="IteratorHelper",v="WrapForValidIterator",m="normal",h="throw",b=n.set,f=function(y){var _=n.getterFor(y?v:p);return a(t(l),{next:function(){var R=_(this);if(y)return R.nextHandler();if(R.done)return s(void 0,!0);try{var w=R.nextHandler();return R.returnHandlerResult?w:s(w,R.done)}catch(E){throw R.done=!0,E}},return:function(){var S=_(this),R=S.iterator;if(S.done=!0,y){var w=o(R,"return");return w?e(w,R):s(void 0,!0)}if(S.inner)try{u(S.inner.iterator,m)}catch(E){return u(R,h,E)}if(S.openIters)try{d(S.openIters,m)}catch(E){return u(R,h,E)}return R&&u(R,m),s(void 0,!0)}})},g=f(!0),k=f(!1);return r(k,c,"Iterator Helper"),cs=function(y,_,S){var R=function(E,P){P?(P.iterator=E.iterator,P.next=E.next):P=E,P.type=_?v:p,P.returnHandlerResult=!!S,P.nextHandler=y,P.counter=0,P.done=!1,b(this,P)};return R.prototype=_?g:k,R},cs}var ps,Hg;function Ta(){return Hg||(Hg=1,ps=function(e,t){var r=typeof Iterator=="function"&&Iterator.prototype[e];if(r)try{r.call({next:null},t).next()}catch{return!0}}),ps}var ms,Kg;function Yt(){if(Kg)return ms;Kg=1;var e=se();return ms=function(t,r){var a=e.Iterator,i=a&&a.prototype,n=i&&i[t],o=!1;if(n)try{n.call({next:function(){return{done:!0}},return:function(){o=!0}},-1)}catch(l){l instanceof r||(o=!1)}if(!o)return n},ms}var Wg;function hj(){if(Wg)return Lg;Wg=1;var e=I(),t=ye(),r=Re(),a=Rt(),i=NP(),n=Nu(),o=yt(),l=Nr(),s=Ta(),u=Yt(),d=Ye(),c=!d&&!s("drop",0),p=!d&&!c&&u("drop",RangeError),v=d||c||p,m=l(function(){for(var h=this.iterator,b=this.next,f,g;this.remaining;)if(this.remaining--,f=r(t(b,h)),g=this.done=!!f.done,g)return;if(f=r(t(b,h)),g=this.done=!!f.done,!g)return f.value});return e({target:"Iterator",proto:!0,real:!0,forced:v},{drop:function(b){r(this);var f;try{f=n(i(+b))}catch(g){o(this,"throw",g)}return p?t(p,this,f):new m(a(this),{remaining:f})}}),Lg}var Gg={},Yg;function bj(){if(Yg)return Gg;Yg=1;var e=I(),t=ye(),r=ct(),a=Fe(),i=Re(),n=Rt(),o=yt(),l=Yt(),s=l("every",TypeError);return e({target:"Iterator",proto:!0,real:!0,forced:s},{every:function(d){i(this);try{a(d)}catch(v){o(this,"throw",v)}if(s)return t(s,this,d);var c=n(this),p=0;return!r(c,function(v,m){if(!d(v,p++))return m()},{IS_RECORD:!0,INTERRUPTED:!0}).stopped}}),Gg}var Qg={},Zg;function kj(){if(Zg)return Qg;Zg=1;var e=I(),t=ye(),r=Fe(),a=Re(),i=Rt(),n=Nr(),o=Iu(),l=Ye(),s=yt(),u=Ta(),d=Yt(),c=!l&&!u("filter",function(){}),p=!l&&!c&&d("filter",TypeError),v=l||c||p,m=n(function(){for(var h=this.iterator,b=this.predicate,f=this.next,g,k,y;;){if(g=a(t(f,h)),k=this.done=!!g.done,k)return;if(y=g.value,o(h,b,[y,this.counter++],!0))return y}});return e({target:"Iterator",proto:!0,real:!0,forced:v},{filter:function(b){a(this);try{r(b)}catch(f){s(this,"throw",f)}return p?t(p,this,b):new m(i(this),{predicate:b})}}),Qg}var Jg={},Xg;function yj(){if(Xg)return Jg;Xg=1;var e=I(),t=ye(),r=ct(),a=Fe(),i=Re(),n=Rt(),o=yt(),l=Yt(),s=l("find",TypeError);return e({target:"Iterator",proto:!0,real:!0,forced:s},{find:function(d){i(this);try{a(d)}catch(v){o(this,"throw",v)}if(s)return t(s,this,d);var c=n(this),p=0;return r(c,function(v,m){if(d(v,p++))return m(v)},{IS_RECORD:!0,INTERRUPTED:!0}).result}}),Jg}var eh={},vs,th;function LP(){if(th)return vs;th=1;var e=ye(),t=Re(),r=Rt(),a=fr();return vs=function(i,n){(!n||typeof i!="string")&&t(i);var o=a(i);return r(t(o!==void 0?e(o,i):i))},vs}var rh;function _j(){if(rh)return eh;rh=1;var e=I(),t=ye(),r=Fe(),a=Re(),i=Rt(),n=LP(),o=Nr(),l=yt(),s=Ye(),u=Ta(),d=Yt(),c=!s&&!u("flatMap",function(){}),p=!s&&!c&&d("flatMap",TypeError),v=s||c||p,m=o(function(){for(var h=this.iterator,b=this.mapper,f,g;;){if(g=this.inner)try{if(f=a(t(g.next,g.iterator)),!f.done)return f.value;this.inner=null}catch(k){l(h,"throw",k)}if(f=a(t(this.next,h)),this.done=!!f.done)return;try{this.inner=n(b(f.value,this.counter++),!1)}catch(k){l(h,"throw",k)}}});return e({target:"Iterator",proto:!0,real:!0,forced:v},{flatMap:function(b){a(this);try{r(b)}catch(f){l(this,"throw",f)}return p?t(p,this,b):new m(i(this),{mapper:b,inner:null})}}),eh}var ah={},ih;function Sj(){if(ih)return ah;ih=1;var e=I(),t=ye(),r=ct(),a=Fe(),i=Re(),n=Rt(),o=yt(),l=Yt(),s=l("forEach",TypeError);return e({target:"Iterator",proto:!0,real:!0,forced:s},{forEach:function(d){i(this);try{a(d)}catch(v){o(this,"throw",v)}if(s)return t(s,this,d);var c=n(this),p=0;r(c,function(v){d(v,p++)},{IS_RECORD:!0})}}),ah}var nh={},oh;function wj(){if(oh)return nh;oh=1;var e=I(),t=ye(),r=Ge(),a=At(),i=Dr().IteratorPrototype,n=Nr(),o=LP(),l=Ye(),s=l||(function(){try{Iterator.from({return:null}).return()}catch{return!0}})(),u=n(function(){return t(this.next,this.iterator)},!0);return e({target:"Iterator",stat:!0,forced:s},{from:function(c){var p=o(typeof c=="string"?r(c):c,!0);return a(i,p.iterator)?p.iterator:new u(p)}}),nh}var sh={},lh;function Rj(){if(lh)return sh;lh=1;var e=I(),t=ye(),r=Fe(),a=Re(),i=Rt(),n=Nr(),o=Iu(),l=yt(),s=Ta(),u=Yt(),d=Ye(),c=!d&&!s("map",function(){}),p=!d&&!c&&u("map",TypeError),v=d||c||p,m=n(function(){var h=this.iterator,b=a(t(this.next,h)),f=this.done=!!b.done;if(!f)return o(h,this.mapper,[b.value,this.counter++],!0)});return e({target:"Iterator",proto:!0,real:!0,forced:v},{map:function(b){a(this);try{r(b)}catch(f){l(this,"throw",f)}return p?t(p,this,b):new m(i(this),{mapper:b})}}),sh}var uh={},dh;function Ej(){if(dh)return uh;dh=1;var e=I(),t=ct(),r=Fe(),a=Re(),i=Rt(),n=yt(),o=Yt(),l=zt(),s=X(),u=TypeError,d=s(function(){[].keys().reduce(function(){},void 0)}),c=!d&&o("reduce",u);return e({target:"Iterator",proto:!0,real:!0,forced:d||c},{reduce:function(v){a(this);try{r(v)}catch(g){n(this,"throw",g)}var m=arguments.length<2,h=m?void 0:arguments[1];if(c)return l(c,this,m?[v]:[v,h]);var b=i(this),f=0;if(t(b,function(g){m?(m=!1,h=g):h=v(h,g,f),f++},{IS_RECORD:!0}),m)throw new u("Reduce of empty iterator with no initial value");return h}}),uh}var ch={},ph;function Aj(){if(ph)return ch;ph=1;var e=I(),t=ye(),r=ct(),a=Fe(),i=Re(),n=Rt(),o=yt(),l=Yt(),s=l("some",TypeError);return e({target:"Iterator",proto:!0,real:!0,forced:s},{some:function(d){i(this);try{a(d)}catch(v){o(this,"throw",v)}if(s)return t(s,this,d);var c=n(this),p=0;return r(c,function(v,m){if(d(v,p++))return m()},{IS_RECORD:!0,INTERRUPTED:!0}).stopped}}),ch}var mh={},vh;function Mj(){if(vh)return mh;vh=1;var e=I(),t=ye(),r=Re(),a=Rt(),i=NP(),n=Nu(),o=Nr(),l=yt(),s=Yt(),u=Ye(),d=!u&&s("take",RangeError),c=o(function(){var p=this.iterator;if(!this.remaining--)return this.done=!0,l(p,"normal",void 0);var v=r(t(this.next,p)),m=this.done=!!v.done;if(!m)return v.value});return e({target:"Iterator",proto:!0,real:!0,forced:u||d},{take:function(v){r(this);var m;try{m=n(i(+v))}catch(h){l(this,"throw",h)}return d?t(d,this,m):new c(a(this),{remaining:m})}}),mh}var fh={},gh;function Pj(){if(gh)return fh;gh=1;var e=I(),t=Re(),r=ct(),a=Rt(),i=[].push;return e({target:"Iterator",proto:!0,real:!0},{toArray:function(){var o=[];return r(a(t(this)),i,{that:o,IS_RECORD:!0}),o}}),fh}var hh={},bh;function Tj(){if(bh)return hh;bh=1;var e=se(),t=Pt();return t(e.JSON,"JSON",!0),hh}var kh={},yh={},fs={exports:{}},gs,_h;function Lu(){if(_h)return gs;_h=1;var e=X();return gs=e(function(){if(typeof ArrayBuffer=="function"){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}}),gs}var hs,Sh;function Fu(){if(Sh)return hs;Sh=1;var e=X(),t=Ie(),r=St(),a=Lu(),i=Object.isExtensible,n=e(function(){});return hs=n||a?function(l){return!t(l)||a&&r(l)==="ArrayBuffer"?!1:i?i(l):!0}:i,hs}var bs,wh;function Lr(){if(wh)return bs;wh=1;var e=X();return bs=!e(function(){return Object.isExtensible(Object.preventExtensions({}))}),bs}var Rh;function br(){if(Rh)return fs.exports;Rh=1;var e=I(),t=te(),r=Gr(),a=Ie(),i=Ve(),n=et().f,o=cr(),l=Ru(),s=Fu(),u=Ir(),d=Lr(),c=!1,p=u("meta"),v=0,m=function(y){n(y,p,{value:{objectID:"O"+v++,weakData:{}}})},h=function(y,_){if(!a(y))return typeof y=="symbol"?y:(typeof y=="string"?"S":"P")+y;if(!i(y,p)){if(!s(y))return"F";if(!_)return"E";m(y)}return y[p].objectID},b=function(y,_){if(!i(y,p)){if(!s(y))return!0;if(!_)return!1;m(y)}return y[p].weakData},f=function(y){return d&&c&&s(y)&&!i(y,p)&&m(y),y},g=function(){k.enable=function(){},c=!0;var y=o.f,_=t([].splice),S={};S[p]=1,y(S).length&&(o.f=function(R){for(var w=y(R),E=0,P=w.length;E1?arguments[1]:void 0),M;M=M?M.next:P.first;)for(A(M.value,M.key,this);M&&M.removed;)M=M.previous},has:function(E){return!!R(this,E)}}),r(y,f?{get:function(E){var P=R(this,E);return P&&P.value},set:function(E,P){return S(this,E===0?0:E,P)}}:{add:function(E){return S(this,E=E===0?0:E,E)}}),d&&t(y,"size",{configurable:!0,get:function(){return _(this).size}}),k},setStrong:function(h,b,f){var g=b+" Iterator",k=m(b),y=m(g);l(h,b,function(_,S){v(this,{type:g,target:_,state:k(_),kind:S,last:null})},function(){for(var _=y(this),S=_.kind,R=_.last;R&&R.removed;)R=R.previous;return!_.target||!(_.last=R=R?R.next:_.state.first)?(_.target=null,s(void 0,!0)):s(S==="keys"?R.key:S==="values"?R.value:[R.key,R.value],!1)},f?"entries":"values",!f,!0),u(b)}},ys}var Mh;function Ij(){if(Mh)return yh;Mh=1;var e=Ia(),t=FP();return e("Map",function(r){return function(){return r(this,arguments.length?arguments[0]:void 0)}},t),yh}var Ph;function jj(){return Ph||(Ph=1,Ij()),kh}var Th={},_s,Ih;function VP(){if(Ih)return _s;Ih=1;var e=te(),t=Map.prototype;return _s={Map,set:e(t.set),get:e(t.get),has:e(t.has),remove:e(t.delete),proto:t},_s}var jh;function Cj(){if(jh)return Th;jh=1;var e=I(),t=te(),r=Fe(),a=rt(),i=ct(),n=VP(),o=Ye(),l=X(),s=n.Map,u=n.has,d=n.get,c=n.set,p=t([].push),v=o||l(function(){return s.groupBy("ab",function(m){return m}).get("a").length!==1});return e({target:"Map",stat:!0,forced:o||v},{groupBy:function(h,b){a(h),r(b);var f=new s,g=0;return i(h,function(k){var y=b(k,g++);u(f,y)?p(d(f,y),k):c(f,y,[k])}),f}}),Th}var Ch={},Ss,Oh;function BP(){if(Oh)return Ss;Oh=1;var e=Math.log;return Ss=Math.log1p||function(r){var a=+r;return a>-1e-8&&a<1e-8?a-a*a/2:e(1+a)},Ss}var zh;function Oj(){if(zh)return Ch;zh=1;var e=I(),t=BP(),r=Math.acosh,a=Math.log,i=Math.sqrt,n=Math.LN2,o=!r||Math.floor(r(Number.MAX_VALUE))!==710||r(1/0)!==1/0;return e({target:"Math",stat:!0,forced:o},{acosh:function(s){var u=+s;return u<1?NaN:u>9490626562425156e-8?a(u)+n:t(u-1+i(u-1)*i(u+1))}}),Ch}var Dh={},xh;function zj(){if(xh)return Dh;xh=1;var e=I(),t=Math.asinh,r=Math.log,a=Math.sqrt;function i(o){var l=+o;return!isFinite(l)||l===0?l:l<0?-i(-l):r(l+a(l*l+1))}var n=!(t&&1/t(0)>0);return e({target:"Math",stat:!0,forced:n},{asinh:i}),Dh}var qh={},Nh;function Dj(){if(Nh)return qh;Nh=1;var e=I(),t=Math.atanh,r=Math.log,a=!(t&&1/t(-0)<0);return e({target:"Math",stat:!0,forced:a},{atanh:function(n){var o=+n;return o===0?o:r((1+o)/(1-o))/2}}),qh}var Lh={},Fh;function xj(){if(Fh)return Lh;Fh=1;var e=I(),t=xu(),r=Math.abs,a=Math.pow;return e({target:"Math",stat:!0},{cbrt:function(n){var o=+n;return t(o)*a(r(o),1/3)}}),Lh}var Vh={},Bh;function qj(){if(Bh)return Vh;Bh=1;var e=I(),t=Math.floor,r=Math.log,a=Math.LOG2E;return e({target:"Math",stat:!0},{clz32:function(n){var o=n>>>0;return o?31-t(r(o+.5)*a):32}}),Vh}var Uh={},ws,$h;function ja(){if($h)return ws;$h=1;var e=Math.expm1,t=Math.exp;return ws=!e||e(10)>22025.465794806718||e(10)<22025.465794806718||e(-2e-17)!==-2e-17?function(a){var i=+a;return i===0?i:i>-1e-6&&i<1e-6?i+i*i/2:t(i)-1}:e,ws}var Hh;function Nj(){if(Hh)return Uh;Hh=1;var e=I(),t=ja(),r=Math.cosh,a=Math.abs,i=Math.E,n=!r||r(710)===1/0;return e({target:"Math",stat:!0,forced:n},{cosh:function(l){var s=t(a(l)-1)+1;return(s+1/(s*i*i))*(i/2)}}),Uh}var Kh={},Wh;function Lj(){if(Wh)return Kh;Wh=1;var e=I(),t=ja();return e({target:"Math",stat:!0,forced:t!==Math.expm1},{expm1:t}),Kh}var Gh={},Yh;function Fj(){if(Yh)return Gh;Yh=1;var e=I(),t=TP();return e({target:"Math",stat:!0},{fround:t}),Gh}var Qh={},Zh;function Vj(){if(Zh)return Qh;Zh=1;var e=I(),t=PP(),r=.0009765625,a=65504,i=6103515625e-14;return e({target:"Math",stat:!0},{f16round:function(o){return t(o,r,a,i)}}),Qh}var Jh={},Xh;function Bj(){if(Xh)return Jh;Xh=1;var e=I(),t=Math.hypot,r=Math.abs,a=Math.sqrt,i=!!t&&t(1/0,NaN)!==1/0;return e({target:"Math",stat:!0,arity:2,forced:i},{hypot:function(o,l){for(var s=0,u=0,d=arguments.length,c=0,p,v;u0?(v=p/c,s+=v*v):s+=p;return c===1/0?1/0:c*a(s)}}),Jh}var eb={},tb;function Uj(){if(tb)return eb;tb=1;var e=I(),t=X(),r=Math.imul,a=t(function(){return r(4294967295,5)!==-5||r.length!==2});return e({target:"Math",stat:!0,forced:a},{imul:function(n,o){var l=65535,s=+n,u=+o,d=l&s,c=l&u;return 0|d*c+((l&s>>>16)*c+d*(l&u>>>16)<<16>>>0)}}),eb}var rb={},Rs,ab;function UP(){if(ab)return Rs;ab=1;var e=Math.log,t=Math.LOG10E;return Rs=Math.log10||function(a){return e(a)*t},Rs}var ib;function $j(){if(ib)return rb;ib=1;var e=I(),t=UP();return e({target:"Math",stat:!0},{log10:t}),rb}var nb={},ob;function Hj(){if(ob)return nb;ob=1;var e=I(),t=BP();return e({target:"Math",stat:!0},{log1p:t}),nb}var sb={},lb;function Kj(){if(lb)return sb;lb=1;var e=I(),t=IP();return e({target:"Math",stat:!0},{log2:t}),sb}var ub={},db;function Wj(){if(db)return ub;db=1;var e=I(),t=xu();return e({target:"Math",stat:!0},{sign:t}),ub}var cb={},pb;function Gj(){if(pb)return cb;pb=1;var e=I(),t=X(),r=ja(),a=Math.abs,i=Math.exp,n=Math.E,o=t(function(){return Math.sinh(-2e-17)!==-2e-17});return e({target:"Math",stat:!0,forced:o},{sinh:function(s){var u=+s;return a(u)<1?(r(u)-r(-u))/2:(i(u-1)-i(-u-1))*(n/2)}}),cb}var mb={},vb;function Yj(){if(vb)return mb;vb=1;var e=I(),t=te(),r=ct(),a=RangeError,i=TypeError,n=1/0,o=NaN,l=Math.abs,s=Math.pow,u=t([].push),d=s(2,1023),c=s(2,53)-1,p=Number.MAX_VALUE,v=s(2,971),m={},h={},b={},f={},g={},k=function(y,_){var S=y+_,R=_-(S-y);return{hi:S,lo:R}};return e({target:"Math",stat:!0},{sumPrecise:function(_){var S=[],R=0,w=f;switch(r(_,function(U){if(++R>=c)throw new a("Maximum allowed index exceeded");if(typeof U!="number")throw new i("Value is not a number");w!==m&&(U!==U?w=m:U===n?w=w===h?m:b:U===-n?w=w===b?m:h:(U!==0||1/U===n)&&(w===f||w===g)&&(w=g,u(S,U)))}),w){case m:return o;case h:return-n;case b:return n;case f:return-0}for(var E=[],P=0,A,M,T,C,z,q,V=0;V=0?E[D]:0;if(D--,l(P)>1||P>0&&$>0||P<0&&$<0)return P>0?n:-n;if(T=k(P*d,$/2),C=T.hi,z=T.lo,z*=2,l(2*C)===n)return C>0?C===d&&z===-(v/2)&&D>=0&&E[D]<0?p:n:C===-d&&z===v/2&&D>=0&&E[D]>0?-p:-n;z!==0&&(E[++D]=z,z=0),C*=2}for(;D>=0&&(T=k(C,E[D--]),C=T.hi,z=T.lo,z===0););return D>=0&&(z<0&&E[D]<0||z>0&&E[D]>0)&&(M=z*2,A=C+M,M===A-C&&(C=A)),C}}),mb}var fb={},gb;function Qj(){if(gb)return fb;gb=1;var e=I(),t=ja(),r=Math.exp;return e({target:"Math",stat:!0},{tanh:function(i){var n=+i,o=t(n),l=t(-n);return o===1/0?1:l===1/0?-1:(o-l)/(r(n)+r(-n))}}),fb}var hb={},bb;function Zj(){if(bb)return hb;bb=1;var e=Pt();return e(Math,"Math",!0),hb}var kb={},yb;function Jj(){if(yb)return kb;yb=1;var e=I(),t=aP();return e({target:"Math",stat:!0},{trunc:t}),kb}var _b={},Es,Sb;function Ca(){if(Sb)return Es;Sb=1;var e=te();return Es=e(1.1.valueOf),Es}var As,wb;function aa(){return wb||(wb=1,As=` +\v\f\r                 \u2028\u2029\uFEFF`),As}var Ms,Rb;function Fr(){if(Rb)return Ms;Rb=1;var e=te(),t=rt(),r=xe(),a=aa(),i=e("".replace),n=RegExp("^["+a+"]+"),o=RegExp("(^|[^"+a+"])["+a+"]+$"),l=function(s){return function(u){var d=r(t(u));return s&1&&(d=i(d,n,"")),s&2&&(d=i(d,o,"$1")),d}};return Ms={start:l(1),end:l(2),trim:l(3)},Ms}var Eb;function Xj(){if(Eb)return _b;Eb=1;var e=I(),t=Ye(),r=Ae(),a=se(),i=ga(),n=te(),o=Qr(),l=Ve(),s=vr(),u=At(),d=ur(),c=pa(),p=X(),v=cr().f,m=gt().f,h=et().f,b=Ca(),f=Fr().trim,g="Number",k=a[g],y=i[g],_=k.prototype,S=a.TypeError,R=n("".slice),w=n("".charCodeAt),E=function(z){var q=c(z,"number");return typeof q=="bigint"?q:P(q)},P=function(z){var q=c(z,"number"),V,F,j,O,D,$,U,ae;if(d(q))throw new S("Cannot convert a Symbol value to a number");if(typeof q=="string"&&q.length>2){if(q=f(q),V=w(q,0),V===43||V===45){if(F=w(q,2),F===88||F===120)return NaN}else if(V===48){switch(w(q,1)){case 66:case 98:j=2,O=49;break;case 79:case 111:j=8,O=55;break;default:return+q}for(D=R(q,2),$=D.length,U=0;U<$;U++)if(ae=w(D,U),ae<48||ae>O)return NaN;return parseInt(D,j)}}return+q},A=o(g,!k(" 0o1")||!k("0b1")||k("+0x1")),M=function(z){return u(_,z)&&p(function(){b(z)})},T=function(q){var V=arguments.length<1?0:k(E(q));return M(this)?s(Object(V),this,T):V};T.prototype=_,A&&!t&&(_.constructor=T),e({global:!0,constructor:!0,wrap:!0,forced:A},{Number:T});var C=function(z,q){for(var V=r?v(q):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,fromString,range".split(","),F=0,j;V.length>F;F++)l(q,j=V[F])&&!l(z,j)&&h(z,j,m(q,j))};return t&&y&&C(i[g],y),(A||t)&&C(i[g],k),_b}var Ab={},Mb;function eC(){if(Mb)return Ab;Mb=1;var e=I();return e({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{EPSILON:Math.pow(2,-52)}),Ab}var Pb={},Ps,Tb;function tC(){if(Tb)return Ps;Tb=1;var e=se(),t=e.isFinite;return Ps=Number.isFinite||function(a){return typeof a=="number"&&t(a)},Ps}var Ib;function rC(){if(Ib)return Pb;Ib=1;var e=I(),t=tC();return e({target:"Number",stat:!0},{isFinite:t}),Pb}var jb={},Ts,Cb;function Vu(){if(Cb)return Ts;Cb=1;var e=Ie(),t=Math.floor;return Ts=Number.isInteger||function(a){return!e(a)&&isFinite(a)&&t(a)===a},Ts}var Ob;function aC(){if(Ob)return jb;Ob=1;var e=I(),t=Vu();return e({target:"Number",stat:!0},{isInteger:t}),jb}var zb={},Db;function iC(){if(Db)return zb;Db=1;var e=I();return e({target:"Number",stat:!0},{isNaN:function(r){return r!==r}}),zb}var xb={},qb;function nC(){if(qb)return xb;qb=1;var e=I(),t=Vu(),r=Math.abs;return e({target:"Number",stat:!0},{isSafeInteger:function(i){return t(i)&&r(i)<=9007199254740991}}),xb}var Nb={},Lb;function oC(){if(Lb)return Nb;Lb=1;var e=I();return e({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MAX_SAFE_INTEGER:9007199254740991}),Nb}var Fb={},Vb;function sC(){if(Vb)return Fb;Vb=1;var e=I();return e({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MIN_SAFE_INTEGER:-9007199254740991}),Fb}var Bb={},Is,Ub;function $P(){if(Ub)return Is;Ub=1;var e=se(),t=X(),r=te(),a=xe(),i=Fr().trim,n=aa(),o=r("".charAt),l=e.parseFloat,s=e.Symbol,u=s&&s.iterator,d=1/l(n+"-0")!==-1/0||u&&!t(function(){l(Object(u))});return Is=d?function(p){var v=i(a(p)),m=l(v);return m===0&&o(v,0)==="-"?-0:m}:l,Is}var $b;function lC(){if($b)return Bb;$b=1;var e=I(),t=$P();return e({target:"Number",stat:!0,forced:Number.parseFloat!==t},{parseFloat:t}),Bb}var Hb={},js,Kb;function HP(){if(Kb)return js;Kb=1;var e=se(),t=X(),r=te(),a=xe(),i=Fr().trim,n=aa(),o=e.parseInt,l=e.Symbol,s=l&&l.iterator,u=/^[+-]?0x/i,d=r(u.exec),c=o(n+"08")!==8||o(n+"0x16")!==22||s&&!t(function(){o(Object(s))});return js=c?function(v,m){var h=i(a(v));return o(h,m>>>0||(d(u,h)?16:10))}:o,js}var Wb;function uC(){if(Wb)return Hb;Wb=1;var e=I(),t=HP();return e({target:"Number",stat:!0,forced:Number.parseInt!==t},{parseInt:t}),Hb}var Gb={},Yb;function dC(){if(Yb)return Gb;Yb=1;var e=I(),t=te(),r=it(),a=Ca(),i=Ma(),n=UP(),o=X(),l=RangeError,s=String,u=isFinite,d=Math.abs,c=Math.floor,p=Math.pow,v=Math.round,m=t(1.1.toExponential),h=t(i),b=t("".slice),f=m(-69e-12,4)==="-6.9000e-11"&&m(1.255,2)==="1.25e+0"&&m(12345,3)==="1.235e+4"&&m(25,0)==="3e+1",g=function(){return o(function(){m(1,1/0)})&&o(function(){m(1,-1/0)})},k=function(){return!o(function(){m(1/0,1/0),m(NaN,1/0)})},y=!f||!g()||!k();return e({target:"Number",proto:!0,forced:y},{toExponential:function(S){var R=a(this);if(S===void 0)return m(R);var w=r(S);if(!u(R))return String(R);if(w<0||w>20)throw new l("Incorrect fraction digits");if(f)return m(R,w);var E="",P,A,M,T;if(R<0&&(E="-",R=-R),R===0)A=0,P=h("0",w+1);else{var C=n(R);A=c(C);var z=p(10,A-w),q=v(R/z);2*R>=(2*q+1)*z&&(q+=1),q>=p(10,w+1)&&(q/=10,A+=1),P=s(q)}return w!==0&&(P=b(P,0,1)+"."+b(P,1)),A===0?(M="+",T="0"):(M=A>0?"+":"-",T=s(d(A))),P+="e"+M+T,E+P}}),Gb}var Qb={},Zb;function cC(){if(Zb)return Qb;Zb=1;var e=I(),t=te(),r=it(),a=Ca(),i=Ma(),n=X(),o=RangeError,l=String,s=Math.floor,u=t(i),d=t("".slice),c=t(1.1.toFixed),p=function(g,k,y){return k===0?y:k%2===1?p(g,k-1,y*g):p(g*g,k/2,y)},v=function(g){for(var k=0,y=g;y>=4096;)k+=12,y/=4096;for(;y>=2;)k+=1,y/=2;return k},m=function(g,k,y){for(var _=-1,S=y;++_<6;)S+=k*g[_],g[_]=S%1e7,S=s(S/1e7)},h=function(g,k){for(var y=6,_=0;--y>=0;)_+=g[y],g[y]=s(_/k),_=_%k*1e7},b=function(g){for(var k=6,y="";--k>=0;)if(y!==""||k===0||g[k]!==0){var _=l(g[k]);y=y===""?_:y+u("0",7-_.length)+_}return y},f=n(function(){return c(8e-5,3)!=="0.000"||c(.9,0)!=="1"||c(1.255,2)!=="1.25"||c(0xde0b6b3a7640080,0)!=="1000000000000000128"})||!n(function(){c({})});return e({target:"Number",proto:!0,forced:f},{toFixed:function(k){var y=a(this),_=r(k),S=[0,0,0,0,0,0],R="",w="0",E,P,A,M;if(_<0||_>20)throw new o("Incorrect fraction digits");if(y!==y)return"NaN";if(y<=-1e21||y>=1e21)return l(y);if(y<0&&(R="-",y=-y),y>1e-21)if(E=v(y*p(2,69,1))-69,P=E<0?y*p(2,-E,1):y/p(2,E,1),P*=4503599627370496,E=52-E,E>0){for(m(S,0,P),A=_;A>=7;)m(S,1e7,0),A-=7;for(m(S,p(10,A,1),0),A=E-1;A>=23;)h(S,1<<23),A-=23;h(S,1<0?(M=w.length,w=R+(M<=_?"0."+u("0",_-M)+w:d(w,0,M-_)+"."+d(w,M-_))):w=R+w,w}}),Qb}var Jb={},Xb;function pC(){if(Xb)return Jb;Xb=1;var e=I(),t=te(),r=X(),a=Ca(),i=t(1.1.toPrecision),n=r(function(){return i(1,void 0)!=="1"})||!r(function(){i({})});return e({target:"Number",proto:!0,forced:n},{toPrecision:function(l){return l===void 0?i(a(this)):i(a(this),l)}}),Jb}var ek={},Cs,tk;function KP(){if(tk)return Cs;tk=1;var e=Ae(),t=te(),r=ye(),a=X(),i=Zr(),n=fa(),o=da(),l=Ge(),s=Mr(),u=Object.assign,d=Object.defineProperty,c=t([].concat);return Cs=!u||a(function(){if(e&&u({b:1},u(d({},"a",{enumerable:!0,get:function(){d(this,"b",{value:3,enumerable:!1})}}),{b:2})).b!==1)return!0;var p={},v={},m=Symbol("assign detection"),h="abcdefghijklmnopqrst";return p[m]=7,h.split("").forEach(function(b){v[b]=b}),u({},p)[m]!==7||i(u({},v)).join("")!==h})?function(v,m){for(var h=l(v),b=arguments.length,f=1,g=n.f,k=o.f;b>f;)for(var y=s(arguments[f++]),_=g?c(i(y),g(y)):i(y),S=_.length,R=0,w;S>R;)w=_[R++],(!e||r(k,y,w))&&(h[w]=y[w]);return h}:u,Cs}var rk;function mC(){if(rk)return ek;rk=1;var e=I(),t=KP();return e({target:"Object",stat:!0,arity:2,forced:Object.assign!==t},{assign:t}),ek}var ak={},ik;function vC(){if(ik)return ak;ik=1;var e=I(),t=Ae(),r=bt();return e({target:"Object",stat:!0,sham:!t},{create:r}),ak}var nk={},Os,ok;function Oa(){if(ok)return Os;ok=1;var e=Ye(),t=se(),r=X(),a=Du();return Os=e||!r(function(){if(!(a&&a<535)){var i=Math.random();__defineSetter__.call(null,i,function(){}),delete t[i]}}),Os}var sk;function fC(){if(sk)return nk;sk=1;var e=I(),t=Ae(),r=Oa(),a=Fe(),i=Ge(),n=et();return t&&e({target:"Object",proto:!0,forced:r},{__defineGetter__:function(l,s){n.f(i(this),l,{get:a(s),enumerable:!0,configurable:!0})}}),nk}var lk={},uk;function gC(){if(uk)return lk;uk=1;var e=I(),t=Ae(),r=wu().f;return e({target:"Object",stat:!0,forced:Object.defineProperties!==r,sham:!t},{defineProperties:r}),lk}var dk={},ck;function hC(){if(ck)return dk;ck=1;var e=I(),t=Ae(),r=et().f;return e({target:"Object",stat:!0,forced:Object.defineProperty!==r,sham:!t},{defineProperty:r}),dk}var pk={},mk;function bC(){if(mk)return pk;mk=1;var e=I(),t=Ae(),r=Oa(),a=Fe(),i=Ge(),n=et();return t&&e({target:"Object",proto:!0,forced:r},{__defineSetter__:function(l,s){n.f(i(this),l,{set:a(s),enumerable:!0,configurable:!0})}}),pk}var vk={},zs,fk;function WP(){if(fk)return zs;fk=1;var e=Ae(),t=X(),r=te(),a=Mt(),i=Zr(),n=mt(),o=da().f,l=r(o),s=r([].push),u=e&&t(function(){var c=Object.create(null);return c[2]=2,!l(c,2)}),d=function(c){return function(p){for(var v=n(p),m=i(v),h=u&&a(v)===null,b=m.length,f=0,g=[],k;b>f;)k=m[f++],(!e||(h?k in v:l(v,k)))&&s(g,c?[k,v[k]]:v[k]);return g}};return zs={entries:d(!0),values:d(!1)},zs}var gk;function kC(){if(gk)return vk;gk=1;var e=I(),t=WP().entries;return e({target:"Object",stat:!0},{entries:function(a){return t(a)}}),vk}var hk={},bk;function yC(){if(bk)return hk;bk=1;var e=I(),t=Lr(),r=X(),a=Ie(),i=br().onFreeze,n=Object.freeze,o=r(function(){n(1)});return e({target:"Object",stat:!0,forced:o,sham:!t},{freeze:function(s){return n&&a(s)?n(i(s)):s}}),hk}var kk={},yk;function _C(){if(yk)return kk;yk=1;var e=I(),t=ct(),r=Gt();return e({target:"Object",stat:!0},{fromEntries:function(i){var n={};return t(i,function(o,l){r(n,o,l)},{AS_ENTRIES:!0}),n}}),kk}var _k={},Sk;function SC(){if(Sk)return _k;Sk=1;var e=I(),t=X(),r=mt(),a=gt().f,i=Ae(),n=!i||t(function(){a(1)});return e({target:"Object",stat:!0,forced:n,sham:!i},{getOwnPropertyDescriptor:function(l,s){return a(r(l),s)}}),_k}var wk={},Rk;function wC(){if(Rk)return wk;Rk=1;var e=I(),t=Ae(),r=_u(),a=mt(),i=gt(),n=Gt();return e({target:"Object",stat:!0,sham:!t},{getOwnPropertyDescriptors:function(l){for(var s=a(l),u=i.f,d=r(s),c={},p=0,v,m;d.length>p;)m=u(s,v=d[p++]),m!==void 0&&n(c,v,m);return c}}),wk}var Ek={},Ak;function RC(){if(Ak)return Ek;Ak=1;var e=I(),t=X(),r=Ru().f,a=t(function(){return!Object.getOwnPropertyNames(1)});return e({target:"Object",stat:!0,forced:a},{getOwnPropertyNames:r}),Ek}var Mk={},Pk;function EC(){if(Pk)return Mk;Pk=1;var e=I(),t=X(),r=Ge(),a=Mt(),i=Mu(),n=t(function(){a(1)});return e({target:"Object",stat:!0,forced:n,sham:!i},{getPrototypeOf:function(l){return a(r(l))}}),Mk}var Tk={},Ik;function AC(){if(Ik)return Tk;Ik=1;var e=I(),t=Gt(),r=Le(),a=te(),i=Fe(),n=rt(),o=ir(),l=ct(),s=X(),u=Object.groupBy,d=r("Object","create"),c=a([].push),p=!u||s(function(){return u("ab",function(v){return v}).a.length!==1});return e({target:"Object",stat:!0,forced:p},{groupBy:function(m,h){n(m),i(h);var b=d(null),f=0;return l(m,function(g){var k=o(h(g,f++));k in b?c(b[k],g):t(b,k,[g])}),b}}),Tk}var jk={},Ck;function MC(){if(Ck)return jk;Ck=1;var e=I(),t=Ve();return e({target:"Object",stat:!0},{hasOwn:t}),jk}var Ok={},Ds,zk;function GP(){return zk||(zk=1,Ds=Object.is||function(t,r){return t===r?t!==0||1/t===1/r:t!==t&&r!==r}),Ds}var Dk;function PC(){if(Dk)return Ok;Dk=1;var e=I(),t=GP();return e({target:"Object",stat:!0},{is:t}),Ok}var xk={},qk;function TC(){if(qk)return xk;qk=1;var e=I(),t=Fu();return e({target:"Object",stat:!0,forced:Object.isExtensible!==t},{isExtensible:t}),xk}var Nk={},Lk;function IC(){if(Lk)return Nk;Lk=1;var e=I(),t=X(),r=Ie(),a=St(),i=Lu(),n=Object.isFrozen,o=i||t(function(){});return e({target:"Object",stat:!0,forced:o},{isFrozen:function(s){return!r(s)||i&&a(s)==="ArrayBuffer"?!0:n?n(s):!1}}),Nk}var Fk={},Vk;function jC(){if(Vk)return Fk;Vk=1;var e=I(),t=X(),r=Ie(),a=St(),i=Lu(),n=Object.isSealed,o=i||t(function(){});return e({target:"Object",stat:!0,forced:o},{isSealed:function(s){return!r(s)||i&&a(s)==="ArrayBuffer"?!0:n?n(s):!1}}),Fk}var Bk={},Uk;function CC(){if(Uk)return Bk;Uk=1;var e=I(),t=Ge(),r=Zr(),a=X(),i=a(function(){r(1)});return e({target:"Object",stat:!0,forced:i},{keys:function(o){return r(t(o))}}),Bk}var $k={},Hk;function OC(){if(Hk)return $k;Hk=1;var e=I(),t=Ae(),r=Oa(),a=Ge(),i=ir(),n=Mt(),o=gt().f;return t&&e({target:"Object",proto:!0,forced:r},{__lookupGetter__:function(s){var u=a(this),d=i(s),c;do if(c=o(u,d))return c.get;while(u=n(u))}}),$k}var Kk={},Wk;function zC(){if(Wk)return Kk;Wk=1;var e=I(),t=Ae(),r=Oa(),a=Ge(),i=ir(),n=Mt(),o=gt().f;return t&&e({target:"Object",proto:!0,forced:r},{__lookupSetter__:function(s){var u=a(this),d=i(s),c;do if(c=o(u,d))return c.set;while(u=n(u))}}),Kk}var Gk={},Yk;function DC(){if(Yk)return Gk;Yk=1;var e=I(),t=Ie(),r=br().onFreeze,a=Lr(),i=X(),n=Object.preventExtensions,o=i(function(){n(1)});return e({target:"Object",stat:!0,forced:o,sham:!a},{preventExtensions:function(s){return n&&t(s)?n(r(s)):s}}),Gk}var Qk={},Zk;function xC(){if(Zk)return Qk;Zk=1;var e=Ae(),t=ot(),r=Ie(),a=dP(),i=Ge(),n=rt(),o=Object.getPrototypeOf,l=Object.setPrototypeOf,s=Object.prototype,u="__proto__";if(e&&o&&l&&!(u in s))try{t(s,u,{configurable:!0,get:function(){return o(i(this))},set:function(c){var p=n(this);a(c)&&r(p)&&l(p,c)}})}catch{}return Qk}var Jk={},Xk;function qC(){if(Xk)return Jk;Xk=1;var e=I(),t=Ie(),r=br().onFreeze,a=Lr(),i=X(),n=Object.seal,o=i(function(){n(1)});return e({target:"Object",stat:!0,forced:o,sham:!a},{seal:function(s){return n&&t(s)?n(r(s)):s}}),Jk}var ey={},ty;function NC(){if(ty)return ey;ty=1;var e=I(),t=Bt();return e({target:"Object",stat:!0},{setPrototypeOf:t}),ey}var ry={},xs,ay;function LC(){if(ay)return xs;ay=1;var e=Su(),t=Ct();return xs=e?{}.toString:function(){return"[object "+t(this)+"]"},xs}var iy;function FC(){if(iy)return ry;iy=1;var e=Su(),t=Qe(),r=LC();return e||t(Object.prototype,"toString",r,{unsafe:!0}),ry}var ny={},oy;function VC(){if(oy)return ny;oy=1;var e=I(),t=WP().values;return e({target:"Object",stat:!0},{values:function(a){return t(a)}}),ny}var sy={},ly;function BC(){if(ly)return sy;ly=1;var e=I(),t=$P();return e({global:!0,forced:parseFloat!==t},{parseFloat:t}),sy}var uy={},dy;function UC(){if(dy)return uy;dy=1;var e=I(),t=HP();return e({global:!0,forced:parseInt!==t},{parseInt:t}),uy}var cy={},py={},qs,my;function Bu(){if(my)return qs;my=1;var e=mr(),t=dr(),r=TypeError;return qs=function(a){if(e(a))return a;throw new r(t(a)+" is not a constructor")},qs}var Ns,vy;function za(){if(vy)return Ns;vy=1;var e=Re(),t=Bu(),r=Jt(),a=je(),i=a("species");return Ns=function(n,o){var l=e(n).constructor,s;return l===void 0||r(s=e(l)[i])?o:t(s)},Ns}var Ls,fy;function Vt(){if(fy)return Ls;fy=1;var e=TypeError;return Ls=function(t,r){if(t1?a(arguments,1):[],p=i.f(this),v=o(function(){return r(n(d),void 0,c)});return(v.error?p.reject:p.resolve)(v.value),p.promise}}),Gy}var Qy={},Zy;function iO(){if(Zy)return Qy;Zy=1;var e=I(),t=rr();return e({target:"Promise",stat:!0},{withResolvers:function(){var a=t.f(this);return{promise:a.promise,resolve:a.resolve,reject:a.reject}}}),Qy}var Jy={},el,Xy;function eT(){if(Xy)return el;Xy=1;var e=se(),t=ca(),r=Ue(),a=bt(),i=Mt(),n=Qe(),o=je(),l=Ye(),s="USE_FUNCTION_CONSTRUCTOR",u=o("asyncIterator"),d=e.AsyncIterator,c=t.AsyncIteratorPrototype,p,v;if(c)p=c;else if(r(d))p=d.prototype;else if(t[s]||e[s])try{v=i(i(i(Function("return async function*(){}()")()))),i(v)===Object.prototype&&(p=v)}catch{}return p?l&&(p=a(p)):p={},r(p[u])||n(p,u,function(){return this}),el=p,el}var tl,e_;function tT(){if(e_)return tl;e_=1;var e=ye(),t=Re(),r=bt(),a=ft(),i=tr(),n=at(),o=yt(),l=Le(),s=eT(),u=hr(),d=l("Promise"),c="AsyncFromSyncIterator",p=n.set,v=n.getterFor(c),m=function(b,f,g,k,y){var _=b.done;d.resolve(b.value).then(function(S){f(u(S,_))},function(S){if(!_&&y)try{o(k,"throw",S)}catch(R){S=R}g(S)})},h=function(f){f.type=c,p(this,f)};return h.prototype=i(r(s),{next:function(){var f=v(this);return new d(function(g,k){var y=t(e(f.next,f.iterator));m(y,g,k,f.iterator,!0)})},return:function(){var b=v(this).iterator;return new d(function(f,g){var k=a(b,"return");if(k===void 0)return f(u(void 0,!0));var y=t(e(k,b));m(y,f,g,b)})}}),tl=h,tl}var rl,t_;function nO(){if(t_)return rl;t_=1;var e=ye(),t=tT(),r=Re(),a=zr(),i=Rt(),n=ft(),o=je(),l=o("asyncIterator");return rl=function(s,u){var d=arguments.length<2?n(s,l):u;return d?r(e(d,s)):new t(i(a(s)))},rl}var al,r_;function oO(){if(r_)return al;r_=1;var e=ye(),t=Le(),r=ft();return al=function(a,i,n,o){try{var l=r(a,"return");if(l)return t("Promise").resolve(e(l,a)).then(function(){i(n)},function(s){o(s)})}catch(s){return o(s)}i(n)},al}var il,a_;function sO(){if(a_)return il;a_=1;var e=ye(),t=Fe(),r=Re(),a=Ie(),i=gr(),n=Le(),o=Rt(),l=oO(),s=function(u){var d=u===0,c=u===1,p=u===2,v=u===3;return function(m,h,b){r(m);var f=h!==void 0;(f||!d)&&t(h);var g=o(m),k=n("Promise"),y=g.iterator,_=g.next,S=0;return new k(function(R,w){var E=function(A){l(y,w,A,w)},P=function(){try{if(f)try{i(S)}catch(A){E(A)}k.resolve(r(e(_,y))).then(function(A){try{if(r(A).done)d?(b.length=S,R(b)):R(v?!1:p||void 0);else{var M=A.value;try{if(f){var T=h(M,S),C=function(z){if(c)P();else if(p)z?P():l(y,R,!1,w);else if(d)try{b[S++]=z,P()}catch(q){E(q)}else z?l(y,R,v||M,w):P()};a(T)?k.resolve(T).then(C,E):C(T)}else b[S++]=M,P()}catch(z){E(z)}}}catch(z){w(z)}},w)}catch(A){w(A)}};P()})}};return il={toArray:s(0),forEach:s(1),every:s(2),some:s(3),find:s(4)},il}var nl,i_;function lO(){if(i_)return nl;i_=1;var e=Ot(),t=te(),r=Ge(),a=mr(),i=nO(),n=zr(),o=Rt(),l=fr(),s=ft(),u=Le(),d=EP(),c=je(),p=tT(),v=sO().toArray,m=c("asyncIterator"),h=t(d("Array","values")),b=t(h([]).next),f=function(){return new g(this)},g=function(k){this.iterator=h(k)};return g.prototype.next=function(){return b(this.iterator)},nl=function(y){var _=this,S=arguments.length,R=S>1?arguments[1]:void 0,w=S>2?arguments[2]:void 0;return new(u("Promise"))(function(E){var P=r(y);R!==void 0&&(R=e(R,w));var A=s(P,m),M=A?void 0:l(P)||f,T=a(_)?new _:[],C=A?i(P,A):new p(o(n(P,M)));E(v(C,R,T))})},nl}var n_;function uO(){if(n_)return Jy;n_=1;var e=I(),t=lO(),r=X(),a=Array.fromAsync,i=!a||r(function(){var n=0;return a.call(function(){return n++,[]},{length:0}),n!==1});return e({target:"Array",stat:!0,forced:i},{fromAsync:t}),Jy}var o_={},s_;function dO(){if(s_)return o_;s_=1;var e=I(),t=Ae(),r=Le(),a=Fe(),i=Dt(),n=Qe(),o=tr(),l=ot(),s=je(),u=at(),d=xP(),c=Wt(),p=r("Promise"),v=r("SuppressedError"),m=ReferenceError,h=s("asyncDispose"),b=s("toStringTag"),f="AsyncDisposableStack",g=u.set,k=u.getterFor(f),y="async-dispose",_="disposed",S="pending",R=function(A){var M=k(A);if(M.state===_)throw new m(f+" already disposed");return M},w=function(){g(i(this,E),{type:f,state:S,stack:[]}),t||(this.disposed=!1)},E=w.prototype;o(E,{disposeAsync:function(){var M=this;return new p(function(T,C){var z=k(M);if(z.state===_)return T(void 0);z.state=_,t||(M.disposed=!0);var q=z.stack,V=q.length,F=!1,j,O=function($){F?j=new v($,j):(F=!0,j=$),D()},D=function(){if(V){var $=q[--V];q[V]=null;try{p.resolve($()).then(D,O)}catch(U){O(U)}}else z.stack=null,F?C(j):T(void 0)};D()})},use:function(M){return d(R(this),M,y),M},adopt:function(M,T){var C=R(this);return a(T),d(C,void 0,y,function(){return T(M)}),M},defer:function(M){var T=R(this);a(M),d(T,void 0,y,M)},move:function(){var M=R(this),T=new w;return k(T).stack=M.stack,M.stack=[],M.state=_,t||(this.disposed=!0),T}}),t&&l(E,"disposed",{configurable:!0,get:function(){return k(this).state===_}}),n(E,h,E.disposeAsync,{name:"disposeAsync"}),n(E,b,f,{nonWritable:!0});var P=c&&c<136;return e({global:!0,constructor:!0,forced:P},{AsyncDisposableStack:w}),o_}var l_={},u_;function cO(){if(u_)return l_;u_=1;var e=ye(),t=Qe(),r=Le(),a=ft(),i=Ve(),n=je(),o=eT(),l=n("asyncDispose"),s=r("Promise");return i(o,l)||t(o,l,function(){var u=this;return new s(function(d,c){var p=a(u,"return");p?s.resolve(e(p,u)).then(function(){d(void 0)},c):d(void 0)})}),l_}var d_={},c_;function pO(){if(c_)return d_;c_=1;var e=I(),t=zt(),r=Fe(),a=Re(),i=X(),n=!i(function(){Reflect.apply(function(){})});return e({target:"Reflect",stat:!0,forced:n},{apply:function(l,s,u){return t(r(l),s,a(u))}}),d_}var p_={},m_;function mO(){if(m_)return p_;m_=1;var e=I(),t=Le(),r=zt(),a=qP(),i=Bu(),n=Re(),o=Ie(),l=bt(),s=X(),u=t("Reflect","construct"),d=Object.prototype,c=[].push,p=s(function(){function h(){}return!(u(function(){},[],h)instanceof h)}),v=!s(function(){u(function(){})}),m=p||v;return e({target:"Reflect",stat:!0,forced:m,sham:m},{construct:function(b,f){i(b),n(f);var g=arguments.length<3?b:i(arguments[2]);if(v&&!p)return u(b,f,g);if(b===g){switch(f.length){case 0:return new b;case 1:return new b(f[0]);case 2:return new b(f[0],f[1]);case 3:return new b(f[0],f[1],f[2]);case 4:return new b(f[0],f[1],f[2],f[3])}var k=[null];return r(c,k,f),new(r(a,b,k))}var y=g.prototype,_=l(o(y)?y:d),S=r(b,_,f);return o(S)?S:_}}),p_}var v_={},f_;function vO(){if(f_)return v_;f_=1;var e=I(),t=Ae(),r=Re(),a=ir(),i=et(),n=X(),o=n(function(){Reflect.defineProperty(i.f({},1,{value:1}),1,{value:2})});return e({target:"Reflect",stat:!0,forced:o,sham:!t},{defineProperty:function(s,u,d){r(s);var c=a(u);r(d);try{return i.f(s,c,d),!0}catch{return!1}}}),v_}var g_={},h_;function fO(){if(h_)return g_;h_=1;var e=I(),t=Re(),r=gt().f;return e({target:"Reflect",stat:!0},{deleteProperty:function(i,n){var o=r(t(i),n);return o&&!o.configurable?!1:delete i[n]}}),g_}var b_={},ol,k_;function rT(){if(k_)return ol;k_=1;var e=Ve();return ol=function(t){return t!==void 0&&(e(t,"value")||e(t,"writable"))},ol}var y_;function gO(){if(y_)return b_;y_=1;var e=I(),t=ye(),r=Ie(),a=Re(),i=rT(),n=gt(),o=Mt();function l(s,u){var d=arguments.length<3?s:arguments[2],c,p;if(a(s)===d)return s[u];if(c=n.f(s,u),c)return i(c)?c.value:c.get===void 0?void 0:t(c.get,d);if(r(p=o(s)))return l(p,u,d)}return e({target:"Reflect",stat:!0},{get:l}),b_}var __={},S_;function hO(){if(S_)return __;S_=1;var e=I(),t=Ae(),r=Re(),a=gt();return e({target:"Reflect",stat:!0,sham:!t},{getOwnPropertyDescriptor:function(n,o){return a.f(r(n),o)}}),__}var w_={},R_;function bO(){if(R_)return w_;R_=1;var e=I(),t=Re(),r=Mt(),a=Mu();return e({target:"Reflect",stat:!0,sham:!a},{getPrototypeOf:function(n){return r(t(n))}}),w_}var E_={},A_;function kO(){if(A_)return E_;A_=1;var e=I();return e({target:"Reflect",stat:!0},{has:function(r,a){return a in r}}),E_}var M_={},P_;function yO(){if(P_)return M_;P_=1;var e=I(),t=Re(),r=Fu();return e({target:"Reflect",stat:!0},{isExtensible:function(i){return t(i),r(i)}}),M_}var T_={},I_;function _O(){if(I_)return T_;I_=1;var e=I(),t=_u();return e({target:"Reflect",stat:!0},{ownKeys:t}),T_}var j_={},C_;function SO(){if(C_)return j_;C_=1;var e=I(),t=Le(),r=Re(),a=Lr();return e({target:"Reflect",stat:!0,sham:!a},{preventExtensions:function(n){r(n);try{var o=t("Object","preventExtensions");return o&&o(n),!0}catch{return!1}}}),j_}var O_={},z_;function wO(){if(z_)return O_;z_=1;var e=I(),t=ye(),r=Re(),a=Ie(),i=rT(),n=X(),o=et(),l=gt(),s=Mt(),u=It();function d(p,v,m){var h=arguments.length<4?p:arguments[3],b=l.f(r(p),v),f,g,k;if(!b){if(a(g=s(p)))return d(g,v,m,h);b=u(0)}if(i(b)){if(b.writable===!1||!a(h))return!1;if(f=l.f(h,v)){if(f.get||f.set||f.writable===!1)return!1;f.value=m,o.f(h,v,f)}else o.f(h,v,u(0,m))}else{if(k=b.set,k===void 0)return!1;t(k,h,m)}return!0}var c=n(function(){var p=function(){},v=o.f(new p,"a",{configurable:!0});return Reflect.set(p.prototype,"a",1,v)!==!1});return e({target:"Reflect",stat:!0,forced:c},{set:d}),O_}var D_={},x_;function RO(){if(x_)return D_;x_=1;var e=I(),t=Re(),r=cP(),a=Bt();return a&&e({target:"Reflect",stat:!0},{setPrototypeOf:function(n,o){t(n),r(o);try{return a(n,o),!0}catch{return!1}}}),D_}var q_={},N_;function EO(){if(N_)return q_;N_=1;var e=I(),t=se(),r=Pt();return e({global:!0},{Reflect:{}}),r(t.Reflect,"Reflect",!0),q_}var L_={},sl,F_;function qa(){if(F_)return sl;F_=1;var e=Ie(),t=St(),r=je(),a=r("match");return sl=function(i){var n;return e(i)&&((n=i[a])!==void 0?!!n:t(i)==="RegExp")},sl}var ll,V_;function aT(){if(V_)return ll;V_=1;var e=se(),t=X(),r=e.RegExp,a=!t(function(){var i=!0;try{r(".","d")}catch{i=!1}var n={},o="",l=i?"dgimsy":"gimsy",s=function(p,v){Object.defineProperty(n,p,{get:function(){return o+=v,!0}})},u={dotAll:"s",global:"g",ignoreCase:"i",multiline:"m",sticky:"y"};i&&(u.hasIndices="d");for(var d in u)s(d,u[d]);var c=Object.getOwnPropertyDescriptor(r.prototype,"flags").get.call(n);return c!==l||o!==l});return ll={correct:a},ll}var ul,B_;function Uu(){if(B_)return ul;B_=1;var e=Re();return ul=function(){var t=e(this),r="";return t.hasIndices&&(r+="d"),t.global&&(r+="g"),t.ignoreCase&&(r+="i"),t.multiline&&(r+="m"),t.dotAll&&(r+="s"),t.unicode&&(r+="u"),t.unicodeSets&&(r+="v"),t.sticky&&(r+="y"),r},ul}var dl,U_;function kr(){if(U_)return dl;U_=1;var e=ye(),t=Ve(),r=At(),a=aT(),i=Uu(),n=RegExp.prototype;return dl=a.correct?function(o){return o.flags}:function(o){return!a.correct&&r(n,o)&&!t(o,"flags")?e(i,o):o.flags},dl}var cl,$_;function Na(){if($_)return cl;$_=1;var e=X(),t=se(),r=t.RegExp,a=e(function(){var o=r("a","y");return o.lastIndex=2,o.exec("abcd")!==null}),i=a||e(function(){return!r("a","y").sticky}),n=a||e(function(){var o=r("^r","gy");return o.lastIndex=2,o.exec("str")!==null});return cl={BROKEN_CARET:n,MISSED_STICKY:i,UNSUPPORTED_Y:a},cl}var pl,H_;function $u(){if(H_)return pl;H_=1;var e=X(),t=se(),r=t.RegExp;return pl=e(function(){var a=r(".","s");return!(a.dotAll&&a.test(` +`)&&a.flags==="s")}),pl}var ml,K_;function iT(){if(K_)return ml;K_=1;var e=X(),t=se(),r=t.RegExp;return ml=e(function(){var a=r("(?b)","g");return a.exec("b").groups.a!=="b"||"b".replace(a,"$c")!=="bc"}),ml}var W_;function AO(){if(W_)return L_;W_=1;var e=Ae(),t=se(),r=te(),a=Qr(),i=vr(),n=ht(),o=bt(),l=cr().f,s=At(),u=qa(),d=xe(),c=kr(),p=Na(),v=pP(),m=Qe(),h=X(),b=Ve(),f=at().enforce,g=qr(),k=je(),y=$u(),_=iT(),S=k("match"),R=t.RegExp,w=R.prototype,E=t.SyntaxError,P=r(w.exec),A=r("".charAt),M=r("".replace),T=r("".indexOf),C=r("".slice),z=/^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/,q=/a/g,V=/a/g,F=new R(q)!==q,j=p.MISSED_STICKY,O=p.UNSUPPORTED_Y,D=e&&(!F||j||y||_||h(function(){return V[S]=!1,R(q)!==q||R(V)===V||String(R(q,"i"))!=="/a/i"})),$=function(fe){for(var K=fe.length,le=0,ge="",_e=!1,ke;le<=K;le++){if(ke=A(fe,le),ke==="\\"){ge+=ke+A(fe,++le);continue}!_e&&ke==="."?ge+="[\\s\\S]":(ke==="["?_e=!0:ke==="]"&&(_e=!1),ge+=ke)}return ge},U=function(fe){for(var K=fe.length,le=0,ge="",_e=[],ke=o(null),Pe=!1,He=!1,We=0,qe="",Se;le<=K;le++){if(Se=A(fe,le),Se==="\\")Se+=A(fe,++le);else if(Se==="]")Pe=!1;else if(!Pe)switch(!0){case Se==="[":Pe=!0;break;case Se==="(":if(ge+=Se,C(fe,le+1,le+3)==="?:")continue;P(z,C(fe,le+1))&&(le+=2,He=!0),We++;continue;case(Se===">"&&He):if(qe===""||b(ke,qe))throw new E("Invalid capture group name");ke[qe]=!0,_e[_e.length]=[qe,We],He=!1,qe="";continue}He?qe+=Se:ge+=Se}return[ge,_e]};if(a("RegExp",D)){for(var ae=function(K,le){var ge=s(w,this),_e=u(K),ke=le===void 0,Pe=[],He=K,We,qe,Se,Ne,ze,Ce;if(!ge&&_e&&ke&&K.constructor===ae)return K;if((_e||s(w,K))&&(K=K.source,ke&&(le=c(He))),K=K===void 0?"":d(K),le=le===void 0?"":d(le),He=K,y&&"dotAll"in q&&(qe=!!le&&T(le,"s")>-1,qe&&(le=M(le,/s/g,""))),We=le,j&&"sticky"in q&&(Se=!!le&&T(le,"y")>-1,Se&&O&&(le=M(le,/y/g,""))),_&&(Ne=U(K),K=Ne[0],Pe=Ne[1]),ze=i(R(K,le),ge?this:w,ae),(qe||Se||Pe.length)&&(Ce=f(ze),qe&&(Ce.dotAll=!0,Ce.raw=ae($(K),We)),Se&&(Ce.sticky=!0),Pe.length&&(Ce.groups=Pe)),K!==He)try{n(ze,"source",He===""?"(?:)":He)}catch{}return ze},Me=l(R),he=0;Me.length>he;)v(ae,R,Me[he++]);w.constructor=ae,ae.prototype=w,m(t,"RegExp",ae,{constructor:!0})}return g("RegExp"),L_}var G_={},vl,Y_;function La(){if(Y_)return vl;Y_=1;var e=TypeError;return vl=function(t){if(typeof t=="string")return t;throw new e("Argument is not a string")},vl}var Q_;function MO(){if(Q_)return G_;Q_=1;var e=I(),t=te(),r=La(),a=Ve(),i=Pa().start,n=aa(),o=Array,l=RegExp.escape,s=t("".charAt),u=t("".charCodeAt),d=t(1.1.toString),c=t([].join),p=/^[0-9a-z]/i,v=/^[$()*+./?[\\\]^{|}]/,m=RegExp("^[!\"#%&',\\-:;<=>@`~"+n+"]"),h=t(p.exec),b={" ":"t","\n":"n","\v":"v","\f":"f","\r":"r"},f=function(k){var y=d(u(k,0),16);return y.length<3?"\\x"+i(y,2,"0"):"\\u"+i(y,4,"0")},g=!l||l("ab")!=="\\x61b";return e({target:"RegExp",stat:!0,forced:g},{escape:function(y){r(y);for(var _=y.length,S=o(_),R=0;R<_;R++){var w=s(y,R);if(R===0&&h(p,w))S[R]=f(w);else if(a(b,w))S[R]="\\"+b[w];else if(h(v,w))S[R]="\\"+w;else if(h(m,w))S[R]=f(w);else{var E=u(w,0);(E&63488)!==55296?S[R]=w:E>=56320||R+1>=_||(u(y,R+1)&64512)!==56320?S[R]=f(w):(S[R]=w,S[++R]=s(y,R))}}return c(S,"")}}),G_}var Z_={},J_;function PO(){if(J_)return Z_;J_=1;var e=Ae(),t=$u(),r=St(),a=ot(),i=at().get,n=RegExp.prototype,o=TypeError;return e&&t&&a(n,"dotAll",{configurable:!0,get:function(){if(this!==n){if(r(this)==="RegExp")return!!i(this).dotAll;throw new o("Incompatible receiver, RegExp required")}}}),Z_}var X_={},fl,eS;function Hu(){if(eS)return fl;eS=1;var e=ye(),t=te(),r=xe(),a=Uu(),i=Na(),n=Tr(),o=bt(),l=at().get,s=$u(),u=iT(),d=n("native-string-replace",String.prototype.replace),c=RegExp.prototype.exec,p=c,v=t("".charAt),m=t("".indexOf),h=t("".replace),b=t("".slice),f=(function(){var _=/a/,S=/b*/g;return e(c,_,"a"),e(c,S,"a"),_.lastIndex!==0||S.lastIndex!==0})(),g=i.BROKEN_CARET,k=/()??/.exec("")[1]!==void 0,y=f||k||g||s||u;return y&&(p=function(S){var R=this,w=l(R),E=r(S),P=w.raw,A,M,T,C,z,q,V;if(P)return P.lastIndex=R.lastIndex,A=e(p,P,E),R.lastIndex=P.lastIndex,A;var F=w.groups,j=g&&R.sticky,O=e(a,R),D=R.source,$=0,U=E;if(j&&(O=h(O,"y",""),m(O,"g")===-1&&(O+="g"),U=b(E,R.lastIndex),R.lastIndex>0&&(!R.multiline||R.multiline&&v(E,R.lastIndex-1)!==` +`)&&(D="(?: "+D+")",U=" "+U,$++),M=new RegExp("^(?:"+D+")",O)),k&&(M=new RegExp("^"+D+"$(?!\\s)",O)),f&&(T=R.lastIndex),C=e(c,j?M:R,U),j?C?(C.input=b(C.input,$),C[0]=b(C[0],$),C.index=R.lastIndex,R.lastIndex+=C[0].length):R.lastIndex=0:f&&C&&(R.lastIndex=R.global?C.index+C[0].length:T),k&&C&&C.length>1&&e(d,C[0],M,function(){for(z=1;z1;return l.has(1)&&l.clear(),{done:u,value:2}}}}},l=new Set([1,2,3,4]);return l.difference(o).size!==3});return e({target:"Set",proto:!0,real:!0,forced:n},{difference:t}),vS}var ES={},El,AS;function qO(){if(AS)return El;AS=1;var e=yr(),t=Ut(),r=na(),a=Sr(),i=Ur(),n=_r(),o=t.Set,l=t.add,s=t.has;return El=function(d){var c=e(this),p=a(d),v=new o;return r(c)>p.size?n(p.getIterator(),function(m){s(c,m)&&l(v,m)}):i(c,function(m){p.includes(m)&&l(v,m)}),v},El}var MS;function NO(){if(MS)return ES;MS=1;var e=I(),t=X(),r=qO(),a=wr(),i=!a("intersection",function(n){return n.size===2&&n.has(1)&&n.has(2)})||t(function(){return String(Array.from(new Set([1,2,3]).intersection(new Set([3,2]))))!=="3,2"});return e({target:"Set",proto:!0,real:!0,forced:i},{intersection:r}),ES}var PS={},Al,TS;function LO(){if(TS)return Al;TS=1;var e=yr(),t=Ut().has,r=na(),a=Sr(),i=Ur(),n=_r(),o=yt();return Al=function(s){var u=e(this),d=a(s);if(r(u)<=d.size)return i(u,function(p){if(d.includes(p))return!1},!0)!==!1;var c=d.getIterator();return n(c,function(p){if(t(u,p))return o(c,"normal",!1)})!==!1},Al}var IS;function FO(){if(IS)return PS;IS=1;var e=I(),t=LO(),r=wr(),a=!r("isDisjointFrom",function(i){return!i});return e({target:"Set",proto:!0,real:!0,forced:a},{isDisjointFrom:t}),PS}var jS={},Ml,CS;function VO(){if(CS)return Ml;CS=1;var e=yr(),t=na(),r=Ur(),a=Sr();return Ml=function(n){var o=e(this),l=a(n);return t(o)>l.size?!1:r(o,function(s){if(!l.includes(s))return!1},!0)!==!1},Ml}var OS;function BO(){if(OS)return jS;OS=1;var e=I(),t=VO(),r=wr(),a=!r("isSubsetOf",function(i){return i});return e({target:"Set",proto:!0,real:!0,forced:a},{isSubsetOf:t}),jS}var zS={},Pl,DS;function UO(){if(DS)return Pl;DS=1;var e=yr(),t=Ut().has,r=na(),a=Sr(),i=_r(),n=yt();return Pl=function(l){var s=e(this),u=a(l);if(r(s)=0?p:c+p;return v<0||v>=c?void 0:o(d,v)}}),$S}var KS={},Cl,WS;function Fa(){if(WS)return Cl;WS=1;var e=te(),t=it(),r=xe(),a=rt(),i=e("".charAt),n=e("".charCodeAt),o=e("".slice),l=function(s){return function(u,d){var c=r(a(u)),p=t(d),v=c.length,m,h;return p<0||p>=v?s?"":void 0:(m=n(c,p),m<55296||m>56319||p+1===v||(h=n(c,p+1))<56320||h>57343?s?i(c,p):m:s?o(c,p,p+2):(m-55296<<10)+(h-56320)+65536)}};return Cl={codeAt:l(!1),charAt:l(!0)},Cl}var GS;function QO(){if(GS)return KS;GS=1;var e=I(),t=Fa().codeAt;return e({target:"String",proto:!0},{codePointAt:function(a){return t(this,a)}}),KS}var YS={},Ol,QS;function Gu(){if(QS)return Ol;QS=1;var e=qa(),t=TypeError;return Ol=function(r){if(e(r))throw new t("The method doesn't accept regular expressions");return r},Ol}var zl,ZS;function Yu(){if(ZS)return zl;ZS=1;var e=je(),t=e("match");return zl=function(r){var a=/./;try{"/./"[r](a)}catch{try{return a[t]=!1,"/./"[r](a)}catch{}}return!1},zl}var JS;function ZO(){if(JS)return YS;JS=1;var e=I(),t=pr(),r=gt().f,a=jt(),i=xe(),n=Gu(),o=rt(),l=Yu(),s=Ye(),u=t("".slice),d=Math.min,c=l("endsWith"),p=!s&&!c&&!!(function(){var v=r(String.prototype,"endsWith");return v&&!v.writable})();return e({target:"String",proto:!0,forced:!p&&!c},{endsWith:function(m){var h=i(o(this));n(m);var b=arguments.length>1?arguments[1]:void 0,f=h.length,g=b===void 0?f:d(a(b),f),k=i(m);return u(h,g-k.length,g)===k}}),YS}var XS={},ew;function oT(){if(ew)return XS;ew=1;var e=I(),t=te(),r=Xt(),a=RangeError,i=String.fromCharCode,n=String.fromCodePoint,o=t([].join),l=!!n&&n.length!==1;return e({target:"String",stat:!0,arity:1,forced:l},{fromCodePoint:function(u){for(var d=[],c=arguments.length,p=0,v;c>p;){if(v=+arguments[p++],r(v,1114111)!==v)throw new a(v+" is not a valid code point");d[p]=v<65536?i(v):i(((v-=65536)>>10)+55296,v%1024+56320)}return o(d,"")}}),XS}var tw={},rw;function JO(){if(rw)return tw;rw=1;var e=I(),t=te(),r=Gu(),a=rt(),i=xe(),n=Yu(),o=t("".indexOf);return e({target:"String",proto:!0,forced:!n("includes")},{includes:function(s){return!!~o(i(a(this)),i(r(s)),arguments.length>1?arguments[1]:void 0)}}),tw}var aw={},iw;function XO(){if(iw)return aw;iw=1;var e=I(),t=te(),r=rt(),a=xe(),i=t("".charCodeAt);return e({target:"String",proto:!0},{isWellFormed:function(){for(var o=a(r(this)),l=o.length,s=0;s=56320||++s>=l||(i(o,s)&64512)!==56320))return!1}return!0}}),aw}var nw={},ow;function sT(){if(ow)return nw;ow=1;var e=Fa().charAt,t=xe(),r=at(),a=Cu(),i=hr(),n="String Iterator",o=r.set,l=r.getterFor(n);return a(String,"String",function(s){o(this,{type:n,string:t(s),index:0})},function(){var u=l(this),d=u.string,c=u.index,p;return c>=d.length?i(void 0,!0):(p=e(d,c),u.index+=p.length,i(p,!1))}),nw}var sw={},Dl,lw;function Va(){if(lw)return Dl;lw=1,Ku();var e=ye(),t=Qe(),r=Hu(),a=X(),i=je(),n=ht(),o=i("species"),l=RegExp.prototype;return Dl=function(s,u,d,c){var p=i(s),v=!a(function(){var f={};return f[p]=function(){return 7},""[s](f)!==7}),m=v&&!a(function(){var f=!1,g=/a/;return s==="split"&&(g={},g.constructor={},g.constructor[o]=function(){return g},g.flags="",g[p]=/./[p]),g.exec=function(){return f=!0,null},g[p](""),!f});if(!v||!m||d){var h=/./[p],b=u(p,""[s],function(f,g,k,y,_){var S=g.exec;return S===r||S===l.exec?v&&!_?{done:!0,value:e(h,g,k,y)}:{done:!0,value:e(f,k,g,y)}:{done:!1}});t(String.prototype,s,b[0]),t(l,p,b[1])}c&&n(l[p],"sham",!0)},Dl}var xl,uw;function Ba(){if(uw)return xl;uw=1;var e=Fa().charAt;return xl=function(t,r,a){return r+(a?e(t,r).length:1)},xl}var ql,dw;function oa(){if(dw)return ql;dw=1;var e=ye(),t=Re(),r=Ue(),a=St(),i=Hu(),n=TypeError;return ql=function(o,l){var s=o.exec;if(r(s)){var u=e(s,o,l);return u!==null&&t(u),u}if(a(o)==="RegExp")return e(i,o,l);throw new n("RegExp#exec called on incompatible receiver")},ql}var cw;function ez(){if(cw)return sw;cw=1;var e=ye(),t=te(),r=Va(),a=Re(),i=Ie(),n=jt(),o=xe(),l=rt(),s=ft(),u=Ba(),d=kr(),c=oa(),p=t("".indexOf);return r("match",function(v,m,h){return[function(f){var g=l(this),k=i(f)?s(f,v):void 0;return k?e(k,f,g):new RegExp(f)[v](o(g))},function(b){var f=a(this),g=o(b),k=h(m,f,g);if(k.done)return k.value;var y=o(d(f));if(p(y,"g")===-1)return c(f,g);var _=p(y,"u")!==-1;f.lastIndex=0;for(var S=[],R=0,w;(w=c(f,g))!==null;){var E=o(w[0]);S[R]=E,E===""&&(f.lastIndex=u(g,n(f.lastIndex),_)),R++}return R===0?null:S}]}),sw}var pw={},mw;function tz(){if(mw)return pw;mw=1;var e=I(),t=ye(),r=pr(),a=ju(),i=hr(),n=rt(),o=jt(),l=xe(),s=Re(),u=Ie(),d=St(),c=qa(),p=kr(),v=ft(),m=Qe(),h=X(),b=je(),f=za(),g=Ba(),k=oa(),y=at(),_=Ye(),S=b("matchAll"),R="RegExp String",w=R+" Iterator",E=y.set,P=y.getterFor(w),A=RegExp.prototype,M=TypeError,T=r("".indexOf),C=r("".matchAll),z=!!C&&!h(function(){C("a",/./)}),q=a(function(j,O,D,$){E(this,{type:w,regexp:j,string:O,global:D,unicode:$,done:!1})},R,function(){var j=P(this);if(j.done)return i(void 0,!0);var O=j.regexp,D=j.string,$=k(O,D);return $===null?(j.done=!0,i(void 0,!0)):j.global?(l($[0])===""&&(O.lastIndex=g(D,o(O.lastIndex),j.unicode)),i($,!1)):(j.done=!0,i($,!1))}),V=function(F){var j=s(this),O=l(F),D=f(j,RegExp),$=l(p(j)),U,ae,Me;return U=new D(D===RegExp?j.source:j,$),ae=!!~T($,"g"),Me=!!~T($,"u"),U.lastIndex=o(j.lastIndex),new q(U,O,ae,Me)};return e({target:"String",proto:!0,forced:z},{matchAll:function(j){var O=n(this),D,$,U,ae;if(u(j)){if(c(j)&&(D=l(n(p(j))),!~T(D,"g")))throw new M("`.matchAll` does not allow non-global regexes");if(z)return C(O,j);if(U=v(j,S),U===void 0&&_&&d(j)==="RegExp"&&(U=V),U)return t(U,j,O)}else if(z)return C(O,j);return $=l(O),ae=new RegExp(j,"g"),_?t(V,ae,$):ae[S]($)}}),_||S in A||m(A,S,V),pw}var vw={},Nl,fw;function lT(){if(fw)return Nl;fw=1;var e=Kt();return Nl=/Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(e),Nl}var gw;function rz(){if(gw)return vw;gw=1;var e=I(),t=Pa().end,r=lT();return e({target:"String",proto:!0,forced:r},{padEnd:function(i){return t(this,i,arguments.length>1?arguments[1]:void 0)}}),vw}var hw={},bw;function az(){if(bw)return hw;bw=1;var e=I(),t=Pa().start,r=lT();return e({target:"String",proto:!0,forced:r},{padStart:function(i){return t(this,i,arguments.length>1?arguments[1]:void 0)}}),hw}var kw={},yw;function iz(){if(yw)return kw;yw=1;var e=I(),t=te(),r=mt(),a=Ge(),i=xe(),n=Ze(),o=t([].push),l=t([].join);return e({target:"String",stat:!0},{raw:function(u){var d=r(a(u).raw),c=n(d);if(!c)return"";for(var p=arguments.length,v=[],m=0;;){if(o(v,i(d[m++])),m===c)return l(v,"");m]*>)/g,l=/\$([$&'`]|\d{1,2})/g;return Ll=function(s,u,d,c,p,v){var m=d+s.length,h=c.length,b=l;return p!==void 0&&(p=t(p),b=o),i(v,b,function(f,g){var k;switch(a(g,0)){case"$":return"$";case"&":return s;case"`":return n(u,0,d);case"'":return n(u,m);case"<":k=p[n(g,1,-1)];break;default:var y=+g;if(y===0)return f;if(y>h){var _=r(y/10);return _===0?f:_<=h?c[_-1]===void 0?a(g,1):c[_-1]+a(g,1):f}k=c[y-1]}return k===void 0?"":k})},Ll}var Ew;function oz(){if(Ew)return ww;Ew=1;var e=zt(),t=ye(),r=te(),a=Va(),i=X(),n=Re(),o=Ue(),l=Ie(),s=it(),u=jt(),d=xe(),c=rt(),p=Ba(),v=ft(),m=uT(),h=kr(),b=oa(),f=je(),g=f("replace"),k=Math.max,y=Math.min,_=r([].concat),S=r([].push),R=r("".indexOf),w=r("".slice),E=function(T){return T===void 0?T:String(T)},P=(function(){return"a".replace(/./,"$0")==="$0"})(),A=(function(){return/./[g]?/./[g]("a","$0")==="":!1})(),M=!i(function(){var T=/./;return T.exec=function(){var C=[];return C.groups={a:"7"},C},"".replace(T,"$")!=="7"});return a("replace",function(T,C,z){var q=A?"$":"$0";return[function(F,j){var O=c(this),D=l(F)?v(F,g):void 0;return D?t(D,F,O,j):t(C,d(O),F,j)},function(V,F){var j=n(this),O=d(V);if(typeof F=="string"&&R(F,q)===-1&&R(F,"$<")===-1){var D=z(C,j,O,F);if(D.done)return D.value}var $=o(F);$||(F=d(F));var U=d(h(j)),ae=R(U,"g")!==-1,Me;ae&&(Me=R(U,"u")!==-1,j.lastIndex=0);for(var he=[],fe;fe=b(j,O),!(fe===null||(S(he,fe),!ae));){var K=d(fe[0]);K===""&&(j.lastIndex=p(O,u(j.lastIndex),Me))}for(var le="",ge=0,_e=0;_e=ge&&(le+=w(O,ge,Pe)+We,ge=Pe+ke.length)}return le+w(O,ge)}]},!M||!P||A),ww}var Aw={},Mw;function sz(){if(Mw)return Aw;Mw=1;var e=I(),t=ye(),r=te(),a=rt(),i=Ue(),n=Ie(),o=qa(),l=xe(),s=ft(),u=kr(),d=uT(),c=je(),p=Ye(),v=c("replace"),m=TypeError,h=r("".indexOf),b=r("".replace),f=r("".slice),g=Math.max;return e({target:"String",proto:!0},{replaceAll:function(y,_){var S=a(this),R,w,E,P,A,M,T,C,z,q,V=0,F="";if(n(y)){if(R=o(y),R&&(w=l(a(u(y))),!~h(w,"g")))throw new m("`.replaceAll` does not allow non-global regexes");if(E=s(y,v),E)return t(E,y,S,_);if(p&&R)return b(l(S),y,_)}for(P=l(S),A=l(y),M=i(_),M||(_=l(_)),T=A.length,C=g(1,T),z=h(P,A);z!==-1;)q=M?l(_(A,z,P)):d(A,P,z,[],void 0,_),F+=f(P,V,z)+q,V=z+T,z=z+C>P.length?-1:h(P,A,z+C);return V1||"".split(/.?/).length;return r("split",function(_,S,R){var w="0".split(void 0,0).length?function(E,P){return E===void 0&&P===0?[]:e(S,this,E,P)}:S;return[function(P,A){var M=n(this),T=i(P)?d(P,_):void 0;return T?e(T,P,M,A):e(w,u(M),P,A)},function(E,P){var A=a(this),M=u(E);if(!y){var T=R(w,A,M,P,w!==S);if(T.done)return T.value}var C=o(A,RegExp),z=A.unicode,q=(A.ignoreCase?"i":"")+(A.multiline?"m":"")+(A.unicode?"u":"")+(m?"g":"y"),V=new C(m?"^(?:"+A.source+")":A,q),F=P===void 0?h:P>>>0;if(F===0)return[];if(M.length===0)return c(V,M)===null?[M]:[];for(var j=0,O=0,D=[];O1?arguments[1]:void 0,h.length)),f=i(m);return u(h,b,b+f.length)===f}}),Cw}var zw={},Dw;function cz(){if(Dw)return zw;Dw=1;var e=I(),t=te(),r=rt(),a=it(),i=xe(),n=t("".slice),o=Math.max,l=Math.min,s=!"".substr||"ab".substr(-1)!=="b";return e({target:"String",proto:!0,forced:s},{substr:function(d,c){var p=i(r(this)),v=p.length,m=a(d),h,b;return m===1/0&&(m=0),m<0&&(m=o(v+m,0)),h=c===void 0?v:a(c),h<=0||h===1/0?"":(b=l(m+h,v),m>=b?"":n(p,m,b))}}),zw}var xw={},qw;function pz(){if(qw)return xw;qw=1;var e=I(),t=ye(),r=te(),a=rt(),i=xe(),n=X(),o=Array,l=r("".charAt),s=r("".charCodeAt),u=r([].join),d="".toWellFormed,c="�",p=d&&n(function(){return t(d,1)!=="1"});return e({target:"String",proto:!0,forced:p},{toWellFormed:function(){var m=i(a(this));if(p)return t(d,m);for(var h=m.length,b=o(h),f=0;f=56320||f+1>=h||(s(m,f+1)&64512)!==56320?b[f]=c:(b[f]=l(m,f),b[++f]=l(m,f))}return u(b,"")}}),xw}var Nw={},Fl,Lw;function Qu(){if(Lw)return Fl;Lw=1;var e=jr().PROPER,t=X(),r=aa(),a="​…᠎";return Fl=function(i){return t(function(){return!!r[i]()||a[i]()!==a||e&&r[i].name!==i})},Fl}var Fw;function mz(){if(Fw)return Nw;Fw=1;var e=I(),t=Fr().trim,r=Qu();return e({target:"String",proto:!0,forced:r("trim")},{trim:function(){return t(this)}}),Nw}var Vw={},Bw={},Vl,Uw;function dT(){if(Uw)return Vl;Uw=1;var e=Fr().end,t=Qu();return Vl=t("trimEnd")?function(){return e(this)}:"".trimEnd,Vl}var $w;function vz(){if($w)return Bw;$w=1;var e=I(),t=dT();return e({target:"String",proto:!0,name:"trimEnd",forced:"".trimRight!==t},{trimRight:t}),Bw}var Hw;function fz(){if(Hw)return Vw;Hw=1,vz();var e=I(),t=dT();return e({target:"String",proto:!0,name:"trimEnd",forced:"".trimEnd!==t},{trimEnd:t}),Vw}var Kw={},Ww={},Bl,Gw;function cT(){if(Gw)return Bl;Gw=1;var e=Fr().start,t=Qu();return Bl=t("trimStart")?function(){return e(this)}:"".trimStart,Bl}var Yw;function gz(){if(Yw)return Ww;Yw=1;var e=I(),t=cT();return e({target:"String",proto:!0,name:"trimStart",forced:"".trimLeft!==t},{trimLeft:t}),Ww}var Qw;function hz(){if(Qw)return Kw;Qw=1,gz();var e=I(),t=cT();return e({target:"String",proto:!0,name:"trimStart",forced:"".trimStart!==t},{trimStart:t}),Kw}var Zw={},Ul,Jw;function xt(){if(Jw)return Ul;Jw=1;var e=te(),t=rt(),r=xe(),a=/"/g,i=e("".replace);return Ul=function(n,o,l,s){var u=r(t(n)),d="<"+o;return l!==""&&(d+=" "+l+'="'+i(r(s),a,""")+'"'),d+">"+u+""},Ul}var $l,Xw;function qt(){if(Xw)return $l;Xw=1;var e=X();return $l=function(t){return e(function(){var r=""[t]('"');return r!==r.toLowerCase()||r.split('"').length>3})},$l}var eR;function bz(){if(eR)return Zw;eR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("anchor")},{anchor:function(i){return t(this,"a","name",i)}}),Zw}var tR={},rR;function kz(){if(rR)return tR;rR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("big")},{big:function(){return t(this,"big","","")}}),tR}var aR={},iR;function yz(){if(iR)return aR;iR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("blink")},{blink:function(){return t(this,"blink","","")}}),aR}var nR={},oR;function _z(){if(oR)return nR;oR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("bold")},{bold:function(){return t(this,"b","","")}}),nR}var sR={},lR;function Sz(){if(lR)return sR;lR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("fixed")},{fixed:function(){return t(this,"tt","","")}}),sR}var uR={},dR;function wz(){if(dR)return uR;dR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("fontcolor")},{fontcolor:function(i){return t(this,"font","color",i)}}),uR}var cR={},pR;function Rz(){if(pR)return cR;pR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("fontsize")},{fontsize:function(i){return t(this,"font","size",i)}}),cR}var mR={},vR;function Ez(){if(vR)return mR;vR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("italics")},{italics:function(){return t(this,"i","","")}}),mR}var fR={},gR;function Az(){if(gR)return fR;gR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("link")},{link:function(i){return t(this,"a","href",i)}}),fR}var hR={},bR;function Mz(){if(bR)return hR;bR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("small")},{small:function(){return t(this,"small","","")}}),hR}var kR={},yR;function Pz(){if(yR)return kR;yR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("strike")},{strike:function(){return t(this,"strike","","")}}),kR}var _R={},SR;function Tz(){if(SR)return _R;SR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("sub")},{sub:function(){return t(this,"sub","","")}}),_R}var wR={},RR;function Iz(){if(RR)return wR;RR=1;var e=I(),t=xt(),r=qt();return e({target:"String",proto:!0,forced:r("sup")},{sup:function(){return t(this,"sup","","")}}),wR}var ER={},sa={exports:{}},Hl,AR;function Zu(){if(AR)return Hl;AR=1;var e=se(),t=X(),r=ya(),a=$e().NATIVE_ARRAY_BUFFER_VIEWS,i=e.ArrayBuffer,n=e.Int8Array;return Hl=!a||!t(function(){n(1)})||!t(function(){new n(-1)})||!r(function(o){new n,new n(null),new n(1.5),new n(o)},!0)||t(function(){return new n(new i(2),1,void 0).length!==1}),Hl}var Kl,MR;function pT(){if(MR)return Kl;MR=1;var e=Nu(),t=RangeError;return Kl=function(r,a){var i=e(r);if(i%a)throw new t("Wrong offset");return i},Kl}var Wl,PR;function jz(){if(PR)return Wl;PR=1;var e=Math.round;return Wl=function(t){var r=e(t);return r<0?0:r>255?255:r&255},Wl}var Gl,TR;function mT(){if(TR)return Gl;TR=1;var e=Ct();return Gl=function(t){var r=e(t);return r==="BigInt64Array"||r==="BigUint64Array"},Gl}var Yl,IR;function Ju(){if(IR)return Yl;IR=1;var e=pa(),t=TypeError;return Yl=function(r){var a=e(r,"number");if(typeof a=="number")throw new t("Can't convert number to bigint");return BigInt(a)},Yl}var Ql,jR;function vT(){if(jR)return Ql;jR=1;var e=Ot(),t=ye(),r=Bu(),a=Ge(),i=Ze(),n=zr(),o=fr(),l=Pu(),s=mT(),u=$e().aTypedArrayConstructor,d=Ju();return Ql=function(p){var v=r(this),m=a(p),h=arguments.length,b=h>1?arguments[1]:void 0,f=b!==void 0,g=o(m),k,y,_,S,R,w,E,P;if(g&&!l(g))for(E=n(m,g),P=E.next,m=[];!(w=t(P,E)).done;)m.push(w.value);for(f&&h>2&&(b=e(b,arguments[2])),y=i(m),_=new(u(v))(y),S=s(_),k=0;y>k;k++)R=f?b(m[k],k):m[k],_[k]=S?d(R):+R;return _},Ql}var CR;function ar(){if(CR)return sa.exports;CR=1;var e=I(),t=se(),r=ye(),a=Ae(),i=Zu(),n=$e(),o=Aa(),l=Dt(),s=It(),u=ht(),d=Vu(),c=jt(),p=Ea(),v=pT(),m=jz(),h=ir(),b=Ve(),f=Ct(),g=Ie(),k=ur(),y=bt(),_=At(),S=Bt(),R=cr().f,w=vT(),E=kt().forEach,P=qr(),A=ot(),M=et(),T=gt(),C=ta(),z=at(),q=vr(),V=z.get,F=z.set,j=z.enforce,O=M.f,D=T.f,$=t.RangeError,U=o.ArrayBuffer,ae=U.prototype,Me=o.DataView,he=n.NATIVE_ARRAY_BUFFER_VIEWS,fe=n.TYPED_ARRAY_TAG,K=n.TypedArray,le=n.TypedArrayPrototype,ge=n.isTypedArray,_e="BYTES_PER_ELEMENT",ke="Wrong length",Pe=function(Ne,ze){A(Ne,ze,{configurable:!0,get:function(){return V(this)[ze]}})},He=function(Ne){var ze;return _(ae,Ne)||(ze=f(Ne))==="ArrayBuffer"||ze==="SharedArrayBuffer"},We=function(Ne,ze){return ge(Ne)&&!k(ze)&&ze in Ne&&d(+ze)&&ze>=0},qe=function(ze,Ce){return Ce=h(Ce),We(ze,Ce)?s(2,ze[Ce]):D(ze,Ce)},Se=function(ze,Ce,J){return Ce=h(Ce),We(ze,Ce)&&g(J)&&b(J,"value")&&!b(J,"get")&&!b(J,"set")&&!J.configurable&&(!b(J,"writable")||J.writable)&&(!b(J,"enumerable")||J.enumerable)?(ze[Ce]=J.value,ze):O(ze,Ce,J)};return a?(he||(T.f=qe,M.f=Se,Pe(le,"buffer"),Pe(le,"byteOffset"),Pe(le,"byteLength"),Pe(le,"length")),e({target:"Object",stat:!0,forced:!he},{getOwnPropertyDescriptor:qe,defineProperty:Se}),sa.exports=function(Ne,ze,Ce){var J=Ne.match(/\d+/)[0]/8,oe=Ne+(Ce?"Clamped":"")+"Array",Ee="get"+Ne,ie="set"+Ne,me=t[oe],ve=me,ce=ve&&ve.prototype,De={},Xe=function(Z,ne){var H=V(Z);return H.view[Ee](ne*J+H.byteOffset,!0)},L=function(Z,ne,H){var we=V(Z);we.view[ie](ne*J+we.byteOffset,Ce?m(H):H,!0)},G=function(Z,ne){O(Z,ne,{get:function(){return Xe(this,ne)},set:function(H){return L(this,ne,H)},enumerable:!0})};he?i&&(ve=ze(function(Z,ne,H,we){return l(Z,ce),q((function(){return g(ne)?He(ne)?we!==void 0?new me(ne,v(H,J),we):H!==void 0?new me(ne,v(H,J)):new me(ne):ge(ne)?C(ve,ne):r(w,ve,ne):new me(p(ne))})(),Z,ve)}),S&&S(ve,K),E(R(me),function(Z){Z in ve||u(ve,Z,me[Z])}),ve.prototype=ce):(ve=ze(function(Z,ne,H,we){l(Z,ce);var Ke=0,W=0,ue,de,pe;if(!g(ne))pe=p(ne),de=pe*J,ue=new U(de);else if(He(ne)){ue=ne,W=v(H,J);var Te=ne.byteLength;if(we===void 0){if(Te%J)throw new $(ke);if(de=Te-W,de<0)throw new $(ke)}else if(de=c(we)*J,de+W>Te)throw new $(ke);pe=de/J}else return ge(ne)?C(ve,ne):r(w,ve,ne);for(F(Z,{buffer:ue,byteOffset:W,byteLength:de,length:pe,view:new Me(ue)});Ke=0?u:s+u;return d<0||d>=s?void 0:l[d]}),QR}var JR={},XR;function Bz(){if(XR)return JR;XR=1;var e=te(),t=$e(),r=hP(),a=e(r),i=t.aTypedArray,n=t.exportTypedArrayMethod;return n("copyWithin",function(l,s){return a(i(this),l,s,arguments.length>2?arguments[2]:void 0)}),JR}var eE={},tE;function Uz(){if(tE)return eE;tE=1;var e=$e(),t=kt().every,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("every",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),eE}var rE={},aE;function $z(){if(aE)return rE;aE=1;var e=$e(),t=Tu(),r=Ju(),a=Ct(),i=ye(),n=te(),o=X(),l=e.aTypedArray,s=e.exportTypedArrayMethod,u=n("".slice),d=o(function(){var c=0;return new Int8Array(2).fill({valueOf:function(){return c++}}),c!==1});return s("fill",function(p){var v=arguments.length;l(this);var m=u(a(this),0,3)==="Big"?r(p):+p;return i(t,this,m,v>1?arguments[1]:void 0,v>2?arguments[2]:void 0)},d),rE}var iE={},Zl,nE;function Hz(){if(nE)return Zl;nE=1;var e=ta(),t=$e().getTypedArrayConstructor;return Zl=function(r,a){return e(t(r),a)},Zl}var oE;function Kz(){if(oE)return iE;oE=1;var e=$e(),t=kt().filter,r=Hz(),a=e.aTypedArray,i=e.exportTypedArrayMethod;return i("filter",function(o){var l=t(a(this),o,arguments.length>1?arguments[1]:void 0);return r(this,l)}),iE}var sE={},lE;function Wz(){if(lE)return sE;lE=1;var e=$e(),t=kt().find,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("find",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),sE}var uE={},dE;function Gz(){if(dE)return uE;dE=1;var e=$e(),t=kt().findIndex,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("findIndex",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),uE}var cE={},pE;function Yz(){if(pE)return cE;pE=1;var e=$e(),t=ka().findLast,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("findLast",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),cE}var mE={},vE;function Qz(){if(vE)return mE;vE=1;var e=$e(),t=ka().findLastIndex,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("findLastIndex",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),mE}var fE={},gE;function Zz(){if(gE)return fE;gE=1;var e=$e(),t=kt().forEach,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("forEach",function(n){t(r(this),n,arguments.length>1?arguments[1]:void 0)}),fE}var hE={},bE;function Jz(){if(bE)return hE;bE=1;var e=Zu(),t=$e().exportTypedArrayStaticMethod,r=vT();return t("from",r,e),hE}var kE={},yE;function Xz(){if(yE)return kE;yE=1;var e=$e(),t=Yr().includes,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("includes",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),kE}var _E={},SE;function eD(){if(SE)return _E;SE=1;var e=$e(),t=Yr().indexOf,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("indexOf",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),_E}var wE={},RE;function tD(){if(RE)return wE;RE=1;var e=se(),t=X(),r=te(),a=$e(),i=_a(),n=je(),o=n("iterator"),l=e.Uint8Array,s=r(i.values),u=r(i.keys),d=r(i.entries),c=a.aTypedArray,p=a.exportTypedArrayMethod,v=l&&l.prototype,m=!t(function(){v[o].call([1])}),h=!!v&&v.values&&v[o]===v.values&&v.values.name==="values",b=function(){return s(c(this))};return p("entries",function(){return d(c(this))},m),p("keys",function(){return u(c(this))},m),p("values",b,m||!h,{name:"values"}),p(o,b,m||!h,{name:"values"}),wE}var EE={},AE;function rD(){if(AE)return EE;AE=1;var e=$e(),t=te(),r=e.aTypedArray,a=e.exportTypedArrayMethod,i=t([].join);return a("join",function(o){return i(r(this),o)}),EE}var ME={},PE;function aD(){if(PE)return ME;PE=1;var e=$e(),t=zt(),r=_P(),a=e.aTypedArray,i=e.exportTypedArrayMethod;return i("lastIndexOf",function(o){var l=arguments.length;return t(r,a(this),l>1?[o,arguments[1]]:[o])}),ME}var TE={},IE;function iD(){if(IE)return TE;IE=1;var e=$e(),t=kt().map,r=e.aTypedArray,a=e.getTypedArrayConstructor,i=e.exportTypedArrayMethod;return i("map",function(o){return t(r(this),o,arguments.length>1?arguments[1]:void 0,function(l,s){return new(a(l))(s)})}),TE}var jE={},CE;function nD(){if(CE)return jE;CE=1;var e=$e(),t=Zu(),r=e.aTypedArrayConstructor,a=e.exportTypedArrayStaticMethod;return a("of",function(){for(var n=0,o=arguments.length,l=new(r(this))(o);o>n;)l[n]=arguments[n++];return l},t),jE}var OE={},zE;function oD(){if(zE)return OE;zE=1;var e=$e(),t=Sa().left,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("reduce",function(n){var o=arguments.length;return t(r(this),n,o,o>1?arguments[1]:void 0)}),OE}var DE={},xE;function sD(){if(xE)return DE;xE=1;var e=$e(),t=Sa().right,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("reduceRight",function(n){var o=arguments.length;return t(r(this),n,o,o>1?arguments[1]:void 0)}),DE}var qE={},NE;function lD(){if(NE)return qE;NE=1;var e=$e(),t=e.aTypedArray,r=e.exportTypedArrayMethod,a=Math.floor;return r("reverse",function(){for(var n=this,o=t(n).length,l=a(o/2),s=0,u;s1?arguments[1]:void 0,1),g=n(b);if(v)return t(d,this,g,f);var k=this.length,y=a(g),_=0;if(y+f>k)throw new l("Wrong length");for(;_p;)m[p]=d[p++];return m},o),VE}var UE={},$E;function cD(){if($E)return UE;$E=1;var e=$e(),t=kt().some,r=e.aTypedArray,a=e.exportTypedArrayMethod;return a("some",function(n){return t(r(this),n,arguments.length>1?arguments[1]:void 0)}),UE}var HE={},KE;function pD(){if(KE)return HE;KE=1;var e=se(),t=pr(),r=X(),a=Fe(),i=zu(),n=$e(),o=SP(),l=wP(),s=Wt(),u=Du(),d=n.aTypedArray,c=n.exportTypedArrayMethod,p=e.Uint16Array,v=p&&t(p.prototype.sort),m=!!v&&!(r(function(){v(new p(2),null)})&&r(function(){v(new p(2),{})})),h=!!v&&!r(function(){if(s)return s<74;if(o)return o<67;if(l)return!0;if(u)return u<602;var f=new p(516),g=Array(516),k,y;for(k=0;k<516;k++)y=k%4,f[k]=515-k,g[k]=k-2*y+3;for(v(f,function(_,S){return(_/4|0)-(S/4|0)}),k=0;k<516;k++)if(f[k]!==g[k])return!0}),b=function(f){return function(g,k){return f!==void 0?+f(g,k)||0:k!==k?-1:g!==g?1:g===0&&k===0?1/g>0&&1/k<0?1:-1:g>k}};return c("sort",function(g){return g!==void 0&&a(g),h?v(this,g):i(d(this),b(g))},!h||m),HE}var WE={},GE;function mD(){if(GE)return WE;GE=1;var e=$e(),t=jt(),r=Xt(),a=e.aTypedArray,i=e.getTypedArrayConstructor,n=e.exportTypedArrayMethod;return n("subarray",function(l,s){var u=a(this),d=u.length,c=r(l,d),p=i(u);return new p(u.buffer,u.byteOffset+c*u.BYTES_PER_ELEMENT,t((s===void 0?d:r(s,d))-c))}),WE}var YE={},QE;function vD(){if(QE)return YE;QE=1;var e=se(),t=zt(),r=$e(),a=X(),i=Ft(),n=e.Int8Array,o=r.aTypedArray,l=r.exportTypedArrayMethod,s=[].toLocaleString,u=!!n&&a(function(){s.call(new n(1))}),d=a(function(){return[1,2].toLocaleString()!==new n([1,2]).toLocaleString()})||!a(function(){n.prototype.toLocaleString.call([1,2])});return l("toLocaleString",function(){return t(s,u?i(o(this)):o(this),i(arguments))},d),YE}var ZE={},JE;function fD(){if(JE)return ZE;JE=1;var e=RP(),t=$e(),r=t.aTypedArray,a=t.exportTypedArrayMethod,i=t.getTypedArrayConstructor;return a("toReversed",function(){return e(r(this),i(this))}),ZE}var XE={},eA;function gD(){if(eA)return XE;eA=1;var e=$e(),t=te(),r=Fe(),a=ta(),i=e.aTypedArray,n=e.getTypedArrayConstructor,o=e.exportTypedArrayMethod,l=t(e.TypedArrayPrototype.sort);return o("toSorted",function(u){u!==void 0&&r(u);var d=i(this),c=a(n(d),d);return l(c,u)}),XE}var tA={},rA;function hD(){if(rA)return tA;rA=1;var e=$e().exportTypedArrayMethod,t=X(),r=se(),a=te(),i=r.Uint8Array,n=i&&i.prototype||{},o=[].toString,l=a([].join);t(function(){o.call({})})&&(o=function(){return l(this)});var s=n.toString!==o;return e("toString",o,s),tA}var aA={},iA;function bD(){if(iA)return aA;iA=1;var e=AP(),t=$e(),r=mT(),a=it(),i=Ju(),n=t.aTypedArray,o=t.getTypedArrayConstructor,l=t.exportTypedArrayMethod,s=(function(){try{new Int8Array(1).with(2,{valueOf:function(){throw 8}})}catch(d){return d===8}})(),u=s&&(function(){try{new Int8Array(1).with(-.5,1)}catch{return!0}})();return l("with",function(d,c){var p=n(this),v=a(d),m=r(p)?i(c):+c;return e(p,o(p),v,m)},!s||u),aA}var nA={},Jl,oA;function fT(){if(oA)return Jl;oA=1;var e=Ie(),t=String,r=TypeError;return Jl=function(a){if(a===void 0||e(a))return a;throw new r(t(a)+" is not an object or undefined")},Jl}var Xl,sA;function Ua(){if(sA)return Xl;sA=1;var e="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",t=e+"+/",r=e+"-_",a=function(i){for(var n={},o=0;o<64;o++)n[i.charAt(o)]=o;return n};return Xl={i2c:t,c2i:a(t),i2cUrl:r,c2iUrl:a(r)},Xl}var eu,lA;function gT(){if(lA)return eu;lA=1;var e=TypeError;return eu=function(t){var r=t&&t.alphabet;if(r===void 0||r==="base64"||r==="base64url")return r||"base64";throw new e("Incorrect `alphabet` option")},eu}var tu,uA;function hT(){if(uA)return tu;uA=1;var e=se(),t=te(),r=fT(),a=La(),i=Ve(),n=Ua(),o=gT(),l=ra(),s=n.c2i,u=n.c2iUrl,d=e.SyntaxError,c=e.TypeError,p=t("".charAt),v=function(b,f){for(var g=b.length;f>16&255,y>>8&255,y&255];if(k===2){if(g&&_[1]!==0)throw new d("Extra bits");return[_[0]]}if(k===3){if(g&&_[2]!==0)throw new d("Extra bits");return[_[0],_[1]]}return _},h=function(b,f,g){for(var k=f.length,y=0;y0){if(_==="stop-before-partial")break;if(_==="loose"){if(P.length===1)throw new d("Malformed padding: exactly one additional character");w=h(R,m(P,y,!1),w)}else throw new d("Missing padding")}E=S;break}var M=p(b,A);if(++A,M==="="){if(P.length<2)throw new d("Padding is too early");if(A=v(b,A),P.length===2){if(A===S){if(_==="stop-before-partial")break;throw new d("Malformed padding: only one =")}p(b,A)==="="&&(++A,A=v(b,A))}if(A1?arguments[1]:void 0,null,9007199254740991);return r(i,s.bytes)}}),nA}var cA={},ru,pA;function bT(){if(pA)return ru;pA=1;var e=se(),t=te(),r=e.Uint8Array,a=e.SyntaxError,i=e.parseInt,n=Math.min,o=/[^\da-f]/i,l=t(o.exec),s=t("".slice);return ru=function(u,d){var c=u.length;if(c%2!==0)throw new a("String should be an even number of characters");for(var p=d?n(d.length,c/2):c/2,v=d||new r(p),m=0,h=0;h1?arguments[1]:void 0,this,this.length);return{read:s.read,written:s.written}}}),vA}var hA={},bA;function SD(){if(bA)return hA;bA=1;var e=I(),t=se(),r=La(),a=$a(),i=ra(),n=bT();return t.Uint8Array&&e({target:"Uint8Array",proto:!0},{setFromHex:function(l){a(this),r(l),i(this.buffer);var s=n(l,this).read;return{read:s,written:s/2}}}),hA}var kA={},yA;function wD(){if(yA)return kA;yA=1;var e=I(),t=se(),r=te(),a=fT(),i=$a(),n=ra(),o=Ua(),l=gT(),s=o.i2c,u=o.i2cUrl,d=r("".charAt),c=t.Uint8Array,p=!c||!c.prototype.toBase64||!(function(){try{var v=new c;v.toBase64(null)}catch{return!0}})();return c&&e({target:"Uint8Array",proto:!0,forced:p},{toBase64:function(){var m=i(this),h=arguments.length?a(arguments[0]):void 0,b=l(h)==="base64"?s:u,f=!!h&&!!h.omitPadding;n(this.buffer);for(var g="",k=0,y=m.length,_,S=function(R){return d(b,_>>6*R&63)};k+2>(-2*M&6)));return P}}),zA}var xA={},qA;function jD(){if(qA)return xA;qA=1;var e=I(),t=se(),r=Le(),a=te(),i=ye(),n=X(),o=xe(),l=Vt(),s=Ua().i2c,u=r("btoa"),d=a("".charAt),c=a("".charCodeAt),p=!!u&&!n(function(){return u("hi")!=="aGk="}),v=p&&!n(function(){u()}),m=p&&n(function(){return u(null)!=="bnVsbA=="}),h=p&&u.length!==1;return e({global:!0,bind:!0,enumerable:!0,forced:!p||v||m||h},{btoa:function(f){if(l(arguments.length,1),p)return i(u,t,o(f));for(var g=o(f),k="",y=0,_=s,S,R;d(g,y)||(_="=",y%1);){if(R=c(g,y+=3/4),R>255)throw new(r("DOMException"))("The string contains characters outside of the Latin1 range","InvalidCharacterError");S=S<<8|R,k+=d(_,63&S>>8-y%1*8)}return k}}),xA}var NA={},nu,LA;function yT(){return LA||(LA=1,nu={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}),nu}var ou,FA;function _T(){if(FA)return ou;FA=1;var e=ma(),t=e("span").classList,r=t&&t.constructor&&t.constructor.prototype;return ou=r===Object.prototype?void 0:r,ou}var VA;function CD(){if(VA)return NA;VA=1;var e=se(),t=yT(),r=_T(),a=kP(),i=ht(),n=function(l){if(l&&l.forEach!==a)try{i(l,"forEach",a)}catch{l.forEach=a}};for(var o in t)t[o]&&n(e[o]&&e[o].prototype);return n(r),NA}var BA={},UA;function OD(){if(UA)return BA;UA=1;var e=se(),t=yT(),r=_T(),a=_a(),i=ht(),n=Pt(),o=je(),l=o("iterator"),s=a.values,u=function(c,p){if(c){if(c[l]!==s)try{i(c,l,s)}catch{c[l]=s}if(n(c,p,!0),t[p]){for(var v in a)if(c[v]!==a[v])try{i(c,v,a[v])}catch{c[v]=a[v]}}}};for(var d in t)u(e[d]&&e[d].prototype,d);return u(r,"DOMTokenList"),BA}var $A={},su,HA;function ST(){return HA||(HA=1,su={IndexSizeError:{s:"INDEX_SIZE_ERR",c:1,m:1},DOMStringSizeError:{s:"DOMSTRING_SIZE_ERR",c:2,m:0},HierarchyRequestError:{s:"HIERARCHY_REQUEST_ERR",c:3,m:1},WrongDocumentError:{s:"WRONG_DOCUMENT_ERR",c:4,m:1},InvalidCharacterError:{s:"INVALID_CHARACTER_ERR",c:5,m:1},NoDataAllowedError:{s:"NO_DATA_ALLOWED_ERR",c:6,m:0},NoModificationAllowedError:{s:"NO_MODIFICATION_ALLOWED_ERR",c:7,m:1},NotFoundError:{s:"NOT_FOUND_ERR",c:8,m:1},NotSupportedError:{s:"NOT_SUPPORTED_ERR",c:9,m:1},InUseAttributeError:{s:"INUSE_ATTRIBUTE_ERR",c:10,m:1},InvalidStateError:{s:"INVALID_STATE_ERR",c:11,m:1},SyntaxError:{s:"SYNTAX_ERR",c:12,m:1},InvalidModificationError:{s:"INVALID_MODIFICATION_ERR",c:13,m:1},NamespaceError:{s:"NAMESPACE_ERR",c:14,m:1},InvalidAccessError:{s:"INVALID_ACCESS_ERR",c:15,m:1},ValidationError:{s:"VALIDATION_ERR",c:16,m:0},TypeMismatchError:{s:"TYPE_MISMATCH_ERR",c:17,m:1},SecurityError:{s:"SECURITY_ERR",c:18,m:1},NetworkError:{s:"NETWORK_ERR",c:19,m:1},AbortError:{s:"ABORT_ERR",c:20,m:1},URLMismatchError:{s:"URL_MISMATCH_ERR",c:21,m:1},QuotaExceededError:{s:"QUOTA_EXCEEDED_ERR",c:22,m:1},TimeoutError:{s:"TIMEOUT_ERR",c:23,m:1},InvalidNodeTypeError:{s:"INVALID_NODE_TYPE_ERR",c:24,m:1},DataCloneError:{s:"DATA_CLONE_ERR",c:25,m:1}}),su}var KA;function zD(){if(KA)return $A;KA=1;var e=I(),t=Le(),r=OP(),a=X(),i=bt(),n=It(),o=et().f,l=Qe(),s=ot(),u=Ve(),d=Dt(),c=Re(),p=gP(),v=Or(),m=ST(),h=Eu(),b=at(),f=Ae(),g=Ye(),k="DOMException",y="DATA_CLONE_ERR",_=t("Error"),S=t(k)||(function(){try{var K=t("MessageChannel")||r("worker_threads").MessageChannel;new K().port1.postMessage(new WeakMap)}catch(le){if(le.name===y&&le.code===25)return le.constructor}})(),R=S&&S.prototype,w=_.prototype,E=b.set,P=b.getterFor(k),A="stack"in new _(k),M=function(K){return u(m,K)&&m[K].m?m[K].c:0},T=function(){d(this,C);var le=arguments.length,ge=v(le<1?void 0:arguments[0]),_e=v(le<2?void 0:arguments[1],"Error"),ke=M(_e);if(E(this,{type:k,name:_e,message:ge,code:ke}),f||(this.name=_e,this.message=ge,this.code=ke),A){var Pe=new _(ge);Pe.name=k,o(this,"stack",n(1,h(Pe.stack,1)))}},C=T.prototype=i(w),z=function(K){return{enumerable:!0,configurable:!0,get:K}},q=function(K){return z(function(){return P(this)[K]})};f&&(s(C,"code",q("code")),s(C,"message",q("message")),s(C,"name",q("name"))),o(C,"constructor",n(1,T));var V=a(function(){return!(new S instanceof _)}),F=V||a(function(){return w.toString!==p||String(new S(1,2))!=="2: 1"}),j=V||a(function(){return new S(1,"DataCloneError").code!==25}),O=V||S[y]!==25||R[y]!==25,D=g?F||j||O:V;e({global:!0,constructor:!0,forced:D},{DOMException:D?T:S});var $=t(k),U=$.prototype;F&&(g||S===$)&&l(U,"toString",p),j&&f&&S===$&&s(U,"code",z(function(){return M(c(this).name)}));for(var ae in m)if(u(m,ae)){var Me=m[ae],he=Me.s,fe=n(6,Me.c);u($,he)||o($,he,fe),u(U,he)||o(U,he,fe)}return $A}var WA={},GA;function DD(){if(GA)return WA;GA=1;var e=I(),t=se(),r=Le(),a=It(),i=et().f,n=Ve(),o=Dt(),l=vr(),s=Or(),u=ST(),d=Eu(),c=Ae(),p=Ye(),v="DOMException",m=r("Error"),h=r(v),b=function(){o(this,f);var T=arguments.length,C=s(T<1?void 0:arguments[0]),z=s(T<2?void 0:arguments[1],"Error"),q=new h(C,z),V=new m(C);return V.name=v,i(q,"stack",a(1,d(V.stack,1))),l(q,this,b),q},f=b.prototype=h.prototype,g="stack"in new m(v),k="stack"in new h(1,2),y=h&&c&&Object.getOwnPropertyDescriptor(t,v),_=!!y&&!(y.writable&&y.configurable),S=g&&!_&&!k;e({global:!0,constructor:!0,forced:p||S},{DOMException:S?b:h});var R=r(v),w=R.prototype;if(w.constructor!==R){p||i(w,"constructor",a(1,R));for(var E in u)if(n(u,E)){var P=u[E],A=P.s;n(R,A)||i(R,A,a(6,P.c))}}return WA}var YA={},QA;function xD(){if(QA)return YA;QA=1;var e=Le(),t=Pt(),r="DOMException";return t(e(r),r),YA}var ZA={},JA={},XA;function qD(){if(XA)return JA;XA=1;var e=I(),t=se(),r=Da().clear;return e({global:!0,bind:!0,enumerable:!0,forced:t.clearImmediate!==r},{clearImmediate:r}),JA}var eM={},lu,tM;function Xu(){if(tM)return lu;tM=1;var e=se(),t=zt(),r=Ue(),a=wa(),i=Kt(),n=Ft(),o=Vt(),l=e.Function,s=/MSIE .\./.test(i)||a==="BUN"&&(function(){var u=e.Bun.version.split(".");return u.length<3||u[0]==="0"&&(u[1]<3||u[1]==="3"&&u[2]==="0")})();return lu=function(u,d){var c=d?2:1;return s?function(p,v){var m=o(arguments.length,1)>c,h=r(p)?p:l(p),b=m?n(arguments,c):[],f=m?function(){t(h,this,b)}:h;return d?u(f,v):u(f)}:u},lu}var rM;function ND(){if(rM)return eM;rM=1;var e=I(),t=se(),r=Da().set,a=Xu(),i=t.setImmediate?a(r,!1):r;return e({global:!0,bind:!0,enumerable:!0,forced:t.setImmediate!==i},{setImmediate:i}),eM}var aM;function LD(){return aM||(aM=1,qD(),ND()),ZA}var iM={},nM;function FD(){if(nM)return iM;nM=1;var e=I(),t=se(),r=JP(),a=Fe(),i=Vt(),n=X(),o=Ae(),l=n(function(){return o&&Object.getOwnPropertyDescriptor(t,"queueMicrotask").value.length!==1});return e({global:!0,enumerable:!0,dontCallGetSet:!0,forced:l},{queueMicrotask:function(u){i(arguments.length,1),r(a(u))}}),iM}var oM={},sM;function VD(){if(sM)return oM;sM=1;var e=I(),t=se(),r=ot(),a=Ae(),i=TypeError,n=Object.defineProperty,o=t.self!==t;try{if(a){var l=Object.getOwnPropertyDescriptor(t,"self");(o||!l||!l.get||!l.enumerable)&&r(t,"self",{get:function(){return t},set:function(u){if(this!==t)throw new i("Illegal invocation");n(t,"self",{value:u,writable:!0,configurable:!0,enumerable:!0})},configurable:!0,enumerable:!0})}else e({global:!0,simple:!0,forced:o},{self:t})}catch{}return oM}var lM={},uM;function BD(){if(uM)return lM;uM=1;var e=Ye(),t=I(),r=se(),a=Le(),i=te(),n=X(),o=Ir(),l=Ue(),s=mr(),u=Jt(),d=Ie(),c=ur(),p=ct(),v=Re(),m=Ct(),h=Ve(),b=Gt(),f=ht(),g=Ze(),k=Vt(),y=kr(),_=VP(),S=Ut(),R=Ur(),w=zP(),E=vP(),P=qu(),A=r.Object,M=r.Array,T=r.Date,C=r.Error,z=r.TypeError,q=r.PerformanceMark,V=a("DOMException"),F=_.Map,j=_.has,O=_.get,D=_.set,$=S.Set,U=S.add,ae=S.has,Me=a("Object","keys"),he=i([].push),fe=i((!0).valueOf),K=i(1.1.valueOf),le=i("".valueOf),ge=i(T.prototype.getTime),_e=o("structuredClone"),ke="DataCloneError",Pe="Transferring",He=function(L){return!n(function(){var G=new r.Set([7]),Q=L(G),Z=L(A(7));return Q===G||!Q.has(7)||!d(Z)||+Z!=7})&&L},We=function(L,G){return!n(function(){var Q=new G,Z=L({a:Q,b:Q});return!(Z&&Z.a===Z.b&&Z.a instanceof G&&Z.a.stack===Q.stack)})},qe=function(L){return!n(function(){var G=L(new r.AggregateError([1],_e,{cause:3}));return G.name!=="AggregateError"||G.errors[0]!==1||G.message!==_e||G.cause!==3})},Se=r.structuredClone,Ne=e||!We(Se,C)||!We(Se,V)||!qe(Se),ze=!Se&&He(function(L){return new q(_e,{detail:L}).detail}),Ce=He(Se)||ze,J=function(L){throw new V("Uncloneable type: "+L,ke)},oe=function(L,G){throw new V((G||"Cloning")+" of "+L+" cannot be properly polyfilled in this engine",ke)},Ee=function(L,G){return Ce||oe(G),Ce(L)},ie=function(){var L;try{L=new r.DataTransfer}catch{try{L=new r.ClipboardEvent("").clipboardData}catch{}}return L&&L.items&&L.files?L:null},me=function(L,G,Q){if(j(G,L))return O(G,L);var Z=Q||m(L),ne,H,we,Ke,W,ue;if(Z==="SharedArrayBuffer")Ce?ne=Ce(L):ne=L;else{var de=r.DataView;!de&&!l(L.slice)&&oe("ArrayBuffer");try{if(l(L.slice)&&!L.resizable)ne=L.slice(0);else for(H=L.byteLength,we=("maxByteLength"in L)?{maxByteLength:L.maxByteLength}:void 0,ne=new ArrayBuffer(H,we),Ke=new de(L),W=new de(ne),ue=0;ue1&&!u(arguments[1])?v(arguments[1]):void 0,Z=Q?Q.transfer:void 0,ne,H;Z!==void 0&&(ne=new F,H=De(Z,ne));var we=ce(G,ne);return H&&Xe(H),we}}),lM}var dM={},cM={},pM;function UD(){if(pM)return cM;pM=1;var e=I(),t=se(),r=Xu(),a=r(t.setInterval,!0);return e({global:!0,bind:!0,forced:t.setInterval!==a},{setInterval:a}),cM}var mM={},vM;function $D(){if(vM)return mM;vM=1;var e=I(),t=se(),r=Xu(),a=r(t.setTimeout,!0);return e({global:!0,bind:!0,forced:t.setTimeout!==a},{setTimeout:a}),mM}var fM;function HD(){return fM||(fM=1,UD(),$D()),dM}var gM={},hM={},uu,bM;function Ha(){if(bM)return uu;bM=1;var e=X(),t=je(),r=Ae(),a=Ye(),i=t("iterator");return uu=!e(function(){var n=new URL("b?a=1&b=2&c=3","https://a"),o=n.searchParams,l=new URLSearchParams("a=1&a=2&b=3"),s="";return n.pathname="c%20d",o.forEach(function(u,d){o.delete("b"),s+=d+u}),l.delete("a",2),l.delete("b",void 0),a&&(!n.toJSON||!l.has("a",1)||l.has("a",2)||!l.has("a",void 0)||l.has("b"))||!o.size&&(a||!r)||!o.sort||n.href!=="https://a/c%20d?a=1&c=3"||o.get("c")!=="3"||String(new URLSearchParams("?a=1"))!=="a=1"||!o[i]||new URL("https://a@b").username!=="a"||new URLSearchParams(new URLSearchParams("a=b")).get("a")!=="b"||new URL("https://тест").host!=="xn--e1aybc"||new URL("https://a#б").hash!=="#%D0%B1"||s!=="a1c3"||new URL("https://x",void 0).host!=="x"}),uu}var du,kM;function KD(){if(kM)return du;kM=1;var e=te(),t=2147483647,r=36,a=1,i=26,n=38,o=700,l=72,s=128,u="-",d=/[^\0-\u007E]/,c=/[.\u3002\uFF0E\uFF61]/g,p="Overflow: input needs wider integers to process",v=r-a,m=RangeError,h=e(c.exec),b=Math.floor,f=String.fromCharCode,g=e("".charCodeAt),k=e([].join),y=e([].push),_=e("".replace),S=e("".split),R=e("".toLowerCase),w=function(M){for(var T=[],C=0,z=M.length;C=55296&&q<=56319&&C>1,M+=b(M/T);M>v*i>>1;)M=b(M/v),z+=r;return b(z+(v+1)*M/(M+n))},A=function(M){var T=[];M=w(M);var C=M.length,z=s,q=0,V=l,F,j;for(F=0;F=z&&j<$&&($=j);var U=D+1;if($-z>b((t-q)/U))throw new m(p);for(q+=($-z)*U,z=$,F=0;Ft)throw new m(p);if(j===z){for(var ae=q,Me=r;;){var he=Me<=V?a:Me>=V+i?i:Me-V;if(ae0&&(W&de)!==0;de>>=1)ue++;return ue},ie=function(W){var ue=null;switch(W.length){case 1:ue=W[0];break;case 2:ue=(W[0]&31)<<6|W[1]&63;break;case 3:ue=(W[0]&15)<<12|(W[1]&63)<<6|W[2]&63;break;case 4:ue=(W[0]&7)<<18|(W[1]&63)<<12|(W[2]&63)<<6|W[3]&63;break}return ue>1114111?null:ue},me=function(W){W=Pe(W,ze," ");for(var ue=W.length,de="",pe=0;peue){de+="%",pe++;continue}var Be=oe(W,pe+1);if(Be!==Be){de+=Te,pe++;continue}pe+=2;var Je=Ee(Be);if(Je===0)Te=fe(Be);else{if(Je===1||Je>4){de+=Ce,pe++;continue}for(var tt=[Be],st=1;stue||ge(W,pe)!=="%"));){var _t=oe(W,pe+1);if(_t!==_t){pe+=3;break}if(_t>191||_t<128)break;ke(tt,_t),pe+=2,st++}if(tt.length!==Je){de+=Ce;continue}var $t=ie(tt);$t===null?de+=Ce:Te=K($t)}}de+=Te,pe++}return de},ve=/[!'()~]|%20/g,ce={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"},De=function(W){return ce[W]},Xe=function(W){return Pe(he(W),ve,De)},L=p(function(ue,de){V(this,{type:q,target:F(ue).entries,index:0,kind:de})},z,function(){var ue=j(this),de=ue.target,pe=ue.index++;if(!de||pe>=de.length)return ue.target=null,P(void 0,!0);var Te=de[pe];switch(ue.kind){case"keys":return P(Te.key,!1);case"values":return P(Te.value,!1)}return P([Te.key,Te.value],!1)},!0),G=function(W){this.entries=[],this.url=null,W!==void 0&&(y(W)?this.parseObject(W):this.parseQuery(typeof W=="string"?ge(W,0)==="?"?Se(W,1):W:_(W)))};G.prototype={type:z,bindURL:function(W){this.url=W,this.update()},parseObject:function(W){var ue=this.entries,de=E(W),pe,Te,Be,Je,tt,st,_t;if(de)for(pe=w(W,de),Te=pe.next;!(Be=i(Te,pe)).done;){if(Je=w(k(Be.value)),tt=Je.next,(st=i(tt,Je)).done||(_t=i(tt,Je)).done||!i(tt,Je).done)throw new Me("Expected sequence with length 2");ke(ue,{key:_(st.value),value:_(_t.value)})}else for(var $t in W)b(W,$t)&&ke(ue,{key:$t,value:_(W[$t])})},parseQuery:function(W){if(W)for(var ue=this.entries,de=qe(W,"&"),pe=0,Te,Be;pe0?arguments[0]:void 0,de=V(this,new G(ue));o||(this.size=de.entries.length)},Z=Q.prototype;if(d(Z,{append:function(ue,de){var pe=F(this);A(arguments.length,2),ke(pe.entries,{key:_(ue),value:_(de)}),o||this.length++,pe.updateURL()},delete:function(W){for(var ue=F(this),de=A(arguments.length,1),pe=ue.entries,Te=_(W),Be=de<2?void 0:arguments[1],Je=Be===void 0?Be:_(Be),tt=0;ttpe.key?1:-1}),ue.updateURL()},forEach:function(ue){for(var de=F(this).entries,pe=f(ue,arguments.length>1?arguments[1]:void 0),Te=0,Be;Te1?we(arguments[1]):{})}}),h(D)){var Ke=function(ue){return m(this,U),new D(ue,arguments.length>1?we(arguments[1]):{})};U.constructor=Ke,Ke.prototype=U,e({global:!0,constructor:!0,dontCallGetSet:!0,forced:!0},{Request:Ke})}}return cu={URLSearchParams:Q,getState:F},cu}var _M;function WD(){if(_M)return hM;_M=1,sT();var e=I(),t=Ae(),r=Ha(),a=se(),i=Ot(),n=te(),o=Qe(),l=ot(),s=Dt(),u=Ve(),d=KP(),c=yP(),p=Ft(),v=Fa().codeAt,m=KD(),h=xe(),b=Pt(),f=Vt(),g=wT(),k=at(),y=k.set,_=k.getterFor("URL"),S=g.URLSearchParams,R=g.getState,w=a.URL,E=a.TypeError,P=a.parseInt,A=Math.floor,M=Math.pow,T=n("".charAt),C=n(/./.exec),z=n([].join),q=n(1.1.toString),V=n([].pop),F=n([].push),j=n("".replace),O=n([].shift),D=n("".split),$=n("".slice),U=n("".toLowerCase),ae=n([].unshift),Me="Invalid authority",he="Invalid scheme",fe="Invalid host",K="Invalid port",le=/[a-z]/i,ge=/[\d+-.a-z]/i,_e=/\d/,ke=/^0x/i,Pe=/^[0-7]+$/,He=/^\d+$/,We=/^[\da-f]+$/i,qe=/[\0\t\n\r #%/:<>?@[\\\]^|]/,Se=/[\0\t\n\r #/:<>?@[\\\]^|]/,Ne=/^[\u0000-\u0020]+/,ze=/(^|[^\u0000-\u0020])[\u0000-\u0020]+$/,Ce=/[\t\n\r]/g,J,oe=function(N){var re=D(N,"."),B,x,Y,Oe,be,nt,lt;if(re.length&&re[re.length-1]===""&&re.length--,B=re.length,B>4)return N;for(x=[],Y=0;Y1&&T(Oe,0)==="0"&&(be=C(ke,Oe)?16:8,Oe=$(Oe,be===8?1:2)),Oe==="")nt=0;else{if(!C(be===10?He:be===8?Pe:We,Oe))return N;nt=P(Oe,be)}F(x,nt)}for(Y=0;Y=M(256,5-B))return null}else if(nt>255)return null;for(lt=V(x),Y=0;Y6))return;for(nt=0;pt();){if(lt=null,nt>0)if(pt()==="."&&nt<4)Y++;else return;if(!C(_e,pt()))return;for(;C(_e,pt());){if(vt=P(pt(),10),lt===null)lt=vt;else{if(lt===0)return;lt=lt*10+vt}if(lt>255)return;Y++}re[B]=re[B]*256+lt,nt++,(nt===2||nt===4)&&B++}if(nt!==4)return;break}else if(pt()===":"){if(Y++,!pt())return}else if(pt())return;re[B++]=Oe}if(x!==null)for(Lt=B-x,B=7;B!==0&&Lt>0;)ee=re[B],re[B--]=re[x+Lt-1],re[x+--Lt]=ee;else if(B!==8)return;return re},ie=function(N){for(var re=null,B=1,x=null,Y=0,Oe=0;Oe<8;Oe++)N[Oe]!==0?(Y>B&&(re=x,B=Y),x=null,Y=0):(x===null&&(x=Oe),++Y);return Y>B?x:re},me=function(N){var re,B,x,Y;if(typeof N=="number"){for(re=[],B=0;B<4;B++)ae(re,N%256),N=A(N/256);return z(re,".")}if(typeof N=="object"){for(re="",x=ie(N),B=0;B<8;B++)Y&&N[B]===0||(Y&&(Y=!1),x===B?(re+=B?":":"::",Y=!0):(re+=q(N[B],16),B<7&&(re+=":")));return"["+re+"]"}return N},ve={},ce=d({},ve,{" ":1,'"':1,"<":1,">":1,"`":1}),De=d({},ce,{"#":1,"?":1,"{":1,"}":1}),Xe=d({},De,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),L=function(N,re){var B=v(N,0);return B>32&&B<127&&!u(re,N)?N:encodeURIComponent(N)},G={ftp:21,file:null,http:80,https:443,ws:80,wss:443},Q=function(N,re){var B;return N.length===2&&C(le,T(N,0))&&((B=T(N,1))===":"||!re&&B==="|")},Z=function(N){var re;return N.length>1&&Q($(N,0,2))&&(N.length===2||(re=T(N,2))==="/"||re==="\\"||re==="?"||re==="#")},ne=function(N){return N==="."||U(N)==="%2e"},H=function(N){return N=U(N),N===".."||N==="%2e."||N===".%2e"||N==="%2e%2e"},we={},Ke={},W={},ue={},de={},pe={},Te={},Be={},Je={},tt={},st={},_t={},$t={},Ka={},ed={},Wa={},Rr={},Ht={},td={},or={},Qt={},Ga=function(N,re,B){var x=h(N),Y,Oe,be;if(re){if(Oe=this.parse(x),Oe)throw new E(Oe);this.searchParams=null}else{if(B!==void 0&&(Y=new Ga(B,!0)),Oe=this.parse(x,null,Y),Oe)throw new E(Oe);be=R(new S),be.bindURL(this),this.searchParams=be}};Ga.prototype={type:"URL",parse:function(N,re,B){var x=this,Y=re||we,Oe=0,be="",nt=!1,lt=!1,vt=!1,Lt,ee,pt,Zt;for(N=h(N),re||(x.scheme="",x.username="",x.password="",x.host=null,x.port=null,x.path=[],x.query=null,x.fragment=null,x.cannotBeABaseURL=!1,N=j(N,Ne,""),N=j(N,ze,"$1")),N=j(N,Ce,""),Lt=c(N);Oe<=Lt.length;){switch(ee=Lt[Oe],Y){case we:if(ee&&C(le,ee))be+=U(ee),Y=Ke;else{if(re)return he;Y=W;continue}break;case Ke:if(ee&&(C(ge,ee)||ee==="+"||ee==="-"||ee==="."))be+=U(ee);else if(ee===":"){if(re&&(x.isSpecial()!==u(G,be)||be==="file"&&(x.includesCredentials()||x.port!==null)||x.scheme==="file"&&!x.host))return;if(x.scheme=be,re){x.isSpecial()&&G[x.scheme]===x.port&&(x.port=null);return}be="",x.scheme==="file"?Y=Ka:x.isSpecial()&&B&&B.scheme===x.scheme?Y=ue:x.isSpecial()?Y=Be:Lt[Oe+1]==="/"?(Y=de,Oe++):(x.cannotBeABaseURL=!0,F(x.path,""),Y=td)}else{if(re)return he;be="",Y=W,Oe=0;continue}break;case W:if(!B||B.cannotBeABaseURL&&ee!=="#")return he;if(B.cannotBeABaseURL&&ee==="#"){x.scheme=B.scheme,x.path=p(B.path),x.query=B.query,x.fragment="",x.cannotBeABaseURL=!0,Y=Qt;break}Y=B.scheme==="file"?Ka:pe;continue;case ue:if(ee==="/"&&Lt[Oe+1]==="/")Y=Je,Oe++;else{Y=pe;continue}break;case de:if(ee==="/"){Y=tt;break}else{Y=Ht;continue}case pe:if(x.scheme=B.scheme,ee===J)x.username=B.username,x.password=B.password,x.host=B.host,x.port=B.port,x.path=p(B.path),x.query=B.query;else if(ee==="/"||ee==="\\"&&x.isSpecial())Y=Te;else if(ee==="?")x.username=B.username,x.password=B.password,x.host=B.host,x.port=B.port,x.path=p(B.path),x.query="",Y=or;else if(ee==="#")x.username=B.username,x.password=B.password,x.host=B.host,x.port=B.port,x.path=p(B.path),x.query=B.query,x.fragment="",Y=Qt;else{x.username=B.username,x.password=B.password,x.host=B.host,x.port=B.port,x.path=p(B.path),x.path.length--,Y=Ht;continue}break;case Te:if(x.isSpecial()&&(ee==="/"||ee==="\\"))Y=Je;else if(ee==="/")Y=tt;else{x.username=B.username,x.password=B.password,x.host=B.host,x.port=B.port,Y=Ht;continue}break;case Be:if(Y=Je,ee!=="/"||T(be,Oe+1)!=="/")continue;Oe++;break;case Je:if(ee!=="/"&&ee!=="\\"){Y=tt;continue}break;case tt:if(ee==="@"){nt&&(be="%40"+be),nt=!0,pt=c(be);for(var Ya=0;Ya65535)return K;x.port=x.isSpecial()&&Qa===G[x.scheme]?null:Qa,be=""}if(re)return;Y=Rr;continue}else return K;break;case Ka:if(x.scheme="file",ee==="/"||ee==="\\")Y=ed;else if(B&&B.scheme==="file")switch(ee){case J:x.host=B.host,x.path=p(B.path),x.query=B.query;break;case"?":x.host=B.host,x.path=p(B.path),x.query="",Y=or;break;case"#":x.host=B.host,x.path=p(B.path),x.query=B.query,x.fragment="",Y=Qt;break;default:Z(z(p(Lt,Oe),""))||(x.host=B.host,x.path=p(B.path),x.shortenPath()),Y=Ht;continue}else{Y=Ht;continue}break;case ed:if(ee==="/"||ee==="\\"){Y=Wa;break}B&&B.scheme==="file"&&!Z(z(p(Lt,Oe),""))&&(Q(B.path[0],!0)?F(x.path,B.path[0]):x.host=B.host),Y=Ht;continue;case Wa:if(ee===J||ee==="/"||ee==="\\"||ee==="?"||ee==="#"){if(!re&&Q(be))Y=Ht;else if(be===""){if(x.host="",re)return;Y=Rr}else{if(Zt=x.parseHost(be),Zt)return Zt;if(x.host==="localhost"&&(x.host=""),re)return;be="",Y=Rr}continue}else be+=ee;break;case Rr:if(x.isSpecial()){if(Y=Ht,ee!=="/"&&ee!=="\\")continue}else if(!re&&ee==="?")x.query="",Y=or;else if(!re&&ee==="#")x.fragment="",Y=Qt;else if(ee!==J&&(Y=Ht,ee!=="/"))continue;break;case Ht:if(ee===J||ee==="/"||ee==="\\"&&x.isSpecial()||!re&&(ee==="?"||ee==="#")){if(H(be)?(x.shortenPath(),ee!=="/"&&!(ee==="\\"&&x.isSpecial())&&F(x.path,"")):ne(be)?ee!=="/"&&!(ee==="\\"&&x.isSpecial())&&F(x.path,""):(x.scheme==="file"&&!x.path.length&&Q(be)&&(x.host&&(x.host=""),be=T(be,0)+":"),F(x.path,be)),be="",x.scheme==="file"&&(ee===J||ee==="?"||ee==="#"))for(;x.path.length>1&&x.path[0]==="";)O(x.path);ee==="?"?(x.query="",Y=or):ee==="#"&&(x.fragment="",Y=Qt)}else be+=L(ee,De);break;case td:ee==="?"?(x.query="",Y=or):ee==="#"?(x.fragment="",Y=Qt):ee!==J&&(x.path[0]+=L(ee,ve));break;case or:!re&&ee==="#"?(x.fragment="",Y=Qt):ee!==J&&(ee==="'"&&x.isSpecial()?x.query+="%27":ee==="#"?x.query+="%23":x.query+=L(ee,ve));break;case Qt:ee!==J&&(x.fragment+=L(ee,ce));break}Oe++}},parseHost:function(N){var re,B,x;if(T(N,0)==="["){if(T(N,N.length-1)!=="]"||(re=Ee($(N,1,-1)),!re))return fe;this.host=re}else if(this.isSpecial()){if(N=m(N),C(qe,N)||(re=oe(N),re===null))return fe;this.host=re}else{if(C(Se,N))return fe;for(re="",B=c(N),x=0;x1?arguments[1]:void 0,Y=y(B,new Ga(re,!1,x));t||(B.href=Y.serialize(),B.origin=Y.getOrigin(),B.protocol=Y.getProtocol(),B.username=Y.getUsername(),B.password=Y.getPassword(),B.host=Y.getHost(),B.hostname=Y.getHostname(),B.port=Y.getPort(),B.pathname=Y.getPathname(),B.search=Y.getSearch(),B.searchParams=Y.getSearchParams(),B.hash=Y.getHash())},Et=Er.prototype,Nt=function(N,re){return{get:function(){return _(this)[N]()},set:re&&function(B){return _(this)[re](B)},configurable:!0,enumerable:!0}};if(t&&(l(Et,"href",Nt("serialize","setHref")),l(Et,"origin",Nt("getOrigin")),l(Et,"protocol",Nt("getProtocol","setProtocol")),l(Et,"username",Nt("getUsername","setUsername")),l(Et,"password",Nt("getPassword","setPassword")),l(Et,"host",Nt("getHost","setHost")),l(Et,"hostname",Nt("getHostname","setHostname")),l(Et,"port",Nt("getPort","setPort")),l(Et,"pathname",Nt("getPathname","setPathname")),l(Et,"search",Nt("getSearch","setSearch")),l(Et,"searchParams",Nt("getSearchParams")),l(Et,"hash",Nt("getHash","setHash"))),o(Et,"toJSON",function(){return _(this).serialize()},{enumerable:!0}),o(Et,"toString",function(){return _(this).serialize()},{enumerable:!0}),w){var rd=w.createObjectURL,ad=w.revokeObjectURL;rd&&o(Er,"createObjectURL",i(rd,w)),ad&&o(Er,"revokeObjectURL",i(ad,w))}return b(Er,"URL"),e({global:!0,constructor:!0,forced:!r,sham:!t},{URL:Er}),hM}var SM;function GD(){return SM||(SM=1,WD()),gM}var wM={},RM;function YD(){if(RM)return wM;RM=1;var e=I(),t=Le(),r=X(),a=Vt(),i=xe(),n=Ha(),o=t("URL"),l=n&&r(function(){o.canParse()}),s=r(function(){return o.canParse.length!==1});return e({target:"URL",stat:!0,forced:!l||s},{canParse:function(d){var c=a(arguments.length,1),p=i(d),v=c<2||arguments[1]===void 0?void 0:i(arguments[1]);try{return!!new o(p,v)}catch{return!1}}}),wM}var EM={},AM;function QD(){if(AM)return EM;AM=1;var e=I(),t=Le(),r=Vt(),a=xe(),i=Ha(),n=t("URL");return e({target:"URL",stat:!0,forced:!i},{parse:function(l){var s=r(arguments.length,1),u=a(l),d=s<2||arguments[1]===void 0?void 0:a(arguments[1]);try{return new n(u,d)}catch{return null}}}),EM}var MM={},PM;function ZD(){if(PM)return MM;PM=1;var e=I(),t=ye();return e({target:"URL",proto:!0,enumerable:!0},{toJSON:function(){return t(URL.prototype.toString,this)}}),MM}var TM={},IM;function JD(){return IM||(IM=1,wT()),TM}var jM={},CM;function XD(){if(CM)return jM;CM=1;var e=Qe(),t=te(),r=xe(),a=Vt(),i=URLSearchParams,n=i.prototype,o=t(n.append),l=t(n.delete),s=t(n.forEach),u=t([].push),d=new i("a=1&a=2&b=3");return d.delete("a",1),d.delete("b",void 0),d+""!="a=2"&&e(n,"delete",function(c){var p=arguments.length,v=p<2?void 0:arguments[1];if(p&&v===void 0)return l(this,c);var m=[];s(this,function(S,R){u(m,{key:R,value:S})}),a(p,1);for(var h=r(c),b=r(v),f=0,g=0,k=!1,y=m.length,_;f
{{ $tc('mollie-payments.config.info.title', 0, { userName: userName}) }}
{{ $tc('mollie-payments.config.info.descriptionTop') }}

  1. {{ $tc('mollie-payments.config.info.onboardingStep1') }}
    https://www.mollie.com/signup
  2. {{ $tc('mollie-payments.config.info.onboardingStep2') }}
    {{ $tc('mollie-payments.config.info.onboardingStep2TestMode') }}
  3. {{ $tc('mollie-payments.config.info.onboardingStep3') }}
    {{ $tc('mollie-payments.config.info.onboardingStep3Link') }}

{{ $tc('mollie-payments.config.info.descriptionBottom') }}
{{ $tc('mollie-payments.config.info.btnDocumentation') }} {{ $tc('mollie-payments.config.info.btnRequestSupport') }} {{ $tc('mollie-payments.config.info.btnTroubleshooting') }}
`;class RT{equals(t,r){return this.compare(t,r,"=")}notEquals(t,r){return this.compare(t,r,"!=")}greater(t,r){return this.compare(t,r,">")}greaterOrEqual(t,r){return this.compare(t,r,">=")}lesser(t,r){return this.compare(t,r,"<")}lesserOrEqual(t,r){return this.compare(t,r,"<=")}compare(t,r,a="="){const i=this.matchVersion(t),n=this.matchVersion(r);if(i===null||n===null)return!1;switch(a){case"=":case"==":case"===":case"eq":return i.major===n.major&&i.minor===n.minor&&i.patch===n.patch&&i.build===n.build;case"!=":case"!==":case"neq":return!(i.major===n.major&&i.minor===n.minor&&i.patch===n.patch&&i.build===n.build);case">":case"gt":return i.major>n.major||i.minor>n.minor||i.patch>n.patch?!0:i.build>n.build;case">=":case"gte":return i.major=n.build;case"<":case"lt":return i.majori.major||n.minor>i.minor||n.patch>i.patch?!0:n.build>=i.build}return!1}matchVersion(t){const r=t.match(/(?(?\d+)\.?(?\d+)\.?(?\d+)\.?(?\d*))-?(?[a-z]+)?\.?(?\d+(?:.\d+)*)?/i);if(r===null)return console.warn(`${t} is not a valid version string.`),null;const a=r.groups;return["major","minor","patch","build"].forEach(i=>{a[i]=parseInt(a[i])||0}),a}getHumanReadableVersion(t){const r=this.matchVersion(t);if(r===null)return t;let a=`v${r.version}`;return r.prerelease?a+=` ${this.getHumanReadablePrereleaseText(r.prerelease)}`:a+=" Stable Version",r.prereleaseDigits&&(a+=` ${r.prereleaseDigits}`),a}getHumanReadablePrereleaseText(t){switch(t){case"dp":return"Developer Preview";case"rc":return"Release Candidate";case"dev":return"Developer Version";case"ea":return"Early Access";default:return t}}}const{Component:ix,Mixin:nx}=Shopware;ix.register("mollie-pluginconfig-section-info",{template:ax,mixins:[nx.getByName("notification")],data(){return{isSupportOpen:!1,versionCompare:null}},shortcuts:{"SYSTEMKEY+i":"openConfigImport"},created(){this.versionCompare=new RT},computed:{userName(){const e=this.getCurrentUser();return e?e.firstName===""?e.username:e.firstName:""},hasSalesChannelList(){return this.versionCompare.greaterOrEqual(Shopware.Context.app.config.version,"6.4.2")}},methods:{openConfigImport(){},getCurrentUser(){let e=Shopware.State.get("session");return e===void 0&&(e=Shopware.Store.get("session")),e.currentUser},openSupport(){this.isSupportOpen=!0},closeSupport(){this.isSupportOpen=!1}}});const ox=` {{ $tc('mollie-payments.config.api.testButton') }} {{ $tc('mollie-payments.config.api.apiLinkButton') }} `,{Component:sx,Mixin:lx}=Shopware;sx.register("mollie-pluginconfig-section-api",{template:ox,inject:["MolliePaymentsConfigService"],mixins:[lx.getByName("notification")],methods:{onTestButtonClicked(){const e=this,t=document.querySelector('input[name="MolliePayments.config.liveApiKey"]'),r=document.querySelector('input[name="MolliePayments.config.testApiKey"]'),a=t?t.value:null,i=r?r.value:null;this.MolliePaymentsConfigService.testApiKeys({liveApiKey:a,testApiKey:i}).then(n=>{n.results.forEach(function(o){const l={title:e.$tc("mollie-payments.config.api.testApiKeys.title"),message:`${e.$tc("mollie-payments.config.api.testApiKeys.apiKey")} "${o.key}" (${o.mode}) ${o.valid===!0?e.$tc("mollie-payments.config.api.testApiKeys.isValid"):e.$tc("mollie-payments.config.api.testApiKeys.isInvalid")}.`},s=o.mode==="live"?t:r;s&&s.parentNode.parentNode.classList.remove("has--error"),o.valid===!0?e.createNotificationSuccess(l):(e.createNotificationError(l),s&&s.parentNode.parentNode.classList.add("has--error"))})})}}});const ux=` {{ $tc('mollie-payments.config.payments.updatePaymentMethods.button') }} {{ $tc('mollie-payments.config.payments.mollieLimits.link') }} `,{Component:dx,Mixin:cx}=Shopware;dx.register("mollie-pluginconfig-section-payments",{template:ux,inject:["MolliePaymentsPaymentMethodService"],mixins:[cx.getByName("notification")],data(){return{updatePaymentMethodsIsLoading:!1}},methods:{onUpdatePaymentMethodsButtonClicked(){const e=this;this.startUpdatePaymentMethod(),this.MolliePaymentsPaymentMethodService.updatePaymentMethods().then(t=>{const r={title:e.$tc("mollie-payments.config.payments.updatePaymentMethods.title"),message:e.$tc("mollie-payments.config.payments.updatePaymentMethods.succeeded")};t.success===!0?e.createNotificationSuccess(r):(r.message=e.$tc("mollie-payments.config.payments.updatePaymentMethods.failed")+` + +Exception: +`+t.message,e.createNotificationError(r)),this.updatePaymentMethodsIsDone()}).catch(()=>{this.updatePaymentMethodsIsDone()})},startUpdatePaymentMethod(){this.updatePaymentMethodsIsLoading=!0},updatePaymentMethodsIsDone(){this.updatePaymentMethodsIsLoading=!1}}});const px=`
{{ $tc('mollie-payments.config.payments.format.placeholder') }}: {ordernumber}, {customernumber}
{{ $tc('mollie-payments.config.payments.format.preview') }}: "{{ sample1 }}", "{{ sample2 }}", ...
`;class mx{isNullOrEmpty(t){return t===void 0||t===null||t===""}replace(t,r,a){if(!a)return"";const i=new RegExp(t,"g");return a.replace(i,r)}}const{Component:vx}=Shopware;vx.register("mollie-pluginconfig-section-payments-format",{template:px,inject:["actualConfigData","currentSalesChannelId"],computed:{sample1(){return this.getFormat("1000","5000")},sample2(){return this.getFormat("5023","2525")}},methods:{getFormat(e,t){var n,o;const r=((o=(n=this.actualConfigData)==null?void 0:n[this.currentSalesChannelId])==null?void 0:o["MolliePayments.config.formatOrderNumber"])||"",a=new mx;let i=a.replace("{ordernumber}",e,r);return i=a.replace("{customernumber}",t,i),i}}});const fx=` {{ $tc('mollie-payments.config.rounding.info1') }}

{{ $tc('mollie-payments.config.rounding.info2') }}

{{ $tc('mollie-payments.config.rounding.info3') }}
`,{Component:gx}=Shopware;gx.register("mollie-pluginconfig-section-rounding",{template:fx,data(){return{}},computed:{},methods:{}});const hx=` {{ $tc('mollie-payments.config.support.success') }}
{{ $tc('mollie-payments.config.support.data.header') }}
{{ $tc('mollie-payments.config.support.data.shopwareVersion') }}
{{ shopwareVersion }}
{{ $tc('mollie-payments.config.support.data.other') }}
{{ $tc('mollie-payments.config.support.data.pluginLogs', 0, { plugin: molliePlugin.label }) }}
{{ $tc('mollie-payments.config.support.data.pluginConfiguration', 0, { plugin: molliePlugin.label }) }}
{{ $tc('mollie-payments.config.support.data.paymentMethods') }}
{{ $tc('mollie-payments.config.info.btnDocumentation') }} {{ $tc('mollie-payments.config.support.btnSupport') }}
`,{Application:bx,Component:kx,Context:NM,Mixin:yx,State:_x}=Shopware,{Criteria:Sx}=Shopware.Data,{string:sr}=Shopware.Utils;kx.register("mollie-pluginconfig-support-modal",{template:hx,inject:{shopwareExtensionService:{default:null},MolliePaymentsSupportService:{},repositoryFactory:{}},mixins:[yx.getByName("notification")],data(){return{mailSent:!1,isSubmitting:!1,name:"",email:"",subject:"",message:"",recipientLocale:"",recipientOptions:[{label:"International Support (info@mollie.com)",value:null},{label:"German Support (meinsupport@mollie.com)",value:"de-DE"}],versionCompare:null}},computed:{isLoading(){return this.shopwareExtensionService?this.getShopwareExtensions().loading:this.isLoadingPlugins},canSubmit(){return!sr.isEmptyOrSpaces(this.contactName)&&!sr.isEmptyOrSpaces(this.contactEmail)&&!sr.isEmptyOrSpaces(this.subject)&&!sr.isEmptyOrSpaces(this.message)},contactName:{get(){return sr.isEmptyOrSpaces(name)?this.userName:this.name},set(e){this.name=e}},contactEmail:{get(){return sr.isEmptyOrSpaces(this.email)?this.user.email:this.email},set(e){this.email=e}},locale(){return bx.getContainer("factory").locale.getLastKnownLocale()},user(){let e=Shopware.State.get("session");return e===void 0&&(e=Shopware.Store.get("session")),e.currentUser},userName(){if(!this.user)return"";const e=`${this.user.firstName} ${this.user.lastName}`.trim();return sr.isEmptyOrSpaces(e)?this.user.username:e},plugins(){if(this.shopwareExtensionService)return this.getShopwareExtensions().data||[];let e=Shopware.State.get("swPlugin");return e===void 0&&(e=Shopware.Store.get("swPlugin")),e.plugins||[]},molliePlugin(){return this.plugins.find(e=>e.name==="MolliePayments")},mollieVersion(){return this.molliePlugin?this.versionCompare.getHumanReadableVersion(this.molliePlugin.version):""},shopwareVersion(){return this.versionCompare.getHumanReadableVersion(NM.app.config.version)}},created(){this.versionCompare=new RT},mounted(){this.mountedComponent()},methods:{mountedComponent(){this.determineDefaultSupportDesk(),this.plugins.length===0&&(this.shopwareExtensionService?this.shopwareExtensionService.updateExtensionData():this.loadPluginsLegacy())},getShopwareExtensions(){let e=Shopware.State.get("shopwareExtensions");return e===void 0&&(e=Shopware.Store.get("shopwareExtensions")),e.myExtensions},determineDefaultSupportDesk(){this.recipientLocale=this.recipientOptions.some(e=>e.value===this.locale)?this.locale:null},loadPluginsLegacy(){this.isLoadingPlugins=!0;const e=new Sx;e.setTerm("Mollie");const t={criteria:e,repository:this.repositoryFactory.create("plugin"),context:NM.api};_x.dispatch("swPlugin/updatePluginList",t).finally(()=>{this.isLoadingPlugins=!1})},onRequestSupport(){this.isSubmitting=!0,this.MolliePaymentsSupportService.request(this.contactName,this.contactEmail,this.recipientLocale,this.subject,this.message).then(e=>{if(!e.success){this._showNotificationError(this.$tc("mollie-payments.config.support.error")),this.mailSent=!1;return}this.mailSent=!0,this._showNotificationSuccess(this.$tc("mollie-payments.config.support.success"))}).catch(e=>{this._showNotificationError(e)}).finally(()=>this.isSubmitting=!1)},_showNotificationSuccess(e){this.createNotificationSuccess({message:e})},_showNotificationError(e){this.createNotificationError({message:e})}}});const wx=` {{ $tc('mollie-payments.config.order.bankTransferDueDateKlarnaLimitReached') }} {{ $tc('mollie-payments.config.order.bankTransferDueDateLimitReached') }} `;class Rx{constructor(){this.maximumOrderLifeTimeKlarna=28,this.maximumOrderLifeTime=100}isOderLifeTimeLimitReached(t){return t>this.maximumOrderLifeTime}isKlarnaOrderLifeTimeReached(t){return t>this.maximumOrderLifeTimeKlarna&&t<=this.maximumOrderLifeTime}}const{Component:Ex,Mixin:Ax}=Shopware;Ex.register("mollie-pluginconfig-section-order-lifetime-warning",{template:wx,inject:["MolliePaymentsConfigService"],mixins:[Ax.getByName("notification")],data(){return{oderLifeTimeLimitReached:!1,klarnaOrderLifeTimeReached:!1}},created(){this.createdComponent()},methods:{createdComponent(){const e=new Rx,t=setInterval(()=>{const r=document.querySelector('input[name="MolliePayments.config.orderLifetimeDays"]');if(r===null)return;clearInterval(t);const a=parseInt(r.value);this.oderLifeTimeLimitReached=e.isOderLifeTimeLimitReached(a),this.klarnaOrderLifeTimeReached=e.isKlarnaOrderLifeTimeReached(a),r.addEventListener("keyup",i=>{const n=parseInt(i.target.value);this.oderLifeTimeLimitReached=e.isOderLifeTimeLimitReached(n),this.klarnaOrderLifeTimeReached=e.isKlarnaOrderLifeTimeReached(n)},!0)},500)}}});const{Component:Mx}=Shopware,{Criteria:LM}=Shopware.Data;Mx.extend("mollie-pluginconfig-element-orderstate-select","sw-entity-single-select",{props:{criteria:{type:Object,required:!1,default(){const e=new LM;return e.addFilter(LM.equals("stateMachine.technicalName","order.state")),e}}}});const Hr=Shopware.Classes.ApiService;class Px extends Hr{constructor(t,r,a){super(t,r,"mollie"),this.currentLocale=a}testApiKeys(t={liveApiKey:null,testApiKey:null}){const r=this.getBasicHeaders();return this.httpClient.post(`_action/${this.getApiBasePath()}/config/test-api-keys`,JSON.stringify(t),{headers:r}).then(a=>Hr.handleResponse(a))}validateFlowBuilder(){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/validate/flowbuilder`,{locale:this.currentLocale},{headers:this.getBasicHeaders()}).then(t=>Hr.handleResponse(t))}getSubscriptionConfig(){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/subscription`,{locale:this.currentLocale},{headers:this.getBasicHeaders()}).then(t=>Hr.handleResponse(t))}getRefundManagerConfig(t,r){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/refund-manager`,{salesChannelId:t,orderId:r},{headers:this.getBasicHeaders()}).then(a=>Hr.handleResponse(a))}}const FM=Shopware.Classes.ApiService;class Tx extends FM{constructor(t,r,a="mollie"){super(t,r,a)}getPaymentUrl(t={orderId:null}){const r=this.getBasicHeaders();return this.httpClient.post(`_action/${this.getApiBasePath()}/order/payment-url`,JSON.stringify(t),{headers:r}).then(a=>FM.handleResponse(a))}}const VM=Shopware.Classes.ApiService;class Ix extends VM{constructor(t,r,a="mollie"){super(t,r,a)}updatePaymentMethods(){const t=this.getBasicHeaders();return this.httpClient.get(`_action/${this.getApiBasePath()}/payment-method/update-methods`,{headers:t}).then(r=>VM.handleResponse(r))}}const mu=Shopware.Classes.ApiService;class jx extends mu{constructor(t,r,a="mollie"){super(t,r,a)}getRefundManagerData(t={orderId:null}){return this.__post("/refund-manager/data",t)}list(t={orderId:null}){return this.__post("/refund/list",t)}refund(t={orderId:null,amount:null,description:"",internalDescription:"",items:[]}){return this.__post("/refund",t)}refundAll(t={orderId:null,description:"",internalDescription:""}){return this.__post("/refund",t)}cancel(t={orderId:null,refundId:null}){return this.__post("/refund/cancel",t)}__post(t="",r={},a={}){return this.httpClient.post(`_action/${this.getApiBasePath()}${t}`,JSON.stringify(r),{headers:this.getBasicHeaders(a)}).then(i=>mu.handleResponse(i)).catch(i=>mu.handleResponse(i.response))}}const BM=Shopware.Classes.ApiService;class Cx extends BM{constructor(t,r,a="mollie"){super(t,r,a)}shipOrder(t,r,a,i,n){const o={orderId:t,trackingCarrier:r,trackingCode:a,trackingUrl:i,items:n};return this.__post("",o)}shipItem(t={orderId:null,itemId:null,quantity:null,trackingCarrier:null,trackingCode:null,trackingUrl:null}){return this.__post("/item",t)}status(t={orderId:null}){return this.__post("/status",t)}total(t={orderId:null}){return this.__post("/total",t)}__post(t="",r={},a={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/ship${t}`,JSON.stringify(r),{headers:this.getBasicHeaders(a)}).then(i=>BM.handleResponse(i))}}const UM=Shopware.Classes.ApiService;class Ox extends UM{constructor(t,r,a="mollie"){super(t,r,a)}__post(t="",r={},a={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/support${t}`,JSON.stringify(r),{headers:this.getBasicHeaders(a)}).then(i=>UM.handleResponse(i))}request(t,r,a,i,n){const o={name:t,email:r,recipientLocale:a,subject:i,message:n};return this.__post("/request",o)}}const Kr=Shopware.Classes.ApiService;class zx extends Kr{constructor(t,r,a="mollie"){super(t,r,a)}cancel(t={id:null,customerId:null,salesChannelId:null}){return this.__post("/cancel",t)}pause(t={id:null,customerId:null,salesChannelId:null}){return this.__post("/pause",t)}resume(t={id:null,customerId:null,salesChannelId:null}){return this.__post("/resume",t)}skip(t={id:null,customerId:null,salesChannelId:null}){return this.__post("/skip",t)}__get(t=""){return this.httpClient.get(`_action/${this.getApiBasePath()}/subscriptions${t}`,{headers:this.getBasicHeaders({})}).then(r=>Kr.handleResponse(r)).catch(r=>Kr.handleResponse(r.response))}__post(t="",r={},a={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/subscriptions${t}`,JSON.stringify(r),{headers:this.getBasicHeaders(a)}).then(i=>Kr.handleResponse(i)).catch(i=>Kr.handleResponse(i.response))}}const vu=Shopware.Classes.ApiService;class Dx extends vu{constructor(t,r,a="mollie"){super(t,r,a)}status(t={mollieOrderId:null}){return this.__post("/status",t)}cancel(t={mollieOrderId:null,mollieLineId:null,shopwareLineId:null,canceledQuantity:0,resetStock:!1}){return this.__post("/cancel",t)}__post(t="",r={},a={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/cancel-item${t}`,JSON.stringify(r),{headers:this.getBasicHeaders(a)}).then(i=>vu.handleResponse(i)).catch(i=>vu.handleResponse(i.response))}}const xx='{% block sw_condition_value_content %} {% endblock %}';Shopware.Component.extend("mollie-lineitem-subscription-rule","sw-condition-base",{template:xx,computed:{selectValues(){return[{label:this.$tc("global.sw-condition.condition.yes"),value:!0},{label:this.$tc("global.sw-condition.condition.no"),value:!1}]},isSubscription:{get(){return this.ensureValueExist(),this.condition.value.isSubscription==null&&(this.condition.value.isSubscription=!1),this.condition.value.isSubscription},set(e){this.ensureValueExist(),this.condition.value={...this.condition.value,isSubscription:e}}}}});const qx='{% block sw_condition_value_content %} {% endblock %}';Shopware.Component.extend("mollie-cart-subscription-rule","sw-condition-base",{template:qx,computed:{selectValues(){return[{label:this.$tc("global.sw-condition.condition.yes"),value:!0},{label:this.$tc("global.sw-condition.condition.no"),value:!1}]},isSubscription:{get(){return this.ensureValueExist(),this.condition.value.isSubscription==null&&(this.condition.value.isSubscription=!1),this.condition.value.isSubscription},set(e){this.ensureValueExist(),this.condition.value={...this.condition.value,isSubscription:e}}}}});const{Application:dt}=Shopware;dt.addServiceProvider("MolliePaymentsConfigService",e=>{const t=dt.getContainer("init"),r=dt.getContainer("factory").locale.getLastKnownLocale();return new Px(t.httpClient,e.loginService,r)});dt.addServiceProvider("MolliePaymentsOrderService",e=>{const t=dt.getContainer("init");return new Tx(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsPaymentMethodService",e=>{const t=dt.getContainer("init");return new Ix(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsRefundService",e=>{const t=dt.getContainer("init");return new jx(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsShippingService",e=>{const t=dt.getContainer("init");return new Cx(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsSupportService",e=>{const t=dt.getContainer("init");return new Ox(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsSubscriptionService",e=>{const t=dt.getContainer("init");return new zx(t.httpClient,e.loginService)});dt.addServiceProvider("MolliePaymentsItemCancelService",e=>{const t=dt.getContainer("init");return new Dx(t.httpClient,e.loginService)});dt.addServiceProviderDecorator("ruleConditionDataProviderService",e=>(e.addCondition("mollie_lineitem_subscription_rule",{component:"mollie-lineitem-subscription-rule",label:"mollie-payments.rules.itemSubscriptionRule",scopes:["lineitem"],group:"item"}),e.addCondition("mollie_cart_subscription_rule",{component:"mollie-cart-subscription-rule",label:"mollie-payments.rules.cartSubscriptionRule",scopes:["cart"],group:"cart"}),e));dt.addServiceProviderDecorator("searchTypeService",e=>(e.upsertType("mollie_subscription",{entityName:"mollie_subscription",placeholderSnippet:"mollie-payments.searchPlaceholder",listingRoute:"mollie.payments.subscriptions"}),e));const Ar=Object.freeze({MOLLIE_SHIP_ORDER:"action.mollie.order.ship",MOLLIE_REFUND_ORDER:"action.mollie.order.refund"}),{Component:Nx}=Shopware;Nx.override("sw-flow-sequence-action",{computed:{modalName(){return this.selectedAction===Ar.MOLLIE_SHIP_ORDER?"mollie-payments-flowsequence-action-order-ship-modal":this.selectedAction===Ar.MOLLIE_REFUND_ORDER?"mollie-payments-flowsequence-action-order-refund-modal":this.$super("modalName")},actionDescription(){return{...this.$super("actionDescription"),[Ar.MOLLIE_SHIP_ORDER]:t=>this.$tc("mollie-payments.sw-flow.actions.shipOrder.editor.description"),[Ar.MOLLIE_REFUND_ORDER]:t=>this.$tc("mollie-payments.sw-flow.actions.refundOrder.editor.description")}}},methods:{getActionTitle(e){return e===Ar.MOLLIE_SHIP_ORDER?{value:e,icon:"default-package-open",label:this.$tc("mollie-payments.sw-flow.actions.shipOrder.editor.title")}:e===Ar.MOLLIE_REFUND_ORDER?{value:e,icon:"default-symbol-euro",label:this.$tc("mollie-payments.sw-flow.actions.refundOrder.editor.title")}:this.$super("getActionTitle",e)}}});const Lx=`{% block sw_search_bar_item_cms_page %} {% parent %} {% block sw_search_bar_item_mollie_subscription_label %} {% endblock %} {% endblock %}`;Shopware.Component.override("sw-search-bar-item",{template:Lx});const Fx=`
{{ $tc('mollie-payments.sw-flow.actions.shipOrder.modal.title') }}

{{ $tc('mollie-payments.sw-flow.actions.shipOrder.modal.description') }}

{{ $tc('mollie-payments.sw-flow.actions.shipOrder.modal.warningConfig') }}
  • {{ $tc('mollie-payments.sw-flow.actions.shipOrder.modal.noWarnings') }}
  • {{ warning }}
`,{Component:Vx}=Shopware;Vx.register("mollie-payments-flowsequence-action-order-ship-modal",{template:Fx,inject:["MolliePaymentsConfigService"],props:{sequence:{type:Object,required:!0}},data(){return{tags:[],warnings:[]}},created(){this.createdComponent(),this.MolliePaymentsConfigService.validateFlowBuilder().then(e=>{this.warnings=e.actions.shipping.warnings})},methods:{createdComponent(){this.sequence&&this.sequence.config?this.tags=this.sequence.config.tags:this.tags=[]},onClose(){this.$emit("modal-close")},onAddAction(){const e={...this.sequence,config:{...this.config,tags:this.tags}};this.$emit("process-finish",e)}}});const Bx=`
{{ $tc('mollie-payments.sw-flow.actions.refundOrder.modal.title') }}

{{ $tc('mollie-payments.sw-flow.actions.refundOrder.modal.description') }}

{{ $tc('mollie-payments.sw-flow.actions.refundOrder.modal.warning') }} {{ $tc('mollie-payments.sw-flow.actions.refundOrder.modal.warningConfig') }}
`,{Component:Ux}=Shopware;Ux.register("mollie-payments-flowsequence-action-order-refund-modal",{template:Bx,inject:["MolliePaymentsConfigService"],props:{sequence:{type:Object,required:!0}},data(){return{tags:[]}},created(){this.createdComponent()},methods:{createdComponent(){this.sequence&&this.sequence.config?this.tags=this.sequence.config.tags:this.tags=[]},onClose(){this.$emit("modal-close")},onAddAction(){const e={...this.sequence,config:{...this.config,tags:this.tags}};this.$emit("process-finish",e)}}});const $x='{% block credit_card_logo %}
{% endblock %}',{Component:Hx}=Shopware;Hx.register("mollie-credit-card-logo",{template:$x,props:{creditCardCompany:{type:String,required:!0,default:""}},methods:{getImageNameForCreditcard(e){switch(e){case"American Express":return"amex";case"Carta Si":return"cartasi";case"Carte Bleue":return"cartebancaire";case"Maestro":return"maestro";case"Mastercard":return"mastercard";case"Visa":return"visa";default:return"creditcard"}}},computed:{creditCardComponentName(){const e="mollie-credit-card-logo-",t=this.getImageNameForCreditcard(this.creditCardCompany);return`${e}${t}`}}});const Kx={_searchable:!0,description:{_searchable:!0,_score:500}},Wx=`{% block mollie_payments_subscription_list %} {% block mollie_payments_subscription_list_search_bar %} {% endblock %} {% block mollie_payments_subscription_list_smart_bar_header %} {% endblock %} {% endblock %}`,{Application:Gx}=Shopware;class Yx{buildColumns(){const t=Gx.getApplicationRoot();return t?[{property:"createdAt",label:t.$tc("mollie-payments.subscriptions.list.columns.createdAt"),allowResize:!0},{property:"customerId",label:t.$tc("mollie-payments.subscriptions.list.columns.customer"),allowResize:!0},{property:"description",label:t.$tc("mollie-payments.subscriptions.list.columns.description"),allowResize:!0},{property:"status",label:t.$tc("mollie-payments.subscriptions.list.columns.status"),allowResize:!0,sortable:!0},{property:"amount",label:t.$tc("mollie-payments.subscriptions.list.columns.amount"),allowResize:!0,align:"right"},{property:"nextPaymentAt",label:t.$tc("mollie-payments.subscriptions.list.columns.nextPaymentAt"),allowResize:!0},{property:"lastRemindedAt",label:t.$tc("mollie-payments.subscriptions.list.columns.prePaymentReminder"),allowResize:!0},{property:"canceledAt",dataIndex:"canceledAt",label:t.$tc("mollie-payments.subscriptions.list.columns.canceledAt"),visible:!0}]:[]}}class ET{constructor(t){this._app=t}getStatusTranslation(t){return(t===""||t===null)&&(t=""),["pending","active","canceled","suspended","completed","paused","resumed","skipped"].includes(t)?this._app.$tc("mollie-payments.subscriptions.status."+t):t}getStatusColor(t){return t===""||t===null?"neutral":t==="active"||t==="resumed"?"success":t==="canceled"||t==="suspended"||t==="completed"?"neutral":t==="skipped"?"info":t==="pending"||t==="paused"?"warning":"danger"}isCancellationAllowed(t){return t!=="canceled"&&t!=="pending"}isSkipAllowed(t){return t==="active"||t==="resumed"}isPauseAllowed(t){return t==="active"||t==="resumed"}isResumeAllowed(t){return t==="paused"||t==="canceled"}}const{Component:$M,Mixin:fu,Application:Qx,Filter:HM}=Shopware,{Criteria:KM}=Shopware.Data;$M.register("mollie-subscriptions-list",{template:Wx,inject:["systemConfigApiService","MolliePaymentsSubscriptionService","repositoryFactory","acl"],mixins:[fu.getByName("notification"),fu.getByName("listing"),fu.getByName("placeholder")],data(){return{isLoading:!0,systemConfig:null,subscriptions:null,sortBy:"createdAt",sortDirection:"DESC",naturalSorting:!0,showHelp:!1,searchConfigEntity:"mollie_subscription"}},metaInfo(){return{title:this.$createTitle()}},computed:{repoSubscriptions(){return this.repositoryFactory.create("mollie_subscription")},subscriptionService(){return new ET(Qx.getApplicationRoot())},prePaymentReminderEmail(){return this.systemConfig&&this.systemConfig["MolliePayments.config.prePaymentReminderEmail"]!==void 0?this.systemConfig["MolliePayments.config.prePaymentReminderEmail"]:null},totalSubscriptions(){return this.subscriptions.length},compatibilityIcons(){return{refresh:$M.getComponentRegistry().has("icons-regular-undo")?"regular-undo":"default-arrow-360-left"}},currencyFilter(){return HM.getByName("currency")},dateFilter(){return HM.getByName("date")}},methods:{gridColumns(){return new Yx().buildColumns()},async getList(){this.isLoading=!0,this.naturalSorting=this.sortBy==="createdAt";let e=new KM;"addQueryScores"in this?e=await this.addQueryScores(this.term,e):e.setTerm(this.term),e.addSorting(KM.sort(this.sortBy,this.sortDirection,this.naturalSorting)),e.addAssociation("customer"),e.addAssociation("currency"),this.repoSubscriptions.search(e,Shopware.Context.api).then(t=>{this.subscriptions=t,this.isLoading=!1})},statusTranslation(e){return this.subscriptionService.getStatusTranslation(e)},statusColor(e){return this.subscriptionService.getStatusColor(e)}}});const Zx=`{% block sw_order_detail %} {% block sw_order_detail_actions %} {% endblock %} {% endblock %}`,{Component:Jx,Mixin:WM,Application:Xx,ApiService:e1,Filter:t1}=Shopware,{Criteria:GM}=Shopware.Data;Jx.register("mollie-subscriptions-detail",{template:Zx,inject:["MolliePaymentsSubscriptionService","repositoryFactory","acl"],mixins:[WM.getByName("notification"),WM.getByName("placeholder")],data(){return{isLoading:!0,allowPauseResume:!1,allowSkip:!1,showConfirmCancel:!1,showConfirmPause:!1,showConfirmResume:!1,showConfirmSkip:!1,subscription:null,history:[],customerFullName:"",translatedStatus:"",formattedCreateAt:"",formattedNextPaymentAt:"",formattedLastRemindedAt:"",formattedCanceledAt:""}},metaInfo(){return{title:this.$createTitle()}},computed:{repoSubscriptions(){return this.repositoryFactory.create("mollie_subscription")},subscriptionService(){return new ET(Xx.getApplicationRoot())},subscriptionId(){return this.$route.params.id},isAclEditAllowed(){return this.acl.can("mollie_subscription:update")},isAclCancelAllowed(){return this.acl.can("mollie_subscription_custom:cancel")},isCancellationAllowed(){return this.subscription===null?!1:this.subscriptionService.isCancellationAllowed(this.subscription.status)},isPauseAllowed(){return this.subscription===null?!1:this.subscriptionService.isPauseAllowed(this.subscription.status)},isResumeAllowed(){return this.subscription===null?!1:this.subscriptionService.isResumeAllowed(this.subscription.status)},isSkipAllowed(){return this.subscription===null?!1:this.subscriptionService.isSkipAllowed(this.subscription.status)},cardTitleHistory(){return this.$tc("mollie-payments.subscriptions.detail.history.cardTitle")+" ("+this.history.length+")"},dateFilter(){return t1.getByName("date")}},created(){this.createdComponent()},methods:{createdComponent(){this.loadDetails()},loadDetails(){this.isLoading=!0;const e=new GM;e.addFilter(GM.equals("id",this.subscriptionId)),e.addAssociation("addresses"),e.addAssociation("historyEntries"),e.addAssociation("customer"),e.addAssociation("currency"),this.repoSubscriptions.search(e,Shopware.Context.api).then(r=>{this.subscription=r[0],this.customerFullName=this.subscription.customer.firstName+" "+this.subscription.customer.lastName,this.translatedStatus=this.statusTranslation(this.subscription.status),this.formattedCreateAt=this.getFormattedDate(this.subscription.createdAt),this.formattedNextPaymentAt=this.getFormattedDate(this.subscription.nextPaymentAt),this.formattedLastRemindedAt=this.getFormattedDate(this.subscription.lastRemindedAt),this.formattedCanceledAt=this.getFormattedDate(this.subscription.canceledAt),this.history=this.subscription.historyEntries,this.history.sort(function(a,i){return new Date(i.createdAt)-new Date(a.createdAt)}),this.history.forEach(a=>{a.statusFromTranslated=this.subscriptionService.getStatusTranslation(a.statusFrom),a.statusToTranslated=this.subscriptionService.getStatusTranslation(a.statusTo)}),this.isLoading=!1}),e1.getByName("systemConfigApiService").getValues("MolliePayments").then(r=>{this.allowPauseResume=r["MolliePayments.config.subscriptionsAllowPauseResume"],this.allowSkip=r["MolliePayments.config.subscriptionsAllowSkip"]})},statusTranslation(e){return this.subscriptionService.getStatusTranslation(e)},statusColor(e){return this.subscriptionService.getStatusColor(e)},getFormattedDate(e){if(e===null||e==="")return"";const t=Shopware;if(t.Utils.format.dateWithUserTimezone){const r=t.Utils.format.dateWithUserTimezone(new Date(e));return r.toLocaleDateString()+" "+r.toLocaleTimeString()}return t.Utils.format.date(new Date(e))},btnCancel_Click(){this.isAclCancelAllowed&&(this.showConfirmCancel=!0)},btnPause_Click(){this.showConfirmPause=!0},btnResume_Click(){this.showConfirmResume=!0},btnSkip_Click(){this.showConfirmSkip=!0},btnCloseAnyModal_Click(){this.showConfirmCancel=!1,this.showConfirmPause=!1,this.showConfirmResume=!1,this.showConfirmSkip=!1},btnConfirmCancel_Click(){this.showConfirmCancel=!1,this.isAclCancelAllowed&&this.MolliePaymentsSubscriptionService.cancel({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.cancelSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmPause_Click(){this.showConfirmPause=!1,this.MolliePaymentsSubscriptionService.pause({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.pauseSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmResume_Click(){this.showConfirmResume=!1,this.MolliePaymentsSubscriptionService.resume({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.resumeSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmSkip_Click(){this.showConfirmSkip=!1,this.MolliePaymentsSubscriptionService.skip({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.skipSuccess")})):this.createNotificationError({message:e.errors[0]})})}}});const{Module:r1,Plugin:a1,Service:i1}=Shopware,n1=a1.addBootPromise(),o1=i1("MolliePaymentsConfigService");o1.getSubscriptionConfig().then(e=>{const t=[];e.enabled===!0&&t.push({id:"mollie-subscriptions",label:"mollie-payments.subscriptions.navigation.title",path:"mollie.payments.subscriptions",parent:"sw-order",position:10,privilege:"mollie_subscription:read"}),r1.register("mollie-payments",{type:"plugin",title:"mollie-payments.general.mainMenuItemGeneral",description:"mollie-payments.general.descriptionTextModule",version:"1.0.0",targetVersion:"1.0.0",color:"#333",icon:"regular-shopping-bag",entity:"mollie_subscription",routes:{subscriptions:{component:"mollie-subscriptions-list",path:"subscriptions",meta:{privilege:"mollie_subscription:read"}},subscription_detail:{component:"mollie-subscriptions-detail",path:"subscription/detail/:id",props:{default:r=>({subscriptionId:r.params.id})},meta:{parentPath:"mollie.payments.subscriptions",privilege:"mollie_subscription:read"}}},navigation:t,defaultSearchConfiguration:Kx})}).finally(()=>{n1()});const s1=`{% block sw_product_detail_content_tabs_cross_selling %} {% parent %} Mollie {% endblock %}`;Shopware.Component.override("sw-product-detail",{template:s1});const l1=`
{% block sw_product_detail_mollie_vouchers %} {{ $tc('mollie-payments.vouchers.VOUCHER_INFO_TITLE') }}

{{ $tc('mollie-payments.vouchers.VOUCHER_INFO_DESCRIPTION') }}

{{ $tc('mollie-payments.vouchers.VOUCHER_BTN_READMORE') }}
{{ $tc('mollie-payments.vouchers.VOUCHER_INFO_DEFAULTLANGUAGE') }}
{% endblock %} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {% block sw_product_detail_mollie_subscription %} {{ $tc('mollie-payments.subscriptions.product.title') }}

{{ $tc('mollie-payments.subscriptions.product.description') }}

{{ $tc('mollie-payments.subscriptions.product.btnReadMore') }}
{# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {{ $tc('mollie-payments.subscriptions.product.infoDefaultLanguage') }}
{% endblock %}
`;Shopware.Component.register("sw-product-detail-mollie",{template:l1,inject:["repositoryFactory"],metaInfo(){return{title:"Mollie"}},data(){return{}},watch:{product(){this.initFields()},parentProduct(){this.initFields()}},created(){this.initFields()},computed:{productId(){return this.$route.params.id},product(){let e=Shopware.State.get("swProductDetail");return e===void 0&&(e=Shopware.Store.get("swProductDetail")),e.product},parentProduct(){let e=Shopware.State.get("swProductDetail");return e===void 0&&(e=Shopware.Store.get("swProductDetail")),e.parentProduct},isLoading(){let e=Shopware.State.get("swProductDetail");return e===void 0&&(e=Shopware.Store.get("swProductDetail")),e.isLoading},context(){let e=Shopware.State.get("context");return e===void 0&&(e=Shopware.Store.get("context")),e},languageId(){return this.context.languageId},systemLanguageId(){return this.context.systemLanguageId},isSystemDefaultLanguage(){return this.context.isSystemDefaultLanguage},voucherTypes(){return[{value:0,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_NONE")},{value:1,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_ECO")},{value:2,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_MEAL")},{value:3,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_VOUCHER")}]},voucherTypeNONE(){return"0"},subscriptionIntervalTypes(){return[{value:"days",label:this.$tc("mollie-payments.subscriptions.TYPE_DAYS")},{value:"weeks",label:this.$tc("mollie-payments.subscriptions.TYPE_WEEKS")},{value:"months",label:this.$tc("mollie-payments.subscriptions.TYPE_MONTHS")}]},isDefaultLanguage(){return this.languageId===this.systemLanguageId}},methods:{initFields(){this.product&&(this.product.customFields||(this.product.customFields={})),this.parentProduct&&(this.parentProduct.customFields||(this.parentProduct.customFields={}))}}});const{Module:u1}=Shopware;u1.register("mollie-sw-product-detail",{type:"plugin",name:"MolliePayments",title:"mollie-payments.pluginTitle",description:"mollie-payments.pluginDescription",version:"1.0.0",targetVersion:"1.0.0",color:"#333",icon:"default-action-settings",routeMiddleware(e,t){t.name==="sw.product.detail"&&t.children.push({name:"sw.product.detail.mollie",path:"/sw/product/detail/:id/mollie",component:"sw-product-detail-mollie",meta:{parentPath:"sw.product.index"}}),e(t)}});Shopware.Service("privileges").addPrivilegeMappingEntry({category:"permissions",parent:"mollie",key:"mollie_refund_manager",roles:{viewer:{privileges:["mollie_refund_manager:read","mollie_refund:read"],dependencies:[]},creator:{privileges:["mollie_refund_manager:create","mollie_refund:create"],dependencies:["mollie_refund_manager.viewer"]},deleter:{privileges:["mollie_refund_manager:delete","mollie_refund:delete"],dependencies:["mollie_refund_manager.creator"]}}});Shopware.Service("privileges").addPrivilegeMappingEntry({category:"permissions",parent:"mollie",key:"mollie_subscription",roles:{viewer:{privileges:["mollie_subscription:read","mollie_subscription_address:read","mollie_subscription_history:read"],dependencies:[]},editor:{privileges:["mollie_subscription:update","mollie_subscription_address:create","mollie_subscription_address:update","mollie_subscription_history:create","mollie_subscription_history:update"],dependencies:["mollie_subscription.viewer"]},deleter:{privileges:["mollie_subscription_custom:cancel"],dependencies:["mollie_subscription.viewer"]}}});const d1=`{% block sw_order_line_items_grid_actions %} {% parent %} {% block sw_order_line_items_grid_line_item_filter %} {% parent %} {% endblock %} {# =================================================================================================================== MOLLIE ACTIONS =================================================================================================================== #} {% block sw_order_line_items_grid_mollie_actions %}
{% block sw_order_line_items_grid_mollie_actions_button %} {{ $tc('mollie-payments.general.btnMollieActions') }} ({{ possibleActionsCount }}) {% endblock %} {% block sw_order_line_items_grid_mollie_actions_context_button %} {% block sw_order_line_items_grid_mollie_actions_dropdown %} {% block sw_order_line_items_grid_mollie_actions_dropdown_ship %} {{ $tc('mollie-payments.general.shipThroughMollie') }} {% endblock %} {% block sw_order_line_items_grid_mollie_actions_dropdown_refund %} {{ $tc('sw-order.detailExtended.refundManager.btnOpenRefundManager') }} {% endblock %} {% endblock %} {% endblock %}
{% endblock %}
{# =================================================================================================================== REFUND MANAGER =================================================================================================================== #} {# =================================================================================================================== SHIPPING =================================================================================================================== #} {% endblock %} {% block sw_order_line_items_grid_grid_columns %} {% parent %} {% endblock %} {% block sw_order_line_items_grid_grid_actions_modals_items %} {% parent %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_product %}
{{ $tc('mollie-payments.modals.shipping.item.label') }} {{ item.label }}
{% endblock %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_description %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary_shipped %}
{{ $tc('mollie-payments.modals.shipping.item.summary.shipped') }}
{{ shippedQuantity(item) }}
{% endblock %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary_shippable %}
{{ $tc('mollie-payments.modals.shipping.item.summary.shippable') }}
{{ shippableQuantity(item) }}
{% endblock %} {% endblock %}
{% endblock %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_quantity %} {% endblock %} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_tracking %} {% endblock %}
{% endblock %} {% block sw_order_line_items_grid_grid_mollie_cancel_item_modal %} {% endblock %} {% endblock %} {% block sw_order_line_items_grid_grid_actions_show %} {% parent %} {{ $tc('mollie-payments.general.shipThroughMollie') }} {{ $tc('mollie-payments.general.cancelMollieItem') }} {% endblock %}`;class c1{constructor(t){if(this._audience="",this._countryCode="",this._feeRegion="",this._holder="",this._label="",this._number="",this._security="",t!==null)return this._audience=this._convertString(t.creditCardAudience),this._countryCode=this._convertString(t.creditCardCountryCode),this._feeRegion=this._convertString(t.creditCardFeeRegion),this._holder=this._convertString(t.creditCardHolder),this._label=this._convertString(t.creditCardLabel),this._number=this._convertString(t.creditCardNumber),this._security=this._convertString(t.creditCardSecurity),null}hasCreditCardData(){return!!this._audience&&!!this._countryCode&&!!this._feeRegion&&!!this._holder&&!!this._label&&!!this._number}getAudience(){return this._audience}getCountryCode(){return this._countryCode}getFeeRegion(){return this._feeRegion}getHolder(){return this._holder}getLabel(){return this._label}getNumber(){return this._number}getSecurity(){return this._security}_convertString(t){return t==null?"":String(t)}}class ut{constructor(t){if(this._orderId="",this._paymentId="",this._swSubscriptionId="",this._creditCardAttributes=null,this._paymentRef=null,t===null||(this.customFields=t.customFields,this.customFields===null||this.customFields===void 0)||this.customFields.mollie_payments===void 0||this.customFields.mollie_payments===null)return;const r=this.customFields.mollie_payments;this._orderId=this._convertString(r.order_id),this._paymentId=this._convertString(r.payment_id),this._swSubscriptionId=this._convertString(r.swSubscriptionId),this._paymentRef=this._convertString(r.third_party_payment_id),this._creditCardAttributes=new c1(r)}isMollieOrder(){return this.customFields!==null&&"mollie_payments"in this.customFields}getCreditCardAttributes(){return this._creditCardAttributes}getOrderId(){return this._orderId}getPaymentId(){return this._paymentId}getMollieID(){return this.getOrderId()!==""?this.getOrderId():this.getPaymentId()!==""?this.getPaymentId():null}isSubscription(){return this.getSwSubscriptionId()!==""}getSwSubscriptionId(){return this._swSubscriptionId}getPaymentRef(){return this._paymentRef}_convertString(t){return t==null?"":String(t)}}class gu{constructor(t,r){this._configService=t,this._acl=r}async isRefundManagerAvailable(t,r){var o,l,s;if((((s=(l=(o=r==null?void 0:r.transactions)==null?void 0:o[0])==null?void 0:l.stateMachineState)==null?void 0:s.technicalName)??"unknown")==="authorized"||!this._acl.can("mollie_refund_manager:read"))return!1;let n=!1;return await this._configService.getRefundManagerConfig(t,r.id).then(u=>{n=u.enabled}),n}}class ua{constructor(t){this._shippingService=t}async isShippingPossible(t){if(new ut(t).getOrderId()==="")return!1;const a=await this.getShippableItems(t);for(let i=0;i0)return!0;return!1}async getShippableItems(t){await this._shippingService.status({orderId:t.id}).then(a=>{this.shippedLineItems=a});const r=[];for(let a=0;a{this.onCloseShipOrderModal()}):Shopware.Utils.EventBus.on(lr.EventShippedOrder,()=>{this.onCloseShipOrderModal()}),this.refundedManagerService=new gu(this.MolliePaymentsConfigService,this.acl),this.shippingManagerService=new ua(this.MolliePaymentsShippingService),this.reloadData())},async reloadData(){var e,t;this.isShippingPossible=await((e=this.shippingManagerService)==null?void 0:e.isShippingPossible(this.order))||!1,this.isRefundManagerPossible=await((t=this.refundedManagerService)==null?void 0:t.isRefundManagerAvailable(this.order.salesChannelId,this.order.id))||!1,await this.loadMollieShippingStatus(),await this.loadMollieCancelStatus()},onOpenRefundManager(){this.showRefundModal=!0},onCloseRefundManager(){this.showRefundModal=!1,location.reload()},onOpenShipOrderModal(){this.showShipOrderModal=!0},onCloseShipOrderModal(){this.showShipOrderModal=!1,this.reloadData()},onOpenShipItemModal(e){this.showShipItemModal=e.id,this.updateTrackingPrefilling()},onOpenCancelItemModal(e){this.cancelItemModal=e.id},closeCancelItemModal(){this.cancelItemModal=null},onCloseShipItemModal(){this.isShipItemLoading=!1,this.showShipItemModal=!1,this.shipQuantity=0,this.resetTracking(),this.reloadData()},async loadMollieShippingStatus(){await this.MolliePaymentsShippingService.status({orderId:this.order.id}).then(e=>{this.shippingStatus=e})},async loadMollieCancelStatus(){await this.MolliePaymentsItemCancelService.status({mollieOrderId:this.mollieId}).then(e=>{this.cancelStatus=e})},onConfirmShipItem(e){if(this.shipQuantity===0){this.createNotificationError({message:this.$tc("mollie-payments.modals.shipping.item.noQuantity")});return}if(this.showTrackingInfo&&!this.validateTracking()){this.createNotificationError({message:this.$tc("mollie-payments.modals.shipping.tracking.invalid")});return}this.isShipItemLoading!==!0&&(this.isShipItemLoading=!0,this.MolliePaymentsShippingService.shipItem({orderId:this.order.id,itemId:e.id,quantity:this.shipQuantity,trackingCarrier:this.tracking.carrier,trackingCode:this.tracking.code,trackingUrl:this.tracking.url}).then(()=>{this.isShipItemLoading=!1,this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.shipping.item.success")}),this.onCloseShipItemModal(),this.$root.$emit(lr.EventShippedOrder)}).then(()=>{this.$emit("ship-item-success")}).catch(t=>{this.isShipItemLoading=!1,this.createNotificationError({message:t.response.data.message})}))},setMaxQuantity(e){this.shipQuantity=this.shippableQuantity(e)},isShippable(e){return this.shippableQuantity(e)>0},shippableQuantity(e){if(this.shippingStatus===null||this.shippingStatus===void 0)return"~";const t=this.shippingStatus[e.id];return t==null?"~":t.quantityShippable},shippedQuantity(e){if(this.shippingStatus===null||this.shippingStatus===void 0)return"~";const t=this.shippingStatus[e.id];return t==null?"~":t.quantityShipped},canceledQuantity(e){if(this.cancelStatus===void 0||this.cancelStatus===null)return"~";const t=this.cancelStatus[e.id];return t==null?"~":t.quantityCanceled},isCancelable(e){if(this.cancelStatus===void 0||this.cancelStatus===null)return!1;const t=this.cancelStatus[e.id];return t==null?!1:t.isCancelable},getCancelData(e){if(this.cancelStatus===void 0||this.cancelStatus===null)return{};const t=this.cancelStatus[e.id];return t===void 0?{}:(t.shopwareItemId=e.id,t.label=e.label,t.payload=e.payload,t)},updateTrackingPrefilling(){if(this.order.deliveries.length){const e=this.order.deliveries.first();this.showTrackingInfo=e.trackingCodes.length>=1}else this.showTrackingInfo=!1},validateTracking(){return!YM.isEmptyOrSpaces(this.tracking.carrier)&&!YM.isEmptyOrSpaces(this.tracking.code)},resetTracking(){this.showTrackingInfo=!1,this.tracking={carrier:"",code:"",url:""}}}});const v1=`{% block sw_order_detail_base_secondary_info_payment %} {% parent %} {% endblock %}`,{Component:f1}=Shopware;f1.override("sw-order-user-card",{template:v1,inject:["MolliePaymentsOrderService"],data(){return{isMolliePaymentUrlLoading:!1,molliePaymentUrl:null,molliePaymentUrlCopied:!1}},computed:{isMollieOrder(){return new ut(this.currentOrder).isMollieOrder()},hasCreditCardData(){return this._creditCardData().hasCreditCardData()},creditCardLabel(){return this._creditCardData().getLabel()},creditCardNumber(){return"**** **** **** "+this._creditCardData().getNumber()},creditCardHolder(){return this._creditCardData().getHolder()},mollieOrderId(){return new ut(this.currentOrder).getMollieID()},mollieThirdPartyPaymentId(){return new ut(this.currentOrder).getPaymentRef()},isSubscription(){return new ut(this.currentOrder).isSubscription()},subscriptionId(){return new ut(this.currentOrder).getSwSubscriptionId()},hasPaymentLink(){return this.molliePaymentUrl!==""}},created(){this.createdComponent()},methods:{createdComponent(){this.$super("createdComponent"),this.molliePaymentUrl="",this.mollieOrderId&&(this.isMolliePaymentUrlLoading=!0,this.MolliePaymentsOrderService.getPaymentUrl({orderId:this.currentOrder.id}).then(e=>{this.molliePaymentUrl=e.url!==null?e.url:""}).finally(()=>{this.isMolliePaymentUrlLoading=!1}))},_creditCardData(){return new ut(this.currentOrder).getCreditCardAttributes()},copyPaymentUrlToClipboard(){Shopware.Utils.dom.copyToClipboard(this.molliePaymentUrl),this.molliePaymentUrlCopied=!0},onMolliePaymentUrlProcessFinished(e){this.molliePaymentUrlCopied=e}}});const g1=`{% block sw_order_detail_base_line_items_summary_entries %} {% parent %}
{{ $tc('sw-order.detailExtended.totalRefunds') }}
{{ currencyFilter( refundedAmount, order.currency.isoCode, order.totalRounding.decimals) }}
{{ $tc('sw-order.detailExtended.totalRefundsPending') }}
{{ currencyFilter( refundAmountPending, order.currency.isoCode, order.totalRounding.decimals) }}
{{ $tc('sw-order.detailExtended.totalShipments', 0, { quantity: shippedQuantity }) }}
{{ currencyFilter( shippedAmount, order.currency.isoCode, order.totalRounding.decimals) }}
{% endblock %}`,{Component:h1,Mixin:b1,Filter:k1}=Shopware;h1.override("sw-order-detail-base",{template:g1,mixins:[b1.getByName("notification")],inject:["MolliePaymentsRefundService","MolliePaymentsShippingService"],data(){return{remainingAmount:0,refundedAmount:0,voucherAmount:0,refundAmountPending:0,existingRefunds:[],shippedAmount:0,shippedQuantity:0}},computed:{isMollieOrder(){return new ut(this.order).isMollieOrder()},currencyFilter(){return k1.getByName("currency")}},watch:{order(){this.loadMollieData()}},methods:{createdComponent(){this.$super("createdComponent"),this.$root.$on(lr.EventShippedOrder,()=>{this.loadMollieData()}),this.loadMollieData()},loadMollieData(){this.isMollieOrder&&(this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(e=>{this.remainingAmount=e.totals.remaining,this.refundedAmount=e.totals.refunded,this.voucherAmount=e.totals.voucherAmount,this.refundAmountPending=e.totals.pendingRefunds,this.existingRefunds=e.refunds}).catch(e=>{this.createNotificationError({message:e.message})}),this.MolliePaymentsShippingService.total({orderId:this.order.id}).then(e=>{this.shippedAmount=Math.round(e.amount*100)/100,this.shippedQuantity=e.quantity}))}}});const y1=`{% block sw_order_detail_general_info_card %} {% parent %} {% block sw_order_detail_general_mollie_refund_manager %} {% endblock %} {% block sw_order_detail_general_mollie_shipping %} {% endblock %} {% block sw_order_detail_general_mollie_info %}
{% block sw_order_detail_general_mollie_info_property_creditcard %}
{{ $tc('sw-order.detailExtended.titleCreditCardData') }}
{{ creditCardLabel }}
{{ creditCardNumber }}
{{ creditCardHolder }}
{% endblock %} {% block sw_order_detail_general_mollie_info_property_orderid %}
{{ $tc('sw-order.detailExtended.labelMollieOrderId') }}
{{ mollieOrderId }}
{{ $tc('sw-order.detailExtended.subscriptionBadge') }}
{% endblock %} {% block sw_order_detail_general_mollie_info_property_paymentref %}
{{ $tc('sw-order.detailExtended.labelMollieThirdPartyPaymentId') }}
{{ mollieThirdPartyPaymentId }}
{% endblock %} {% block sw_order_detail_general_mollie_info_property_paymentlink %}
{{ $tc('sw-order.detailExtended.labelMolliePaymentLink') }}
{{ $tc('sw-order.detailExtended.buttonMolliePaymentLink') }}
{% endblock %}
{% block sw_order_detail_general_mollie_info_action_buttons %} {% block sw_order_detail_general_mollie_info_action_buttons_order_shipping %} {{ $tc('mollie-payments.general.shipThroughMollie') }} {% endblock %} {% block sw_order_detail_general_mollie_info_action_buttons_refund_manager %} {{ $tc('sw-order.detailExtended.refundManager.btnOpenRefundManager') }} {% endblock %} {% endblock %}
{% endblock %}
{% endblock %} {% block sw_order_detail_general_line_items_summary_entries %} {% parent %}
{{ $tc('sw-order.detailExtended.totalRefunds') }}
{{ currencyFilter( refundedAmount, order.currency.isoCode, order.totalRounding.decimals) }}
{{ $tc('sw-order.detailExtended.totalRefundsPending') }}
{{ currencyFilter( refundAmountPending, order.currency.isoCode, order.totalRounding.decimals) }}
{{ $tc('sw-order.detailExtended.totalShipments', 0, { quantity: shippedQuantity }) }}
{{ currencyFilter( shippedAmount, order.currency.isoCode, order.totalRounding.decimals) }}
{% endblock %}`,{Component:_1,Mixin:S1,Filter:w1}=Shopware;_1.override("sw-order-detail-general",{template:y1,mixins:[S1.getByName("notification")],inject:["MolliePaymentsRefundService","MolliePaymentsShippingService","MolliePaymentsOrderService","MolliePaymentsConfigService","acl"],data(){return{refundManagerService:null,shippingManagerService:null,molliePaymentUrl:"",molliePaymentUrlCopied:!1,isRefundManagerPossible:!1,showRefundModal:!1,isShippingPossible:!1,showShippingModal:!1,remainingAmount:0,refundedAmount:0,voucherAmount:0,refundAmountPending:0,shippedAmount:0,shippedQuantity:0}},computed:{isMollieOrder(){return new ut(this.order).isMollieOrder()},hasCreditCardData(){var e;return((e=this._creditCardData())==null?void 0:e.hasCreditCardData())??!1},creditCardLabel(){return this._creditCardData().getLabel()},creditCardNumber(){return"**** **** **** "+this._creditCardData().getNumber()},creditCardHolder(){return this._creditCardData().getHolder()},mollieOrderId(){return new ut(this.order).getMollieID()},mollieThirdPartyPaymentId(){return new ut(this.order).getPaymentRef()},isSubscription(){return new ut(this.order).isSubscription()},subscriptionId(){return new ut(this.order).getSwSubscriptionId()},hasPaymentLink(){return this.molliePaymentUrl!==""},currencyFilter(){return w1.getByName("currency")}},watch:{order(){this.getMollieData()}},created(){this.createdComponent()},methods:{createdComponent(){this.molliePaymentUrl="",this.isShippingPossible=!1,this.isRefundManagerPossible=!1,this.mollieOrderId&&(this.refundedManagerService=new gu(this.MolliePaymentsConfigService,this.acl),this.shippingManagerService=new ua(this.MolliePaymentsShippingService),this.$root&&this.$root.$on?this.$root.$on(lr.EventShippedOrder,()=>{this.onCloseShippingManager(),location.reload()}):Shopware.Utils.EventBus.on(lr.EventShippedOrder,()=>{this.onCloseShippingManager(),location.reload()}),this.getMollieData())},onOpenRefundManager(){this.showRefundModal=!0},onCloseRefundManager(){this.showRefundModal=!1,location.reload()},onOpenShippingManager(){this.showShippingModal=!0},onCloseShippingManager(){this.showShippingModal=!1},_creditCardData(){return new ut(this.order).getCreditCardAttributes()},copyPaymentUrlToClipboard(){const e=async function(r){await navigator.clipboard.writeText(r)};(typeof Shopware.Utils.dom.copyToClipboard=="function"?Shopware.Utils.dom.copyToClipboard:e)(this.molliePaymentUrl),this.molliePaymentUrlCopied=!0},onMolliePaymentUrlProcessFinished(e){this.molliePaymentUrlCopied=e},getMollieData(){this.isMollieOrder&&(this.MolliePaymentsOrderService.getPaymentUrl({orderId:this.order.id}).then(e=>{this.molliePaymentUrl=e.url!==null?e.url:""}),this.shippingManagerService||(this.shippingManagerService=new ua(this.MolliePaymentsShippingService)),this.shippingManagerService.isShippingPossible(this.order).then(e=>{this.isShippingPossible=e}),this.refundedManagerService||(this.refundedManagerService=new gu(this.MolliePaymentsConfigService,this.acl)),this.refundedManagerService.isRefundManagerAvailable(this.order.salesChannelId,this.order).then(e=>{this.isRefundManagerPossible=e}),this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(e=>{this.remainingAmount=e.totals.remaining,this.refundedAmount=e.totals.refunded,this.voucherAmount=e.totals.voucherAmount,this.refundAmountPending=e.totals.pendingRefunds}).catch(e=>{this.createNotificationError({message:e.message})}),this.MolliePaymentsShippingService.total({orderId:this.order.id}).then(e=>{this.shippedAmount=Math.round(e.amount*100)/100,this.shippedQuantity=e.quantity}))}}});const R1=`{% block sw_order_list_grid_columns %} {% parent %} {% block sw_order_list_grid_columns_mollie_abo %} {% endblock %} {% endblock %}`,{Component:E1}=Shopware;E1.override("sw-order-list",{template:R1,methods:{getOrderColumns(){const e=this.$super("getOrderColumns");return e.push({property:"mollie",label:"mollie-payments.sw-order-list.columns.mollie",allowResize:!0,primary:!1}),e},isMollie(e){const t=new ut(e);return t.getOrderId()!==""||t.getPaymentId()!==""},getMollieId(e){const t=new ut(e);return t.getOrderId()!==""?t.getOrderId():t.getPaymentId()!==""?t.getPaymentId():""},isMollieSubscription(e){return new ut(e).getSwSubscriptionId()!==""}}});const{Component:A1}=Shopware;A1.override("sw-system-config",{provide(){return{actualConfigData:this.actualConfigData,currentSalesChannelId:this.currentSalesChannelId}}});const M1=`{% block mollie_tracking_info %} {% endblock %}`,{Component:P1}=Shopware,{string:T1}=Shopware.Utils;P1.register("mollie-tracking-info",{template:M1,props:{delivery:{type:Object,required:!0,default(){return null}},tracking:{type:Object,required:!0,default(){return{carrier:"",code:"",url:""}}}},created(){this.createdComponent()},methods:{createdComponent(){this.delivery.trackingCodes.length===1&&this.prefillTrackingInfo(this.delivery.trackingCodes[0],this.delivery.shippingMethod)},prefillTrackingInfo(e,t){this.tracking.carrier=t.name,this.tracking.code=e,T1.isEmptyOrSpaces(t.trackingUrl)||(this.tracking.url=this.renderTrackingUrl(e,t))},renderTrackingUrl(e,t){const r=t?t.trackingUrl:null;return r?r.replace("%s",encodeURIComponent(e)):""}}});const I1=` {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #}
{{ $tc('mollie-payments.refund-manager.cart.btnSelectAll') }} {{ $tc('mollie-payments.refund-manager.cart.btnResetForm') }}
{{ $tc('mollie-payments.refund-manager.cart.linkHowTo') }}
{{ $tc('mollie-payments.refund-manager.cart.roundDiffItemAdded') }} ({{ currencyFilter( roundingDiff , order.currency.isoCode, order.totalRounding.decimals) }})
{{ $tc('mollie-payments.refund-manager.acl.warningCancel') }} {{ $tc('mollie-payments.refund-manager.refunds.linkMore') }}
{# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #}
{{ $tc('mollie-payments.refund-manager.instructions.linkResetTutorials') }}
{{ $tc('mollie-payments.refund-manager.instructions.titleFullRefund') }}
{{ $tc('mollie-payments.refund-manager.instructions.textFullRefund') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{{ $tc('mollie-payments.refund-manager.instructions.titleRoundingDiff') }}
{{ $tc('mollie-payments.refund-manager.instructions.textRoundingDiff') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{{ $tc('mollie-payments.refund-manager.instructions.titleStockReset') }}
{{ $tc('mollie-payments.refund-manager.instructions.textStockReset') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{{ $tc('mollie-payments.refund-manager.instructions.titleShipping') }}
{{ $tc('mollie-payments.refund-manager.instructions.textShipping') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{# --------------------------------------------------------------------------------------------- #}
{{ $tc('mollie-payments.refund-manager.instructions.titlePartialAmount') }}
{{ $tc('mollie-payments.refund-manager.instructions.textPartialAmount') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{{ $tc('mollie-payments.refund-manager.instructions.titlePartialItems') }}
{{ $tc('mollie-payments.refund-manager.instructions.textPartialItems') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{{ $tc('mollie-payments.refund-manager.instructions.titlePartialPromotions') }}
{{ $tc('mollie-payments.refund-manager.instructions.textPartialPromotions') }}

{{ $tc('mollie-payments.refund-manager.instructions.btnToggleTutorial') }}
{# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #}
{{ $tc('mollie-payments.refund-manager.summary.dataLoading') }}
{# --------------------------------------------------------------------------------------------- #} {% block sw_order_line_items_grid_refund_summary %}
{{ $tc('mollie-payments.refund-manager.summary.headerExcludingVat') }}
{{ $tc('mollie-payments.refund-manager.summary.headerIncludingVat') }}
{% block sw_order_line_items_grid_refund_summary_amount_total %} {% endblock %} {% block sw_order_line_items_grid_refund_summary_amount_free_tax %} {% endblock %} {% block sw_order_line_items_grid_refund_summary_rounding_diff %} {% endblock %} {% block sw_order_line_items_grid_refund_summary_amount_voucher %} {% endblock %} {% block sw_order_line_items_grid_refund_summary_amount_pending_refunds %}
{{ $tc('mollie-payments.refund-manager.summary.captionPendingRefunds') }}
- {{ currencyFilter( pendingRefunds , order.currency.isoCode, order.totalRounding.decimals) }}
{% endblock %} {% block sw_order_line_items_grid_refund_summary_amount_refunded %}
{{ $tc('mollie-payments.refund-manager.summary.captionRefunded') }}
- {{ currencyFilter( refundedAmount , order.currency.isoCode, order.totalRounding.decimals) }}
{% endblock %} {% block sw_order_line_items_grid_refund_summary_amount_remaining %}
{{ $tc('mollie-payments.refund-manager.summary.captionRemaining') }}
= {{ currencyFilter( remainingAmount , order.currency.isoCode, order.totalRounding.decimals) }}
{% endblock %} {% endblock %}
{# --------------------------------------------------------------------------------------------- #} {{ $tc('mollie-payments.refund-manager.summary.btnFixDiff') }} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------,------------------------------------- #} {{ $tc('mollie-payments.refund-manager.acl.warningCreate') }} {{ $tc('mollie-payments.refund-manager.summary.btnRefund') }}
{{ $tc('mollie-payments.refund-manager.summary.btnFullRefund') }}
{# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #} {# --------------------------------------------------------------------------------------------- #}
`,{Application:j1}=Shopware;class C1{buildColumns(){const t=j1.getApplicationRoot();return[{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.item"),property:"shopware.label",align:"left"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.productNumber"),property:"shopware.productNumber",align:"left"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.unitPrice"),property:"shopware.unitPrice",width:"90px",align:"right"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.quantity"),property:"shopware.quantity",width:"50px",align:"right"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.refunded"),property:"refunded",width:"50px",align:"right"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.refundQuantity"),property:"inputQuantity",width:"140px",align:"center"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.totalPrice"),property:"shopware.totalPrice",width:"110px",align:"right"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.refundAmount"),property:"inputAmount",width:"150px",align:"center"},{label:"",property:"inputConsiderTax",align:"center"},{label:"",property:"inputConsiderPromotion",align:"center"},{label:t.$tc("mollie-payments.refund-manager.cart.grid.columns.resetStock"),property:"inputStock",width:"135px",align:"center"}]}}const{Application:O1}=Shopware;class z1{buildColumns(){const t=O1.getApplicationRoot();return[{property:"amount.value",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.amount"),width:"120px",align:"right",sortable:!0},{property:"status",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.status"),width:"190px",sortable:!0},{property:"description",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.description")},{property:"internalDescription",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.internalDescription")},{property:"composition",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.composition"),width:"100px"},{property:"createdAt",label:t.$tc("mollie-payments.refund-manager.refunds.grid.columns.date"),width:"100px",sortable:!0}]}}const D1="none",QM="quantity",la="amount";class x1{isTypePromotion(t){return t.shopware.isPromotion}isTypeDelivery(t){return t.shopware.isDelivery}isDiscounted(t){return t.shopware.promotion.discount>0}isRefundable(t){return t.shopware.unitPrice!==0}setStockReset(t,r){t.resetStock>0||(t.resetStock=r)}setFullRefund(t){t.refundQuantity=t.shopware.quantity-t.refunded,this.onQuantityChanged(t)}resetRefundData(t){t.refundMode=D1,t.refundQuantity=0,t.refundAmount=0,t.resetStock=0,t.refundPromotion=!1,t.refundTax=!1}onQuantityChanged(t){if(t.refundMode===la)return;const r=t.shopware.quantity-t.refunded;t.refundQuantity>r&&(t.refundQuantity=r),t.refundMode=QM,this._calculateItemAmount(t)}onAmountChanged(t){t.refundMode!==QM&&(t.refundMode=la,t.refundQuantity<=0&&(t.refundQuantity=parseInt(t.refundAmount/t.shopware.unitPrice)))}onRefundTaxChanged(t){t.refundMode!==la&&this._calculateItemAmount(t)}onPromotionDeductionChanged(t){t.refundMode!==la&&this._calculateItemAmount(t)}_calculateItemAmount(t){const r=t.shopware.unitPrice*t.refundQuantity;let a=0;if(t.refundTax){a+=t.shopware.tax.perItemTax*t.refundQuantity,t.refundQuantity>0&&t.refundQuantity+t.refunded===t.shopware.quantity&&(a+=t.shopware.tax.totalToPerItemRoundingDiff);let i=0;t.refundTax&&t.shopware.promotion.taxValue>0&&(i=t.shopware.promotion.taxValue/t.shopware.promotion.quantity*t.refundQuantity),a-=i}if(t.refundPromotion){const i=t.shopware.promotion.discount/t.shopware.promotion.quantity,n=t.refundQuantity*i;t.refundAmount=r+a-n}else t.refundAmount=r+a}}const{Component:q1,Mixin:N1,Filter:ZM}=Shopware;q1.register("mollie-refund-manager",{template:I1,mixins:[N1.getByName("notification")],inject:["MolliePaymentsConfigService","MolliePaymentsRefundService","acl"],props:{order:{type:Object,required:!0}},data(){return{itemService:null,configVerifyRefund:!0,configAutoStockReset:!0,configShowInstructions:!0,isRefundDataLoading:!1,isRefunding:!1,orderItems:[],mollieRefunds:[],remainingAmount:0,refundAmount:0,refundedAmount:0,voucherAmount:0,pendingRefunds:0,checkVerifyRefund:!1,refundDescription:"",refundInternalDescription:"",roundingDiff:0,tutorialFullRefundVisible:!1,tutorialPartialAmountRefundVisible:!1,tutorialPartialQuantityVisible:!1,tutorialPartialPromotionsVisible:!1,tutorialResetStock:!1,tutorialRefundShipping:!1}},created(){this.createdComponent()},computed:{titleCardOrder(){let e=this.$tc("mollie-payments.refund-manager.cart.title");return e=e.replace("##orderNumber##",this.order.orderNumber),e},gridCartColumns(){return new C1().buildColumns()},gridMollieRefundsColumns(){return new z1().buildColumns()},isAclRefundAllowed(){return this.acl.can("mollie_refund_manager:create")},isAclCancelAllowed(){return this.acl.can("mollie_refund_manager:delete")},descriptionCharacterCountingTitle(){return this.$tc("mollie-payments.refund-manager.summary.lblDescription",0,{characters:this.refundDescription.length})},currencyFilter(){return ZM.getByName("currency")},dateFilter(){return ZM.getByName("date")}},methods:{createdComponent(){if(this.itemService=new x1,this.order){this._fetchFormData();const e=this;this.MolliePaymentsConfigService.getRefundManagerConfig(this.order.salesChannelId,this.order.id).then(t=>{e.configVerifyRefund=t.verifyRefund,e.configAutoStockReset=t.autoStockReset,e.configShowInstructions=t.showInstructions})}},isItemPromotion(e){return this.itemService.isTypePromotion(e)},isItemDelivery(e){return this.itemService.isTypeDelivery(e)},isItemDiscounted(e){return this.itemService.isDiscounted(e)},isItemRefundable(e){return this.itemService.isRefundable(e)},isTaxStatusGross(){return this.order.taxStatus==="gross"},btnSelectAllItems_Click(){const e=this;this.orderItems.forEach(function(t){e.itemService.setFullRefund(t)}),this._calculateFinalAmount()},btnResetCartForm_Click(){const e=this;this.orderItems.forEach(function(t){e.itemService.resetRefundData(t)}),this._calculateFinalAmount(),this.checkVerifyRefund=!1,this.refundDescription="",this.refundInternalDescription=""},onItemQtyChanged(e){this.itemService.onQuantityChanged(e),this.configAutoStockReset&&this.itemService.setStockReset(e,e.refundQuantity),this._calculateFinalAmount()},onItemAmountChanged(e){this.itemService.onAmountChanged(e),this._calculateFinalAmount()},onItemRefundTaxChanged(e){this.itemService.onRefundTaxChanged(e),this._calculateFinalAmount()},onItemPromotionDeductionChanged(e){this.itemService.onPromotionDeductionChanged(e),this._calculateFinalAmount()},btnResetLine_Click(e){this.itemService.resetRefundData(e),this._calculateFinalAmount()},btnToggleTutorialFull_Click(){this.tutorialFullRefundVisible=!this.tutorialFullRefundVisible},btnToggleTutorialPartialAmount_Click(){this.tutorialPartialAmountRefundVisible=!this.tutorialPartialAmountRefundVisible},btnToggleTutorialPartialQuantities_Click(){this.tutorialPartialQuantityVisible=!this.tutorialPartialQuantityVisible},btnToggleTutorialPartialPromotions_Click(){this.tutorialPartialPromotionsVisible=!this.tutorialPartialPromotionsVisible},btnToggleTutorialStock_Click(){this.tutorialResetStock=!this.tutorialResetStock},btnToggleTutorialShipping_Click(){this.tutorialRefundShipping=!this.tutorialRefundShipping},btnResetTutorials_Click(){this.tutorialFullRefundVisible=!1,this.tutorialPartialAmountRefundVisible=!1,this.tutorialPartialQuantityVisible=!1,this.tutorialPartialPromotionsVisible=!1,this.tutorialResetStock=!1,this.tutorialRefundShipping=!1},isButtonFixDiffAvailable(){const e=Math.abs(this.refundAmount-this.remainingAmount);return e>0&&e<=.07},btnFixDiff_Click(){this.refundAmount=this.remainingAmount},btnRefund_Click(){if(this.isAclRefundAllowed){if(this.refundAmount<=0){this._showNotificationWarning(this.$tc("mollie-payments.refund-manager.notifications.error.low-amount"));return}var e=[];this.orderItems.forEach(function(t){const r={id:t.shopware.id,label:t.shopware.label,quantity:t.refundQuantity,amount:t.refundAmount,resetStock:t.resetStock};e.push(r)}),this.isRefunding=!0,this.MolliePaymentsRefundService.refund({orderId:this.order.id,amount:this.refundAmount,description:this.refundDescription,internalDescription:this.refundInternalDescription,items:e}).then(t=>{t.success?this._handleRefundSuccess(t):this._showNotificationError(t.errors[0])}).finally(()=>{this.isRefunding=!1})}},btnRefundFull_Click(){this.isAclRefundAllowed&&(this.isRefunding=!1,this.MolliePaymentsRefundService.refundAll({orderId:this.order.id,description:this.refundDescription,internalDescription:this.refundInternalDescription}).then(e=>{e.success?this._handleRefundSuccess(e):this._showNotificationError(e.errors[0])}).finally(()=>{this.isRefunding=!1}))},getRefundStatusName(e){return this.$tc("mollie-payments.refunds.status."+e)},getRefundStatusDescription(e){return this.$tc("mollie-payments.refunds.status.description."+e)},getRefundCompositions(e){if(!e||!e.metadata||!e.metadata.composition||e.metadata.composition.length<=0)return[this.$tc("mollie-payments.refund-manager.refunds.grid.lblNoComposition")];const t=this,r=[];return e.metadata.composition.forEach(function(a){let i=a.label;a.swReference.length>0&&(i=a.swReference),a.quantity>0?r.push(i+" ("+a.quantity+" x "+a.amount+" "+t.order.currency.symbol+")"):r.push(i+" ("+a.amount+" "+t.order.currency.symbol+")")}),r},getRefundStatusBadge(e){return e==="refunded"?"success":"warning"},isRefundCancelable(e){return e.isPending||e.isQueued},btnCancelRefund_Click(e){this.isAclCancelAllowed&&this.MolliePaymentsRefundService.cancel({orderId:this.order.id,refundId:e.id}).then(t=>{t.success?(this._showNotificationSuccess(this.$tc("mollie-payments.refund-manager.notifications.success.refund-canceled")),this.$emit("refund-cancelled"),this._fetchFormData()):this._showNotificationError(t.errors[0])}).catch(t=>{this._showNotificationError(t.error)})},_fetchFormData(){this.isRefundDataLoading=!0;const e=this;this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(t=>{this.mollieRefunds=t.refunds,this.remainingAmount=t.totals.remaining,this.refundedAmount=t.totals.refunded,this.voucherAmount=t.totals.voucherAmount,this.pendingRefunds=t.totals.pendingRefunds,this.roundingDiff=t.totals.roundingDiff,this.orderItems=[],t.cart.forEach(function(r){const a={refunded:r.refunded,shopware:r.shopware};e.itemService.resetRefundData(a),e.orderItems.push(a)}),this.isRefundDataLoading=!1})},_calculateFinalAmount(){var e=0;this.orderItems.forEach(function(t){e+=parseFloat(t.refundAmount)}),this.refundAmount=this._roundToTwo(e)},_roundToTwo(e){return+(Math.round(e+"e+2")+"e-2")},_showNotification(e){this.createNotificationWarning({message:this.$tc(e)})},_showNotificationWarning(e){this.createNotificationWarning({message:this.$tc(e)})},_showNotificationSuccess(e){this.createNotificationSuccess({message:e})},_showNotificationError(e){this.createNotificationError({message:e})},_handleRefundSuccess(e){if(this.isRefunding=!1,!e.success){this._showNotificationError(this.$tc("mollie-payments.refund-manager.notifications.error.refund-created"));return}this._showNotificationSuccess(this.$tc("mollie-payments.refund-manager.notifications.success.refund-created")),this.$emit("refund-success"),this._fetchFormData(),this.btnResetCartForm_Click()}}});const L1=`

{{ $tc('mollie-payments.modals.shipping.order.description') }}

{{ $tc('mollie-payments.modals.shipping.selectAllButton') }} {{ $tc('mollie-payments.modals.shipping.resetButton') }} {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_items %} {% endblock %}
{{ $tc('mollie-payments.modals.shipping.confirmButton') }}
{% block sw_order_line_items_grid_grid_mollie_ship_item_modal_tracking %} {% endblock %}
`,{Component:F1,Mixin:V1}=Shopware;F1.register("mollie-ship-order",{template:L1,mixins:[V1.getByName("notification")],inject:["MolliePaymentsShippingService","MolliePaymentsConfigService","acl"],props:{order:{type:Object,required:!0}},data(){return{shippableLineItems:[],shippedLineItems:[],showTrackingInfo:!1,tracking:{carrier:"",code:"",url:""}}},created(){this.createdComponent()},computed:{getShipOrderColumns(){return[{property:"itemselect",label:""},{property:"label",label:this.$tc("mollie-payments.modals.shipping.order.itemHeader")},{property:"quantity",label:this.$tc("mollie-payments.modals.shipping.order.quantityHeader"),width:"160px"},{property:"originalQuantity",label:this.$tc("mollie-payments.modals.shipping.order.originalQuantityHeader"),width:"160px"}]}},methods:{async createdComponent(){if(this.showTrackingInfo=!1,this.tracking={carrier:"",code:"",url:""},await this.MolliePaymentsShippingService.status({orderId:this.order.id}).then(t=>{this.shippedLineItems=t}),new ua(this.MolliePaymentsShippingService).getShippableItems(this.order).then(t=>{for(let r=0;r=1}},btnSelectAllItems_Click(){for(let e=0;e0&&(t.selected=!0)}},btnResetItems_Click(){for(let e=0;e{this.$root.$emit(lr.EventShippedOrder),this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.shipping.item.success")})}).catch(t=>{const r=t.response.data.message?t.response.data.message:t.response.data.errors[0];this.createNotificationError({message:r})})}}});const B1=`
{{ item.label }}
{{ item.label }}
`,{Component:U1,Mixin:$1}=Shopware;U1.register("mollie-cancel-item",{template:B1,props:{item:{type:Object,required:!0}},data(){return{cancelableQuantity:0,canceledQuantity:1,resetStock:!1,isLoading:!1}},mixins:[$1.getByName("notification")],inject:["MolliePaymentsItemCancelService"],methods:{submit(){this.isLoading||(this.isLoading=!0,this.MolliePaymentsItemCancelService.cancel({mollieOrderId:this.item.mollieOrderId,mollieLineId:this.item.mollieId,shopwareLineId:this.item.shopwareItemId,canceledQuantity:this.canceledQuantity,resetStock:this.resetStock}).then(e=>{this.isLoading=!1,e.success?this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.cancel.item.success")}):this.createNotificationError({message:this.$tc("mollie-payments.modals.cancel.item.failed."+e.message)}),this.$emit("update-cancel-status"),this.$emit("close")}).catch(e=>{this.isLoading=!1,this.createNotificationError({message:e.response.data.message}),this.$emit("close")}))},close(){this.$emit("close")}}});const H1={entities:{mollie_subscription:"Mollie Abonnement | Mollie Abonnements"},businessEvents:{mollie_checkout_order_success:" Bestellung erfolgreich",mollie_checkout_order_failed:" Bestellung fehlgeschlagen",mollie_checkout_order_canceled:" Bestellung abgebrochen",mollie_webhook_received_All:" Mollie Webhook empfangen (Alle)",mollie_webhook_received_status_authorized:" Mollie Webhook empfangen (Authorisiert)",mollie_webhook_received_status_failed:" Mollie Webhook empfangen (Fehler)",mollie_webhook_received_status_canceled:" Mollie Webhook empfangen (Abgebrochen)",mollie_webhook_received_status_expired:" Mollie Webhook empfangen (Abgelaufen)",mollie_webhook_received_status_pending:" Mollie Webhook empfangen (Wartend)",mollie_webhook_received_status_paid:" Mollie Webhook empfangen (Bezahlt)",mollie_webhook_received_status_completed:" Mollie Webhook empfangen (Komplett)",mollie_webhook_received_status_refunded:" Mollie Webhook empfangen (Rückerstattet)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook empfangen (Teilweise Rückerstattet)",mollie_refund_started:" Mollie Rückerstattung gestartet",mollie_subscription_started:" Mollie Abonnement gestartet",mollie_subscription_ended:" Mollie Abonnement abgeschlossen",mollie_subscription_cancelled:" Mollie Abonnement abgebrochen",mollie_subscription_paused:" Mollie Abonnement pausiert",mollie_subscription_resumed:" Mollie Abonnement fortgesetzt",mollie_subscription_skipped:" Mollie Abonnement ausgesetzt",mollie_subscription_renewed:" Mollie Abonnement erneuert",mollie_subscription_renewal_reminder:" Mollie Erinnerung zur Abonnement Erneuerung"}},K1={global:H1,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"In Abonnements suchen...","general":{"mainMenuItemGeneral":"Mollie Payments Zahlungen","descriptionTextModule":"Mollie Payments Zahlungen","btnMollieActions":"Mollie Aktionen","refundThroughMollie":"Rückerstattung über Mollie","shipThroughMollie":"Versand melden","cancelMollieItem":"Abbrechen über Mollie"},"config":{"info":{"title":"Hallo {userName}, Willkommen bei Mollie!","descriptionTop":"Starten mit Mollie ist einfach!","descriptionBottom":"Das ist alles!","descriptionFooter":"Wenn du mehr über unser Plugin lernen möchtest, besuche bitte unsere offizielle Dokumentation.","onboardingStep1":"Registriere dich für ein Mollie Konto.","onboardingStep2":"Gib deine API Schlüssel weiter unten ein.","onboardingStep2TestMode":"Aktiviere den 'Testmodus' wenn du Zahlungen nur testen möchtest.","onboardingStep3":"Weise die Zahlungsarten deinen Verkaufskanälen zu.","onboardingStep3Link":"Verkaufskanäle öffnen","btnDocumentation":"Dokumentation","btnRequestSupport":"Support","btnTroubleshooting":"zu den Fehlerbehebungen"},"api":{"apiLinkButton":"Erhalten Sie Ihre API Keys vom Mollie Dashboard","testButton":"Teste API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API Schlüssel","isValid":"ist gültig","isInvalid":"ist ungültig"}},"payments":{"format":{"placeholder":"Platzhalter","preview":"Vorschau"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Zahlungsarten aktualisieren","succeeded":"Die Zahlungsarten wurden erfolgreich aktualisiert.","failed":"Die Zahlungsarten konnten nicht aktualisiert werden."},"mollieLimits":{"link":"Zeige Mollie-Verfügbarkeitregeln für Zahlungsmethoden"}},"rounding":{"info1":"Shopware kann anhand von Währungseinstellungen berechnen, wie die Gesamtsumme einer Bestellung gerundet wird. Dazu gehören die Anzahl der Dezimalstellen in den Produktpreisen und das nächste Rundungsintervall, z. B. 0,50 oder 1,00.","info2":"Diese Einstellungen können zu einer anderen Gesamtsumme als der Gesamtsumme der Einzelposten führen. Wenn Mollie diese Beträge abgleicht und feststellt, dass sie nicht übereinstimmen, verursacht dies einen Fehler.","info3":"Sie können diese Funktion verwenden, um Rundungsprobleme in Ihrem Checkout zu vermeiden. Wenn diese aktiviert ist, fügt sie eine separate Position im Mollie-Dashboard für die Rundungsdifferenz hinzu, und die Kunden zahlen die von Shopware berechnete Gesamtsumme."},"order":{"bankTransferDueDateKlarnaLimitReached":"Es ist nicht möglich, Klarna Pay now, Klarna Slice it oder Klarna Pay later als Zahlungsmethode zu verwenden, wenn Ihr Ablaufdatum mehr als 28 Tage in der Zukunft liegt, es sei denn, zwischen dem Händler und Klarna wurde eine andere Höchstgrenze vereinbart.","bankTransferDueDateLimitReached":"Es ist nicht möglich, die Bestelllaufzeit auf mehr als 100 Tage festzulegen."},"support":{"modalTitle":"Unterstützung von Mollie anfordern","btnCancel":"Abbrechen","btnConfirm":"Unterstützung anfordern","btnSupport":"Mehr über unseren Support","form":{"name":"Ihr Name","email":"Ihre E-Mail","recipient":"Anfrage senden an","subject":"Betreff","message":"Nachricht"},"data":{"header":"Datentransfer zu Mollie:","other":"Andere:","shopwareVersion":"Shopware-Version","pluginLogs":"{plugin} log files","pluginConfiguration":"{plugin}-Konfiguration","pluginConfigurationHelpText":"API-Schlüssel sind ausgeschlossen.","paymentMethods":"Daten zur Zahlungsmethode","paymentMethodsHelpText":"Enthält Informationen darüber, welche Zahlungsmethoden aktiv sind, welche den einzelnen Vertriebskanälen zugeordnet sind, sowie deren Status in Ihrem Mollie-Konto."},"success":"Die Supportanfrage wurde erfolgreich versendet. Wir geben unser Bestes für eine schnelle Antwort.","error":"Es gab leider ein Problem beim Versand über Shopware. Bitte probieren Sie es erneut oder kontaktieren uns direkt per E-Mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart has subscription items (Mollie)"},"refunds":{"status":{"queued":"Warteschlange","pending":"Ausstehend","processing":"Processing","refunded":"Erstattet","failed":"Gescheitert","description":{"queued":"Die Rückerstattung steht in der Warteschlange, bis genügend Guthaben vorhanden ist, um die Rückerstattung zu verarbeiten. Sie können die Rückerstattung noch stornieren.","pending":"Die Rückerstattung wird am nächsten Werktag an die Bank gesendet. Sie können die Rückerstattung immer noch stornieren.","processing":"Die Rückerstattung wurde an die Bank gesendet. Der Rückerstattungsbetrag wird so schnell wie möglich auf das Kundenkonto überwiesen.","refunded":"Der Rückerstattungsbetrag wurde an den Kunden überwiesen.","failed":"Die Rückerstattung ist nach der Bearbeitung fehlgeschlagen. Zum Beispiel hat der Kunde sein Bankkonto geschlossen. Das Geld wird auf das Konto zurücküberwiesen."}}},"refund-manager":{"general":{"unitQuantity":"Stk."},"acl":{"warningCreate":"Sie besitzen keine Berechtigungen, um Rückerstattungen durchzuführen","warningCancel":"Sie besitzen keine Berechtigungen, um Rückerstattungen abzubrechen"},"cart":{"title":"Bestellung ##orderNumber##","btnSelectAll":"Alle auswählen","btnResetForm":"Formular zurücksetzen","linkHowTo":"Wie benutze ich dieses Formular?","grid":{"columns":{"item":"Position","productNumber":"Produktnummer","unitPrice":"Stückpreis","quantity":"Anzahl","refunded":"Rückerstattet","refundQuantity":"Rückerstatten","totalPrice":"Gesamt","refundAmount":"Rückerstatten","resetStock":"Lagerbestand zurücksetzen"},"btnResetLine":"Zeile zurücksetzen","checkDeductPromotion":"Rabatt abziehen","checkRefundTax":"BTW terugbetalen"},"roundDiffItemAdded":"Automatische Position für Rundungen wurde hinzugefügt"},"instructions":{"linkResetTutorials":"Tutorials zurücksetzen","btnToggleTutorial":"Tutorial anzeigen/verstecken","titleFullRefund":"Vollständige Rückerstattung","textFullRefund":"Verwenden Sie einfach die Schaltfläche für die vollständige Rückerstattung. Dadurch wird sichergestellt, dass alle Ihre Artikel als erstattet markiert werden und der volle Betrag an den Kunden zurückerstattet wird.","titleStockReset":"Lagerbestand zurücksetzen","textStockReset":"Sie können den verfügbaren Bestand automatisch erhöhen, indem Sie die Menge eingeben, die Sie wieder auf Lager haben möchten. Geben Sie es einfach ein, bevor Sie mit einer vollständigen oder teilweisen Rückerstattung fortfahren. Das Zurücksetzen des Bestands kann flexibel mit dem eigentlichen Rückerstattungsprozess kombiniert werden.","titleShipping":"Versandkosten","textShipping":"Versandartikel können wie alle anderen Produktartikel erstattet werden. Geben Sie entweder die volle Menge oder einen benutzerdefinierten Teilbetrag ein und fahren Sie mit der Rückerstattung fort. Die Rückerstattung der Versandkosten kann flexibel mit dem eigentlichen Rückerstattungsprozess von Artikeln kombiniert werden.","titlePartialAmount":"Teilweise Rückerstattung (nur Betrag)","textPartialAmount":"Geben Sie einfach den Teilbetrag in das Textfeld ein und starten Sie die Rückerstattung.","titlePartialItems":"Teilweise Rückerstattung (mit Positionen)","textPartialItems":"Wenn Sie Mengen und Artikel in Mollie als erstattet markieren möchten, verwenden Sie das obige Formular. Legen Sie Ihre Mengen fest und geben Sie einen benutzerdefinierten Betrag für jeden Artikel an, der erstattet wird. Die Gesamtsumme wird dann im Textfeld des finalen Erstattungsbetrages angezeigt. Denken Sie daran, dass es immer noch möglich ist, diesen endgültigen Betrag anzupassen, bevor Sie mit der Rückerstattung beginnen.","titlePartialPromotions":"Teilweise Rückerstattung (mit Rabatten)","textPartialPromotions":"Wenn Sie eine oder mehrere Rabatte in Ihrem Warenkorb haben, dann sind diese in Shopware als eigene Position in der Bestellung angelegt. Wenn Sie nun alle rabattierten Artikel erstatten möchten, erstatten Sie einfach alle Positionen der Artikel sowie die gesamte Rabattposition selbst. Wenn Sie jedoch nur einen Teil der rabattierten Artikel erstatten möchten, können Sie den angewendeten Rabatt automatisch für jeden einzelnen Artikel abziehen lassen. Sie können Werte natürlich jederzeit ändern, wenn sie nicht korrekt sind.","titleRoundingDiff":"Rundungsdifferenz","textRoundingDiff":"Bei einer vollständigen Rückerstattung werden Rundungsdifferenzen mit erstattet"},"summary":{"dataLoading":"Daten werden geladen...","headerExcludingVat":"Exkl. MwSt.","headerIncludingVat":"Inkl. MwSt.","captionTotal":"Gesamtsumme","captionTotalTaxFree":"Gesamtsumme","captionPendingRefunds":"Warten auf Rückerstattung","captionVouchers":"Gutscheine","captionRefunded":"Rückerstattete Menge","captionRemaining":"Rückerstattbar","btnFixDiff":"Differenz ausfüllen","placeholderDescription":"Geben Sie eine Beschreibung für den Kontoauszug bzw. Kartenabrechnung an. Max. 140 Zeichen","lblDescription":"Beschreibung (optional) ({characters}/140 Zeichen)","descriptionHelp":"Dies wird, wenn möglich, auf der Bank- oder Kartenabrechnung des Verbrauchers angezeigt. Die Nachricht wird nach 140 Zeichen abgeschnitten.","placeholderInternalDescription":"Geben Sie Ihre interne Beschreibung ein","lblInternalDescription":"Interne Beschreibung (optional)","internalDescriptionHelp":"Dies wird als lokale Beschreibung in der Verwaltungsschnittstelle angezeigt.","checkVerification":"Ich habe den Betrag der Rückerstattung geprüft und die Anzahl der Positionen für Erstattung und Lagerbestand konfiguriert.","btnRefund":"Rückerstatten","btnFullRefund":"Vollständig rückerstatten","roundDiffItemAdded":"Position für Rundungen"},"refunds":{"title":"Rückerstattungen im Mollie Dashboard","linkMore":"Mehr über Rückerstattungen","grid":{"columns":{"amount":"Betrag","status":"Status","description":"Beschreibung","internalDescription":"Interne beschreibung","composition":"Zusammensetzung","date":"Datum"},"lblNoComposition":"Keine Zusammensetzung verfügbar","btnCancelRefund":"Diese Rückerstattung stornieren"}},"notifications":{"success":{"refund-created":"Es wurde eine Rückerstattung bei Mollie erstellt. Es kann bis zu 2 Stunden dauern, bis die Rückerstattung abgeschlossen ist. Bis dahin können Sie die Rückerstattung stornieren.","refund-canceled":"Die ausstehende Rückerstattung wurde erfolgreich storniert und entfernt."},"error":{"low-amount":"Bitte geben Sie einen zu erstattenden Betrag ein.","refund-created":"Beim Erstellen einer Rückerstattung ist etwas schief gelaufen.","refund-canceled":"Es gab ein Problem beim Löschen der ausstehenden Rückertattung. Bitte versuche es erneut im Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Gutscheine","VOUCHER_INFO_TITLE":"Gutschein Bezahlung","VOUCHER_INFO_DESCRIPTION":"Mit Mollie können Sie ganz einfach Zahlungen in Ihrem Online-Shop mit Öko-, Geschenk- und Essensgutscheinen akzeptieren – eine clevere Wahl, um den Umsatz zu steigern und Ihre Kunden zufrieden zu stellen. Die Zahlungsmethode \\"Gutschein\\" ist nur sichtbar, wenn Sie mindestens 1 Produkt in Ihrem Warenkorb haben, das mit einem konfigurierten Gutscheintyp berechtigt ist.","VOUCHER_INFO_DEFAULTLANGUAGE":"Bitte beachten Sie, dass diese Konfiguration nur in der Standard Sprache durchgeführt werden kann. Ändern Sie die hier angezeigte Sprache um den Gutscheintyp verändern zu können.","VOUCHER_BTN_READMORE":"Mehr lesen","VOUCHER_TYPE_CAPTION":"Gutschein Typ für Produkt","VOUCHER_TYPE_VALUE_NONE":"Kein Gutschein Typ","VOUCHER_TYPE_VALUE_ECO":"Öko","VOUCHER_TYPE_VALUE_MEAL":"Mahlzeit","VOUCHER_TYPE_VALUE_VOUCHER":"Geschenk"},"modals":{"shipping":{"title":"Versand an Mollie melden","item":{"label":"Artikel:","noQuantity":"Bitte geben Sie eine Menge für den Versand ein.","shipAll":"Alles versenden","summary":{"quantity":"Zu versendende Menge","shipped":"Versendete Menge","shippable":"Zu versendende Menge"},"success":"Die Bestellung wurde erfolgreich als versendet markiert."},"order":{"description":"Die folgenden Artikelmengen werden versandt.","itemHeader":"Artikel","quantityHeader":"Menge","originalQuantityHeader":"Menge (verschickbar)"},"availableTracking":{"label":"Verfügbare Tracking-Codes","hint":"Klicken Sie auf einen dieser Tracking-Codes, um alle Daten automatisch auszufüllen."},"showTracking":"Tracking-Informationen für diese Sendung hinzufügen","tracking":{"carrier":"Spediteur","code":"Code","url":"Url","invalid":"Bitte geben Sie sowohl Spediteur als auch Code ein"},"confirmButton":"Bestellung versenden","cancelButton":"Abbrechen","selectAllButton":"Alle auswählen","resetButton":"Zurücksetzen"},"cancel":{"title":"Produkt in Mollie abbrechen","confirmButton":"Produkt in Mollie abbrechen","cancelButton":"Schließen","resetStock":"Bestand zurücksetzen","item":{"success":"Produkt erfolgreich abgebrochen","failed":{"quantityZero":"Menge ist 0","invalidLine":"Produkt exestiert nicht in der Bestellung","quantityTooHigh":"Menge ist zu hoch"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Bestellung verschicken (Mollie)","description":"Bestellung wird in Mollie als verschickt markiert."},"modal":{"title":"Bestellung verschicken","description":"Diese Aktion markiert automatisch eine Bestellung in Mollie als 'versendet'. Dabei wird aus der Sequenz die Bestellnummer gelesen und an die Mollie API übergeben. Erfolgreiche sowie fehlgeschlagene Aktionen sind dabei in den Mollie Logs einsehbar.","warningConfig":"Bitte deaktivieren Sie alle zusätzlichen Automatisierungen, die mit dieser Flow Builder Aktion kolidieren können.\\nDie folgenden aktivierten Features dieses Plugins können sich mit dieser Aktion überschneiden:","noWarnings":"Keine Warnungen"}},"refundOrder":{"editor":{"title":"Bestellung erstatten (Mollie)","description":"Bestellung wird via Mollie zurückerstattet."},"modal":{"title":"Bestellung erstatten","description":"Diese Aktion startet eine Rückerstattung via Mollie. Dabei wird aus der Sequenz die Bestellnummer gelesen und an die Mollie API übergeben. Erfolgreiche sowie fehlgeschlagene Aktionen sind dabei in den Mollie Logs einsehbar.","warning":"Bitte beachten Sie, dass eine Rückerstattung bis zu 2 Stunden dauern kann, bis diese im Shop sichtbar ist. Bis dahin können sie eingeleitete Erstattungen jederzeit auf der Bestellseite im Shop, oder direkt im Mollie Dashboard abbrechen.","warningConfig":"Bitte deaktivieren Sie alle zusätzlichen Automatisierungen, die mit dieser Flow Builder Aktion kolidieren können."}},"warnings":{"automaticShipping":"Automatischer Versand in Plugin Konfiguration"}}},"subscriptions":{"status":{"pending":"Ausstehend","active":"Aktiv","canceled":"Abgebrochen","suspended":"Ausgesetzt","completed":"Abgeschlossen","paused":"Pausiert","resumed":"Fortgesetzt","skipped":"Ausgesetzt"},"navigation":{"title":"Mollie Abonnements"},"TYPE_DAYS":"Tage","TYPE_WEEKS":"Woche(n)","TYPE_MONTHS":"Monat(e)","confirm":{"cancelTitle":"Abonnement beenden?","cancel":"Kündigen Sie das Abonnement Ihres Kunden.","pauseTitle":"Abonnement pausieren?","pause":"Pausieren Sie das Abonnement, bis Sie es wieder fortsetzen.","resumeTitle":"Abonnement fortsetzen?","resume":"Das Abonnement erneut fortsetzen.","skipTitle":"Nächste Rate überspringen?","skip":"Überspringen Sie die nächste Rate im Abonnement. Es wird danach automatisch fortgesetzt."},"alerts":{"cancelSuccess":"Das Abonnement wurde erfolgreich gekündigt","pauseSuccess":"Das Abonnement wurde erfolgreich pausiert","resumeSuccess":"Das Abonnement wurde erfolgreich fortgesetzt","skipSuccess":"Das Abonnement wurde erfolgreich ausgesetzt. Das Datum der nächsten Zahlung wurde aktualisiert."},"list":{"title":"Mollie Abonnements","columns":{"customer":"Kunde","status":"Status","description":"Beschreibung","amount":"Betrag","nextPaymentAt":"Nächste Zahlung","prePaymentReminder":"Erinnert am","canceledAt":"Gekündigt","createdAt":"Erstellt"},"action":{"edit":"Abonnement bearbeiten"},"deletedCustomer":"Gelöschter Kunde"},"detail":{"title":"Mollie Abonnements","buttonCancelSubscription":"Abonnement kündigen","labelDescription":"Beschreibung","labelAmount":"Betrag","labelQuantity":"Stück","labelMollieSubscription":"Mollie Abo","labelMollieCustomer":"Mollie Kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware Kunde","labelCreatedAt":"Erstellt am","buttonShowShopwareOrder":"Shopware Bestellung anzeigen","buttonShowShopwareCustomer":"Shopware Kunde anzeigen","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Nächste Zahlung am","labelLastRemindedAt":"Zuletzt erinnert am","labelCanceledAt":"Gekündigt am","buttonPauseSubscription":"Abonnement pausieren","buttonResumeSubscription":"Abonnement fortsetzen","buttonSkipSubscription":"Abonnement aussetzen","history":{"cardTitle":"Statushistorie","colDate":"Datum","colComment":"Kommentar","colStatusFrom":"Status (von)","colStatusTo":"Status (zu)","colMollieSubscription":"Mollie Abo"}},"product":{"card-title":"Abonnement","title":"Mollie-Abonnements","description":"Die Verwaltung Ihrer wiederkehrenden Zahlungen ist mit unseren hilfreichen Funktionen einfacher denn je. Bringen Sie Ihr Unternehmen mit effizienten Tracking-Optionen, einfachen Integrationen und mehr auf die nächste Stufe. Mit Mollie-Abonnements können Sie ganz einfach Abonnementprodukte erstellen und wiederkehrende Zahlungen so planen, dass sie im konfigurierten Intervall und Zeitraum stattfinden.","mollieSubscriptionProduct":"Ist das ein Abo-Produkt?","mollieSubscriptionIntervalAmount":"Zahlung wiederholen alle","mollieSubscriptionIntervalType":"Abonnement-Intervall-Typ","mollieSubscriptionRepetitionAmount":"Zahlung wiederholen","mollieSubscriptionRepetitionPlaceholder":"Nummer eingeben oder leer lassen","infoDefaultLanguage":"Bitte beachten Sie, dass diese Konfiguration nur in Ihrer Standardsprache bearbeitet werden kann. Bitte ändern Sie Ihre Sprache, um die Abonnementeinstellungen dieses Produkts zu ändern.","btnReadMore":"Mehr lesen"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abo Bestellung"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kreditkartendaten",buttonMolliePaymentLink:"In die Zwischenablage kopieren",columnRefunded:"Rückerstattet",columnShipped:"Versandt",columnCanceled:"Abgebrochen",labelMollieOrderId:"Mollie Bestell ID",labelMollieThirdPartyPaymentId:"Zahlungsreferenz",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Rückerstattete Menge",totalRefundsPending:"Warten auf Rückerstattung",totalRemaining:"Rückerstattbar",totalVouchers:"Gutscheine",totalShipments:"Versandte Menge ({quantity} Stück)",subscriptionBadge:"Abo Bestellung",refundManager:{title:"Rückerstattung über Mollie",btnOpenRefundManager:"Refund Manager öffnen",btnCloseRefundManager:"Refund Manager schließen"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Bevorzugter iDeal Aussteller"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refund Manager"},mollie_subscription:{label:"Abonnements"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Beschreibung"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Rückerstattung",subscription:"Abonnement",webhookReceived:"Webhooks",status:"Status",started:"Gestartet",ended:"Beendet",paused:"Pausiert",renewalReminder:"Verlängerungserinnerung",renewed:"Erneuert",resumed:"Verlängert",skipped:"Ausgesetzt",all:"Alle",canceled:"Abgebrochen",expired:"Abgelaufen",partiallyRefunded:"Rückerstattet (teilweise)",orderSuccess:"Bestellung erfolgreich",orderFailed:"Bestellung fehlgeschlagen",orderCanceled:"Bestellung abgebrochen"}}},W1={entities:{mollie_subscription:"Mollie Subscription | Mollie Subscriptions"},businessEvents:{mollie_checkout_order_success:" Order successful",mollie_checkout_order_failed:" Order failed",mollie_checkout_order_canceled:" Order canceled",mollie_webhook_received_All:" Mollie Webhook Received (All)",mollie_webhook_received_status_authorized:" Mollie Webhook Received (Authorized)",mollie_webhook_received_status_failed:" Mollie Webhook Received (Failed)",mollie_webhook_received_status_canceled:" Mollie Webhook Received (Canceled)",mollie_webhook_received_status_expired:" Mollie Webhook Received (Expired)",mollie_webhook_received_status_pending:" Mollie Webhook Received (Pending)",mollie_webhook_received_status_paid:" Mollie Webhook Received (Paid)",mollie_webhook_received_status_completed:" Mollie Webhook Received (Completed)",mollie_webhook_received_status_refunded:" Mollie Webhook Received (Refunded)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Received (Partially Refunded)",mollie_refund_started:" Mollie refund started",mollie_subscription_started:" Mollie subscription started",mollie_subscription_ended:" Mollie subscription completed",mollie_subscription_cancelled:" Mollie subscription cancelled",mollie_subscription_paused:" Mollie subscription paused",mollie_subscription_resumed:" Mollie subscription resumed",mollie_subscription_skipped:" Mollie subscription skipped",mollie_subscription_renewed:" Mollie subscription renewed",mollie_subscription_renewal_reminder:" Mollie reminder for subscription renewal"}},G1={global:W1,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Search subscriptions...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Refund through Mollie","shipThroughMollie":"Ship through Mollie","cancelMollieItem":"Cancel through Mollie"},"config":{"info":{"title":"Hi {userName}, Welcome to Mollie!","descriptionTop":"Onboarding is easy with Mollie!","descriptionBottom":"That's it!","descriptionFooter":"If you want to learn more about our plugin, please visit our official documentation page.","onboardingStep1":"Sign up for a Mollie Account.","onboardingStep2":"Enter your API keys in the section below.","onboardingStep2TestMode":"Turn on 'Test Mode' if you want to only test payments.","onboardingStep3":"Assign payment methods to your sales channel.","onboardingStep3Link":"to your sales channels","btnDocumentation":"Documentation","btnRequestSupport":"Support","btnTroubleshooting":"Troubleshooting Guide"},"api":{"apiLinkButton":"Get your API keys from the Mollie Dashboard","testButton":"Test API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API key","isValid":"is valid","isInvalid":"is invalid"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Preview"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Update payment methods","succeeded":"The payment methods are successfully updated.","failed":"The payment methods couldn't be updated."},"mollieLimits":{"link":"Show mollie availability rules for payment methods"}},"rounding":{"info1":"Shopware can use currency settings to calculate how it rounds an order’s grand total. This includes the number of decimals in your product pricing and the nearest rounding interval, such as 0.50 or 1.00.","info2":"These settings can lead to a different grand total than the total sum of line items. When Mollie cross-checks these amounts and finds that they don’t match, it causes a checkout error.","info3":"You can use this feature to avoid rounding issues in your checkout. When enabled, it adds a separate line item in your Mollie Dashboard for the difference in rounding, and your customers pay the grand total calculated by Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"It is not possible to use Klarna Pay now, Klarna Slice it or Klarna Pay later as method when your expiry date is more than 28 days in the future, unless another maximum is agreed between the merchant and Klarna.","bankTransferDueDateLimitReached":"It is not possible to set the order life time higher than 100 days."},"support":{"modalTitle":"Request support from Mollie","btnCancel":"Cancel","btnConfirm":"Request support","btnSupport":"More about our support","form":{"name":"Your name","email":"Your email","recipient":"Send request to","subject":"Subject","message":"Message"},"data":{"header":"Data sent to Mollie:","other":"Other:","shopwareVersion":"Shopware version","pluginLogs":"{plugin} log files","pluginConfiguration":"{plugin} configuration","pluginConfigurationHelpText":"API keys are excluded.","paymentMethods":"Payment method data","paymentMethodsHelpText":"Contains information about which payment methods are active, assigned to each sales channel, as well as their status in your Mollie account."},"success":"The suport request has been successfully sent. We do our best to reply as soon as possible","error":"There was a problem when sending the mail through Shopware. Please try it again or contact us directly per e-mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart with subscriptions (Mollie)"},"refunds":{"status":{"queued":"Queued","pending":"Pending","processing":"Processing","refunded":"Refunded","failed":"Failed","description":{"queued":"The refund is queued until there is enough balance to process te refund. You can still cancel the refund.","pending":"The refund will be sent to the bank on the next business day. You can still cancel the refund.","processing":"The refund has been sent to the bank. The refund amount will be transferred to the consumer account as soon as possible.","refunded":"The refund amount has been transferred to the consumer.","failed":"The refund has failed after processing. For example, the customer has closed his / her bank account. The funds will be returned to your account."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"You don't have permissions to create refunds","warningCancel":"You don't have permissions to cancel refunds"},"cart":{"title":"Order ##orderNumber##","btnSelectAll":"Select All","btnResetForm":"Reset Form","linkHowTo":"How to use this form?","grid":{"columns":{"item":"Item","productNumber":"Product Number","unitPrice":"Unit Price","quantity":"Quantity","refunded":"Refunded","refundQuantity":"Refund","totalPrice":"Total","refundAmount":"Refund","resetStock":"Reset Stock"},"btnResetLine":"Reset Line","checkDeductPromotion":"Deduct promotion","checkRefundTax":"Refund VAT"},"roundDiffItemAdded":"Automatic rounding item was added"},"instructions":{"linkResetTutorials":"Reset Tutorials","btnToggleTutorial":"Show/Hide Tutorial","titleFullRefund":"Full Refund","textFullRefund":"Just use the button for the full refund. This makes sure that all your items are marked as refunded and the full amount is returned to the customer.","titleStockReset":"Stock Reset","textStockReset":"You can automatically increase the available stock by entering the quantity that you would like to put back in stock. Just enter it before proceeding with a full or partial refund. Resetting the stock can be combined with the actual refund process in a flexible way.","titleShipping":"Shipping","textShipping":"Shipping items can be refunded as any other produt item. Either enter the full quantity or a custom partial amount and proceed with the refund. Refunding shipping costs can be combined with the actual refund process of items in a flexible way.","titlePartialAmount":"Partial Refund (only amount)","textPartialAmount":"Just enter the partial amount in the text field and start the refund.","titlePartialItems":"Partial Refund (with items)","textPartialItems":"If you want to mark quantities and items as refunded in Mollie, use the form above. Set your quantities and provide a custom amount for every item that will be refunded. The total sum will then be visible in the final refund amount text field. Remember, it's still possible to adjust this final amount before starting your refund.","titlePartialPromotions":"Partial Refund (with promotions)","textPartialPromotions":"If you have a promotion in your cart, then your promotion is a separate line item. If you want to refund all discounted items, go ahead and refund their total values and the full promotion line item itself. However, if you only want to refund a few items that were discounted, you can deduct the applied discount automatically for every single line item. You can of course always change values if they are not correct.","titleRoundingDiff":"Rounding difference","textRoundingDiff":"A full refund will include rounding differences"},"summary":{"dataLoading":"Data is loading...","headerExcludingVat":"Excl. VAT","headerIncludingVat":"Incl. VAT","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Waiting to be refunded","captionVouchers":"Voucher amount","captionRefunded":"Refunded amount","captionRemaining":"Refundable amount","btnFixDiff":"Fix Difference","placeholderDescription":"Enter bank/card statement description for consumer. Max 140 characters","lblDescription":"Description (optional) ({characters}/140 characters)","descriptionHelp":"This will be shown on the consumer's bank or card statement when possible. The message will be truncated after 140 characters.","placeholderInternalDescription":"Enter your internal description","lblInternalDescription":"Internal description (optional)","internalDescriptionHelp":"This will be shown as a local description in the administration interface.","checkVerification":"I have verified the total refund amount and the configured quantities to refund and re-stock.","btnRefund":"Refund","btnFullRefund":"Full Refund","roundDiffItemAdded":"Rounding item"},"refunds":{"title":"Refunds in the Mollie Dashboard","linkMore":"More about refunds","grid":{"columns":{"amount":"Amount","status":"Status","description":"Description","internalDescription":"Internal description","composition":"Composition","date":"Date"},"lblNoComposition":"No composition available","btnCancelRefund":"Cancel this refund"}},"notifications":{"success":{"refund-created":"A refund has been created in Mollie. It may take 2 hours for the refund to complete. Until this time, you can cancel the refund.","refund-canceled":"The pending refund has been successfully cancelled and removed."},"error":{"low-amount":"Please enter an amount to be refunded.","refund-created":"Something went wrong creating a refund.","refund-canceled":"There was a problem when cancelling the pending refund. Please try it again in the Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucher Payments","VOUCHER_INFO_DESCRIPTION":"Mollie lets you easily accept payments in your online shop using Eco-, gift- and meal vouchers—a smart choice for boosting sales and satisfying your customers. The payment method \\"voucher\\" is only visible, if you have at least 1 product with an assigned voucher type in the cart.","VOUCHER_INFO_DEFAULTLANGUAGE":"Please note, this configuration can only be edited in your default language. Please change your language to modify the voucher type of this product.","VOUCHER_BTN_READMORE":"Read more","VOUCHER_TYPE_CAPTION":"Voucher type of product","VOUCHER_TYPE_VALUE_NONE":"None","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Meal","VOUCHER_TYPE_VALUE_VOUCHER":"Gift"},"modals":{"shipping":{"title":"Ship through Mollie","item":{"label":"Item:","noQuantity":"Please enter a quantity to ship.","shipAll":"Ship all","summary":{"quantity":"Quantity to ship","shipped":"Quantity shipped","shippable":"Quantity shippable"},"success":"The order has been successfully shipped."},"order":{"description":"The following item quantities will be shipped.","itemHeader":"Item","quantityHeader":"Quantity","originalQuantityHeader":"Quantity (shippable)"},"availableTracking":{"label":"Available tracking codes","hint":"Click one of these tracking codes to automatically fill in all data."},"showTracking":"Add tracking info for this shipment","tracking":{"carrier":"Carrier","code":"Code","url":"Url","invalid":"Please enter both Carrier and Code"},"confirmButton":"Ship order","cancelButton":"Cancel","selectAllButton":"Select all","resetButton":"Reset"},"cancel":{"title":"Cancel item through mollie","confirmButton":"Cancel item through mollie","cancelButton":"Close modal","resetStock":"Reset stocks","item":{"success":"Product canceled successfully","failed":{"quantityZero":"Quantity is 0","invalidLine":"Product does not exist in the order","quantityTooHigh":"Quantity is too high"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Ship Order (Mollie)","description":"Ship order in Mollie."},"modal":{"title":"Ship Order","description":"This action will automatically ship an order through Mollie. The flow sequence will receive the order number, and pass this on to the Mollie API. Successful shipments and failed shipments will be visible in the Mollie log files.","warningConfig":"Please make sure to turn off any additional automation for this type of action to avoid any interferences.\\nThe following activated features of this plugin might interfere with this action:","noWarnings":"No warnings"}},"refundOrder":{"editor":{"title":"Refund Order (Mollie)","description":"Refund order through Mollie."},"modal":{"title":"Refund Order","description":"This action will automatically start a refund through Mollie. The flow sequence will receive the order number, and pass this on to the Mollie API. Successful refunds and failed refunds will be visible in the Mollie log files.","warning":"Please keep in mind, that refunds might take up to 2 hours to be finalized and visible in the shop. Until then you can always cancel a pending refund either from the order page in Shopware or from the Mollie Dashboard.","warningConfig":"Please make sure to turn off any additional automation for this type of action to avoid any interferences."}},"warnings":{"automaticShipping":"Automatic shipping in plugin configuration"}}},"subscriptions":{"status":{"pending":"Pending","active":"Active","canceled":"Canceled","suspended":"Suspended","completed":"Completed","paused":"Paused","resumed":"Resumed","skipped":"Skipped"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Day(s)","TYPE_WEEKS":"Week(s)","TYPE_MONTHS":"Month(s)","confirm":{"cancelTitle":"End subscription?","cancel":"Cancel your customer's subscription.","pauseTitle":"Pause subscription?","pause":"Put the subscription on hold until you resume it again.","resumeTitle":"Resume subscription?","resume":"Continue the subscription again.","skipTitle":"Skip next instalment?","skip":"Skip the next instalment in the subscription. It continues automatically afterwards."},"alerts":{"cancelSuccess":"The subscription has been canceled successfully","pauseSuccess":"The subscription has been paused successfully","resumeSuccess":"The subscription has been resumed successfully","skipSuccess":"The subscription has been skipped successfully. The next payment has been updated."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Customer","status":"Status","description":"Description","amount":"Amount","nextPaymentAt":"Next Payment","prePaymentReminder":"Reminded at","canceledAt":"Canceled at","createdAt":"Created at"},"action":{"edit":"Edit subscription"},"deletedCustomer":"Deleted customer"},"detail":{"title":"Mollie subscription","buttonCancelSubscription":"Cancel subscription","labelDescription":"Description","labelAmount":"Amount","labelQuantity":"Quantity","labelMollieSubscription":"Mollie Subscription","labelMollieCustomer":"Mollie customer","labelMandateId":"Mandate","labelShopwareCustomer":"Shopware customer","labelCreatedAt":"Created at","buttonShowShopwareOrder":"Show Shopware order","buttonShowShopwareCustomer":"Show Shopware customer","cardTitleSubscription":"Subscription","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Next payment at","labelLastRemindedAt":"Last reminded at","labelCanceledAt":"Canceled at","buttonPauseSubscription":"Pause subscription","buttonResumeSubscription":"Resume subscription","buttonSkipSubscription":"Skip subscription","history":{"cardTitle":"History","colDate":"Date","colComment":"Comment","colStatusFrom":"Status (from)","colStatusTo":"Status (to)","colMollieSubscription":"Mollie subscription"}},"product":{"card-title":"Subscription","title":"Mollie Subscriptions","description":"Managing your recurring payments is easier than ever with our helpful features. Take your business to the next level with efficient tracking options, simple integrations, and more. With Mollie subscriptions, you can easily create subscription products and schedule recurring payments to take place at the configured interval and period.","mollieSubscriptionProduct":"Subscription Product","mollieSubscriptionIntervalAmount":"Repeat Payment every","mollieSubscriptionIntervalType":"Interval Unit","mollieSubscriptionRepetitionAmount":"Number or repetitions","mollieSubscriptionRepetitionPlaceholder":"Enter number or leave empty","infoDefaultLanguage":"Please note, this configuration can only be edited in your default language. Please change your language to modify the subscription settings of this product.","btnReadMore":"Read more"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subscription"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Credit Card data",buttonMolliePaymentLink:"Copy to Clipboard",columnRefunded:"Refunded",columnShipped:"Shipped",columnCanceled:"Canceled",labelMollieOrderId:"Mollie Order ID",labelMollieThirdPartyPaymentId:"Payment Reference",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Refunded amount",totalRefundsPending:"Waiting to be refunded",totalRemaining:"Refundable amount",totalVouchers:"Voucher amount",totalShipments:"Shipped amount ({quantity} items)",subscriptionBadge:"Subscription Order",refundManager:{title:"Mollie Refund Manager",btnOpenRefundManager:"Open Refund Manager",btnCloseRefundManager:"Close Refund Manager"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferred iDeal issuer"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refund Manager"},mollie_subscription:{label:"Subscriptions"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Description"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Refund",subscription:"Subscription",webhookReceived:"Webhooks",status:"Status",started:"Started",ended:"Ended",paused:"Paused",renewalReminder:"Renewal Reminder",renewed:"Renewed",resumed:"Resumed",skipped:"Skipped",all:"All",canceled:"Canceled",expired:"Expired",partiallyRefunded:"Refunded (partially)",orderSuccess:"Order successful",orderFailed:"Order failed",orderCanceled:"Order canceled"}}},Y1={entities:{mollie_subscription:"Mollie Abonnement | Mollie Abonnementen"},businessEvents:{mollie_checkout_order_success:" Bestelling succesvol",mollie_checkout_order_failed:" Bestelling mislukt",mollie_checkout_order_canceled:" Bestelling geannuleerd",mollie_webhook_received_All:" Mollie Webhook Ontvangen (Alle)",mollie_webhook_received_status_authorized:" Mollie Webhook Ontvangen (Geautoriseerd)",mollie_webhook_received_status_failed:" Mollie Webhook Ontvangen (Mislukt)",mollie_webhook_received_status_canceled:" Mollie Webhook Ontvangen (Geannuleerd)",mollie_webhook_received_status_expired:" Mollie Webhook Ontvangen (Vervallen)",mollie_webhook_received_status_pending:" Mollie Webhook Ontvangen (In Afwachting)",mollie_webhook_received_status_paid:" Mollie Webhook Ontvangen (Betaald)",mollie_webhook_received_status_completed:" Mollie Webhook Ontvangen (Voltooid)",mollie_webhook_received_status_refunded:" Mollie Webhook Ontvangen (Terugbetaald)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Ontvangen (Gedeeltelijk terugbetaald)",mollie_refund_started:" Mollie terugbetaling gestart",mollie_subscription_started:" Mollie abonnement gestart",mollie_subscription_ended:" Mollie abonnement voltooid",mollie_subscription_cancelled:" Mollie abonnement opgezegd",mollie_subscription_paused:" Mollie abonnement gepauzeerd",mollie_subscription_resumed:" Mollie abonnement hervat",mollie_subscription_skipped:" Mollie abonnement overgeslagen",mollie_subscription_renewed:" Mollie abonnement verlengd",mollie_subscription_renewal_reminder:" Mollie herinnering voor abonnementsverlenging"}},Q1={global:Y1,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Zoek in abonnementen...","general":{"mainMenuItemGeneral":"Mollie betalingen","descriptionTextModule":"Mollie betalingen","btnMollieActions":"Mollie acties","refundThroughMollie":"Terugbetaling via Mollie","shipThroughMollie":"Verzending door Mollie","cancelMollieItem":"Opzeggen via Mollie"},"config":{"info":{"title":"Hi {userName}, Welkom bij Mollie!","descriptionTop":"Onboarding is eenvoudig bij Mollie!","descriptionBottom":"Dat is alles!","descriptionFooter":"Als je meer wilt weten over onze plugin, bezoek dan onze officiële documentatie pagina.","onboardingStep1":"Meld je aan voor een Mollie Account.","onboardingStep2":"Voer je API sleutels in de sectie hieronder in.","onboardingStep2TestMode":"Zet 'Test Mode' aan als je alleen betalingen wilt testen.","onboardingStep3":"Wijs betaalmethoden toe aan je verkoopkanaal.","onboardingStep3Link":"naar je verkoopkanalen","btnDocumentation":"Documentatie","btnRequestSupport":"Support","btnTroubleshooting":"Troubleshooting Gids"},"api":{"apiLinkButton":"Haal jouw API sleutels van het Mollie Dashboard","testButton":"Controlle API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API Key","isValid":"is geldig","isInvalid":"is ongeldig"}},"payments":{"format":{"placeholder":"Plaatshouder","preview":"Preview"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Betaalmethoden updaten","succeeded":"De betaalmethoden zijn succesvol geupdated.","failed":"De betaalmethoden konden niet worden geupdated."},"mollieLimits":{"link":"Toon Mollie-beschikbaarheidsregels voor betaalmethoden"}},"rounding":{"info1":"Shopware kan valuta-instellingen gebruiken om te berekenen hoe het totaal van een bestelling wordt afgerond. Dit omvat het aantal decimalen in jouw productprijzen en het dichtstbijzijnde afrondingsinterval, zoals 0,50 of 1,00.","info2":"Deze instellingen kunnen leiden tot een andere totale som dan de totale som van lineitems. Wanneer Mollie deze bedragen kruiselings controleert en vaststelt dat ze niet overeenkomen, ontstaat er een fout bij het afrekenen.","info3":"Je kunt deze functie gebruiken om afrondingsproblemen bij het afrekenen te voorkomen. Indien ingeschakeld, voegt het een apart lineitem toe aan je Mollie Dashboard met het afrondingsverschil, en betalen je klanten de totale som zoals berekend door Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Het is niet mogelijk om Klarna Pay now, Klarna Slice it of Klarna Pay later als methode te gebruiken wanneer de vervaldatum meer dan 28 dagen in de toekomst ligt, tenzij een ander maximum is overeengekomen tussen de merchant en Klarna.","bankTransferDueDateLimitReached":"Het is niet mogelijk om de orderlevensduur langer dan 100 dagen in te stellen."},"support":{"modalTitle":"Verzoek support van Mollie","btnCancel":"Cancel","btnConfirm":"Verzoek support","btnSupport":"Meer over onze ondersteuning","form":{"name":"Uw naam","email":"Uw e-mail","recipient":"Stuur verzoek naar","subject":"Onderwerp","message":"Message"},"data":{"header":"Gegevens verzonden naar Mollie:","other":"Andere:","shopwareVersion":"Shopwareversie","pluginLogs":"{plugin} logbestanden","pluginConfiguration":"{plugin} configuratie","pluginConfigurationHelpText":"API-sleutels zijn uitgesloten.","paymentMethods":"Informatie over betaalmethoden","paymentMethodsHelpText":"Bevat informatie over betaalmethoden, welke zijn gekoppeld aan de verkoopkanalen, en de betreffende status ervan in uw Mollie account."},"success":"Het ondersteuningsverzoek is succesvol verzonden. We doen ons best om zo snel mogelijk te antwoorden","error":"Helaas was er een probleem met de verzending via Shopware. Probeer het opnieuw of stuur ons direct een e-mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart has subscription items (Mollie)"},"refunds":{"status":{"queued":"In wachtrij","pending":"In afwachting","processing":"In behandeling","refunded":"Terugbetaald","failed":"Mislukt","description":{"queued":"De terugbetaling wordt in de wachtrij geplaatst totdat er voldoende saldo is om de terugbetaling te verwerken. U kunt de terugbetaling nog steeds annuleren.","pending":"De terugbetaling wordt de volgende werkdag naar de bank gestuurd. U kunt de terugbetaling nog annuleren.","processing":"De terugbetaling is naar de bank gestuurd. Het bedrag wordt zo spoedig mogelijk overgemaakt op de rekening van de klant.","refunded":"Het restitutiebedrag is overgemaakt naar de klant.","failed":"De terugbetaling is mislukt na verwerking. De klant heeft bijvoorbeeld zijn/haar bankrekening opgeheven. Het geld zal worden teruggestort op de rekening."}}},"refund-manager":{"general":{"unitQuantity":"st."},"acl":{"warningCreate":"U heeft geen rechten om terugbetalingen te maken","warningCancel":"U heeft geen rechten om terugbetalingen te annuleren"},"cart":{"title":"Bestelling ##orderNumber##","btnSelectAll":"Alles selecteren","btnResetForm":"Formulier resetten","linkHowTo":"Hoe gebruik je dit formulier?","grid":{"columns":{"item":"Artikel","productNumber":"Artikelnummer","unitPrice":"Prijs per eenheid","quantity":"Aantal","refunded":"Vergoed","refundQuantity":"Vergoeding","totalPrice":"Totaal","refundAmount":"Vergoeding","resetStock":"Voorraad resetten"},"btnResetLine":"Rij resetten","checkDeductPromotion":"Promotie aftrekken","checkRefundTax":"Refund VAT"},"roundDiffItemAdded":"Automatisch afrondingsitem toegevoegd"},"instructions":{"linkResetTutorials":"Handleidingen resetten","btnToggleTutorial":"Handleidingen tonen/verbergen","titleFullRefund":"Volledige terugbetaling","textFullRefund":"Gebruik gewoon de knop voor de volledige terugbetaling. Dit zorgt ervoor dat alle artikelen worden gemarkeerd als terugbetaald en het volledige bedrag wordt vergoed aan de klant.","titleStockReset":"Voorraad resetten","textStockReset":"Je kunt de beschikbare voorraad automatisch verhogen door de hoeveelheid in te voeren die u weer op voorraad wilt hebben. Dit moet je invoeren voordat je overgaat tot een volledige of gedeeltelijke terugbetaling. Het terugzetten van de voorraad kan op een flexibele manier gecombineerd worden met het eigenlijke terugbetalingsproces.","titleShipping":"Verzendkosten","textShipping":"Verzendkosten kunnen worden terugbetaald zoals elk ander artikel. Voer de volledige hoeveelheid in of een aangepast deelbedrag en ga verder met de terugbetaling. Het terugbetalen van verzendkosten kan op een flexibele manier gecombineerd worden met het eigenlijke terugbetalingsproces van artikelen.","titlePartialAmount":"Gedeeltelijke terugbetaling (enkel een bedrag)","textPartialAmount":"Voer gewoon het deelbedrag in het tekstveld in en start de terugbetaling.","titlePartialItems":"Gedeeltelijke terugbetaling (met artikelen)","textPartialItems":"Als u hoeveelheden en artikelen als terugbetaald wilt markeren in Mollie, gebruik dan bovenstaand formulier. Stel uw hoeveelheden in en geef een aangepast bedrag op voor elk item dat zal worden terugbetaald. De totale som zal dan zichtbaar zijn in het tekstveld met het finale terugbetalingsbedrag. Vergeet niet dat het nog steeds mogelijk is om dit eindbedrag aan te passen voordat u de terugbetaling start.","titlePartialPromotions":"Gedeeltelijke terugbetaling (met promotions)","textPartialPromotions":"Als je een promotion in je winkelwagen hebt, dan is de promotion een eigen line item. Als je alle afgeprijsde artikelen wilt terugbetalen, dan kann je de totale waarde van alle artikelen terugbetalen en ook de promotie zelf. Als u echter slechts een paar afgeprijsde artikelen wilt terugbetalen, kunt je de aangepaste korting automatisch aftrekken voor elk afzonderlijk artikel. Je kunt natuurlijk altijd de waarden veranderen mochten ze niet juist zijn.","titleRoundingDiff":"Afrondingsverschil","textRoundingDiff":"Een volledige terugbetaling is inclusief afrondingsverschillen"},"summary":{"dataLoading":"Gegevens worden geladen...","headerExcludingVat":"Excl. BTW","headerIncludingVat":"Incl. BTW","captionTotal":"Totaal","captionTotalTaxFree":"Totaal","captionPendingRefunds":"Wachtend op terugbetaling","captionVouchers":"Voucher bedrag","captionRefunded":"Terugbetaald bedrag","captionRemaining":"Terugbetaalbaar bedrag","btnFixDiff":"Herstel verschil","placeholderDescription":"Voer uw bank/card statement beschrijving in. Max. 140 tekens","lblDescription":"Beschrijving (optioneel) ({characters}/140 tekens)","descriptionHelp":"Dit wordt indien mogelijk getoond op het bank- of kaartafschrift van de consument. Het bericht wordt afgekapt na 140 tekens.","placeholderInternalDescription":"Voer uw interne beschrijving in.","lblInternalDescription":"Interne beschrijving (optioneel)","internalDescriptionHelp":"Dit wordt getoond als een lokale beschrijving in de administratie-interface.","checkVerification":"Ik heb het totale restitutiebedrag en de geconfigureerde hoeveelheden voor restitutie en herbevoorrading geverifieerd.","btnRefund":"Terugbetaling","btnFullRefund":"Volledige terugbetaling","roundDiffItemAdded":"Afrondingsitem"},"refunds":{"title":"Terugbetalingen in het Mollie Dashboard","linkMore":"Meer over terugbetalingen","grid":{"columns":{"amount":"Bedrag","status":"Status","description":"Beschrijving","internalDescription":"Interne beschrijving","composition":"Samenstelling","date":"Datum"},"lblNoComposition":"Geen samenstelling beschikbaar","btnCancelRefund":"Annuleer deze terugbetaling"}},"notifications":{"success":{"refund-created":"Er is een terugbetaling aangemaakt in Mollie. Het kan 2 uur duren voordat de terugbetaling is voltooid. Tot die tijd kan de terugbetaling worden geannuleerd.","refund-canceled":"De uitstaande terugbetaling is met succes geannuleerd en verwijderd."},"error":{"low-amount":"Vull een terug te betalen bedrag in","refund-created":"Er is iets misgegaan bij het aanmaken van een terugbetaling.","refund-canceled":"Er is een probleem opgetreden bij het annuleren van de uitstaande terugbetaling. Probeer het opnieuw in het Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucher Betalingen","VOUCHER_INFO_DESCRIPTION":"Met Mollie kunt u in uw online winkel eenvoudig betalingen accepteren met Eco-, cadeau- en maaltijdcheques - een slimme keuze om de verkoop te stimuleren en uw klanten tevreden te stellen. De betaalmethode \\"voucher\\" is alleen zichtbaar als u ten minste 1 product met de toegewezen type \\"voucher\\", in de winkelwagen heeft.","VOUCHER_INFO_DEFAULTLANGUAGE":"Let op, deze configuratie kan alleen worden bewerkt in uw standaard taal. Wijzig uw taal om het vouchertype van dit product te veranderen.","VOUCHER_BTN_READMORE":"Lees meer","VOUCHER_TYPE_CAPTION":"Vouchertype voor product","VOUCHER_TYPE_VALUE_NONE":"Geen vouchertype","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Meal","VOUCHER_TYPE_VALUE_VOUCHER":"Gift"},"modals":{"shipping":{"title":"Verzenden bij Mollie","item":{"label":"Product:","noQuantity":"Voer een hoeveelheid in om te verzenden.","shipAll":"Verzend alles","summary":{"quantity":"Te verzenden hoeveelheid","shipped":"Verzonden hoeveelheid","shippable":"Verzendbare hoeveelheid"},"success":"De bestelling is succesvol verzonden."},"order":{"description":"De volgende product aantallen zullen worden verzonden.","itemHeader":"Product","quantityHeader":"Aantal","originalQuantityHeader":"Aantal (verzendbaar)"},"availableTracking":{"label":"Beschikbare tracking codes","hint":"Klik op een van deze tracking codes om automatisch alle gegevens in te vullen."},"showTracking":"Voeg tracking info toe aan deze zending","tracking":{"carrier":"Carrier","code":"Code","url":"Url","invalid":"Voer zowel Carrier als Code in"},"confirmButton":"Bestelling verzenden","cancelButton":"Annuleren","selectAllButton":"Selecteer alles","resetButton":"Resetten"},"cancel":{"title":"Product in Mollie afkorting","confirmButton":"Product in Mollie afkorting","cancelButton":"Annuleren","resetStock":"Voorraad resetten","item":{"success":"Product geannuleerd","failed":{"quantityZero":"Aantal is 0","invalidLine":"Product bestaat niet in de bestelling","quantityTooHigh":"Het aantal is te hoog"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Bestelling verzenden (Mollie)","description":"Bestelling is gemarkeerd als verzonden in Mollie."},"modal":{"title":"Bestelling verzenden","description":"Deze actie zal automatisch een bestelling verzenden via Mollie. De flow sequence ontvangt het ordernummer, en geeft dit door aan de Mollie API. Succesvolle verzendingen en mislukte verzendingen zullen zichtbaar zijn in de Mollie logbestanden.","warningConfig":"Schakel alle extra automatiseringen uit die eventueel in conflict komen met deze Flow Builder actie. De volgende geactiveerde features in deze plugin kunnen elkaar kruisen met deze actie:","noWarnings":"Geen waarschuwingen"}},"refundOrder":{"editor":{"title":"Bestelling terugbetalen (Mollie)","description":"Bestelling zal worden terugbetaald via Mollie."},"modal":{"title":"Bestelling terugbetalen","description":"Deze actie zal automatisch een terugbetaling starten via Mollie. De flow sequence ontvangt het ordernummer, en geeft dit door aan de Mollie API. Succesvolle refunds en mislukte refunds zullen zichtbaar zijn in de Mollie logbestanden.","warning":"Houd er rekening mee dat het tot 2 uur kan duren voordat een terugbetaling zichtbaar is in de shop. Tot die tijd kunt u geïnitieerde terugbetalingen op elk moment annuleren op de bestelpagina in de shop, of direct in het Mollie Dashboard.","warningConfig":"Deactiveer alle extra automatiseringen die kunnen collideren met deze Flow Builder actie."}},"warnings":{"automaticShipping":"Automatische verzending in plugin configuratie"}}},"subscriptions":{"status":{"pending":"In afwachting","active":"Actief","canceled":"Geannuleerd","suspended":"Gepauzeerd","completed":"Voltooid","paused":"Onderbroken","resumed":"Hervat","skipped":"Overgeslagen"},"navigation":{"title":"Mollie Abonnementen"},"TYPE_DAYS":"Dag(en)","TYPE_WEEKS":"Weken","TYPE_MONTHS":"Maanden","confirm":{"cancelTitle":"Abonnement beëindigen?","cancel":"Annuleer het abonnement van uw klant.","pauseTitle":"Abonnement pauzeren?","pause":"Zet het abonnement in de wacht totdat je het weer hervat.","resumeTitle":"Abonnement hervatten?","resume":"Zet het abonnement weer voort.","skipTitle":"Volgende betaling overslaan?","skip":"Sla het volgende betaling van het abonnement over. Daarna gaat het automatisch verder."},"alerts":{"cancelSuccess":"Het abonnement is succesvol opgezegd","pauseSuccess":"Het abonnement is succesvol onderbroken","resumeSuccess":"Het abonnement is succesvol voortgezet","skipSuccess":"Het abonnement is succesvol opgeschort. De volgende betalingsdatum is bijgewerkt."},"list":{"title":"Mollie Abonnementen","columns":{"customer":"Klant","status":"Status","description":"Beschrijving","amount":"Bedrag","nextPaymentAt":"Volgende betaling","prePaymentReminder":"Herinnerd op","canceledAt":"Geannuleerd op","createdAt":"Gecreëerd op"},"action":{"edit":"Abonnement bewerken"},"deletedCustomer":"Klant verwijderd"},"detail":{"title":"Mollie Abonnement","buttonCancelSubscription":"Abonnement opzeggen","labelDescription":"Omschrijving","labelAmount":"Bedrag","labelQuantity":"Hoeveelheid","labelMollieSubscription":"Mollie Abonnement","labelMollieCustomer":"Mollie klant","labelMandateId":"Mandaat","labelShopwareCustomer":"Shopware klant","labelCreatedAt":"Gecreëerd op","buttonShowShopwareOrder":"Toon Shopware bestelling","buttonShowShopwareCustomer":"Show Shopware klant","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Volgende betaling op","labelLastRemindedAt":"Laatst herinnerd op","labelCanceledAt":"Geannuleerd op","buttonPauseSubscription":"Abonnement pauzeren","buttonResumeSubscription":"Abonnement hervatten","buttonSkipSubscription":"Bestelling overslaan","history":{"cardTitle":"Historie","colDate":"Datum","colComment":"commentaar","colStatusFrom":"Status (van)","colStatusTo":"Status (tot)","colMollieSubscription":"Mollie Abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie Abonnementen","description":"Het beheren van uw terugkerende betalingen is eenvoudiger dan ooit met onze handige functies. Breng uw bedrijf naar een hoger niveau met efficiënte trackingopties, eenvoudige integraties en meer. Met Mollie-abonnementen kun je eenvoudig abonnementsproducten maken en terugkerende betalingen plannen die plaatsvinden op het ingestelde interval en de ingestelde periode.","mollieSubscriptionProduct":"Is dit een abonnementsproduct?","mollieSubscriptionIntervalAmount":"Herhaal betaling elke","mollieSubscriptionIntervalType":"Type abonnementsinterval","mollieSubscriptionRepetitionAmount":"Herhaal betaling","mollieSubscriptionRepetitionPlaceholder":"Nummer invoeren of leeg laten","infoDefaultLanguage":"Let op, deze configuratie kan alleen in uw standaardtaal worden bewerkt. Wijzig uw taal om de abonnementsinstellingen van dit product te wijzigen.","btnReadMore":"Lees meer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Credit Card data",buttonMolliePaymentLink:"Kopieer naar Klembord",columnRefunded:"Terugbetaald",columnShipped:"Verzonden",columnCanceled:"Geannuleerd",labelMollieOrderId:"Mollie Order ID",labelMollieThirdPartyPaymentId:"Betalingskenmerk",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Terugbetaald bedrag",totalRefundsPending:"Wachtend op terugbetaling",totalRemaining:"Terug te betalen",totalVouchers:"Voucher",totalShipments:"Verzonden bedrag ({quantity} items)",subscriptionBadge:"Abonnement besteling",refundManager:{title:"Terugbetaling via Mollie",btnOpenRefundManager:"Refund Manager openen",btnCloseRefundManager:"Refund Manager sluiten"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Voorkeur iDeal verstrekker"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refund Manager"},mollie_subscription:{label:"Abonnementen"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Beschrijving"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Terugbetaling",subscription:"Abonnement",webhookReceived:"Webhook",status:"Toestand",started:"Begonnen",ended:"Geëindigd",paused:"Onderbroken",renewalReminder:"Verlengingsherinnering",renewed:"Vernieuwd",resumed:"Hervat",skipped:"Overgeslagen",all:"Alle",canceled:"Geannuleerd",expired:"Verlopen",partiallyRefunded:"Terugbetaald (gedeeltelijk)",orderSuccess:"Bestelling succesvol",orderFailed:"Bestelling mislukt",orderCanceled:"Bestelling geannuleerd"}}},Z1={entities:{mollie_subscription:"Abbonamento Mollie | Abbonamenti Mollie"},businessEvents:{mollie_checkout_order_success:" Ordine riuscito",mollie_checkout_order_failed:" Ordine non riuscito",mollie_checkout_order_canceled:" Ordine annullato",mollie_webhook_received_All:" Webhook Mollie ricevuto (tutti)",mollie_webhook_received_status_authorized:" Webhook Mollie ricevuto (autorizzato)",mollie_webhook_received_status_failed:" Webhook Mollie ricevuto (fallito)",mollie_webhook_received_status_canceled:" Webhook Mollie ricevuto (annullato)",mollie_webhook_received_status_expired:" Webhook ricevuto da Mollie (scaduto)",mollie_webhook_received_status_pending:" Webhook Mollie ricevuto (in attesa)",mollie_webhook_received_status_paid:" Webhook Mollie ricevuto (pagato)",mollie_webhook_received_status_completed:" Webhook Mollie ricevuto (completato)",mollie_webhook_received_status_refunded:" Webhook Mollie ricevuto (rimborsato)",mollie_webhook_received_status_partially_refunded:" Webhook Mollie ricevuto (parzialmente rimborsato)",mollie_refund_started:" Rimborso Mollie iniziato",mollie_subscription_started:" Abbonamento Mollie iniziato",mollie_subscription_ended:" Abbonamento Mollie completato",mollie_subscription_cancelled:" Abbonamento Mollie annullato",mollie_subscription_paused:" Abbonamento Mollie messo in pausa",mollie_subscription_resumed:" Abbonamento Mollie ripreso",mollie_subscription_skipped:" Abbonamento Mollie saltato",mollie_subscription_renewed:" Abbonamento Mollie rinnovato",mollie_subscription_renewal_reminder:" Promemoria Mollie per il rinnovo dell'abbonamento"}},J1={global:Z1,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Modulo Mollie","searchPlaceholder":"Cerca abbonamenti...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Azioni Mollie","refundThroughMollie":"Rimborsa tramite Mollie","shipThroughMollie":"Spedizione tramite Mollie","cancelMollieItem":"Annulla tramite Mollie"},"config":{"info":{"title":"Ciao {userName}, benvenuto su Mollie!","descriptionTop":"L'onboarding è facile con Mollie!","descriptionBottom":"Ecco fatto!","descriptionFooter":"Se vuoi saperne di più sul nostro plugin, visita la nostra pagina di documentazione ufficiale.","onboardingStep1":"Iscriviti per un account Mollie.","onboardingStep2":"Inserisci le tue chiavi API nella sezione sottostante.","onboardingStep2TestMode":"Attiva la modalità \\"Test\\" se desideri testare solo i pagamenti.","onboardingStep3":"Assegna i metodi di pagamento al tuo canale di vendita.","onboardingStep3Link":"ai tuoi canali di vendita","btnDocumentation":"Documentazione","btnRequestSupport":"Assistenza","btnTroubleshooting":"Guida alla risoluzione dei problemi"},"api":{"apiLinkButton":"Ottieni le chiavi API dalla Mollie Dashboard","testButton":"Chiavi Test API","testApiKeys":{"title":"Mollie Payments","apiKey":"Chiave API","isValid":"è valido","isInvalid":"non è valido"}},"payments":{"format":{"placeholder":"Segnaposto","preview":"Anteprima"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Aggiorna i metodi di pagamento","succeeded":"I metodi di pagamento sono stati aggiornati con successo.","failed":"Non è stato possibile aggiornare i metodi di pagamento."},"mollieLimits":{"link":"Mostra le regole di disponibilità di Mollie per i metodi di pagamento"}},"rounding":{"info1":"Shopware può utilizzare le impostazioni di valuta per calcolare come arrotonda il totale finale di un ordine. Questo include il numero di decimali nei prezzi dei tuoi prodotti e l'intervallo di arrotondamento più vicino, come 0,50 o 1,00.","info2":"Queste impostazioni possono portare a un totale finale diverso dalla somma totale delle righe dell'ordine. Quando Mollie verifica questi importi e scopre che non corrispondono, si verifica un errore al momento del checkout.","info3":"Puoi utilizzare questa funzione per evitare problemi di arrotondamento durante il checkout. Quando abilitata, aggiunge una riga separata nella tua Mollie Dashboard per la differenza di arrotondamento e i tuoi clienti pagano il totale finale calcolato da Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Non è possibile utilizzare Klarna Pay now, Klarna Slice it o Klarna Pay later come metodo quando la data di scadenza è oltre 28 giorni nel futuro, a meno che non venga concordato un altro massimo tra il commerciante e Klarna.","bankTransferDueDateLimitReached":"Non è possibile impostare la durata dell'ordine superiore a 100 giorni."},"support":{"modalTitle":"Richiedi assistenza da Mollie","btnCancel":"Annulla","btnConfirm":"Richiedi assistenza","btnSupport":"Per saperne di più sulla nostra assistenza","form":{"name":"Il tuo nome","email":"Il tuo indirizzo e-mail","recipient":"Invia la richiesta a","subject":"Oggetto","message":"Messaggio"},"data":{"header":"Dati inviati a Mollie:","other":"Altro:","shopwareVersion":"Versione Shopware","pluginLogs":"File di log {plugin}","pluginConfiguration":"Configurazione {plugin}","pluginConfigurationHelpText":"Le chiavi API sono escluse.","paymentMethods":"Dati sul metodo di pagamento","paymentMethodsHelpText":"Contiene informazioni su quali metodi di pagamento sono attivi, assegnati a ciascun canale di vendita e sul loro stato nel tuo account Mollie."},"success":"La richiesta di assistenza è stata inviata con successo. Faremo del nostro meglio per rispondere il prima possibile","error":"Si è verificato un problema durante l'invio della mail tramite Shopware. Per favore riprova o contattaci direttamente tramite e-mail."}},"rules":{"itemSubscriptionRule":"Articolo in abbonamento (Mollie)","cartSubscriptionRule":"Carrello con abbonamenti (Mollie)"},"refunds":{"status":{"queued":"In coda","pending":"In attesa","processing":"Elaborazione in corso","refunded":"Rimborsato","failed":"Non riuscito","description":{"queued":"Il rimborso è in coda fino a quando non ci sarà abbastanza saldo per elaborarlo. Puoi comunque annullare il rimborso.","pending":"Il rimborso sarà inviato alla banca il giorno lavorativo successivo. Puoi comunque annullare il rimborso.","processing":"Il rimborso è stato inviato alla banca. L'importo del rimborso sarà trasferito sul conto del consumatore il prima possibile.","refunded":"L'importo del rimborso è stato trasferito al consumatore.","failed":"Il rimborso non è riuscito dopo l'elaborazione. Ad esempio, il cliente ha chiuso il proprio conto bancario. I fondi saranno restituiti sul tuo conto."}}},"refund-manager":{"general":{"unitQuantity":"quantità"},"acl":{"warningCreate":"Non hai i permessi per creare rimborsi","warningCancel":"Non hai i permessi per annullare i rimborsi"},"cart":{"title":"Ordine ##orderNumber##","btnSelectAll":"Seleziona tutti","btnResetForm":"Reimposta modulo","linkHowTo":"Come usare questo modulo?","grid":{"columns":{"item":"Articolo","productNumber":"Numero di prodotto","unitPrice":"Prezzo unitario","quantity":"Quantità","refunded":"Rimborsato","refundQuantity":"Rimborso","totalPrice":"Totale","refundAmount":"Rimborso","resetStock":"Reimposta stock"},"btnResetLine":"Reimposta la linea","checkDeductPromotion":"Deduci promozione","checkRefundTax":"Rimborsa IVA"},"roundDiffItemAdded":"È stato aggiunto un elemento di arrotondamento automatico"},"instructions":{"linkResetTutorials":"Reimposta tutorial","btnToggleTutorial":"Mostra/Nascondi Tutorial","titleFullRefund":"Rimborso totale","textFullRefund":"Utilizza semplicemente il pulsante per il rimborso totale. In questo modo, tutti i tuoi articoli saranno contrassegnati come rimborsati e l'intero importo sarà restituito al cliente.","titleStockReset":"Reimpostazione stock","textStockReset":"Puoi aumentare automaticamente lo stock disponibile inserendo la quantità che desideri rimettere in stock. Basta inserirla prima di procedere con un rimborso totale o parziale. La reimpostazione dello stock può essere combinata in modo flessibile con il processo effettivo di rimborso.","titleShipping":"Spedizione","textShipping":"Gli articoli di spedizione possono essere rimborsati come qualsiasi altro articolo di prodotto. Inserisci la quantità totale o un importo parziale personalizzato e procedi con il rimborso. Il rimborso dei costi di spedizione può essere combinato in modo flessibile con il processo effettivo di rimborso degli articoli.","titlePartialAmount":"Rimborso parziale (solo l'importo)","textPartialAmount":"Basta inserire l'importo parziale nel campo di testo e avviare il rimborso.","titlePartialItems":"Rimborso parziale (con articoli)","textPartialItems":"Se desideri segnare quantità e articoli come rimborsati in Mollie, utilizza il modulo sopra. Imposta le tue quantità e fornisci un importo personalizzato per ogni articolo che verrà rimborsato. La somma totale sarà poi visibile nel campo di testo dell'importo finale del rimborso. Ricorda, è ancora possibile modificare questo importo finale prima di avviare il rimborso.","titlePartialPromotions":"Rimborso parziale (con promozioni)","textPartialPromotions":"Se hai una promozione nel tuo carrello, allora la promozione è un articolo separato nella riga. Se desideri rimborsare tutti gli articoli scontati, procedi e rimborsa i loro valori totali e l'intero articolo della promozione. Tuttavia, se desideri rimborsare solo alcuni articoli scontati, puoi dedurre automaticamente lo sconto applicato per ogni singolo articolo nella riga. Puoi ovviamente sempre modificare i valori se non sono corretti.","titleRoundingDiff":"Differenza di arrotondamento","textRoundingDiff":"Un rimborso completo includerà le differenze di arrotondamento"},"summary":{"dataLoading":"Caricamento dei dati in corso...","headerExcludingVat":"IVA esclusa","headerIncludingVat":"IVA inclusa","captionTotal":"Totale","captionTotalTaxFree":"Totale","captionPendingRefunds":"In attesa del rimborso","captionVouchers":"Importo del voucher","captionRefunded":"Importo rimborsato","captionRemaining":"Importo rimborsabile","btnFixDiff":"Correggi la differenza","placeholderDescription":"Inserisci la descrizione dell'estratto conto bancario/carta per il consumatore. Massimo 140 caratteri","lblDescription":"Descrizione (opzionale) ({characters}/140 caratteri)","descriptionHelp":"Questo verrà mostrato sul resoconto bancario o della carta del consumatore quando possibile. Il messaggio sarà troncato dopo 140 caratteri.","placeholderInternalDescription":"Inserisci la tua descrizione interna","lblInternalDescription":"Descrizione interna (opzionale)","internalDescriptionHelp":"Questo sarà mostrato come descrizione locale nell'interfaccia di amministrazione.","checkVerification":"Ho verificato l'importo totale del rimborso e le quantità configurate per il rimborso e il reintegro dello stock.","btnRefund":"Rimborso","btnFullRefund":"Rimborso totale","roundDiffItemAdded":"Elemento di arrotondamento"},"refunds":{"title":"Rimborsi nella Mollie Dashboard","linkMore":"Maggiori informazioni sui rimborsi","grid":{"columns":{"amount":"Importo","status":"Stato","description":"Descrizione","internalDescription":"Descrizione interna","composition":"Composizione","date":"Data"},"lblNoComposition":"Nessuna composizione disponibile","btnCancelRefund":"Annulla questo rimborso"}},"notifications":{"success":{"refund-created":"Un rimborso è stato creato in Mollie. Potrebbero essere necessarie fino a 2 ore per completare il rimborso. Fino a quel momento, puoi annullare il rimborso.","refund-canceled":"Il rimborso in attesa è stato annullato e rimosso con successo."},"error":{"low-amount":"Inserisci un importo da rimborsare.","refund-created":"Si è verificato un problema durante la creazione del rimborso.","refund-canceled":"Si è verificato un problema durante l'annullamento del rimborso in attesa. Riprova nella Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Buono","VOUCHER_INFO_TITLE":"Pagamenti con buono","VOUCHER_INFO_DESCRIPTION":"Mollie ti permette di accettare facilmente pagamenti nel tuo negozio online utilizzando buoni ecologici, buoni regalo e buoni pasto, una scelta intelligente per aumentare le vendite e soddisfare i tuoi clienti. Il metodo di pagamento \\"voucher\\" è visibile solo se hai almeno 1 prodotto con un tipo di voucher assegnato nel carrello.","VOUCHER_INFO_DEFAULTLANGUAGE":"Si prega di notare che questa configurazione può essere modificata solo nella lingua predefinita. Cambia la tua lingua per modificare il tipo di voucher di questo prodotto.","VOUCHER_BTN_READMORE":"Leggi di più","VOUCHER_TYPE_CAPTION":"Tipo di buono del prodotto","VOUCHER_TYPE_VALUE_NONE":"Nessuno","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Pasto","VOUCHER_TYPE_VALUE_VOUCHER":"Regalo"},"modals":{"shipping":{"title":"Spedisci tramite Mollie","item":{"label":"Articolo:","noQuantity":"Inserisci una quantità da spedire.","shipAll":"Spedisci tutto","summary":{"quantity":"Quantità da spedire","shipped":"Quantità spedita","shippable":"Quantità spedibile"},"success":"L'ordine è stato spedito con successo."},"order":{"description":"Le seguenti quantità di articoli saranno spedite.","itemHeader":"Articolo","quantityHeader":"Quantità","originalQuantityHeader":"Quantità (spedibile)"},"availableTracking":{"label":"Codici di tracciamento disponibili","hint":"Fai clic su uno di questi codici di tracciamento per compilare automaticamente tutti i dati."},"showTracking":"Aggiungi le informazioni di tracciamento per questa spedizione","tracking":{"carrier":"Vettore","code":"Codice","url":"Url","invalid":"Per favore, inserisci sia il vettore che il codice"},"confirmButton":"Spedisci l'ordine","cancelButton":"Annulla","selectAllButton":"Seleziona tutto","resetButton":"Reimposta"},"cancel":{"title":"Annulla l'articolo tramite Mollie","confirmButton":"Annulla l'articolo tramite Mollie","cancelButton":"Chiudi finestra modale","resetStock":"Reimposta stock","item":{"success":"Prodotto annullato con successo","failed":{"quantityZero":"La quantità è 0","invalidLine":"Il prodotto non esiste nell'ordine","quantityTooHigh":"La quantità è troppo alta"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Spedisci l'ordine (Mollie)","description":"Spedisci l'ordine in Mollie."},"modal":{"title":"Spedisci l'ordine","description":"Questa azione spedirà automaticamente un ordine tramite Mollie. La sequenza del flusso riceverà il numero dell'ordine e lo trasmetterà al Mollie API. Le spedizioni riuscite e quelle fallite saranno visibili nei file di log di Mollie.","warningConfig":"Assicurati di disattivare qualsiasi automazione aggiuntiva per questo tipo di azione per evitare interferenze.\\nLe seguenti funzionalità attivate di questo plugin potrebbero interferire con questa azione:","noWarnings":"Nessun avviso"}},"refundOrder":{"editor":{"title":"Rimborsa ordine (Mollie)","description":"Rimborsa ordine tramite Mollie."},"modal":{"title":"Rimborsa ordine","description":"Questa azione avvierà automaticamente un rimborso tramite Mollie. La sequenza del flusso riceverà il numero dell'ordine e lo trasmetterà al Mollie API. I rimborsi riusciti e quelli falliti saranno visibili nei file di log di Mollie.","warning":"Si prega di tenere presente che i rimborsi potrebbero richiedere fino a 2 ore per essere finalizzati e visibili nel negozio. Fino ad allora, è sempre possibile annullare un rimborso in sospeso sia dalla pagina dell'ordine in Shopware che dalla Mollie Dashboard.","warningConfig":"Assicurati di disattivare qualsiasi automazione aggiuntiva per questo tipo di azione per evitare interferenze."}},"warnings":{"automaticShipping":"Spedizione automatica nella configurazione del plugin"}}},"subscriptions":{"status":{"pending":"In attesa","active":"Attivo","canceled":"Annullato","suspended":"Sospeso","completed":"Completato","paused":"In pausa","resumed":"Ripreso","skipped":"Saltato"},"navigation":{"title":"Abbonamenti Mollie"},"TYPE_DAYS":"Giorno/i","TYPE_WEEKS":"Settimana/e","TYPE_MONTHS":"Mese/i","confirm":{"cancelTitle":"Termina l'abbonamento?","cancel":"Annulla l'abbonamento del tuo cliente.","pauseTitle":"Metti l'abbonamento in pausa?","pause":"Metti in pausa l'abbonamento finché non lo riprendi.","resumeTitle":"Riprendere l'abbonamento?","resume":"Continua l'abbonamento di nuovo.","skipTitle":"Saltare la prossima rata?","skip":"Salta la prossima rata dell'abbonamento. Successivamente, l'abbonamento continuerà automaticamente."},"alerts":{"cancelSuccess":"L'abbonamento è stato annullato con successo","pauseSuccess":"L'abbonamento è stato messo in pausa con successo","resumeSuccess":"L'abbonamento è stato ripreso con successo","skipSuccess":"L'abbonamento è stato saltato con successo. Il prossimo pagamento è stato aggiornato."},"list":{"title":"Abbonamenti Mollie","columns":{"customer":"Cliente","status":"Stato","description":"Descrizione","amount":"Importo","nextPaymentAt":"Prossimo pagamento","prePaymentReminder":"Ricordato alle","canceledAt":"Annullato alle","createdAt":"Creato alle"},"action":{"edit":"Modifica abbonamento"},"deletedCustomer":"Cliente eliminato"},"detail":{"title":"Abbonamento Mollie","buttonCancelSubscription":"Annulla l'abbonamento","labelDescription":"Descrizione","labelAmount":"Importo","labelQuantity":"Quantità","labelMollieSubscription":"Abbonamento Mollie","labelMollieCustomer":"Cliente Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente Shopware","labelCreatedAt":"Creato alle","buttonShowShopwareOrder":"Mostra l'ordine Shopware","buttonShowShopwareCustomer":"Mostra il cliente Shopware","cardTitleSubscription":"Abbonamento","cardTitleStatus":"Stato","labelStatus":"Stato","labelNextPaymentAt":"Prossimo pagamento alle","labelLastRemindedAt":"Ultimo ricordo alle","labelCanceledAt":"Annullato alle","buttonPauseSubscription":"Metti in pausa l'abbonamento","buttonResumeSubscription":"Riprendi abbonamento","buttonSkipSubscription":"Salta l'abbonamento","history":{"cardTitle":"Cronologia","colDate":"Data","colComment":"Commento","colStatusFrom":"Stato (da)","colStatusTo":"Stato (a)","colMollieSubscription":"Abbonamento Mollie"}},"product":{"card-title":"Abbonamento","title":"Abbonamenti Mollie","description":"Gestire i tuoi pagamenti ricorrenti è più facile che mai grazie alle nostre utili funzionalità. Porta la tua attività al livello successivo con opzioni di tracciamento efficienti, integrazioni semplici e molto altro. Con gli abbonamenti Mollie, puoi facilmente creare prodotti in abbonamento e programmare pagamenti ricorrenti che avvengano all'intervallo e periodo configurati.","mollieSubscriptionProduct":"Prodotto in abbonamento","mollieSubscriptionIntervalAmount":"Ripeti il pagamento ogni","mollieSubscriptionIntervalType":"Unità di intervallo","mollieSubscriptionRepetitionAmount":"Numero di ripetizioni","mollieSubscriptionRepetitionPlaceholder":"Inserisci numero o lascia vuoto","infoDefaultLanguage":"Si prega di notare che questa configurazione può essere modificata solo nella lingua predefinita. Cambia la tua lingua per modificare le impostazioni di abbonamento di questo prodotto.","btnReadMore":"Leggi di più"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abbonamento"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Dati della carta di credito",buttonMolliePaymentLink:"Copia negli Appunti",columnRefunded:"Rimborsato",columnShipped:"Spedito",columnCanceled:"Annullato",labelMollieOrderId:"ID ordine Mollie",labelMollieThirdPartyPaymentId:"Riferimento pagamento",labelMolliePaymentLink:"URL di Checkout Mollie",totalRefunds:"Importo rimborsato",totalRefundsPending:"In attesa del rimborso",totalRemaining:"Importo rimborsabile",totalVouchers:"Importo del voucher",totalShipments:"Importo spedito ({quantity} articoli)",subscriptionBadge:"Ordine di Abbonamento",refundManager:{title:"Gestore Rimborsi Mollie",btnOpenRefundManager:"Apri Gestore Rimborsi",btnCloseRefundManager:"Chiudi Gestore Rimborsi"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Emittente iDEAL preferito"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Gestore Rimborsi"},mollie_subscription:{label:"Abbonamenti"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Descrizione"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Rimborso",subscription:"Abbonamento",webhookReceived:"Webhook",status:"Stato",started:"Iniziato",ended:"Terminato",paused:"In pausa",renewalReminder:"Promemoria di rinnovo",renewed:"Rinnovato",resumed:"Ripreso",skipped:"Saltato",all:"Tutto",canceled:"Annullato",expired:"Scaduto",partiallyRefunded:"Rimborsato (parzialmente)",orderSuccess:"Ordine completato con successo",orderFailed:"Ordine non riuscito",orderCanceled:"Ordine annullato"}}},X1={entities:{mollie_subscription:"Subscrição Mollie | Subscrições Mollie"},businessEvents:{mollie_checkout_order_success:" Encomenda efetuada com sucesso",mollie_checkout_order_failed:" A encomenda falhou",mollie_checkout_order_canceled:" Encomenda cancelada",mollie_webhook_received_All:" Mollie Webhook recebido (todos)",mollie_webhook_received_status_authorized:" Mollie Webhook recebido (Autorizado)",mollie_webhook_received_status_failed:" Mollie Webhook Recebido (Não efetuado)",mollie_webhook_received_status_canceled:" Mollie Webhook recebido (Cancelado)",mollie_webhook_received_status_expired:" Mollie Webhook Recebido (Expirado)",mollie_webhook_received_status_pending:" Mollie Webhook recebido (Pendente)",mollie_webhook_received_status_paid:" Mollie Webhook Recebido (Pago)",mollie_webhook_received_status_completed:" Mollie Webhook recebido (Concluído)",mollie_webhook_received_status_refunded:" Mollie Webhook Recebido (Reembolsado)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook recebido (Parcialmente Reembolsado)",mollie_refund_started:" Reembolso da Mollie iniciado",mollie_subscription_started:" Subscrição da Mollie iniciada",mollie_subscription_ended:" Subscrição da Mollie concluída",mollie_subscription_cancelled:" Subscrição da Mollie cancelada",mollie_subscription_paused:" Subscrição da Mollie colocada em pausa",mollie_subscription_resumed:" Subscrição da Mollie retomada",mollie_subscription_skipped:" Subscrição da Mollie ignorada",mollie_subscription_renewed:" Subscrição da Mollie renovada",mollie_subscription_renewal_reminder:" Lembrete da Mollie para renovar a subscrição"}},eq={global:X1,"mollie-payments":JSON.parse('{"pluginTitle":"Mollie","pluginDescription":"Módulo Mollie","searchPlaceholder":"Pesquisar subscrições...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Reembolsar através da Mollie","shipThroughMollie":"Enviar através da Mollie","cancelMollieItem":"Cancelar através da Mollie"},"config":{"info":{"title":"Olá {userName}, Bem-vindo(a) à Mollie!","descriptionTop":"A integração é fácil com a Mollie!","descriptionBottom":"É tudo!","descriptionFooter":"Se quiser saber mais sobre o nosso plugin, visite a nossa página de documentação oficial.","onboardingStep1":"Crie uma conta Mollie.","onboardingStep2":"Insira suas chaves de API na secção abaixo.","onboardingStep2TestMode":"Ative o \\"Modo de teste\\" se pretender apenas testar pagamentos.","onboardingStep3":"Atribua métodos de pagamento ao seu canal de vendas.","onboardingStep3Link":"para os seus canais de vendas","btnDocumentation":"Documentação","btnRequestSupport":"Ajuda","btnTroubleshooting":"Guia de Resolução de Problemas"},"api":{"apiLinkButton":"Obtenha as suas chaves de API no Painel de Controlo Mollie","testButton":"Chaves de API de teste","testApiKeys":{"title":"Mollie Payments","apiKey":"Chave de API","isValid":"é válido","isInvalid":"é inválido"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Pré-visualização"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Atualizar métodos de pagamento","succeeded":"Os métodos de pagamento foram atualizados com sucesso.","failed":"Não foi possível atualizar os métodos de pagamento."},"mollieLimits":{"link":"Mostrar as regras de disponibilidade da Mollie para os métodos de pagamento"}},"rounding":{"info1":"O Shopware pode usar as definições de moeda para calcular como arredonda o total de uma encomenda. Isso inclui o número de casas decimais nos preços dos seus produtos e o intervalo de arredondamento mais próximo, como 0,50 ou 1,00.","info2":"Estas definições podem resultar um total diferente do total da soma dos itens. Quando a Mollie verifica que essas quantias não correspondem, cria um erro de checkout.","info3":"Pode utilizar esta função para evitar problemas de arredondamento no seu checkout. Quando ativada, ela adiciona um item de linha separado no seu Painel de Controlo Mollie para a diferença no arredondamento, e os seus clientes pagam o total calculado pelo Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Não é possível usar o Klarna Pagar Agora, Klarna Financiamento ou Klarna Pagar e 30 dias como método quando a sua data de validade é superior a 28 dias, a menos que outro máximo seja acordado entre o comerciante e o Klarna.","bankTransferDueDateLimitReached":"Não é possível definir um tempo de vida superior a 100 dias para uma encomenda."},"support":{"modalTitle":"Pedir ajuda à Mollie","btnCancel":"Cancelar","btnConfirm":"Pedir ajuda","btnSupport":"Mais sobre a nossa ajuda","form":{"name":"O seu nome","email":"O seu e-mail","recipient":"Enviar pedido para","subject":"Assunto","message":"Mensagem"},"data":{"header":"Dados enviados para a Mollie:","other":"Outro:","shopwareVersion":"Versão do Shopware","pluginLogs":"{plugin} arquivos de log","pluginConfiguration":"{plugin} configuração","pluginConfigurationHelpText":"As chaves de API estão excluídas.","paymentMethods":"Dados do método de pagamento","paymentMethodsHelpText":"Contém informações sobre que métodos de pagamento estão ativos e atribuídos a cada canal de vendas, bem como o seu estado na sua conta Mollie."},"success":"O pedido de ajuda foi enviado com sucesso. Faremos o nosso melhor para responder o mais rapidamente possível.","error":"Ocorreu um problema ao enviar o e-mail pelo Shopware. Por favor, tente novamente ou entre em contacto diretamente por e-mail."}},"rules":{"itemSubscriptionRule":"Item é uma subscrição (Mollie)","cartSubscriptionRule":"Carrinho com subscrições (Mollie)"},"refunds":{"status":{"queued":"Em fila de espera","pending":"Pendente","processing":"A processar","refunded":"Reembolsado","failed":"Não efetuado","description":{"queued":"O reembolso é colocado em fila de espera até que haja saldo suficiente para o processar. Ainda é possível cancelar o reembolso.","pending":"O reembolso será enviado ao banco no próximo dia útil. Ainda é possível cancelar o reembolso.","processing":"O reembolso foi enviado para o banco. O montante do reembolso será transferido para a conta do consumidor o mais rapidamente possível.","refunded":"O montante do reembolso foi transferido para o consumidor.","failed":"O reembolso falhou após o processamento. Por exemplo, o cliente fechou a sua conta bancária. Os fundos serão devolvidos à sua conta."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Não tem permissões para criar reembolsos","warningCancel":"Não tem permissões para cancelar reembolsos"},"cart":{"title":"Encomenda ##orderNumber##","btnSelectAll":"Selecionar Tudo","btnResetForm":"Reiniciar Formulário","linkHowTo":"Como utilizar este formulário?","grid":{"columns":{"item":"Item","productNumber":"Número do Produto","unitPrice":"Preço Unitário","quantity":"Quantidade","refunded":"Reembolsado","refundQuantity":"Reembolso","totalPrice":"Total","refundAmount":"Reembolso","resetStock":"Repor o stock"},"btnResetLine":"Redefinir Linha","checkDeductPromotion":"Deduzir promoção","checkRefundTax":"Reembolsar o IVA"},"roundDiffItemAdded":"Item de arredondamento automático adicionado"},"instructions":{"linkResetTutorials":"Repor Tutoriais","btnToggleTutorial":"Mostrar/Ocultar Tutorial","titleFullRefund":"Reembolso Total","textFullRefund":"Basta utilizar o botão para o reembolso total. Isto garante que todos os seus itens são marcados como reembolsados e que o montante total é devolvido ao cliente.","titleStockReset":"Reposição de stock","textStockReset":"Pode aumentar automaticamente o stock disponível, introduzindo a quantidade que pretende repor em stock. Basta introduzi-la antes de proceder a um reembolso total ou parcial. A reposição do stock pode ser combinada com o processo de reembolso de forma flexível.","titleShipping":"Envio","textShipping":"Os itens de envio podem ser reembolsados como qualquer outro artigo. Basta inserir a quantidade total ou um montante parcial personalizado e prosseguir com o reembolso. O reembolso dos custos de envio pode ser combinado com o processo de reembolso efetivo de itens de forma flexível.","titlePartialAmount":"Reembolso parcial (apenas o montante)","textPartialAmount":"Basta introduzir o montante parcial no campo de texto e iniciar o reembolso.","titlePartialItems":"Reembolso parcial (com artigos)","textPartialItems":"Se pretender marcar quantidades e itens como reembolsados na Mollie, utilize o formulário acima. Defina as suas quantidades e forneça um montante personalizado para cada artigo que será reembolsado. A soma total será então visível no campo de texto do valor final do reembolso. Lembre-se que ainda é possível ajustar esse valor final antes de iniciar o reembolso.","titlePartialPromotions":"Reembolso Parcial (com promoções)","textPartialPromotions":"Se tiver uma promoção no seu carrinho, a promoção é um item de linha separado. Se pretender reembolsar todos os artigos com desconto, reembolse os seus valores totais e a totalidade do item de linha da promoção. No entanto, se pretender reembolsar apenas alguns itens com desconto, pode deduzir automaticamente o desconto aplicado a cada item. É claro que pode sempre alterar os valores se estes não estiverem corretos.","titleRoundingDiff":"Diferença de arredondamento","textRoundingDiff":"O reembolso total incluirá as diferenças de arredondamento"},"summary":{"dataLoading":"Os dados estão a ser carregados...","headerExcludingVat":"Sem IVA","headerIncludingVat":"Com IVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"A aguardar reembolso","captionVouchers":"Montante do cupão","captionRefunded":"Montante reembolsado","captionRemaining":"Montante reembolsável","btnFixDiff":"Corrigir a diferença","placeholderDescription":"Introduzir a descrição do extrato do banco/cartão para o consumidor. Máximo de 140 caracteres","lblDescription":"Descrição (opcional) ({characters}/140 caracteres)","descriptionHelp":"Sempre que possível, esta mensagem será apresentada no extrato bancário ou do cartão do consumidor. A mensagem será truncada após 140 caracteres.","placeholderInternalDescription":"Introduza a sua descrição interna","lblInternalDescription":"Descrição interna (opcional)","internalDescriptionHelp":"Isto será mostrado como uma descrição local na interface de administração.","checkVerification":"Verifiquei o montante total do reembolso e as quantidades configuradas para reembolsar e repor em stock.","btnRefund":"Reembolso","btnFullRefund":"Reembolso Total","roundDiffItemAdded":"Item de arredondamento"},"refunds":{"title":"Reembolsos no Painel de Controlo Mollie","linkMore":"Mais sobre reembolsos","grid":{"columns":{"amount":"Montante","status":"Estado","description":"Descrição","internalDescription":"Descrição interna","composition":"Composição","date":"Data"},"lblNoComposition":"Nenhuma composição disponível","btnCancelRefund":"Cancelar este reembolso"}},"notifications":{"success":{"refund-created":"Foi criado um reembolso na Mollie. Este pode demorar 2 horas a ficar concluído. Até lá, pode cancelar o reembolso.","refund-canceled":"O reembolso pendente foi cancelado e eliminado com sucesso."},"error":{"low-amount":"Introduza o montante a reembolsar.","refund-created":"Algo correu mal ao criar um reembolso.","refund-canceled":"Ocorreu um problema ao cancelar o reembolso pendente. Por favor, tente novamente no Painel de Controlo Mollie."}}},"vouchers":{"CARD_TITLE":"Cupão","VOUCHER_INFO_TITLE":"Pagamentos com cupão","VOUCHER_INFO_DESCRIPTION":"A Mollie permite-lhe aceitar facilmente pagamentos na sua loja virtual utilizando cupão Eco, de oferta e de refeição - uma escolha inteligente para aumentar as suas vendas e a satisfação dos seus clientes. O método de pagamento \\"cupão\\" só é visível se tiver pelo menos um produto com um tipo de vale atribuído no carrinho.","VOUCHER_INFO_DEFAULTLANGUAGE":"Atenção, esta configuração só pode ser editada na sua língua predefinida. Altere a sua língua para modificar o tipo de cupão deste produto.","VOUCHER_BTN_READMORE":"Ler mais","VOUCHER_TYPE_CAPTION":"Tipo de cupão do produto","VOUCHER_TYPE_VALUE_NONE":"Nenhum","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Refeição","VOUCHER_TYPE_VALUE_VOUCHER":"Presente"},"modals":{"shipping":{"title":"Enviar através da Mollie","item":{"label":"Item:","noQuantity":"Por favor, introduza a quantidade a enviar.","shipAll":"Enviar tudo","summary":{"quantity":"Quantidade a enviar","shipped":"Quantidade enviada","shippable":"Quantidade enviável"},"success":"A encomenda foi enviada com sucesso."},"order":{"description":"As seguintes quantidades de itens serão enviadas.","itemHeader":"Item","quantityHeader":"Quantidade","originalQuantityHeader":"Quantidade (enviável)"},"availableTracking":{"label":"Códigos de rastreio disponíveis","hint":"Clique em um destes códigos de rastreio para preencher automaticamente todos os dados."},"showTracking":"Adicionar informações de rastreio para este envio","tracking":{"carrier":"Transportadora","code":"Código","url":"URL","invalid":"Por favor, introduza a Transportadora e o Código"},"confirmButton":"Enviar encomenda","cancelButton":"Cancelar","selectAllButton":"Selecionar tudo","resetButton":"Repor"},"cancel":{"title":"Cancelar item através da Mollie","confirmButton":"Cancelar item através da Mollie","cancelButton":"Fechar modal","resetStock":"Repor stock","item":{"success":"Produto cancelado com sucesso","failed":{"quantityZero":"A quantidade é 0","invalidLine":"O produto não existe na encomenda","quantityTooHigh":"A quantidade é demasiado elevada"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Enviar Encomenda (Mollie)","description":"Enviar encomenda na Mollie."},"modal":{"title":"Enviar Encomenda","description":"Esta ação enviará automaticamente uma encomenda através da Mollie. A sequência de fluxo receberá o número da encomenda e transmiti-lo-á à API da Mollie. Envios bem-sucedidos e falhados serão visíveis nos arquivos de log da Mollie.","warningConfig":"Certifique-se de que desativa qualquer automação adicional para este tipo de ação para evitar quaisquer interferências.\\nAs seguintes funcionalidades ativadas deste plugin podem interferir com esta ação:","noWarnings":"Sem avisos"}},"refundOrder":{"editor":{"title":"Reembolsar Encomenda (Mollie)","description":"Reembolsar encomenda através da Mollie."},"modal":{"title":"Reembolsar Encomenda","description":"Esta ação iniciará automaticamente um reembolso através da Mollie. A sequência de fluxo receberá o número da encomenda e o transmiti-lo-á à API da Mollie. Reembolsos bem-sucedidos e falhados serão visíveis nos arquivos de log da Mollie.","warning":"Por favor, lembre-se de que os reembolsos podem levar até 2 horas para serem finalizados e visíveis na loja. Até lá, pode sempre cancelar um reembolso pendente, seja na página da encomenda no Shopware ou no Painel de Controlo da Mollie.","warningConfig":"Por favor, certifique-se de que desativa qualquer automação adicional para este tipo de ação para evitar qualquer interferência."}},"warnings":{"automaticShipping":"Envio automático na configuração do plugin"}}},"subscriptions":{"status":{"pending":"Pendente","active":"Ativo","canceled":"Cancelado","suspended":"Suspenso","completed":"Concluído","paused":"Em pausa","resumed":"Retomado","skipped":"Ignorado"},"navigation":{"title":"Subscrições Mollie"},"TYPE_DAYS":"Dia(s)","TYPE_WEEKS":"Semana(s)","TYPE_MONTHS":"Mês(es)","confirm":{"cancelTitle":"Cancelar a subscrição?","cancel":"Cancelar a subscrição do seu cliente.","pauseTitle":"Colocar a subscrição em espera?","pause":"Colocar a subscrição em pausa até retomá-la novamente.","resumeTitle":"Retomar a subscrição?","resume":"Continuar a subscrição novamente.","skipTitle":"Saltar a próxima prestação?","skip":"Saltar a próxima prestação na subscrição. Continuará automaticamente depois disso."},"alerts":{"cancelSuccess":"A subscrição foi cancelada com sucesso","pauseSuccess":"A subscrição foi colocada em pausa com sucesso","resumeSuccess":"A subscrição foi retomada com sucesso","skipSuccess":"A subscrição foi saltada com sucesso. O próximo pagamento foi atualizado."},"list":{"title":"Subscrições Mollie","columns":{"customer":"Cliente","status":"Estado","description":"Descrição","amount":"Montante","nextPaymentAt":"Próximo pagamento","prePaymentReminder":"Relembrado em","canceledAt":"Cancelado em","createdAt":"Criado em"},"action":{"edit":"Editar subscrição"},"deletedCustomer":"Cliente eliminado"},"detail":{"title":"Subscrição Mollie","buttonCancelSubscription":"Cancelar subscrição","labelDescription":"Descrição","labelAmount":"Montante","labelQuantity":"Quantidade","labelMollieSubscription":"Subscrição Mollie","labelMollieCustomer":"Cliente Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente Shopware","labelCreatedAt":"Criado em","buttonShowShopwareOrder":"Mostrar ordem do Shopware","buttonShowShopwareCustomer":"Mostrar cliente do Shopware","cardTitleSubscription":"Subscrição","cardTitleStatus":"Estado","labelStatus":"Estado","labelNextPaymentAt":"Próximo pagamento em","labelLastRemindedAt":"Lembrado pela última vez em","labelCanceledAt":"Cancelado em","buttonPauseSubscription":"Colocar subscrição em pausa","buttonResumeSubscription":"Retomar subscrição","buttonSkipSubscription":"Ignorar subscrição","history":{"cardTitle":"Histórico","colDate":"Data","colComment":"Comentário","colStatusFrom":"Estado (de)","colStatusTo":"Estado (para)","colMollieSubscription":"Subscrição Mollie"}},"product":{"card-title":"Subscrição","title":"Subscrições Mollie","description":"Gerir os seus pagamentos recorrentes é mais fácil do que nunca com as nossas funcionalidades úteis. Leve o seu negócio ao próximo nível com opções de acompanhamento eficientes, integrações simples e muito mais. Com as subscrições Mollie, pode criar facilmente produtos de subscrição e programar pagamentos recorrentes para ocorrerem no intervalo e período configurados.","mollieSubscriptionProduct":"Produto de Subscrição","mollieSubscriptionIntervalAmount":"Repetir pagamento a cada","mollieSubscriptionIntervalType":"Unidade de intervalo","mollieSubscriptionRepetitionAmount":"Número de repetições","mollieSubscriptionRepetitionPlaceholder":"Introduzir o número ou deixar em branco","infoDefaultLanguage":"Atenção: esta configuração só pode ser editada na sua língua predefinida. Altere a sua língua para modificar as definições de subscrição deste produto.","btnReadMore":"Ler mais"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subscrição"}}'),"sw-order":{detailExtended:{titleCreditCardData:"Dados do cartão de crédito",buttonMolliePaymentLink:"Copiar para a área de transferência",columnRefunded:"Reembolsado",columnShipped:"Enviado",columnCanceled:"Cancelado",labelMollieOrderId:"ID de Encomenda da Mollie",labelMollieThirdPartyPaymentId:"Referência de pagamento",labelMolliePaymentLink:"URL do Mollie Checkout",totalRefunds:"Montante reembolsado",totalRefundsPending:"A aguardar reembolso",totalRemaining:"Montante reembolsável",totalVouchers:"Montante do cupão",totalShipments:"Montante enviado ({quantity} itens)",subscriptionBadge:"Pedido de subscrição",refundManager:{title:"Gestor de Reembolsos da Mollie",btnOpenRefundManager:"Abrir Gestor de Reembolsos",btnCloseRefundManager:"Fechar Gerente de Reembolsos"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Emissor iDeal preferido"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Gestor de Reembolsos"},mollie_subscription:{label:"Subscrições"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Descrição"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Reembolso",subscription:"Subscrição",webhookReceived:"Webhooks",status:"Estado",started:"Iniciado",ended:"Terminado",paused:"Em pausa",renewalReminder:"Lembrete de Renovação",renewed:"Renovado",resumed:"Retomado",skipped:"Ignorado",all:"Todos",canceled:"Cancelado",expired:"Expirado",partiallyRefunded:"Reembolsado (parcialmente)",orderSuccess:"Encomenda bem sucedida",orderFailed:"Encomenda não efetuada",orderCanceled:"Encomenda cancelada"}}},tq={entities:{mollie_subscription:"Suscripciones Mollie | Suscripción Mollie"},businessEvents:{mollie_checkout_order_success:" Pedido realizado",mollie_checkout_order_failed:" Pedido fallido",mollie_checkout_order_canceled:" Pedido cancelado",mollie_webhook_received_All:" Mollie Webhook Recibido (Todo)",mollie_webhook_received_status_authorized:" Mollie Webhook Recibido (Autorizado)",mollie_webhook_received_status_failed:" Mollie Webhook Recibido (Fallido)",mollie_webhook_received_status_canceled:" Mollie Webhook Recibido (Cancelado)",mollie_webhook_received_status_expired:" Mollie Webhook Recibido (Expirado)",mollie_webhook_received_status_pending:" Mollie Webhook Recibido (Pendiente)",mollie_webhook_received_status_paid:" Mollie Webhook Recibido (Pagado)",mollie_webhook_received_status_completed:" Mollie Webhook Recibido (Completado)",mollie_webhook_received_status_refunded:" Mollie Webhook Recibido (Reembolsado)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Recibido (Reembolso parcial)",mollie_refund_started:"Reembolso de Mollie iniciado",mollie_subscription_started:"Suscripción de Mollie iniciada",mollie_subscription_ended:"Suscripción de Mollie completada",mollie_subscription_cancelled:"Suscripción de Mollie cancelada",mollie_subscription_paused:"Suscripción de Mollie en pausa",mollie_subscription_resumed:"Suscripción de Mollie reanudada",mollie_subscription_skipped:" Suscripción de Mollie pospuesta",mollie_subscription_renewed:"Suscripción de Mollie renovada",mollie_subscription_renewal_reminder:"Recordatorio de suscripción de Mollie"}},rq={global:tq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Módulo Mollie","searchPlaceholder":"Buscar suscripciones...","general":{"mainMenuItemGeneral":"Pagos Mollie","descriptionTextModule":"Pagos Mollie","btnMollieActions":"Mollie Actions","refundThroughMollie":"Reembolso a través de Mollie","shipThroughMollie":"Enviar a través de Mollie","cancelMollieItem":"Cancelar a través de Mollie"},"config":{"info":{"title":"Hola {userName}, ¡bienvenid@ a Mollie!","descriptionTop":"¡La integración con Mollie es fácil!","descriptionBottom":"¡Eso es todo!","descriptionFooter":"Si deseas más información sobre nuestro plugin, visita nuestra página oficial de documentación.","onboardingStep1":"Crea una cuenta con Mollie.","onboardingStep2":"Introduce tus claves API en la sección de abajo.","onboardingStep2TestMode":"Activa el 'Modo de prueba' si únicamente deseas probar los pagos.","onboardingStep3":"Establece los métodos de pago en tus canales de venta.","onboardingStep3Link":"en tus canales de venta","btnDocumentation":"Documentación","btnRequestSupport":"Ayuda","btnTroubleshooting":"Guía de resolución de problemas"},"api":{"apiLinkButton":"Accede a tus claves API desde Mollie Dashboard","testButton":"Claves API de prueba","testApiKeys":{"title":"Pagos Mollie","apiKey":"Clave API","isValid":"es válido","isInvalid":"no es válido"}},"payments":{"format":{"placeholder":"Texto de muestra","preview":"Vista previa"},"updatePaymentMethods":{"title":"Pagos Mollie","button":"Actualizar métodos de pago","succeeded":"Los métodos de pago se han actualizado correctamente.","failed":"No ha sido posible actualizar los métodos de pago."},"mollieLimits":{"link":"Mostrar reglas de disponibilidad de Mollie para métodos de pago"}},"rounding":{"info1":"Shopware utiliza los ajustes sobre la moneda para calcular el redondeo del importe total de un pedido. Esto incluye el número de decimales en la fijación de precios de productos y el intervalo de redondeo como 0,50 o 1,00.","info2":"Estos ajustes pueden generar un importe total diferente al importe de los artículos. Al verificar Mollie estas cantidades y no coincidir, se produce un error en el proceso de pago.","info3":"Puedes utilizar esta función para evitar problemas de redondeo en tu proceso de pago. Cuando se activa esta función, se añade una nueva línea de artículo en el Mollie Dashboard con la diferencia del redondeo, y tus clientes pagan el total calculado por Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"No es posible elegir Klarna (paga ahora, paga en cuotas o paga más tarde) como método de pago si el plazo de vencimiento es superior a 28 días, salvo que haya un acuerdo especial entre Klarna y el comerciante para extenderlo.","bankTransferDueDateLimitReached":"No es posible establecer el tiempo de vida de un pedido superior a 100 días."},"support":{"modalTitle":"Solicitar ayuda de Mollie","btnCancel":"Cancelar","btnConfirm":"Solicitar ayuda","btnSupport":"Más sobre nuestra ayuda","form":{"name":"Nombre","email":"Correo electrónico","recipient":"Enviar solicitud a","subject":"Asunto","message":"Mensaje"},"data":{"header":"Datos enviados a Mollie:","other":"Otros:","shopwareVersion":"Versión de Shopware","pluginLogs":"archivos de registro de {plugin}","pluginConfiguration":"configuración de {plugin}","pluginConfigurationHelpText":"Las claves API no están incluidas.","paymentMethods":"Datos de métodos de pago","paymentMethodsHelpText":"Contiene información sobre qué métodos de pago están activos, asignados a cada canal de venta, así como su estado en tu cuenta de Mollie."},"success":"La solicitud de ayuda se ha enviado correctamente. Haremos el mayor esfuerzo para responder lo antes posible","error":"Ha habido un problema al enviar el correo a través de Shopware. Por favor, inténtalo de nuevo o contáctanos por correo electrónico."}},"rules":{"itemSubscriptionRule":"El artículo es una suscripción (Mollie)","cartSubscriptionRule":"Carrito con suscripciones (Mollie)"},"refunds":{"status":{"queued":"En cola","pending":"Pendiente","processing":"Procesando","refunded":"Reembolsado","failed":"Fallido","description":{"queued":"El reembolso está en la cola hasta que haya suficiente saldo para procesarlo. Todavía puedes cancelar el reembolso.","pending":"El reembolso se enviará al banco el siguiente día hábil. Todavía puedes cancelar el reembolso.","processing":"El reembolso ha sido enviado al banco. La cantidad reembolsada se transferirá a la cuenta del consumidor lo antes posible.","refunded":"La cantidad reembolsada ha sido transferida al consumidor.","failed":"No ha sido posible abonar el reembolso tras procesarlo. Es posible que el cliente haya cerrado su cuenta bancaria. Los fondos serán devueltos a tu cuenta."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"No tienes permisos para crear reembolsos","warningCancel":"No tienes permisos para cancelar reembolsos"},"cart":{"title":"Pedido ##orderNumber##","btnSelectAll":"Seleccionar todo","btnResetForm":"Restablecer formulario","linkHowTo":"¿Cómo usar este formulario?","grid":{"columns":{"item":"Artículo","productNumber":"Número de producto","unitPrice":"Precio unitario","quantity":"Cantidad","refunded":"Reembolsado","refundQuantity":"Reembolso","totalPrice":"Total","refundAmount":"Reembolso","resetStock":"Restablecer stock"},"btnResetLine":"Restablecer línea","checkDeductPromotion":"Deducir la promoción","checkRefundTax":"Devolver IVA"},"roundDiffItemAdded":"Se ha añadido automáticamente un artículo con redondeo"},"instructions":{"linkResetTutorials":"Restablecer tutoriales","btnToggleTutorial":"Mostrar/Ocultar tutorial","titleFullRefund":"Reembolso completo","textFullRefund":"Usa este botón para el reembolso completo. Esto garantiza que todos tus artículos están marcados como reembolsados y la cantidad total se reembolsa al cliente.","titleStockReset":"Restablecer el stock","textStockReset":"Puedes aumentar el stock disponible de manera automática añadiendo la cantidad a reponer. Simplemente añade la información antes de continuar con un reembolso total o parcial. Restablecer el stock se puede combinar con el proceso de reembolso.","titleShipping":"Envío","textShipping":"Los artículos con envío se pueden reembolsar como cualquier otro producto. Simplemente escribe la cantidad total o la deseada y procede con el reembolso. Reembolsar los costes de envío se puede combinar con el proceso de reembolso de artículos.","titlePartialAmount":"Reembolso parcial (solo importe)","textPartialAmount":"Simplemente añade el importe parcial en el campo de texto e inicia el reembolso.","titlePartialItems":"Reembolso parcial (con artículos)","textPartialItems":"Utiliza el formulario de arriba para marcar cantidades y artículos reembolsados en Mollie. Establece tus cantidades y añade el importe único para cada artículo reembolsado. La suma total será visible en el campo de texto de importe total reembolsado. Recuerda que puedes ajustar el importe final antes de empezar con el reembolso.","titlePartialPromotions":"Reembolso parcial (con promociones)","textPartialPromotions":"Si tienes una promoción en el carrito, la promoción aparecerá como una línea de artículo nueva. Si quieres reembolsar todos los artículos con descuento, tienes que devolver la línea del valor total y la línea de artículo con promoción. Si quieres reembolsar solo algunos artículos con descuento, puedes deducir el descuento aplicado para cada artículo de línea de manera automática. Por supuesto, siempre puedes cambiar los valores si no son correctos.","titleRoundingDiff":"Diferencia de redondeo","textRoundingDiff":"Un reembolso completo incluirá diferencias de redondeo"},"summary":{"dataLoading":"Cargando datos...","headerExcludingVat":"Sin IVA","headerIncludingVat":"Con IVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Esperando reembolso","captionVouchers":"Importe del vale","captionRefunded":"Importe reembolsado","captionRemaining":"Importe reembolsable","btnFixDiff":"Corregir diferencia","placeholderDescription":"Introduce la descripción del movimiento en la cuenta bancaria/tarjeta del consumidor. Máx. 140 caracteres","lblDescription":"Descripción (opcional) ({characters}/140 caracteres)","descriptionHelp":"El texto se mostrará en el extracto del banco o en la tarjeta del consumidor. Pasados los 140 caracteres, el mensaje no será visible.","placeholderInternalDescription":"Introduce la descripción interna","lblInternalDescription":"Descripción interna (opcional)","internalDescriptionHelp":"El texto se mostrará como una descripción local en la interfaz de administración.","checkVerification":"He verificado el importe total del reembolso, las cantidades configuradas del reembolso y el stock.","btnRefund":"Reembolso","btnFullRefund":"Reembolso completo","roundDiffItemAdded":"Artículo de redondeo"},"refunds":{"title":"Reembolsos en el Mollie Dashboard","linkMore":"Más sobre reembolsos","grid":{"columns":{"amount":"Importe","status":"Estado","description":"Descripción","internalDescription":"Descripción interna","composition":"Composición","date":"Fecha"},"lblNoComposition":"No hay composición disponible","btnCancelRefund":"Cancelar este reembolso"}},"notifications":{"success":{"refund-created":"Se ha creado un reembolso en Mollie. Puede tardar hasta 2 horas en completarse. Pasado este tiempo, no se podrá cancelar.","refund-canceled":"El reembolso pendiente ha sido cancelado y eliminado."},"error":{"low-amount":"Por favor, introduce el importe a devolver.","refund-created":"Algo salió mal al crear un reembolso.","refund-canceled":"Ha habido un error al cancelar el reembolso pendiente. Por favor, inténtalo de nuevo en el Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vale","VOUCHER_INFO_TITLE":"Pagos con vales","VOUCHER_INFO_DESCRIPTION":"Mollie permite aceptar pagos de tu tienda online con vales ecológicos, de regalo y de comida. Esta opción puede aumentar las ventas y satisfacer a tus clientes. El método de pago con un \\"vale\\" es visible solo si tienes al menos 1 producto con un tipo de vale asignado en el carrito.","VOUCHER_INFO_DEFAULTLANGUAGE":"Ten en cuenta que esta configuración solo puede ser editada en tu idioma predeterminado. Por favor, cambia tu idioma para modificar el tipo de vale de este producto.","VOUCHER_BTN_READMORE":"Seguir leyendo","VOUCHER_TYPE_CAPTION":"Artículos tipo vale","VOUCHER_TYPE_VALUE_NONE":"Ninguno","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Comida","VOUCHER_TYPE_VALUE_VOUCHER":"Regalo"},"modals":{"shipping":{"title":"Enviar a través de Mollie","item":{"label":"Artículo:","noQuantity":"Por favor, introduce la cantidad a enviar.","shipAll":"Enviar todo","summary":{"quantity":"Cantidad a enviar","shipped":"Cantidad enviada","shippable":"Cantidad enviable"},"success":"El pedido ha sido enviado con éxito."},"order":{"description":"Las siguientes cantidades de artículos serán enviadas.","itemHeader":"Artículo","quantityHeader":"Cantidad","originalQuantityHeader":"Cantidad (enviable)"},"availableTracking":{"label":"Códigos de seguimiento disponibles","hint":"Haz clic en uno de los códigos de seguimiento para completar todos los datos."},"showTracking":"Añadir información de seguimiento para este envío","tracking":{"carrier":"Empresa de transporte","code":"Código","url":"Url","invalid":"Por favor, introduce tanto la empresa de transporte como el código"},"confirmButton":"Enviar pedido","cancelButton":"Cancelar","selectAllButton":"Seleccionar todo","resetButton":"Restablecer"},"cancel":{"title":"Cancelar artículo a través de mollie","confirmButton":"Cancelar artículo a través de mollie","cancelButton":"Cerrar modal","resetStock":"Restablecer stocks","item":{"success":"Producto cancelado con éxito","failed":{"quantityZero":"La cantidad es 0","invalidLine":"El producto no existe en el pedido","quantityTooHigh":"La cantidad es demasiado alta"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Enviar pedido (Mollie)","description":"Enviar pedido a través de Mollie."},"modal":{"title":"Enviar pedido","description":"Esta acción enviará el pedido a través de Mollie de forma automática. La secuencia de flujo recibirá el número del pedido y lo pasará a la API de Mollie. Los envíos procesados y los fallidos serán visibles en el registro de Mollie.","warningConfig":"Por favor, desactiva cualquier automatización adicional para acciones de este tipo y evitar interferencias.\\nLos siguientes parámetros están activados y podrían interferir con la acción:","noWarnings":"Sin advertencias"}},"refundOrder":{"editor":{"title":"Reembolsar pedido (Mollie)","description":"Reembolsar pedido a través de Mollie."},"modal":{"title":"Reembolsar pedido","description":"Esta acción iniciará el reembolso a través de Mollie de forma automática. La secuencia de flujo recibirá el número del pedido y lo pasará a la API de Mollie. Los reembolsos procesados y fallidos serán visibles en el registro de Mollie.","warning":"Por favor, ten en cuenta que los reembolsos tardan hasta 2 horas en completarse y ser visibles en la tienda. Antes de este tiempo, siempre puedes cancelar un reembolso pendiente, bien desde la página del pedido en Shopware o desde el Mollie Dashboard.","warningConfig":"Por favor, asegúrate de desactivar cualquier automatización adicional para este tipo de acciones para evitar interferencias."}},"warnings":{"automaticShipping":"Envío automático en la configuración del plugin"}}},"subscriptions":{"status":{"pending":"Pendiente","active":"Activo","canceled":"Cancelado","suspended":"Suspendido","completed":"Completado","paused":"En pausa","resumed":"Reanudado","skipped":"Pospuesto"},"navigation":{"title":"Suscripciones de Mollie"},"TYPE_DAYS":"Día(s)","TYPE_WEEKS":"Semana(s)","TYPE_MONTHS":"Mes(es)","confirm":{"cancelTitle":"¿Finalizar suscripción?","cancel":"Cancelar la suscripción de tu cliente.","pauseTitle":"¿Pausar suscripción?","pause":"Pausar la suscripción hasta nuevo aviso.","resumeTitle":"¿Reanudar suscripción?","resume":"Continuar con la suscripción.","skipTitle":"¿Saltar el pago de la cuota?","skip":"Pospón el pago de la siguiente cuota de suscripción. Continúa después automáticamente."},"alerts":{"cancelSuccess":"La suscripción se ha cancelado con éxito","pauseSuccess":"La suscripción está en pausa","resumeSuccess":"La suscripción se ha reanudado con éxito","skipSuccess":"El pago de la suscripción se ha pospuesto. El siguiente pago ha sido actualizado."},"list":{"title":"Suscripciones de Mollie","columns":{"customer":"Cliente","status":"Estado","description":"Descripción","amount":"Importe","nextPaymentAt":"Próximo pago","prePaymentReminder":"Recordado el","canceledAt":"Cancelado el","createdAt":"Creado el"},"action":{"edit":"Editar suscripción"},"deletedCustomer":"Cliente eliminado"},"detail":{"title":"Suscripción de Mollie","buttonCancelSubscription":"Cancelar suscripción","labelDescription":"Descripción","labelAmount":"Importe","labelQuantity":"Cantidad","labelMollieSubscription":"Suscripción de Mollie","labelMollieCustomer":"Cliente de Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente de Shopware","labelCreatedAt":"Creado el","buttonShowShopwareOrder":"Mostrar pedido de Shopware","buttonShowShopwareCustomer":"Mostrar cliente de Shopware","cardTitleSubscription":"Suscripción","cardTitleStatus":"Estado","labelStatus":"Estado","labelNextPaymentAt":"Próximo pago el","labelLastRemindedAt":"Último recordatorio el","labelCanceledAt":"Cancelado el","buttonPauseSubscription":"Pausar suscripción","buttonResumeSubscription":"Reanudar suscripción","buttonSkipSubscription":"Posponer suscripción","history":{"cardTitle":"Historial","colDate":"Fecha","colComment":"Comentario","colStatusFrom":"Estado (de)","colStatusTo":"Estado (a)","colMollieSubscription":"Suscripción Mollie"}},"product":{"card-title":"Suscripción","title":"Suscripciones Mollie","description":"Es muy fácil gestionar pagos recurrentes gracias a las funciones que ofrecemos. Lleva tu negocio al siguiente nivel con opciones de seguimiento, integraciones sencillas y más. Con las suscripciones Mollie, puedes crear suscripciones y programar pagos recurrentes con el cobro en un intervalo y período establecido.","mollieSubscriptionProduct":"Producto de suscripción","mollieSubscriptionIntervalAmount":"Repetir pago cada","mollieSubscriptionIntervalType":"Unidad de intervalo","mollieSubscriptionRepetitionAmount":"Número de repeticiones","mollieSubscriptionRepetitionPlaceholder":"Introduce un número o deja vacío","infoDefaultLanguage":"Ten en cuenta que esta configuración solo puede ser editada en tu idioma predeterminado. Por favor, cambia tu idioma para modificar la configuración de la suscripción.","btnReadMore":"Seguir leyendo"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Suscripción"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Datos de tarjeta de crédito",buttonMolliePaymentLink:"Copiar al portapapeles",columnRefunded:"Reembolsado",columnShipped:"Enviado",columnCanceled:"Cancelado",labelMollieOrderId:"Núm. de pedido de Mollie",labelMollieThirdPartyPaymentId:"Referencia de pago",labelMolliePaymentLink:"URL de pago de Mollie",totalRefunds:"Cantidad reembolsada",totalRefundsPending:"Reembolso pendiente",totalRemaining:"Cantidad reembolsable",totalVouchers:"Importe del vale",totalShipments:"Cantidad enviada ({quantity} artículos)",subscriptionBadge:"Pedido de suscripción",refundManager:{title:"Administrador de reembolsos Mollie",btnOpenRefundManager:"Abrir administrador de reembolsos",btnCloseRefundManager:"Cerrar administrador de reembolsos"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Emisor iDeal preferido"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Administrador de reembolsos"},mollie_subscription:{label:"Suscripciones"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Descripción"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Reembolso",subscription:"Suscripción",webhookReceived:"Webhooks",status:"Estado",started:"Iniciado",ended:"Finalizado",paused:"En pausa",renewalReminder:"Recordatorio de renovación",renewed:"Renovado",resumed:"Reanudado",skipped:"Pospuesto",all:"Todos",canceled:"Cancelado",expired:"Caducado",partiallyRefunded:"Reembolsado (parcialmente)",orderSuccess:"Pedido realizado",orderFailed:"Pedido fallido",orderCanceled:"Pedido cancelado"}}},aq={entities:{mollie_subscription:"Mollie Prenumeration | Mollie Prenumerationer"},businessEvents:{mollie_checkout_order_success:" Lyckad beställning",mollie_checkout_order_failed:" Misslyckad beställning",mollie_checkout_order_canceled:" Avbruten beställningen",mollie_webhook_received_All:" Mollie Webhook Mottagen (Alla)",mollie_webhook_received_status_authorized:" Mollie Webhook Mottagen (Auktoriserad)",mollie_webhook_received_status_failed:" Mollie Webhook Mottagen (Misslyckad)",mollie_webhook_received_status_canceled:" Mollie Webhook Mottagen (Avbruten)",mollie_webhook_received_status_expired:" Mollie Webhook Mottagen (Har utgått)",mollie_webhook_received_status_pending:" Mollie Webhook Mottagen (Pågående)",mollie_webhook_received_status_paid:" Mollie Webhook Mottagen (Betald)",mollie_webhook_received_status_completed:" Mollie Webhook Mottagen (Slutförd)",mollie_webhook_received_status_refunded:" Mollie Webhook Mottagen (Återbetald)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Mottagen (Delvis återbetalad)",mollie_refund_started:" Mollie återbetalning påbörjad",mollie_subscription_started:" Mollie-prenumerationen har startat",mollie_subscription_ended:" Mollie-prenumerationen slutförd",mollie_subscription_cancelled:" Mollie prenumeration avbruten",mollie_subscription_paused:" Mollie-prenumerationen har pausats",mollie_subscription_resumed:" Mollie-prenumerationen har återupptagits",mollie_subscription_skipped:" Mollie-prenumerationen har hoppats över",mollie_subscription_renewed:" Mollie prenumeration förnyad",mollie_subscription_renewal_reminder:" Mollie påminnelse för prenumerationsförnyelse"}},iq={global:aq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Sök prenumerationer...","general":{"mainMenuItemGeneral":"Mollie Betalningar","descriptionTextModule":"Mollie Betalningar","btnMollieActions":"Mollie åtgärder","refundThroughMollie":"Återbetalning genom Mollie","shipThroughMollie":"Frakta genom Mollie","cancelMollieItem":"Avbryt genom Mollie"},"config":{"info":{"title":"Hej {userName}, Välkommen till Mollie!","descriptionTop":"Att börja med Mollie är enkelt!","descriptionBottom":"Det var allt!","descriptionFooter":"Om du vill lära dig mer om vårt plugin, vänligen besök vår officiella dokumentationssida.","onboardingStep1":"Registrera dig för ett Mollie-konto.","onboardingStep2":"Ange dina API-nycklar i avsnittet nedan.","onboardingStep2TestMode":"Slå på 'Test Mode' om du endast vill testa betalningar.","onboardingStep3":"Tilldela betalningsmetoder till din försäljningskanal.","onboardingStep3Link":"till dina försäljningskanaler","btnDocumentation":"Dokumentation","btnRequestSupport":"Stöd","btnTroubleshooting":"Felsökningsguide"},"api":{"apiLinkButton":"Hämta dina API-nycklar från Mollie Dashboard","testButton":"Test API-nycklar","testApiKeys":{"title":"Mollie Betalningar","apiKey":"API-nyckel","isValid":"är giltig","isInvalid":"är ogiltigt"}},"payments":{"format":{"placeholder":"Platshållare","preview":"Förhandsvisning"},"updatePaymentMethods":{"title":"Mollie Betalningar","button":"Uppdatera betalningsmetoder","succeeded":"Betalningsmetoderna har uppdaterats framgångsrikt.","failed":"Betalningsmetoderna kunde inte uppdateras."},"mollieLimits":{"link":"Visa mollie tillgänglighetsregler för betalningsmetoder"}},"rounding":{"info1":"Shopware kan använda valuta-inställningar för att beräkna hur den avrundar en beställnings totala belopp. Detta inkluderar antalet decimaler i din produktprissättning och det närmaste avrundningsintervallet, såsom 0,50 eller 1,00.","info2":"Dessa inställningar kan leda till ett annat totalbelopp än den totala summan av radposter. När Mollie kontrollerar dessa belopp och upptäcker att de inte stämmer, orsakar det ett checkoutfel.","info3":"Du kan använda den här funktionen för att undvika avrundningsproblem i din checkout. När den är aktiverad läggs en separat radpost till i ditt Mollie Dashboard för skillnaden i avrundning, och dina kunder betalar det totala belopp som beräknats av Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det är inte möjligt att använda Klarna Betala nu, Klarna Slice it eller Klarna Betala senare som metod när ditt utgångsdatum är mer än 28 dagar framåt i tiden, om inte en annan maximal tid har överenskommits mellan handlaren och Klarna.","bankTransferDueDateLimitReached":"Det är inte möjligt att ställa in beställningens livslängd högre än 100 dagar."},"support":{"modalTitle":"Begär hjälp från Mollie","btnCancel":"Avbryt","btnConfirm":"Begäran hjälp","btnSupport":"Mer om vårt hjälp","form":{"name":"Ditt namn","email":"Din e-post","recipient":"Skicka begäran till","subject":"Ämne","message":"Meddelande"},"data":{"header":"Data skickat till Mollie:","other":"Övrigt:","shopwareVersion":"Shopware-version","pluginLogs":"{plugin} loggfiler","pluginConfiguration":"{plugin} konfiguration","pluginConfigurationHelpText":"API-nycklar är uteslutna.","paymentMethods":"Betalningsmetoddata","paymentMethodsHelpText":"Innehåller information om vilka betalningsmetoder som är aktiva, tilldelade varje försäljningskanal, samt deras status i ditt Mollie-konto."},"success":"Förfrågan om hjälp har skickats framgångsrikt. Vi gör vårt bästa för att svara så snart som möjligt","error":"Det uppstod ett problem när mailet skickades via Shopware. Vänligen försök igen eller kontakta oss direkt via e-post."}},"rules":{"itemSubscriptionRule":"Objektet är en prenumeration (Mollie)","cartSubscriptionRule":"Varukorg med prenumerationer (Mollie)"},"refunds":{"status":{"queued":"Köad","pending":"Pågående","processing":"Bearbetar","refunded":"Återbetald","failed":"Misslyckad","description":{"queued":"Återbetalningen är köad tills det finns tillräckligt med saldo för att bearbeta återbetalningen. Du kan fortfarande avbryta återbetalningen.","pending":"Återbetalningen kommer att skickas till banken nästa arbetsdag. Du kan fortfarande avbryta återbetalningen.","processing":"Återbetalningen har skickats till banken. Återbetalt belopp kommer att överföras till konsumentens konto så snart som möjligt.","refunded":"Återbetalat belopp har överförts till konsumenten.","failed":"Återbetalningen har misslyckats efter bearbetningen. Till exempel har kunden stängt sitt bankkonto. Medlen kommer att återföras till ditt konto."}}},"refund-manager":{"general":{"unitQuantity":"st."},"acl":{"warningCreate":"Du har inte behörighet att skapa återbetalningar","warningCancel":"Du har inte behörighet att avboka återbetalningar"},"cart":{"title":"Beställning ##orderNumber##","btnSelectAll":"Välj Alla","btnResetForm":"Återställnings Formulär","linkHowTo":"Hur använder jag detta formulär?","grid":{"columns":{"item":"Objekt","productNumber":"Produktnummer","unitPrice":"Enhetspris","quantity":"Antal","refunded":"Återbetald","refundQuantity":"Återbetalning","totalPrice":"Totalt","refundAmount":"Återbetalning","resetStock":"Återställ lager"},"btnResetLine":"Återställ rad","checkDeductPromotion":"Dra av kampanj","checkRefundTax":"Återbetalning av moms"},"roundDiffItemAdded":"Automatiskt avrundningsobjekt har lagts till"},"instructions":{"linkResetTutorials":"Återställ handledningar","btnToggleTutorial":"Visa/Dölj handledning","titleFullRefund":"Full återbetalning","textFullRefund":"Använd bara knappen för full återbetalning. Detta säkerställer att alla dina objekt markeras som återbetalda och hela beloppet återgår till kunden.","titleStockReset":"Lageråterställning","textStockReset":"Du kan automatiskt öka det tillgängliga lagret genom att ange den mängd du vill sätta tillbaka i lager. Ange det innan du går vidare med en fullständig eller delvis återbetalning. Återställning av lagret kan kombineras med den faktiska återbetalningsprocessen på ett flexibelt sätt.","titleShipping":"Frakt","textShipping":"Fraktartiklar kan återbetalas som alla andra produktartiklar. Antingen anger du hela mängden eller ett anpassat delbelopp och går vidare med återbetalningen. Återbetalning av fraktkostnader kan kombineras med den faktiska återbetalningsprocessen för artiklar på ett flexibelt sätt.","titlePartialAmount":"Delvis återbetalning (endast belopp)","textPartialAmount":"Ange bara delbeloppet i textfältet och starta återbetalningen.","titlePartialItems":"Delvis återbetalning (med artiklar)","textPartialItems":"Om du vill markera mängder och artiklar som återbetalda i Mollie, använd formuläret ovan. Ställ in dina mängder och ange ett anpassat belopp för varje produkt som ska återbetalas. Totalsumman kommer sedan att synas i det slutliga återbetalningsbeloppets textfält. Kom ihåg, det är fortfarande möjligt att justera detta slutliga belopp innan du startar din återbetalning.","titlePartialPromotions":"Delvis återbetalning (med kampanjer)","textPartialPromotions":"Om du har en kampanj i din varukorg så är din kampanj en separat artikelrad. Om du vill återbetala alla rabatterade artiklar, gå vidare och återbetala deras totalsummor och hela kampanjartikeln i sig. Men om du bara vill återbetala några få artiklar som är rabatterade kan du dra av den tillämpade rabatten automatiskt för varje enskild artikelrad. Du kan självklart alltid ändra värden om de inte är korrekta.","titleRoundingDiff":"Avrundningsskillnad","textRoundingDiff":"En full återbetalning kommer att inkludera avrundningsskillnader"},"summary":{"dataLoading":"Data laddas...","headerExcludingVat":"Exkl. moms","headerIncludingVat":"Inkl. moms","captionTotal":"Totalt","captionTotalTaxFree":"Totalt","captionPendingRefunds":"Väntar på att återbetalas","captionVouchers":"Värde av voucher","captionRefunded":"Återbetalt belopp","captionRemaining":"Återbetalningsbart belopp","btnFixDiff":"Fixa skillnaden","placeholderDescription":"Ange bank-/korttransaktionsbeskrivning för konsumenten. Max 140 tecken","lblDescription":"Beskrivning (valfritt) ({characters}/140 tecken)","descriptionHelp":"Detta kommer att visas på konsumentens bank- eller kortutdrag när det är möjligt. Meddelandet kommer att avkortas efter 140 tecken.","placeholderInternalDescription":"Ange din interna beskrivning","lblInternalDescription":"Intern beskrivning (valfritt)","internalDescriptionHelp":"Detta kommer att visas som en lokal beskrivning i admingränssnittet.","checkVerification":"Jag har kontrollerat det totala återbetalningsbeloppet och de konfigurerade mängderna för att återbetala och lagra på nytt.","btnRefund":"Återbetalning","btnFullRefund":"Full återbetalning","roundDiffItemAdded":"Avrundningsobjekt"},"refunds":{"title":"Återbetalningar i Mollie Dashboard","linkMore":"Mer om återbetalningar","grid":{"columns":{"amount":"Belopp","status":"Status","description":"Beskrivning","internalDescription":"Intern beskrivning","composition":"Komposition","date":"Datum"},"lblNoComposition":"Ingen tillgänglig komposition","btnCancelRefund":"Avbryt denna återbetalning"}},"notifications":{"success":{"refund-created":"En återbetalning har skapats i Mollie. Det kan ta 2 timmar för återbetalningen att slutföras. Fram till dess kan du avbryta återbetalningen.","refund-canceled":"Den pågående återbetalningen har framgångsrikt avbrutits och tagits bort."},"error":{"low-amount":"Ange ett belopp som ska återbetalas.","refund-created":"Något gick fel när en återbetalning skapades.","refund-canceled":"Det uppstod ett problem när den pågående återbetalningen avbröts. Vänligen försök igen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucherbetalningar","VOUCHER_INFO_DESCRIPTION":"Mollie låter dig enkelt ta emot betalningar i din webbutik med hjälp av Eco-, present- och måltidsvouchers – ett smart val för att öka försäljningen och tillfredsställa dina kunder. Betalningsmetoden \\"voucher\\" är endast synlig om du har minst 1 produkt med en tilldelad vouchertyp i varukorgen.","VOUCHER_INFO_DEFAULTLANGUAGE":"Observera att denna konfiguration endast kan redigeras på ditt standardspråk. Vänligen ändra ditt språk för att modifiera vouchertypen för denna produkt.","VOUCHER_BTN_READMORE":"Läs mer","VOUCHER_TYPE_CAPTION":"Vouchertyp av produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"Ekologisk","VOUCHER_TYPE_VALUE_MEAL":"Måltid","VOUCHER_TYPE_VALUE_VOUCHER":"Present"},"modals":{"shipping":{"title":"Frakta genom Mollie","item":{"label":"Artikel:","noQuantity":"Vänligen ange en kvantitet att frakta.","shipAll":"Frakta allt","summary":{"quantity":"Antal att frakta","shipped":"Mängd skickad","shippable":"Mängd som kan skickas"},"success":"Beställningen har fraktats framgångsrikt."},"order":{"description":"De följande artikelmängderna kommer att skickas.","itemHeader":"Artikel","quantityHeader":"Mängd","originalQuantityHeader":"Kvantitet (leveransbar)"},"availableTracking":{"label":"Tillgängliga spårningskoder","hint":"Klicka på en av dessa spårningskoder för att automatiskt fylla i all data."},"showTracking":"Lägg till spårningsinformation för denna leverans","tracking":{"carrier":"Transportör","code":"Kod","url":"Url","invalid":"Ange både transportör och kod"},"confirmButton":"Frakta beställning","cancelButton":"Avbryt","selectAllButton":"Välj alla","resetButton":"Återställ"},"cancel":{"title":"Avbryt objekt genom mollie","confirmButton":"Avbryt objekt genom mollie","cancelButton":"Stäng modal","resetStock":"Återställ lager","item":{"success":"Produkt avbokad framgångsrikt","failed":{"quantityZero":"Kvantitet är 0","invalidLine":"Produkten finns inte i beställningen","quantityTooHigh":"Kvantiteten är för hög"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Frakta beställning (Mollie)","description":"Frakta order i Mollie."},"modal":{"title":"Frakta beställning","description":"Denna åtgärd kommer automatiskt att frakta en beställning genom Mollie. Användarflödet kommer att ta emot beställningsnumret och vidarebefordra det till Mollie API. Frakt som lyckas och frakt som misslyckas kommer att synas i Mollie-loggfilerna.","warningConfig":"Vänligen se till att stänga av alla ytterligare automatiseringar för denna typ av åtgärd för att undvika störningar.\\nDe följande aktiverade funktionerna i denna plugin kan störa denna åtgärd:","noWarnings":"Inga varningar"}},"refundOrder":{"editor":{"title":"Återbetalning av order (Mollie)","description":"Återbetala order genom Mollie."},"modal":{"title":"Återbetalning av order","description":"Denna åtgärd kommer automatiskt att frakta en beställning genom Mollie. Användarflödet kommer att ta emot beställningsnumret och vidarebefordra det till Mollie API. Frakt som lyckas och frakt som misslyckas kommer att synas i Mollie-loggfilerna.","warning":"Var vänlig observera att återbetalningar kan ta upp till 2 timmar att slutföras och bli synliga i butiken. Fram till dess kan du alltid avbryta en pågående återbetalning antingen från beställningssidan i Shopware eller från Mollie Dashboard.","warningConfig":"Vänligen se till att stänga av alla ytterligare automatiseringar för denna typ av åtgärd för att undvika störningar."}},"warnings":{"automaticShipping":"Automatisk frakt i plugin-konfiguration"}}},"subscriptions":{"status":{"pending":"Pågående","active":"Aktiv","canceled":"Avbruten","suspended":"Avstängd","completed":"Slutförd","paused":"Pausad","resumed":"Återupptagen","skipped":"Hoppade över"},"navigation":{"title":"Mollie Prenumerationer"},"TYPE_DAYS":"Dag(ar)","TYPE_WEEKS":"Vecka(or)","TYPE_MONTHS":"Månad(er)","confirm":{"cancelTitle":"Avsluta prenumerationen?","cancel":"Avbryt din kunds prenumeration.","pauseTitle":"Pausa prenumeration?","pause":"Sätt prenumerationen på paus tills du återupptar den igen.","resumeTitle":"Återuppta prenumeration?","resume":"Fortsätt prenumerationen igen.","skipTitle":"Hoppa över nästa betalning?","skip":"Hoppa över nästa avbetalning i prenumerationen. Den fortsätter automatiskt efteråt."},"alerts":{"cancelSuccess":"Prenumerationen har avbrutits framgångsrikt","pauseSuccess":"Prenumerationen har pausats framgångsrikt","resumeSuccess":"Prenumerationen har återupptagits framgångsrikt","skipSuccess":"Prenumerationen har hoppa överts framgångsrikt. Nästa betalning har uppdaterats."},"list":{"title":"Mollie Prenumerationer","columns":{"customer":"Kund","status":"Status","description":"Beskrivning","amount":"Belopp","nextPaymentAt":"Nästa betalning","prePaymentReminder":"Påmind klockan","canceledAt":"Avbruten klockan","createdAt":"Skapad klockan"},"action":{"edit":"Redigera prenumeration"},"deletedCustomer":"Raderad kund"},"detail":{"title":"Mollie prenumeration","buttonCancelSubscription":"Avbryt prenumeration","labelDescription":"Beskrivning","labelAmount":"Belopp","labelQuantity":"Kvantitet","labelMollieSubscription":"Mollie Prenumeration","labelMollieCustomer":"Mollie kund","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware kund","labelCreatedAt":"Skapad klockan","buttonShowShopwareOrder":"Visa Shopware beställning","buttonShowShopwareCustomer":"Visa Shopware kund","cardTitleSubscription":"Prenumeration","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Nästa betalning klockan","labelLastRemindedAt":"Senaste påminnelse klockan","labelCanceledAt":"Avbruten klockan","buttonPauseSubscription":"Pausa prenumeration","buttonResumeSubscription":"Återuppta prenumeration","buttonSkipSubscription":"Hoppa över prenumeration","history":{"cardTitle":"Historik","colDate":"Datum","colComment":"Kommentar","colStatusFrom":"Status (från)","colStatusTo":"Status (till)","colMollieSubscription":"Mollie prenumeration"}},"product":{"card-title":"Prenumeration","title":"Mollie Prenumerationer","description":"Att hantera dina återkommande betalningar är enklare än någonsin med våra hjälpsamma funktioner. Ta din verksamhet till nästa nivå med effektiva spårningsalternativ, enkla integrationer och mer. Med Mollie-prenumerationer kan du enkelt skapa prenumerationsprodukter och schemalägga återkommande betalningar att äga rum vid det konfigurerade intervallet och perioden.","mollieSubscriptionProduct":"Prenumerationsprodukt","mollieSubscriptionIntervalAmount":"Upprepa betalning varje","mollieSubscriptionIntervalType":"Intervall enhet","mollieSubscriptionRepetitionAmount":"Antal upprepningar","mollieSubscriptionRepetitionPlaceholder":"Ange nummer eller lämna tomt","infoDefaultLanguage":"Vänligen observera att denna konfiguration endast kan redigeras på ditt standardspråk. Vänligen ändra ditt språk för att ändra prenumerationsinställningarna för denna produkt.","btnReadMore":"Läs mer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Prenumeration"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kreditkort data",buttonMolliePaymentLink:"Kopiera till urklipp",columnRefunded:"Återbetald",columnShipped:"Fraktad",columnCanceled:"Avbruten",labelMollieOrderId:"Mollie Beställnings-ID",labelMollieThirdPartyPaymentId:"Betalningsreferens",labelMolliePaymentLink:"Mollie Checkout-URL",totalRefunds:"Återbetalt belopp",totalRefundsPending:"Väntar på att bli återbetald",totalRemaining:"Belopp för återbetalning",totalVouchers:"Värde av voucher",totalShipments:"Fraktbelopp ({quantity} artiklar)",subscriptionBadge:"Prenumerationsbeställning",refundManager:{title:"Mollie Återbetalningshanterare",btnOpenRefundManager:"Öppna återbetalningshanterare",btnCloseRefundManager:"Stäng återbetalningshanterare"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Önskad iDeal-utgivare"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Återbetalningshanterare"},mollie_subscription:{label:"Prenumerationer"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Beskrivning"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Återbetalning",subscription:"Prenumeration",webhookReceived:"Webhooks",status:"Status",started:"Startad",ended:"Avslutad",paused:"Pausad",renewalReminder:"Påminnelse om förnyelse",renewed:"Förnyad",resumed:"Återupptagen",skipped:"Hoppade över",all:"Alla",canceled:"Avbruten",expired:"Utgått",partiallyRefunded:"Återbetald (delvis)",orderSuccess:"Beställning lyckad",orderFailed:"Beställning misslyckades",orderCanceled:"Beställning avbruten"}}},nq={entities:{mollie_subscription:"Mollie-abonnement | Mollie-abonnementer"},businessEvents:{mollie_checkout_order_success:"Bestilling vellykket",mollie_checkout_order_failed:"Bestilling mislyktes",mollie_checkout_order_canceled:"Bestilling kansellert",mollie_webhook_received_All:"Mollie Webhook Mottatt (Alle)",mollie_webhook_received_status_authorized:"Mollie Webhook Mottatt (Autorisert)",mollie_webhook_received_status_failed:"Mollie Webhook Mottatt (Mislyktes)",mollie_webhook_received_status_canceled:"Mollie Webhook Mottatt (Kansellert)",mollie_webhook_received_status_expired:"Mollie Webhook Mottatt (Utløpt)",mollie_webhook_received_status_pending:"Mollie Webhook Mottatt (Ventende)",mollie_webhook_received_status_paid:"Mollie Webhook Mottatt (Betalt)",mollie_webhook_received_status_completed:"Mollie Webhook Mottatt (Fullført)",mollie_webhook_received_status_refunded:"Mollie Webhook Mottatt (Refundert)",mollie_webhook_received_status_partially_refunded:"Mollie Webhook Mottatt (Delvis refundert)",mollie_refund_started:"Mollie refusjon startet",mollie_subscription_started:"Mollie abonnement startet",mollie_subscription_ended:"Mollie abonnement fullført",mollie_subscription_cancelled:"Mollie abonnement kansellert",mollie_subscription_paused:"Mollie abonnement satt på pause",mollie_subscription_resumed:"Mollie abonnement gjenopptatt",mollie_subscription_skipped:"Mollie abonnement hoppet over",mollie_subscription_renewed:"Mollie abonnement fornyet",mollie_subscription_renewal_reminder:"Mollie påminnelse om fornyelse av abonnement"}},oq={global:nq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Søk abonnementer...","general":{"mainMenuItemGeneral":"Mollie Betalinger","descriptionTextModule":"Mollie Betalinger","btnMollieActions":"Mollie Handlinger","refundThroughMollie":"Refusjon gjennom Mollie","shipThroughMollie":"Frakt gjennom Mollie","cancelMollieItem":"Kanseller gjennom Mollie"},"config":{"info":{"title":"Hei {userName}, Velkommen til Mollie!","descriptionTop":"Onboarding er enkelt med Mollie!","descriptionBottom":"Det er det!","descriptionFooter":"Hvis du ønsker å lære mer om vår plugin, vennligst besøk vår offisielle dokumentasjonside.","onboardingStep1":"Registrer deg for en Mollie konto.","onboardingStep2":"Oppgi API-nøklene dine i seksjonen nedenfor.","onboardingStep2TestMode":"Aktiver 'Testmodus' hvis du kun ønsker å teste betalinger.","onboardingStep3":"Tildel betalingsmetoder til salgs kanalen din.","onboardingStep3Link":"til dine salgskanaler","btnDocumentation":"Dokumentasjon","btnRequestSupport":"Support","btnTroubleshooting":"Feilsøkingsguide"},"api":{"apiLinkButton":"Hent API-nøklene dine fra Mollie Dashboard","testButton":"Test API nøkler","testApiKeys":{"title":"Mollie Betalinger","apiKey":"API-nøkkel","isValid":"er gyldig","isInvalid":"er ugyldig"}},"payments":{"format":{"placeholder":"Plassholder","preview":"Forhåndsvisning"},"updatePaymentMethods":{"title":"Mollie Betalinger","button":"Oppdater betalingsmetoder","succeeded":"Betalingsmetodene er oppdatert.","failed":"Betalingsmetodene kunne ikke oppdateres."},"mollieLimits":{"link":"Vis mollie tilgjengelighetsregler for betalingsmetoder"}},"rounding":{"info1":"Shopware kan bruke valutainnstillinger for å beregne hvordan den avrunder totalbeløpet for en bestilling. Dette inkluderer antall desimaler i produktprisene dine og nærmeste avrundingsintervall, som for eksempel 0,50 eller 1,00.","info2":"Disse innstillingene kan føre til et annet totalbeløp enn totalsummen av linjeelementene. Når Mollie kryssjekker disse beløpene og finner ut at de ikke stemmer overens, forårsaker det en feil ved utsjekking.","info3":"Du kan bruke denne funksjonen for å unngå avrundingsproblemer ved utsjekking. Når den er aktivert, legger den til et eget linjeelement i ditt Mollie Dashboard for forskjellen i avrunding, og kundene dine betaler totalbeløpet beregnet av Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det er ikke mulig å bruke Klarna Betal nå, Klarna Delbetaling eller Klarna Betal senere som metode når utløpsdatoen er mer enn 28 dager frem i tid, med mindre en annen maksimumsperiode er avtalt mellom selgern og Klarna.","bankTransferDueDateLimitReached":"Det er ikke mulig å sette bestillingens levetid høyere enn 100 dager."},"support":{"modalTitle":"Be om support fra Mollie","btnCancel":"Avbryt","btnConfirm":"Be om støtte","btnSupport":"Mer om vår støtte","form":{"name":"Ditt navn","email":"Din e-post","recipient":"Send forespørsel til","subject":"Emne","message":"Melding"},"data":{"header":"Data sendt til Mollie:","other":"Annet:","shopwareVersion":"Shopware-versjon","pluginLogs":"{plugin} loggfiler","pluginConfiguration":"{plugin} konfigurasjon","pluginConfigurationHelpText":"API-nøkler er ekskludert.","paymentMethods":"Betalingsmetode-data","paymentMethodsHelpText":"Inneholder informasjon om hvilke betalingsmetoder som er aktive, tildelt hver salgskanal, samt deres status i Mollie-kontoen din."},"success":"Støtteforespøselen har blitt sendt. Vi gjør vårt beste for å svare så snart som mulig","error":"Det oppstod et problem da e-posten ble sendt gjennom Shopware. Vennligst prøv igjen eller kontakt oss direkte via e-post."}},"rules":{"itemSubscriptionRule":"Vare er abonnement (Mollie)","cartSubscriptionRule":"Handlekurv med abonnementer (Mollie)"},"refunds":{"status":{"queued":"Køet","pending":"Ventende","processing":"Behandles","refunded":"Refundert","failed":"Mislyktes","description":{"queued":"Refusjonen er satt i kø til det er tilstrekkelig saldo for å behandle refusjonen. Du kan fortsatt kansellere refusjonen.","pending":"Refusjonen vil bli sendt til banken neste virkedag. Du kan fortsatt kansellere refusjonen.","processing":"Refusjonen har blitt sendt til banken. Refundert beløp vil bli overført til forbrukerkontoen så snart som mulig.","refunded":"Refundert beløp har blitt overført til forbrukeren.","failed":"Refusjonen har mislyktes etter behandling. For eksempel, kunden har stengt sin bankkonto. Midlene vil bli overført til kontoen din."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Du har ikke tillatelse til å opprette refusjoner","warningCancel":"Du har ikke tillatelse til å kansellere refusjoner"},"cart":{"title":"Bestilling ##orderNumber##","btnSelectAll":"Velg alle","btnResetForm":"Nullstill skjema","linkHowTo":"Hvordan bruke dette skjemaet?","grid":{"columns":{"item":"Vare","productNumber":"Produktnummer","unitPrice":"Enhetspris","quantity":"Antall","refunded":"Refundert","refundQuantity":"Refusjon","totalPrice":"Totalt","refundAmount":"Refusjon","resetStock":"Nullstill lager"},"btnResetLine":"Nullstill linje","checkDeductPromotion":"Trekk fra rabatt","checkRefundTax":"Refusjon av MVA"},"roundDiffItemAdded":"Automatisk avrunding av vare ble lagt til"},"instructions":{"linkResetTutorials":"Nullstill veiledninger","btnToggleTutorial":"Vis/Skjul veiledning","titleFullRefund":"Full refusjon","textFullRefund":"Bare bruk knappen for full refusjon. Dette sikrer at alle varene blir merket som refusert og at hele beløpet blir betakebetalt til kunden.","titleStockReset":"Lager nullstilling","textStockReset":"Du kan automatisk øke tilgjengelig lager ved å skrive inn antallet du ønsker å sette tilbake på lager. Bare skriv det inn før du fortsetter med en full eller delvis refusjon. Nullstilling av lageret kan kombineres med selve refusjonsprosessen på en fleksibel måte.","titleShipping":"Frakt","textShipping":"Fraktvarer kan refunderes som andre produktvarer. Enten angi hele antallet eller et tilpasset delbeløp, og fortsett med refusjonen. Refusjon av fraktkostnader kan kombineres med selve refusjonsprosessen for varer på en fleksibel måte.","titlePartialAmount":"Delvis refusjon (kun beløp)","textPartialAmount":"Bare angi delbeløpet i tekstfeltet og start refusjonen.","titlePartialItems":"Delvis refusjon (med varer)","textPartialItems":"Hvis du vil merke antall og varer som refundert i Mollie, bruk skjemaet ovenfor. Sett antallet og angi et tilpasset beløp for hver vare som skal refunderes. Den totale summen vil deretter vises i textfeltet for det endelige refusjonsbeløpet. Husk at det fortsatt er mulig å justere dette sluttbeløpet før du starter refusjonen.","titlePartialPromotions":"Delvis refusjon (med rabatter)","textPartialPromotions":"Hvis du har en rabatt i handlekurven, så er rabatten en egen linjevare. Hvis du ønsker å refundere alle rabatterte varer, kan du refundere deres totale verdi og hele rabattlinjen. Hvis du derimot kun ønsker å refundere noen få rabatterte varer, kan du automatisk trekke fra den brukte rabatten for hver enkelt linjevare. Du kan selvfølgelig alltid endre verdier hvis de ikke er korrekte.","titleRoundingDiff":"Avrundingsforskjell","textRoundingDiff":"En full refusjon vil inkludere avrundingsforskjeller"},"summary":{"dataLoading":"Data lastes...","headerExcludingVat":"Ekskl. MVA","headerIncludingVat":"Inkl. MVA","captionTotal":"Totalt","captionTotalTaxFree":"Totalt","captionPendingRefunds":"Venter på å bli refundert","captionVouchers":"Kupongbeløp","captionRefunded":"Refundert beløp","captionRemaining":"Refunderbart beløp","btnFixDiff":"Juster forskjell","placeholderDescription":"Angi beskrivelse for bank-/kortutskrift for forbrukeren. Maks 140 tegn","lblDescription":"Beskrivelse (valgfritt) ({characters}/140 tegn)","descriptionHelp":"Dette vil vises på forbrukerens bank- eller kortutskrift når det er mulig. Meldingen vil bli avkortet etter 140 tegn.","placeholderInternalDescription":"Angi din interne beskrivelse","lblInternalDescription":"Intern beskrivelse (valgfritt)","internalDescriptionHelp":"Dette vil bli vist som en lokal beskrivelse i administrasjonsgrensesnittet.","checkVerification":"Jeg har bekreftet det totale refusjonsbeløpet og de konfigurerte antallene som skal refunderes og tillbake på lager.","btnRefund":"Refusjon","btnFullRefund":"Full refusjon","roundDiffItemAdded":"Avrundingspost"},"refunds":{"title":"Refusjoner i Mollie Dashboard","linkMore":"Mer om refusjoner","grid":{"columns":{"amount":"Beløp","status":"Status","description":"Beskrivelse","internalDescription":"Intern beskrivelse","composition":"Sammensetning","date":"Dato"},"lblNoComposition":"Ingen sammensetning tilgjengelig","btnCancelRefund":"Kanseller denne refusjonen"}},"notifications":{"success":{"refund-created":"En refusjon har blitt opprettet i Mollie. Det kan ta opptil 2 timer før refusjonen er fullført. Inntil da kan du kansellere refusjonen.","refund-canceled":"Den ventende refusjonen er kansellert og fjernet."},"error":{"low-amount":"Vennligst oppgi et beløp som skal refunderes.","refund-created":"Noe gikk galt ved oppretting av refusjonen.","refund-canceled":"Det oppstod et problem ved kansellering av den ventende refusjonen. Vennligst prøv igjen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Kupong","VOUCHER_INFO_TITLE":"Kupongbetalinger","VOUCHER_INFO_DESCRIPTION":"Mollie lar deg enkelt akseptere betalinger i nettbutikken ved bruk av øko-, gave- og måltidskuponger—et smart valg for å øke salg og gjøre kundene fornøyde. Betalingsmetoden \\"kupong\\" er kun synlig hvis du har minst 1 produkt med en tildelt kupongtype i handlekurven.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vennligst vær oppmerksom på at denne konfigurasjonen kun kan redigeres på ditt standardspråk. Vennligst endre språket ditt for å endre kupongtypen for dette produktet.","VOUCHER_BTN_READMORE":"Les mer","VOUCHER_TYPE_CAPTION":"Kupongtype for produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"Øko","VOUCHER_TYPE_VALUE_MEAL":"Måltid","VOUCHER_TYPE_VALUE_VOUCHER":"Gave"},"modals":{"shipping":{"title":"Frakt gjennom Mollie","item":{"label":"Vare:","noQuantity":"Vennligst oppgi et antall som skal sendes.","shipAll":"Send alt","summary":{"quantity":"Antall som skal sendes","shipped":"Antall sendt","shippable":"Antall som kan sendes"},"success":"Bestillingen har blitt sendt."},"order":{"description":"Følgende vareantall vil bli sendt.","itemHeader":"Vare","quantityHeader":"Antall","originalQuantityHeader":"Antall (kan sendes)"},"availableTracking":{"label":"Tilgjengelige sporingskoder","hint":"Klikk på en av disse sporingskodene for å fylle inn all data automatisk."},"showTracking":"Legg til sporingsinformasjon for denne forsendelsen","tracking":{"carrier":"Leverandør","code":"Kode","url":"Url","invalid":"Vennligst oppgi både leverandør og kode"},"confirmButton":"Send bestilling","cancelButton":"Kanseller","selectAllButton":"Velg alt","resetButton":"Nullstill"},"cancel":{"title":"Kanseller vare gjennom mollie","confirmButton":"Kanseller vare gjennom mollie","cancelButton":"Lukk modal","resetStock":"Nullstill lager","item":{"success":"Produktet ble kansellert","failed":{"quantityZero":"Antallet er 0","invalidLine":"Produktet eksisterer ikke i bestillingen","quantityTooHigh":"Antallet er for høyt"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Send bestilling (Mollie)","description":"Send bestilling i Mollie."},"modal":{"title":"Send bestilling","description":"Denne handlingen vil automatisk sende en bestilling gjennom Mollie. Flytsekvensen vil motta bestillingsnummeret og sende det videre til Mollie API. Vellykkede forsendelser og mislykkede forsendelser vil være synlige i Mollie-loggfilene.","warningConfig":"Vennligst deaktiver all ekstra automatisering for denne typen handling for å unngå forstyrrelser.\\nDe følgende aktiverte funksjonene i dette plugin kan forstyrre handlingen:","noWarnings":"Ingen varsler"}},"refundOrder":{"editor":{"title":"Refusjon av bestilling (Mollie)","description":"Refunder bestilling gjennom Mollie."},"modal":{"title":"Refusjon av bestilling","description":"Denne handlingen vil automatisk starte en refusjon gjennom Mollie. Flytsekvensen vil motta bestillingsnummeret og sende dette videre til Mollie API. Vellykkede refusjoner og mislykkede refusjoner vil være synlige i Mollie-loggfilene.","warning":"Vennligst husk at refusjoner kan ta opptil 2 timer før de er fullført og synlig i butikken. Inntil da kan du alltid kansellere en ventende refusjon, enten fra bestillingssiden i Shopware eller fra Mollie Dashboard.","warningConfig":"Vennligst sørg for å deaktivere all automatikk for denne typen handling for å unngå forstyrrelser."}},"warnings":{"automaticShipping":"Automatisk frakt i plugin-konfigurasjonen"}}},"subscriptions":{"status":{"pending":"Ventende","active":"Aktiv","canceled":"Kansellert","suspended":"Suspendert","completed":"Fullført","paused":"Pauset","resumed":"Gjenopptatt","skipped":"Hoppet over"},"navigation":{"title":"Mollie Abonnementer"},"TYPE_DAYS":"Dag(er)","TYPE_WEEKS":"Uke(r)","TYPE_MONTHS":"Måned(er)","confirm":{"cancelTitle":"Avslutt abonnement?","cancel":"Kanseller kundens abonnementet.","pauseTitle":"Pause abonnement?","pause":"Sett abonnementet på pause til du gjenopptar det igjen.","resumeTitle":"Gjenoppta abonnement?","resume":"Fortsett abonnementet igjen.","skipTitle":"Hopp over neste avbetaling?","skip":"Hopp over neste avbetaling i abonnementet. Det fortsetter automatisk etterpå."},"alerts":{"cancelSuccess":"Abonnementet har blitt kansellert","pauseSuccess":"Abonnementet har blitt pauset","resumeSuccess":"Abonnementet har blitt gjenopptatt","skipSuccess":"Abonnementet har blitt hoppet over. Neste betaling er oppdatert."},"list":{"title":"Mollie Abonnementer","columns":{"customer":"Kunde","status":"Status","description":"Beskrivelse","amount":"Beløp","nextPaymentAt":"Neste betaling","prePaymentReminder":"Påminnet ved","canceledAt":"Kansellert ved","createdAt":"Opprettet ved"},"action":{"edit":"Rediger abonnement"},"deletedCustomer":"Slettet kunde"},"detail":{"title":"Mollie-abonnement","buttonCancelSubscription":"Kanseller abonnement","labelDescription":"Beskrivelse","labelAmount":"Beløp","labelQuantity":"Antall","labelMollieSubscription":"Mollie-abonnement","labelMollieCustomer":"Mollie-kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware-kunde","labelCreatedAt":"Opprettet ved","buttonShowShopwareOrder":"Vis Shopware-bestilling","buttonShowShopwareCustomer":"Vis Shopware-kunde","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Neste betaling den","labelLastRemindedAt":"Sist påminnet den","labelCanceledAt":"Kansellert den","buttonPauseSubscription":"Sett abonnement på pause","buttonResumeSubscription":"Gjenoppta abonnement","buttonSkipSubscription":"Hopp over abonnement","history":{"cardTitle":"Historikk","colDate":"Dato","colComment":"Kommentar","colStatusFrom":"Status (fra)","colStatusTo":"Status (til)","colMollieSubscription":"Mollie-abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie-abonnementer","description":"Håndtering av gjentakende betalinger er enklere enn noen gang med våre praktiske funksjoner. Ta bedriften din til neste nivå med effektive sporingsalternativer, enkle integrasjoner og mer. Med Mollie-abonnementer kan du enkelt opprette abonnementsprodukter og planlegge gjentakende betalinger som skjer på det konfigurerte intervallet og perioden.","mollieSubscriptionProduct":"Abonnementsprodukt","mollieSubscriptionIntervalAmount":"Gjenta betaling hver","mollieSubscriptionIntervalType":"Intervalenhet","mollieSubscriptionRepetitionAmount":"Antall repetisjoner","mollieSubscriptionRepetitionPlaceholder":"Oppgi antall eller la det stå tomt","infoDefaultLanguage":"Vennligst vær oppmerksom på at denne konfigurasjonen kun kan redigeres på ditt standardspråk. Vennligst endre språket ditt for å endre abonnementsinnstillingene for dette produktet.","btnReadMore":"Les mer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kredittkortdata",buttonMolliePaymentLink:"Kopier til utklippstavlen",columnRefunded:"Refundert",columnShipped:"Fraktet",columnCanceled:"Kansellert",labelMollieOrderId:"Mollie Bestillings-ID",labelMollieThirdPartyPaymentId:"Betalingsreferanse",labelMolliePaymentLink:"Mollie Checkout-URL",totalRefunds:"Refundert beløp",totalRefundsPending:"Venter på å bli refundert",totalRemaining:"Refunderbart beløp",totalVouchers:"Kupongbeløp",totalShipments:"Fraktet beløp ({quantity} varer)",subscriptionBadge:"Abonnementsbestilling",refundManager:{title:"Mollie Refusjonsansvarlig",btnOpenRefundManager:"Åpne refusjonsansvarlig",btnCloseRefundManager:"Lukk refusjonsansvarlig"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Foretrukket iDeal-leverandør"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refusjonsansvarlig"},mollie_subscription:{label:"Abonnementer"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Beskrivelse"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Refusjon",subscription:"Abonnement",webhookReceived:"Webhooks",status:"Status",started:"Startet",ended:"Avsluttet",paused:"Pauset",renewalReminder:"Påminnelse om fornyelse",renewed:"Fornyet",resumed:"Gjenopptatt",skipped:"Hoppet over",all:"Alle",canceled:"Kansellert",expired:"Utløpt",partiallyRefunded:"Refundert (delvis)",orderSuccess:"Bestilling vellykket",orderFailed:"Bestilling mislyktes",orderCanceled:"Bestilling kansellert"}}},sq={entities:{mollie_subscription:"Mollie Subscription | Mollie Subscriptions"},businessEvents:{mollie_checkout_order_success:" Zamówienie zrealizowane",mollie_checkout_order_failed:" Zamówienie nieudane",mollie_checkout_order_canceled:" Zamówienie anulowane",mollie_webhook_received_All:" Otrzymano webhooki Mollie (wszystkie)",mollie_webhook_received_status_authorized:" Otrzymano webhook Mollie (Autoryzowany)",mollie_webhook_received_status_failed:" Otrzymano webhook Mollie (Nieudany)",mollie_webhook_received_status_canceled:" Otrzymano webhook Mollie (Anulowany)",mollie_webhook_received_status_expired:" Otrzymano webhook Mollie (Wygasły)",mollie_webhook_received_status_pending:" Otrzymano webhook Mollie (Oczekiwanie na płatność)",mollie_webhook_received_status_paid:" Otrzymano webhook Mollie (Płatność zrealizowana)",mollie_webhook_received_status_completed:" Otrzymano webhook Mollie (Zakończony)",mollie_webhook_received_status_refunded:" Otrzymano webhook Mollie (Zwrócony)",mollie_webhook_received_status_partially_refunded:" Otrzymano webhook Mollie (Częściowo zwrócony)",mollie_refund_started:" Rozpoczęto zwrot Mollie",mollie_subscription_started:" Rozpoczęto subskrypcję Mollie",mollie_subscription_ended:" Ukończono subskrypcję Mollie",mollie_subscription_cancelled:" Anulowano subskrypcję Mollie",mollie_subscription_paused:" Wstrzymano subskrypcję Mollie",mollie_subscription_resumed:" Wznowiono subskrypcję Mollie",mollie_subscription_skipped:" Pominięto subskrypcję Mollie",mollie_subscription_renewed:" Odnowiono subskrypcję Mollie",mollie_subscription_renewal_reminder:" Przypomnienie Mollie o odnowieniu subskrypcji"}},lq={global:sq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Moduł Mollie","searchPlaceholder":"Szukaj subskrypcji...","general":{"mainMenuItemGeneral":"Płatności Mollie","descriptionTextModule":"Płatności Mollie","btnMollieActions":"Mollie Actions","refundThroughMollie":"Zwróć poprzez Mollie","shipThroughMollie":"Wyślij poprzez Mollie","cancelMollieItem":"Anuluj poprzez Mollie"},"config":{"info":{"title":"Cześć {userName}, Witaj w Mollie!","descriptionTop":"Onboarding jest łatwy z Mollie!","descriptionBottom":"To wszystko!","descriptionFooter":"Jeśli chcesz dowiedzieć się więcej o naszej wtyczce, odwiedź naszą oficjalną stronę z dokumentacją.","onboardingStep1":"Zarejestruj się w Mollie.","onboardingStep2":"Wprowadź swoje klucze API w sekcji poniżej.","onboardingStep2TestMode":"Włącz 'Tryb testowy', jeśli chcesz tylko testować płatności.","onboardingStep3":"Przypisz metody płatności do Twojego kanału sprzedaży.","onboardingStep3Link":"do Twoich kanałów sprzedaży","btnDocumentation":"Dokumentacja","btnRequestSupport":"Wsparcie","btnTroubleshooting":"Przewodnik rozwiązywania problemów"},"api":{"apiLinkButton":"Pozyskaj swoje klucze API z zakładki Mollie Dashboard","testButton":"Testowe Klucze API","testApiKeys":{"title":"Płatności Mollie","apiKey":"Klucz API","isValid":"jest ważny","isInvalid":"jest nieważny"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Podgląd"},"updatePaymentMethods":{"title":"Płatności Mollie","button":"Aktualizuj metody płatności","succeeded":"Metody płatności zostały pomyślnie zaktualizowane.","failed":"Nie udało się zaktualizować metod płatności."},"mollieLimits":{"link":"Pokaż zasady dostępności Mollie dla metod płatności"}},"rounding":{"info1":"Shopware może korzystać z ustawień waluty, aby obliczyć zaokrąglenie całkowitej kwoty zamówienia. Obejmuje to liczbę miejsc po przecinku w cenach produktów oraz najbliższy interwał zaokrąglenia, na przykład 0,50 lub 1,00.","info2":"Te ustawienia mogą prowadzić do sytuacji, w której całkowita kwota zamówienia różni się od sumy pozycji na fakturze. Mogą występować błędy podczas realizacji płatności z powodu niezgodności kwot wykrytej podczas kontroli Mollie.","info3":"Możesz użyć tej funkcji, aby uniknąć problemów z zaokrąglaniem w procesie realizacji zamówienia. Po jej włączeniu, w Twoim panelu Mollie pojawi się oddzielna pozycja dla różnicy wynikającej z zaokrąglenia, a klienci zapłacą całkowitą kwotę obliczoną przez Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nie jest możliwe użycie Klarna: Zapłać za 30 dni jako metody płatności, gdy data ważności zamówienia jest dłuższa niż 28 dni, chyba, że inny maksymalny okres zostanie uzgodniony między sprzedawcą a Klarna.","bankTransferDueDateLimitReached":"Nie można ustawić okresu aktywności zamówienia na więcej niż 100 dni."},"support":{"modalTitle":"Poproś o pomoc od Mollie","btnCancel":"Anuluj","btnConfirm":"Poproś o pomoc","btnSupport":"Więcej o naszym centrum pomocy","form":{"name":"Imię","email":"Twój e-mail","recipient":"Wyślij wniosek do","subject":"Temat","message":"Wiadomość"},"data":{"header":"Dane wysłane do Mollie:","other":"Inne:","shopwareVersion":"Wersja Shopware","pluginLogs":"{plugin} pliki logu","pluginConfiguration":"{plugin} konfiguracja","pluginConfigurationHelpText":"Klucze API nie są uwzględnione.","paymentMethods":"Dane metody płatności","paymentMethodsHelpText":"Zawiera informacje o tym, które metody płatności są aktywne, przypisane do poszczególnych kanałów sprzedaży, a także o ich statusie na Twoim koncie Mollie."},"success":"Prośba o pomoc została pomyślnie wysłana. Dokładamy wszelkich starań, aby odpowiedzieć tak szybko, jak to możliwe","error":"Wystąpił problem przy wysyłaniu maila przez Shopware. Proszę spróbować ponownie lub skontaktować się z nami bezpośrednio przez e-mail."}},"rules":{"itemSubscriptionRule":"Przedmiot to subskrypcja (Mollie)","cartSubscriptionRule":"Koszyk z subskrypcjami (Mollie)"},"refunds":{"status":{"queued":"W kolejce","pending":"Oczekujące","processing":"Przetwarzanie","refunded":"Zwrócony","failed":"Nieudany","description":{"queued":"Zwrot jest oczekujący do czasu, gdy saldo będzie wystarczające na jego realizację. Wciąż możliwe jest anulowanie zwrotu.","pending":"Zwrot zostanie wysłany do banku w następny dzień roboczy. Wciąż możliwe jest anulowanie zwrotu.","processing":"Zwrot został wysłany do banku. Kwota zwrotu zostanie przelana na konto konsumenta tak szybko, jak to możliwe.","refunded":"Kwota zwrotu została przelana na konto konsumenta.","failed":"Nie udało się przetworzyć zwrotu. Powodem może być zamknięcie konta bankowego przez klienta. Środki zostaną zwrócone na Twoje konto."}}},"refund-manager":{"general":{"unitQuantity":"szt."},"acl":{"warningCreate":"Nie masz uprawnień do tworzenia zwrotów","warningCancel":"Nie masz uprawnień do anulowania zwrotów"},"cart":{"title":"Zamówienie ##orderNumber##","btnSelectAll":"Zaznacz wszystko","btnResetForm":"Zresetuj formularz","linkHowTo":"Jak korzystać z tego formularza?","grid":{"columns":{"item":"Pozycja","productNumber":"Numer produktu","unitPrice":"Cena jednostkowa","quantity":"Ilość","refunded":"Zwrócony","refundQuantity":"Zwrot","totalPrice":"Łącznie","refundAmount":"Zwrot","resetStock":"Zresetuj stan magazynowy"},"btnResetLine":"Zresetuj linię","checkDeductPromotion":"Odlicz promocję","checkRefundTax":"Zwróć VAT"},"roundDiffItemAdded":"Dodano automatyczny element zaokrąglający"},"instructions":{"linkResetTutorials":"Zresetuj samouczki","btnToggleTutorial":"Pokaż/Ukryj samouczek","titleFullRefund":"Pełny zwrot","textFullRefund":"Po prostu użyj przycisku do pełnego zwrotu. Dzięki temu wszystkie przedmioty zostaną oznaczone jako zwrócone, a pełna kwota zostanie zwrócona klientowi.","titleStockReset":"Reset stanu magazynowego","textStockReset":"Możesz automatycznie zwiększyć dostępny stan magazynowy, wpisując ilość, którą chcesz z powrotem umieścić w magazynie. Wprowadź ją przed przystąpieniem do pełnego lub częściowego zwrotu. Reset stanu magazynowego można elastycznie łączyć z procesem zwrotu.","titleShipping":"Wysyłka","textShipping":"Koszty wysyłki mogą zostać zwrócone jak każdy inny produkt. Wprowadź pełną lub częściową kwotę i przejdź do zwrotu. Zwrot kosztów wysyłki można elastycznie łączyć z procesem zwrotu produktów.","titlePartialAmount":"Zwrot częściowy (tylko kwota)","textPartialAmount":"Po prostu wprowadź kwotę częściową w polu tekstowym i rozpocznij zwrot.","titlePartialItems":"Zwrot częściowy (z produktami)","textPartialItems":"Jeśli chcesz oznaczyć ilości i produkty jako zwrócone w Mollie, skorzystaj z powyższego formularza. Ustaw odpowiednią liczbę i podaj niestandardową kwotę dla każdego przedmiotu, który ma zostać zwrócony. Całkowita kwota zostanie wyświetlona w polu tekstowym z końcową kwotą zwrotu. Pamiętaj, że nadal możesz dostosować tę kwotę przed rozpoczęciem zwrotu.","titlePartialPromotions":"Zwrot częściowy (z promocjami)","textPartialPromotions":"Jeśli masz promocję w swoim koszyku, będzie ona oddzielnym elementem w zamówieniu. Jeśli chcesz zwrócić wszystkie przedmioty objęte rabatem, wykonaj zwrot pełnej wartości tych przedmiotów oraz pełnej kwoty rabatu. Jeśli chcesz zwrócić tylko niektóre przedmioty objęte rabatem, możesz automatycznie odjąć zastosowany rabat od każdej pozycji. Zawsze możesz dostosować te wartości, jeśli będą one nieprawidłowe.","titleRoundingDiff":"Różnica zaokrąglenia","textRoundingDiff":"Całkowity zwrot będzie zawierał różnicę zaokrąglenia"},"summary":{"dataLoading":"Dane są ładowane...","headerExcludingVat":"Netto","headerIncludingVat":"Brutto","captionTotal":"Łącznie","captionTotalTaxFree":"Łącznie","captionPendingRefunds":"Oczekuje na zwrot","captionVouchers":"Kwota vouchera","captionRefunded":"Zwrócona kwota","captionRemaining":"Kwota do zwrotu","btnFixDiff":"Napraw różnicę","placeholderDescription":"Wprowadź opis transakcji bankowej dla konsumenta. Maks. 140 znaków","lblDescription":"Opis (opcjonalnie) ({characters}/140 znaków)","descriptionHelp":"Ta informacja będzie wyświetlona na wyciągu bankowym lub wyciągu z karty konsumenta, jeśli będzie to możliwe. Wiadomość zostanie obcięta po 140 znakach.","placeholderInternalDescription":"Wprowadź opis","lblInternalDescription":"Opis wewnętrzny (opcjonalnie)","internalDescriptionHelp":"Ten tekst zostanie wyświetlony jako lokalny opis w interfejsie administracyjnym.","checkVerification":"Zweryfikowałem całkowitą kwotę zwrotu oraz ilości do zwrotu i ponownego umieszczenia w magazynie.","btnRefund":"Zwrot","btnFullRefund":"Całkowity zwrot","roundDiffItemAdded":"Element zaokrąglający"},"refunds":{"title":"Zwroty w zakładce Mollie Dashboard","linkMore":"Więcej o zwrotach","grid":{"columns":{"amount":"Kwota","status":"Status","description":"Opis","internalDescription":"Opis wewnętrzny","composition":"Kompozycja","date":"Data"},"lblNoComposition":"Brak dostępnej kompozycji","btnCancelRefund":"Anuluj ten zwrot"}},"notifications":{"success":{"refund-created":"Zwrot został utworzony w Mollie. Sfinalizowanie zwrotu może zająć do 2 godzin. Do tego czasu możesz anulować zwrot.","refund-canceled":"Oczekujący zwrot został pomyślnie anulowany i usunięty."},"error":{"low-amount":"Proszę wprowadzić kwotę do zwrotu.","refund-created":"Coś poszło nie tak podczas tworzenia zwrotu.","refund-canceled":"Wystąpił problem podczas anulowania oczekującego zwrotu. Proszę spróbować ponownie w zakładce Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Płatności poprzez voucher","VOUCHER_INFO_DESCRIPTION":"Mollie pozwala łatwo akceptować płatności w Twoim sklepie internetowym za pomocą voucherów ekologicznych, prezentowych i posiłkowych — to mądry wybór, aby zwiększyć sprzedaż i zadowolić klientów. Metoda płatności \\"voucher\\" jest widoczna tylko w przypadku, gdy w koszyku znajduje się co najmniej 1 produkt z przypisanym typem vouchera.","VOUCHER_INFO_DEFAULTLANGUAGE":"Proszę pamiętać, że ta konfiguracja może być edytowana tylko w domyślnym języku. Zmień język, aby zmodyfikować typ vouchera dla tego produktu.","VOUCHER_BTN_READMORE":"Czytaj więcej","VOUCHER_TYPE_CAPTION":"Typ vouchera","VOUCHER_TYPE_VALUE_NONE":"Brak","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Posiłek","VOUCHER_TYPE_VALUE_VOUCHER":"Prezent"},"modals":{"shipping":{"title":"Wyślij przez Mollie","item":{"label":"Pozycja:","noQuantity":"Proszę wprowadzić ilość do wysłania.","shipAll":"Wyślij wszystko","summary":{"quantity":"Ilość do wysłania","shipped":"Ilość wysłana","shippable":"Ilość do wysłania"},"success":"Zamówienie zostało pomyślnie wysłane."},"order":{"description":"Następujące ilości przedmiotów zostaną wysłane.","itemHeader":"Pozycja","quantityHeader":"Ilość","originalQuantityHeader":"Ilość (do wysłania)"},"availableTracking":{"label":"Dostępne kody śledzenia","hint":"Kliknij jeden z tych kodów, aby automatycznie uzupełnić wszystkie dane."},"showTracking":"Dodaj informacje o śledzeniu dla tej przesyłki","tracking":{"carrier":"Przewoźnik","code":"Kod","url":"Url","invalid":"Proszę wprowadzić zarówno przewoźnika, jak i kod"},"confirmButton":"Wyślij zamówienie","cancelButton":"Anuluj","selectAllButton":"Wybierz wszystko","resetButton":"Zresetuj"},"cancel":{"title":"Anuluj pozycję poprzez Mollie","confirmButton":"Anuluj pozycję poprzez Mollie","cancelButton":"Zamknij modal","resetStock":"Zresetuj stany magazynowe","item":{"success":"Produkt został pomyślnie anulowany","failed":{"quantityZero":"Ilość wynosi 0","invalidLine":"Nie odnaleziono produktu w zamówieniu","quantityTooHigh":"Zbyt duża ilość"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Wyślij zamówienie (Mollie)","description":"Wyślij zamówienie przez Mollie."},"modal":{"title":"Wyślij zamówienie","description":"To działanie automatycznie zrealizuje wysyłkę zamówienia przez Mollie. Sekwencja przepływu odbierze numer zamówienia i przekaże go do API Mollie. Zarówno zakończone pomyślnie, jak i nieudane wysyłki będą widoczne w plikach dziennika Mollie.","warningConfig":"Upewnij się, że wszelkie dodatkowe automatyzacje dla tego typu działania zostały wyłączone, aby uniknąć jakichkolwiek zakłóceń.\\nNastępujące aktywowane funkcje wtyczki mogą zakłócać to działanie:","noWarnings":"Brak ostrzeżeń"}},"refundOrder":{"editor":{"title":"Zwróć zamówienie (Mollie)","description":"Zwróć zamówienie poprzez Mollie."},"modal":{"title":"Zwróć zamówienie","description":"To działanie automatycznie rozpocznie proces zwrotu za pośrednictwem Mollie. Sekwencja przepływu odbierze numer zamówienia i przekaże go do API Mollie. Zarówno zakończone pomyślnie, jak i nieudane zwroty będą widoczne w plikach dziennika Mollie.","warning":"Proszę pamiętać, że proces finalizacji zwrotów może zająć do 2 godzin, zanim będą one widoczne w sklepie. Do tego czasu możliwe jest anulowanie oczekującego zwrotu, korzystając z widoku zamówienia w Shopware lub z poziomu Mollie Dashboard.","warningConfig":"Upewnij się, że wszelkie dodatkowe automatyzacje dla tego typu działania zostały wyłączone, aby uniknąć jakichkolwiek zakłóceń."}},"warnings":{"automaticShipping":"Automatyczna wysyłka w konfiguracji wtyczki"}}},"subscriptions":{"status":{"pending":"Oczekujący","active":"Aktywny","canceled":"Anulowany","suspended":"Wstrzymany","completed":"Zakończony","paused":"Wstrzymany","resumed":"Wznowiony","skipped":"Pominięty"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Dzień (dni)","TYPE_WEEKS":"Tydzień (tygodnie)","TYPE_MONTHS":"Miesiąc (miesiące)","confirm":{"cancelTitle":"Zakończyć subskrypcję?","cancel":"Anuluj subskrypcję swojego klienta.","pauseTitle":"Wstrzymaj subskrypcję?","pause":"Wstrzymaj subskrypcję do czasu jej wznowienia.","resumeTitle":"Wznów subskrypcję?","resume":"Wznów subskrypcję ponownie.","skipTitle":"Pominąć następną ratę?","skip":"Pomiń następną ratę w subskrypcji. Subskrypcja będzie automatycznie kontynuowana po tym okresie."},"alerts":{"cancelSuccess":"Subskrypcja została pomyślnie anulowana","pauseSuccess":"Subskrypcja została pomyślnie wstrzymana","resumeSuccess":"Subskrypcja została pomyślnie wznowiona","skipSuccess":"Subskrypcja została pomyślnie pominięta. Zaktualizowano kolejną płatność."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Klient","status":"Status","description":"Opis","amount":"Kwota","nextPaymentAt":"Następna płatność","prePaymentReminder":"Przypomniano o","canceledAt":"Anulowano o","createdAt":"Utworzono"},"action":{"edit":"Edytuj subskrypcję"},"deletedCustomer":"Usunięty klient"},"detail":{"title":"Subskrypcja Mollie","buttonCancelSubscription":"Anuluj subskrypcję","labelDescription":"Opis","labelAmount":"Kwota","labelQuantity":"Ilość","labelMollieSubscription":"Subskrypcja Mollie","labelMollieCustomer":"Klient Mollie","labelMandateId":"Mandat","labelShopwareCustomer":"Klient Shopware","labelCreatedAt":"Utworzono","buttonShowShopwareOrder":"Pokaż zamówienie Shopware","buttonShowShopwareCustomer":"Pokaż klienta Shopware","cardTitleSubscription":"Subskrypcja","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Następna płatność w","labelLastRemindedAt":"Ostatnie przypomnienie w","labelCanceledAt":"Anulowano","buttonPauseSubscription":"Wstrzymaj subskrypcję","buttonResumeSubscription":"Wznów subskrypcję","buttonSkipSubscription":"Pomiń subskrypcję","history":{"cardTitle":"Historia","colDate":"Data","colComment":"Komentarz","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Subskrypcja Mollie"}},"product":{"card-title":"Subskrypcja","title":"Subskrypcje Mollie","description":"Zarządzanie płatnościami cyklicznymi nigdy nie było prostsze dzięki naszym pomocnym funkcjom. Dzięki Mollie możesz łatwo tworzyć produkty subskrypcyjne i ustawiać cykliczne płatności w zaplanowanych odstępach czasowych. Nasze narzędzia umożliwiają efektywne śledzenie, prostą integrację oraz inne funkcje, które pozwolą Ci przenieść Twój biznes na wyższy poziom.","mollieSubscriptionProduct":"Produkt subskrypcyjny","mollieSubscriptionIntervalAmount":"Powtarzaj płatność co","mollieSubscriptionIntervalType":"Jednostka interwału","mollieSubscriptionRepetitionAmount":"Liczba powtórzeń","mollieSubscriptionRepetitionPlaceholder":"Wprowadź liczbę lub pozostaw puste","infoDefaultLanguage":"Proszę pamiętać, że ta konfiguracja może być edytowana tylko w domyślnym języku. Zmień język, aby zmodyfikować ustawienia subskrypcji dla tego produktu.","btnReadMore":"Czytaj więcej"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subskrypcja"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Dane karty kredytowej",buttonMolliePaymentLink:"Kopiuj do schowka",columnRefunded:"Zwrócony",columnShipped:"Wysłano",columnCanceled:"Anulowano",labelMollieOrderId:"ID zamówienia Mollie",labelMollieThirdPartyPaymentId:"Referencja płatności",labelMolliePaymentLink:"Link do Mollie Checkout",totalRefunds:"Zwrócona kwota",totalRefundsPending:"Oczekuje na zwrot",totalRemaining:"Kwota do zwrotu",totalVouchers:"Kwota vouchera",totalShipments:"Wysłana ilość ({quantity} przedmiotów)",subscriptionBadge:"Produkt subskrypcyjny",refundManager:{title:"Mollie Menedżer Zwrotów",btnOpenRefundManager:"Otwórz Menedżera Zwrotów",btnCloseRefundManager:"Zamknij Menedżera Zwrotów"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferowany emitent iDeal"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Menedżer Zwrotów"},mollie_subscription:{label:"Subskrypcje"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Opis"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Zwrot",subscription:"Subskrypcja",webhookReceived:"Webhooki",status:"Status",started:"Rozpoczęto",ended:"Zakończono",paused:"Wstrzymano",renewalReminder:"Przypomnienie o odnowieniu",renewed:"Odnowiony",resumed:"Wznowiony",skipped:"Pominięty",all:"Wszystko",canceled:"Anulowano",expired:"Wygasły",partiallyRefunded:"Zwrócono (częściowo)",orderSuccess:"Zamówienie zrealizowane",orderFailed:"Zamówienie nieudane",orderCanceled:"Zamówienie anulowane"}}},uq={entities:{mollie_subscription:"Mollie Předplatné | Mollie Předplatná"},businessEvents:{mollie_checkout_order_success:" Objednávka byla úspěšná",mollie_checkout_order_failed:" Objednávka selhala",mollie_checkout_order_canceled:" Objednávka byla zrušena",mollie_webhook_received_All:" Mollie Webhook Přijat (Vše)",mollie_webhook_received_status_authorized:" Mollie Webhook Přijat (Oprávněno)",mollie_webhook_received_status_failed:" Mollie Webhook Přijat (Selhalo)",mollie_webhook_received_status_canceled:" Mollie Webhook Přijat (Zrušeno)",mollie_webhook_received_status_expired:" Mollie Webhook Přijat (Vypršelo)",mollie_webhook_received_status_pending:" Mollie Webhook Přijat (Čekající)",mollie_webhook_received_status_paid:" Mollie Webhook Přijat (Zaplaceno)",mollie_webhook_received_status_completed:" Mollie Webhook Přijat (Dokončeno)",mollie_webhook_received_status_refunded:" Mollie Webhook Přijat (Vráceno)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Přijat (Částečně vráceno)",mollie_refund_started:" Mollie vrácení peněz zahájeno",mollie_subscription_started:" Mollie předplatné zahájeno",mollie_subscription_ended:" Mollie předplatné dokončeno",mollie_subscription_cancelled:" Mollie předplatné zrušeno",mollie_subscription_paused:" Mollie předplatné pozastaveno",mollie_subscription_resumed:" Mollie předplatné pokračuje",mollie_subscription_skipped:" Mollie předplatné přeskočeno",mollie_subscription_renewed:" Mollie předplatné obnoveno",mollie_subscription_renewal_reminder:" Mollie připomínka pro obnovení předplatného"}},dq={global:uq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Hledat předplatná...","general":{"mainMenuItemGeneral":"Mollie Platby","descriptionTextModule":"Mollie Platby","btnMollieActions":"Mollie Akce","refundThroughMollie":"Vrácení peněz přes Mollie","shipThroughMollie":"Odeslat přes Mollie","cancelMollieItem":"Zrušit přes Mollie"},"config":{"info":{"title":"Ahoj {userName}, vítejte v Mollie!","descriptionTop":"Onboarding je s Mollie snadný!","descriptionBottom":"To je vše!","descriptionFooter":"Pokud se chcete dozvědět více o našem pluginu, navštivte prosím naši oficiální stránku dokumentace.","onboardingStep1":"Zaregistrujte se do Mollie účtu.","onboardingStep2":"Zadejte své API klíče v sekci níže.","onboardingStep2TestMode":"Povolte 'Testovací režim', pokud chcete platby pouze testovat.","onboardingStep3":"Přiřaďte způsoby platby k vašemu prodejnímu kanálu.","onboardingStep3Link":"k vašim prodejním kanálům","btnDocumentation":"Dokumentace","btnRequestSupport":"Podpora","btnTroubleshooting":"Průvodce řešením problémů"},"api":{"apiLinkButton":"Získejte své API klíče z Mollie Dashboard","testButton":"Testovací API klíče","testApiKeys":{"title":"Mollie Platby","apiKey":"API klíč","isValid":"je platný","isInvalid":"je neplatný"}},"payments":{"format":{"placeholder":"Zástupný symbol","preview":"Náhled"},"updatePaymentMethods":{"title":"Mollie Platby","button":"Aktualizovat způsoby platby","succeeded":"Způsoby platby byly úspěšně aktualizovány.","failed":"Způsob platby se nepodařilo aktualizovat."},"mollieLimits":{"link":"Zobrazit pravidla přístupnosti mollie pro platební metodz"}},"rounding":{"info1":"Shopware může využít nastavení měny k výpočtu zaokrouhlení celkové částky objednávky. To zahrnuje počet desetinných míst v cenách vašich produktů a nejbližší interval zaokrouhlení, například 0,50 nebo 1,00.","info2":"Tato nastavení mohou vést k jinému celkovému součtu než součet jednotlivých položek. Když Mollie zkontroluje tyto částky a zjistí, že se neshodují, způsobí to chybu při pokladně.","info3":"Tuto funkci můžete použít k vyhnutí se problémům se zaokrouhlováním při pokladně. Po jejím aktivování se v přehledu Mollie přidá samostatná položka pro rozdíl v zaokrouhlování a vaši zákazníci zaplatí celkovou částku vypočítanou Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Použití Klarna Rozděl to nebo Klarna zaplať později není možné pokud je datum vypršení delší než 28 dní, za předpokladu, že mezi obchodníkem a Klarna není dohodnuta jiná maximální doba.","bankTransferDueDateLimitReached":"Není možné nastavit dobu platnosti objednávky na více než 100 dní."},"support":{"modalTitle":"Požádat o podporu od Mollie","btnCancel":"Zrušit","btnConfirm":"Požádat o podporu","btnSupport":"Více o naší podpoře","form":{"name":"Vaše jméno","email":"Váš e-mail","recipient":"Odeslat žádost na","subject":"Předmět","message":"Zpráva"},"data":{"header":"Informace odeslané Mollie:","other":"Ostatní:","shopwareVersion":"Verze Shopware","pluginLogs":"{plugin} soubory protokolu","pluginConfiguration":"{plugin} konfigurace","pluginConfigurationHelpText":"API klíče jsou vyloučeny.","paymentMethods":"Údaje o způsobu platby","paymentMethodsHelpText":"Obsahuje informace o tom, které platební metody jsou aktivní, jejich přiřazení k jednotlivým prodejním kanálům a jejich stav ve vašem účtu Mollie."},"success":"Žádost o podporu byla úspěšně odeslána. Děláme vše pro to, abychom odpověděli co nejdříve","error":"Došlo k problému při odesílání e-mailu přes Shopware. Prosím zkuste to znovu nebo nás kontaktujte přímo e-mailem."}},"rules":{"itemSubscriptionRule":"Položka je předplatné (Mollie)","cartSubscriptionRule":"Košík s předplatným (Mollie)"},"refunds":{"status":{"queued":"Ve frontě","pending":"Čekající","processing":"Zpracovává se","refunded":"Vráceno","failed":"Selhalo","description":{"queued":"Vrácení platby je zařazeno do fronty, dokud nebude dostatečný zůstatek pro jeho zpracování. Vrácení platby můžete stále zrušit.","pending":"Vrácení platby bude odesláno bance následující pracovní den. Vrácení platby můžete stále zrušit","processing":"Vrácená platba byla odeslána na banku. Vrácená částka bude na účet zákazníka převedena co nejdříve.","refunded":"Vrácená částka byla převedena na účet zákazníka.","failed":"Vrácení peněz se po zpracování nepodařilo, například protože zákazník zavřel svůj bankovní účet. Prostředky budou vráceny na váš účet."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nemáte oprávnění k provedení vrácení peněz","warningCancel":"Nemáte oprávnění k zrušení vrácení peněz"},"cart":{"title":"Objednávka ##orderNumber##","btnSelectAll":"Vybrat vše","btnResetForm":"Resetovat formulář","linkHowTo":"Jak používat tento formulář?","grid":{"columns":{"item":"Položka","productNumber":"Číslo produktu","unitPrice":"Jednotková cena","quantity":"Množství","refunded":"Vráceno","refundQuantity":"Vrácení peněz","totalPrice":"Celková částka","refundAmount":"Vrácení peněz","resetStock":"Resetovat zásoby"},"btnResetLine":"Resetovat řádek","checkDeductPromotion":"Odečíst slevu","checkRefundTax":"Vrátit DPH"},"roundDiffItemAdded":"Automatické zaokrouhlení položky bylo přidáno"},"instructions":{"linkResetTutorials":"Resetovat návody","btnToggleTutorial":"Zobrazit/Skrýt návod","titleFullRefund":"Úplné vrácení peněz","textFullRefund":"Stačí použít tlačítko pro úplné vrácení peněz. Tím zajistíte, že všechny vaše položky jsou označeny jako vrácené a celá částka je vrácena zákazníkovi.","titleStockReset":"Resetování zásob","textStockReset":"Můžete automaticky zvýšit dostupné zásoby zadáním množství, které chcete vrátit zpět do zásob. Toto množství zadejte před provedením úplného nebo částečného vrácení platby. Obnovení zásob můžete flexibilně spojit s procesem vrácení platby.","titleShipping":"Doprava","textShipping":"Poštovné lze vrátit stejně jako jakékoli jiné produktové položky. Zadejte celou nebo požadovanou částku a pokračujte ve vrácení platby. Vrácení nákladů na poštovné lze flexibilně spojit s vrácením platby za položky.","titlePartialAmount":"Částečné vrácení peněz (pouze částka)","textPartialAmount":"Jednoduše zadejte požadovanou částku do textového pole a zahajte vrácení peněz.","titlePartialItems":"Částečné vrácení peněz (s položkami)","textPartialItems":"Pokud chcete označit množství a položky jako vrácené v Mollie, použijte formulář výše. Nastavte množství a zadejte vlastní částku pro každou položku, která bude vrácena. Celková částka se následně zobrazí v textovém poli pro konečnou částku vrácení. Nezapomeňte, že tuto konečnou částku je stále možné upravit před zahájením vrácení platby.","titlePartialPromotions":"Částečné vrácení peněz (včetně slev)","textPartialPromotions":"Pokud máte v košíku položku se slevou, bude tato sleva zobrazena jako samostatná položka. Pokud chcete vrátit všechny položky se slevou, vraťte jejich celkové hodnoty a celou položku se slevou. Pokud chcete vrátit pouze některé položky se slevou, můžete automaticky odečíst slevu u každé jednotlivé položky. Samozřejmě nesprávné hodnoty můžete vždy upravit.","titleRoundingDiff":"Rozdíl zaokroulení","textRoundingDiff":"Úplné vrácení peněz zahrne rozdíly v zaokroulení"},"summary":{"dataLoading":"Data se načítají...","headerExcludingVat":"Bez DPH","headerIncludingVat":"S DPH","captionTotal":"Celkem","captionTotalTaxFree":"Celkem","captionPendingRefunds":"Čeká na vrácení peněz","captionVouchers":"Částka poukazu","captionRefunded":"Vrácená částka","captionRemaining":"Vrátitelná částka","btnFixDiff":"Opravit rozdíl","placeholderDescription":"Zadejte popis pro výpis z banky/karty pro zákazníka. Max. 140 znaků","lblDescription":"Popis (volitelné) ({characters}/140 znaků)","descriptionHelp":"Toto bude zobrazeno na výpisu z banky nebo karty zákazníka, pokud to bude možné. Zpráva bude zkrácena po 140 znacích.","placeholderInternalDescription":"Zadejte popis pro interní použití","lblInternalDescription":"Interní popis (volitelné)","internalDescriptionHelp":"Toto bude zobrazeno jako místní popis v administrátorském rozhraní.","checkVerification":"Ověřil(a) jsem celkovou částku vrácení platby a nastavené množství pro vrácení a opětovné naskladnění.","btnRefund":"Vrátit","btnFullRefund":"Úplné vrácení","roundDiffItemAdded":"Položka zaokroulení"},"refunds":{"title":"Vrácení peněz v Mollie Dashboard","linkMore":"Více o vrácení peněz","grid":{"columns":{"amount":"Částka","status":"Status","description":"Popis","internalDescription":"Interní popis","composition":"Složení","date":"Datum"},"lblNoComposition":"Žádné dostupné složení","btnCancelRefund":"Zrušit toto vrácení peněz"}},"notifications":{"success":{"refund-created":"Vrácení platby bylo vytvořeno v Mollie. Může trvat až 2 hodiny, než bude vrácení platby dokončeno. Během této doby můžete vrácení platby zrušit.","refund-canceled":"Probíhající vrácení platby bylo úspěšně zrušeno a odstraněno."},"error":{"low-amount":"Prosím zadejte částku, která má být vrácena.","refund-created":"Při vytváření vrácení platby došlo k chybě.","refund-canceled":"Při zrušení probíhajícího vrácení platby došlo k problému. Prosím, zkuste to znovu v Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Poukaz","VOUCHER_INFO_TITLE":"Platby poukazy","VOUCHER_INFO_DESCRIPTION":"Mollie vám umožňuje snadno přijímat platby ve vašem online obchodě pomocí Eco-, dárkových a stravenkových poukazů – chytrý způsob, jak zvýšit prodeje a uspokojit vaše zákazníky. Platební metoda 'poukaz' je viditelná pouze v případě, že máte v košíku alespoň 1 produkt s přiřazeným typem poukazu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vezměte prosím na vědomí, že tuto konfiguraci lze upravit pouze v nastaveném výchozím jazyce. Změňte prosím jazyk, abyste mohli upravit typ poukazu u tohoto produktu.","VOUCHER_BTN_READMORE":"Zjistit více","VOUCHER_TYPE_CAPTION":"Typ poukazu produktu","VOUCHER_TYPE_VALUE_NONE":"Žádný","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Stravenky","VOUCHER_TYPE_VALUE_VOUCHER":"Dárkový"},"modals":{"shipping":{"title":"Odeslat přes Mollie","item":{"label":"Položka:","noQuantity":"Prosím zadejte množství k odeslání.","shipAll":"Odeslat vše","summary":{"quantity":"Množství k odeslání","shipped":"Odeslané množství","shippable":"Množství, které lze odeslat"},"success":"Objednávka byla úspěšně odeslána."},"order":{"description":"Následující množství položek bude odesláno.","itemHeader":"Položka","quantityHeader":"Množství","originalQuantityHeader":"Množství (k odeslání)"},"availableTracking":{"label":"Dostupné sledovací kódy","hint":"Kliknutím na jeden z těchto sledovacích kódů se všechna data automaticky vyplní."},"showTracking":"Přidat informace o sledování pro tuto zásilku","tracking":{"carrier":"Dopravce","code":"Kód","url":"Url","invalid":"Prosím zadejte Dopravce i Kód"},"confirmButton":"Odeslat objednávku","cancelButton":"Zrušit","selectAllButton":"Vybrat vše","resetButton":"Resetovat"},"cancel":{"title":"Zrušit položku prostřednictvím Mollie","confirmButton":"Zrušit položku prostřednictvím Mollie","cancelButton":"Zavřít modal","resetStock":"Obnovit zásoby","item":{"success":"Produkt byl úspěšně zrušen","failed":{"quantityZero":"Množství je 0","invalidLine":"Produkt neexistuje v objednávce","quantityTooHigh":"Množství je příliš vysoké"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Odeslat objednávku (Mollie)","description":"Odeslat objednávku v Mollie."},"modal":{"title":"Odeslat objednávku","description":"Tato akce automaticky odešle objednávku prostřednictvím Mollie. Sekvence toku obdrží číslo objednávky a předá jej do API Mollie. Úspěšné a neúspěšné zásilky budou viditelné v protokolech Mollie.","warningConfig":"Ujistěte se, že vypnete jakoukoli další automatizaci pro tento typ akce, aby nedošlo k žádným rušením. Následující aktivované funkce tohoto pluginu mohou s touto akcí kolidovat:","noWarnings":"Žádná upozornění"}},"refundOrder":{"editor":{"title":"Vrácení peněz za objednávku (Mollie)","description":"Vrácení peněz za objednávku skrze Mollie."},"modal":{"title":"Vrácení peněz za objednávku","description":"Tato akce automaticky spustí vrácení platby prostřednictvím Mollie. Sekvence toku obdrží číslo objednávky a předá ho do Mollie API. Úspěšná a neúspěšná vrácení platby budou viditelná v protokolech Mollie.","warning":"Mějte prosím na paměti, že vrácení platby může trvat až 2 hodiny, než bude dokončeno a zobrazeno v obchodě. Během této doby můžete vždy zrušit probíhající vrácení platby buď z objednávky v Shopware, nebo z Mollie Dashboard.","warningConfig":"Prosím ujistěte se, že jste vypnuli veškerou další automatizaci pro tento typ akce, abyste předešli možným problémům."}},"warnings":{"automaticShipping":"Automatické odesílání v konfiguraci pluginu"}}},"subscriptions":{"status":{"pending":"Čekající","active":"Aktivní","canceled":"Zrušeno","suspended":"Pozastaveno","completed":"Dokončeno","paused":"Pozastaveno","resumed":"Obnoveno","skipped":"Přeskočeno"},"navigation":{"title":"Mollie Předplatná"},"TYPE_DAYS":"Den (dny)","TYPE_WEEKS":"Týden(y)","TYPE_MONTHS":"Měsíc(e)","confirm":{"cancelTitle":"Zrušit předplatné?","cancel":"Zrušit předplatné vašeho zákazníka.","pauseTitle":"Pozastavit předplatné?","pause":"Pozastavit předplatné, dokud jej znovu neobnovíte.","resumeTitle":"Obnovit předplatné?","resume":"Pokračovat znovu v předplatném.","skipTitle":"Přeskočit příští splátku?","skip":"Přeskočte příští splátku v předplatném. Poté bude pokračovat automaticky."},"alerts":{"cancelSuccess":"Předplatné bylo úspěšně zrušeno","pauseSuccess":"Předplatné bylo úspěšně pozastaveno","resumeSuccess":"Předplatné bylo úspěšně obnoveno","skipSuccess":"Předplatné bylo úspěšně přeskočeno. Následující platba byla aktualizována."},"list":{"title":"Mollie Předplatná","columns":{"customer":"Zákazník","status":"Status","description":"Popis","amount":"Částka","nextPaymentAt":"Další platba","prePaymentReminder":"Připomenuto k","canceledAt":"Zrušeno k","createdAt":"Vytvořeno k"},"action":{"edit":"Upravit předplatné"},"deletedCustomer":"Smazaný zákazník"},"detail":{"title":"Mollie předplatné","buttonCancelSubscription":"Zrušit předplatné","labelDescription":"Popis","labelAmount":"Částka","labelQuantity":"Množství","labelMollieSubscription":"Mollie předplatné","labelMollieCustomer":"Mollie zákazník","labelMandateId":"Pověření","labelShopwareCustomer":"Shopware zákazník","labelCreatedAt":"Vytvořeno k","buttonShowShopwareOrder":"Zobrazit objednávku Shopware","buttonShowShopwareCustomer":"Zobrazit zákazníka Shopware","cardTitleSubscription":"Předplatné","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Další platba k","labelLastRemindedAt":"Poslední připomenutí k","labelCanceledAt":"Zrušeno k","buttonPauseSubscription":"Pozastavit předplatné","buttonResumeSubscription":"Obnovit předplatné","buttonSkipSubscription":"Přeskočit předplatné","history":{"cardTitle":"Historie","colDate":"Datum","colComment":"Komentář","colStatusFrom":"Status (od)","colStatusTo":"Stav (do)","colMollieSubscription":"Mollie předplatné"}},"product":{"card-title":"Předplatné","title":"Mollie Předplatné","description":"Správa vašich opakovaných plateb je snadnější než kdy dříve díky našim užitečným funkcím. Posuňte své podnikání na novou úroveň s efektivními možnostmi sledování, jednoduchými integracemi a dalšími funkcemi. S předplatnými Mollie můžete snadno vytvářet produkty na předplatné i naplánovat opakované platby, které budou probíhat v nastaveném intervalu a období.","mollieSubscriptionProduct":"Produkt předplatného","mollieSubscriptionIntervalAmount":"Opakovat platbu každý","mollieSubscriptionIntervalType":"Jednotka intervalu","mollieSubscriptionRepetitionAmount":"Počet opakování","mollieSubscriptionRepetitionPlaceholder":"Zadejte číslo nebo nechte prázdné","infoDefaultLanguage":"Vezměte prosím na vědomí, že tuto konfiguraci lze upravit pouze ve vašem výchozím jazyce. Prosím změňte svůj jazyk pro úpravu nastavení předplatného tohoto produktu.","btnReadMore":"Zjistit více"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Předplatné"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Údaje o kreditní kartě",buttonMolliePaymentLink:"Kopírovat do schránky",columnRefunded:"Vráceno",columnShipped:"Odesláno",columnCanceled:"Zrušeno",labelMollieOrderId:"ID objednávky Mollie",labelMollieThirdPartyPaymentId:"Reference platby",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Vrácená částka",totalRefundsPending:"Čeká na vrácení",totalRemaining:"Částka, která může být vrácena",totalVouchers:"Částka poukazu",totalShipments:"Odeslaná částka ({quantity} položek)",subscriptionBadge:"Objednávka předplatného",refundManager:{title:"Mollie Manager Vrácení",btnOpenRefundManager:"Otevřít Manager Vrácení",btnCloseRefundManager:"Zavřít Správce Vrácení Peněz"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferovaný iDEAL emitent"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Správce vrácení peněz"},mollie_subscription:{label:"Předplatná"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Popis"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Vrácení peněz",subscription:"Předplatné",webhookReceived:"Webhooky",status:"Status",started:"Zahájeno",ended:"Ukončeno",paused:"Pozastaveno",renewalReminder:"Upomínka na obnovení",renewed:"Obnovený",resumed:"Pokračuje",skipped:"Přeskočeno",all:"Vše",canceled:"Zrušeno",expired:"Vypršelo",partiallyRefunded:"Vráceno (částečně)",orderSuccess:"Objednávka byla úspěšná",orderFailed:"Objednávka selhala",orderCanceled:"Objednávka byla zrušena"}}},cq={entities:{mollie_subscription:"Mollie naročnina | Mollie naročnine"},businessEvents:{mollie_checkout_order_success:" Naročilo uspešno",mollie_checkout_order_failed:" Naročilo neuspešno",mollie_checkout_order_canceled:" Naročilo preklicano",mollie_webhook_received_All:" Prejeto avtomatizirano obvestilo Mollie (vsa)",mollie_webhook_received_status_authorized:" Prejeto avtomatizirano obvestilo Mollie (avtorizirano)",mollie_webhook_received_status_failed:" Mollie avtomatizirano obvestilo prejeto (neuspešno)",mollie_webhook_received_status_canceled:" Mollie avtomatizirano obvestilo prejeto (preklicano)",mollie_webhook_received_status_expired:" Mollie avtomatizirano obvestilo prejeto (potekel)",mollie_webhook_received_status_pending:" Mollie avtomatizirano obvestilo prejeto (v teku)",mollie_webhook_received_status_paid:" Mollie avtomatizirano obvestilo prejeto (plačano)",mollie_webhook_received_status_completed:" Mollie avtomatizirano obvestilo prejeto (končano)",mollie_webhook_received_status_refunded:" Mollie avtomatizirano obvestilo prejeto (vrnjeno)",mollie_webhook_received_status_partially_refunded:" Mollie avtomatizirano obvestilo prejeto (delno vrnjeno)",mollie_refund_started:" Mollie vračilo je bilo začeto",mollie_subscription_started:" Mollie naročnina se je začela",mollie_subscription_ended:" Mollie naročnina se je končala",mollie_subscription_cancelled:" Mollie naročnina je preklicana",mollie_subscription_paused:" Mollie naročnina je začasno ustavljena",mollie_subscription_resumed:" Mollie naročnina se nadaljuje",mollie_subscription_skipped:" Mollie naročnina ni bila izvedena",mollie_subscription_renewed:" Mollie naročnina je obnovljena",mollie_subscription_renewal_reminder:" Mollie opomnik za obnovitev naročnine"}},pq={global:cq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie modul","searchPlaceholder":"Iskanje naročnin...","general":{"mainMenuItemGeneral":"Mollie plačila","descriptionTextModule":"Mollie plačila","btnMollieActions":"Dejanja Mollie","refundThroughMollie":"Vračilo preko Mollie","shipThroughMollie":"Pošiljanje preko Mollie","cancelMollieItem":"Preklici preko Mollie"},"config":{"info":{"title":"Pozdravljeni {userName}, dobrodošli v Mollie!","descriptionTop":"Uvajanje z Mollie je enostavno!","descriptionBottom":"To je vse!","descriptionFooter":"Če želite izvedeti več o našem vtičniku, prosimo, obiščite našo uradno stran z dokumentacijo.","onboardingStep1":"Registrirajte se v Mollie račun.","onboardingStep2":"Vnesite svoje ključe API v spodnji razdelek.","onboardingStep2TestMode":"Vklopite 'Testni način', če želite plačila le testirati.","onboardingStep3":"Dodelite načine plačila vašemu prodajnemu kanalu.","onboardingStep3Link":"vašim prodajnim kanalom","btnDocumentation":"Dokumentacija","btnRequestSupport":"Podpora","btnTroubleshooting":"Priročnik za odpravljanje težav"},"api":{"apiLinkButton":"Pridobite svoje ključe API iz Mollie Dashboard","testButton":"Testni ključi API","testApiKeys":{"title":"Mollie plačila","apiKey":"ključ API","isValid":"je veljaven","isInvalid":"je neveljaven"}},"payments":{"format":{"placeholder":"Vmesno besedilo","preview":"Predogled"},"updatePaymentMethods":{"title":"Mollie plačila","button":"Posodobi načine plačil","succeeded":"Načini plačila so bili uspešno posodobljeni.","failed":"Načinov plačila ni mogoče posodobiti."},"mollieLimits":{"link":"Prikaži pravila razpoložljivosti Mollie za načine plačila"}},"rounding":{"info1":"Shopware lahko uporablja nastavitve valute za izračun, kako zaokroži skupni znesek naročila. To vključuje število decimalnih mest v cenah vaših izdelkov in najbližji interval zaokroževanja, kot je 0,50 ali 1,00.","info2":"Te nastavitve lahko vodijo do drugačne končne cene, kot je skupna vsota vseh postavk. Ko Mollie preveri te zneske in ugotovi, da se ne ujemajo, pride do napake pri nakupu.","info3":"To funkcijo lahko uporabite, da se izognete težavam z zaokroževanjem pri nakupu. Ko je vklopljena, doda ločeno postavko v vašem Mollie Dashboardu za razliko v zaokroževanju, vaši kupci pa plačajo končno skupno ceno, izračunano v programu Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Uporaba Klarna Slice it ali Klarna Pay later kot način plačila ni mogoč, ko je datum poteka daljši od 28 dni, razen če je dogovor med trgovcem in Klarno drugačen.","bankTransferDueDateLimitReached":"Ni mogoče nastaviti življenjske dobe naročila nad 100 dni."},"support":{"modalTitle":"Zahtevajte podporo od Mollie","btnCancel":"Prekliči","btnConfirm":"Zahteva za podporo","btnSupport":"Več o naši podpori","form":{"name":"Vaše ime","email":"Vaš e-poštni naslov","recipient":"Pošlji zahtevo na","subject":"Predmet","message":"Sporočilo"},"data":{"header":"Podatki poslani Mollie:","other":"Drugo:","shopwareVersion":"Različica Shopware","pluginLogs":"{plugin} datoteke dnevnika","pluginConfiguration":"{plugin} konfiguracija","pluginConfigurationHelpText":"Ključi API so izključeni.","paymentMethods":"Podatki o načinu plačila","paymentMethodsHelpText":"Vsebuje informacije o tem, kateri načini plačila so aktivni, dodeljeni vsakemu prodajnemu kanalu, ter njihov status v vašem Mollie računu."},"success":"Zahteva za podporo je bila uspešno poslana. Potrudili se bomo, da odgovorimo čim prej.","error":"Prišlo je do težave pri pošiljanju e-pošte prek Shopware. Poskusite znova ali nas kontaktirajte neposredno po e-pošti."}},"rules":{"itemSubscriptionRule":"Izdelek je naročnina (Mollie)","cartSubscriptionRule":"Košarica z naročninami (Mollie)"},"refunds":{"status":{"queued":"Na čakanju","pending":"V teku","processing":"Obdelava","refunded":"Vrnjeno","failed":"Neuspešno","description":{"queued":"Vračilo je na čakanju, dokler ni dovolj stanja za obdelavo vračila. Vračilo še lahko prekličete.","pending":"Vračilo bo poslano na banko naslednji delovni dan. Vračilo še lahko prekličete.","processing":"Vračilo je bilo poslano na banko. Znesek vračila bo čim prej prenesen na račun potrošnika.","refunded":"Znesek vračila je bil nakazan potrošniku.","failed":"Vračilo je bilo po obdelavi neuspešno. Možno je, da je stranka zaprla svoj bančni račun. Sredstva bodo vrnjena na vaš račun."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nimate dovoljenj za ustvarjanje vračil","warningCancel":"Nimate dovoljenj za preklic vračil"},"cart":{"title":"Naročilo ##orderNumber##","btnSelectAll":"Izberite vse","btnResetForm":"Ponastavite obrazec","linkHowTo":"Kako uporabiti ta obrazec?","grid":{"columns":{"item":"Izdelek","productNumber":"Številka izdelka","unitPrice":"Cena na enoto","quantity":"Količina","refunded":"Vrnjeno","refundQuantity":"Vračilo","totalPrice":"Skupaj","refundAmount":"Vračilo","resetStock":"Ponastavi zalogo"},"btnResetLine":"Ponastavi vrstico","checkDeductPromotion":"Odštej popust","checkRefundTax":"Vrnite DDV"},"roundDiffItemAdded":"Postavka za samodejno zaokroževanje je bil dodan"},"instructions":{"linkResetTutorials":"Ponastavi navodila","btnToggleTutorial":"Prikaži/skrij navodilo","titleFullRefund":"Polno vračilo","textFullRefund":"Preprosto uporabite gumb za celotno vračilo. Tako zagotovite, da so vsi vaši predmeti označeni kot vrnjeni in da je celoten znesek vrnjen stranki.","titleStockReset":"Ponastavitev zaloge","textStockReset":"Razpoložljivo zalogo lahko samodejno povečate tako, da vnesete količino, ki jo želite vrniti. Preprosto jo vnesite preden nadaljujejte s polnim ali delnim vračilom. Ponastavitev zaloge se lahko prilagodi procesu vračila na fleksibilen način.","titleShipping":"Pošiljanje","textShipping":"Odposlani predmet se lahko vrne kot kateri koli drugi produkt. Vnesite celotno količino ali po meri določen delni znesek in nadaljujte s vračilom. Vračilo stroškov pošiljanja je mogoče združiti s procesom vračila predmetov na fleksibilen način.","titlePartialAmount":"Delno vračilo (samo znesek)","textPartialAmount":"Preprosto vnesite delni znesek v polje z besedilom in začnite vračilo.","titlePartialItems":"Delno vračilo (z izdelki)","textPartialItems":"Če želite označiti količine in izdelke kot vrnjene v Mollie, uporabite zgornji obrazec. Nastavite svoje količine in navedite prilagojen znesek za vsak izdelek, ki bo vrnjen. Skupni znesek bo nato viden v končnem polju z besedilom za vračilo.","titlePartialPromotions":"Delno vračilo (s popusti)","textPartialPromotions":"Če imate popust v svoji košarici, potem je vaša promocija ločena postavka. Če želite vrniti vse znižane izdelke, se lotite in vrnite njihovo celotno vrednost in celoten popust. Vendar pa lahko, če želite vrniti le nekaj znižanih izdelkov, avtomatsko odštejete uporabljeni popust za vsako postavko. Seveda lahko vedno spremenite vrednosti, če niso pravilne.","titleRoundingDiff":"Razlika pri zaokroževanju","textRoundingDiff":"Polno vračilo bo vključevalo razlike pri zaokroževanju"},"summary":{"dataLoading":"Podatki se nalagajo...","headerExcludingVat":"Brez DDV","headerIncludingVat":"Z DDV","captionTotal":"Skupaj","captionTotalTaxFree":"Skupaj","captionPendingRefunds":"Čaka na vračilo","captionVouchers":"Znesek vavčerja","captionRefunded":"Znesek vračila","captionRemaining":"Znesek, ki ga je mogoče vrniti","btnFixDiff":"Odpravi razliko","placeholderDescription":"Vnesite opis izpiska za potrošnika. Maksimalno 140 znakov","lblDescription":"Opis (neobvezno) ({characters}/140 znakov)","descriptionHelp":"Ta opis bo prikazan na bančnem ali kartičnem izpisku potrošnika, kadar bo to mogoče. Sporočilo bo skrajšano po 140 znakih.","placeholderInternalDescription":"Vnesite svoj opis za interno uporabo","lblInternalDescription":"Interni opis (neobvezno)","internalDescriptionHelp":"Ta opis bo prikazan kot lokalni opis v vmesniku za upravljanje.","checkVerification":"Preveril(-a) sem skupni znesek vračila in nastavljene količine za vračilo in ponovno zalogo.","btnRefund":"Vračilo","btnFullRefund":"Polno vračilo","roundDiffItemAdded":"Razlika pri zaokroževanju"},"refunds":{"title":"Vračila v Mollie Dashboardu","linkMore":"Več o vračilih","grid":{"columns":{"amount":"Znesek","status":"Status","description":"Opis","internalDescription":"Notranji opis","composition":"Sestava","date":"Datum"},"lblNoComposition":"Nobena sestava ni na voljo","btnCancelRefund":"Prekliči to vračilo"}},"notifications":{"success":{"refund-created":"Vračilo je bilo ustvarjeno v Mollie. Zaključitev vračila lahko traja do 2 uri. Do tega trenutka lahko prekličete vračilo.","refund-canceled":"Vračilo v teku je bilo uspešno preklicano in odstranjeno."},"error":{"low-amount":"Prosimo, vnesite znesek, ki ga želite vrniti.","refund-created":"Pri ustvarjanju vračila je prišlo do napake.","refund-canceled":"Pri preklicu čakajočega vračila je prišlo do težave. Prosimo, poskusite znova v Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vavčer","VOUCHER_INFO_TITLE":"Vavčer plačila","VOUCHER_INFO_DESCRIPTION":"Mollie vam omogoča enostavno sprejemanje plačil v vaši spletni trgovini z uporabo ekoloških, darilnih in obročnih vavčerjev—pametni izbor za povečanje prodaje in zadovoljstvo vaših kupcev. Način plačila \\"vavčer\\" je viden le, če imate vsaj 1 izdelek z dodeljeno vrsto vavčerja v nakupovalni košarici.","VOUCHER_INFO_DEFAULTLANGUAGE":"Prosimo, upoštevajte, da je to nastavitev mogoče urediti samo v vašem privzetem jeziku. Spremenite svoj jezik, da spremenite vrsto vavčerja za ta izdelek.","VOUCHER_BTN_READMORE":"Preberite več","VOUCHER_TYPE_CAPTION":"Vrsta vavčerja izdelka","VOUCHER_TYPE_VALUE_NONE":"Noben","VOUCHER_TYPE_VALUE_ECO":"Ekološki","VOUCHER_TYPE_VALUE_MEAL":"Obrok","VOUCHER_TYPE_VALUE_VOUCHER":"Darilo"},"modals":{"shipping":{"title":"Odpošlji prek Mollie","item":{"label":"Izdelek:","noQuantity":"Prosimo, vnesite količino za pošiljanje.","shipAll":"Odpošlji vse","summary":{"quantity":"Količina za pošiljanje","shipped":"Količina, ki je bila poslana","shippable":"Količina, ki jo lahko pošljemo"},"success":"Naročilo je bilo uspešno odposlano."},"order":{"description":"Naslednje količine predmetov bodo odposlane.","itemHeader":"Izdelek","quantityHeader":"Količina","originalQuantityHeader":"Količina (ki jo lahko pošljemo)"},"availableTracking":{"label":"Razpoložljive številke za sledenje","hint":"Kliknite na eno od teh številk za sledenje, da samodejno izpolnite vse podatke."},"showTracking":"Dodajte informacije o sledenju za to pošiljko","tracking":{"carrier":"Prevoznik","code":"Številka","url":"URL","invalid":"Prosimo, vnesite tako Prevoznika kot Številko"},"confirmButton":"Odpošlji naročilo","cancelButton":"Prekliči","selectAllButton":"Izberi vse","resetButton":"Ponastavi"},"cancel":{"title":"Prekliči izdelek preko Mollie","confirmButton":"Prekliči izdelek preko Mollie","cancelButton":"Zapri okno","resetStock":"Ponastavite zalogo","item":{"success":"Izdelek je bil uspešno preklicano","failed":{"quantityZero":"Količina je 0","invalidLine":"Izdelek ne obstaja v naročilu","quantityTooHigh":"Količina je prekoračena"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Odpošlji naročilo (Mollie)","description":"Odpošlji naročilo v Mollie."},"modal":{"title":"Odpošlji naročilo","description":"Ta ukaz bo samodejno odposlal naročilo preko Mollie. Postopek bo prejel številko naročila in ta bo posredovana Mollie API-ju. Uspešna in neuspešna odpošiljanja bodo vidna v Mollie dnevniških datotekah.","warningConfig":"Prosimo, prepričajte se, da ste izklopili vse dodatne avtomatizacije za to vrsto ukaza, da se izognete morebitnim motnjam.\\nNekatere aktivirane funkcije tega vtičnika lahko motijo ta ukaz:","noWarnings":"Brez opozoril"}},"refundOrder":{"editor":{"title":"Vračilo naročila (Mollie)","description":"Vračilo naročila preko Mollie."},"modal":{"title":"Vračilo naročila","description":"Ta ukaz bo samodejno odposlal naročilo preko Mollie. Postopek bo prejel številko naročila in ta bo posredovana Mollie API-ju. Uspešna in neuspešna odpošiljanja bodo vidna v Mollie dnevniških datotekah.","warning":"Prosimo, upoštevajte, da lahko vračila trajajo do 2 uri, da se zaključijo in postanejo vidna v trgovini. Do takrat lahko vedno prekličete čakajoče vračilo bodisi s strani naročila v Shopware bodisi iz Mollie Dashboard.","warningConfig":"Prosimo, prepričajte se, da ste izklopili vse dodatne avtomatizacije za to vrsto ukaza, da se izognete morebitnim motnjam."}},"warnings":{"automaticShipping":"Samodejno pošiljanje v konfiguraciji vtičnika"}}},"subscriptions":{"status":{"pending":"V teku","active":"Aktivno","canceled":"Preklicano","suspended":"Suspendiran","completed":"Končano","paused":"Na pavzi","resumed":"Nadaljevanje","skipped":"Izpuščeno"},"navigation":{"title":"Mollie naročnine"},"TYPE_DAYS":"Dan(denvi)","TYPE_WEEKS":"Teden(i)","TYPE_MONTHS":"Mesec(i)","confirm":{"cancelTitle":"Prekliči naročnino?","cancel":"Prekličite naročnino vašega kupca.","pauseTitle":"Začasno zaustavi naročnino?","pause":"Naročnino obdržite do ponovnega nadaljevanja.","resumeTitle":"Nadaljujte naročnino?","resume":"Nadaljujte naročnino.","skipTitle":"Preskoči naslednje obročno plačilo?","skip":"Preskočite naslednje obročno plačilo v naročnini. Nato se bo samodejno nadaljevala."},"alerts":{"cancelSuccess":"Naročnina je bila uspešno preklicana","pauseSuccess":"Naročnina je bila uspešno začasno zaustavljena","resumeSuccess":"Naročnina je bila uspešno obnovljena","skipSuccess":"Naročnina je bila uspešno izpuščena. Naslednje plačilo je bilo posodobljeno."},"list":{"title":"Mollie naročnine","columns":{"customer":"Stranka","status":"Status","description":"Opis","amount":"Znesek","nextPaymentAt":"Naslednje plačilo","prePaymentReminder":"Opomnik na","canceledAt":"Preklicano ob","createdAt":"Ustvarjeno ob"},"action":{"edit":"Uredi naročnino"},"deletedCustomer":"Izbrisana stranka"},"detail":{"title":"Mollie naročnina","buttonCancelSubscription":"Prekliči naročnino","labelDescription":"Opis","labelAmount":"Znesek","labelQuantity":"Količina","labelMollieSubscription":"Mollie naročnina","labelMollieCustomer":"Mollie stranka","labelMandateId":"Mandat","labelShopwareCustomer":"Stranka Shopware","labelCreatedAt":"Ustvarjeno ob","buttonShowShopwareOrder":"Prikaži naročilo Shopware","buttonShowShopwareCustomer":"Prikaži stranko Shopware","cardTitleSubscription":"Naročnina","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Naslednje plačilo ob","labelLastRemindedAt":"Zadnji opomnik ob","labelCanceledAt":"Preklicano ob","buttonPauseSubscription":"Začasno zaustavi naročnino","buttonResumeSubscription":"Nadaljuj naročnino","buttonSkipSubscription":"Preskoči naročnino","history":{"cardTitle":"Zgodovina","colDate":"Datum","colComment":"Komentar","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Mollie naročnina"}},"product":{"card-title":"Naročnina","title":"Mollie naročnine","description":"Upravljajte vaša ponavljajoča se plačila lažje kot kdaj koli prej z našimi uporabnimi funkcijami. Popeljite svoj posel na naslednjo raven z učinkovitimi možnostmi sledenja, preprostimi integracijami in še več. S pomočjo Mollie naročnin lahko enostavno ustvarite naročniške izdelke in načrtujete ponavljajoča se plačila, ki bodo izvedena ob nastavljenem intervalu in obdobju.","mollieSubscriptionProduct":"Izdelki naročnin","mollieSubscriptionIntervalAmount":"Ponovite plačilo vsak","mollieSubscriptionIntervalType":"Enota intervala","mollieSubscriptionRepetitionAmount":"Število ponovitev","mollieSubscriptionRepetitionPlaceholder":"Vnesite število ali pustite prazno","infoDefaultLanguage":"Prosimo, upoštevajte, da lahko to nastavitev uredite samo v svojem privzetem jeziku. Prosimo, spremenite svoj jezik, da uredite nastavitve naročnine tega izdelka.","btnReadMore":"Preberite več"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Naročnina"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Podatki o kreditni kartici",buttonMolliePaymentLink:"Kopiraj v odložišče",columnRefunded:"Vrnjeno",columnShipped:"Odposlano",columnCanceled:"Preklicano",labelMollieOrderId:"ID naročila Mollie",labelMollieThirdPartyPaymentId:"Referenca plačila",labelMolliePaymentLink:"URL Mollie Checkout",totalRefunds:"Vrnjeni znesek",totalRefundsPending:"Čaka na vračilo",totalRemaining:"Znesek, ki se lahko vrne",totalVouchers:"Znesek vavčerja",totalShipments:"Poslana količina ({quantity} izdelkov)",subscriptionBadge:"Naročilo naročnine",refundManager:{title:"Mollie upravitelj vračil",btnOpenRefundManager:"Odpri upravitelja vračil",btnCloseRefundManager:"Zapri upravitelja vračil"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Prednostni izdajatelj iDeal"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Upravitelj vračil"},mollie_subscription:{label:"Naročnine"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Opis"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Vračilo",subscription:"Naročnina",webhookReceived:"Avtomatizirana obvestila",status:"Status",started:"Začeto",ended:"Končano",paused:"Na pavzi",renewalReminder:"Opomnik za obnovitev",renewed:"Obnovljeno",resumed:"Se nadaljuje",skipped:"Izpuščeno",all:"Vse",canceled:"Preklicano",expired:"Potekel",partiallyRefunded:"Povrnjeno (delno)",orderSuccess:"Naročilo uspešno",orderFailed:"Naročilo neuspešno",orderCanceled:"Naročilo preklicano"}}},mq={entities:{mollie_subscription:"Mollie előfizetés | Mollie előfizetések"},businessEvents:{mollie_checkout_order_success:" A rendelés sikeres",mollie_checkout_order_failed:" A rendelés sikertelen",mollie_checkout_order_canceled:" A rendelés törölve",mollie_webhook_received_All:" Mollie Webhook beérkezett (Minden)",mollie_webhook_received_status_authorized:" Mollie Webhook beérkezett (Engedélyezett)",mollie_webhook_received_status_failed:" Mollie Webhook beérkezett (Sikertelen)",mollie_webhook_received_status_canceled:" Mollie Webhook beérkezett (Törölve)",mollie_webhook_received_status_expired:" Mollie Webhook beérkezett (Lejárt)",mollie_webhook_received_status_pending:" Mollie Webhook beérkezett (Függőben)",mollie_webhook_received_status_paid:" Mollie Webhook beérkezett (Fizetve)",mollie_webhook_received_status_completed:" Mollie Webhook beérkezett (Befejezett)",mollie_webhook_received_status_refunded:" Mollie Webhook beérkezett (Visszatérítve)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook beérkezett (Részben visszatérítve)",mollie_refund_started:" Mollie visszatérítés megkezdődött",mollie_subscription_started:" Mollie előfizetés megkezdődött",mollie_subscription_ended:" Mollie előfizetés befejeződött",mollie_subscription_cancelled:" Mollie előfizetés törölve",mollie_subscription_paused:" Mollie előfizetés szüneteltetve",mollie_subscription_resumed:" Mollie előfizetés folytatva",mollie_subscription_skipped:" Mollie előfizetés átugorva",mollie_subscription_renewed:" Mollie előfizetés megújítva",mollie_subscription_renewal_reminder:" Mollie emlékeztető az előfizetés megújításához"}},vq={global:mq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Search subscriptions...","general":{"mainMenuItemGeneral":"Mollie Fizetések","descriptionTextModule":"Mollie Fizetések","btnMollieActions":"Mollie Akciók","refundThroughMollie":"Visszatérítés Mollie-n keresztül","shipThroughMollie":"Szállítás Mollie-n keresztül","cancelMollieItem":"Törlés Mollie-n keresztül"},"config":{"info":{"title":"Szia {userName}, üdvözöljük a Mollie-nál!","descriptionTop":"A Mollie-nál könnyű a bevezetés!","descriptionBottom":"Ez ennyi!","descriptionFooter":"Ha többet szeretne megtudni a plugin-ról, kérjük, látogassa meg hivatalos dokumentációs oldalunkat.","onboardingStep1":"Regisztráljon egy Mollie Fiókra.","onboardingStep2":"Adja meg az API kulcsait az alábbi szekcióban.","onboardingStep2TestMode":"'Teszt környezet' bekapcsolása, ha csak a kifizetéseket szeretné tesztelni.","onboardingStep3":"Fizetési módokat rendeljen eladási csatornájához.","onboardingStep3Link":"az eladási csatornáihoz","btnDocumentation":"Dokumentáció","btnRequestSupport":"Támogatás","btnTroubleshooting":"Hibaelhárítási útmutató"},"api":{"apiLinkButton":"Szerezze meg API kulcsait a Mollie Irányítópultról","testButton":"Teszt API Kulcsok","testApiKeys":{"title":"Mollie Fizetések","apiKey":"API kulcs","isValid":"érvényes","isInvalid":"érvénytelen"}},"payments":{"format":{"placeholder":"Helyőrző","preview":"Előnézet"},"updatePaymentMethods":{"title":"Mollie Fizetések","button":"Fizetési módok frissítése","succeeded":"A fizetési módok sikeresen frissítve lettek.","failed":"A fizetési módokat nem sikerült frissíteni."},"mollieLimits":{"link":"Mollie elérhetőségi szabályok megjelenítése a fizetési módokhoz"}},"rounding":{"info1":"A Shopware pénznembeállításokat használ a rendelés teljes összegének kerekítésének kiszámításához. Ez magában foglalja a termékárak tizedesjegyeinek számát és a kerekítési intervallumot, például 0.50 vagy 1.00.","info2":"Ezek a módosítások a tételek összegétől eltérő teljes összeget eredményezhetnek. Amikor Mollie ellenőrzi ezeket az összegeket, és nem egyeznek, a fizetési folyamat meghiúsul.","info3":"Ezzel a funkcióval elkerülheti a kerekítési problémákat a fizetési folyamat során. Ha ez a funkció be van kapcsolva, egy új tételsor kerül a Mollie Dashboardba a kerekítési különbséggel, és ügyfelei kifizetik a Shopware által kiszámított végösszeget."},"order":{"bankTransferDueDateKlarnaLimitReached":"28 napnál hosszabb esedékesség esetén a Klarna (fizessen most, fizessen részletben vagy utólag) fizetési módként nem választható, kivéve, ha a Klarna és a kereskedő külön megállapodást kötött ennek meghosszabbítására.","bankTransferDueDateLimitReached":"Nem lehetséges a rendelés élettartamát 100 napnál magasabbra állítani."},"support":{"modalTitle":"Kérjen segítséget Mollie-tól","btnCancel":"Törlés","btnConfirm":"Kérjen támogatást","btnSupport":"Több információ támogatásunkról","form":{"name":"Az Ön neve","email":"Az Ön email címe","recipient":"Kérelem elküldése","subject":"Tárgy","message":"Üzenet"},"data":{"header":"Adatok elküldve a Mollie-nak:","other":"Más:","shopwareVersion":"Shopware verzió","pluginLogs":"{plugin} naplófájlok","pluginConfiguration":"{plugin} konfiguráció","pluginConfigurationHelpText":"API kulcsok ki vannak zárva.","paymentMethods":"Fizetési mód adat","paymentMethodsHelpText":"Információkat tartalmaz arról, hogy mely fizetési módok aktívak, az egyes értékesítési csatornákhoz vannak hozzárendelve, valamint azok állapotáról a Mollie-fiókjában."},"success":"The suport request has been successfully sent. We do our best to reply as soon as possible","error":"Probléma lépett fel a levél Shopware-en keresztüli elküldésekor. Kérjük, próbálja újra, vagy lépjen közvetlenül kapcsolatba velünk emailben."}},"rules":{"itemSubscriptionRule":"A termék előfizetés (Mollie)","cartSubscriptionRule":"Kosár előfizetésekkel (Mollie)"},"refunds":{"status":{"queued":"Folyamatban","pending":"Függőben","processing":"Feldolgozás alatt","refunded":"Visszatérítve","failed":"Sikertelen","description":{"queued":"A visszatérítés addig van sorban, amíg elegendő egyenleg nem áll rendelkezésre a feldolgozásához. Továbbra is lemondhatja a visszatérítést.","pending":"A visszatérítést a következő munkanapon küldik a banknak. A visszatérítés még mindig törölhető.","processing":"A visszatérítést elküldtük a banknak. A visszatérített összeg a lehető leghamarabb át lesz utalva a fogyasztói számlára.","refunded":"A visszatérített összeg át lett utalva a fogyasztónak.","failed":"A visszatérítés feldolgozás után meghiúsult. Például a vásárló bezárta a bankszámláját. Az összeg visszakerül az Ön számlájára."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nincs jogosultsága a visszatérítések létrehozására","warningCancel":"Nincs jogosultsága a visszatérítések törlésére"},"cart":{"title":"Megrendelés ##orderNumber##","btnSelectAll":"Összes kiválasztása","btnResetForm":"Űrlap visszaállítása","linkHowTo":"Hogyan használjam ezt az űrlapot?","grid":{"columns":{"item":"Termék","productNumber":"Termékszám","unitPrice":"Egységár","quantity":"Mennyiség","refunded":"Visszatérítve","refundQuantity":"Visszatérítés","totalPrice":"Összesen","refundAmount":"Visszatérítés","resetStock":"Készlet visszaállítása"},"btnResetLine":"Sor visszaállítása","checkDeductPromotion":"Promóció levonása","checkRefundTax":"ÁFA visszatérítése"},"roundDiffItemAdded":"Automatikus kerekítési elem került hozzáadásra"},"instructions":{"linkResetTutorials":"Útmutatók visszaállítása","btnToggleTutorial":"Útmutató megjelenítése/elrejtése","titleFullRefund":"Teljes visszatérítés","textFullRefund":"Csak használja a teljes visszatérítés gombot. Ez biztosítja, hogy az összes elemét visszatérítettnek jelöljön meg, és a teljes összeg visszatérítést nyújtsa a vásárlónak.","titleStockReset":"Készlet visszaállítás","textStockReset":"A feltöltendő mennyiség hozzáadásával automatikusan növelheti a rendelkezésre álló készletet. Egyszerűen adja meg az információkat, mielőtt folytatná a teljes vagy részleges visszatérítést. Az állomány helyreállítása kombinálható a visszatérítési folyamattal.","titleShipping":"Szállítás","textShipping":"A kiszállításra kerülő tételeket ugyanúgy vissza lehet téríteni, mint bármely más terméket. Egyszerűen írja be a teljes vagy a kívánt összeget, és folytassa a visszatérítéssel. A szállítási költségek visszatérítése kombinálható a tétel-visszatérítési folyamattal.","titlePartialAmount":"Részleges Visszatérítés (csak összeg)","textPartialAmount":"Csak írja be a részletösszeget a szövegmezőbe, és kezdje meg a visszatérítést.","titlePartialItems":"Részleges Visszatérítés (termékekkel)","textPartialItems":"A fenti űrlap segítségével jelölje meg a Mollie-nál visszatérített összegeket és tételeket. Állítsa be a mennyiségeket, és adja hozzá az egyszeri összeget minden egyes visszatérített tételhez. A teljes összeg a teljes visszatérített összeg szövegmezőben lesz látható. Ne feledje, hogy a visszatérítés megkezdése előtt módosíthatja a végső összeget.","titlePartialPromotions":"Részleges Visszatérítés (promóciókkal)","textPartialPromotions":"Ha van egy akció a kosarában, az akció új tételsorként jelenik meg. Ha az összes kedvezményes terméket vissza kívánja téríteni, vissza kell adnia az összérték sort és a promóciós tétel sort. Ha csak néhány akciós tételt szeretne visszafizetni, akkor az egyes sorokra alkalmazott kedvezményt automatikusan levonhatja. Természetesen bármikor módosíthatja az értékeket, ha nem megfelelőek.","titleRoundingDiff":"Kerekítési különbség","textRoundingDiff":"A teljes visszatérítés tartalmazni fogja a kerekítési különbségeket"},"summary":{"dataLoading":"Adatok betöltése...","headerExcludingVat":"Nettó","headerIncludingVat":"Bruttó","captionTotal":"Összesen","captionTotalTaxFree":"Összesen","captionPendingRefunds":"Visszatérítésre vár","captionVouchers":"Kupon összege","captionRefunded":"Visszatérített összeg","captionRemaining":"Visszatéríthető összeg","btnFixDiff":"Különbség javítása","placeholderDescription":"Írja be a bank/kártya kimutatás leírását a fogyasztó számára. Max 140 karakter","lblDescription":"Leírás (opcionális) ({characters}/140 karakter)","descriptionHelp":"Ez meg fog jelenni a fogyasztó bank- vagy kártyakimutatásán, amikor lehetséges. Az üzenet 140 karakter után trunkolva lesz.","placeholderInternalDescription":"Adja meg a belső leírását","lblInternalDescription":"Belső leírás (opcionális)","internalDescriptionHelp":"Ez a helyi leírása fog megjelenni az adminisztrációs felületen.","checkVerification":"Ellenőriztem a teljes visszatérítési összeget és a konfigurált mennyiségeket a visszatérítéshez és a készletvisszahelyezéshez.","btnRefund":"Visszatérítés","btnFullRefund":"Teljes visszatérítés","roundDiffItemAdded":"Kerekítési elem"},"refunds":{"title":"Visszatérítések a Mollie Irányítópulton","linkMore":"Több információ a visszatérítésekről","grid":{"columns":{"amount":"Összeg","status":"Állapot","description":"Leírás","internalDescription":"Belső leírás","composition":"Összetétel","date":"Dátum"},"lblNoComposition":"Nincs elérhető összetétel","btnCancelRefund":"Törölje ezt a visszatérítést"}},"notifications":{"success":{"refund-created":"Egy visszatérítést létrehoztak Mollie-ban. A visszatérítés teljesítése legfeljebb 2 órát vehet igénybe. Ezen idő alatt törölheti a visszatérítést.","refund-canceled":"A függőben lévő visszatérítést sikeresen törölték és eltávolították."},"error":{"low-amount":"Kérjük, adjon meg egy visszatérítendő összeget.","refund-created":"Valami elromlott a visszatérítés létrehozásakor.","refund-canceled":"Probléma történt a függőben lévő visszatérítés törlésekor. Kérjük, próbálja újra a Mollie Irányítópulton."}}},"vouchers":{"CARD_TITLE":"Kupon","VOUCHER_INFO_TITLE":"Kuponos kifizetések","VOUCHER_INFO_DESCRIPTION":"A Mollie lehetővé teszi, hogy ökológiai, ajándék- és élelmiszerutalványokkal fogadjon be fizetéseket online áruházából. Ez a lehetőség növelheti az eladásokat, és kielégítheti ügyfeleit. Az \\"utalványos\\" fizetési mód csak akkor látható, ha a kosárban legalább 1 db utalványtípushoz rendelt termék van.","VOUCHER_INFO_DEFAULTLANGUAGE":"Kérjük, vegye figyelembe, hogy ezt a beállítást csak az alapnyelvén tudja szerkeszteni. Kérjük, váltson nyelvet, hogy módosíthassa ennek a terméknek a kupon típusát.","VOUCHER_BTN_READMORE":"További információ","VOUCHER_TYPE_CAPTION":"Termék kupon típusa","VOUCHER_TYPE_VALUE_NONE":"Nincs","VOUCHER_TYPE_VALUE_ECO":"Öko","VOUCHER_TYPE_VALUE_MEAL":"Étkezés","VOUCHER_TYPE_VALUE_VOUCHER":"Ajándék"},"modals":{"shipping":{"title":"Szállítás Mollie-on keresztül","item":{"label":"Termék:","noQuantity":"Kérjük, adjon meg egy mennyiséget a szállításhoz.","shipAll":"Minden szállítása","summary":{"quantity":"Szállítandó mennyiség","shipped":"Szállított mennyiség","shippable":"Szállítható mennyiség"},"success":"A rendelést sikeresen szállították."},"order":{"description":"A következő termékek mennyisége lesz szállítva.","itemHeader":"Termék","quantityHeader":"Mennyiség","originalQuantityHeader":"Mennyiség (szállítható)"},"availableTracking":{"label":"Elérhető nyomkövetési kódok","hint":"Kattintson az egyik nyomkövetési kódra, hogy automatikusan kitölthesse az összes adatot."},"showTracking":"Adjon meg nyomkövetési információt ehhez a szállításhoz","tracking":{"carrier":"Fuvarozó","code":"Kód","url":"Url","invalid":"Kérjük, adja meg a Fuvarozót és a Kódot"},"confirmButton":"Rendelés szállítása","cancelButton":"Törlés","selectAllButton":"Mind kiválasztása","resetButton":"Visszaállítás"},"cancel":{"title":"Törölje a tételt Mollie-on keresztül","confirmButton":"Törölje a tételt Mollie-on keresztül","cancelButton":"Modal bezárása","resetStock":"Készletek visszaállítása","item":{"success":"A termék sikeresen törölve","failed":{"quantityZero":"A mennyiség 0","invalidLine":"A termék nem létezik a rendelésben","quantityTooHigh":"A mennyiség túl magas"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Rendelés szállítása (Mollie)","description":"Rendelés szállítása Mollie-val."},"modal":{"title":"Rendelés szállítása","description":"Ez a művelet automatikusan szállítja a rendelést Mollie-n keresztül. A folyamat fel fogja venni a rendelési számot, és továbbítja azt a Mollie API-nak. A sikeres és sikertelen szállítások láthatóak lesznek a Mollie naplófájljaiban.","warningConfig":"Kérjük, kapcsoljon ki minden további automatizálást az ilyen típusú műveletekhez a zavarás elkerülése érdekében.\\nA következő paraméterek aktiválva vannak, és zavarhatják a műveletet:","noWarnings":"Nincsenek figyelmeztetések"}},"refundOrder":{"editor":{"title":"Rendelés visszatérítése (Mollie)","description":"Rendelés visszatérítése Mollie-n keresztül."},"modal":{"title":"Rendelés visszatérítése","description":"Ez a művelet automatikusan elindít egy visszatérítést Mollie-n keresztül. A folyamat fel fogja venni a rendelési számot, és továbbítja azt a Mollie API-nak. A sikeres és sikertelen visszatérítések láthatóak lesznek a Mollie naplófájljaiban.","warning":"Felhívjuk figyelmét, hogy a visszatérítés legfeljebb 2 órát vesz igénybe, és az üzletben látható. Ez előtt az idő előtt bármikor törölhet egy függőben lévő visszatérítést, akár a Shopware rendelési oldalán, akár a Mollie irányítópultján.","warningConfig":"Kérjük, a zavarás elkerülése érdekében tiltsa le az ilyen típusú műveletek további automatizálását."}},"warnings":{"automaticShipping":"Automatikus elküldés a plugin beállításaiban"}}},"subscriptions":{"status":{"pending":"Függőben","active":"Aktív","canceled":"Törölve","suspended":"Felfüggesztve","completed":"Befejezett","paused":"Felfüggesztve","resumed":"Folyamatban","skipped":"Átugrott"},"navigation":{"title":"Mollie Előfizetések"},"TYPE_DAYS":"Nap(ek)","TYPE_WEEKS":"Hét(ek)","TYPE_MONTHS":"Hónap(ok)","confirm":{"cancelTitle":"Előfizetés lemondása?","cancel":"Lemondja az ügyfél előfizetését.","pauseTitle":"Előfizetés felfüggesztése?","pause":"Tartsa az előfizetést a felfüggesztéséig.","resumeTitle":"Előfizetés folytatása?","resume":"Folytassa az előfizetést.","skipTitle":"Átugorja a következő részletet?","skip":"Átugorja a következő részletet az előfizetésben. Később automatikusan folytatódik."},"alerts":{"cancelSuccess":"Az előfizetések sikeresen lemondásra kerültek","pauseSuccess":"Az előfizetés sikeresen felfüggesztve","resumeSuccess":"Az előfizetés sikeresen folytatva","skipSuccess":"Az előfizetés sikeresen átugrásra került. A következő kifizetés frissítve lett."},"list":{"title":"Mollie Előfizetések","columns":{"customer":"Ügyfél","status":"Állapot","description":"Leírás","amount":"Összeg","nextPaymentAt":"Következő kifizetés","prePaymentReminder":"Emlékeztető","canceledAt":"Lemondva","createdAt":"Létrehozva"},"action":{"edit":"Előfizetés szerkesztése"},"deletedCustomer":"Törölt ügyfél"},"detail":{"title":"Mollie előfizetés","buttonCancelSubscription":"Előfizetés lemondása","labelDescription":"Leírás","labelAmount":"Összeg","labelQuantity":"Mennyiség","labelMollieSubscription":"Mollie előfizetés","labelMollieCustomer":"Mollie ügyfél","labelMandateId":"Mandátum","labelShopwareCustomer":"Shopware ügyfél","labelCreatedAt":"Létrehozva","buttonShowShopwareOrder":"Shopware rendelés megjelenítése","buttonShowShopwareCustomer":"Shopware ügyfél megjelenítése","cardTitleSubscription":"Előfizetés","cardTitleStatus":"Állapot","labelStatus":"Állapot","labelNextPaymentAt":"Következő kifizetés időpontja","labelLastRemindedAt":"Utolsó emlékeztető","labelCanceledAt":"Lemondva","buttonPauseSubscription":"Előfizetés felfüggesztése","buttonResumeSubscription":"Előfizetés folytatása","buttonSkipSubscription":"Előfizetés átugrása","history":{"cardTitle":"Történet","colDate":"Dátum","colComment":"Megjegyzés","colStatusFrom":"Állapot (től)","colStatusTo":"Állapot (ig)","colMollieSubscription":"Mollie előfizetés"}},"product":{"card-title":"Előfizetés","title":"Mollie Előfizetések","description":"Az általunk kínált funkcióknak köszönhetően nagyon egyszerű az ismétlődő fizetések kezelése. Emelje vállalkozását a következő szintre a nyomkövetési lehetőségekkel, az egyszerű integrációkkal és sok mással. A Mollie Subscriptions segítségével előfizetéseket hozhat létre, és ütemezheti az ismétlődő fizetéseket meghatározott időközönként és időszakonkénti fizetéssel.","mollieSubscriptionProduct":"Előfizetési termék","mollieSubscriptionIntervalAmount":"Kifizetés ismétlése minden","mollieSubscriptionIntervalType":"Időköz típusa","mollieSubscriptionRepetitionAmount":"Ismétlések száma","mollieSubscriptionRepetitionPlaceholder":"Adja meg a számot, vagy hagyja üresen","infoDefaultLanguage":"Kérjük, vegye figyelembe, hogy ezt a beállítást csak az alapnyelvén tudja szerkeszteni. Kérjük, váltson nyelvet, hogy módosíthassa ennek a terméknek az előfizetési beállításait.","btnReadMore":"További információ"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Előfizetés"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Hitelkártya adatok",buttonMolliePaymentLink:"Másolás a vágólapra",columnRefunded:"Visszatérítve",columnShipped:"Kiszállítva",columnCanceled:"Törölve",labelMollieOrderId:"Mollie Rendelés ID",labelMollieThirdPartyPaymentId:"Fizetési hivatkozás",labelMolliePaymentLink:"Mollie Fizetés URL",totalRefunds:"Visszatérített összeg",totalRefundsPending:"Visszatérítésre vár",totalRemaining:"Visszatéríthető összeg",totalVouchers:"Kupon összeg",totalShipments:"Kiszállított összeg ({quantity} tétel)",subscriptionBadge:"Előfizetés Rendelés",refundManager:{title:"Mollie Visszatérítési Menedzser",btnOpenRefundManager:"Visszatérítési Menedzser megnyitása",btnCloseRefundManager:"Visszatérítési Menedzser bezárása"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferált iDeal kibocsátó"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Visszatérítési Menedzser"},mollie_subscription:{label:"Előfizetések"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Leírás"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Visszatérítés",subscription:"Előfizetés",webhookReceived:"Webhookok",status:"Állapot",started:"Kezdődött",ended:"Befejeződött",paused:"Felfüggesztve",renewalReminder:"Megújítási emlékeztető",renewed:"Megújítva",resumed:"Folytatva",skipped:"Átugorva",all:"Mind",canceled:"Törölve",expired:"Lejárt",partiallyRefunded:"Refunded (partially)",orderSuccess:"A megrendelés sikeres",orderFailed:"A megrendelés sikertelen",orderCanceled:"A megrendelés törölve"}}},fq={entities:{mollie_subscription:"Mollie-tilaus | Mollie-tilaukset"},businessEvents:{mollie_checkout_order_success:" Tilaus onnistui",mollie_checkout_order_failed:" Tilaus epäonnistui",mollie_checkout_order_canceled:" Tilaus peruutettu",mollie_webhook_received_All:" Mollie Webhook vastaanotettu (Kaikki)",mollie_webhook_received_status_authorized:" Mollie Webhook vastaanotettu (Valtuutettu)",mollie_webhook_received_status_failed:" Mollie Webhook vastaanotettu (Epäonnistunut)",mollie_webhook_received_status_canceled:" Mollie Webhook vastaanotettu (Peruutettu)",mollie_webhook_received_status_expired:" Mollie Webhook vastaanotettu (Vanhentunut)",mollie_webhook_received_status_pending:" Mollie Webhook vastaanotettu (Kesken)",mollie_webhook_received_status_paid:" Mollie Webhook vastaanotettu (Maksettu)",mollie_webhook_received_status_completed:" Mollie Webhook vastaanotettu (Suoritettu)",mollie_webhook_received_status_refunded:" Mollie Webhook vastaanotettu (Hyvitetty)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook vastaanotettu (Osittain hyvitetty)",mollie_refund_started:" Mollie hyvityspyyntö aloitettu",mollie_subscription_started:" Mollie-tilaus aloitettu",mollie_subscription_ended:" Mollie-tilaus suoritettu",mollie_subscription_cancelled:" Mollie-tilaus peruutettu",mollie_subscription_paused:" Mollie-tilaus keskeytetty",mollie_subscription_resumed:" Mollie-tilaus jatkettu",mollie_subscription_skipped:" Mollie-tilaus ohitettu",mollie_subscription_renewed:" Mollie-tilaus uusittu",mollie_subscription_renewal_reminder:" Mollie muistutus tilauksen uusimisesta"}},gq={global:fq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie-moduuli","searchPlaceholder":"Etsi tilauksia...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Hyvitys Mollien kautta","shipThroughMollie":"Toimita Mollien kautta","cancelMollieItem":"Peruuta Mollien kautta"},"config":{"info":{"title":"Hei {userName}, Tervetuloa Mollieen!","descriptionTop":"Mollien käyttöönotto on helppoa!","descriptionBottom":"Siinä se!","descriptionFooter":"Jos haluat lukea lisää laajennuksistamme, vieraile virallisella asiakirjasivullamme.","onboardingStep1":"Luo Mollie-tili.","onboardingStep2":"Syötä API-avaimesi alla olevaan osioon.","onboardingStep2TestMode":"Ota käyttöön 'Test Mode', jos haluat testata vain maksuja.","onboardingStep3":"Määritä maksutavat myyntikanavallesi.","onboardingStep3Link":"myyntikanavillesi","btnDocumentation":"Asiakirjat","btnRequestSupport":"Tuki","btnTroubleshooting":"Vianetsintäopas"},"api":{"apiLinkButton":"Hanki API-avaimesi Mollie-hallintapaneelista","testButton":"Test API-avaimet","testApiKeys":{"title":"Mollie Payments","apiKey":"API-avain","isValid":"on voimassa","isInvalid":"on virheellinen"}},"payments":{"format":{"placeholder":"Paikkamerkki","preview":"Esikatselu"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Päivitä maksutavat","succeeded":"Maksutavat on päivitetty onnistuneesti.","failed":"Maksutapoja ei voitu päivittää."},"mollieLimits":{"link":"Näytä Mollien saatavuus säännöt maksutavoille"}},"rounding":{"info1":"Shopware voi käyttää valuutta-asetuksia laskeakseen, kuinka se pyöristää tilauksen loppusumman. Tämä sisältää tuotteen hinnan desimaalien määrän ja lähimmän pyöristysvälin, kuten 0,50 tai 1,00.","info2":"Nämä asetukset voivat johtaa erilaiseen loppusummaan kuin rivikohtien kokonaissumma. Kun Mollie tarkistaa nämä summat ja huomaa, että ne eivät täsmää, se aiheuttaa kassavirheen.","info3":"Voit käyttää tätä ominaisuutta välttääksesi pyöristysongelmia kassalla. Kun se on käytössä, se lisää erillisen rivikohdan Mollie-hallintapaneeliin pyöristyksen eroa varten, ja asiakkaasi maksavat Shopwaren laskeman loppusumman."},"order":{"bankTransferDueDateKlarnaLimitReached":"Ei ole mahdollista käyttää Klarna Pay now, Klarna Slice it tai Klarna Pay later -menetelmää, kun vanhenemispäiväsi on yli 28 päivän päässä, ellei kauppiaan ja Klarnan välillä olla sovittu muuta maksimiarvoa.","bankTransferDueDateLimitReached":"Tilauksen kestoaikaa ei voi asettaa yli 100 päivää pidemmäksi."},"support":{"modalTitle":"Pyydä tukea Mollielta","btnCancel":"Peruuta","btnConfirm":"Pyydä tukea","btnSupport":"Lisää tietoa tuestamme","form":{"name":"Nimesi","email":"Sähköpostisi","recipient":"Lähetä pyyntö osoitteeseen","subject":"Aihe","message":"Viesti"},"data":{"header":"Data lähetetty Mollielle:","other":"Muu:","shopwareVersion":"Shopware-versio","pluginLogs":"{plugin} lokitiedostot","pluginConfiguration":"{plugin} konfiguraatio","pluginConfigurationHelpText":"API-avaimet ovat suljettu pois.","paymentMethods":"Maksutavan tiedot","paymentMethodsHelpText":"Sisältää tiedot aktiivisista maksutavoista, jotka on määritetty kullekin myyntikanavalle, sekä niiden tilan Mollie-tililläsi."},"success":"Tukipyyntö on lähetetty onnistuneesti. Teemme parhaamme vastataksemme sinulle mahdollisimman pian","error":"Sähköpostin lähettämisessä Shopwaren kautta ilmeni ongelma. Yritä uudelleen tai ota yhteyttä suoraan sähköpostitse."}},"rules":{"itemSubscriptionRule":"Tuote on tilaus (Mollie)","cartSubscriptionRule":"Ostoskärry, jossa on tilauksia (Mollie)"},"refunds":{"status":{"queued":"Jonossa","pending":"Odottaa","processing":"Käsittelyssä","refunded":"Hyvitetty","failed":"Epäonnistunut","description":{"queued":"Hyvitys on jonossa, kunnes saldoa on riittävästi hyvityksen käsittelyyn. Voit silti peruuttaa hyvityksen.","pending":"Hyvitys lähetetään pankkiin seuraavana arkipäivänä. Voit silti peruuttaa hyvityksen.","processing":"Hyvitys on lähetetty pankkiin. Hyvityssumma siirretään kuluttajan tilille mahdollisimman pian.","refunded":"Hyvityssumma on siirretty kuluttajalle.","failed":"Hyvitys epäonnistui käsittelyn jälkeen. Esimerkiksi asiakas on sulkenut pankkitilinsä. Varat palautetaan tilillesi."}}},"refund-manager":{"general":{"unitQuantity":"kpl."},"acl":{"warningCreate":"Sinulla ei ole oikeuksia luoda hyvityksiä","warningCancel":"Sinulla ei ole oikeuksia peruuttaa hyvityksiä"},"cart":{"title":"Tilaus ##orderNumber##","btnSelectAll":"Valitse kaikki","btnResetForm":"Nollaa lomake","linkHowTo":"Kuinka käyttää tätä lomaketta?","grid":{"columns":{"item":"Tuote","productNumber":"Tuotenumero","unitPrice":"Yksikköhinta","quantity":"Määrä","refunded":"Hyvitetty","refundQuantity":"Hyvitys","totalPrice":"Yhteensä","refundAmount":"Hyvitys","resetStock":"Nollaa varasto"},"btnResetLine":"Nollaa rivi","checkDeductPromotion":"Vähennä alennusta","checkRefundTax":"Hyvitä ALV"},"roundDiffItemAdded":"Automaattinen pyöristysrivi lisättiin"},"instructions":{"linkResetTutorials":"Nollaa oppat","btnToggleTutorial":"Näytä/piilota opas","titleFullRefund":"Kokonaishyvitys","textFullRefund":"Käytä vain painiketta tehdäksesi täyden hyvityksen. Tämä varmistaa, että kaikki tuotteet merkitään hyvitetyiksi ja koko summa palautetaan asiakkaalle.","titleStockReset":"Varaston nollaus","textStockReset":"Voit automaattisesti lisätä käytettävissä olevaa varastoa syöttämällä määrän, jonka haluat palauttaa varastoon. Syötä se ennen kuin jatkat täyden tai osittaisen hyvityksen kanssa. Varaston nollaus voidaan yhdistää joustavasti varsinaiseen palautusprosessiin.","titleShipping":"Toimitus","textShipping":"Toimituksessa olevat tuotteet voidaan palauttaa kuten mikä tahansa muu tuote. Syötä joko koko määrä tai mukautettu osasumma ja jatka hyvitystä. Toimituskulujen hyvitys voidaan yhdistää joustavasti tuotteiden varsinaiseen palautusprosessiin.","titlePartialAmount":"Osittainen hyvitys (vain summa)","textPartialAmount":"Syötä vain osasumma tekstikenttään ja aloita hyvitys.","titlePartialItems":"Osittainen hyvitys (tuotteiden kanssa)","textPartialItems":"Jos haluat merkitä määrät ja tuotteet hyvitetyiksi Molliessa, käytä yllä olevaa lomaketta. Syötä määrät ja anna mukautettu summa jokaiselle hyvitettävälle tuotteelle. Kokonaissumma näkyy sitten lopullisen hyvityssumman tekstikentässä. Muista, että tätä lopullista summaa on edelleen mahdollista muuttaa ennen hyvityksen aloittamista.","titlePartialPromotions":"Osittainen hyvitys (sisältäen alennukset)","textPartialPromotions":"Jos ostoskorissasi on tarjous, tarjous on erillinen rivikohta. Jos haluat hyvittää kaikki alennetut tuotteet, jatka ja hyvitä niiden kokonaisarvot ja koko tarjousrivikohta. Jos kuitenkin haluat hyvittää vain tiettyjä alennettuja tuotteita, voit vähentää sovelletun alennuksen automaattisesti jokaisesta rivikohdasta. Voit aina muuttaa arvoja, jos ne eivät ole oikein.","titleRoundingDiff":"Pyöristysero","textRoundingDiff":"Kokonaishyvitys sisältää pyöristyseron"},"summary":{"dataLoading":"Tietoja ladataan...","headerExcludingVat":"Ei sisällä alv.","headerIncludingVat":"Sis. ALV","captionTotal":"Yhteensä","captionTotalTaxFree":"Yhteensä","captionPendingRefunds":"Odottaa hyvitystä","captionVouchers":"Kupongin arvo","captionRefunded":"Hyvitetty summa","captionRemaining":"Hyvitettävä summa","btnFixDiff":"Korjaa ero","placeholderDescription":"Syötä pankki-/korttiotteen kuvaus kuluttajalle. Max 140 merkkiä","lblDescription":"Kuvaus (valinnainen) ({characters}/140 merkkiä)","descriptionHelp":"Tämä näkyy mahdollisuuksien mukaan kuluttajan pankki- tai korttiotteella. Viesti katkaistaan ​​140 merkin jälkeen.","placeholderInternalDescription":"Syötä sisäinen kuvaus","lblInternalDescription":"Sisäinen kuvaus (valinnainen)","internalDescriptionHelp":"Tämä näytetään paikallisena kuvauksena hallintoliittymässä.","checkVerification":"Olen tarkistanut palautuksen kokonaissumman ja määritetyt määrät hyvitettäväksi ja varastoitavaksi.","btnRefund":"Hyvitys","btnFullRefund":"Täysi hyvitys","roundDiffItemAdded":"Pyöristyskohde"},"refunds":{"title":"Hyvitykset Mollie-hallintapaneelissa","linkMore":"Lisää tietoa hyvityksistä","grid":{"columns":{"amount":"Summa","status":"Tila","description":"Kuvaus","internalDescription":"Sisäinen kuvaus","composition":"Rakenne","date":"Päivämäärä"},"lblNoComposition":"Ei käytettävissä olevaa rakennetta","btnCancelRefund":"Peruuta tämä hyvitys"}},"notifications":{"success":{"refund-created":"Hyvitys on luotu Molliessa. Hyvityksen suorittaminen voi kestää 2 tuntia. Tähän asti voit peruuttaa hyvityksen.","refund-canceled":"Odottava hyvitys on onnistuneesti peruutettu ja poistettu."},"error":{"low-amount":"Ole hyvä ja syötä hyvitettävä määrä.","refund-created":"Jokin meni pieleen hyvitystä luotaessa.","refund-canceled":"Hyvityksen peruuttamisessa oli ongelma. Ole hyvä ja yritä uudelleen Mollie-hallintapaneelissa."}}},"vouchers":{"CARD_TITLE":"Kuponki","VOUCHER_INFO_TITLE":"Kuponkimaksut","VOUCHER_INFO_DESCRIPTION":"Mollien avulla voit helposti hyväksyä maksuja verkkokaupassasi käyttämällä eko-, lahja- ja ateriaseteleitä – fiksu valinta myynnin lisäämiseen ja asiakkaiden tyytyväisyyteen. Maksutapa \\"kunponki\\" näkyy vain, jos ostoskorissa on vähintään 1 tuote, jolle on määritetty kuponkityyppi.","VOUCHER_INFO_DEFAULTLANGUAGE":"Huomaa, että tätä rakennetta voidaan muokata vain oletuskielelläsi. Vaihda kieli muuttaaksesi tämän tuotteen kuponkityyppiä.","VOUCHER_BTN_READMORE":"Lue lisää","VOUCHER_TYPE_CAPTION":"Tuotteen kuponkityyppi","VOUCHER_TYPE_VALUE_NONE":"Ei mitään","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Ateria","VOUCHER_TYPE_VALUE_VOUCHER":"Lahja"},"modals":{"shipping":{"title":"Toimita Mollien kautta","item":{"label":"Tuote:","noQuantity":"Ole hyvä ja syötä lähettävä määrä.","shipAll":"Toimita kaikki","summary":{"quantity":"Lähetys määrä","shipped":"Lähetetty määrä","shippable":"Toimitettava määrä"},"success":"Tilaus on toimitettu onnistuneesti."},"order":{"description":"Seuraavat tuotemäärät toimitetaan.","itemHeader":"Tuote","quantityHeader":"Määrä","originalQuantityHeader":"Määrä (toimitettavissa)"},"availableTracking":{"label":"Saatavilla olevat seurantakoodit","hint":"Täytä kaikki tiedot automaattisesti napsauttamalla jotakin näistä seurantakoodeista."},"showTracking":"Lisää seurantatietoja tälle lähetykselle","tracking":{"carrier":"Kuriiri","code":"Koodi","url":"Url","invalid":"Syötä sekä kuriiri että koodi"},"confirmButton":"Toimita tilaus","cancelButton":"Peruuta","selectAllButton":"Valitse kaikki","resetButton":"Nollaa"},"cancel":{"title":"Peruuta tuote Mollien kautta","confirmButton":"Peruuta tuote Mollien kautta","cancelButton":"Sulje modaali","resetStock":"Nollaa varastot","item":{"success":"Tuote on peruutettu onnistuneesti","failed":{"quantityZero":"Määrä on 0","invalidLine":"Tuotetta ei ole tilauksessa","quantityTooHigh":"Määrä on liian suuri"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Toimita tilaus (Mollie)","description":"Toimita tilaus Molliessa."},"modal":{"title":"Toimita tilaus","description":"Tämä toiminto lähettää tilauksen automaattisesti Mollien kautta. Prosessointijärjestelmä vastaanottaa tilausnumeron ja välittää sen Mollie API:lle. Onnistuneet ja epäonnistuneet lähetykset näkyvät Mollien lokitiedostoissa.","warningConfig":"Varmista, että samantyyppisille toiminnoille ei ole käytössä muita automaatioita häiriöiden välttämiseksi.\\nSeuraavat tämän laajennuksen aktivoidut ominaisuudet saattavat häiritä tätä toimintoa:","noWarnings":"Ei varoituksia"}},"refundOrder":{"editor":{"title":"Hyvitä tilaus (Mollie)","description":"Hyvitä tilaus Mollien kautta."},"modal":{"title":"Hyvitä tilaus","description":"Tämä toiminto aloittaa automaattisesti hyvityksen Mollien kautta. Prosessijärjestelmä vastaanottaa tilausnumeron ja välittää sen Mollien API:lle. Onnistuneet hyvitykset ja epäonnistuneet hyvitykset näkyvät Mollien lokitiedostoissa.","warning":"Huomaa, että hyvitysten viimeistely ja näkyminen kaupassa voi kestää jopa 2 tuntia. Siihen asti voit peruuttaa odottavan hyvityksen joko Shopwaren tilaussivulta tai Mollie-hallintapaneelista.","warningConfig":"Varmista, että samantyyppisille toimille ei ole käytössä muita automaatioita häiriöiden välttämiseksi."}},"warnings":{"automaticShipping":"Automaattinen toimitus laajennusmäärityksessä"}}},"subscriptions":{"status":{"pending":"Odottaa","active":"Aktiivinen","canceled":"Peruutettu","suspended":"Keskeytetty","completed":"Suoritettu","paused":"Pysäytetty","resumed":"Jatkettu","skipped":"Ohitettu"},"navigation":{"title":"Mollie-tilaukset"},"TYPE_DAYS":"Päivä(t)","TYPE_WEEKS":"Viikko(t)","TYPE_MONTHS":"Kuukausi/kuukaudet","confirm":{"cancelTitle":"Lopeta tilaus?","cancel":"Peruuta asiakkaasi tilaus.","pauseTitle":"Keskeytä tilaus?","pause":"Laita tilaus pysäytetään, kunnes jatkat sitä uudelleen.","resumeTitle":"Jatketaanko tilausta?","resume":"Jatka tilausta uudelleen.","skipTitle":"Ohita seuraava erä?","skip":"Ohita tilauksen seuraava erä. Se jatkuu automaattisesti sen jälkeen."},"alerts":{"cancelSuccess":"Tilaus on peruutettu onnistuneesti","pauseSuccess":"Tilaus on keskeytetty onnistuneesti","resumeSuccess":"Tilausta on jatkettu onnistuneesti","skipSuccess":"Tilaus on ohitettu onnistuneesti. Seuraava maksu on päivitetty."},"list":{"title":"Mollie-tilaukset","columns":{"customer":"Asiakas","status":"Tila","description":"Kuvaus","amount":"Summa","nextPaymentAt":"Seuraava maksu","prePaymentReminder":"Muistutettu","canceledAt":"Peruutettu","createdAt":"Luotu"},"action":{"edit":"Muokkaa tilausta"},"deletedCustomer":"Poistettu asiakas"},"detail":{"title":"Mollie-tilaus","buttonCancelSubscription":"Peruuta tilaus","labelDescription":"Kuvaus","labelAmount":"Summa","labelQuantity":"Määrä","labelMollieSubscription":"Mollie-tilaus","labelMollieCustomer":"Mollie-asiakas","labelMandateId":"Valtuutus","labelShopwareCustomer":"Shopware-asiakas","labelCreatedAt":"Luotu","buttonShowShopwareOrder":"Näytä Shopware-tilaus","buttonShowShopwareCustomer":"Näytä Shopware-asiakas","cardTitleSubscription":"Tilaus","cardTitleStatus":"Tila","labelStatus":"Tila","labelNextPaymentAt":"Seuraava maksu","labelLastRemindedAt":"Viimeksi muistutettu","labelCanceledAt":"Peruutettu","buttonPauseSubscription":"Keskeytä tilaus","buttonResumeSubscription":"Jatka tilausta","buttonSkipSubscription":"Ohita tilaus","history":{"cardTitle":"Historia","colDate":"Päivämäärä","colComment":"Kommentti","colStatusFrom":"Tila (alkaen)","colStatusTo":"Tila (asti)","colMollieSubscription":"Mollie-tilaus"}},"product":{"card-title":"Tilaus","title":"Mollie-tilaukset","description":"Toistuvien maksujesi hallinta on helpompaa kuin koskaan hyödyllisten ominaisuuksiemme ansiosta. Vie yrityksesi uudelle tasolle tehokkailla seurantavaihtoehdoilla, yksinkertaisilla integroinneilla ja monilla muilla tavoilla. Mollie-tilausten avulla voit helposti luoda tilaustuotteita ja ajoittaa toistuvia maksuja suoritettavaksi määritetyllä aikavälillä ja ajanjaksolla.","mollieSubscriptionProduct":"Tilaustuote","mollieSubscriptionIntervalAmount":"Toista maksu joka","mollieSubscriptionIntervalType":"Aikaväliyksikkö","mollieSubscriptionRepetitionAmount":"Toistojen määrä","mollieSubscriptionRepetitionPlaceholder":"Syötä numero tai jätä tyhjäksi","infoDefaultLanguage":"Huomaa, että tätä rakennetta voidaan muokata vain oletuskielelläsi. Vaihda kielesi, jotta voit muokata tämän tuotteen tilaushallinnan.","btnReadMore":"Lue lisää"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Tilaus"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Luottokorttitiedot",buttonMolliePaymentLink:"Kopioi leikepöydälle",columnRefunded:"Hyvitetty",columnShipped:"Toimitettu",columnCanceled:"Peruutettu",labelMollieOrderId:"Mollie-tilaustunnus",labelMollieThirdPartyPaymentId:"Maksuviite",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Hyvitetty summa",totalRefundsPending:"Odottaa hyvitystä",totalRemaining:"Hyvitettävä summa",totalVouchers:"Kuponkimäärä",totalShipments:"Toimitettu määrä ({quantity} tuotetta)",subscriptionBadge:"Tilaus",refundManager:{title:"Mollie-hyvityshallinta",btnOpenRefundManager:"Avaa hyvityshallinta",btnCloseRefundManager:"Sulje hyvityshallinta"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Suositeltu iDeal-myöntäjä"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Hyvityshallinta"},mollie_subscription:{label:"Tilaukset"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Kuvaus"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Hyvitys",subscription:"Tilaus",webhookReceived:"Webhook",status:"Tila",started:"Aloitettu",ended:"Päättynyt",paused:"Keskeytetty",renewalReminder:"Uusimismuistutus",renewed:"Uusittu",resumed:"Jatkettu",skipped:"Ohitettu",all:"Kaikki",canceled:"Peruutettu",expired:"Vanhentunut",partiallyRefunded:"Hyvitetty (osittain)",orderSuccess:"Tilaus onnistui",orderFailed:"Tilaus epäonnistui",orderCanceled:"Tilaus peruutettu"}}},hq={entities:{mollie_subscription:"Mollie Abonnement | Mollie Abonnementer"},businessEvents:{mollie_checkout_order_success:" Bestilling gennemført",mollie_checkout_order_failed:" Bestilling mislykkedes",mollie_checkout_order_canceled:" Bestilling annulleret",mollie_webhook_received_All:" Mollie Webhook Modtaget (Alle)",mollie_webhook_received_status_authorized:" Mollie Webhook Modtaget (Autoriseret)",mollie_webhook_received_status_failed:" Mollie Webhook Modtaget (Mislykkedes)",mollie_webhook_received_status_canceled:" Mollie Webhook Modtaget (Annulleret)",mollie_webhook_received_status_expired:" Mollie Webhook Modtaget (Udløbet)",mollie_webhook_received_status_pending:" Mollie Webhook Modtaget (Afventer)",mollie_webhook_received_status_paid:" Mollie Webhook Modtaget (Betalt)",mollie_webhook_received_status_completed:" Mollie Webhook Modtaget (Færdiggjort)",mollie_webhook_received_status_refunded:" Mollie Webhook Modtaget (Refunderet)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Modtaget (Delvist Refunderet)",mollie_refund_started:" Mollie refundering igangsat",mollie_subscription_started:" Mollie abonnement startet",mollie_subscription_ended:" Mollie abonnement færdiggjort",mollie_subscription_cancelled:" Mollie abonnement annulleret",mollie_subscription_paused:" Mollie abonnement sat på pause",mollie_subscription_resumed:" Mollie abonnement genoptaget",mollie_subscription_skipped:" Mollie abonnement sprunget over",mollie_subscription_renewed:" Mollie abonnement fornyet",mollie_subscription_renewal_reminder:" Mollie påmindelse om fornyelse af abonnement"}},bq={global:hq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Søg abonnementer...","general":{"mainMenuItemGeneral":"Mollie Betalinger","descriptionTextModule":"Mollie Betalinger","btnMollieActions":"Mollie Handlinger","refundThroughMollie":"Refunder gennem Mollie","shipThroughMollie":"Send gennem Mollie","cancelMollieItem":"Annuller gennem Mollie"},"config":{"info":{"title":"Hej {userName}, Velkommen til Mollie!","descriptionTop":"Onboarding er enkelt med Mollie!","descriptionBottom":"Det er det!","descriptionFooter":"Hvis du vil lære mere om vores plugin, så besøg venligst vores officielle dokumentationsside.","onboardingStep1":"Tilmeld dig en Mollie Konto.","onboardingStep2":"Indtast dine API-nøgler i sektionen nedenfor.","onboardingStep2TestMode":"Aktiver 'Testmode', hvis du kun vil teste betalinger.","onboardingStep3":"Tildel betalingsmetoder til din salgskanal.","onboardingStep3Link":"til dine salgskanaler","btnDocumentation":"Dokumentation","btnRequestSupport":"Support","btnTroubleshooting":"Fejlfinding Guide"},"api":{"apiLinkButton":"Hent dine API-nøgler fra Mollie Dashboard","testButton":"Test API-nøgler","testApiKeys":{"title":"Mollie Betalinger","apiKey":"API-nøgle","isValid":"er gyldig","isInvalid":"er ugyldig"}},"payments":{"format":{"placeholder":"Pladsholder","preview":"Forhåndsvisning"},"updatePaymentMethods":{"title":"Mollie Betalinger","button":"Opdater betalingsmetoder","succeeded":"Betalingsmetoderne er blevet opdateret.","failed":"Betalingsmetoderne kunne ikke opdateres."},"mollieLimits":{"link":"Vis mollie tilgængelighedsregler for betalingsmetoder"}},"rounding":{"info1":"Shopware kan bruge valutaindstillinger til at beregne, hvordan den afrunder den samlede ordre. Dette inkluderer antallet af decimaler i priserne på dine produkter og det nærmeste afrundingsinterval, som f.eks. 0,50 eller 1,00.","info2":"Disse indstillinger kan føre til et andet samlet beløb end den totale sum af linjeposterne. Når Mollie krydstjekker disse beløb og finder, at de ikke stemmer overens, forårsager det en fejl ved kassen.","info3":"Du kan bruge denne funktion til at undgå afrundingsproblemer ved kassen. Når den er aktiveret, tilføjer den et separat linjepunkt i dit Mollie Dashboard for forskellen i afrunding, og dine kunder betaler det samlede beløb beregnet af Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det er ikke muligt at bruge Klarna Betal nu, Klarna Delbatalinger eller Klarna Betal senere som metode, når din udløbsdato er mere end 28 dage frem, medmindre en anden maksimumsperiode er aftalt mellem forhandleren og Klarna.","bankTransferDueDateLimitReached":"Det er ikke muligt at sætte bestillingens levetid højere end 100 dage."},"support":{"modalTitle":"Anmod om support fra Mollie","btnCancel":"Annuller","btnConfirm":"Anmod om support","btnSupport":"Mere om vores support","form":{"name":"Dit navn","email":"Din e-mail","recipient":"Send anmodning til","subject":"Emne","message":"Besked"},"data":{"header":"Data sendt til Mollie:","other":"Andre:","shopwareVersion":"Shopware-version","pluginLogs":"{plugin} logfiler","pluginConfiguration":"{plugin} konfiguration","pluginConfigurationHelpText":"API-nøgler er udelukket.","paymentMethods":"Betalingsmetode-data","paymentMethodsHelpText":"Indeholder oplysninger om, hvilke betalingsmetoder der er aktive, tildelt hver salgskanal, samt deres status på din Mollie-konto."},"success":"Supportanmodningen er sendt. Vi gør vores bedste for at svare så hurtigt som muligt","error":"Der opstod et problem ved afsendelse af mailen gennem Shopware. Forsøg venligst igen eller kontakt os direkte via e-mail."}},"rules":{"itemSubscriptionRule":"Varen er abonnement (Mollie)","cartSubscriptionRule":"Kurv med abonnementer (Mollie)"},"refunds":{"status":{"queued":"I kø","pending":"Afventer","processing":"Behandles","refunded":"Refunderet","failed":"Mislykkedes","description":{"queued":"Refusionen er sat i kø, indtil der er tilstrækkelig saldo til at behandle refusionen. Du kan stadig annullere refusionen.","pending":"Refusionen sendes til banken den næste arbejdsdag. Du kan stadig annullere refusionen.","processing":"Refusionen er blevet sendt til banken. Refusionsbeløbet vil blive overført til forbrugerens konto så hurtigt som muligt.","refunded":"Refusionsbeløbet er blevet overført til forbrugeren.","failed":"Refusionen mislykkedes efter behandling. For eksempel har kunden lukket sin bankkonto. Midlerne vil blive returneret til din konto."}}},"refund-manager":{"general":{"unitQuantity":"stk."},"acl":{"warningCreate":"Du har ikke tilladelse til at oprette refusioner","warningCancel":"Du har ikke tilladelse til at annullere refusioner"},"cart":{"title":"Ordre ##orderNumber##","btnSelectAll":"Vælg Alle","btnResetForm":"Nulstil Formular","linkHowTo":"Hvordan bruger jeg denne formular?","grid":{"columns":{"item":"Vare","productNumber":"Produktnummer","unitPrice":"Enhedspris","quantity":"Antal","refunded":"Refunderet","refundQuantity":"Refusion","totalPrice":"Total","refundAmount":"Refusion","resetStock":"Nulstil Lager"},"btnResetLine":"Nulstil Linje","checkDeductPromotion":"Træk rabat fra","checkRefundTax":"Refusion af moms"},"roundDiffItemAdded":"Automatisk afrundingspost blev tilføjet"},"instructions":{"linkResetTutorials":"Nulstil Vejledninger","btnToggleTutorial":"Vis/Skjul Vejledning","titleFullRefund":"Fuld Refusion","textFullRefund":"Brug knappen til fuld refusion. Dette sikrer, at alle dine elementer markeres som refunderet, og det fulde beløb returneres til kunden.","titleStockReset":"Nulstilling af lager","textStockReset":"Du kan automatisk øge det tilgængelige lager ved at indtaste den mængde, du ønsker at sætte tilbage i lageret. Indtast det før du går videre med en fuld eller delvis refusion. Nulstilling af lageret kan kombineres fleksibelt med selve refusionsprocessen.","titleShipping":"Forsendelse","textShipping":"Forsendelsesvarer kan refunderes som enhver anden produktvare. Indtast enten den samlede mængde eller et tilpasset delbeløb, og fortsæt med refusionen. Refusion af forsendelsesomkostninger kan kombineres fleksibelt med den faktiske refusionsproces for varer.","titlePartialAmount":"Delvis Refusion (kun beløb)","textPartialAmount":"Indtast blot det delvise beløb i tekstfeltet og start refusionen.","titlePartialItems":"Delvis Refundering (med varer)","textPartialItems":"Hvis du vil markere mængder og varer som refunderet i Mollie, skal du bruge formularen ovenfor. Indstil dine mængder og angiv et tilpasset beløb for hver vare, der skal refunderes. Den totale sum vil derefter være synlig i tekstfeltet for det endelige refundbeløb. Husk, at det stadig er muligt at justere dette endelige beløb, før du starter din refundering.","titlePartialPromotions":"Delvis Refundering (med rabatter)","textPartialPromotions":"Hvis du har en rabat i din indkøbskurv, så er din rabat en separat linjepost. Hvis du ønsker at refundere alle rabatterede varer, skal du gå videre og refundere deres samlede værdier samt hele kampagnelinjen. Hvis du kun ønsker at refundere nogle varer, der var rabatterede, kan du automatisk trække den anvendte rabat fra for hver enkelt linjepost. Du kan selvfølgelig altid ændre værdierne, hvis de ikke er korrekte.","titleRoundingDiff":"Afrundingsforskel","textRoundingDiff":"En fuld refundering vil inkludere afrundingsforskelle"},"summary":{"dataLoading":"Data indlæses...","headerExcludingVat":"Ekskl. moms","headerIncludingVat":"Inkl. moms","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Venter på at blive refunderet","captionVouchers":"Voucherbeløb","captionRefunded":"Refunderet beløb","captionRemaining":"Refunderbart beløb","btnFixDiff":"Ret forskel","placeholderDescription":"Indtast bank/kortudskrift for forbrugeren. Max 140 tegn","lblDescription":"Beskrivelse (valgfrit) ({characters}/140 tegn)","descriptionHelp":"Dette vil blive vist på forbrugerens bank- eller kortudskrift, når det er muligt. Beskeden vil blive afkortet efter 140 tegn.","placeholderInternalDescription":"Indtast din interne beskrivelse","lblInternalDescription":"Intern beskrivelse (valgfrit)","internalDescriptionHelp":"Dette vil blive vist som en lokal beskrivelse i administrationsgrænsesnittet.","checkVerification":"Jeg har bekræftet det samlede refusionsbeløb og de konfigurerede mængder, der skal refunderes og genlagres.","btnRefund":"Refusion","btnFullRefund":"Fuld Refundering","roundDiffItemAdded":"Afrundingspost"},"refunds":{"title":"Refusioner i Mollie Dashboard","linkMore":"Mere om refusioner","grid":{"columns":{"amount":"Beløb","status":"Status","description":"Beskrivelse","internalDescription":"Intern beskrivelse","composition":"Sammensætning","date":"Dato"},"lblNoComposition":"Ingen sammensætning tilgængelig","btnCancelRefund":"Annuller denne refundering"}},"notifications":{"success":{"refund-created":"En refundering er blevet oprettet i Mollie. Det kan tage 2 timer for refunderingen at blive fuldført. Indtil da kan du annullere refunderingen.","refund-canceled":"Den ventende refundering er blevet annulleret og fjernet."},"error":{"low-amount":"Indtast venligst et beløb, der skal refunderes.","refund-created":"Noget gik galt, da der blev oprettet en refundering.","refund-canceled":"Der opstod et problem ved annullering af den ventende refundering. Prøv venligst igen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vouchere","VOUCHER_INFO_TITLE":"Voucher betalinger","VOUCHER_INFO_DESCRIPTION":"Mollie lader dig nemt acceptere betalinger i din online butik ved brug af Eco-, gave- og måltid vouchers — et smart valg til at øge salget og tilfredsstille dine kunder. Betalingsmetoden \\"voucher\\" er kun synlig, hvis du har mindst 1 produkt med en tildelt vouchertype i indkøbskurven.","VOUCHER_INFO_DEFAULTLANGUAGE":"Bemærk, at denne konfiguration kun kan redigeres på dit standardsprog. Venligst skift dit sprog for at ændre vouchertypen for dette produkt.","VOUCHER_BTN_READMORE":"Læs mere","VOUCHER_TYPE_CAPTION":"Vouchertype for produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Måltid","VOUCHER_TYPE_VALUE_VOUCHER":"Gave"},"modals":{"shipping":{"title":"Send gennem Mollie","item":{"label":"Vare:","noQuantity":"Indtast venligst en mængde til forsendelse.","shipAll":"Send alt","summary":{"quantity":"Mængde til forsendelse","shipped":"Mængde sendt","shippable":"Mængde der kan sendes"},"success":"Bestillingen er blevet sendt."},"order":{"description":"Følgende varemængder vil blive sendt.","itemHeader":"Vare","quantityHeader":"Mængde","originalQuantityHeader":"Mængde (til forsendelse)"},"availableTracking":{"label":"Tilgængelige sporingskoder","hint":"Klik på en af disse sporingskoder for automatisk at udfylde alle data."},"showTracking":"Tilføj sporingsinfo for denne forsendelse","tracking":{"carrier":"Transportør","code":"Kode","url":"URL","invalid":"Indtast både Transportør og Kode"},"confirmButton":"Send ordre","cancelButton":"Annuller","selectAllButton":"Vælg alle","resetButton":"Nulstil"},"cancel":{"title":"Annuller vare gennem Mollie","confirmButton":"Annuller vare gennem Mollie","cancelButton":"Luk modal","resetStock":"Nulstil lager","item":{"success":"Produkt blev annulleret","failed":{"quantityZero":"Mængden er 0","invalidLine":"Produktet findes ikke i ordren","quantityTooHigh":"Mængden er for høj"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Send ordre (Mollie)","description":"Send ordre i Mollie."},"modal":{"title":"Send ordre","description":"Denne handling vil automatisk sende en ordre gennem Mollie. Flow sekvensen vil modtage ordrenummeret og sende dette videre til Mollie API. Vellykkede forsendelser og mislykkede forsendelser vil være synlige i Mollies logfiler.","warningConfig":"Venligst sørg for at deaktivere alle yderligere automatiseringer for denne type handling for at undgå forstyrrelser.\\nDe følgende aktiverede funktioner i denne plugin kan interferere med denne handling:","noWarnings":"Ingen advarsler"}},"refundOrder":{"editor":{"title":"Refunder ordre (Mollie)","description":"Refunder ordre gennem Mollie."},"modal":{"title":"Refunder ordre","description":"Denne handling vil automatisk starte en refundering gennem Mollie. Flow sekvensen vil modtage ordrenummeret og sende dette videre til Mollie API. Vellykkede refusioner og mislykkede refusioner vil være synlige i Mollies logfiler.","warning":"Venligst husk, at refusioner kan tage op til 2 timer at blive afsluttet og synlige i butikken. Indtil da kan du altid annullere en ventende refusion enten fra ordren siden i Shopware eller fra Mollie Dashboard.","warningConfig":"Venligst sørg for at deaktivere enhver yderligere automatisering for denne type handling for at undgå forstyrrelser."}},"warnings":{"automaticShipping":"Automatisk forsendelse i plugin konfiguration"}}},"subscriptions":{"status":{"pending":"Afventer","active":"Aktiv","canceled":"Annulleret","suspended":"Suspenderet","completed":"Færdiggjort","paused":"Sat på pause","resumed":"Genoptaget","skipped":"Sprunget over"},"navigation":{"title":"Mollie Abonnementer"},"TYPE_DAYS":"Dag(e)","TYPE_WEEKS":"Uge(r)","TYPE_MONTHS":"Måned(er)","confirm":{"cancelTitle":"Afslut abonnement?","cancel":"Annuller din kundes abonnement.","pauseTitle":"Pause abonnement?","pause":"Sæt abonnementet på pause, indtil du genoptager det igen.","resumeTitle":"Genoptag abonnement?","resume":"Fortsæt abonnementet igen.","skipTitle":"Spring næste rate over?","skip":"Spring den næste rate i abonnementet over. Det fortsætter automatisk herefter."},"alerts":{"cancelSuccess":"Abonnementet er blevet annulleret","pauseSuccess":"Abonnementet er blevet sat på pause","resumeSuccess":"Abonnementet er blevet genoptaget","skipSuccess":"Abonnementet er blevet sprunget over. Den næste betaling er blevet opdateret."},"list":{"title":"Mollie Abonnementer","columns":{"customer":"Kunde","status":"Status","description":"Beskrivelse","amount":"Beløb","nextPaymentAt":"Næste betaling","prePaymentReminder":"Påmindet ved","canceledAt":"Annulleret ved","createdAt":"Oprettet ved"},"action":{"edit":"Rediger abonnement"},"deletedCustomer":"Slettet kunde"},"detail":{"title":"Mollie abonnement","buttonCancelSubscription":"Annuller abonnement","labelDescription":"Beskrivelse","labelAmount":"Beløb","labelQuantity":"Antal","labelMollieSubscription":"Mollie abonnement","labelMollieCustomer":"Mollie kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware kunde","labelCreatedAt":"Oprettet ved","buttonShowShopwareOrder":"Vis Shopware ordre","buttonShowShopwareCustomer":"Vis Shopware kunde","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Næste betaling ved","labelLastRemindedAt":"Sidst påmindet ved","labelCanceledAt":"Annulleret ved","buttonPauseSubscription":"Sæt abonnement på pause","buttonResumeSubscription":"Genoptag abonnement","buttonSkipSubscription":"Spring abonnement over","history":{"cardTitle":"Historik","colDate":"Dato","colComment":"Kommentar","colStatusFrom":"Status (fra)","colStatusTo":"Status (til)","colMollieSubscription":"Mollie abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie abonnementer","description":"At håndtere dine gentagne betalinger er lettere end nogensinde med vores nyttige funktioner. Tag din virksomhed til næste niveau med effektive sporingsmuligheder, enkle integrationer og mere. Med Mollie abonnementer kan du nemt oprette abonnementsprodukter og planlægge gentagne betalinger til at finde sted på det konfigurerede interval og periode.","mollieSubscriptionProduct":"Abonnementsprodukt","mollieSubscriptionIntervalAmount":"Gentag betaling hver","mollieSubscriptionIntervalType":"Interval enhed","mollieSubscriptionRepetitionAmount":"Antal gentagelser","mollieSubscriptionRepetitionPlaceholder":"Indtast nummer eller efterlad tomt","infoDefaultLanguage":"Bemærk venligst, at denne konfiguration kun kan redigeres på dit standardsprog. Skift venligst dit sprog for at ændre abonnementsindstillingerne for dette produkt.","btnReadMore":"Læs mere"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kreditkortdata",buttonMolliePaymentLink:"Kopier til udklipsholderen",columnRefunded:"Refunderet",columnShipped:"Afsendt",columnCanceled:"Annulleret",labelMollieOrderId:"Mollie Ordre ID",labelMollieThirdPartyPaymentId:"Betalingsreference",labelMolliePaymentLink:"Mollie Checkout-URL",totalRefunds:"Refunderet beløb",totalRefundsPending:"Afventer refundering",totalRemaining:"Refunderbart beløb",totalVouchers:"Voucherværdi",totalShipments:"Forsendt beløb ({quantity} varer)",subscriptionBadge:"Abonnementsordre",refundManager:{title:"Mollie Refusionsansvarlig",btnOpenRefundManager:"Åben Refusion Manager",btnCloseRefundManager:"Luk Refusion Manager"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Foretrukken iDeal udsteder"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refusion Manager"},mollie_subscription:{label:"Abonnementer"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Beskrivelse"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Refundering",subscription:"Abonnement",webhookReceived:"Webhooks",status:"Status",started:"Startet",ended:"Afsluttet",paused:"Sat på pause",renewalReminder:"Påmindelse om fornyelse",renewed:"Fornyet",resumed:"Genoptaget",skipped:"Sprunget over",all:"Alle",canceled:"Annulleret",expired:"Udløbet",partiallyRefunded:"Refunderet (delvist)",orderSuccess:"Ordren var vellykket",orderFailed:"Ordren mislykkedes",orderCanceled:"Ordren blev annulleret"}}},kq={entities:{mollie_subscription:"Mollie Συνδρομή | Mollie Συνδρομές"},businessEvents:{mollie_checkout_order_success:" Η παραγγελία ήταν επιτυχής",mollie_checkout_order_failed:" Η παραγγελία απέτυχε",mollie_checkout_order_canceled:" Η παραγγελία ακυρώθηκε",mollie_webhook_received_All:" Λήφθηκε Webhook Mollie (Όλα)",mollie_webhook_received_status_authorized:" Λήφθηκε Webhook Mollie (Εγκεκριμένο)",mollie_webhook_received_status_failed:" Λήφθηκε Webhook Mollie (Απέτυχε)",mollie_webhook_received_status_canceled:" Λήφθηκε Webhook Mollie (Ακυρωμένο)",mollie_webhook_received_status_expired:" Λήφθηκε Webhook Mollie (Έληξε)",mollie_webhook_received_status_pending:" Λήφθηκε Webhook Mollie (Εκκρεμεί)",mollie_webhook_received_status_paid:" Λήφθηκε Webhook Mollie (Πληρωμένο)",mollie_webhook_received_status_completed:" Λήφθηκε Webhook Mollie (Ολοκληρωμένο)",mollie_webhook_received_status_refunded:" Λήφθηκε Webhook Mollie (Επιστράφηκε)",mollie_webhook_received_status_partially_refunded:" Λήφθηκε Webhook Mollie (Επιστράφηκε μερικώς)",mollie_refund_started:" Η επιστροφή Mollie ξεκίνησε",mollie_subscription_started:" Η συνδρομή Mollie ξεκίνησε",mollie_subscription_ended:" Η συνδρομή Mollie ολοκληρώθηκε",mollie_subscription_cancelled:" Η συνδρομή Mollie ακυρώθηκε",mollie_subscription_paused:" Η συνδρομή Mollie τέθηκε σε παύση",mollie_subscription_resumed:" Η συνδρομή Mollie συνεχίζεται",mollie_subscription_skipped:" Η συνδρομή Mollie παραλείφθηκε",mollie_subscription_renewed:" Η συνδρομή Mollie ανανεώθηκε",mollie_subscription_renewal_reminder:" Υπενθύμιση Mollie για ανανέωση συνδρομής"}},yq={global:kq,"mollie-payments":JSON.parse(`{"pluginTitle":" Mollie","pluginDescription":"Λειτουργία Mollie","searchPlaceholder":"Αναζήτηση συνδρομών...","general":{"mainMenuItemGeneral":"Πληρωμές Mollie","descriptionTextModule":"Πληρωμές Mollie","btnMollieActions":"Ενέργειες Mollie","refundThroughMollie":"Επιστροφή χρημάτων μέσω Mollie","shipThroughMollie":"Αποστολή μέσω Mollie","cancelMollieItem":"Ακύρωση μέσω Mollie"},"config":{"info":{"title":"Γεια σου {userName}, Καλώς ήρθες στην Mollie!","descriptionTop":"Η ενσωμάτωση είναι εύκολη με την Mollie!","descriptionBottom":"Αυτό είναι!","descriptionFooter":"Αν θέλεις να μάθεις περισσότερα για το πρόσθετο μας, επισκέψου παρακαλώ την επίσημη σελίδα εγγράφων μας.","onboardingStep1":"Εγγραφή για λογαριασμό Mollie.","onboardingStep2":"Εισάγετε τα API keys σας στην παρακάτω ενότητα.","onboardingStep2TestMode":"Ενεργοποιήστε τη 'Δοκιμαστική Λειτουργία' αν θέλετε να δοκιμάσετε μόνο πληρωμές.","onboardingStep3":"Αναθέστε μεθόδους πληρωμής στο κανάλι πωλήσεών σας.","onboardingStep3Link":"στα κανάλια πωλήσεων σας","btnDocumentation":"Έγγραφα","btnRequestSupport":"Υποστήριξη","btnTroubleshooting":"Οδηγός Αντιμετώπισης Προβλημάτων"},"api":{"apiLinkButton":"Λάβετε τα API keys σας από το Mollie Dashboard","testButton":"Δοκιμαστικά API keys","testApiKeys":{"title":"Πληρωμές Mollie","apiKey":"API key","isValid":"είναι έγκυρο","isInvalid":"δεν είναι έγκυρο"}},"payments":{"format":{"placeholder":"Πλαίσιο κειμένου","preview":"Προεπισκόπηση"},"updatePaymentMethods":{"title":"Πληρωμές Mollie","button":"Ενημέρωση μεθόδων πληρωμής","succeeded":"Οι μέθοδοι πληρωμής ενημερώθηκαν επιτυχώς.","failed":"Οι μέθοδοι πληρωμής δεν μπόρεσαν να ενημερωθούν."},"mollieLimits":{"link":"Δείξε τους κανόνες διαθεσιμότητας mollie για τις μεθόδους πληρωμής"}},"rounding":{"info1":"Το Shopware μπορεί να χρησιμοποιήσει τις ρυθμίσεις νομίσματος για να υπολογίσει πώς στρογγυλοποιείται το συνολικό ποσό μιας παραγγελίας. Αυτό περιλαμβάνει τον αριθμό των δεκαδικών στις τιμές των προϊόντων σας και το πλησιέστερο διάστημα στρογγυλοποίησης, όπως 0,50 ή 1,00.","info2":"Αυτές οι ρυθμίσεις μπορεί να οδηγήσουν σε διαφορετικό συνολικό ποσό από το συνολικό άθροισμα των στοιχείων. Όταν η Mollie ελέγχει αυτά τα ποσά και διαπιστώνει ότι δεν ταιριάζουν, προκαλεί σφάλμα κατά την ολοκλήρωση της παραγγελίας.","info3":"Μπορείτε να χρησιμοποιήσετε αυτή τη δυνατότητα για να αποφύγετε ζητήματα στρογγυλοποίησης στη διαδικασία ολοκλήρωσης. Όταν είναι ενεργοποιημένη, προσθέτει μια ξεχωριστή γραμμή στοιχείου στο Mollie Dashboard για τη διαφορά στη στρογγυλοποίηση, και οι πελάτες σας πληρώνουν το συνολικό ποσό που υπολογίζεται από το Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Δεν είναι δυνατόν να χρησιμοποιήσετε το Klarna Pay Now, το Klarna Slice It ή το Klarna Pay Later ως μέθοδο όταν η ημερομηνία λήξης σας είναι περισσότερες από 28 ημέρες στο μέλλον, εκτός αν συμφωνηθεί διαφορετική προθεσμία μεταξύ του εμπόρου και της Klarna.","bankTransferDueDateLimitReached":"Δεν είναι δυνατόν να ορίσετε τη διάρκεια ζωής της παραγγελίας υψηλότερη από 100 ημέρες."},"support":{"modalTitle":"Ζητήστε υποστήριξη από την Mollie","btnCancel":"Ακυρώνω","btnConfirm":"Ζητήστε υποστήριξη","btnSupport":"Περισσότερα για την υποστήριξή μας","form":{"name":"Το όνομά σας","email":"Η ηλεκτρονική σας διεύθυνση","recipient":"Αποστολή αιτήματος στο","subject":"Θέμα","message":"Μήνυμα"},"data":{"header":"Δεδομένα που εστάλησαν στην Mollie:","other":"Άλλα:","shopwareVersion":"Έκδοση Shopware","pluginLogs":"Αρχεία καταγραφής {plugin}","pluginConfiguration":"Διαμόρφωση {plugin}","pluginConfigurationHelpText":"Τα API keys εξαιρούνται.","paymentMethods":"Δεδομένα μεθόδου πληρωμής","paymentMethodsHelpText":"Περιλαμβάνει πληροφορίες σχετικά με ποιες μέθοδοι πληρωμής είναι ενεργές, ποιες έχουν ανατεθεί σε κάθε κανάλι πωλήσεων, καθώς και την κατάσταση τους στον λογαριασμό σας Mollie."},"success":"Το αίτημα υποστήριξης εστάλη επιτυχώς. Κάνουμε το καλύτερο δυνατό για να απαντήσουμε το συντομότερο δυνατό","error":"Παρουσιάστηκε πρόβλημα κατά την αποστολή του email μέσω του Shopware. Παρακαλούμε προσπαθήστε ξανά ή επικοινωνήστε μαζί μας άμεσα μέσω email."}},"rules":{"itemSubscriptionRule":"Το αντικείμενο είναι συνδρομή (Mollie)","cartSubscriptionRule":"Καλάθι με συνδρομές (Mollie)"},"refunds":{"status":{"queued":"Σε ουρά","pending":"Εκκρεμεί","processing":"Σε επεξεργασία","refunded":"Επιστράφηκε","failed":"Απέτυχε","description":{"queued":"Η επιστροφή χρημάτων είναι σε ουρά μέχρι να υπάρχει επαρκής υπόλοιπο για να επεξεργαστεί. Μπορείτε ακόμα να ακυρώσετε την επιστροφή.","pending":"Η επιστροφή θα σταλεί στην τράπεζα την επόμενη εργάσιμη ημέρα. Μπορείτε ακόμα να ακυρώσετε την επιστροφή.","processing":"Η επιστροφή έχει σταλεί στην τράπεζα. Το ποσό της επιστροφής θα μεταφερθεί στον λογαριασμό του καταναλωτή το συντομότερο δυνατό.","refunded":"Το ποσό της επιστροφής έχει μεταφερθεί στον καταναλωτή.","failed":"Η επιστροφή απέτυχε μετά την επεξεργασία. Για παράδειγμα, ο πελάτης έχει κλείσει τον τραπεζικό του λογαριασμό. Τα κεφάλαια θα επιστραφούν στον λογαριασμό σας."}}},"refund-manager":{"general":{"unitQuantity":"τεμ."},"acl":{"warningCreate":"Δεν έχετε άδειες για να δημιουργήσετε επιστροφές χρημάτων","warningCancel":"Δεν έχετε άδειες για να ακυρώσετε επιστροφές"},"cart":{"title":"Παραγγελία ##orderNumber##","btnSelectAll":"Επιλογή όλων","btnResetForm":"Επαναφορά Φόρμας","linkHowTo":"Πώς να χρησιμοποιήσετε αυτή τη φόρμα;","grid":{"columns":{"item":"Αντικείμενο","productNumber":"Αριθμός Προϊόντος","unitPrice":"Τιμή Μονάδας","quantity":"Ποσότητα","refunded":"Επιστράφηκε","refundQuantity":"Επιστροφή χρημάτων","totalPrice":"Σύνολο","refundAmount":"Επιστροφή χρημάτων","resetStock":"Επαναφορά Αποθέματος"},"btnResetLine":"Επαναφορά Γραμμής","checkDeductPromotion":"Αφαίρεση προωθητικής ενέργειας","checkRefundTax":"Επιστροφή ΦΠΑ"},"roundDiffItemAdded":"Το αντικείμενο αυτόματης στρογγυλοποίησης προστέθηκε"},"instructions":{"linkResetTutorials":"Επαναφορά Οδηγιών","btnToggleTutorial":"Εμφάνιση/Απόκρυψη Οδηγιών","titleFullRefund":"Πλήρης Επιστροφή χρημάτων","textFullRefund":"Απλά χρησιμοποιήστε το κουμπί για την πλήρη επιστροφή χρημάτων. Αυτό εξασφαλίζει ότι όλα τα αντικείμενά σας θα σημειωθούν ως επιστραμμένα και το πλήρες ποσό θα επιστραφεί στον πελάτη.","titleStockReset":"Επαναφορά Αποθεμάτων","textStockReset":"Μπορείτε αυτόματα να αυξήσετε το διαθέσιμο απόθεμα εισάγοντας την ποσότητα που θέλετε να επιστρέψετε. Απλά το εισάγετε πριν προχωρήσετε σε πλήρη ή μερική επιστροφή χρημάτων. Η επαναφορά του αποθέματος μπορεί να συνδυαστεί με τη διαδικασία επιστροφής με ευέλικτο τρόπο.","titleShipping":"Αποστολή","textShipping":"Τα αντικείμενα αποστολής μπορούν να επιστραφούν όπως οποιοδήποτε άλλο προϊόν. Είτε εισάγετε την πλήρη ποσότητα είτε ένα προσαρμοσμένο μερικό ποσό και προχωράτε με την επιστροφή. Η επιστροφή των εξόδων αποστολής μπορεί να συνδυαστεί με τη διαδικασία επιστροφής των αντικειμένων με ευέλικτο τρόπο.","titlePartialAmount":"Μερική επιστροφή χρημάτων (μόνο ποσό)","textPartialAmount":"Απλά εισάγετε το μερικό ποσό στο πεδίο κειμένου και ξεκινήστε την επιστροφή.","titlePartialItems":"Μερική Επιστροφή (με είδη)","textPartialItems":"Εάν θέλετε να επισημάνετε ποσότητες και αντικείμενα ως επιστραμμένα στο Mollie, χρησιμοποιήστε την παραπάνω φόρμα. Ορίστε τις ποσότητες σας και δώστε ένα προσαρμοσμένο ποσό για κάθε αντικείμενο που θα επιστραφεί. Το συνολικό ποσό θα είναι στη συνέχεια ορατό στο τελικό πεδίο ποσού επιστροφής. Θυμηθείτε, είναι ακόμα δυνατό να προσαρμόσετε αυτό το τελικό ποσό πριν ξεκινήσετε την επιστροφή σας.","titlePartialPromotions":"Μερική επιστροφή (με προωθητικές ενέργειες)","textPartialPromotions":"Εάν έχετε μια προώθηση στο καλάθι σας, τότε η προώθηση είναι μια ξεχωριστή γραμμή. Εάν θέλετε να επιστρέψετε όλα τα αντικείμενα που έχουν έκπτωση, προχωρήστε και επιστρέψτε τις συνολικές τους τιμές καθώς και τη γραμμή προώθησης. Ωστόσο, αν θέλετε να επιστρέψετε μόνο μερικά αντικείμενα που είχαν έκπτωση, μπορείτε να αφαιρέσετε την εφαρμοσμένη έκπτωση αυτόματα για κάθε γραμμή. Βεβαίως, μπορείτε πάντα να αλλάξετε τις τιμές αν δεν είναι σωστές.","titleRoundingDiff":"Διαφορά στρογγυλοποίησης","textRoundingDiff":"Μια πλήρης επιστροφή χρημάτων θα περιλαμβάνει τις διαφορές στρογγυλοποίησης"},"summary":{"dataLoading":"Τα δεδομένα φορτώνονται...","headerExcludingVat":"Εξαιρ. ΦΠΑ","headerIncludingVat":"Συμπ. ΦΠΑ","captionTotal":"Σύνολο","captionTotalTaxFree":"Σύνολο","captionPendingRefunds":"Σε αναμονή για επιστροφή χρημάτων","captionVouchers":"Ποσό κουπονιού","captionRefunded":"Ποσό που επιστράφηκε","captionRemaining":"Επιστρεπτέο ποσό","btnFixDiff":"Διορθώστε τη διαφορά","placeholderDescription":"Εισάγετε την περιγραφή της ανάλυσης τράπεζας/κάρτας για τον καταναλωτή. Μέγιστο 140 χαρακτήρες","lblDescription":"Περιγραφή (προαιρετικά) ({characters}/140 χαρακτήρες)","descriptionHelp":"Αυτό θα εμφανίζεται στην ανάλυση της τράπεζας ή της κάρτας του καταναλωτή όταν είναι δυνατόν. Το μήνυμα θα περικοπεί μετά από 140 χαρακτήρες.","placeholderInternalDescription":"Εισάγετε την εσωτερική σας περιγραφή","lblInternalDescription":"Εσωτερική περιγραφή (προαιρετικά)","internalDescriptionHelp":"Αυτό θα εμφανίζεται ως τοπική περιγραφή στο περιβάλλον διαχείρισης.","checkVerification":"Έχω επαληθεύσει το συνολικό ποσό επιστροφής και τις διαμορφωμένες ποσότητες για επιστροφή και ανεφοδιασμό.","btnRefund":"Επιστροφή χρημάτων","btnFullRefund":"Πλήρης Επιστροφή χρημάτων","roundDiffItemAdded":"Αντικείμενο στρογγυλοποίησης"},"refunds":{"title":"Επιστροφές στο Κέντρο Ελέγχου Mollie","linkMore":"Περισσότερα για τις επιστροφές χρημάτων","grid":{"columns":{"amount":"Ποσό","status":"Κατάσταση","description":"Περιγραφή","internalDescription":"Εσωτερική περιγραφή","composition":"Σύνθεση","date":"Ημερομηνία"},"lblNoComposition":"Δεν υπάρχει διαθέσιμη σύνθεση","btnCancelRefund":"Ακυρώστε αυτήν την επιστροφή χρημάτων"}},"notifications":{"success":{"refund-created":"Έχει δημιουργηθεί μια επιστροφή χρημάτων στη Mollie. Μπορεί να χρειαστούν 2 ώρες για να ολοκληρωθεί η επιστροφή. Μέχρι τότε, μπορείτε να ακυρώσετε την επιστροφή.","refund-canceled":"Η εκκρεμής επιστροφή έχει ακυρωθεί και αφαιρεθεί με επιτυχία."},"error":{"low-amount":"Παρακαλώ εισάγετε ποσό προς επιστροφή.","refund-created":"Κάτι πήγε στραβά κατά τη δημιουργία επιστροφής.","refund-canceled":"Υπήρξε πρόβλημα κατά την ακύρωση της εκκρεμούς επιστροφής. Παρακαλώ δοκιμάστε ξανά στο Κέντρο Ελέγχου Mollie."}}},"vouchers":{"CARD_TITLE":"Κουπόνι","VOUCHER_INFO_TITLE":"Πληρωμές με Κουπόνια","VOUCHER_INFO_DESCRIPTION":"Η Mollie σας επιτρέπει να δέχεστε εύκολα πληρωμές στο ηλεκτρονικό σας κατάστημα χρησιμοποιώντας οικολογικά κουπόνια, δωροκάρτες και κουπόνια για γεύματα—μια έξυπνη επιλογή για αύξηση πωλήσεων και ικανοποίηση των πελατών σας. Ο τρόπος πληρωμής \\"κουπόνι\\" είναι ορατός μόνο αν έχετε τουλάχιστον 1 προϊόν με ανατεθεί τύπο κουπονιού στο καλάθι.","VOUCHER_INFO_DEFAULTLANGUAGE":"Σημειώστε ότι αυτή η ρύθμιση μπορεί να επεξεργαστεί μόνο στην προεπιλεγμένη σας γλώσσα. Παρακαλώ αλλάξτε τη γλώσσα σας για να τροποποιήσετε τον τύπο κουπονιού αυτού του προϊόντος.","VOUCHER_BTN_READMORE":"Διαβάστε περισσότερα","VOUCHER_TYPE_CAPTION":"Τύπος κουπονιού προϊόντος","VOUCHER_TYPE_VALUE_NONE":"Κανένα","VOUCHER_TYPE_VALUE_ECO":"Οικολογικό","VOUCHER_TYPE_VALUE_MEAL":"Γεύμα","VOUCHER_TYPE_VALUE_VOUCHER":"Δώρο"},"modals":{"shipping":{"title":"Αποστολή μέσω Mollie","item":{"label":"Αντικείμενο:","noQuantity":"Παρακαλώ εισάγετε μία ποσότητα προς αποστολή.","shipAll":"Αποστολή όλων","summary":{"quantity":"Ποσότητα προς αποστολή","shipped":"Ποσότητα που απεστάλη","shippable":"Ποσότητα που μπορεί να αποσταλεί"},"success":"Η παραγγελία έχει αποσταλεί με επιτυχία."},"order":{"description":"Οι παρακάτω ποσότητες στοιχείων θα αποσταλούν.","itemHeader":"Αντικείμενο","quantityHeader":"Ποσότητα","originalQuantityHeader":"Ποσότητα (προοριζόμενη για αποστολή)"},"availableTracking":{"label":"Διαθέσιμοι κωδικοί παρακολούθησης","hint":"Κάντε κλικ σε έναν από αυτούς τους κωδικούς παρακολούθησης για να συμπληρώσετε αυτόματα όλα τα στοιχεία."},"showTracking":"Προσθήκη πληροφοριών παρακολούθησης για αυτή τη αποστολή","tracking":{"carrier":"Μεταφορέας","code":"Κωδικός","url":"Url","invalid":"Παρακαλώ εισάγετε τον Μεταφορέα και τον Κωδικό"},"confirmButton":"Αποστολή παραγγελίας","cancelButton":"Ακύρωση","selectAllButton":"Επιλογή όλων","resetButton":"Επαναφορά"},"cancel":{"title":"Ακύρωση στοιχείου μέσω mollie","confirmButton":"Ακύρωση στοιχείου μέσω mollie","cancelButton":"Κλείσιμο παραθύρου","resetStock":"Επαναφορά αποθεμάτων","item":{"success":"Το προϊόν ακυρώθηκε επιτυχώς","failed":{"quantityZero":"Η ποσότητα είναι 0","invalidLine":"Το προϊόν δεν υπάρχει στην παραγγελία","quantityTooHigh":"Η ποσότητα είναι πολύ υψηλή"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Αποστολή παραγγελίας (Mollie)","description":"Αποστολή παραγγελίας μέσω Mollie."},"modal":{"title":"Αποστολή Παραγγελίας","description":"Αυτή η ενέργεια θα αποστείλει αυτόματα μια παραγγελία μέσω Mollie. Η ακολουθία ροής θα λάβει τον αριθμό παραγγελίας και θα τον μεταφέρει στο API της Mollie. Οι επιτυχείς και αποτυχημένες αποστολές θα είναι ορατές στα αρχεία καταγραφής της Mollie.","warningConfig":"Παρακαλώ βεβαιωθείτε ότι έχετε απενεργοποιήσει οποιαδήποτε πρόσθετη αυτοματοποίηση για αυτό το είδος ενέργειας ώστε να αποφευχθούν τυχόν παρεμβολές.\\nΟι ακόλουθες ενεργοποιημένες δυνατότητες αυτού του πρόσθετου μπορεί να παρεμποδίσουν αυτή την ενέργεια:","noWarnings":"Καμία προειδοποίηση"}},"refundOrder":{"editor":{"title":"Επιστροφή Χρημάτων Παραγγελίας (Mollie)","description":"Επιστροφή χρημάτων παραγγελίας μέσω Mollie."},"modal":{"title":"Επιστροφή Χρημάτων Παραγγελίας","description":"Αυτή η ενέργεια θα ξεκινήσει αυτόματα μια επιστροφή μέσω Mollie. Η ακολουθία ροής θα λάβει τον αριθμό παραγγελίας και θα τον μεταφέρει στο API της Mollie. Οι επιτυχείς και αποτυχημένες επιστροφές θα είναι ορατές στα αρχεία καταγραφής της Mollie.","warning":"Παρακαλώ έχετε υπόψη ότι οι επιστροφές μπορεί να διαρκέσουν έως 2 ώρες για να ολοκληρωθούν και να φανούν στο κατάστημα. Μέχρι τότε μπορείτε πάντα να ακυρώσετε μια εκκρεμή επιστροφή είτε από τη σελίδα παραγγελίας στο Shopware είτε από το Κέντρο Ελέγχου Mollie.","warningConfig":"Παρακαλώ βεβαιωθείτε ότι έχετε απενεργοποιήσει οποιαδήποτε πρόσθετη αυτοματοποίηση για αυτό το είδος ενέργειας ώστε να αποφευχθούν τυχόν παρεμβολές."}},"warnings":{"automaticShipping":"Αυτόματη αποστολή στη διαμόρφωση του πρόσθετου"}}},"subscriptions":{"status":{"pending":"Εκκρεμεί","active":"Ενεργό","canceled":"Ακυρώθηκε","suspended":"Σε αναστολή","completed":"Ολοκληρώθηκε","paused":"Σε παύση","resumed":"Επαναφέρθηκε","skipped":"Παραλείφθηκε"},"navigation":{"title":"Συνδρομές Mollie"},"TYPE_DAYS":"Ημέρα/ές","TYPE_WEEKS":"Εβδομάδα/ές","TYPE_MONTHS":"Μήνας/ες","confirm":{"cancelTitle":"Τερματισμός συνδρομής;","cancel":"Ακυρώστε τη συνδρομή του πελάτη σας.","pauseTitle":"Πάυση συνδρομής;","pause":"Βάλτε τη συνδρομή σε αναμονή μέχρι να την επαναφέρετε.","resumeTitle":"Επαναφορά συνδρομής;","resume":"Συνεχίστε ξανά τη συνδρομή.","skipTitle":"Παραλείψτε την επόμενη δόση;","skip":"Παραλείψτε την επόμενη δόση σε αυτή τη συνδρομή. Θα συνεχιστεί αυτόματα μετά."},"alerts":{"cancelSuccess":"Η συνδρομή ακυρώθηκε επιτυχώς","pauseSuccess":"Η συνδρομή παύθηκε επιτυχώς","resumeSuccess":"Η συνδρομή έχει επαναφερθεί επιτυχώς","skipSuccess":"Η συνδρομή παραλείφθηκε επιτυχώς. Η επόμενη πληρωμή έχει ενημερωθεί."},"list":{"title":"Συνδρομές Mollie","columns":{"customer":"Πελάτης","status":"Κατάσταση","description":"Περιγραφή","amount":"Ποσό","nextPaymentAt":"Επόμενη πληρωμή","prePaymentReminder":"Υπενθύμιση στις","canceledAt":"Ακυρώθηκε στις","createdAt":"Δημιουργήθηκε στις"},"action":{"edit":"Επεξεργασία συνδρομής"},"deletedCustomer":"Διαγραμμένος πελάτης"},"detail":{"title":"Συνδρομή Mollie","buttonCancelSubscription":"Ακύρωση συνδρομής","labelDescription":"Περιγραφή","labelAmount":"Ποσό","labelQuantity":"Ποσότητα","labelMollieSubscription":"Συνδρομή Mollie","labelMollieCustomer":"Πελάτης Mollie","labelMandateId":"Εντολή","labelShopwareCustomer":"Πελάτης Shopware","labelCreatedAt":"Δημιουργήθηκε στις","buttonShowShopwareOrder":"Εμφάνιση παραγγελίας Shopware","buttonShowShopwareCustomer":"Εμφάνιση πελάτη Shopware","cardTitleSubscription":"Συνδρομή","cardTitleStatus":"Κατάσταση","labelStatus":"Κατάσταση","labelNextPaymentAt":"Επόμενη πληρωμή στις","labelLastRemindedAt":"Τελευταία υπενθύμιση στις","labelCanceledAt":"Ακυρώθηκε στις","buttonPauseSubscription":"Παύση συνδρομής","buttonResumeSubscription":"Επαναφορά συνδρομής","buttonSkipSubscription":"Παράλειψη συνδρομής","history":{"cardTitle":"Ιστορικό","colDate":"Ημερομηνία","colComment":"Σχόλιο","colStatusFrom":"Κατάσταση (από)","colStatusTo":"Κατάσταση (σε)","colMollieSubscription":"Συνδρομή Mollie"}},"product":{"card-title":"Συνδρομή","title":"Συνδρομές Mollie","description":"Η διαχείριση των επαναλαμβανόμενων πληρωμών σας είναι πιο εύκολη από ποτέ με τις βοηθητικές δυνατότητες μας. Ανεβάστε την επιχείρησή σας σε νέο επίπεδο με αποτελεσματικές επιλογές παρακολούθησης, απλές ενσωματώσεις και πολλά άλλα. Με τις συνδρομές Mollie, μπορείτε εύκολα να δημιουργήσετε προϊόντα συνδρομής και να προγραμματίσετε επαναλαμβανόμενες πληρωμές που θα γίνονται στο καθορισμένο διάστημα και διάρκεια.","mollieSubscriptionProduct":"Προϊόν Συνδρομής","mollieSubscriptionIntervalAmount":"Επανάληψη πληρωμής κάθε","mollieSubscriptionIntervalType":"Μονάδα διαστήματος","mollieSubscriptionRepetitionAmount":"Αριθμός επαναλήψεων","mollieSubscriptionRepetitionPlaceholder":"Εισάγετε αριθμό ή αφήστε κενό","infoDefaultLanguage":"Σημειώστε ότι αυτή η ρύθμιση μπορεί να επεξεργαστεί μόνο στην προεπιλεγμένη γλώσσα σας. Αλλάξτε τη γλώσσα σας για να τροποποιήσετε τις ρυθμίσεις συνδρομής αυτού του προϊόντος.","btnReadMore":"Διαβάστε περισσότερα"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Συνδρομή"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Δεδομένα πιστωτικής κάρτας",buttonMolliePaymentLink:"Αντιγραφή στο πρόχειρο",columnRefunded:"Επιστράφηκε",columnShipped:"Απεστάλη",columnCanceled:"Ακυρώθηκε",labelMollieOrderId:"Αναγνωριστικό παραγγελίας Mollie",labelMollieThirdPartyPaymentId:"Αναφορά πληρωμής",labelMolliePaymentLink:"Διεύθυνση URL για Ταμείο Mollie",totalRefunds:"Επιστραφέν ποσό",totalRefundsPending:"Αναμονή για επιστροφή χρημάτων",totalRemaining:"Επιστρεπτέο ποσό",totalVouchers:"Ποσό κουπονιού",totalShipments:"Ποσό που απεστάλη ({quantity} αντικείμενα)",subscriptionBadge:"Παραγγελία Συνδρομής",refundManager:{title:"Διαχειριστής Επιστροφών Mollie",btnOpenRefundManager:"Άνοιγμα Διαχειριστή Επιστροφών",btnCloseRefundManager:"Κλείσιμο Διαχειριστή Επιστροφών"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Προτιμώμενος εκδότης iDeal"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Διαχειριστής Επιστροφών"},mollie_subscription:{label:"Συνδρομές"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Περιγραφή"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Επιστροφή χρημάτων",subscription:"Συνδρομή",webhookReceived:"Webhooks",status:"Κατάσταση",started:"Ξεκίνησε",ended:"Έληξε",paused:"Σε παύση",renewalReminder:"Υπενθύμιση Ανανέωσης",renewed:"Ανανεώθηκε",resumed:"Επαναφέρθηκε",skipped:"Παραλείφθηκε",all:"Όλα",canceled:"Ακυρωμένο",expired:"Έληξε",partiallyRefunded:"Επιστράφηκε (μερικώς)",orderSuccess:"Η παραγγελία ήταν επιτυχής",orderFailed:"Η παραγγελία απέτυχε",orderCanceled:"Η παραγγελία ακυρώθηκε"}}},_q={entities:{mollie_subscription:"Mollie pretplata | Mollie pretplate"},businessEvents:{mollie_checkout_order_success:" Narudžba je uspješna",mollie_checkout_order_failed:" Narudžba je neuspjela",mollie_checkout_order_canceled:" Narudžba je otkazana",mollie_webhook_received_All:" Mollie Webhook primljen (Sve)",mollie_webhook_received_status_authorized:" Mollie Webhook primljen (Autorizirano)",mollie_webhook_received_status_failed:" Mollie Webhook primljen (Neuspjelo)",mollie_webhook_received_status_canceled:" Mollie Webhook primljen (Otkazano)",mollie_webhook_received_status_expired:" Mollie Webhook primljen (Isteklo)",mollie_webhook_received_status_pending:" Mollie Webhook primljen (Na čekanju)",mollie_webhook_received_status_paid:" Mollie Webhook primljen (Plaćeno)",mollie_webhook_received_status_completed:" Mollie Webhook primljen (Završeno)",mollie_webhook_received_status_refunded:" Mollie Webhook primljen (Vraćeno)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook primljen (Djelomično vraćeno)",mollie_refund_started:" Mollie povrat je započet",mollie_subscription_started:" Mollie pretplata je započeta",mollie_subscription_ended:" Mollie pretplata završena",mollie_subscription_cancelled:" Mollie pretplata otkazana",mollie_subscription_paused:" Mollie pretplata pauzirana",mollie_subscription_resumed:" Mollie pretplata nastavljena",mollie_subscription_skipped:" Mollie pretplata preskočena",mollie_subscription_renewed:" Mollie pretplata obnovljena",mollie_subscription_renewal_reminder:" Mollie podsjetnik za obnovu pretplate"}},Sq={global:_q,"mollie-payments":JSON.parse('{"pluginTitle":"Mollie","pluginDescription":"Mollie modul","searchPlaceholder":"Pretraži pretplate...","general":{"mainMenuItemGeneral":"Mollie Plaćanja","descriptionTextModule":"Mollie Plaćanja","btnMollieActions":"Mollie radnje","refundThroughMollie":"Povrat preko Mollie","shipThroughMollie":"Pošalji preko Mollie","cancelMollieItem":"Otkaži preko Mollie"},"config":{"info":{"title":"Bok {userName}, dobrodošli u Mollie!","descriptionTop":"Prijava i početak korištenja uz Mollie su brzi i jednostavni!","descriptionBottom":"To je to!","descriptionFooter":"Ako želite saznati više o našem dodatku, posjetite našu službenu stranicu s dokumentacijom.","onboardingStep1":"Prijavite se za Mollie račun.","onboardingStep2":"Unesite svoje API ključeve u odjeljak ispod.","onboardingStep2TestMode":"Uključite \\"Testni način\\" ako želite testirati plaćanja.","onboardingStep3":"Dodijelite metode plaćanja svom prodajnom kanalu.","onboardingStep3Link":"do svojih prodajnih kanala","btnDocumentation":"Dokumentacija","btnRequestSupport":"Podrška","btnTroubleshooting":"Vodič za rješavanje problema"},"api":{"apiLinkButton":"Preuzmite svoje API ključeve iz Mollie nadzorne ploče.","testButton":"Test API ključevi","testApiKeys":{"title":"Mollie Plaćanja","apiKey":"API-key","isValid":"je valjan","isInvalid":"nije valjan"}},"payments":{"format":{"placeholder":"Privremeni tekst","preview":"Pregled"},"updatePaymentMethods":{"title":"Mollie Plaćanja","button":"Ažuriraj metode plaćanja","succeeded":"Metode plaćanja su uspješno ažurirane.","failed":"Metode plaćanja nije bilo moguće ažurirati."},"mollieLimits":{"link":"Pokaži Mollie pravila dostupnosti za metode plaćanja"}},"rounding":{"info1":"Shopware može koristiti postavke valute za izračunavanje zaokruživanja ukupnog iznosa narudžbe. To uključuje broj decimala u cijenama proizvoda te najbliži interval zaokruživanja, poput 0,50 ili 1,00.","info2":"Ove postavke mogu dovesti do toga da ukupan iznos narudžbe bude drugačiji od zbroja pojedinačnih stavki. Kada Mollie usporedi te iznose i otkrije da se ne podudaraju, dolazi do pogreške pri naplati.","info3":"Ovu značajku možete koristiti kako biste izbjegli probleme sa zaokruživanjem pri naplati. Kada je omogućena, u vašoj Mollie nadzornoj ploči dodaje se zasebna stavka za razliku u zaokruživanju, a kupci plaćaju ukupan iznos izračunat od strane Shopwarea."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nije moguće koristiti metode Klarna Pay now, Klarna Slice it ili Klarna Pay later ako je datum isteka narudžbe više od 28 dana u budućnosti, osim ako trgovac i Klarna nisu dogovorili drugačiji maksimalni rok.","bankTransferDueDateLimitReached":"Nije moguće postaviti trajanje narudžbe na više od 100 dana."},"support":{"modalTitle":"Zatraži podršku od Mollie tima","btnCancel":"Odustani","btnConfirm":"Zatraži podršku","btnSupport":"Više o našoj podršci","form":{"name":"Vaše ime","email":"Vaš email adresa","recipient":"Pošaljite zahtjev ","subject":"Predmet","message":"Poruka"},"data":{"header":"Podaci poslani Mollie:","other":"Ostalo:","shopwareVersion":"Shopware verzija","pluginLogs":"{plugin} log datoteke","pluginConfiguration":"{plugin} konfiguracija","pluginConfigurationHelpText":"API ključevi su isključeni.","paymentMethods":"Podaci o metodi plaćanja","paymentMethodsHelpText":"Sadrži informacije o tome koje su metode plaćanja aktivne, koje su dodijeljene pojedinom prodajnom kanalu, kao i njihov status u vašem Mollie računu."},"success":"Zahtjev za podršku je uspješno poslan. Trudimo se odgovoriti što je prije moguće","error":"Došlo je do problema pri slanju e-pošte putem Shopwarea. Pokušajte ponovno ili nas kontaktirajte izravno putem e-pošte."}},"rules":{"itemSubscriptionRule":"Stavka je pretplata (Mollie)","cartSubscriptionRule":"Košarica s pretplatama (Mollie)"},"refunds":{"status":{"queued":"U redu","pending":"Na čekanju","processing":"Obrada","refunded":"Refundirano","failed":"Neuspjelo","description":{"queued":"Povrat novca je u redu čekanja dok na računu ne bude dovoljno sredstava za obradu povrata. I dalje možete otkazati povrat.","pending":"Povrat novca bit će poslan na banku sljedeći radni dan. I dalje možete otkazati povrat.","processing":"Povrat novca je poslan banci. Iznos povrata bit će što prije prebačen na račun korisnika.","refunded":"Iznos povrata novca je prebačen korisniku.","failed":"Povrat novca nije uspio nakon obrade. Na primjer, korisnik je zatvorio svoj bankovni račun. Sredstva će biti vraćena na vaš račun."}}},"refund-manager":{"general":{"unitQuantity":"kom."},"acl":{"warningCreate":"Nemate ovlasti za kreiranje povrata novca.","warningCancel":"Nemate ovlasti za otkazivanje povrata novca."},"cart":{"title":"Narudžba ##orderNumber##","btnSelectAll":"Odaberi sve","btnResetForm":"Ponovno postavi obrazac","linkHowTo":"Kako koristiti ovaj obrazac?","grid":{"columns":{"item":"Stavka","productNumber":"Broj proizvoda","unitPrice":"Cijena po jedinici","quantity":"Količina","refunded":"Vraćeno","refundQuantity":"Povrat novca","totalPrice":"Ukupno","refundAmount":"Povrat novca","resetStock":"Resetiraj zalihe"},"btnResetLine":"Resetiraj redak","checkDeductPromotion":"Oduzmi promociju","checkRefundTax":"Povrat poreza"},"roundDiffItemAdded":"Dodana je automatska stavka zaokruživanja"},"instructions":{"linkResetTutorials":"Poništi upute","btnToggleTutorial":"Prikaži/Sakrij vodič","titleFullRefund":"Potpuni povrat","textFullRefund":"Koristite gumb za puni povrat. Time se osigurava da su sve vaše stavke označene kao vraćene, a puni iznos vraćen kupcu.","titleStockReset":"Poništi stanje zaliha","textStockReset":"Dostupne zalihe možete automatski povećati unosom količine koju želite vratiti na skladište. Jednostavno unesite tu vrijednost prije nego što nastavite s potpunim ili djelomičnim povratom. Poništavanje stanja zaliha može se fleksibilno kombinirati s postupkom povrata.","titleShipping":"Dostava","textShipping":"Stavke dostave mogu se vratiti kao i bilo koji drugi proizvod. Unesite cijelu količinu ili prilagođeni djelomični iznos i nastavite s povratom. Povrat troškova dostave može se fleksibilno kombinirati s postupkom povrata proizvoda.","titlePartialAmount":"Djelomični povrat (samo iznos)","textPartialAmount":"Jednostavno unesite djelomični iznos u tekstualno polje i započnite povrat.","titlePartialItems":"Djelomični povrat (s artiklima)","textPartialItems":"Ako želite označiti količine i stavke kao vraćene u Mollie, koristite gornji obrazac. Postavite količine i unesite prilagođeni iznos za svaku stavku koja će biti vraćena. Ukupni zbroj bit će vidljiv u polju za unos konačnog iznosa povrata. Imajte na umu da je moguće dodatno prilagoditi taj konačni iznos prije početka povrata.","titlePartialPromotions":"Djelomični povrat (s promocijama)","textPartialPromotions":"Ako u svojoj košarici imate promociju, ona će biti prikazana kao zasebna stavka. Ako želite vratiti puni iznos za sve artikle s popustom, jednostavno izvršite povrat njihovih ukupnih vrijednosti zajedno s punim iznosom promocije. Međutim, ako želite vratiti samo neke od snižених artikala, možete automatski oduzeti primijenjeni popust za svaku pojedinačnu stavku. Naravno, vrijednosti uvijek možete ručno prilagoditi ako nisu točne.\\n","titleRoundingDiff":"Razlika u zaokruživanju","textRoundingDiff":"Puni povrat uključuje i razlike u zaokruživanju."},"summary":{"dataLoading":"Učitavanje podataka...","headerExcludingVat":"Isključ. PDV","headerIncludingVat":"Uključ. PDV","captionTotal":"Ukupno","captionTotalTaxFree":"Ukupno","captionPendingRefunds":"Čeka se povrat novca","captionVouchers":"Iznos vaučera","captionRefunded":"Vraćeni iznos","captionRemaining":"Iznos za povrat","btnFixDiff":"Ispravi razliku","placeholderDescription":"Unesite opis za izvod banke/kartice za korisnika. Maksimalno 140 znakova","lblDescription":"Opis (neobavezno) ({characters}/140 znakova)","descriptionHelp":"Ova poruka će, kad je moguće, biti prikazana na izvodu banke ili kartice korisnika. Poruka će biti skraćena nakon 140 znakova.","placeholderInternalDescription":"Unesite svoj interni opis","lblInternalDescription":"Interni opis (neobavezno)","internalDescriptionHelp":"Ovo će biti prikazano kao lokalni opis u administratorskom sučelju.","checkVerification":"Potvrdio/la sam ukupan iznos povrata te postavljene količine za povrat i vraćanje na skladište.","btnRefund":"Povrat novca","btnFullRefund":"Puni povrat","roundDiffItemAdded":"Stavka zaokruživanja"},"refunds":{"title":"Povrati u Mollie nadzornoj ploči","linkMore":"Više o povratima","grid":{"columns":{"amount":"Iznos","status":"Status","description":"Opis","internalDescription":"Interni opis","composition":"Sastav","date":"Datum"},"lblNoComposition":"Nema dostupnog sastava","btnCancelRefund":"Otkaži ovaj povrat."}},"notifications":{"success":{"refund-created":"U Mollieju je kreiran povrat. Završetak povrata može potrajati do 2 sata. Do tada možete otkazati povrat.","refund-canceled":"Na čekanju bio povrat uspješno je otkazan i uklonjen."},"error":{"low-amount":"Molimo unesite iznos za povrat.","refund-created":"Došlo je do pogreške pri kreiranju povrata.","refund-canceled":"Došlo je do problema pri otkazivanju povrata na čekanju. Molimo pokušajte ponovno u Mollie nadzornoj ploči."}}},"vouchers":{"CARD_TITLE":"Bon","VOUCHER_INFO_TITLE":"Plaćanja vaučerima","VOUCHER_INFO_DESCRIPTION":"Mollie vam omogućuje jednostavno prihvaćanje plaćanja u vašoj online trgovini koristeći ekološke, poklon i prehrambene vaučere — pametan izbor za povećanje prodaje i zadovoljstvo kupaca. Metoda plaćanja \\"vaučer\\" vidljiva je samo ako u košarici imate barem jedan proizvod kojem je dodijeljen tip vaučera.","VOUCHER_INFO_DEFAULTLANGUAGE":"Imajte na umu da se ova konfiguracija može uređivati samo na vašem zadanim jeziku. Molimo promijenite jezik kako biste mogli izmijeniti tip vaučera za ovaj proizvod.","VOUCHER_BTN_READMORE":"Pročitaj više","VOUCHER_TYPE_CAPTION":"Tip vaučera proizvoda","VOUCHER_TYPE_VALUE_NONE":"Nema","VOUCHER_TYPE_VALUE_ECO":"Ekološki","VOUCHER_TYPE_VALUE_MEAL":"Obrok","VOUCHER_TYPE_VALUE_VOUCHER":"Poklon"},"modals":{"shipping":{"title":"Isporuka putem Mollieja","item":{"label":"Stavka:","noQuantity":"Molimo unesite količinu za isporuku.","shipAll":"Pošalji sve","summary":{"quantity":"Količina za slanje","shipped":"Količina poslana","shippable":"Količina za isporuku"},"success":"Narudžba je uspješno isporučena."},"order":{"description":"Sljedeće količine stavki bit će isporučene.","itemHeader":"Stavka","quantityHeader":"Količina","originalQuantityHeader":"Količina (za isporuku)"},"availableTracking":{"label":"Dostupni brojevi za praćenje","hint":"Kliknite na jedan od ovih brojeva za automatsko popunjavanje svih podataka."},"showTracking":"Dodaj podatke za praćenje ove pošiljke","tracking":{"carrier":"Prijevoznik","code":"Kod","url":"Url","invalid":"Molimo unesite i prijevoznika i broj za praćenje"},"confirmButton":"Pošalji narudžbu","cancelButton":"Otkaži","selectAllButton":"Odaberi sve","resetButton":"Resetiraj"},"cancel":{"title":"Otkaži stavku putem Mollieja","confirmButton":"Otkaži stavku putem Mollieja","cancelButton":"Zatvori prozor","resetStock":"Poništi zalihe","item":{"success":"Proizvod je uspješno otkazan","failed":{"quantityZero":"Količina je 0","invalidLine":"Proizvod ne postoji u narudžbi","quantityTooHigh":"Količina je prevelika"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Pošalji narudžbu (Mollie)","description":"Isporuči narudžbu putem Mollieja."},"modal":{"title":"Isporuči narudžbu","description":"Ova radnja će automatski isporučiti narudžbu putem Mollieja. Tijekom procesa bit će proslijeđen broj narudžbe Mollie API-ju. Uspješne i neuspjele isporuke bit će vidljive u Mollie log datotekama.","warningConfig":"Molimo vas da isključite bilo kakvu dodatnu automatizaciju za ovu vrstu radnje kako biste izbjegli moguće smetnje.\\nSljedeće aktivirane značajke ovog dodatka mogu ometati ovu radnju:","noWarnings":"Nema upozorenja"}},"refundOrder":{"editor":{"title":"Povrat narudžbe (Mollie)","description":"Vrati narudžbu putem Mollieja."},"modal":{"title":"Povrat narudžbe","description":"Ova radnja će automatski započeti povrat novca putem Mollieja. Tijekom procesa broj narudžbe bit će proslijeđen Mollie API-ju. Uspješni i neuspješni povrati bit će vidljivi u Mollie log datotekama.","warning":"Imajte na umu da povrati novca mogu potrajati do 2 sata dok ne budu završeni i vidljivi u trgovini. Do tada uvijek možete otkazati povrat na čekanju, bilo putem stranice narudžbe u Shopwareu ili putem Mollie nadzorne ploče.","warningConfig":"Molimo vas da isključite bilo kakvu dodatnu automatizaciju za ovu vrstu radnje kako biste izbjegli moguće smetnje."}},"warnings":{"automaticShipping":"Automatska isporuka u postavkama dodatka"}}},"subscriptions":{"status":{"pending":"Na čekanju","active":"Aktivan","canceled":"Otkazan","suspended":"Suspendiran","completed":"Završen","paused":"Pauzirano","resumed":"Nastavljeno","skipped":"Preskočeno"},"navigation":{"title":"Mollie Pretplate"},"TYPE_DAYS":"Dan(i)","TYPE_WEEKS":"Tjedan(i)","TYPE_MONTHS":"Mjesec(i)","confirm":{"cancelTitle":"Prekinuti pretplatu?","cancel":"Otkažite pretplatu svog korisnika.","pauseTitle":"Pauziraj pretplatu?","pause":"Stavite pretplatu na čekanje dok je ponovno ne nastavite.","resumeTitle":"Nastaviti pretplatu?","resume":"Nastavite pretplatu.","skipTitle":"Preskočiti sljedeću ratu?","skip":"Preskočite sljedeću ratu u pretplati. Nakon toga pretplata se automatski nastavlja."},"alerts":{"cancelSuccess":"Pretplata je uspješno otkazana","pauseSuccess":"Pretplata je uspješno pauzirana","resumeSuccess":"Pretplata je uspješno obnovljena","skipSuccess":"Pretplata je uspješno preskočena. Sljedeća uplata je ažurirana."},"list":{"title":"Mollie Pretplate","columns":{"customer":"Korisnik","status":"Status","description":"Opis","amount":"Iznos","nextPaymentAt":"Sljedeća uplata","prePaymentReminder":"Podsjećeno dana","canceledAt":"Otkazano","createdAt":"Stvoreno"},"action":{"edit":"Uredi pretplatu"},"deletedCustomer":"Obrisani korisnik"},"detail":{"title":"Mollie pretplata","buttonCancelSubscription":"Otkaži pretplatu","labelDescription":"Opis","labelAmount":"Iznos","labelQuantity":"Količina","labelMollieSubscription":"Mollie pretplata","labelMollieCustomer":"Mollie korisnik","labelMandateId":"Ovlast","labelShopwareCustomer":"Shopware korisnik","labelCreatedAt":"Stvoreno","buttonShowShopwareOrder":"Pokaži Shopware narudžbu","buttonShowShopwareCustomer":"Pokaži Shopware korisnika","cardTitleSubscription":"Pretplata","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Sljedeća uplata","labelLastRemindedAt":"Zadnji podsjetnik poslan dana","labelCanceledAt":"Otkazano","buttonPauseSubscription":"Pauziraj pretplatu","buttonResumeSubscription":"Obnovi pretplatu","buttonSkipSubscription":"Preskoči pretplatu","history":{"cardTitle":"Povijest","colDate":"Datum","colComment":"Komentar","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Mollie pretplata"}},"product":{"card-title":"Pretplata","title":"Mollie Pretplate","description":"Upravljanje vašim ponavljajućim plaćanjima nikada nije bilo jednostavnije uz naše korisne značajke. Podignite svoje poslovanje na višu razinu uz učinkovite mogućnosti praćenja, jednostavne integracije i još mnogo toga. Uz Mollie pretplate lako možete kreirati proizvode s pretplatom i zakazati ponavljajuća plaćanja koja će se odvijati u unaprijed postavljenim intervalima i razdobljima.\\n","mollieSubscriptionProduct":"Proizvod s pretplatom","mollieSubscriptionIntervalAmount":"Ponovi plaćanje svakih","mollieSubscriptionIntervalType":"Jednica intervala","mollieSubscriptionRepetitionAmount":"Broj ponavljanja","mollieSubscriptionRepetitionPlaceholder":"Unesite broj ili ostavite prazno","infoDefaultLanguage":"Imajte na umu da se ova konfiguracija može uređivati samo na vašem zadanim jeziku. Molimo promijenite jezik kako biste mogli izmijeniti postavke pretplate za ovaj proizvod.","btnReadMore":"Pročitaj više"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Pretplata"}}'),"sw-order":{detailExtended:{titleCreditCardData:"Podatci o kreditnoj kartici",buttonMolliePaymentLink:"Kopiraj u međuspremnik",columnRefunded:"Vraćeno",columnShipped:"Poslano",columnCanceled:"Otkazano",labelMollieOrderId:"Mollie ID narudžbe",labelMollieThirdPartyPaymentId:"Referenca plaćanja",labelMolliePaymentLink:"Mollie URL za naplatu",totalRefunds:"Iznos povrata",totalRefundsPending:"Čeka se povrat",totalRemaining:"Iznos za povrat",totalVouchers:"Iznos vaučera",totalShipments:"Poslano ({quantity} stavki)",subscriptionBadge:"Narudžba s pretplatom",refundManager:{title:"Mollie upravitelj povrata",btnOpenRefundManager:"Otvori upravitelj povrata",btnCloseRefundManager:"Zatvori upravitelj povrata"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferirani izdavatelj iDeal"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Upravitelj povrata"},mollie_subscription:{label:"Pretplate"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Opis"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Povrat",subscription:"Pretplata",webhookReceived:"Webhooks",status:"Status",started:"Započet",ended:"Završen",paused:"Pauzirano",renewalReminder:"Podsjetnik na obnovu",renewed:"Obnovljeno",resumed:"Nastavljeno",skipped:"Preskočeno",all:"Sve",canceled:"Otkazano",expired:"Isteklo",partiallyRefunded:"Vraćeno (djelomično)",orderSuccess:"Narudžba uspješna",orderFailed:"Narudžba neuspješna",orderCanceled:"Narudžba otkazana"}}},wq={entities:{mollie_subscription:"Mollie tellimus | Mollie tellimused"},businessEvents:{mollie_checkout_order_success:"Tellimus edukas",mollie_checkout_order_failed:"Tellimus ebaõnnestus",mollie_checkout_order_canceled:"Tellimus tühistatud",mollie_webhook_received_All:" Mollie Veebikonks Saadud (Kõik)",mollie_webhook_received_status_authorized:" Mollie Veebikonks Saadud (Volitatud)",mollie_webhook_received_status_failed:" Mollie Veebikonks Saadud (Ebaõnnestunud)",mollie_webhook_received_status_canceled:" Mollie Veebikonks Saadud (Tühistatud)",mollie_webhook_received_status_expired:" Mollie Veebikonks Saadud (Aegunud)",mollie_webhook_received_status_pending:" Mollie Veebikonks Saadud (Ootel)",mollie_webhook_received_status_paid:" Mollie Veebikonks Saadud (Makstud)",mollie_webhook_received_status_completed:" Mollie Veebikonks Saadud (Lõpetatud)",mollie_webhook_received_status_refunded:" Mollie Veebikonks Saadud (Tagastatud)",mollie_webhook_received_status_partially_refunded:" Mollie Veebikonks Saadud (Osaliselt tagastatud)",mollie_refund_started:" Mollie tagasimakse algatatud",mollie_subscription_started:" Mollie tellimus alustatud",mollie_subscription_ended:" Mollie tellimus lõpetatud",mollie_subscription_cancelled:" Mollie tellimus tühistatud",mollie_subscription_paused:" Mollie tellimus peatatud",mollie_subscription_resumed:" Mollie tellimus taaskäivitatud",mollie_subscription_skipped:" Mollie tellimus vahele jäetud",mollie_subscription_renewed:" Mollie tellimus uuendatud",mollie_subscription_renewal_reminder:" Mollie meeldetuletus tellimuse uuendamiseks"}},Rq={global:wq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie moodul","searchPlaceholder":"Otsi tellimusi...","general":{"mainMenuItemGeneral":"Mollie maksed","descriptionTextModule":"Mollie maksed","btnMollieActions":"Mollie tegevused","refundThroughMollie":"Tagasta läbi Mollie","shipThroughMollie":"Saada läbi Mollie","cancelMollieItem":"Tühista läbi Mollie"},"config":{"info":{"title":"Tere {userName}, Tere tulemast Molliesse!","descriptionTop":"Molliega liitumine on lihtne!","descriptionBottom":"Ongi kõik!","descriptionFooter":"Kui soovid meie pluginast rohkem teada, külasta meie ametlikku dokumentatsioonilehte.","onboardingStep1":"Registreeri Mollie konto.","onboardingStep2":"Sisesta oma API võtmed allolevas jaotises.","onboardingStep2TestMode":"Lülita sisse 'Testimisrežiim', kui soovid makseid ainult katsetada.","onboardingStep3":"Määra makseviisid oma müügikanalitele.","onboardingStep3Link":"oma müügikanalitele","btnDocumentation":"Dokumentatsioon","btnRequestSupport":"Tugi","btnTroubleshooting":"Tõrkeotsingu juhend"},"api":{"apiLinkButton":"Hankige oma API võtmed Mollie töölaualt","testButton":"Testi API võtmeid","testApiKeys":{"title":"Mollie maksed","apiKey":"API võti","isValid":"kehtib","isInvalid":"on kehtetu"}},"payments":{"format":{"placeholder":"Kohatäide","preview":"Eelvaade"},"updatePaymentMethods":{"title":"Mollie maksed","button":"Uuenda makseviise","succeeded":"Makseviisid on edukalt uuendatud.","failed":"Makseviise ei saanud uuendada."},"mollieLimits":{"link":"Näita makseviiside kättesaadavuse reegleid"}},"rounding":{"info1":"Shopware võib kasutada valuuta seadeid, et arvutada, kuidas ümardada tellimuse kogusumma. See hõlmab toote hinna kümnendkohtade arvu ja lähima ümardamisintervalli, näiteks 0,50 või 1,00.","info2":"Need seaded võivad viia erineva kogusummani kui ridaelementide kogusumma. Kui Mollie kontrollib neid summasid ja leiab, et need ei klapi, tekitab see kassas vea.","info3":"Võid kasutada seda funktsiooni, et vältida ümardamise probleeme kassas. Kui see on lubatud, lisab see sinu Mollie töölauale eraldi reaelemendi tasakaaluvahe jaoks, ja sinu kliendid maksavad Shopware'i arvutatud kogusumma."},"order":{"bankTransferDueDateKlarnaLimitReached":"Klarna Pay now, Klarna Slice it või Klarna Pay later makseviisi kasutamine ei ole võimalik, kui teie maksetähtaeg on rohkem kui 28 päeva tulevikus, välja arvatud juhul, kui kaupmees ja Klarna on kokku leppinud teises maksimumsummas.","bankTransferDueDateLimitReached":"Tellimuse kehtivusaega ei ole võimalik määrata pikemaks kui 100 päeva."},"support":{"modalTitle":"Palu Mollielt abi","btnCancel":"Tühista","btnConfirm":"Palu abi","btnSupport":"Rohkem meie toe kohta","form":{"name":"Sinu nimi","email":"Sinu e-post","recipient":"Saada taotlus aadressile","subject":"Teema","message":"Sõnum"},"data":{"header":"Molliele saadetud andmed:","other":"Muud:","shopwareVersion":"Shopware'i versioon","pluginLogs":"{plugin} logifailid","pluginConfiguration":"{plugin} konfigureerimine","pluginConfigurationHelpText":"API võtmed on välistatud.","paymentMethods":"Makseviisi andmed","paymentMethodsHelpText":"Sisaldab teavet selle kohta, millised makseviisid on aktiivsed, millistele müügikanalitele need on määratud ning milline on nende staatus sinu Mollie kontol."},"success":"Toetuse taotlus on edukalt saadetud. Teeme oma parima, et vastata võimalikult kiiresti","error":"E-kirja saatmisel Shopware'i kaudu ilmnes probleem. Palun proovi uuesti või võta meiega otse ühendust e-posti teel."}},"rules":{"itemSubscriptionRule":"Toode on tellimus (Mollie)","cartSubscriptionRule":"Ostukorv tellimustega (Mollie)"},"refunds":{"status":{"queued":"Järjekorras","pending":"Ootel","processing":"Töötlemisel","refunded":"Tagastatud","failed":"Ebaõnnestunud","description":{"queued":"Tagasimakse on järjekorras, kuni saldo on piisav tagasimakse töötlemiseks. Sa saad endiselt tagasimakse tühistada.","pending":"Tagasimakse saadetakse panka järgmisel tööpäeval. Sa saad endiselt tagasimakse tühistada.","processing":"Tagasimakse on saadetud panka. Tagastatav summa kantakse tarbija kontole niipea kui võimalik.","refunded":"Tagasimakstud summa on kantud tarbijale.","failed":"Tagasimakse ebaõnnestus pärast töötlemist. Näiteks on klient sulgenud oma pangakonto. Raha tagastatakse sinu kontole."}}},"refund-manager":{"general":{"unitQuantity":"tk."},"acl":{"warningCreate":"Sul pole õigust tagasimakseid teha","warningCancel":"Sul pole õigust tagasimakseid tühistada"},"cart":{"title":"Tellimus ##orderNumber##","btnSelectAll":"Vali kõik","btnResetForm":"Vormi lähtestamine","linkHowTo":"Kuidas seda vormi kasutada?","grid":{"columns":{"item":"Ese","productNumber":"Toote number","unitPrice":"Ühikuhind","quantity":"Kogus","refunded":"Tagastatud","refundQuantity":"Tagasimakse","totalPrice":"Kokku","refundAmount":"Tagasimakse","resetStock":"Lähtesta varud"},"btnResetLine":"Lähtesta read","checkDeductPromotion":"Eemalda allahindlus","checkRefundTax":"Tagasta käibemaks"},"roundDiffItemAdded":"Lisati automaatne ümardamisartikkel"},"instructions":{"linkResetTutorials":"Juhendite lähtestamine","btnToggleTutorial":"Näita/Peida juhendid","titleFullRefund":"Täielik tagasimakse","textFullRefund":"Kasuta lihtsalt nuppu täieliku tagasimakse saamiseks. See tagab, et kõik sinu kaubad märgitakse tagastatuks ja kogu summa tagastatakse kliendile.","titleStockReset":"Varude lähtestamine","textStockReset":"Sa saad automaatselt suurendada saadaval olevaid varusid, sisestades koguse, mida soovid varudesse lisada. Lihtsalt sisesta see enne kui jätkad täis- või osalise tagasimakse tegemisega. Varude taastamist saab paindlikult kombineerida tegeliku tagasimaksete protsessiga.","titleShipping":"Saatmine","textShipping":"Saatmisartikleid saab tagastada nagu igat muud tootet. Sisesta täielik kogus või eraldi osaline summa ja jätka tagasimakset. Saate kulude hüvitamise paindlikult kombineerida toodete tegeliku tagastamisega.","titlePartialAmount":"Osaline tagasimakse (ainult summa)","textPartialAmount":"Lihtsalt sisesta osaline summa tekstivälja ja alusta tagasimakset.","titlePartialItems":"Osaline tagasimakse (artiklitega)","textPartialItems":"Kui soovid, et kogused ja esemed oleksid Mollies tagastatud, kasuta ülalolevat vormi. Sea oma kogused ja sisesta iga tagastatava toote jaoks kohandatud summa. Kogu summa kuvatakse seejärel lõpliku tagasimakse summa tekstiväljas. Pea meeles, et lõpliku summat saab enne tagasimakse algatamist endiselt muuta.","titlePartialPromotions":"Osaline tagasimakse (koos soodustustega)","textPartialPromotions":"Kui sul on ostukorvis soodustus, on soodustus eraldi rida. Kui soovid tagastada kõik allahinnatud tooted, mine edasi ja tagasta nende koguväärtused ja terve soodustuse rida. Siiski, kui soovid vaid tagastada mõned allahinnatud tooted, saad iga tulu peaautomaatsete allahindluste automaatselt maha arvata. Loomulikult saad alati väärtusi muuta, kui need ei ole õiged.","titleRoundingDiff":"Ümardamisvahe","textRoundingDiff":"Täielik tagasimakse hõlmab ümardamisest tulenevaid erinevusi"},"summary":{"dataLoading":"Andmeid laaditakse...","headerExcludingVat":"Ilma käibemaksuta","headerIncludingVat":"Käibemaksuga","captionTotal":"Kokku","captionTotalTaxFree":"Kokku","captionPendingRefunds":"Ootab tagasimakset","captionVouchers":"Kinkekaardi summa","captionRefunded":"Tagastatud summa","captionRemaining":"Tagastatav summa","btnFixDiff":"Paranda erinevus","placeholderDescription":"Sisesta tarbija pangakonto/krediitkaardi väljavõtte kirjeldus. Max 140 tähemärki","lblDescription":"Kirjeldus (valikuline) ({characters}/140 tähemärki)","descriptionHelp":"Võimalusel kuvatakse see tarbija pangakonto või krediitkaardi väljavõttel. Sõnum kärbitakse pärast 140 tähemärki.","placeholderInternalDescription":"Sisesta oma sisekirjeldus","lblInternalDescription":"Sisekirjeldus (valikuline)","internalDescriptionHelp":"See kuvatakse haldusliideses kohaliku kirjeldusena.","checkVerification":"Olen kontrollinud tagasimakse kogusumma ja konfigureeritud tagasimakse- ja varude täiendamise kogused.","btnRefund":"Tagasimakse","btnFullRefund":"Täielik tagasimakse","roundDiffItemAdded":"Ümardamisartikkel"},"refunds":{"title":"Tagasimaksed Mollie töölaual","linkMore":"Rohkem tagasimaksetest","grid":{"columns":{"amount":"Summa","status":"Staatus","description":"Kirjeldus","internalDescription":"Sisekirjeldus","composition":"Koostisosad","date":"Kuupäev"},"lblNoComposition":"Koostisosade puudumine","btnCancelRefund":"Tühista see tagasimakse"}},"notifications":{"success":{"refund-created":"Mollie's on loodud tagasimakse. Tagasimakse teostamine võib võtta aega kuni 2 tundi. Selle aja jooksul on sul võimalik tagasimakse tühistada.","refund-canceled":"Ootel tagasimakse on edukalt tühistatud ja eemaldatud."},"error":{"low-amount":"Palun sisesta tagastatav summa.","refund-created":"Tagasimakse loomisel tekkis viga.","refund-canceled":"Ootel tagasimakse tühistamisel tekkis probleem. Palun proovi uuesti Mollie töölaual."}}},"vouchers":{"CARD_TITLE":"Kinkekaart","VOUCHER_INFO_TITLE":"Kinkekaardi maksed","VOUCHER_INFO_DESCRIPTION":"Mollie võimaldab sul oma veebipoes hõlpsasti vastu võtta makseid öko-, kinkekaartide ja toidutalongidega – see on nutikas valik müügi suurendamiseks ja klientide rahulolu tagamiseks. Makseviis „kinkekaart” on nähtav ainult siis, kui ostukorvis on vähemalt 1 toode, millele on määratud kinkekaardi tüüp.","VOUCHER_INFO_DEFAULTLANGUAGE":"Palun pane tähele, et seda konfiguratsiooni saab redigeerida ainult sinu vaikimisi keeles. Palun muuda oma keelt, et muuta selle toote kinkekaardi tüüpi.","VOUCHER_BTN_READMORE":"Loe lähemalt","VOUCHER_TYPE_CAPTION":"Kinkekaardilaadne toode","VOUCHER_TYPE_VALUE_NONE":"Puudub","VOUCHER_TYPE_VALUE_ECO":"Öko","VOUCHER_TYPE_VALUE_MEAL":"Eine","VOUCHER_TYPE_VALUE_VOUCHER":"Kink"},"modals":{"shipping":{"title":"Saada läbi Mollie","item":{"label":"Ese:","noQuantity":"Palun sisesta saadetav kogus.","shipAll":"Saada kõik","summary":{"quantity":"Saadetav kogus","shipped":"Saadetud kogus","shippable":"Saatmiseks valmisolev kogus"},"success":"Tellimus on edukalt saadetud."},"order":{"description":"Järgmised kogused saadetakse teele.","itemHeader":"Ese","quantityHeader":"Kogus","originalQuantityHeader":"Kogus (saadetav)"},"availableTracking":{"label":"Saadaval jälgimiskoodid","hint":"Kliki ühele neist jälgimiskoodidest, et kõik andmed täidetaks automaatselt."},"showTracking":"Lisa jälgimise info selle saadetise jaoks","tracking":{"carrier":"Vedaja","code":"Kood","url":"URL","invalid":"Palun sisesta nii vedaja kui ka kood"},"confirmButton":"Saada tellimus","cancelButton":"Tühista","selectAllButton":"Vali kõik","resetButton":"Nulli"},"cancel":{"title":"Tühista ese Mollie kaudu","confirmButton":"Tühista ese Mollie kaudu","cancelButton":"Sulge hüpikaken","resetStock":"Taasta varud","item":{"success":"Toode on edukalt tühistatud","failed":{"quantityZero":"Kogus on 0","invalidLine":"Toodet ei ole tellimuses","quantityTooHigh":"Kogus on liiga suur"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Saada tellimus (Mollie)","description":"Saada tellimus Mollies."},"modal":{"title":"Saada tellimus","description":"See toiming saadab tellimuse automaatselt läbi Mollie. Protsess saab tellimuse numbri ja edastab selle Mollie API-le. Edustatud ja ebaõnnestunud saadetised on nähtavad Mollie logifailides.","warningConfig":"Palun veendu, et kõik täiendavad automatiseerimised seda tüüpi toimingutes on välja lülitatud, et vältida segadust.\\nSelle pistikprogrammi järgmised aktiveeritud funktsioonid võivad seda toimingut häirida:","noWarnings":"Hoiatusi pole"}},"refundOrder":{"editor":{"title":"Tagasta tellimus (Mollie)","description":"Tagasta tellimus Mollie kaudu."},"modal":{"title":"Tagasta tellimus","description":"See toiming alustab automaatselt tagasimakset läbi Mollie. Protsess saab tellimuse numbri ja edastab selle Mollie API-le. Edukad ja ebaõnnestunud tagasimaksed on nähtavad Mollie logifailides.","warning":"Palun pea meeles, et tagasimaksete lõplikuks kinnitamiseks ja poes kuvamiseks võib kuluda kuni 2 tundi. Seni saate ootava tagasimakse alati tühistada kas Shopware'i tellimuste lehelt või Mollie töölaualt.","warningConfig":"Häirete vältimiseks palun veendu, et sellist tüüpi toimingute jaoks on kõik lisafunktsioonid välja lülitatud."}},"warnings":{"automaticShipping":"Automaatne saadetis pistikprogrammi konfiguratsioonis"}}},"subscriptions":{"status":{"pending":"Ootel","active":"Aktiivne","canceled":"Tühistatud","suspended":"Peatatud","completed":"Täidetud","paused":"Peatatud","resumed":"Jätkatud","skipped":"Vahele jäetud"},"navigation":{"title":"Mollie tellimused"},"TYPE_DAYS":"Päev(ad)","TYPE_WEEKS":"Nädal(ad)","TYPE_MONTHS":"Kuu(d)","confirm":{"cancelTitle":"Lõpeta tellimus?","cancel":"Tühista oma kliendi tellimus.","pauseTitle":"Peata tellimus?","pause":"Peata tellimus, kuni soovid seda uuesti jätkata.","resumeTitle":"Jätka tellimust?","resume":"Jätka tellimust uuesti.","skipTitle":"Jäta järgmine makse vahele?","skip":"Jäta järgmine osamakse tellimusest vahele. Pärast seda jätkub tellimus automaatselt."},"alerts":{"cancelSuccess":"Tellimus on edukalt tühistatud","pauseSuccess":"Tellimus on edukalt peatatud","resumeSuccess":"Tellimus on edukalt taastatud","skipSuccess":"Tellimus on edukalt vahele jäetud. Järgmine makse on uuendatud."},"list":{"title":"Mollie Tellimused","columns":{"customer":"Klient","status":"Staatus","description":"Kirjeldus","amount":"Summa","nextPaymentAt":"Järgmine makse","prePaymentReminder":"Meenutatud","canceledAt":"Tühistatud","createdAt":"Loodud"},"action":{"edit":"Muuda tellimust"},"deletedCustomer":"Kustutatud klient"},"detail":{"title":"Mollie tellimus","buttonCancelSubscription":"Tühista tellimus","labelDescription":"Kirjeldus","labelAmount":"Summa","labelQuantity":"Kvantiteet","labelMollieSubscription":"Mollie tellimus","labelMollieCustomer":"Mollie klient","labelMandateId":"Mandaat","labelShopwareCustomer":"Shopware klient","labelCreatedAt":"Loodud","buttonShowShopwareOrder":"Kuva Shopware tellimus","buttonShowShopwareCustomer":"Kuva Shopware klient","cardTitleSubscription":"Tellimus","cardTitleStatus":"Staatus","labelStatus":"Staatus","labelNextPaymentAt":"Järgmine makse kell","labelLastRemindedAt":"Viimane meeldetuletus kell","labelCanceledAt":"Tühistatud","buttonPauseSubscription":"Pane tellimus pausile","buttonResumeSubscription":"Jätka tellimust","buttonSkipSubscription":"Tühista tellimus","history":{"cardTitle":"Ajalugu","colDate":"Kuupäev","colComment":"Kommentaar","colStatusFrom":"Staatus (alates)","colStatusTo":"Staatus (kuni)","colMollieSubscription":"Mollie tellimus"}},"product":{"card-title":"Tellimus","title":"Mollie Tellimused","description":"Meie kasulike funktsioonide abil on korduvate maksete haldamine lihtsam kui kunagi varem. Vii oma äri uuele tasemele tõhusate jälgimisvõimaluste, lihtsate integratsioonide ja muude funktsioonide abil. Mollie tellimustega saad hõlpsasti luua tellimustooted ja planeerida korduvaid maksed, mis toimuvad konfigureeritud intervalli ja perioodi järel.","mollieSubscriptionProduct":"Tellimuse toode","mollieSubscriptionIntervalAmount":"Korda makset iga","mollieSubscriptionIntervalType":"Ajavahemiku ühik","mollieSubscriptionRepetitionAmount":"Korduste arv","mollieSubscriptionRepetitionPlaceholder":"Sisesta number või jäta tühjaks","infoDefaultLanguage":"Palun pane tähele, et seda konfiguratsiooni saab redigeerida ainult teie vaikimisi keeles. Palun muuda oma keelt, et muuta selle toote tellimusseadistusi.","btnReadMore":"Loe lähemalt"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Tellimus"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Krediitkaardi andmed",buttonMolliePaymentLink:"Kopeeri lõikelauale",columnRefunded:"Tagastatud",columnShipped:"Saadetud",columnCanceled:"Tühistatud",labelMollieOrderId:"Mollie tellimuse ID",labelMollieThirdPartyPaymentId:"Makse viitenumber",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Tagastatud summa",totalRefundsPending:"Ootab tagastamist",totalRemaining:"Tagastatav summa",totalVouchers:"Kinkekaardi summa",totalShipments:"Saadetud summa ({quantity} toodet)",subscriptionBadge:"Tellimuse tellimine",refundManager:{title:"Mollie Tagasimakse Haldur",btnOpenRefundManager:"Ava tagasimaksete haldur",btnCloseRefundManager:"Sulge tagasimaksete haldur"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Eelistatud iDeal väljastaja"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Tagasimaksete haldur"},mollie_subscription:{label:"Tellimused"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Kirjeldus"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Tagasimakse",subscription:"Tellimus",webhookReceived:"Veebikonksud",status:"Staatus",started:"Alustatud",ended:"Lõpetatud",paused:"Peatatud",renewalReminder:"Uuendamise meeldetuletus",renewed:"Uuendatud",resumed:"Jätkatud",skipped:"Vahele jäetud",all:"Kõik",canceled:"Tühistatud",expired:"Aegunud",partiallyRefunded:"Tagastatud (osaliselt)",orderSuccess:"Tellimus õnnestus",orderFailed:"Tellimus ebaõnnestus",orderCanceled:"Tellimus tühistatud"}}},Eq={entities:{mollie_subscription:"Mollie áskrift | Mollie áskriftir"},businessEvents:{mollie_checkout_order_success:" Pöntun árángursrík",mollie_checkout_order_failed:"Pöntun misheppnaðist",mollie_checkout_order_canceled:"Pöntun aflýst",mollie_webhook_received_All:" Mollie Webhook Móttekin (Allt)",mollie_webhook_received_status_authorized:" Mollie Webhook Móttekin (Viðurkennd)",mollie_webhook_received_status_failed:" Mollie Webhook Móttekin (Mistókst)",mollie_webhook_received_status_canceled:" Mollie Webhook Móttekin (Aflýst)",mollie_webhook_received_status_expired:" Mollie Webhook Móttekin (útrunnin)",mollie_webhook_received_status_pending:" Mollie Webhook Móttekin (Í vinnslu)",mollie_webhook_received_status_paid:" Mollie Webhook Móttekin (Greidd)",mollie_webhook_received_status_completed:" Mollie Webhook Móttekin (Fullunnin)",mollie_webhook_received_status_refunded:" Mollie Webhook Móttekin (Endurgreidd)",mollie_webhook_received_status_partially_refunded:" Mollie Webhook Móttekin (Að hluta til endurgreidd)",mollie_refund_started:"Endurgreiðsla Mollie hafin",mollie_subscription_started:"Mollie áskrift hafin",mollie_subscription_ended:"Mollie áskrift lokið",mollie_subscription_cancelled:"Mollie áskrift aflýst",mollie_subscription_paused:"Mollie áskrift stöðvuð",mollie_subscription_resumed:"Mollie áskrift endurtekinn",mollie_subscription_skipped:"Mollie áskrift sleppt",mollie_subscription_renewed:"Mollie áskrift endurnýjuð",mollie_subscription_renewal_reminder:"Mollie áminning um endurnýjun áskriftar"}},Aq={global:Eq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Eining","searchPlaceholder":"Leita að áskriftum...","general":{"mainMenuItemGeneral":"Mollie greiðslur","descriptionTextModule":"Mollie greiðslur","btnMollieActions":"Mollie aðgerðir","refundThroughMollie":"Endurgreiðsla í gegnum Mollie","shipThroughMollie":"Sending í gegnum Mollie","cancelMollieItem":"Aflýsa í gegnum Mollie"},"config":{"info":{"title":"Halló {userName}, velkomin/n til Mollie!","descriptionTop":"Innleiðsla er auðveld hjá Mollie!","descriptionBottom":"Það er allt og sumt!","descriptionFooter":"Ef þú vilt læra meira um viðbótina okkar, vinsamlegast heimsæktu opinberu skjalasíðuna okkar.","onboardingStep1":"Skráðu þig inn til þess að fá Mollie reikning.","onboardingStep2":"Sláðu inn API lyklana þína í hlutanum hér fyrir að neðan.","onboardingStep2TestMode":"Kveiktu á 'Prófunarham' ef þú vilt prófa greiðslurnar.","onboardingStep3":"Tilefndu greiðslumáta til sölurásar þinnar.","onboardingStep3Link":"til þinnar sölurásar","btnDocumentation":"Skjalfesting","btnRequestSupport":"Stuðningur","btnTroubleshooting":"Leiðbeiningar um úrræðaleit"},"api":{"apiLinkButton":"Sæktu API lyklana þína í Stjórnborði Mollie","testButton":"Prófa API lykla","testApiKeys":{"title":"Mollie greiðslur","apiKey":"API lykill","isValid":"er gildur","isInvalid":"er ógildur"}},"payments":{"format":{"placeholder":"Staðgengill","preview":"Forskoðun"},"updatePaymentMethods":{"title":"Mollie greiðslur","button":"Uppfæra greiðslumáta","succeeded":"Greiðslumátar hafa verið uppfærðir með góðum árangri.","failed":"Ekki var hægt að uppfæra greiðslumáta."},"mollieLimits":{"link":"Sýna aðgengisreglur fyrir greiðslumáta Mollie"}},"rounding":{"info1":"Shopware getur notað gjaldmiðlastillingar til þess að reikna út hvernig það námundar heildarverð pöntunnar. Þetta inniheldur fjölda aukastafa á verði varanna þinna og næsta námundunarbili eins og 0,50 eða 1,00.","info2":"Þessar stillingar geta valdið því að heildarupphæð verður önnur en heildarsumman af línuþáttum. Þegar Mollie athugar þessa upphæð og kemst að því að þær passi ekki, veldur það villu í afgreiðslu.","info3":"Þú getur notað þessan eiginleika til þess að forðast vandamál við námundum í afgreiðslu. Þegar það er virkt, bætir það við sér línuhlut í Stjórnborði Mollie fyrir mismun við námundun, og viðskiptavinir þínir greiða heildartölu sem Shopware reiknar."},"order":{"bankTransferDueDateKlarnaLimitReached":"Það er ekki mögulegt að nota Klarna Greiða núna, Klarna Skera það eða Klarna Greiða síðar sem aðferð þegar gildistíminn þinn er meira en 28 daga í framtíðinni, nema annað hámark sé samið um milli seljanda og Klarna.","bankTransferDueDateLimitReached":"Það er ekki hægt að stilla líftíma pöntunar hærri en 100 daga."},"support":{"modalTitle":"Óskaðu eftir stuðningi frá Mollie","btnCancel":"Hætta við","btnConfirm":"Óska eftir stuðningi","btnSupport":"Meira um stuðninginn okkar","form":{"name":"Nafnið þitt","email":"Tölvupósturinn þinn","recipient":"Senda beiðni til","subject":"Efni","message":"Skilaboð"},"data":{"header":"Gögn send til Mollie:","other":"Annað:","shopwareVersion":"Shopware útgáfa","pluginLogs":"{plugin} skrá","pluginConfiguration":"{plugin} grunnstilling","pluginConfigurationHelpText":"API lyklar eru undanskildir.","paymentMethods":"Gögn um greiðslumáta","paymentMethodsHelpText":"Inniheldur upplýsingar um hvaða greiðslumátar eru virkir, tilnefndar hverju söluþætti og stöðu þeirra í Mollie reikningnum þínum."},"success":"Beiðni um stuðning hefur verið send með góðum árangri. Við gerum okkar besta til að svara eins fljótt og auðið er","error":"Það kom upp vandamál þegar sendingin var send með Shopware. Vinsamlegast reyndu aftur eða hafðu samband við okkur beint í gegnum tölvupóst."}},"rules":{"itemSubscriptionRule":"Vara er áskrift (Mollie)","cartSubscriptionRule":"Karfa með áskriftum (Mollie)"},"refunds":{"status":{"queued":"Í röð","pending":"Í bið","processing":"Í vinnslu","refunded":"Endurgreidd","failed":"Mistókst","description":{"queued":"Endurgreiðslan er í bið þar til nægileg innistæða finnst til að vinna endurgreiðsluna. Þú getur enn afskráð endurgreiðsluna.","pending":"Endurgreiðslan verður send til bankans á næsta vinnudegi. Þú getur enn afskráð endurgreiðsluna.","processing":"Endurgreiðslan hefur verið send til bankans. Endurgreiðslufjárhæðin mun verða flutt á reikning neytenda eins fljótt og auðið er.","refunded":"Endurgreiðslufjárhæðin hefur verið flutt til neytandans.","failed":"Endurgreiðslan hefur mistekist eftir vinnslu. Til dæmis, gæti viðskiptavinurinn hafa lokað bankareikning sínum. Fjármunirnir verða sendir til þíns reiknings."}}},"refund-manager":{"general":{"unitQuantity":"stk."},"acl":{"warningCreate":"Þú hefur ekki heimildir til að búa til endurgreiðslur","warningCancel":"Þú hefur ekki heimildir til að hætta við endurgreiðslur"},"cart":{"title":"Pöntun ##orderNumber##","btnSelectAll":"Velja allt","btnResetForm":"Endurstilla eyðublað","linkHowTo":"Hvernig á að nota þetta eyðublað?","grid":{"columns":{"item":"Hlutur","productNumber":"Vörunúmer","unitPrice":"Verð á einingu","quantity":"Magn","refunded":"Endurgreitt","refundQuantity":"Endurgreiðsla","totalPrice":"Samtals","refundAmount":"Endurgreiðsla","resetStock":"Endurstilla birgðir"},"btnResetLine":"Endurstilla línu","checkDeductPromotion":"Draga frá afslætti","checkRefundTax":"Endurgreiða VSK"},"roundDiffItemAdded":"Bætt var við sjálfvirka námundun"},"instructions":{"linkResetTutorials":"Endurstilla leiðbeiningar","btnToggleTutorial":"Sýna/Fela leiðbeiningar","titleFullRefund":"Full endurgreiðsla","textFullRefund":"Notaðu einungis hnappinn til þess að fá fulla endurgreiðslu. Þetta tryggir að allar þínar vörur séu merktar sem endurgreiddar og að heildarfjárhæðinni sé skilað til viðskiptavinarins.","titleStockReset":"Endurstilling birgða","textStockReset":"Þú getur sjálfkrafa aukið fáanlegar birgðir með því að slá inn magn sem er aftur komið á lager. Sláðu það inn áður en þú hefur heila eða bútaða endurgreiðslu. Þú getur sameinað endurstillingu birgða og endurgreiðslu á sveigjanlegan máta.","titleShipping":"Sending","textShipping":"Vörur í sendingu má endurgreiða eins og aðrar vörur. Annað hvort sláðu inn fullt magn eða hluta magns og haltu áfram með endurgreiðsluna. Endurgreiðsla sendingarkostnaðs má sameina á sveigjanlegan hátt við endurgreiðsluferli vöru.","titlePartialAmount":"Sundruð endurgreiðsla (einungis magn)","textPartialAmount":"Sláðu einfaldlega inn hluta fjárhæðar í reitinn og byrjaðu endurgreiðsluna.","titlePartialItems":"Sundruð endurgreiðsla (með vörum)","textPartialItems":"Ef þú vilt merkja magn og vörur sem endurgreiddar í Mollie, skaltu nota eyðublaðið hér að ofan. Stilltu magn og gefðu sérstaka upp fjárhæð fyrir hverja vöru sem verður endurgreidd. Heildarfjárhæðin mun þá vera sýnileg í textareitnum fyrir lokafjárhæðina. Mundu eftir því að enn er mögulegt að breyta þessari lokafjárhæð áður en þú hefur endurgreiðsluna.","titlePartialPromotions":"Hlutbundin endurgreiðsla (með afsláttum)","textPartialPromotions":"Ef þú ert með afslátt í innkaupakörfunni þinni, er afsláttirinn aðskilin línufærsla. Ef þú vilt endurgreiða allar afsláttarvörur, skaltu halda áfram og endurgreiða heildargildin þeirra og alla afsláttalínuvöruna sjálfa. Hins vegar, ef þú vilt aðeins endurgreiða nokkrar vörur sem voru afsláttarvörur, geturðu dregið af brúkuðum afslætti sjálfkrafa fyrir hverja einstaka línuvöru. Þú getur auðvitað alltaf breytt gildum ef þau eru vitlaus.","titleRoundingDiff":"Mismunur á námundun","textRoundingDiff":"Full endurgreiðsla mun fela í sér mismun í námundun"},"summary":{"dataLoading":"Gögn eru að hlaðast...","headerExcludingVat":"Án VSK","headerIncludingVat":"Með VSK","captionTotal":"Samtals","captionTotalTaxFree":"Samtals","captionPendingRefunds":"Bíð eftir endurgreiðslu","captionVouchers":"Upphæð ásláttarmiða","captionRefunded":"Fjárhæð sem endurgreidd","captionRemaining":"Fjárhæð sem hægt er að endurgreiða","btnFixDiff":"Laga mismun","placeholderDescription":"Sláðu inn lýsingu fyrir bankarreikning/kort fyrir neytandann. Að hámarki 140 stafir","lblDescription":"Lýsing (valfrjáls) ({characters}/140 stafir)","descriptionHelp":"Þetta verður sýnt í banka eða kortayfirliti neytandans þegar það er mögulegt. Skilaboðin verða stytt eftir 140 stafi.","placeholderInternalDescription":"Sláðu inn innri lýsingu þína","lblInternalDescription":"Innri lýsing (valfrjáls)","internalDescriptionHelp":"Þetta verður sýnt sem staðbundin lýsing í stjórnunaraðgerðunum.","checkVerification":"Ég hef staðfest heildarfjárhæð endurgreiðslu og samstilltan fjölda sem á að endurgreiða og birgja.","btnRefund":"Endurgreiðsla","btnFullRefund":"Full endurgreiðsla","roundDiffItemAdded":"Námundun hluts"},"refunds":{"title":"Endurgreiðslur í Mollie stjórnborðinu","linkMore":"Meira um endurgreiðslur","grid":{"columns":{"amount":"Fjárhæð","status":"Staða","description":"Lýsing","internalDescription":"Innri lýsing","composition":"Samsetning","date":"Dagsetning"},"lblNoComposition":"Engin samsetning tiltæk","btnCancelRefund":"Hætta við þessa endurgreiðslu"}},"notifications":{"success":{"refund-created":"Endurgreiðsla hefur verið stofnuð í Mollie. Það getur tekið allt að 2 klukkustundir að vinna endurgreiðsluna. Upp að því marki getur þú enn hætt við endurgreiðsluna.","refund-canceled":"Endurgreiðslan í bið hefur verið hætt við og fjarlægð með góðum árangri."},"error":{"low-amount":"Vinsamlegast sláðu inn upphæð sem á að endurgreiða.","refund-created":"Eitthvað fór úrskeiðis við stofnun endurgreiðslu.","refund-canceled":"Það kom upp vandamál þegar hætt var við endurgreiðsluna í bið. Vinsamlegast reyndu aftur í Mollie stjórnborðinu."}}},"vouchers":{"CARD_TITLE":"Afsláttarmiði","VOUCHER_INFO_TITLE":"Borgun afsláttarmiða","VOUCHER_INFO_DESCRIPTION":"Mollie gerir þér kleift að þiggja greiðslur auðveldlega í vefverslun þinni með Eco-, gjaf- og máltíðarafsláttarmiða — snjallur kostur til þess að auka hagnað og fullnægja viðskiptavinum þínum. Greiðslumátinn \\"afsláttarmiði\\" er aðeins sýnilegur ef þú hefur að minnsta kosti 1 vöru með tiltekinni tegund afsláttarmiða í verslunarkörfunni.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vinsamlegast athugaðu að þessa uppsetningu má aðeins breyta á þínu sjálfgefna tungumáli. Vinsamlegast breyttu tungumálinu þínu til að breyta tegund afsláttarmiða þessarar vöru.","VOUCHER_BTN_READMORE":"Lesa meira","VOUCHER_TYPE_CAPTION":"Tegund afsláttarmiða vörunnar","VOUCHER_TYPE_VALUE_NONE":"Enginn","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Máltíð","VOUCHER_TYPE_VALUE_VOUCHER":"Gjöf"},"modals":{"shipping":{"title":"Senda í gegnum Mollie","item":{"label":"Vara:","noQuantity":"Vinsamlegast sláðu inn fjölda til þess að hefja sendingu.","shipAll":"Senda allt","summary":{"quantity":"Fjöldi til sendingar","shipped":"Fjöldi sendur","shippable":"Fjöldi sem hægt er að senda"},"success":"Pöntun hefur verið send með góðum árangri."},"order":{"description":"Eftirfarandi hlutir gátu ekki verið sendir.","itemHeader":"Vara","quantityHeader":"Fjöldi","originalQuantityHeader":"Fjöldi (sem hægt er að senda)"},"availableTracking":{"label":"Tiltækir kóðar til rakningar","hint":"Smelltu á einn af þessum sendingarkóðum til að fylla sjálfvirkt út allar upplýsingar."},"showTracking":"Bæta við upplýsingar um sendingu fyrir þessa sendingu","tracking":{"carrier":"Flutningsaðili","code":"Kóði","url":"Url","invalid":"Vinsamlegast sláðu inn bæði flutningsaðila og kóða"},"confirmButton":"Senda pöntun","cancelButton":"Hætta við","selectAllButton":"Velja allt","resetButton":"Endurstilla"},"cancel":{"title":"Hætta við vöru í gegnum Mollie","confirmButton":"Hætta við vöru í gegnum Mollie","cancelButton":"Loka glugga","resetStock":"Endurstilla birgðir","item":{"success":"Vörunni hefur verið aflýst með góðum árangri","failed":{"quantityZero":"Fjöldi er 0","invalidLine":"Varan er ekki til í pöntuninni","quantityTooHigh":"Fjöldi er of hár"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Senda pöntun (Mollie)","description":"Senda pöntun í Mollie."},"modal":{"title":"Senda pöntun","description":"Þessi aðgerð mun sjálfkrafa senda pöntun í gegnum Mollie. Flæðisröðin mun taka á móti pöntunarnúmerinu og senda það á Mollie API. Árángursríkar sendingar og mislukkaðar sendingar munu sjást í skrám Mollie.","warningConfig":"Vinsamlegast vertu viss um að slökkva á allri viðbótar sjálfvirkni fyrir þessa tegund aðgerðar til að forðast truflanir.\\nVirkjaðir eiginleikarnar í þessari viðbót gætu truflað þessa aðgerð:","noWarnings":"Engar viðvaranir"}},"refundOrder":{"editor":{"title":"Endurgreiðsla pöntunar (Mollie)","description":"Endurgreiða pöntun í gegnum Mollie."},"modal":{"title":"Endurgreiðsla pöntunar","description":"Þessi aðgerð mun sjálfkrafa hefja endurgreiðslu í gegnum Mollie. Flæðisröðin mun taka á móti pöntunarnúmerinu og senda það á Mollie API. Árángursríkar endurgreiðslur og misheppanaðar endurgreiðslur munu sjást í Mollie skráningu.","warning":"Vinsamlegast hafðu í huga að það gæti tekið allt að 2 klukkustundir þar til endurgreiðslur eru sjáanlegar í verslun. Þangað til geturðu alltaf hætt við endurgreiðslu í vinnsly annað hvort frá pöntunarsíðunni í Shopware eða frá Mollie stjórnborðinu.","warningConfig":"Vinsamlegast vertu viss um að slökkva á allri viðbótar sjálfvirkni fyrir þessa tegund aðgerðar til að forðast truflanir."}},"warnings":{"automaticShipping":"Sjálfvirk sending í viðbótarstillingum"}}},"subscriptions":{"status":{"pending":"Í bið","active":"Virkur","canceled":"Hætt við","suspended":"Frestað","completed":"Lokið","paused":"Stöðvað","resumed":"Endurnýjað","skipped":"Sleppt"},"navigation":{"title":"Mollie áskriftir"},"TYPE_DAYS":"Dagur/dagar","TYPE_WEEKS":"Vika/vikur","TYPE_MONTHS":"Mánuður/mánuðir","confirm":{"cancelTitle":"Binda enda á áskrift?","cancel":"Hætta við áskrift viðskiptavinarins.","pauseTitle":"Stöðva áskrift?","pause":"Setji áskriftina á hlé þar til þú endurnýjar hana aftur.","resumeTitle":"Endurnýja áskrift?","resume":"Halda áfram áskriftinni aftur.","skipTitle":"Sleppa næstu greiðslu?","skip":"Sleppa næstu greiðslu í áskriftinni. Hún heldur áfram sjálfkrafa eftir það."},"alerts":{"cancelSuccess":"Hætt var við pöntun með góðum árangri","pauseSuccess":"Áskriftin hefur verið dregin í hlé með góðum árangri","resumeSuccess":"Áskriftin hefur verið endurnýjuð með góðum árangri","skipSuccess":"Áskriftinni hefur verið sleppt með góðum árangri. Næsta greiðsla hefur verið uppfærð."},"list":{"title":"Mollie áskriftir","columns":{"customer":"Viðskiptavinur","status":"Staða","description":"Lýsing","amount":"Upphæð","nextPaymentAt":"Næsta greiðsla","prePaymentReminder":"Áminning á","canceledAt":"Hætt við á","createdAt":"Búið til á"},"action":{"edit":"Breyta áskrift"},"deletedCustomer":"Eyddur viðskiptavinur"},"detail":{"title":"Mollie áskrift","buttonCancelSubscription":"Hætta við áskrift","labelDescription":"Lýsing","labelAmount":"Upphæð","labelQuantity":"Magn","labelMollieSubscription":"Mollie áskrift","labelMollieCustomer":"Mollie viðskiptavinur","labelMandateId":"Umboð","labelShopwareCustomer":"Shopware viðskiptavinur","labelCreatedAt":"Búið til á","buttonShowShopwareOrder":"Sýna Shopware pöntun","buttonShowShopwareCustomer":"Sýna Shopware viðskiptavin","cardTitleSubscription":"Áskrift","cardTitleStatus":"Staða","labelStatus":"Staða","labelNextPaymentAt":"Næsta greiðsla á","labelLastRemindedAt":"Síðast áminnt á","labelCanceledAt":"Afskráð á","buttonPauseSubscription":"Stöðva áskrift","buttonResumeSubscription":"Hefja áskrift aftur","buttonSkipSubscription":"Sleppa áskrift","history":{"cardTitle":"Saga","colDate":"Dagsetning","colComment":"Athugasemd","colStatusFrom":"Staða (frá)","colStatusTo":"Staða (til)","colMollieSubscription":"Mollie áskrift"}},"product":{"card-title":"Áskrift","title":"Mollie áskriftir","description":"Að stýra endurteknum greiðslum er auðveldari en nokkru sinni fyrr með nytsamlegu eiginleikunum okkar. Færðu fyrirtæki þitt á næsta stig með virkri eftirfylgni, einföldum samþættingum og fleiru. Með Mollie áskriftum geturðu auðveldlega skapað áskriftarvörur og skipulagt endurteknar greiðslur sem eiga að eiga sér stað á tilskildnu tímabili.","mollieSubscriptionProduct":"Áskriftarvara","mollieSubscriptionIntervalAmount":"Endurtaka greiðslu á hverju","mollieSubscriptionIntervalType":"Tímabilseining","mollieSubscriptionRepetitionAmount":"Fjöldi eða endurtekningar","mollieSubscriptionRepetitionPlaceholder":"Sláðu inn fjölda eða skildu eftir autt","infoDefaultLanguage":"Vinsamlegast athugið að þessi uppsetning er aðeins breytanleg á þínu staðal tungumáli. Vinsamlegast breyttu tungumálinu þínu til að breyta áskriftarstillingum á þessari vöru.","btnReadMore":"Lesa meira"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Áskrift"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kreditkortagögn",buttonMolliePaymentLink:"Afrita í klippibúnað",columnRefunded:"Endurgreitt",columnShipped:"Sent",columnCanceled:"Hætt við",labelMollieOrderId:"Mollie pöntunar ID",labelMollieThirdPartyPaymentId:"Greiðsluauðkenni",labelMolliePaymentLink:"Mollie Afgreiðsla URL",totalRefunds:"Endurgreidd upphæð",totalRefundsPending:"Bíð eftir endurgreiðslu",totalRemaining:"Endurgreidd upphæð",totalVouchers:"Magn afsláttarmiða",totalShipments:"Send upphæð ({quantity} vörur)",subscriptionBadge:"Pöntun áskriftar",refundManager:{title:"Mollie endurgreiðslustjóri",btnOpenRefundManager:"Opna endurgreiðslustjóra",btnCloseRefundManager:"Loka endurgreiðslustjóra"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Ákjósanlegur iDeal útgefandi"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Endurgreiðslustjóri"},mollie_subscription:{label:"Áskriftir"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Lýsing"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Endurgreiðsla",subscription:"Áskrift",webhookReceived:"Webhooks",status:"Staða",started:"Byrjað",ended:"Lokið",paused:"Stöðvað",renewalReminder:"Áminning um endurnýjun",renewed:"Endurnýjað",resumed:"Hafið aftur",skipped:"Sleppt",all:"Allt",canceled:"Hætt við",expired:"Útrunnið",partiallyRefunded:"Endurgreitt (að hluta til)",orderSuccess:"Pöntun árángursrík",orderFailed:"Pöntun misheppnaðist",orderCanceled:"Hætt við pöntun"}}},Mq={entities:{mollie_subscription:"Mollie prenumerata | Mollie prenumeratos"},businessEvents:{mollie_checkout_order_success:"Užsakymas sėkmingas",mollie_checkout_order_failed:"Užsakymas nepavyko",mollie_checkout_order_canceled:"Užsakymas atšauktas",mollie_webhook_received_All:"Gautas Mollie Webhook (Visi)",mollie_webhook_received_status_authorized:"Gautas Mollie Webhook (Autorizuota)",mollie_webhook_received_status_failed:"Gautas Mollie Webhook (Nepavykęs)",mollie_webhook_received_status_canceled:"Gautas Mollie Webhook (Atšauktas)",mollie_webhook_received_status_expired:"Gautas Mollie Webhook (Pasibaigęs)",mollie_webhook_received_status_pending:"Gautas Mollie Webhook (Laukiamas)",mollie_webhook_received_status_paid:"Gautas Mollie Webhook (Apmokėta)",mollie_webhook_received_status_completed:"Gautas Mollie Webhook (Įvykdyta)",mollie_webhook_received_status_refunded:"Gautas Mollie Webhook (Grąžinta)",mollie_webhook_received_status_partially_refunded:" Gautas Mollie Webhook (Iš dalies grąžinta)",mollie_refund_started:"Mollie grąžinimo procesas pradėtas",mollie_subscription_started:"Mollie prenumerata pradėta",mollie_subscription_ended:"Mollie prenumerata įvykdyta",mollie_subscription_cancelled:"Mollie prenumerata atšaukta",mollie_subscription_paused:"Mollie prenumerata sustabdyta",mollie_subscription_resumed:"Mollie prenumerata atnaujinta",mollie_subscription_skipped:"Mollie prenumerata praleista",mollie_subscription_renewed:"Mollie prenumerata atnaujinta",mollie_subscription_renewal_reminder:"Mollie priminimas apie prenumeratos atnaujinimą"}},Pq={global:Mq,"mollie-payments":JSON.parse('{"pluginTitle":"Mollie","pluginDescription":"Mollie modulis","searchPlaceholder":"Ieškoti prenumeratų...","general":{"mainMenuItemGeneral":"Mollie mokėjimai","descriptionTextModule":"Mollie mokėjimai","btnMollieActions":"Mollie veiksmai","refundThroughMollie":"Grąžinti per Mollie","shipThroughMollie":"Siųsti per Mollie","cancelMollieItem":"Atšaukti per Mollie"},"config":{"info":{"title":"Labas {userName}, Sveiki atvykę į Mollie!","descriptionTop":"Integracija su Mollie yra paprasta!","descriptionBottom":"Tai viskas!","descriptionFooter":"Jei norite sužinoti daugiau apie mūsų papildinį, apsilankykite oficialiame dokumentacijos puslapyje.","onboardingStep1":"Užsiregistruokite Mollie paskyrai.","onboardingStep2":"Įveskite savo API raktus į žemiau esančią eilutę.","onboardingStep2TestMode":"Įjunkite „Testavimo režimą“, jei norite tik išbandyti mokėjimus.","onboardingStep3":"Priskirkite mokėjimo būdus savo pardavimų kanalui.","onboardingStep3Link":"į jūsų pardavimo kanalus","btnDocumentation":"Dokumentacija","btnRequestSupport":"Pagalba","btnTroubleshooting":"Problemų sprendimo vadovas"},"api":{"apiLinkButton":"Gaukite savo API raktais iš Mollie Dashboard","testButton":"Testuoti API raktus","testApiKeys":{"title":"Mollie mokėjimai","apiKey":"API raktas","isValid":"yra galiojantis","isInvalid":"yra negaliojantis"}},"payments":{"format":{"placeholder":"Vietaženklis","preview":"Peržiūra"},"updatePaymentMethods":{"title":"Mollie mokėjimai","button":"Atnaujinti mokėjimo būdus","succeeded":"Mokėjimo metodai sėkmingai atnaujinti.","failed":"Nepavyko atnaujinti mokėjimo būdų."},"mollieLimits":{"link":"Rodyti mollie prieinamumo taisykles mokėjimo būdams"}},"rounding":{"info1":"„Shopware“ gali naudoti valiutos nustatymus, kad apskaičiuotų, kaip suapvalinti bendrą užsakymo sumą. Tai apima skaičių po kablelio jūsų produktų kainose ir artimiausią apvalinimo intervalą, pavyzdžiui, 0,50 arba 1,00.","info2":"Šie nustatymai gali lemti kitokią bendrą užsakymo sumą nei eilučių elementų suma. Kai Mollie patikrina šias sumas ir nustato, kad jos nesutampa, įvyksta atsiskaitymo klaida.","info3":"Šią funkciją galite naudoti, kad išvengtumėte apvalinimo problemų atsiskaitymo metu. Įjungus, Mollie paskyros suvestinėje bus pridėta atskira eilutė su apvalinimo skirtumu, o klientai mokės bendrą sumą, apskaičiuotą „Shopware“."},"order":{"bankTransferDueDateKlarnaLimitReached":"Negalima naudoti Klarna Pay now, Klarna Slice it ar Klarna Pay later kaip mokėjimo būdo, jei jūsų galiojimo pabaigos data yra daugiau nei 28 dienos į priekį, nebent prekybininkas ir Klarna yra susitarę dėl kito maksimalaus termino.","bankTransferDueDateLimitReached":"Negalima nustatyti užsakymo galiojimo trukmės ilgesnės, nei 100 dienų."},"support":{"modalTitle":"Prašykite pagalbos iš Mollie","btnCancel":"Atšaukti","btnConfirm":"Prašyti pagalbos","btnSupport":"Daugiau apie mūsų pagalbą","form":{"name":"Jūsų vardas","email":"Jūsų el. paštas","recipient":"Siųsti prašymą","subject":"Tema","message":"Žinutė"},"data":{"header":"Duomenys, išsiųsti Mollie:","other":"Kita:","shopwareVersion":"„Shopware“ versija","pluginLogs":"{plugin} žurnalo failai","pluginConfiguration":"{plugin} nustatymai","pluginConfigurationHelpText":"API raktai yra neįtraukti.","paymentMethods":"Mokėjimo būdo duomenys","paymentMethodsHelpText":"Įtraukta informacija apie tai, kurie mokėjimo būdai yra aktyvūs, priskirti kiekvienam pardavimo kanalui, taip pat apie jų būseną jūsų Mollie paskyroje."},"success":"Pagalbos užklausa buvo sėkmingai išsiųsta. Mes pasistengsime atsakyti kuo greičiau","error":"Siunčiant laišką per „Shopware“ įvyko klaida. Bandykite dar kartą arba susisiekite su mumis tiesiogiai el. paštu."}},"rules":{"itemSubscriptionRule":"Prekė yra prenumerata (Mollie)","cartSubscriptionRule":"Krepšelis su prenumeratomis (Mollie)"},"refunds":{"status":{"queued":"Eilėje","pending":"Laukiama","processing":"Apdorojama","refunded":"Grąžinta","failed":"Nepavykęs","description":{"queued":"Grąžinimas įtrauktas į eilę, kol bus pakankamai lėšų jo apdorojimui. Vis dar galite atšaukti šį grąžinimą.","pending":"Grąžinimas bus išsiųstas į banką kitą darbo dieną. Vis dar galite atšaukti šį grąžinimą.","processing":"Grąžinimas buvo išsiųstas į banką. Grąžinama suma bus pervesta į vartotojo sąskaitą kuo greičiau.","refunded":"Grąžinimo suma buvo pervesta vartotojui.","failed":"Grąžinimas nepavyko po apdorojimo. Pavyzdžiui, klientas uždarė savo banko sąskaitą. Lėšos bus grąžintos į jūsų sąskaitą."}}},"refund-manager":{"general":{"unitQuantity":"vnt."},"acl":{"warningCreate":"Neturite leidimo kurti grąžinimų","warningCancel":"Neturite leidimo atšaukti grąžinimų"},"cart":{"title":"Užsakymas ##orderNumber##","btnSelectAll":"Pasirinkti viską","btnResetForm":"Iš naujo nustatyti formą","linkHowTo":"Kaip naudoti šią formą?","grid":{"columns":{"item":"Prekė","productNumber":"Prekės numeris","unitPrice":"Vieneto kaina","quantity":"Kiekis","refunded":"Grąžinta","refundQuantity":"Grąžinimas","totalPrice":"Iš viso","refundAmount":"Grąžinimas","resetStock":"Iš naujo nustatyti atsargas"},"btnResetLine":"Iš naujo nustatyti eilutę","checkDeductPromotion":"Atimti nuolaidą","checkRefundTax":"Grąžinti PVM"},"roundDiffItemAdded":"Automatinis suapvalinimo elementas buvo pridėtas"},"instructions":{"linkResetTutorials":"Iš naujo nustatyti mokymus","btnToggleTutorial":"Rodyti/Slėpti mokymą","titleFullRefund":"Pilnas grąžinimas","textFullRefund":"Tiesiog naudokite mygtuką visam grąžinimui. Taip užtikrinama, kad visos jūsų prekės bus pažymėtos kaip grąžintos ir visa suma bus grąžinta klientui.","titleStockReset":"Atsargų atnaujinimas","textStockReset":"Galite automatiškai padidinti turimą atsargų kiekį, įvesdami kiekį, kurį norite grąžinti į sandėlį. Tiesiog įveskite jį prieš atlikdami visą arba dalinį grąžinimą. Atsargų atnaujinimą galima lanksčiai derinti su faktiniu grąžinimo procesu.","titleShipping":"Siuntimas","textShipping":"Siunimo prekes galima grąžinti kaip bet kurią kitą prekę. Įveskite visą kiekį arba nurodykite pasirinktą dalinę sumą ir tęskite grąžinimo procesą. Siuntimo išlaidų grąžinimas gali būti derinamas su faktiniu prekių grąžinimo procesu lanksčiu būdu.","titlePartialAmount":"Dalinis grąžinimas (tik suma)","textPartialAmount":"Tiesiog įveskite dalinę sumą į teksto laukelį ir pradėkite grąžinimą.","titlePartialItems":"Dalinis grąžinimas (su prekėmis)","textPartialItems":"Jei norite „Mollie“ sistemoje pažymėti kiekius ir prekes kaip grąžintas, naudokite aukščiau esančią formą. Nustatykite kiekius ir nurodykite pasirinktą sumą kiekvienai grąžinamai prekei. Bendra suma bus matoma galutinės grąžinimo sumos laukelyje. Prisiminkite, kad prieš pradėdami grąžinimą vis dar galite pakoreguoti šią galutinę sumą.","titlePartialPromotions":"Dalinis grąžinimas (su nuolaidomis)","textPartialPromotions":"Jei jūsų krepšelyje yra akcija, ji pateikiama kaip atskira eilutė. Jei norite grąžinti visas su nuolaida įsigytas prekes, grąžinkite jų bendras vertes ir visą akcijos eilutę. Tačiau jei norite grąžinti tik kelias nuolaidas gavusias prekes, galite automatiškai atimti pritaikytą nuolaidą kiekvienai eilutei atskirai. Žinoma, visada galite pakeisti vertes, jei jos neteisingos.","titleRoundingDiff":"Apvalinimo skirtumas","textRoundingDiff":"Visos sumos grąžinimas apims ir apvalinimo skirtumus"},"summary":{"dataLoading":"Duomenys kraunami...","headerExcludingVat":"Be PVM","headerIncludingVat":"Įskaitant PVM","captionTotal":"Iš viso","captionTotalTaxFree":"Iš viso","captionPendingRefunds":"Laukiama grąžinimo","captionVouchers":"Kupono suma","captionRefunded":"Grąžinta suma","captionRemaining":"Grąžinama suma","btnFixDiff":"Ištaisyti skirtumą","placeholderDescription":"Įveskite banko / kortelės išrašo aprašymą vartotojui. Daugiausia 140 simbolių","lblDescription":"Aprašymas (neprivalomas) ({characters}/140 simbolių)","descriptionHelp":"Kai įmanoma, tai bus rodoma vartotojo banko ar kortelės išraše. Pranešimas bus sutrumpintas po 140 simbolių.","placeholderInternalDescription":"Įveskite savo vidinį aprašymą","lblInternalDescription":"Vidinis aprašymas (neprivalomas)","internalDescriptionHelp":"Tai bus rodoma kaip vietinis aprašymas administravimo sąsajoje.","checkVerification":"Aš patikrinau visą grąžinamą sumą ir nustatytus kiekius grąžinimui bei grąžinimui į sandėlį.","btnRefund":"Grąžinimas","btnFullRefund":"Pilnas grąžinimas","roundDiffItemAdded":"Apvalinimo elementas"},"refunds":{"title":"Grąžinimai Mollie suvestinėje","linkMore":"Daugiau apie grąžinimus","grid":{"columns":{"amount":"Suma","status":"Statusas","description":"Aprašymas","internalDescription":"Vidinis aprašymas","composition":"Sudėtis","date":"Data"},"lblNoComposition":"Sudėtis neprieinama","btnCancelRefund":"Atšaukti šį grąžinimą"}},"notifications":{"success":{"refund-created":"Grąžinimas buvo sukurtas Mollie. Gali užtrukti iki 2 valandų, kol grąžinimas bus užbaigtas. Iki šio laiko galite atšaukti grąžinimą.","refund-canceled":"Laukiantis grąžinimas sėkmingai atšauktas ir pašalintas."},"error":{"low-amount":"Prašome įvesti sumą, kurią reikia grąžinti.","refund-created":"Įvyko klaida kuriant grąžinimą.","refund-canceled":"Atšaukiant grąžinimą įvyko klaida. Bandykite dar kartą Mollie suvestinėje."}}},"vouchers":{"CARD_TITLE":"Kuponas","VOUCHER_INFO_TITLE":"Kupono mokėjimai","VOUCHER_INFO_DESCRIPTION":"Mollie leidžia lengvai priimti mokėjimus savo internetinėje parduotuvėje, naudojant ekologiškus, dovanų ir valgio kuponus – išmanus pasirinkimas padedantis didinti pardavimus ir patenkinti jūsų klientus. Mokėjimo būdas „kuponas“ bus matomas tik tuo atveju, jei krepšelyje yra bent 1 produktas su priskirtu kupono tipu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Atkreipkite dėmesį, kad šis nustatymas gali būti redaguojamas tik jūsų numatyta kalba. Norėdami pakeisti šio produkto kupono tipą, pakeiskite kalbą.","VOUCHER_BTN_READMORE":"Skaityti daugiau","VOUCHER_TYPE_CAPTION":"Kuponų produkto tipas","VOUCHER_TYPE_VALUE_NONE":"Nėra","VOUCHER_TYPE_VALUE_ECO":"Ekologiškas","VOUCHER_TYPE_VALUE_MEAL":"Patiekalas","VOUCHER_TYPE_VALUE_VOUCHER":"Dovana"},"modals":{"shipping":{"title":"Siųsti per Mollie","item":{"label":"Prekė:","noQuantity":"Prašome įvesti kiekį, kuris bus siųstas.","shipAll":"Siųsti viską","summary":{"quantity":"Kiekis, kurį reikia siųsti","shipped":"Išsiųstas kiekis","shippable":"Kiekis, kuris gali būti siunčiamas"},"success":"Užsakymas buvo sėkmingai išsiųstas."},"order":{"description":"Šios prekės kiekiai bus siunčiami.","itemHeader":"Prekė","quantityHeader":"Kiekis","originalQuantityHeader":"Kiekis (kuris gali būti siunčiamas)"},"availableTracking":{"label":"Pasiekiami sekimo kodai","hint":"Paspauskite vieną iš šių sekimo kodų, kad automatiškai užpildytumėte visus duomenis."},"showTracking":"Pridėti siuntos sekimo informaciją","tracking":{"carrier":"Vežėjas","code":"Kodas","url":"Url","invalid":"Prašome įvesti tiek Vežėją, tiek Kodą"},"confirmButton":"Siųsti užsakymą","cancelButton":"Atšaukti","selectAllButton":"Pasirinkti viską","resetButton":"Atstatyti"},"cancel":{"title":"Atšaukti prekę per Mollie","confirmButton":"Atšaukti prekę per Mollie","cancelButton":"Uždaryti modalą","resetStock":"Iš naujo nustatyti atsargas","item":{"success":"Produktas sėkmingai atšauktas","failed":{"quantityZero":"Kiekis yra 0","invalidLine":"Produktas neegzistuoja užsakyme","quantityTooHigh":"Kiekis yra per didelis"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Siųsti užsakymą (Mollie)","description":"Siųsti užsakymą per Mollie."},"modal":{"title":"Siųsti užsakymą","description":"Šis veiksmas automatiškai išsiųs užsakymą per Mollie. Veiksmų seka gaus užsakymo numerį ir perduos jį Mollie API. Sėkmingi ir nesėkmingi siuntimai bus matomi Mollie žurnalo failuose.","warningConfig":"Įsitikinkite, kad šiam veiksmui išjungėte bet kokią papildomą automatiką, kad išvengtumėte trukdžių.\\nŠios papildomos funkcijos gali trukdyti šiam veiksmui:","noWarnings":"Įspėjimų nėra"}},"refundOrder":{"editor":{"title":"Grąžinti užsakymą (Mollie)","description":"Grąžinti užsakymą per Mollie."},"modal":{"title":"Grąžinti užsakymą","description":"Šis veiksmas automatiškai pradės grąžinimą per Mollie. Šis procesas gaus užsakymo numerį ir perduos jį Mollie API. Sėkmingi ir nesėkmingi grąžinimai bus matomi Mollie žurnalo failuose.","warning":"Atminkite, kad grąžinimų užbaigimas ir jų matomumas parduotuvėje gali užtrukti iki 2 valandų. ki tol visada galite atšaukti laukiantį grąžinimą iš užsakymo puslapio Shopware sistemoje arba iš Mollie suvestinės.","warningConfig":"Įsitikinkite, kad šiam veiksmui išjungėte bet kokią papildomą automatiką, kad išvengtumėte trukdžių."}},"warnings":{"automaticShipping":"Automatinis siuntimas papildinio nustatymuose"}}},"subscriptions":{"status":{"pending":"Laukiama","active":"Aktyvus","canceled":"Atšauktas","suspended":"Sustabdytas","completed":"Įvykdyta","paused":"Sustabdyta","resumed":"Atnaujinta","skipped":"Praleista"},"navigation":{"title":"Mollie Prenumeratos"},"TYPE_DAYS":"Diena(-os)","TYPE_WEEKS":"Savaitė(s)","TYPE_MONTHS":"Mėnuo(-esiai)","confirm":{"cancelTitle":"Atšaukti prenumeratą?","cancel":"Atšaukti jūsų kliento prenumeratą.","pauseTitle":"Sustabdyti prenumeratą?","pause":"Sustabdykite prenumeratą, kol vėl ją atnaujinsite.","resumeTitle":"Atnaujinti prenumeratą?","resume":"Tęskite prenumeratą dar kartą.","skipTitle":"Praleisti kitą mokėjimą?","skip":"Praleiskite kitą prenumeratos mokėjimą. Vėliau ji tęsis automatiškai."},"alerts":{"cancelSuccess":"Prenumerata sėkmingai atšaukta","pauseSuccess":"Prenumerata sėkmingai sustabdyta","resumeSuccess":"Prenumerata sėkmingai atnaujinta","skipSuccess":"Prenumerata sėkmingai praleista. Kitas mokėjimas buvo atnaujintas."},"list":{"title":"Mollie prenumeratos","columns":{"customer":"Klientas","status":"Statusas","description":"Aprašymas","amount":"Suma","nextPaymentAt":"Kitas mokėjimas","prePaymentReminder":"Priminta","canceledAt":"Atšauktas","createdAt":"Sukurtas"},"action":{"edit":"Redaguoti prenumeratą"},"deletedCustomer":"Ištrintas klientas"},"detail":{"title":"Mollie prenumerata","buttonCancelSubscription":"Atšaukti prenumeratą","labelDescription":"Aprašymas","labelAmount":"Suma","labelQuantity":"Kiekis","labelMollieSubscription":"Mollie prenumerata","labelMollieCustomer":"Mollie klientas","labelMandateId":"Įgaliojimas","labelShopwareCustomer":"Shopware klientas","labelCreatedAt":"Sukurtas","buttonShowShopwareOrder":"Rodyti Shopware užsakymą","buttonShowShopwareCustomer":"Rodyti Shopware klientą","cardTitleSubscription":"Prenumerata","cardTitleStatus":"Statusas","labelStatus":"Statusas","labelNextPaymentAt":"Kitas mokėjimas","labelLastRemindedAt":"Paskutinį kartą priminta","labelCanceledAt":"Atšauktas","buttonPauseSubscription":"Sustabdyti prenumeratą","buttonResumeSubscription":"Pratęsti prenumeratą","buttonSkipSubscription":"Praleisti prenumeratą","history":{"cardTitle":"Istorija","colDate":"Data","colComment":"Komentaras","colStatusFrom":"Statusas (iš)","colStatusTo":"Statusas (į)","colMollieSubscription":"Mollie prenumerata"}},"product":{"card-title":"Prenumerata","title":"Mollie prenumeratos","description":"Tvarkyti jūsų periodinius mokėjimus dabar lengviau nei bet kada su mūsų naudingomis funkcijomis. Pakelkite savo verslą į aukštesnį lygį naudodamiesi efektyvaus sekimo galimybėmis, paprastomis integracijomis ir dar daugiau. Su Mollie prenumeratomis galite lengvai kurti prenumeratos produktus ir suplanuoti periodinius mokėjimus pasirinktu intervalu bei laikotarpiu.","mollieSubscriptionProduct":"Prenumeratos produktas","mollieSubscriptionIntervalAmount":"Kartoti mokėjimą kas","mollieSubscriptionIntervalType":"Intervalo vienetas","mollieSubscriptionRepetitionAmount":"Pasikartojimų skaičius","mollieSubscriptionRepetitionPlaceholder":"Įveskite skaičių arba palikite tuščią","infoDefaultLanguage":"Prašome atkreipti dėmesį, kad šis nustatymas gali būti redaguojamas tik jūsų numata kalba. Prašome pakeisti savo kalbą norint pakeisti produkto prenumeratos nustatymus.","btnReadMore":"Skaityti daugiau"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Prenumerata"}}'),"sw-order":{detailExtended:{titleCreditCardData:"Kredito kortelės duomenys",buttonMolliePaymentLink:"Kopijuoti į iškarpinę",columnRefunded:"Grąžinta",columnShipped:"Išsiųsta",columnCanceled:"Atšaukta",labelMollieOrderId:"Mollie užsakymo ID",labelMollieThirdPartyPaymentId:"Mokėjimo nuoroda",labelMolliePaymentLink:"Mollie atsiskaitymo URL",totalRefunds:"Grąžinta suma",totalRefundsPending:"Laukiama grąžinimo",totalRemaining:"Grąžinama suma",totalVouchers:"Kupono suma",totalShipments:"Išsiųsta suma ({quantity} daiktai)",subscriptionBadge:"Prenumeratos užsakymas",refundManager:{title:"Mollie grąžinimų valdymas",btnOpenRefundManager:"Atidaryti grąžinimų tvarkyklę",btnCloseRefundManager:"Uždaryti grąžinimų tvarkyklę"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Pageidaujamas iDEAL bankas"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Grąžinimų tvarkyklė"},mollie_subscription:{label:"Prenumeratos"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Aprašymas"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Grąžinimas",subscription:"Prenumerata",webhookReceived:"Webhooks",status:"Statusas",started:"Pradėta",ended:"Baigta",paused:"Sustabdyta",renewalReminder:"Atnaujinimo priminimas",renewed:"Atnaujinta",resumed:"Pratęsta",skipped:"Praleista",all:"Visi",canceled:"Atšaukta",expired:"Pasibaigęs",partiallyRefunded:"Grąžinta (dalinai)",orderSuccess:"Užsakymas sėkmingas",orderFailed:"Užsakymas nepavyko",orderCanceled:"Užsakymas atšauktas"}}},Tq={entities:{mollie_subscription:"Mollie Subscription | Mollie Subscriptions"},businessEvents:{mollie_checkout_order_success:"Pasūtījums veiksmīgs ",mollie_checkout_order_failed:" Pasūtījums neizdevās",mollie_checkout_order_canceled:" Pasūtījums atcelts",mollie_webhook_received_All:" Mollie Webhook Saņemts (Visi)",mollie_webhook_received_status_authorized:"Mollie tīmekļa āķi saņemti (Autorizēti)",mollie_webhook_received_status_failed:"Mollie tīmekļa āķi saņemti (Neizdevušies)",mollie_webhook_received_status_canceled:"Mollie tīmekļa āķi saņemti (Atcelti)",mollie_webhook_received_status_expired:"Mollie tīmekļa āķi saņemti (Beigušies)",mollie_webhook_received_status_pending:"Mollie tīmekļa āķi saņemti (Procesā esoši)",mollie_webhook_received_status_paid:"Mollie tīmekļa āķi saņemti (Samaksāti)",mollie_webhook_received_status_completed:"Mollie tīmekļa āķi saņemti (Pabeigti)",mollie_webhook_received_status_refunded:"Mollie tīmekļa āķi saņemti (Atmaksāti)",mollie_webhook_received_status_partially_refunded:"Mollie tīmekļa āķi saņemti (Daļēji Atmaksāti)",mollie_refund_started:"Mollie atmaksa sākta",mollie_subscription_started:" Sākta Mollie abonēšana",mollie_subscription_ended:" Mollie abonēšana pabeigta",mollie_subscription_cancelled:"Mollie abonements atcelts",mollie_subscription_paused:"Mollie abonements apturēts",mollie_subscription_resumed:"Mollie abonements atsākts",mollie_subscription_skipped:"Mollie abonements izlaists",mollie_subscription_renewed:"Mollie abonements atjaunots",mollie_subscription_renewal_reminder:"Mollie atgādinājums par abonementa atjaunošanu"}},Iq={global:Tq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Meklēt abonementus...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie darbības","refundThroughMollie":"Atmaksa caur Mollie","shipThroughMollie":"Nosūtīt caur Mollie","cancelMollieItem":"Atcelt caur Mollie"},"config":{"info":{"title":"Sveiks {userName}, laipni lūdzam Mollie!","descriptionTop":"Iepazīšanās ar Mollie ir vienkārša!","descriptionBottom":"Tas ir viss!","descriptionFooter":"Ja vēlies uzzināt vairāk par mūsu spraudni, lūdzu, apmeklē mūsu oficiālo dokumentācijas lapu.","onboardingStep1":"Reģistrēties Mollie kontam.","onboardingStep2":"Ievadiet savas API atslēgas zemāk esošajā sadaļā.","onboardingStep2TestMode":"Ieslēdziet 'Testa režīmu', ja vēlaties tikai izmēģināt maksājumus.","onboardingStep3":"Piešķiriet maksājuma metodes savam pārdošanas kanālam.","onboardingStep3Link":"uz jūsu pārdošanas kanāliem","btnDocumentation":"Dokumentācija","btnRequestSupport":"Atbalsts","btnTroubleshooting":"Problēmu novēršanas rokasgrāmata"},"api":{"apiLinkButton":"Iegūstiet savas API atslēgas no Mollie Dashboard","testButton":"Test API atslēgas","testApiKeys":{"title":"Mollie Payments","apiKey":"API atslēga","isValid":"ir derīga","isInvalid":"ir nederīga"}},"payments":{"format":{"placeholder":"Aizvietotājs","preview":"Priekšskatījums"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Atjaunot maksājumu metodes","succeeded":"Maksājumu metodes veiksmīgi atjaunotas.","failed":"Maksājuma metodes nevarēja tikt atjauninātas."},"mollieLimits":{"link":"Rādīt Mollie pieejamības noteikumus maksājumu metodēm"}},"rounding":{"info1":"Shopware var izmantot valūtas iestatījumus, lai aprēķinātu, kā tas noapaļo pasūtījuma kopējo summu. Tas ietver decimāldaļu skaitu jūsu produktu cenās un tuvāko noapaļošanas intervālu, piemēram, 0.50 vai 1.00.","info2":"Šie iestatījumi var novest pie kopējās summas, kas atšķiras no rindu elementu kopējās summas. Kad Mollie pārbauda šos apmērus un atklāj, ka tie nesakrīt, tas apmaksas kases kļūdu.","info3":"Šo funkciju varat izmantot, lai izvairītos no noapaļošanas problēmām jūsu apmaksā. Kad tā ir iespējota, tā pievieno atsevišķu rindu jūsu Mollie vadības panelī par starpību noapaļošanā, un jūsu klienti samaksā kopējo summu, ko aprēķina Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nav iespējams izmantot Klarna Pay now, Klarna Slice it vai Klarna Pay later kā metodi, kad jūsu derīguma termiņš ir vairāk nekā 28 dienas nākotnē, ja vien tirgotājs un Klarna nav vienojušies par citu maksimumu.","bankTransferDueDateLimitReached":"Nav iespējams iestatīt pasūtījuma ilgumu ilgāk par 100 dienām."},"support":{"modalTitle":"Pieprasīt Mollie atbalstu","btnCancel":"Atcelt","btnConfirm":"Pieprasīt atbalstu","btnSupport":"Vairāk par mūsu atbalstu","form":{"name":"Jūsu vārds","email":"Jūsu e-pasts","recipient":"Nosūtīt pieprasījumu uz","subject":"Temats","message":"Ziņojums"},"data":{"header":"Dati nosūtīti uz Mollie:","other":"Citi:","shopwareVersion":"Shopware versija","pluginLogs":"{plugin} žurnāla faili","pluginConfiguration":"{plugin} konfigurācija","pluginConfigurationHelpText":"API atslēgas ir izslēgtas.","paymentMethods":"Maksājumu metodes informācija","paymentMethodsHelpText":"Satur informāciju par to, kuras maksājuma metodes ir aktīvas un piešķirtas katram pārdošanas kanālam, kā arī to statusu jūsu Mollie kontā."},"success":"Atbalsta pieprasījums ir veiksmīgi nosūtīts. Mēs darām visu iespējamo, lai atbildētu cik ātri vien iespējams.","error":"Radās problēma, nosūtot e-pastu caur Shopware. Lūdzu, mēģiniet vēlreiz vai sazinieties ar mums tieši pa e-pastu."}},"rules":{"itemSubscriptionRule":"Prece ir abonements (Mollie)","cartSubscriptionRule":"Grozs ar abonementiem (Mollie)"},"refunds":{"status":{"queued":"Kārtots","pending":"Procesā esošs","processing":"Apstrādā","refunded":"Atmaksāts","failed":"Neizdevies","description":{"queued":"Atmaksa ir kārtota, līdz ir pietiekams atlikums, lai apstrādātu atmaksu. Jūs joprojām varat atcelt atmaksu.","pending":"Atmaksa tiks nosūtīta uz banku nākamajā darba dienā. Jūs joprojām varat atcelt atmaksu.","processing":"Atmaksa ir nosūtīta uz banku. Atmaksātā summa tiks pārskaitīta uz patērētāja kontu pēc iespējas ātrāk.","refunded":"Atmaksas summa ir pārsūtīts patērētājam.","failed":"Atmaksa neizdevās pēc apstrādes. Piemēram, klients ir slēdzis savu bankas kontu. Līdzekļi tiks atgriezti jūsu kontā."}}},"refund-manager":{"general":{"unitQuantity":"gab."},"acl":{"warningCreate":"Jums nav atļauju veidot atmaksas","warningCancel":"Jums nav atļauju atcelt atmaksas"},"cart":{"title":"Pasūtījums ##orderNumber##","btnSelectAll":"Atlasīt visus","btnResetForm":"Atjaunot formu","linkHowTo":"Kā izmantot šo formu?","grid":{"columns":{"item":"Prece","productNumber":"Produkta numurs","unitPrice":"Vienības cena","quantity":"Daudzums","refunded":"Atmaksāts","refundQuantity":"Atmaksa","totalPrice":"Kopā","refundAmount":"Atmaksa","resetStock":"Atjaunot krājumus"},"btnResetLine":"Atiestatīt rindu","checkDeductPromotion":"Atcelt akciju","checkRefundTax":"Atmaksāt PVN"},"roundDiffItemAdded":"Automātiskā noapaļošanas vienība tika pievienota"},"instructions":{"linkResetTutorials":"Atjaunot apmācības","btnToggleTutorial":"Rādīt/Slēpt apmācību","titleFullRefund":"Pilna atmaksa","textFullRefund":"Vienkārši izmantojiet pogu pilnīgai atmaksai. Tas nodrošina, ka visas jūsu preces tiek atzītas par atgrieztām un pilna summa tiek atgriezta klientam.","titleStockReset":"Krājuma atiestatīšana","textStockReset":"Jūs varat automātiski palielināt pieejamo krājumu, ievadot daudzumu, kuru vēlaties atgriezt krājumā. Vienkārši ievadiet to, pirms turpināt ar pilnu vai daļēju atmaksu. Krājumu atiestatīšanu var elastīgi apvienot ar faktiskā atmaksas procesa veikšanu.","titleShipping":"Piegāde","textShipping":"Piegādes priekšmetus var atmaksāt kā jebkuru citu preces priekšmetu. Ievadiet pilnu daudzumu vai pielāgotu daļēju summu un turpiniet ar atmaksu. Piegādes izmaksu atmaksa var tikt elastīgi kombinēta ar faktisko priekšmetu atmaksas procesu.","titlePartialAmount":"Daļēja atmaksa (tikai daudzums)","textPartialAmount":"Vienkārši ievadiet daļēju summu teksta laukā un sāciet atmaksu.","titlePartialItems":"Daļēja atmaksa (ar precēm)","textPartialItems":"Ja vēlaties atzīmēt daudzumus un priekšmetus kā atmaksātus Mollie, izmantojiet iepriekš minēto formu. Iestatiet savus daudzumus un norādiet pielāgotu summu katram priekšmetam, kas tiks atmaksāts. Kopējā summa tad būs redzama galīgās atmaksas summas tekstlaukā. Atcerieties, ka joprojām ir iespējams pielāgot šo galīgo summu pirms atmaksas uzsākšanas.","titlePartialPromotions":"Daļēja atmaksa (ar akcijām)","textPartialPromotions":"Ja jums ir akcija savā grozā, tad jūsu akcija ir atsevišķa rindas vienība. Ja vēlaties atmaksāt visas atlaides preces, turpiniet un atmaksājiet to kopējās vērtības un pilnīgu akcijas rindas vienību pati. Tomēr, ja vēlaties atmaksāt tikai dažas atlaides preces, jūs varat automātiski atņemt piemēroto atlaidi katram atsevišķam rindas vienībai. Protams, jūs vienmēr varat mainīt vērtības, ja tās nav pareizas.","titleRoundingDiff":"Noapaļošanas atšķirība","textRoundingDiff":"Pilna atmaksa iekļaus noapaļošanas atšķirības"},"summary":{"dataLoading":"Dati tiek ielādēti...","headerExcludingVat":"Bez PVN","headerIncludingVat":"Ar PVN","captionTotal":"Kopā","captionTotalTaxFree":"Kopā","captionPendingRefunds":"Gaida atgriešanu","captionVouchers":"Kupona summa","captionRefunded":"Atmaksātā summa","captionRemaining":"Atmaksājamā summa","btnFixDiff":"Labot atšķirību","placeholderDescription":"Ievadiet bankas/kartes izrakstu aprakstu patērētājam. Maks. 140 zīmes","lblDescription":"Apraksts (pēc izvēles) ({characters}/140 rakstzīmes)","descriptionHelp":"Kad tas ir iespējams, tas tiks rādīts patērētāja bankas vai kartes izrakstā. Ziņojums tiks saīsināts pēc 140 rakstzīmēm.","placeholderInternalDescription":"Ievadiet savu iekšējo aprakstu","lblInternalDescription":"Iekšējais apraksts (pēc izvēles)","internalDescriptionHelp":"Šis tiks rādīts kā vietējā apraksts administrācijas interfeisā.","checkVerification":"Es esmu pārbaudījis kopējo atmaksas summu un konfigurētos daudzumus atmaksai un piegādei.","btnRefund":"Atmaksa","btnFullRefund":"Pilna atmaksa","roundDiffItemAdded":"Noapaļošanas pozīcija"},"refunds":{"title":"Atmaksas Mollie vadības panelī","linkMore":"Vairāk par atmaksām","grid":{"columns":{"amount":"Daudzums","status":"Statuss","description":"Apraksts","internalDescription":"Iekšējais apraksts","composition":"Kompozīcija","date":"Datums"},"lblNoComposition":"Nav pieejama kompozīcija","btnCancelRefund":"Atcelt šo atmaksu"}},"notifications":{"success":{"refund-created":"Atmaksa ir izveidota Mollie. Var paiet 2 stundas, līdz atmaksas process pabeigts. Līdz tam brīdim jūs varat atcelt atmaksu.","refund-canceled":"Procesā esošā atmaksāšana ir veiksmīgi atcelta un noņemta."},"error":{"low-amount":"Lūdzu, ievadiet summu, kas jāatmaksā.","refund-created":"Kaut kas nogāja greizi, veidojot atmaksu.","refund-canceled":"Radās problēma, atceļot procesā esošo atmaksu. Lūdzu, mēģiniet vēlreiz Mollie informācijas paneļā."}}},"vouchers":{"CARD_TITLE":"Kupons","VOUCHER_INFO_TITLE":"Kupona maksājumi","VOUCHER_INFO_DESCRIPTION":"Mollie ļauj jums viegli pieņemt maksājumus jūsu tiešsaistes veikalā, izmantojot ekoloģiskos, dāvanu un ēdienu kuponus — gudra izvēle, lai palielinātu pārdošanu un apmierinātu jūsu klientus. Maksājuma metode \\"kupons\\" ir redzama tikai tad, ja grozā ir vismaz 1 produkts ar piešķirtu kupona veidu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Lūdzu, ņemiet vērā, ka šo konfigurāciju var rediģēt tikai jūsu noklusējuma valodā! Lūdzu, mainiet savu valodu, lai mainītu šī produkta kupona veidu!","VOUCHER_BTN_READMORE":"Lasiet vairāk","VOUCHER_TYPE_CAPTION":"Produkta kupona veids","VOUCHER_TYPE_VALUE_NONE":"Nav","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Maltīte","VOUCHER_TYPE_VALUE_VOUCHER":"Dāvana"},"modals":{"shipping":{"title":"Nosūtīt caur Mollie","item":{"label":"Prece:","noQuantity":"Lūdzu, ievadiet daudzumu, kas jānosūta!","shipAll":"Nosūtīt visu","summary":{"quantity":"Nosūtāmais daudzumu","shipped":"Nosūtītais daudzums","shippable":"Nosūtāmo preču daudzums"},"success":"Pasūtījums veiksmīgi nosūtīts."},"order":{"description":"Sekojamo preču daudzumi tiks nosūtīti.","itemHeader":"Prece","quantityHeader":"Daudzums","originalQuantityHeader":"Daudzums (nosūtāms)"},"availableTracking":{"label":"Pieejamie izsekošanas kodi","hint":"Noklikšķiniet uz viena no šiem izsekošanas kodiem, lai automātiski aizpildītu visus datus."},"showTracking":"Pievienot izsekošanas informāciju šai sūtījumam","tracking":{"carrier":"Pārvadātājs","code":"Kods","url":"Url","invalid":"Lūdzu, ievadiet gan pārvadātāju, gan kodu"},"confirmButton":"Nosūtīt pasūtījumu","cancelButton":"Atcelt","selectAllButton":"Izvēlēties visu","resetButton":"Atjaunot"},"cancel":{"title":"Atcelt preci caur Mollie","confirmButton":"Atcelt preci caur Mollie","cancelButton":"Aizvērt modālo logu","resetStock":"Atjaunot krājumus","item":{"success":"Produkts veiksmīgi atcelts","failed":{"quantityZero":"Daudzums ir 0","invalidLine":"Produkta nav pasūtījumā","quantityTooHigh":"Daudzums ir pārāk liels"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Nosūtīt pasūtījumu (Mollie)","description":"Nosūtīt pasūtījumu caur Mollie."},"modal":{"title":"Nosūtīt pasūtījumu","description":"Šī darbība automātiski nosūtīs pasūtījumu, izmantojot Mollie. Procesa secība saņems pasūtījuma numuru un nodos to Mollie API. Veiksmīgas nosūtīšanas un neizdevušās nosūtīšanas būs redzamas Mollie žurnāla failos.","warningConfig":"Lūdzu, pārliecinieties, ka izslēdzāt visas papildu automatizācijas šī veida darbībām, lai izvairītos no iejaukšanās.\\nŠīs spraudņa aktivētās funkcijas var traucēt šo darbību:","noWarnings":"Nav brīdinājumu"}},"refundOrder":{"editor":{"title":"Atmaksāt pasūtījumu (Mollie)","description":"Atmaksāt pasūtījumu caur Mollie."},"modal":{"title":"Atmaksāt pasūtījumu","description":"Šī darbība automātiski uzsāks atmaksu caur Mollie. Darbības secība saņems pasūtījuma numuru un nosūtīs to uz Mollie API. Veiksmīgās atmaksas un neveiksmīgās atmaksas būs redzamas Mollie žurnāla failos.","warning":"Lūdzu, ņemiet vērā, ka atmaksas var ilgt līdz 2 stundām, lai tiktu pabeigtas un redzamas veikalā. Līdz tam jūs vienmēr varat atcelt gaidošo atmaksu, vai nu no pasūtījuma lapas Shopware, vai no Mollie Dashboard.","warningConfig":"Lūdzu, pārliecinieties, ka izslēdzāt visas papildu automatizācijas šī veida darbībām, lai izvairītos no iejaukšanās."}},"warnings":{"automaticShipping":"Automātiskā piegāde spraudņa konfigurācijā"}}},"subscriptions":{"status":{"pending":"Procesā esošs","active":"Aktīvs","canceled":"Atcelts","suspended":"Pārtraukts","completed":"Pabeigts","paused":"Pauzēts","resumed":"Turpināts","skipped":"Izlaists"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Diena(-s)","TYPE_WEEKS":"Nedēļa(-s)","TYPE_MONTHS":"Mēnesis(-ši)","confirm":{"cancelTitle":"Atcelt abonementu?","cancel":"Atcelt klienta abonementu.","pauseTitle":"Pauzēt abonementu?","pause":"Nolikt abonementu uz gaidīšanu līdz jūs to atkal atsākat.","resumeTitle":"Atjaunot abonementu?","resume":"Turpināt abonementu vēlreiz.","skipTitle":"Izlaist nākamo iemaksu?","skip":"Izlaidiet nākamo maksājumu abonementā. Pēc tam tas automātiski turpinās."},"alerts":{"cancelSuccess":"Abonements tika veiksmīgi atcelts","pauseSuccess":"Abonements ir veiksmīgi pauzēts","resumeSuccess":"Abonements ir veiksmīgi atjaunots","skipSuccess":"Abonements ir veiksmīgi izlaists. Nākamais maksājums ir atjaunināts."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Klients","status":"Statuss","description":"Apraksts","amount":"Daudzums","nextPaymentAt":"Nākamais maksājums","prePaymentReminder":"Atgādināts par","canceledAt":"Atcelts pie","createdAt":"Izveidots pie"},"action":{"edit":"Rediģēt abonementu"},"deletedCustomer":"Izdzēsts klients"},"detail":{"title":"Mollie abonements","buttonCancelSubscription":"Atcelt abonementu","labelDescription":"Apraksts","labelAmount":"Daudzums","labelQuantity":"Daudzums","labelMollieSubscription":"Mollie Subscription","labelMollieCustomer":"Mollie klients","labelMandateId":"Pilnvarot","labelShopwareCustomer":"Shopware klients","labelCreatedAt":"Izveidots pie","buttonShowShopwareOrder":"Rādīt Shopware pasūtījumu","buttonShowShopwareCustomer":"Rādīt Shopware klientu","cardTitleSubscription":"Abonements","cardTitleStatus":"Statuss","labelStatus":"Statuss","labelNextPaymentAt":"Nākamais maksājums pie","labelLastRemindedAt":"Pēdējais atgādinājums pie","labelCanceledAt":"Atcelts pie","buttonPauseSubscription":"Pauzēt abonementu","buttonResumeSubscription":"Atjaunot abonementu","buttonSkipSubscription":"Izlaist abonementu","history":{"cardTitle":"Vēsture","colDate":"Datums","colComment":"Komentārs","colStatusFrom":"Statuss (no)","colStatusTo":"Statuss (uz)","colMollieSubscription":"Mollie abonements"}},"product":{"card-title":"Abonements","title":"Mollie Subscriptions","description":"Jūsu regulāro maksājumu pārvaldīšana ir vieglāka nekā jebkad agrāk ar mūsu noderīgajām funkcijām. Paceliet savu biznesu jaunā līmenī ar efektīvām izsekosanas iespējām, vienkāršām integrācijām un vairāk. Ar Mollie abonementiem jūs varat viegli izveidot abonementa produktus un ieplānot regulārus maksājumus, lai tie notiktu noteiktajos intervālos un periodos.","mollieSubscriptionProduct":"Abonementa Produkts","mollieSubscriptionIntervalAmount":"Atkārtot maksājumu katru","mollieSubscriptionIntervalType":"Intervāla vienība","mollieSubscriptionRepetitionAmount":"Atkārtojumu skaits","mollieSubscriptionRepetitionPlaceholder":"Ievadiet skaitli vai atstājiet tukšu","infoDefaultLanguage":"Lūdzu, ņemiet vērā, ka šo konfigurāciju varat rediģēt tikai savā noklusējuma valodā. Lūdzu, mainiet valodu, lai modificētu šī produkta abonementa iestatījumus.","btnReadMore":"Lasiet vairāk"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonements"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Kredītkartes dati",buttonMolliePaymentLink:"Kopēt uz starpliktuvi",columnRefunded:"Atmaksāts",columnShipped:"Nosūtīts",columnCanceled:"Atcelts",labelMollieOrderId:"Mollie Order ID",labelMollieThirdPartyPaymentId:"Maksājuma atsauce",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Atmaksātā summa",totalRefundsPending:"Gaidot atmaksu",totalRemaining:"Atmaksājamā summa",totalVouchers:"Kupona summa",totalShipments:"Nosūtītā summa ({quantity} priekšmeti)",subscriptionBadge:"Abonementa Pasūtījums",refundManager:{title:"Mollie Refund Manager",btnOpenRefundManager:"Atvērt Refund Manager",btnCloseRefundManager:"Aizvērt Refund Manager"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Vēlamā iDEAL izsniedzējs"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Atmaksas pārvaldnieks"},mollie_subscription:{label:"Abonementi"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Apraksts"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Atmaksa",subscription:"Abonements",webhookReceived:"Webhooks",status:"Statuss",started:"Sācies",ended:"Beidzies",paused:"Pauzēts",renewalReminder:"Atjaunošanas atgādinājums",renewed:"Atjaunots",resumed:"Atjaunots",skipped:"Izlaists",all:"Visi",canceled:"Atcelts",expired:"Beidzies",partiallyRefunded:"Atmaksāts (daļēji)",orderSuccess:"Pasūtījums veiksmīgs",orderFailed:"Pasūtījums neizdevās",orderCanceled:"Pasūtījums atcelts"}}},jq={entities:{mollie_subscription:"Abonament Mollie | Abonamente Mollie"},businessEvents:{mollie_checkout_order_success:" Comandă reușită",mollie_checkout_order_failed:" Comandă eșuată",mollie_checkout_order_canceled:" Comandă anulată",mollie_webhook_received_All:" Webhook Mollie primit (Toate)",mollie_webhook_received_status_authorized:" Webhook Mollie primit (Autorizat)",mollie_webhook_received_status_failed:" Webhook Mollie primit (Eșuat)",mollie_webhook_received_status_canceled:"Webhook Mollie primit (Anulat)",mollie_webhook_received_status_expired:"Webhook Mollie primit (Expirat)",mollie_webhook_received_status_pending:" Webhook Mollie primit (În așteptare)",mollie_webhook_received_status_paid:" Webhook Mollie primit (Plătit)",mollie_webhook_received_status_completed:" Webhook Mollie primit (Finalizat)",mollie_webhook_received_status_refunded:" Webhook Mollie primit (Rambursat)",mollie_webhook_received_status_partially_refunded:" Webhook Mollie primit (Rambursat parțial)",mollie_refund_started:" Rambursarea Mollie a început",mollie_subscription_started:" Abonamentul Mollie a început",mollie_subscription_ended:" Abonament Mollie finalizat",mollie_subscription_cancelled:" Abonament Mollie anulat",mollie_subscription_paused:" Abonament Mollie suspendat",mollie_subscription_resumed:" Abonamentul Mollie a fost reluat",mollie_subscription_skipped:" Abonamentul Mollie a fost omis",mollie_subscription_renewed:" Abonamentul Mollie s-a reînnoit",mollie_subscription_renewal_reminder:" Memento Mollie pentru reînnoirea abonamentului"}},Cq={global:jq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Modul Mollie","searchPlaceholder":"Căutați abonamente...","general":{"mainMenuItemGeneral":"Plăți Mollie","descriptionTextModule":"Plăți Mollie","btnMollieActions":"Acțiuni Mollie","refundThroughMollie":"Rambursare prin Mollie","shipThroughMollie":"Expediere prin Mollie","cancelMollieItem":"Anulare prin Mollie"},"config":{"info":{"title":"Bună {userName}, Bine ai venit la Mollie!","descriptionTop":"Onboardingul este ușor cu Mollie!","descriptionBottom":"Asta e tot!","descriptionFooter":"Dacă doriți să aflați mai multe despre pluginul nostru, vizitați pagina noastră oficială de informații.","onboardingStep1":"Înregistrează-te pentru un cont Mollie.","onboardingStep2":"Introduceți codurile dumneavoastră API în secțiunea de mai jos.","onboardingStep2TestMode":"Activați 'Mod Test' dacă doriți să testați doar plățile.","onboardingStep3":"Atribuiți metode de plată canalelor de vânzare.","onboardingStep3Link":"pentru canalele de vânzare","btnDocumentation":"Documentație","btnRequestSupport":"Asistență","btnTroubleshooting":"Ghid de soluționare a problemelor"},"api":{"apiLinkButton":"Obțineți codurile API de pe tabloul de bord Mollie","testButton":"Testează codurile API","testApiKeys":{"title":"Plăți Mollie","apiKey":"Cod API","isValid":"este valid","isInvalid":"este invalid"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Previzualizare"},"updatePaymentMethods":{"title":"Plăți Mollie","button":"Actualizează metodele de plată","succeeded":"Metodele de plată au fost actualizate cu succes.","failed":"Metodele de plată nu au putut fi actualizate."},"mollieLimits":{"link":"Afișați regulile de disponibilitate Mollie pentru metodele de plată"}},"rounding":{"info1":"Shopware poate utiliza setările valutare pentru a calcula cum rotunjește suma totală a unei comenzi. Aceasta include numărul de zecimale din prețurile produselor și intervalul de rotunjire cel mai apropiat, cum ar fi 0,50 sau 1,00.","info2":"Aceste setări pot duce la un total general diferit față de suma totală a elementelor de linie. Atunci când Mollie verifică aceste sume și constată că nu se potrivesc, aceasta provoacă o eroare la finalizarea comenzii.","info3":"Puteți folosi această funcție pentru a evita problemele de rotunjire în finalizarea comenzii. Când este activată, ea adaugă un element de linie separat în tabloul de bord Mollie pentru diferența de rotunjire, iar clienții dumneavoastră plătesc suma totală calculată de Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nu este posibil să folosiți Klarna Plătiți acum, Klarna Împărțiți sau Klarna Plătiți mai târziu ca metodă atunci când data limită este mai mare de 28 de zile în viitor, cu excepția cazului în care un alt maxim este convenit între comerciant și Klarna.","bankTransferDueDateLimitReached":"Nu este posibil să setați durata de viață a comenzii mai mare de 100 de zile."},"support":{"modalTitle":"Solicitați asistență de la Mollie","btnCancel":"Anulați","btnConfirm":"Solicitați asistență","btnSupport":"Mai multe despre asistența noastră","form":{"name":"Numele dumneavoastră","email":"Emailul dumneavoastră","recipient":"Trimiteți cererea la","subject":"Subiect","message":"Mesaj"},"data":{"header":"Date trimise către Mollie:","other":"Altele:","shopwareVersion":"Versiunea Shopware","pluginLogs":"Fișierele log {plugin}","pluginConfiguration":"Configurația {plugin}","pluginConfigurationHelpText":"Codurile API sunt excluse.","paymentMethods":"Datele metodei de plată","paymentMethodsHelpText":"Conține informații despre care metode de plată sunt active, atribuite fiecărui canal de vânzare, precum și statusul lor în contul dumneavoastră Mollie."},"success":"Cererea de asistență a fost trimisă cu succes. Facem tot posibilul să răspundem cât mai repede posibil","error":"A apărut o problemă la trimiterea mailului prin Shopware. Vă rugăm să încercați din nou sau să ne contactați direct prin e-mail."}},"rules":{"itemSubscriptionRule":"Articolul este un abonament (Mollie)","cartSubscriptionRule":"Coș cu abonamente (Mollie)"},"refunds":{"status":{"queued":"În așteptare","pending":"În așteptare","processing":"Se procesează","refunded":"Rambursat","failed":"Eșuat","description":{"queued":"Rambursarea este în așteptare până când există suficient sold pentru a procesa rambursarea. Puteți, de asemenea, să anulați rambursarea.","pending":"Rambursarea va fi trimisă băncii în următoarea zi lucrătoare. Puteți, de asemenea, să anulați rambursarea.","processing":"Rambursarea a fost trimisă băncii. Suma rambursată va fi transferată contului consumatorului cât mai curând posibil.","refunded":"Suma rambursării a fost transferată către consumator.","failed":"Rambursarea a eșuat după procesare. De exemplu, clientul și-a închis contul bancar. Fondurile vor fi returnate în contul dvs."}}},"refund-manager":{"general":{"unitQuantity":"buc."},"acl":{"warningCreate":"Nu aveți permisiuni pentru a crea rambursări","warningCancel":"Nu aveți permisiuni pentru a anula rambursările"},"cart":{"title":"Comanda ##orderNumber##","btnSelectAll":"Selectați tot","btnResetForm":"Resetați formularul","linkHowTo":"Cum să folosiți acest formular?","grid":{"columns":{"item":"Articol","productNumber":"Numărul produsului","unitPrice":"Preț unitar","quantity":"Cantitate","refunded":"Rambursat","refundQuantity":"Rambursare","totalPrice":"Total","refundAmount":"Rambursare","resetStock":"Resetați stocul"},"btnResetLine":"Resetați linia","checkDeductPromotion":"Scădeți promoția","checkRefundTax":"Rambursare TVA"},"roundDiffItemAdded":"Articolul de rotunjire a fost adăugat"},"instructions":{"linkResetTutorials":"Resetați tutorialele","btnToggleTutorial":"Arată/Ascunde tutorialul","titleFullRefund":"Rambursare totală","textFullRefund":"Trebuie doar să folosiți butonul pentru rambursarea totală. Acest lucru asigură că toate articolele dvs. sunt marcate ca fiind rambursate și întreaga sumă este returnată clientului.","titleStockReset":"Resetare stoc","textStockReset":"Puteți crește automat stocul disponibil introducând cantitatea pe care doriți să o repuneți în stoc. Introduceți-o înainte de a continua cu o rambursare totală sau parțială. Resetarea stocului poate fi combinată cu procesul efectiv de rambursare într-un mod flexibil.","titleShipping":"Livrare","textShipping":"Articolele de livrare pot fi rambursate ca orice alt articol de produs. Fie introduceți cantitatea totală, fie o sumă parțială personalizată și continuați cu rambursarea. Rambursarea costurilor de livrare poate fi combinată cu procesul efectiv de rambursare a articolelor într-un mod flexibil.","titlePartialAmount":"Rambursare parțială (doar suma)","textPartialAmount":"Doar introduceți suma parțială în câmpul de text și începeți rambursarea.","titlePartialItems":"Rambursare parțială (cu articole)","textPartialItems":"Dacă doriți să marcați cantitățile și articolele ca fiind rambursate în Mollie, folosiți formularul de mai sus. Stabiliți cantitățile dvs. și oferiți o sumă personalizată pentru fiecare articol care va fi rambursat. Suma totală va fi apoi vizibilă în câmpul de text pentru suma finală a rambursării. Amintiți-vă, este încă posibil să ajustați această sumă finală înainte de a începe rambursarea.","titlePartialPromotions":"Rambursare parțială (cu promoții)","textPartialPromotions":"Dacă aveți o promoție în coșul dvs., atunci promoția dvs. este un element de linie separat. Dacă doriți să rambursați toate articolele reduse, continuați și rambursați valorile lor totale și întreaga linie de promoție. Cu toate acestea, dacă doriți să rambursați doar câteva articole care au fost reduse, puteți scădea automat discountul aplicat pentru fiecare linie. Desigur, puteți întotdeauna schimba valorile dacă nu sunt corecte.","titleRoundingDiff":"Diferență de rotunjire","textRoundingDiff":"O rambursare totală va include diferențele de rotunjire"},"summary":{"dataLoading":"Datele se încarcă...","headerExcludingVat":"Excl. TVA","headerIncludingVat":"Incl. TVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Așteaptă să fie rambursat","captionVouchers":"Suma voucherului","captionRefunded":"Suma rambursată","captionRemaining":"Suma rambursabilă","btnFixDiff":"Corectați diferența","placeholderDescription":"Introduceți descrierea extrasului bancar/de cont pentru consumator. Max 140 de caractere","lblDescription":"Descriere (opțională) ({characters}/140 de caractere)","descriptionHelp":"Aceasta va fi afișată pe extrasul bancar sau de cont al consumatorului, atunci când este posibil. Mesajul nu poate depăși 140 de caractere.","placeholderInternalDescription":"Introduceți descrierea dumneavoastră internă","lblInternalDescription":"Descriere internă (opțională)","internalDescriptionHelp":"Aceasta va fi afișată ca o descriere locală în interfața de administrare.","checkVerification":"Am verificat suma totală a rambursării și cantitățile configurate pentru rambursare și re-stocare.","btnRefund":"Rambursare","btnFullRefund":"Rambursare totală","roundDiffItemAdded":"Articol de rotunjire"},"refunds":{"title":"Rambursări în tabloul de bord Mollie","linkMore":"Mai multe despre rambursări","grid":{"columns":{"amount":"Sumă","status":"Status","description":"Descriere","internalDescription":"Descriere internă","composition":"Compoziție","date":"Dată"},"lblNoComposition":"Nicio compoziție disponibilă","btnCancelRefund":"Anulați această rambursare"}},"notifications":{"success":{"refund-created":"O rambursare a fost creată în Mollie. Poate dura până la 2 ore pentru a finaliza rambursarea. Până atunci, puteți anula rambursarea.","refund-canceled":"Rambursarea în așteptare a fost anulată cu succes și eliminată."},"error":{"low-amount":"Vă rugăm să introduceți o sumă care să fie rambursată.","refund-created":"A apărut o problemă la crearea unei rambursări.","refund-canceled":"A existat o problemă la anularea rambursării în așteptare. Vă rugăm să încercați din nou în tabloul de bord Mollie."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Plăți prin voucher","VOUCHER_INFO_DESCRIPTION":"Mollie vă permite să acceptați cu ușurință plăți în magazinul dvs. online folosind vouchere ecologice, de cadou și de masă—o alegere inteligentă pentru a crește vânzările și a anticipa clienții dvs.. Metoda de plată \\"voucher\\" este vizibilă doar dacă aveți cel puțin 1 produs cu un tip de voucher asociat în coș.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vă rugăm să rețineți, că această configurație poate fi editată doar în limba dvs. implicită. Vă rugăm să schimbați limba pentru a modifica tipul de voucher al acestui produs.","VOUCHER_BTN_READMORE":"Citiți mai mult","VOUCHER_TYPE_CAPTION":"Tip voucher al produsului","VOUCHER_TYPE_VALUE_NONE":"Niciunul","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Masă","VOUCHER_TYPE_VALUE_VOUCHER":"Cadou"},"modals":{"shipping":{"title":"Expediați prin Mollie","item":{"label":"Articol:","noQuantity":"Vă rugăm să introduceți o cantitate de expediat.","shipAll":"Expediați tot","summary":{"quantity":"Cantitate de expediat","shipped":"Cantitate expediată","shippable":"Cantitate expediabilă"},"success":"Comanda a fost expediată cu succes."},"order":{"description":"Următoarele cantități de articole vor fi expediate.","itemHeader":"Articol","quantityHeader":"Cantitate","originalQuantityHeader":"Cantitate (expediabilă)"},"availableTracking":{"label":"Coduri de urmărire disponibile","hint":"Faceți clic pe unul dintre aceste coduri de urmărire pentru a completa automat toate datele."},"showTracking":"Adăugați informații de urmărire pentru această expediere","tracking":{"carrier":"Transportator","code":"Cod","url":"Url","invalid":"Vă rugăm să introduceți atât Transportator, cât și Cod"},"confirmButton":"Expediați comanda","cancelButton":"Anulați","selectAllButton":"Selectați tot","resetButton":"Resetare"},"cancel":{"title":"Anulați articolul prin mollie","confirmButton":"Anulați articolul prin mollie","cancelButton":"Închideți modalul","resetStock":"Resetare stocuri","item":{"success":"Produs anulat cu succes","failed":{"quantityZero":"Cantitatea este 0","invalidLine":"Produsul nu există în comandă","quantityTooHigh":"Cantitatea este prea mare"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Expediați comanda (Mollie)","description":"Expediați comanda în Mollie."},"modal":{"title":"Expediați comanda","description":"Această acțiune va expedia automat o comandă prin Mollie. Secvența de flux va primi numărul comenzii și îl va transmite la API-ul Mollie. Expedierile reușite și cele eșuate vor fi vizibile în fișierele de jurnal Mollie.","warningConfig":"Vă rugăm să vă asigurați că opriți orice automatizare suplimentară pentru acest tip de acțiune pentru a evita interferențele.\\nUrmătoarele funcții activate ale acestui plugin ar putea interfera cu această acțiune:","noWarnings":"Nu există avertismente"}},"refundOrder":{"editor":{"title":"Rambursați comanda (Mollie)","description":"Rambursați comanda prin Mollie."},"modal":{"title":"Rambursați comanda","description":"Această acțiune va porni automat o rambursare prin Mollie. Secvența de flux va primi numărul comenzii și îl va transmite la API-ul Mollie. Rambursările reușite și cele eșuate vor fi vizibile în fișierele de jurnal Mollie.","warning":"Vă rugăm să rețineți, că rambursările pot dura până la 2 ore pentru a fi finalizate și vizibile în magazin. Până atunci, puteți anula întotdeauna o rambursare în așteptare fie din pagina comenzii în Shopware, fie din tabloul de bord Mollie.","warningConfig":"Vă rugăm să vă asigurați că opriți orice automatizare suplimentară pentru acest tip de acțiune pentru a evita interferențele."}},"warnings":{"automaticShipping":"Expediere automată în configurația plugin-ului"}}},"subscriptions":{"status":{"pending":"În așteptare","active":"Activ","canceled":"Anulat","suspended":"Suspendat","completed":"Finalizat","paused":"Suspendat","resumed":"Reluat","skipped":"Sărit"},"navigation":{"title":"Abonamente Mollie"},"TYPE_DAYS":"Zi(le)","TYPE_WEEKS":"Săptămână(i)","TYPE_MONTHS":"Lună(i)","confirm":{"cancelTitle":"Anulare abonament?","cancel":"Anulați abonamentul clientului dvs..","pauseTitle":"Suspendare abonament?","pause":"Pune abonamentul pe pauză până când decizi să îl reactivezi.","resumeTitle":"Reactivați abonamentul?","resume":"Reluați abonamentul din nou.","skipTitle":"Sari peste următoarea rată?","skip":"Sari peste următoarea tranșă din abonament. Acesta continuă automat după aceea."},"alerts":{"cancelSuccess":"Abonamentul a fost anulat cu succes","pauseSuccess":"Abonamentul a fost pus pe pauză cu succes","resumeSuccess":"Abonamentul a fost reluat cu succes","skipSuccess":"Abonamentul a fost sărit cu succes. Următoarea plată a fost actualizată."},"list":{"title":"Abonamente Mollie","columns":{"customer":"Client","status":"Status","description":"Descriere","amount":"Sumă","nextPaymentAt":"Următoarea plată","prePaymentReminder":"Reamintit la","canceledAt":"Anulat la","createdAt":"Creat la"},"action":{"edit":"Editați abonamentul"},"deletedCustomer":"Client șters"},"detail":{"title":"Abonament Mollie","buttonCancelSubscription":"Anulați abonamentul","labelDescription":"Descriere","labelAmount":"Sumă","labelQuantity":"Cantitate","labelMollieSubscription":"Abonament Mollie","labelMollieCustomer":"Client Mollie","labelMandateId":"Mandat","labelShopwareCustomer":"Client Shopware","labelCreatedAt":"Creat la","buttonShowShopwareOrder":"Arată comanda Shopware","buttonShowShopwareCustomer":"Arată clientul Shopware","cardTitleSubscription":"Abonament","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Următoarea plată la","labelLastRemindedAt":"Ultima reamintire la","labelCanceledAt":"Anulat la","buttonPauseSubscription":"Pauza abonament","buttonResumeSubscription":"Reiați abonamentul","buttonSkipSubscription":"Sari peste abonament","history":{"cardTitle":"Istoric","colDate":"Data","colComment":"Comentariu","colStatusFrom":"Status (de la)","colStatusTo":"Status (până la)","colMollieSubscription":"Abonament Mollie"}},"product":{"card-title":"Abonament","title":"Abonamente Mollie","description":"Gestionarea plăților recurente este mai ușoară ca niciodată cu caracteristicile noastre utile. Duceți-vă afacerea la nivelul următor cu opțiuni eficiente de urmărire, integrații simple și multe altele. Cu abonamentele Mollie, puteți crea cu ușurință produse de abonament și programa plăți recurente care să aibă loc la intervalul și perioada configurate.","mollieSubscriptionProduct":"Produs de abonament","mollieSubscriptionIntervalAmount":"Repetă plata la fiecare","mollieSubscriptionIntervalType":"Unitate de interval","mollieSubscriptionRepetitionAmount":"Numărul de repetiții","mollieSubscriptionRepetitionPlaceholder":"Introduceți numărul sau lăsați gol","infoDefaultLanguage":"Vă rugăm să rețineți că această configurație poate fi editată doar în limba dvs. implicită. Vă rugăm să schimbați limba pentru a modifica setările abonamentului pentru acest produs.","btnReadMore":"Citiți mai mult"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonament"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Date card de credit",buttonMolliePaymentLink:"Copiați în clipboard",columnRefunded:"Rambursat",columnShipped:"Expediat",columnCanceled:"Anulat",labelMollieOrderId:"ID comandă Mollie",labelMollieThirdPartyPaymentId:"Referință plată",labelMolliePaymentLink:"URL Mollie Checkout",totalRefunds:"Sumă rambursată",totalRefundsPending:"Așteaptă să fie rambursat",totalRemaining:"Sumă rambursabilă",totalVouchers:"Sumă voucher",totalShipments:"Cantitate expediată ({quantity} articole)",subscriptionBadge:"Comandă de abonament",refundManager:{title:"Mollie Refund Manager",btnOpenRefundManager:"Deschideți Refund Manager",btnCloseRefundManager:"Închideți Refund Manager"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Emitent iDeal recomandat"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Refund Manager"},mollie_subscription:{label:"Abonamente"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Descriere"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Rambursare",subscription:"Abonament",webhookReceived:"Webhooks",status:"Status",started:"Început",ended:"Finalizat",paused:"Pus pe pauză",renewalReminder:"Memento de reînnoire",renewed:"Reînnoit",resumed:"Reluat",skipped:"Sărit",all:"Toate",canceled:"Anulat",expired:"Expirat",partiallyRefunded:"Rambursat (parțial)",orderSuccess:"Comandă reușită",orderFailed:"Comandă eșuată",orderCanceled:"Comandă anulată"}}},Oq={entities:{mollie_subscription:"Mollie Predplatné | Mollie Predplatné"},businessEvents:{mollie_checkout_order_success:"Objednávka bola úspešná",mollie_checkout_order_failed:"Objednávka zlyhala",mollie_checkout_order_canceled:"Objednávka bola zrušená",mollie_webhook_received_All:"Prijatý Webhook Mollie (všetky)",mollie_webhook_received_status_authorized:"Mollie Webhook prijatý (Autorizovaný)",mollie_webhook_received_status_failed:"Mollie Webhook prijatý (Zlyhalo)",mollie_webhook_received_status_canceled:"Mollie Webhook prijatý (Zrušený)",mollie_webhook_received_status_expired:"Mollie Webhook prijatý (Existujúci)",mollie_webhook_received_status_pending:"Mollie Webhook prijatý (Čakajúci)",mollie_webhook_received_status_paid:"Mollie Webhook prijatý (Zaplatený)",mollie_webhook_received_status_completed:"Mollie Webhook prijatý (Dokončený)",mollie_webhook_received_status_refunded:"Mollie Webhook prijatý (Vrátený)",mollie_webhook_received_status_partially_refunded:"Mollie Webhook prijatý (Čiastočne vrátený)",mollie_refund_started:"Mollie vrátenie peňazí bolo spustené",mollie_subscription_started:"Predplatné Mollie bolo spustené",mollie_subscription_ended:"Mollie predplatné dokončené",mollie_subscription_cancelled:"Mollie predplatné zrušené",mollie_subscription_paused:"Mollie predplatné pozastavené",mollie_subscription_resumed:"Predplatné Mollie bolo znovu aktivované",mollie_subscription_skipped:"Mollie predplatné preskočené",mollie_subscription_renewed:"Mollie predplatné bolo obnovené",mollie_subscription_renewal_reminder:"Mollie pripomienka na obnovenie predplatného"}},zq={global:Oq,"mollie-payments":JSON.parse(`{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Vyhľadajte predplatné...","general":{"mainMenuItemGeneral":"Mollie platby","descriptionTextModule":"Mollie platby","btnMollieActions":"Mollie akcie","refundThroughMollie":"Vrátenie peňazí cez Mollie","shipThroughMollie":"Odoslať cez Mollie","cancelMollieItem":"Zrušiť cez Mollie"},"config":{"info":{"title":"Ahoj {userName}, Vitajte v Mollie!","descriptionTop":"Onboarding je s Mollie jednoduchý!","descriptionBottom":"To je všetko!","descriptionFooter":"Ak sa chcete dozvedieť viac o našom plugine, navštívte našu oficiálnu stránku s dokumentáciou.","onboardingStep1":"Zaregistrujte sa do účtu Mollie.","onboardingStep2":"Zadajte svoje API kľúče do sekcie nižšie.","onboardingStep2TestMode":"Zapnite 'Testovací režim', ak chcete testovať platby","onboardingStep3":"Priraďte platobné metódy k svojmu predajnému kanálu.","onboardingStep3Link":"k vaším predajným kanálom","btnDocumentation":"Dokumentácia","btnRequestSupport":"Podpora","btnTroubleshooting":"Príručka pre riešenie problémov"},"api":{"apiLinkButton":"Získajte svoje API kľúče z Mollie Dashboard","testButton":"Testovať API kľúče","testApiKeys":{"title":"Mollie platby","apiKey":"API kľúč","isValid":"je platný","isInvalid":"je neplatný"}},"payments":{"format":{"placeholder":"Zástupný text (Placeholder)","preview":"Náhľad"},"updatePaymentMethods":{"title":"Mollie platby","button":"Aktualizovať platobné metódy","succeeded":"Platobné metódy boli úspešne aktualizované.","failed":"Platobné metódy sa nepodarilo aktualizovať."},"mollieLimits":{"link":"Zobraziť pravidlá dostupnosti Mollie pre platobné metódy"}},"rounding":{"info1":"Shopware môže použiť nastavenia meny na výpočet spôsobu zaokrúhľovania celkovej sumy objednávky. To zahŕňa počet desatinných miest v cenách produktov a najbližší interval zaokrúhľovania, napríklad 0,50 alebo 1,00.","info2":"Tieto nastavenia môžu viesť k tomu, že celková suma objednávky sa bude líšiť od súčtu jednotlivých položiek. Keď spoločnosť Mollie pri kontrole zistí, že sa tieto sumy nezhodujú, spôsobí to chybu pri dokončení objednávky.","info3":"Túto funkciu môžete použiť na zabránenie problémom so zaokrúhľovaním pri pokladni. Ak je aktivovaná, pridá samostatný riadok do vášho Mollie Dashboard pre rozdiel v zaokrúhľovaní a vaši zákazníci zaplatia celkovú sumu vypočítanú programom Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nie je možné použiť metódy Klarna Pay now, Klarna Slice it ani Klarna Pay later, ak je dátum exspirácie viac ako 28 dní vopred, pokiaľ sa medzi obchodníkom a spoločnosťou Klarna nedohodne iný maximálny limit.","bankTransferDueDateLimitReached":"Nie je možné nastaviť dobu platnosti objednávky na viac ako 100 dní."},"support":{"modalTitle":"Požiadať o podporu od Mollie","btnCancel":"Zrušiť","btnConfirm":"Požiadať o podporu","btnSupport":"Viac o našej podpore","form":{"name":"Vaše meno","email":"Váš email","recipient":"Odoslať žiadosť na","subject":"Predmet","message":"Správa"},"data":{"header":"Údaje odoslané do Mollie:","other":"Iné:","shopwareVersion":"Verzia Shopware","pluginLogs":"{plugin} súbory protokolu","pluginConfiguration":"{plugin} konfigurácia","pluginConfigurationHelpText":"API kľúče sú vylúčené.","paymentMethods":"Údaje o platobnej metóde","paymentMethodsHelpText":"Obsahuje informácie o tom, ktoré platobné metódy sú aktívne, priradené k jednotlivým predajným kanálom, ako aj ich stav vo vašom účte Mollie."},"success":"Žiadosť o podporu bola úspešne odoslaná. Urobíme všetko pre to, aby sme vám odpovedali čo najskôr","error":"Pri odosielaní e-mailu cez Shopware nastal problém. Skúste to znova alebo nás kontaktujte priamo e-mailom."}},"rules":{"itemSubscriptionRule":"Položka je predplatné (Mollie)","cartSubscriptionRule":"Košík s predplatným (Mollie)"},"refunds":{"status":{"queued":"Čaká sa","pending":"Čakajúce","processing":"Spracovávanie","refunded":"Refundované","failed":"Zlyhalo","description":{"queued":"Vrátenie platby je v poradí a čaká na dostatočný zostatok na účte na jeho spracovanie. Stále ho môžete zrušiť.","pending":"Vrátenie platby bude odoslané do banky nasledujúci pracovný deň. Vrátenie môžete stále zrušiť.","processing":"Vrátenie platby bude odoslané do banky nasledujúci pracovný deň. Vrátenie môžete stále zrušiť.","refunded":"Refundovaná suma bola prevedená spotrebiteľovi.","failed":"Vrátenie platby zlyhalo po spracovaní. Napríklad zákazník mohol zrušiť svoj bankový účet. Prostriedky budú vrátené na váš účet."}}},"refund-manager":{"general":{"unitQuantity":"ks."},"acl":{"warningCreate":"Nemáte oprávnenie na vytváranie vrátení platieb","warningCancel":"Nemáte oprávnenia na zrušenie refundácií"},"cart":{"title":"Objednávka ##orderNumber##","btnSelectAll":"Vybrať všetko","btnResetForm":"Obnoviť formulár","linkHowTo":"Ako používať tento formulár?","grid":{"columns":{"item":"Položka","productNumber":"Číslo produktu","unitPrice":"Cena za kus","quantity":"Množstvo","refunded":"Refundované","refundQuantity":"Refundácia","totalPrice":"Celková cena","refundAmount":"Refundácia","resetStock":"Obnoviť zásoby"},"btnResetLine":"Obnoviť riadok","checkDeductPromotion":"Odpočítať zľavu","checkRefundTax":"Vrátit DPH"},"roundDiffItemAdded":"Položka automatického zaokrúhľovania bola pridaná"},"instructions":{"linkResetTutorials":"Obnoviť návody","btnToggleTutorial":"Zobraziť/Skryť návod","titleFullRefund":"Úplné vrátenie peňazí","textFullRefund":"Jednoducho použite tlačidlo na úplné vrátenie peňazí. Tým sa zabezpečí, že všetky položky budú označené ako vrátené a zákazníkovi bude vrátená celá suma.","titleStockReset":"Resetovanie zásob","textStockReset":"Môžete automaticky zvýšiť dostupný zostatok zadaním množstva, ktoré chcete vrátiť do zásoby. Zadajte ho pred tým, ako prejdete k úplnej alebo čiastočnej refundácii. Resetovanie zásob môže byť flexibilne kombinované s procesom refundácie.","titleShipping":"Doprava","textShipping":"Položky dopravy je možné vrátiť rovnako ako akýkoľvek iný produkt. Zadajte buď celé množstvo, alebo vlastnú čiastočnú sumu a pokračujte vo vrátení. Vrátenie nákladov na dopravu je možné flexibilne kombinovať s procesom vrátenia samotných produktov.","titlePartialAmount":"Čiastočné vrátenie peňazí (iba suma)","textPartialAmount":"Stačí zadať čiastočnú sumu do textového poľa a spustiť vrátenie peňazí.","titlePartialItems":"Čiastočná refundácia (s položkami)","textPartialItems":"Ak chcete v Mollie označiť množstvá a položky ako vrátené, použite formulár vyššie. Nastavte požadované množstvá a zadajte vlastnú sumu pre každú položku, ktorá bude vrátená. Celková suma sa následne zobrazí v textovom poli s konečnou sumou na vrátenie. Nezabudnite, že túto konečnú sumu je stále možné upraviť pred spustením refundácie.","titlePartialPromotions":"Čiastočná refundácia (s promo akciami)","textPartialPromotions":"Ak máte v košíku promo akciu, zobrazí sa ako samostatná položka. Ak chcete vrátiť všetky zľavnené produkty, pokračujte a vráťte ich plné sumy spolu s celou položkou promo akcie. Ak však chcete vrátiť len niektoré zľavnené produkty, zľava sa môže automaticky odpočítať z každej položky zvlášť. Samozrejme, hodnoty môžete vždy upraviť, ak nie sú správne.","titleRoundingDiff":"Rozdiel v zaokrúhlení","textRoundingDiff":"Plné vrátenie zahrnie rozdiely v zaokrúhlení"},"summary":{"dataLoading":"Načítavajú sa údaje...","headerExcludingVat":"Bez DPH","headerIncludingVat":"S DPH","captionTotal":"Celkom","captionTotalTaxFree":"Celkom","captionPendingRefunds":"Čaká sa na refundáciu","captionVouchers":"Suma poukazu","captionRefunded":"Vrátená suma","captionRemaining":"Vratná suma","btnFixDiff":"Opraviť rozdiel","placeholderDescription":"Zadajte popis pre výpis z banky/karty pre zákazníka. Maximálne 140 znakov","lblDescription":"Popis (voliteľné) ({characters}/140 znakov)","descriptionHelp":"Tento text sa zobrazí na bankovom alebo kartovom výpise zákazníka, ak to bude možné. Správa bude skrátená po 140 znakoch.","placeholderInternalDescription":"Zadajte popis pre interné použitie","lblInternalDescription":"Interný popis (voliteľné)","internalDescriptionHelp":"Toto sa zobrazí ako miestny popis v administrátorskom rozhraní.","checkVerification":"Overil som celkovú sumu refundácie a konfigurované množstvá na refundáciu a doplnenie skladu.","btnRefund":"Refundácia","btnFullRefund":"Úplné vrátenie peňazí","roundDiffItemAdded":"Položka zaokrúhlenia"},"refunds":{"title":"Refundácie v Mollie Dashboard","linkMore":"Viac o vrátení peňazí","grid":{"columns":{"amount":"Suma","status":"Status","description":"Popis","internalDescription":"Interný popis","composition":"Zloženie","date":"Dátum"},"lblNoComposition":"Zloženie nie je k dispozícii","btnCancelRefund":"Zrušiť túto refundáciu"}},"notifications":{"success":{"refund-created":"V Mollie bolo vytvorené vrátenie peňazí. Dokončenie môže trvať až 2 hodiny. Do tohto času môžete vrátenie zrušiť.","refund-canceled":"Čakajúca refundácia bola úspešne zrušená a odstránená."},"error":{"low-amount":"Prosím, zadajte sumu ktorá má byť vrátená.","refund-created":"Pri vytváraní refundácie došlo k problému.","refund-canceled":"Pri zrušení čakajúceho vrátenia peňazí nastal problém. Skúste to znova v Mollie Dashboarde."}}},"vouchers":{"CARD_TITLE":"Poukaz","VOUCHER_INFO_TITLE":"Platby poukazom","VOUCHER_INFO_DESCRIPTION":"Mollie vám umožňuje jednoducho prijímať platby vo vašom online obchode pomocou ekologických, darčekových a stravných poukazov – inteligentná voľba na zvýšenie predaja a spokojnosti zákazníkov. Platobná metóda „poukaz“ je viditeľná len vtedy, ak máte v košíku aspoň 1 produkt s priradeným typom poukazu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Upozornenie: Táto konfigurácia sa dá upraviť iba v predvolenom jazyku. Ak chcete zmeniť typ poukazu pre tento produkt, zmeňte jazyk.","VOUCHER_BTN_READMORE":"Zistite viac","VOUCHER_TYPE_CAPTION":"Typ poukazu produktu","VOUCHER_TYPE_VALUE_NONE":"Žiadne","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Jedlo","VOUCHER_TYPE_VALUE_VOUCHER":"Darček"},"modals":{"shipping":{"title":"Odoslať cez Mollie","item":{"label":"Položka:","noQuantity":"Zadajte množstvo na odoslanie.","shipAll":"Odoslať všetky","summary":{"quantity":"Množstvo na odoslanie","shipped":"Odoslané množstvo","shippable":"Množstvo, ktoré je možné odoslať"},"success":"Objednávka bola úspešne odoslaná."},"order":{"description":"Nasledujúce množstvá položiek budú odoslané.","itemHeader":"Položka","quantityHeader":"Množstvo","originalQuantityHeader":"Množstvo (na odoslanie)"},"availableTracking":{"label":"Dostupné sledovacie kódy","hint":"Kliknite na jeden z týchto sledovacích kódov, aby sa automaticky vyplnili všetky údaje."},"showTracking":"Pridať informácie o sledovaní k tejto zásielke","tracking":{"carrier":"Dopravca","code":"Kód","url":"Url","invalid":"Prosím, zadajte dopravcu a kód"},"confirmButton":"Zaslať objednávku","cancelButton":"Zrušiť","selectAllButton":"Vybrať všetko","resetButton":"Obnoviť"},"cancel":{"title":"Zrušiť položku cez Mollie","confirmButton":"Zrušiť položku cez Mollie","cancelButton":"Zavrieť modal","resetStock":"Obnoviť zásoby","item":{"success":"Produkt bol úspešne zrušený","failed":{"quantityZero":"Množstvo je 0","invalidLine":"Produkt neexistuje v objednávke","quantityTooHigh":"Množstvo je príliš vysoké"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Zaslať objednávku (Mollie)","description":"Zaslať objednávku v Mollie."},"modal":{"title":"Zaslať objednávku","description":"Táto akcia automaticky odošle objednávku cez Mollie. Postup bude zahŕňať číslo objednávky, ktoré sa odošle do Mollie API. Úspešné aj neúspešné zásielky budú viditeľné v Mollie protokoloch.","warningConfig":"Uistite sa, že vypnete akúkoľvek dodatočnú automatizáciu pre tento typ akcie, aby nedošlo k žiadnym konfliktom. Nasledujúce aktívne funkcie tohto doplnku môžu s touto akciou kolidovať:","noWarnings":"Žiadne upozornenia"}},"refundOrder":{"editor":{"title":"Refundácia objednávky (Mollie)","description":"Refundovať objednávku cez Mollie."},"modal":{"title":"Refundácia objednávky","description":"Táto akcia automaticky spustí vrátenie platby cez Mollie. Postup zahŕňa prijatie čísla objednávky, ktoré sa odošle do Mollie API. Úspešné aj neúspešné vrátenia platby budú viditeľné v Mollie protokoloch.","warning":"Majte na pamäti, že vrátenie platby môže trvať až 2 hodiny, kým sa dokončí a zobrazí v obchode. Dovtedy môžete refundáciu, ktorá je v priebehu spracovania, kedykoľvek zrušiť – buď zo stránky objednávky v Shopware, alebo cez Mollie Dashboard.","warningConfig":"Uistite sa, že ste deaktivovali všetky ďalšie automatizácie pre tento typ akcie, aby ste predišli možným problémom. "}},"warnings":{"automaticShipping":"Automatické odosielanie v konfigurácii doplnku"}}},"subscriptions":{"status":{"pending":"Čakajúce","active":"Aktívne","canceled":"Zrušené","suspended":"Pozastavené","completed":"Dokončené","paused":"Pozastavené","resumed":"Obnovené","skipped":"Preskočené"},"navigation":{"title":"Mollie predplatné"},"TYPE_DAYS":"Deň/ dní","TYPE_WEEKS":"Týždeň/ týždne","TYPE_MONTHS":"Mesiac/ mesiace","confirm":{"cancelTitle":"Ukončiť predplatné?","cancel":"Zrušiť predplatné vášho zákazníka.","pauseTitle":"Pozastaviť predplatné?","pause":"Pozastavte predplatné, kým ho znovu neobnovíte.","resumeTitle":"Obnoviť predplatné?","resume":"Pokračovať v predplatnom.","skipTitle":"Preskočiť nasledujúcu splátku?","skip":"Preskočiť nasledujúcu splátku v predplatnom. Následne bude predplatné pokračovať automaticky."},"alerts":{"cancelSuccess":"Predplatné bolo úspešne zrušené","pauseSuccess":"Predplatné bolo úspešne pozastavené","resumeSuccess":"Predplatné bolo úspešne obnovené","skipSuccess":"Predplatné bolo úspešne preskočené. Nasledujúca platba bola aktualizovaná."},"list":{"title":"Mollie Predplatné","columns":{"customer":"Zákazník","status":"Stav","description":"Popis","amount":"Suma","nextPaymentAt":"Nasledujúca platba","prePaymentReminder":"Pripomenuté o","canceledAt":"Zrušené o","createdAt":"Vytvorené o"},"action":{"edit":"Upraviť predplatné"},"deletedCustomer":"Zmazaný zákazník"},"detail":{"title":"Mollie predplatné","buttonCancelSubscription":"Zrušiť predplatné","labelDescription":"Popis","labelAmount":"Suma","labelQuantity":"Množstvo","labelMollieSubscription":"Mollie predplatné","labelMollieCustomer":"Mollie zákazník","labelMandateId":"Mandát","labelShopwareCustomer":"Shopware zákazník","labelCreatedAt":"Vytvorené o","buttonShowShopwareOrder":"Zobraziť Shopware objednávku","buttonShowShopwareCustomer":"Zobraziť Shopware zákazníka","cardTitleSubscription":"Predplatné","cardTitleStatus":"Stav","labelStatus":"Stav","labelNextPaymentAt":"Nasledujúca platba o","labelLastRemindedAt":"Posledná pripomienka k","labelCanceledAt":"Zrušené k","buttonPauseSubscription":"Pozastaviť predplatné","buttonResumeSubscription":"Obnoviť predplatné","buttonSkipSubscription":"Preskočiť predplatné","history":{"cardTitle":"História","colDate":"Dátum","colComment":"Komentár","colStatusFrom":"Stav (od)","colStatusTo":"Stav (do)","colMollieSubscription":"Mollie predplatné"}},"product":{"card-title":"Predplatné","title":"Mollie Predplatné","description":"Správa opakovaných platieb je jednoduchšia než kedykoľvek predtým vďaka našim užitočným funkciám. Posuňte svoje podnikanie na vyššiu úroveň s efektívnym sledovaním, jednoduchými integráciami a ďalšími možnosťami. S predplatným od Mollie môžete jednoducho vytvárať produkty na predplatné a naplánovať opakované platby podľa nastaveného intervalu a obdobia.","mollieSubscriptionProduct":"Produkt predplatného","mollieSubscriptionIntervalAmount":"Opakovať platbu každých","mollieSubscriptionIntervalType":"Jednotka intervalu","mollieSubscriptionRepetitionAmount":"Počet opakovaní","mollieSubscriptionRepetitionPlaceholder":"Zadajte číslo alebo ponechajte prázdne","infoDefaultLanguage":"Upozornenie: Táto konfigurácia sa dá upraviť iba v predvolenom jazyku. Ak chcete zmeniť nastavenia predplatného pre tento produkt, zmeňte jazyk.","btnReadMore":"Zistite viac"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Predplatné"}}`),"sw-order":{detailExtended:{titleCreditCardData:"Údaje o kreditnej karte",buttonMolliePaymentLink:"Kopírovať do schránky",columnRefunded:"Vrátené",columnShipped:"Odoslané",columnCanceled:"Zrušené",labelMollieOrderId:"Mollie ID objednávky",labelMollieThirdPartyPaymentId:"Referencia platby",labelMolliePaymentLink:"Mollie Checkout URL",totalRefunds:"Suma vrátenia",totalRefundsPending:"Čaká sa na vrátenie",totalRemaining:"Vratná suma",totalVouchers:"Suma poukazu",totalShipments:"Odoslaná suma ({quantity} položiek)",subscriptionBadge:"Objednávka predplatného",refundManager:{title:"Mollie Manager vrátenia",btnOpenRefundManager:"Otvoriť Manager vrátenia",btnCloseRefundManager:"Zavrieť Manager vrátenia"}}},"sw-customer":{extendedInfo:{labelPreferredIdealIssuer:"Preferovaný emitent iDeal"}},"sw-privileges":{permissions:{parents:{mollie:"Mollie"},mollie_refund_manager:{label:"Správca vrátenia peňazí"},mollie_subscription:{label:"Predplatné"}}},"sw-profile":{tabSearchPreferences:{modules:{mollie_subscription:{description:"Popis"}}}},"sw-flow":{triggers:{mollie:"Mollie",refund:"Vrátenie",subscription:"Predplatné",webhookReceived:"Webhooks",status:"Stav",started:"Začaté",ended:"Ukončené",paused:"Pozastavené",renewalReminder:"Pripomienka o obnovení",renewed:"Obnovené",resumed:"Predĺžené",skipped:"Preskočené",all:"Všetko",canceled:"Zrušené",expired:"Expirované",partiallyRefunded:"Vrátené (čiastočne)",orderSuccess:"Objednávka úspešná",orderFailed:"Objednávka zlyhala",orderCanceled:"Objednávka zrušená"}}};Shopware.Locale.extend("de-DE",K1);Shopware.Locale.extend("en-GB",G1);Shopware.Locale.extend("nl-NL",Q1);Shopware.Locale.extend("it-IT",J1);Shopware.Locale.extend("pt-PT",eq);Shopware.Locale.extend("es-ES",rq);Shopware.Locale.extend("sv-SE",iq);Shopware.Locale.extend("nb-NO",oq);Shopware.Locale.extend("pl-PL",lq);Shopware.Locale.extend("cs-CZ",dq);Shopware.Locale.extend("sl-SL",pq);Shopware.Locale.extend("hu-HU",vq);Shopware.Locale.extend("fi-FI",gq);Shopware.Locale.extend("da-DK",bq);Shopware.Locale.extend("el-GR",yq);Shopware.Locale.extend("hr-HR",Sq);Shopware.Locale.extend("et-EE",Rq);Shopware.Locale.extend("is-IS",Aq);Shopware.Locale.extend("lt-LT",Pq);Shopware.Locale.extend("lv-LV",Iq);Shopware.Locale.extend("ro-RO",Cq);Shopware.Locale.extend("sk-SK",zq); diff --git a/src/Resources/public/administration/css/mollie-payments.css b/src/Resources/public/administration/css/mollie-payments.css new file mode 100644 index 000000000..4a0d9c0be --- /dev/null +++ b/src/Resources/public/administration/css/mollie-payments.css @@ -0,0 +1,19 @@ +.mollie-pluginconfig-info .title{font-size:16px;font-weight:700}.mollie-pluginconfig-info .description{margin-top:20px}.mollie-pluginconfig-info .description-footer{margin-top:10px;font-size:12px}.mollie-pluginconfig-info .list{margin-left:30px}.mollie-pluginconfig-info .list .list-item{margin-bottom:15px}.mollie-pluginconfig-info .btn-action{width:100%;margin-bottom:10px;text-align:left}.mollie-pluginconfig-info .link-troubleshooting{margin-top:10px}.mollie-pluginconfig-info .col-right{display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:flex-end} +.mollie-pluginconfig-payments-link-limits{position:absolute !important;right:45px} +.mollie-pluginconfig-payments-link-limits{position:absolute !important;right:45px} +.mollie-pluginconfig-payments-format-preview{background-color:#f8f8f8;border:solid 1px #189eff;border-radius:9px;padding:20px;margin-bottom:20px}.mollie-pluginconfig-payments-format-preview .mollie-pluginconfig-payments-format-text{font-size:14px;margin-left:5px} +.mollie-roundingconfig{margin-top:15px;margin-bottom:15px} +.mollie-support-modal__form :last-child{margin-bottom:0}.mollie-support-modal .sw-description-list{position:relative}.mollie-support-modal .sw-description-list dt,.mollie-support-modal .sw-description-list dd{border-bottom:none}.mollie-support-modal .sw-description-list dt{padding:16px 4px 4px}.mollie-support-modal .sw-description-list dt:first-child{padding-top:0}.mollie-support-modal .sw-description-list dd{padding:1px 4px}.mollie-support-modal .sw-text-editor .sw-text-editor__content-editor p{margin-top:0;margin-bottom:1em}.mollie-support-modal .sw-text-editor .sw-text-editor__content-editor div{margin-top:0}.mollie-btn-action-custom{display:flex !important;align-items:center;gap:4px} +.bankTransferDueDateKlarnaLimitReached{border-color:#fbaf18;background-color:rgba(251,175,24,.2)}.bankTransferDueDateKlarnaLimitReached>[class*=-icon]{color:#fbaf18}.bankTransferDueDateLimitReached{border-color:#e2262a;background-color:rgba(226,38,42,.2)}.bankTransferDueDateLimitReached>[class*=-icon]{color:#e2262a} +.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__description-title{font-weight:700;font-size:14px;text-align:center}.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__image-container{display:flex !important;flex-direction:column !important;justify-content:center !important;align-items:center !important;margin-top:20px}.mollie-payments-flowsequence-action-order-ship-modal .mollie-payments-flowsequence-action-order-ship-modal__image-container .mollie-payments-flowsequence-action-order-ship-modal__image{width:80px} +.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__description-title{font-weight:700;font-size:14px;text-align:center}.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__image-container{display:flex !important;flex-direction:column !important;justify-content:center !important;align-items:center !important;margin-top:20px}.mollie-payments-flowsequence-action-order-refund-modal .mollie-payments-flowsequence-action-order-refund-modal__image-container .mollie-payments-flowsequence-action-order-refund-modal__image{width:80px} +.mollie-credit-card-logo,.mollie-credit-card-text{vertical-align:middle;display:inline-block;font-size:14px} +.mollie-subscriptions-grid-btn-edit a{color:#3d4c5c;text-decoration:none} +.mollie-subscriptions-detail .mollie-subscriptions-detail-link-button a{color:#fff;text-decoration:none}.mollie-subscriptions-detail .mollie-subscriptions-detail-status-action-row{margin-bottom:20px}.mollie-subscriptions-detail .cy-btn-pause,.mollie-subscriptions-detail .cy-btn-skip,.mollie-subscriptions-detail .danger{background:#de294c;color:#fff;line-height:36px} +.sw-product-detail-mollie-subscription-form__subscriptionInterval,.sw-product-detail-mollie-subscription-form__subscriptionRepetition{display:inline-flex}.sw-product-detail-mollie-subscription-form__subscriptionInterval .subscription-form-field,.sw-product-detail-mollie-subscription-form__subscriptionRepetition .subscription-form-field{width:49%;margin-right:10px}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-subscription__description-title,.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__description-title,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-subscription__description-title,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__description-title{font-weight:700;font-size:14px;text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__image-container,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__image-container{display:flex !important;flex-direction:column !important;justify-content:center !important;align-items:center !important;margin-top:20px}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__image-container .sw-product-detail-mollie-vouchers__image,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__image-container .sw-product-detail-mollie-vouchers__image{width:80px}.sw-product-detail-mollie-subscription-form__container .sw-product-feature-set-form__description-body,.sw-product-detail-mollie-vouchers-form__container .sw-product-feature-set-form__description-body{font-size:12px;margin-top:20px;margin-bottom:30px;text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__button-readmore,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__button-readmore{text-align:center}.sw-product-detail-mollie-subscription-form__container .sw-product-detail-mollie-vouchers__inheritance-warning,.sw-product-detail-mollie-vouchers-form__container .sw-product-detail-mollie-vouchers__inheritance-warning{margin-top:20px;font-size:14px} +.mollie-ship-order-grid.sw-data-grid.is--compact .sw-data-grid__cell-content{padding:10px 20px;height:42px}.mollie-modal-refund-manager .sw-modal__body{padding:0} +.mollie-order-user-card-subscription-badge{margin-top:10px}.mollie-order-user-card-subscription-badge a{text-decoration:none} +.sw-order-detail-base__mollie-info .mollie-property-column-left{float:left}.sw-order-detail-base__mollie-info .mollie-property-column-right{float:right}.sw-order-detail-base__mollie-info .mollie-property-section{margin-bottom:20px}.sw-order-detail-base__mollie-info .mollie-property-title{font-weight:600;color:#52667a;font-size:14px}.sw-order-detail-base__mollie-info .mollie-property-creditcard-section{margin-top:6px}.sw-order-detail-base__mollie-info .mollie-property-content{font-size:14px}.sw-order-detail-base__mollie-info .mollie-property-paymentlink-button{margin-top:10px} +.mollie-tracking-info__tracking-code-button{margin-bottom:.25rem}.mollie-tracking-info__tracking-code-button:not(:last-child){margin-right:.25rem} +.mollie-refund-manager{width:100%;background-color:#f0f2f5;padding:20px;display:inline-table}.mollie-refund-manager .color-delivery{color:#189eff}.mollie-refund-manager .color-refund{color:#1abc9c}.mollie-refund-manager .color-stock{color:#ca5208}.mollie-refund-manager .color-promotion{color:gold}.mollie-refund-manager .color-product-discounted{color:#d2d2d2}.mollie-refund-manager .color-refunded{color:#1abc9c}.mollie-refund-manager .color-rounding-item{color:#ca5208}.mollie-refund-manager .sw-card--large{margin-left:20px;margin-right:20px;max-width:100%}.mollie-refund-manager .tutorial-active{border:red solid 4px;padding:6px}.mollie-refund-manager .danger{background:#de294c;color:#fff;line-height:36px}.mollie-refund-manager .warning{background:gold;color:#52667a;line-height:36px}.mollie-refund-manager .mollie-refund-manager-order-container .order-container-top .order-container-top-left{text-align:left}.mollie-refund-manager .mollie-refund-manager-order-container .order-container-top .order-container-top-right{text-align:right}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid .order-item-icon{margin-right:10px}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid input{padding:6px;text-align:center}.mollie-refund-manager .mollie-refund-manager-order-container .order-grid .sw-field__addition{padding:6px}.mollie-refund-manager .mollie-refund-manager-order-container .input-mode-active input{background:#faebd7}.mollie-refund-manager .mollie-refund-manager-order-container .input-mode-inactive input{background:initial}.mollie-refund-manager .mollie-refund-manager-order-container .check-deduct-promotion label,.mollie-refund-manager .mollie-refund-manager-order-container .check-refund-tax label{font-size:12px}.mollie-refund-manager .mollie-refund-manager-order-container .rounding-item-info-container{margin-top:20px;margin-left:20px}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-top{text-align:left}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-content .instructions-block{margin-bottom:30px}.mollie-refund-manager .mollie-refund-manager-instructions-container .instructions-container-content .instructions-block-icon{margin-right:10px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-loading-container{margin-bottom:50px;text-align:center}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content{margin-bottom:20px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value{text-align:right;padding-right:0}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value.heading{font-weight:bold}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value.no-border{border-bottom-color:rgba(0,0,0,0)}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-item-value-remaining{margin:0;padding-right:5px;font-size:14px}.mollie-refund-manager .mollie-refund-manager-summary-container .summary-content .summary-fix-available{color:red;font-size:16px}.mollie-refund-manager .mollie-refund-manager-summary-container .btn-fix-diff{margin-bottom:5px;margin-left:1px}.mollie-refund-manager .mollie-refund-manager-summary-container input{padding:6px;text-align:center}.mollie-refund-manager .mollie-refund-manager-summary-container .field-description{margin-bottom:10px}.mollie-refund-manager .mollie-refund-manager-refunds .instructions-bar{display:flex;flex-wrap:wrap;align-content:flex-start;justify-content:flex-end;margin-bottom:30px} +.mollie-ship-order .mollie-ship-order-grid .mollie-ship-order-grid-quantity input:not([disabled]){background-color:#fff5e0} diff --git a/src/Resources/public/administration/js/mollie-payments.js b/src/Resources/public/administration/js/mollie-payments.js new file mode 100644 index 000000000..b564bcacd --- /dev/null +++ b/src/Resources/public/administration/js/mollie-payments.js @@ -0,0 +1 @@ +!function(){var e={90794:function(){},83001:function(){},22369:function(){},56489:function(){},32897:function(){},42751:function(){},63437:function(){},78011:function(){},93617:function(){},63313:function(){},16445:function(){},38521:function(){},49433:function(){},90266:function(){},79718:function(){},82788:function(){},95482:function(){},69074:function(){},38726:function(){},1174:function(){Shopware.Service("privileges").addPrivilegeMappingEntry({category:"permissions",parent:"mollie",key:"mollie_refund_manager",roles:{viewer:{privileges:["mollie_refund_manager:read","mollie_refund:read"],dependencies:[]},creator:{privileges:["mollie_refund_manager:create","mollie_refund:create"],dependencies:["mollie_refund_manager.viewer"]},deleter:{privileges:["mollie_refund_manager:delete","mollie_refund:delete"],dependencies:["mollie_refund_manager.creator"]}}}),Shopware.Service("privileges").addPrivilegeMappingEntry({category:"permissions",parent:"mollie",key:"mollie_subscription",roles:{viewer:{privileges:["mollie_subscription:read","mollie_subscription_address:read","mollie_subscription_history:read"],dependencies:[]},editor:{privileges:["mollie_subscription:update","mollie_subscription_address:create","mollie_subscription_address:update","mollie_subscription_history:create","mollie_subscription_history:update"],dependencies:["mollie_subscription.viewer"]},deleter:{privileges:["mollie_subscription_custom:cancel"],dependencies:["mollie_subscription.viewer"]}}})},45501:function(){let{Component:e}=Shopware,{Criteria:t}=Shopware.Data;e.extend("mollie-pluginconfig-element-orderstate-select","sw-entity-single-select",{props:{criteria:{type:Object,required:!1,default(){let e=new t;return e.addFilter(t.equals("stateMachine.technicalName","order.state")),e}}}})},12395:function(){let{Component:e}=Shopware;e.override("sw-system-config",{provide(){return{actualConfigData:this.actualConfigData,currentSalesChannelId:this.currentSalesChannelId}}})},41825:function(e,t,i){var n=i(90794);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("8f556f1e",n,!0,{})},50230:function(e,t,i){var n=i(83001);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("83f191da",n,!0,{})},68958:function(e,t,i){var n=i(22369);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("74784d87",n,!0,{})},54878:function(e,t,i){var n=i(56489);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("1560f7e3",n,!0,{})},89982:function(e,t,i){var n=i(32897);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("fe694052",n,!0,{})},55856:function(e,t,i){var n=i(42751);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("2c8b5f0e",n,!0,{})},31722:function(e,t,i){var n=i(63437);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("6e3838e8",n,!0,{})},16e3:function(e,t,i){var n=i(78011);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("ffbae650",n,!0,{})},75862:function(e,t,i){var n=i(93617);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("5e9a90f1",n,!0,{})},9174:function(e,t,i){var n=i(63313);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("1ce6e3cc",n,!0,{})},1258:function(e,t,i){var n=i(16445);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("917dcb2e",n,!0,{})},13334:function(e,t,i){var n=i(38521);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("e2f1974c",n,!0,{})},14838:function(e,t,i){var n=i(49433);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("29001f01",n,!0,{})},48245:function(e,t,i){var n=i(90266);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("49994cb6",n,!0,{})},52977:function(e,t,i){var n=i(79718);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("20e9cb02",n,!0,{})},4473:function(e,t,i){var n=i(82788);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("03881731",n,!0,{})},4749:function(e,t,i){var n=i(95482);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("09b11340",n,!0,{})},14461:function(e,t,i){var n=i(69074);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("3a466f8e",n,!0,{})},6683:function(e,t,i){var n=i(38726);n.__esModule&&(n=n.default),"string"==typeof n&&(n=[[e.id,n,""]]),n.locals&&(e.exports=n.locals),(0,i(70534).A)("e678133c",n,!0,{})},70534:function(e,t,i){"use strict";function n(e,t){for(var i=[],n={},a=0;ai.parts.length&&(n.parts.length=i.parts.length)}else{for(var o=[],a=0;a=0;--o){var r=this.tryEntries[o],s=r.completion;if("root"===r.tryLoc)return a("end");if(r.tryLoc<=this.prev){var l=n.call(r,"catchLoc"),u=n.call(r,"finallyLoc");if(l&&u){if(this.prev=0;--i){var a=this.tryEntries[i];if(a.tryLoc<=this.prev&&n.call(a,"finallyLoc")&&this.prev=0;--t){var i=this.tryEntries[t];if(i.finallyLoc===e)return this.complete(i.completion,i.afterLoc),j(i),g}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var i=this.tryEntries[t];if(i.tryLoc===e){var n=i.completion;if("throw"===n.type){var a=n.arg;j(i)}return a}}throw Error("illegal catch attempt")},delegateYield:function(e,i,n){return this.delegate={iterator:A(e),resultName:i,nextLoc:n},"next"===this.method&&(this.arg=t),g}},e}(e.exports);try{regeneratorRuntime=t}catch(e){"object"==typeof globalThis?globalThis.regeneratorRuntime=t:Function("r","regeneratorRuntime = r")(t)}},11459:function(e,t,i){"use strict";var n=i(26838),a=i(31524),o=TypeError;e.exports=function(e){if(n(e))return e;throw new o(a(e)+" is not a function")}},79079:function(e,t,i){"use strict";var n=i(3776),a=i(31524),o=TypeError;e.exports=function(e){if(n(e))return e;throw new o(a(e)+" is not a constructor")}},88281:function(e,t,i){"use strict";var n=i(81192),a=TypeError;e.exports=function(e){if("DataView"===n(e))return e;throw new a("Argument is not a DataView")}},70615:function(e,t,i){"use strict";var n=i(56662),a=String,o=TypeError;e.exports=function(e){if(n(e))return e;throw new o("Can't set "+a(e)+" as a prototype")}},54795:function(e,t,i){"use strict";var n=i(27853).has;e.exports=function(e){return n(e),e}},20078:function(e){"use strict";var t=TypeError;e.exports=function(e){if("string"==typeof e)return e;throw new t("Argument is not a string")}},2960:function(e,t,i){"use strict";var n=i(5012),a=i(1127),o=i(45392).f,r=n("unscopables"),s=Array.prototype;void 0===s[r]&&o(s,r,{configurable:!0,value:a(null)}),e.exports=function(e){s[r][e]=!0}},2132:function(e,t,i){"use strict";var n=i(9946).charAt;e.exports=function(e,t,i){return t+(i?n(e,t).length:1)}},72720:function(e,t,i){"use strict";var n=i(29020),a=TypeError;e.exports=function(e,t){if(n(t,e))return e;throw new a("Incorrect invocation")}},78700:function(e,t,i){"use strict";var n=i(90897),a=String,o=TypeError;e.exports=function(e){if(n(e))return e;throw new o(a(e)+" is not an object")}},71246:function(e){"use strict";e.exports="undefined"!=typeof ArrayBuffer&&"undefined"!=typeof DataView},41759:function(e,t,i){"use strict";var n=i(78307),a=i(595),o=i(64955),r=n.ArrayBuffer,s=n.TypeError;e.exports=r&&a(r.prototype,"byteLength","get")||function(e){if("ArrayBuffer"!==o(e))throw new s("ArrayBuffer expected");return e.byteLength}},94423:function(e,t,i){"use strict";var n=i(78307),a=i(71246),o=i(41759),r=n.DataView;e.exports=function(e){if(!a||0!==o(e))return!1;try{return new r(e),!1}catch(e){return!0}}},88683:function(e,t,i){"use strict";var n=i(87584);e.exports=n(function(){if("function"==typeof ArrayBuffer){var e=new ArrayBuffer(8);Object.isExtensible(e)&&Object.defineProperty(e,"a",{value:8})}})},97678:function(e,t,i){"use strict";var n=i(94423),a=TypeError;e.exports=function(e){if(n(e))throw new a("ArrayBuffer is detached");return e}},37975:function(e,t,i){"use strict";var n=i(78307),a=i(21287),o=i(595),r=i(81973),s=i(97678),l=i(41759),u=i(8892),d=i(95161),c=n.structuredClone,m=n.ArrayBuffer,p=n.DataView,f=Math.min,g=m.prototype,h=p.prototype,b=a(g.slice),k=o(g,"resizable","get"),v=o(g,"maxByteLength","get"),y=a(h.getInt8),w=a(h.setInt8);e.exports=(d||u)&&function(e,t,i){var n,a=l(e),o=void 0===t?a:r(t),g=!k||!k(e);if(s(e),d&&(e=c(e,{transfer:[e]}),a===o&&(i||g)))return e;if(a>=o&&(!i||g))n=b(e,0,o);else{n=new m(o,i&&!g&&v?{maxByteLength:v(e)}:void 0);for(var h=new p(e),_=new p(n),S=f(o,a),M=0;M>8&255]},Y=function(e){return[255&e,e>>8&255,e>>16&255,e>>24&255]},Q=function(e){return e[3]<<24|e[2]<<16|e[1]<<8|e[0]},Z=function(e){return q(h(e),23,4)},J=function(e){return q(e,52,8)},X=function(e,t,i){u(e[T],t,{configurable:!0,get:function(){return i(this)[t]}})},ee=function(e,t,i,n){var a=I(e),o=g(i);if(o+t>a.byteLength)throw new B(C);var r=a.bytes,s=o+a.byteOffset,l=w(r,s,s+t);return n?l:K(l)},et=function(e,t,i,n,a,o){var r=I(e),s=g(i),l=n(+a),u=!!o;if(s+t>r.byteLength)throw new B(C);for(var d=r.bytes,c=s+r.byteOffset,m=0;m>24)},setUint8:function(e,t){ea(this,e,t<<24>>24)}},{unsafe:!0})}else L=(O=function(e){m(this,L);var t=g(e);x(this,{type:A,bytes:H(F(t),0),byteLength:t}),o||(this.byteLength=t,this.detached=!1)})[T],N=(V=function(e,t,i){m(this,N),m(e,L);var n=E(e),a=n.byteLength,r=p(t);if(r<0||r>a)throw new B("Wrong offset");if(i=void 0===i?a-r:f(i),r+i>a)throw new B("Wrong length");x(this,{type:R,buffer:e,byteLength:i,byteOffset:r,bytes:n.bytes}),o||(this.buffer=e,this.byteLength=i,this.byteOffset=r)})[T],o&&(X(O,"byteLength",E),X(V,"buffer",I),X(V,"byteLength",I),X(V,"byteOffset",I)),d(N,{getInt8:function(e){return ee(this,1,e)[0]<<24>>24},getUint8:function(e){return ee(this,1,e)[0]},getInt16:function(e){var t=ee(this,2,e,arguments.length>1&&arguments[1]);return(t[1]<<8|t[0])<<16>>16},getUint16:function(e){var t=ee(this,2,e,arguments.length>1&&arguments[1]);return t[1]<<8|t[0]},getInt32:function(e){return Q(ee(this,4,e,arguments.length>1&&arguments[1]))},getUint32:function(e){return Q(ee(this,4,e,arguments.length>1&&arguments[1]))>>>0},getFloat32:function(e){return $(ee(this,4,e,arguments.length>1&&arguments[1]),23)},getFloat64:function(e){return $(ee(this,8,e,arguments.length>1&&arguments[1]),52)},setInt8:function(e,t){et(this,1,e,W,t)},setUint8:function(e,t){et(this,1,e,W,t)},setInt16:function(e,t){et(this,2,e,G,t,arguments.length>2&&arguments[2])},setUint16:function(e,t){et(this,2,e,G,t,arguments.length>2&&arguments[2])},setInt32:function(e,t){et(this,4,e,Y,t,arguments.length>2&&arguments[2])},setUint32:function(e,t){et(this,4,e,Y,t,arguments.length>2&&arguments[2])},setFloat32:function(e,t){et(this,4,e,Z,t,arguments.length>2&&arguments[2])},setFloat64:function(e,t){et(this,8,e,J,t,arguments.length>2&&arguments[2])}});M(O,A),M(V,R),e.exports={ArrayBuffer:O,DataView:V}},31118:function(e,t,i){"use strict";var n=i(76998),a=i(68757),o=i(6171),r=i(24339),s=Math.min;e.exports=[].copyWithin||function(e,t){var i=n(this),l=o(i),u=a(e,l),d=a(t,l),c=arguments.length>2?arguments[2]:void 0,m=s((void 0===c?l:a(c,l))-d,l-u),p=1;for(d0;)d in i?i[u]=i[d]:r(i,u),u+=p,d+=p;return i}},50356:function(e,t,i){"use strict";var n=i(76998),a=i(68757),o=i(6171);e.exports=function(e){for(var t=n(this),i=o(t),r=arguments.length,s=a(r>1?arguments[1]:void 0,i),l=r>2?arguments[2]:void 0,u=void 0===l?i:a(l,i);u>s;)t[s++]=e;return t}},92166:function(e,t,i){"use strict";var n=i(67754).forEach,a=i(45395)("forEach");e.exports=a?[].forEach:function(e){return n(this,e,arguments.length>1?arguments[1]:void 0)}},30161:function(e,t,i){"use strict";var n=i(6171);e.exports=function(e,t,i){for(var a=0,o=arguments.length>2?i:n(t),r=new e(o);o>a;)r[a]=t[a++];return r}},35657:function(e,t,i){"use strict";var n=i(2595),a=i(79830),o=i(76998),r=i(30262),s=i(65680),l=i(3776),u=i(6171),d=i(44083),c=i(23e3),m=i(40876),p=Array;e.exports=function(e){var t,i,f,g,h,b,k=o(e),v=l(this),y=arguments.length,w=y>1?arguments[1]:void 0,_=void 0!==w;_&&(w=n(w,y>2?arguments[2]:void 0));var S=m(k),M=0;if(S&&!(this===p&&s(S)))for(i=v?new this:[],h=(g=c(k,S)).next;!(f=a(h,g)).done;M++)b=_?r(g,w,[f.value,M],!0):f.value,d(i,M,b);else for(t=u(k),i=v?new this(t):p(t);t>M;M++)b=_?w(k[M],M):k[M],d(i,M,b);return i.length=M,i}},51872:function(e,t,i){"use strict";var n=i(770),a=i(68757),o=i(6171),r=function(e){return function(t,i,r){var s,l=n(t),u=o(l);if(0===u)return!e&&-1;var d=a(r,u);if(e&&i!=i){for(;u>d;)if((s=l[d++])!=s)return!0}else for(;u>d;d++)if((e||d in l)&&l[d]===i)return e||d||0;return!e&&-1}};e.exports={includes:r(!0),indexOf:r(!1)}},26864:function(e,t,i){"use strict";var n=i(2595),a=i(10518),o=i(76998),r=i(6171),s=function(e){var t=1===e;return function(i,s,l){for(var u,d=o(i),c=a(d),m=r(c),p=n(s,l);m-- >0;)if(p(u=c[m],m,d))switch(e){case 0:return u;case 1:return m}return t?-1:void 0}};e.exports={findLast:s(0),findLastIndex:s(1)}},67754:function(e,t,i){"use strict";var n=i(2595),a=i(21287),o=i(10518),r=i(76998),s=i(6171),l=i(52844),u=a([].push),d=function(e){var t=1===e,i=2===e,a=3===e,d=4===e,c=6===e,m=7===e,p=5===e||c;return function(f,g,h,b){for(var k,v,y=r(f),w=o(y),_=s(w),S=n(g,h),M=0,z=b||l,j=t?z(f,_):i||m?z(f,0):void 0;_>M;M++)if((p||M in w)&&(v=S(k=w[M],M,y),e)){if(t)j[M]=v;else if(v)switch(e){case 3:return!0;case 5:return k;case 6:return M;case 2:u(j,k)}else switch(e){case 4:return!1;case 7:u(j,k)}}return c?-1:a||d?d:j}};e.exports={forEach:d(0),map:d(1),filter:d(2),some:d(3),every:d(4),find:d(5),findIndex:d(6),filterReject:d(7)}},62348:function(e,t,i){"use strict";var n=i(76180),a=i(770),o=i(47742),r=i(6171),s=i(45395),l=Math.min,u=[].lastIndexOf,d=!!u&&1/[1].lastIndexOf(1,-0)<0,c=s("lastIndexOf");e.exports=d||!c?function(e){if(d)return n(u,this,arguments)||0;var t=a(this),i=r(t);if(0===i)return -1;var s=i-1;for(arguments.length>1&&(s=l(s,o(arguments[1]))),s<0&&(s=i+s);s>=0;s--)if(s in t&&t[s]===e)return s||0;return -1}:u},97068:function(e,t,i){"use strict";var n=i(87584),a=i(5012),o=i(17258),r=a("species");e.exports=function(e){return o>=51||!n(function(){var t=[];return(t.constructor={})[r]=function(){return{foo:1}},1!==t[e](Boolean).foo})}},45395:function(e,t,i){"use strict";var n=i(87584);e.exports=function(e,t){var i=[][e];return!!i&&n(function(){i.call(null,t||function(){return 1},1)})}},7751:function(e,t,i){"use strict";var n=i(11459),a=i(76998),o=i(10518),r=i(6171),s=TypeError,l="Reduce of empty array with no initial value",u=function(e){return function(t,i,u,d){var c=a(t),m=o(c),p=r(c);if(n(i),0===p&&u<2)throw new s(l);var f=e?p-1:0,g=e?-1:1;if(u<2)for(;;){if(f in m){d=m[f],f+=g;break}if(f+=g,e?f<0:p<=f)throw new s(l)}for(;e?f>=0:p>f;f+=g)f in m&&(d=i(d,m[f],f,c));return d}};e.exports={left:u(!1),right:u(!0)}},66894:function(e,t,i){"use strict";var n=i(95851),a=i(95493),o=TypeError,r=Object.getOwnPropertyDescriptor,s=n&&!function(){if(void 0!==this)return!0;try{Object.defineProperty([],"length",{writable:!1}).length=1}catch(e){return e instanceof TypeError}}();e.exports=s?function(e,t){if(a(e)&&!r(e,"length").writable)throw new o("Cannot set read only .length");return e.length=t}:function(e,t){return e.length=t}},89887:function(e,t,i){"use strict";var n=i(21287);e.exports=n([].slice)},54917:function(e,t,i){"use strict";var n=i(89887),a=Math.floor,o=function(e,t){var i=e.length;if(i<8)for(var r,s,l=1;l0;)e[s]=e[--s];s!==l++&&(e[s]=r)}else for(var u=a(i/2),d=o(n(e,0,u),t),c=o(n(e,u),t),m=d.length,p=c.length,f=0,g=0;f=t(d[f],c[g])?d[f++]:c[g++]:f=s||u<0)throw new o("Incorrect index");for(var d=new t(s),c=0;c1?arguments[1]:void 0);t=t?t.next:i.first;)for(n(t.value,t.key,this);t&&t.removed;)t=t.previous},has:function(e){return!!v(this,e)}}),o(m,i?{get:function(e){var t=v(this,e);return t&&t.value},set:function(e,t){return k(this,0===e?0:e,t)}}:{add:function(e){return k(this,e=0===e?0:e,e)}}),p&&a(m,"size",{configurable:!0,get:function(){return g(this).size}}),c},setStrong:function(e,t,i){var n=t+" Iterator",a=b(t),o=b(n);d(e,t,function(e,t){h(this,{type:n,target:e,state:a(e),kind:t,last:null})},function(){for(var e=o(this),t=e.kind,i=e.last;i&&i.removed;)i=i.previous;return e.target&&(e.last=i=i?i.next:e.state.first)?"keys"===t?c(i.key,!1):"values"===t?c(i.value,!1):c([i.key,i.value],!1):(e.target=null,c(void 0,!0))},i?"entries":"values",!i,!0),m(t)}}},70674:function(e,t,i){"use strict";var n=i(21287),a=i(42726),o=i(40104).getWeakData,r=i(72720),s=i(78700),l=i(61852),u=i(90897),d=i(48747),c=i(67754),m=i(18280),p=i(60472),f=p.set,g=p.getterFor,h=c.find,b=c.findIndex,k=n([].splice),v=0,y=function(e){return e.frozen||(e.frozen=new w)},w=function(){this.entries=[]},_=function(e,t){return h(e.entries,function(e){return e[0]===t})};w.prototype={get:function(e){var t=_(this,e);if(t)return t[1]},has:function(e){return!!_(this,e)},set:function(e,t){var i=_(this,e);i?i[1]=t:this.entries.push([e,t])},delete:function(e){var t=b(this.entries,function(t){return t[0]===e});return~t&&k(this.entries,t,1),!!~t}},e.exports={getConstructor:function(e,t,i,n){var c=e(function(e,a){r(e,p),f(e,{type:t,id:v++,frozen:null}),l(a)||d(a,e[n],{that:e,AS_ENTRIES:i})}),p=c.prototype,h=g(t),b=function(e,t,i){var n=h(e),a=o(s(t),!0);return!0===a?y(n).set(t,i):a[n.id]=i,e};return a(p,{delete:function(e){var t=h(this);if(!u(e))return!1;var i=o(e);return!0===i?y(t).delete(e):i&&m(i,t.id)&&delete i[t.id]},has:function(e){var t=h(this);if(!u(e))return!1;var i=o(e);return!0===i?y(t).has(e):i&&m(i,t.id)}}),a(p,i?{get:function(e){var t=h(this);if(u(e)){var i=o(e);if(!0===i)return y(t).get(e);if(i)return i[t.id]}},set:function(e,t){return b(this,e,t)}}:{add:function(e){return b(this,e,!0)}}),c}}},44781:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(21287),r=i(7539),s=i(98243),l=i(40104),u=i(48747),d=i(72720),c=i(26838),m=i(61852),p=i(90897),f=i(87584),g=i(35765),h=i(30380),b=i(58728);e.exports=function(e,t,i){var k=-1!==e.indexOf("Map"),v=-1!==e.indexOf("Weak"),y=k?"set":"add",w=a[e],_=w&&w.prototype,S=w,M={},z=function(e){var t=o(_[e]);s(_,e,"add"===e?function(e){return t(this,0===e?0:e),this}:"delete"===e?function(e){return(!v||!!p(e))&&t(this,0===e?0:e)}:"get"===e?function(e){return v&&!p(e)?void 0:t(this,0===e?0:e)}:"has"===e?function(e){return(!v||!!p(e))&&t(this,0===e?0:e)}:function(e,i){return t(this,0===e?0:e,i),this})};if(r(e,!c(w)||!(v||_.forEach&&!f(function(){new w().entries().next()}))))S=i.getConstructor(t,e,k,y),l.enable();else if(r(e,!0)){var j=new S,P=j[y](v?{}:-0,1)!==j,A=f(function(){j.has(1)}),R=g(function(e){new w(e)}),T=!v&&f(function(){for(var e=new w,t=5;t--;)e[y](t,t);return!e.has(-0)});R||((S=t(function(e,t){d(e,_);var i=b(new w,e,S);return m(t)||u(t,i[y],{that:i,AS_ENTRIES:k}),i})).prototype=_,_.constructor=S),(A||T)&&(z("delete"),z("has"),k&&z("get")),(T||P)&&z(y),v&&_.clear&&delete _.clear}return M[e]=S,n({global:!0,constructor:!0,forced:S!==w},M),h(S,e),v||i.setStrong(S,e,k),S}},39207:function(e,t,i){"use strict";var n=i(18280),a=i(50758),o=i(18994),r=i(45392);e.exports=function(e,t,i){for(var s=a(t),l=r.f,u=o.f,d=0;d"+l+""}},75562:function(e){"use strict";e.exports=function(e,t){return{value:e,done:t}}},45790:function(e,t,i){"use strict";var n=i(95851),a=i(45392),o=i(7221);e.exports=n?function(e,t,i){return a.f(e,t,o(1,i))}:function(e,t,i){return e[t]=i,e}},7221:function(e){"use strict";e.exports=function(e,t){return{enumerable:!(1&e),configurable:!(2&e),writable:!(4&e),value:t}}},44083:function(e,t,i){"use strict";var n=i(95851),a=i(45392),o=i(7221);e.exports=function(e,t,i){n?a.f(e,t,o(0,i)):e[t]=i}},80689:function(e,t,i){"use strict";var n=i(21287),a=i(87584),o=i(54672).start,r=RangeError,s=isFinite,l=Math.abs,u=Date.prototype,d=u.toISOString,c=n(u.getTime),m=n(u.getUTCDate),p=n(u.getUTCFullYear),f=n(u.getUTCHours),g=n(u.getUTCMilliseconds),h=n(u.getUTCMinutes),b=n(u.getUTCMonth),k=n(u.getUTCSeconds);e.exports=a(function(){return"0385-07-25T07:06:39.999Z"!==d.call(new Date(-5e13-1))})||!a(function(){d.call(new Date(NaN))})?function(){if(!s(c(this)))throw new r("Invalid time value");var e=p(this),t=g(this),i=e<0?"-":e>9999?"+":"";return i+o(l(e),i?6:4,0)+"-"+o(b(this)+1,2,0)+"-"+o(m(this),2,0)+"T"+o(f(this),2,0)+":"+o(h(this),2,0)+":"+o(k(this),2,0)+"."+o(t,3,0)+"Z"}:d},92803:function(e,t,i){"use strict";var n=i(78700),a=i(75121),o=TypeError;e.exports=function(e){if(n(this),"string"===e||"default"===e)e="string";else if("number"!==e)throw new o("Incorrect hint");return a(this,e)}},25039:function(e,t,i){"use strict";var n=i(39692),a=i(45392);e.exports=function(e,t,i){return i.get&&n(i.get,t,{getter:!0}),i.set&&n(i.set,t,{setter:!0}),a.f(e,t,i)}},98243:function(e,t,i){"use strict";var n=i(26838),a=i(45392),o=i(39692),r=i(71776);e.exports=function(e,t,i,s){s||(s={});var l=s.enumerable,u=void 0!==s.name?s.name:t;if(n(i)&&o(i,u,s),s.global)l?e[t]=i:r(t,i);else{try{s.unsafe?e[t]&&(l=!0):delete e[t]}catch(e){}l?e[t]=i:a.f(e,t,{value:i,enumerable:!1,configurable:!s.nonConfigurable,writable:!s.nonWritable})}return e}},42726:function(e,t,i){"use strict";var n=i(98243);e.exports=function(e,t,i){for(var a in t)n(e,a,t[a],i);return e}},71776:function(e,t,i){"use strict";var n=i(78307),a=Object.defineProperty;e.exports=function(e,t){try{a(n,e,{value:t,configurable:!0,writable:!0})}catch(i){n[e]=t}return t}},24339:function(e,t,i){"use strict";var n=i(31524),a=TypeError;e.exports=function(e,t){if(!delete e[t])throw new a("Cannot delete property "+n(t)+" of "+n(e))}},95851:function(e,t,i){"use strict";var n=i(87584);e.exports=!n(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]})},8892:function(e,t,i){"use strict";var n,a,o,r,s=i(78307),l=i(42160),u=i(95161),d=s.structuredClone,c=s.ArrayBuffer,m=s.MessageChannel,p=!1;if(u)p=function(e){d(e,{transfer:[e]})};else if(c)try{!m&&(n=l("worker_threads"))&&(m=n.MessageChannel),m&&(a=new m,o=new c(2),r=function(e){a.port1.postMessage(null,[e])},2===o.byteLength&&(r(o),0===o.byteLength&&(p=r)))}catch(e){}e.exports=p},57004:function(e,t,i){"use strict";var n=i(78307),a=i(90897),o=n.document,r=a(o)&&a(o.createElement);e.exports=function(e){return r?o.createElement(e):{}}},19580:function(e){"use strict";var t=TypeError;e.exports=function(e){if(e>0x1fffffffffffff)throw t("Maximum allowed index exceeded");return e}},98597:function(e){"use strict";e.exports={IndexSizeError:{s:"INDEX_SIZE_ERR",c:1,m:1},DOMStringSizeError:{s:"DOMSTRING_SIZE_ERR",c:2,m:0},HierarchyRequestError:{s:"HIERARCHY_REQUEST_ERR",c:3,m:1},WrongDocumentError:{s:"WRONG_DOCUMENT_ERR",c:4,m:1},InvalidCharacterError:{s:"INVALID_CHARACTER_ERR",c:5,m:1},NoDataAllowedError:{s:"NO_DATA_ALLOWED_ERR",c:6,m:0},NoModificationAllowedError:{s:"NO_MODIFICATION_ALLOWED_ERR",c:7,m:1},NotFoundError:{s:"NOT_FOUND_ERR",c:8,m:1},NotSupportedError:{s:"NOT_SUPPORTED_ERR",c:9,m:1},InUseAttributeError:{s:"INUSE_ATTRIBUTE_ERR",c:10,m:1},InvalidStateError:{s:"INVALID_STATE_ERR",c:11,m:1},SyntaxError:{s:"SYNTAX_ERR",c:12,m:1},InvalidModificationError:{s:"INVALID_MODIFICATION_ERR",c:13,m:1},NamespaceError:{s:"NAMESPACE_ERR",c:14,m:1},InvalidAccessError:{s:"INVALID_ACCESS_ERR",c:15,m:1},ValidationError:{s:"VALIDATION_ERR",c:16,m:0},TypeMismatchError:{s:"TYPE_MISMATCH_ERR",c:17,m:1},SecurityError:{s:"SECURITY_ERR",c:18,m:1},NetworkError:{s:"NETWORK_ERR",c:19,m:1},AbortError:{s:"ABORT_ERR",c:20,m:1},URLMismatchError:{s:"URL_MISMATCH_ERR",c:21,m:1},QuotaExceededError:{s:"QUOTA_EXCEEDED_ERR",c:22,m:1},TimeoutError:{s:"TIMEOUT_ERR",c:23,m:1},InvalidNodeTypeError:{s:"INVALID_NODE_TYPE_ERR",c:24,m:1},DataCloneError:{s:"DATA_CLONE_ERR",c:25,m:1}}},76155:function(e){"use strict";e.exports={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0}},5377:function(e,t,i){"use strict";var n=i(57004)("span").classList,a=n&&n.constructor&&n.constructor.prototype;e.exports=a===Object.prototype?void 0:a},80708:function(e){"use strict";e.exports=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"]},70724:function(e,t,i){"use strict";var n=i(43950).match(/firefox\/(\d+)/i);e.exports=!!n&&+n[1]},24388:function(e,t,i){"use strict";var n=i(43950);e.exports=/MSIE|Trident/.test(n)},40930:function(e,t,i){"use strict";var n=i(43950);e.exports=/ipad|iphone|ipod/i.test(n)&&"undefined"!=typeof Pebble},25505:function(e,t,i){"use strict";var n=i(43950);e.exports=/(?:ipad|iphone|ipod).*applewebkit/i.test(n)},46318:function(e,t,i){"use strict";var n=i(88812);e.exports="NODE"===n},90079:function(e,t,i){"use strict";var n=i(43950);e.exports=/web0s(?!.*chrome)/i.test(n)},43950:function(e,t,i){"use strict";var n=i(78307).navigator,a=n&&n.userAgent;e.exports=a?String(a):""},17258:function(e,t,i){"use strict";var n,a,o=i(78307),r=i(43950),s=o.process,l=o.Deno,u=s&&s.versions||l&&l.version,d=u&&u.v8;d&&(a=(n=d.split("."))[0]>0&&n[0]<4?1:+(n[0]+n[1])),!a&&r&&(!(n=r.match(/Edge\/(\d+)/))||n[1]>=74)&&(n=r.match(/Chrome\/(\d+)/))&&(a=+n[1]),e.exports=a},81974:function(e,t,i){"use strict";var n=i(43950).match(/AppleWebKit\/(\d+)\./);e.exports=!!n&&+n[1]},88812:function(e,t,i){"use strict";var n=i(78307),a=i(43950),o=i(64955),r=function(e){return a.slice(0,e.length)===e};e.exports=r("Bun/")?"BUN":r("Cloudflare-Workers")?"CLOUDFLARE":r("Deno/")?"DENO":r("Node.js/")?"NODE":n.Bun&&"string"==typeof Bun.version?"BUN":n.Deno&&"object"==typeof Deno.version?"DENO":"process"===o(n.process)?"NODE":n.window&&n.document?"BROWSER":"REST"},17294:function(e,t,i){"use strict";var n=i(21287),a=Error,o=n("".replace),r=String(new a("zxcasd").stack),s=/\n\s*at [^:]*:[^\n]*/,l=s.test(r);e.exports=function(e,t){if(l&&"string"==typeof e&&!a.prepareStackTrace)for(;t--;)e=o(e,s,"");return e}},40472:function(e,t,i){"use strict";var n=i(45790),a=i(17294),o=i(98300),r=Error.captureStackTrace;e.exports=function(e,t,i,s){o&&(r?r(e,t):n(e,"stack",a(i,s)))}},98300:function(e,t,i){"use strict";var n=i(87584),a=i(7221);e.exports=!n(function(){var e=Error("a");return!("stack"in e)||(Object.defineProperty(e,"stack",a(1,7)),7!==e.stack)})},16099:function(e,t,i){"use strict";var n=i(95851),a=i(87584),o=i(78700),r=i(78244),s=Error.prototype.toString,l=a(function(){if(n){var e=Object.create(Object.defineProperty({},"name",{get:function(){return this===e}}));if("true"!==s.call(e))return!0}return"2: 1"!==s.call({message:1,name:2})||"Error"!==s.call({})});e.exports=l?function(){var e=o(this),t=r(e.name,"Error"),i=r(e.message);return t?i?t+": "+i:t:i}:s},21911:function(e,t,i){"use strict";var n=i(78307),a=i(18994).f,o=i(45790),r=i(98243),s=i(71776),l=i(39207),u=i(7539);e.exports=function(e,t){var i,d,c,m,p,f=e.target,g=e.global,h=e.stat;if(i=g?n:h?n[f]||s(f,{}):n[f]&&n[f].prototype)for(d in t){if(m=t[d],c=e.dontCallGetSet?(p=a(i,d))&&p.value:i[d],!u(g?d:f+(h?".":"#")+d,e.forced)&&void 0!==c){if(typeof m==typeof c)continue;l(m,c)}(e.sham||c&&c.sham)&&o(m,"sham",!0),r(i,d,m,e)}}},87584:function(e){"use strict";e.exports=function(e){try{return!!e()}catch(e){return!0}}},74529:function(e,t,i){"use strict";i(35594);var n=i(79830),a=i(98243),o=i(31960),r=i(87584),s=i(5012),l=i(45790),u=s("species"),d=RegExp.prototype;e.exports=function(e,t,i,c){var m=s(e),p=!r(function(){var t={};return t[m]=function(){return 7},7!==""[e](t)}),f=p&&!r(function(){var t=!1,i=/a/;return"split"===e&&((i={}).constructor={},i.constructor[u]=function(){return i},i.flags="",i[m]=/./[m]),i.exec=function(){return t=!0,null},i[m](""),!t});if(!p||!f||i){var g=/./[m],h=t(m,""[e],function(e,t,i,a,r){var s=t.exec;return s===o||s===d.exec?p&&!r?{done:!0,value:n(g,t,i,a)}:{done:!0,value:n(e,i,t,a)}:{done:!1}});a(String.prototype,e,h[0]),a(d,m,h[1])}c&&l(d[m],"sham",!0)}},20106:function(e,t,i){"use strict";var n=i(95493),a=i(6171),o=i(19580),r=i(2595),s=function(e,t,i,l,u,d,c,m){for(var p,f,g=u,h=0,b=!!c&&r(c,m);h0&&n(p)?(f=a(p),g=s(e,t,p,f,g,d-1)-1):(o(g+1),e[g]=p),g++),h++;return g};e.exports=s},59397:function(e,t,i){"use strict";var n=i(87584);e.exports=!n(function(){return Object.isExtensible(Object.preventExtensions({}))})},76180:function(e,t,i){"use strict";var n=i(77213),a=Function.prototype,o=a.apply,r=a.call;e.exports="object"==typeof Reflect&&Reflect.apply||(n?r.bind(o):function(){return r.apply(o,arguments)})},2595:function(e,t,i){"use strict";var n=i(98293),a=i(11459),o=i(77213),r=n(n.bind);e.exports=function(e,t){return a(e),void 0===t?e:o?r(e,t):function(){return e.apply(t,arguments)}}},77213:function(e,t,i){"use strict";var n=i(87584);e.exports=!n(function(){var e=(function(){}).bind();return"function"!=typeof e||e.hasOwnProperty("prototype")})},37965:function(e,t,i){"use strict";var n=i(21287),a=i(11459),o=i(90897),r=i(18280),s=i(89887),l=i(77213),u=Function,d=n([].concat),c=n([].join),m={},p=function(e,t,i){if(!r(m,t)){for(var n=[],a=0;a]*>)/g,d=/\$([$&'`]|\d{1,2})/g;e.exports=function(e,t,i,n,c,m){var p=i+e.length,f=n.length,g=d;return void 0!==c&&(c=a(c),g=u),s(m,g,function(a,s){var u;switch(r(s,0)){case"$":return"$";case"&":return e;case"`":return l(t,0,i);case"'":return l(t,p);case"<":u=c[l(s,1,-1)];break;default:var d=+s;if(0===d)return a;if(d>f){var m=o(d/10);if(0===m)return a;if(m<=f)return void 0===n[m-1]?r(s,1):n[m-1]+r(s,1);return a}u=n[d-1]}return void 0===u?"":u})}},78307:function(e,t,i){"use strict";var n=function(e){return e&&e.Math===Math&&e};e.exports=n("object"==typeof globalThis&&globalThis)||n("object"==typeof window&&window)||n("object"==typeof self&&self)||n("object"==typeof i.g&&i.g)||n("object"==typeof this&&this)||function(){return this}()||Function("return this")()},18280:function(e,t,i){"use strict";var n=i(21287),a=i(76998),o=n({}.hasOwnProperty);e.exports=Object.hasOwn||function(e,t){return o(a(e),t)}},15526:function(e){"use strict";e.exports={}},21236:function(e){"use strict";e.exports=function(e,t){try{1==arguments.length?console.error(e):console.error(e,t)}catch(e){}}},61156:function(e,t,i){"use strict";var n=i(30290);e.exports=n("document","documentElement")},22148:function(e,t,i){"use strict";var n=i(95851),a=i(87584),o=i(57004);e.exports=!n&&!a(function(){return 7!==Object.defineProperty(o("div"),"a",{get:function(){return 7}}).a})},66969:function(e){"use strict";var t=Array,i=Math.abs,n=Math.pow,a=Math.floor,o=Math.log,r=Math.LN2;e.exports={pack:function(e,s,l){var u,d,c,m=t(l),p=8*l-s-1,f=(1<>1,h=23===s?n(2,-24)-n(2,-77):0,b=e<0||0===e&&1/e<0?1:0,k=0;for((e=i(e))!=e||e===1/0?(d=e!=e?1:0,u=f):(c=n(2,-(u=a(o(e)/r))),e*c<1&&(u--,c*=2),u+g>=1?e+=h/c:e+=h*n(2,1-g),e*c>=2&&(u++,c/=2),u+g>=f?(d=0,u=f):u+g>=1?(d=(e*c-1)*n(2,s),u+=g):(d=e*n(2,g-1)*n(2,s),u=0));s>=8;)m[k++]=255&d,d/=256,s-=8;for(u=u<0;)m[k++]=255&u,u/=256,p-=8;return m[k-1]|=128*b,m},unpack:function(e,t){var i,a=e.length,o=8*a-t-1,r=(1<>1,l=o-7,u=a-1,d=e[u--],c=127&d;for(d>>=7;l>0;)c=256*c+e[u--],l-=8;for(i=c&(1<<-l)-1,c>>=-l,l+=t;l>0;)i=256*i+e[u--],l-=8;if(0===c)c=1-s;else{if(c===r)return i?NaN:d?-1/0:1/0;i+=n(2,t),c-=s}return(d?-1:1)*i*n(2,c-t)}}},10518:function(e,t,i){"use strict";var n=i(21287),a=i(87584),o=i(64955),r=Object,s=n("".split);e.exports=a(function(){return!r("z").propertyIsEnumerable(0)})?function(e){return"String"===o(e)?s(e,""):r(e)}:r},58728:function(e,t,i){"use strict";var n=i(26838),a=i(90897),o=i(27572);e.exports=function(e,t,i){var r,s;return o&&n(r=t.constructor)&&r!==i&&a(s=r.prototype)&&s!==i.prototype&&o(e,s),e}},30139:function(e,t,i){"use strict";var n=i(21287),a=i(26838),o=i(6972),r=n(Function.toString);a(o.inspectSource)||(o.inspectSource=function(e){return r(e)}),e.exports=o.inspectSource},84639:function(e,t,i){"use strict";var n=i(90897),a=i(45790);e.exports=function(e,t){n(t)&&"cause"in t&&a(e,"cause",t.cause)}},40104:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(15526),r=i(90897),s=i(18280),l=i(45392).f,u=i(84519),d=i(56355),c=i(19457),m=i(61239),p=i(59397),f=!1,g=m("meta"),h=0,b=function(e){l(e,g,{value:{objectID:"O"+h++,weakData:{}}})},k=e.exports={enable:function(){k.enable=function(){},f=!0;var e=u.f,t=a([].splice),i={};i[g]=1,e(i).length&&(u.f=function(i){for(var n=e(i),a=0,o=n.length;ak;k++)if((y=T(e[k]))&&u(g,y))return y;return new f(!1)}h=d(e,b)}for(w=z?e.next:h.next;!(_=a(w,h)).done;){try{y=T(_.value)}catch(e){m(h,"throw",e)}if("object"==typeof y&&y&&u(g,y))return y}return new f(!1)}},32070:function(e,t,i){"use strict";var n=i(79830),a=i(78700),o=i(95211);e.exports=function(e,t,i){var r,s;a(e);try{if(!(r=o(e,"return"))){if("throw"===t)throw i;return i}r=n(r,e)}catch(e){s=!0,r=e}if("throw"===t)throw i;if(s)throw r;return a(r),i}},44137:function(e,t,i){"use strict";var n=i(70656).IteratorPrototype,a=i(1127),o=i(7221),r=i(30380),s=i(10418),l=function(){return this};e.exports=function(e,t,i,u){var d=t+" Iterator";return e.prototype=a(n,{next:o(+!u,i)}),r(e,d,!1,!0),s[d]=l,e}},73605:function(e,t,i){"use strict";var n=i(79830),a=i(1127),o=i(45790),r=i(42726),s=i(5012),l=i(60472),u=i(95211),d=i(70656).IteratorPrototype,c=i(75562),m=i(32070),p=s("toStringTag"),f="IteratorHelper",g="WrapForValidIterator",h=l.set,b=function(e){var t=l.getterFor(e?g:f);return r(a(d),{next:function(){var i=t(this);if(e)return i.nextHandler();if(i.done)return c(void 0,!0);try{var n=i.nextHandler();return i.returnHandlerResult?n:c(n,i.done)}catch(e){throw i.done=!0,e}},return:function(){var i=t(this),a=i.iterator;if(i.done=!0,e){var o=u(a,"return");return o?n(o,a):c(void 0,!0)}if(i.inner)try{m(i.inner.iterator,"normal")}catch(e){return m(a,"throw",e)}return a&&m(a,"normal"),c(void 0,!0)}})},k=b(!0),v=b(!1);o(v,p,"Iterator Helper"),e.exports=function(e,t,i){var n=function(n,a){a?(a.iterator=n.iterator,a.next=n.next):a=n,a.type=t?g:f,a.returnHandlerResult=!!i,a.nextHandler=e,a.counter=0,a.done=!1,h(this,a)};return n.prototype=t?k:v,n}},41979:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(55564),r=i(99397),s=i(26838),l=i(44137),u=i(78792),d=i(27572),c=i(30380),m=i(45790),p=i(98243),f=i(5012),g=i(10418),h=i(70656),b=r.PROPER,k=r.CONFIGURABLE,v=h.IteratorPrototype,y=h.BUGGY_SAFARI_ITERATORS,w=f("iterator"),_="keys",S="values",M="entries",z=function(){return this};e.exports=function(e,t,i,r,f,h,j){l(i,t,r);var P,A,R,T=function(e){if(e===f&&D)return D;if(!y&&e&&e in I)return I[e];switch(e){case _:case S:case M:return function(){return new i(this,e)}}return function(){return new i(this)}},C=t+" Iterator",E=!1,I=e.prototype,x=I[w]||I["@@iterator"]||f&&I[f],D=!y&&x||T(f),O="Array"===t&&I.entries||x;if(O&&(P=u(O.call(new e)))!==Object.prototype&&P.next&&(o||u(P)===v||(d?d(P,v):s(P[w])||p(P,w,z)),c(P,C,!0,!0),o&&(g[C]=z)),b&&f===S&&x&&x.name!==S&&(!o&&k?m(I,"name",S):(E=!0,D=function(){return a(x,this)})),f){if(A={values:T(S),keys:h?D:T(_),entries:T(M)},j)for(R in A)!y&&!E&&R in I||p(I,R,A[R]);else n({target:t,proto:!0,forced:y||E},A)}return(!o||j)&&I[w]!==D&&p(I,w,D,{name:f}),g[t]=D,A}},39788:function(e,t,i){"use strict";var n=i(78307);e.exports=function(e,t){var i=n.Iterator,a=i&&i.prototype,o=a&&a[e],r=!1;if(o)try{o.call({next:function(){return{done:!0}},return:function(){r=!0}},-1)}catch(e){e instanceof t||(r=!1)}if(!r)return o}},70656:function(e,t,i){"use strict";var n,a,o,r=i(87584),s=i(26838),l=i(90897),u=i(1127),d=i(78792),c=i(98243),m=i(5012),p=i(55564),f=m("iterator"),g=!1;[].keys&&("next"in(o=[].keys())?(a=d(d(o)))!==Object.prototype&&(n=a):g=!0),!l(n)||r(function(){var e={};return n[f].call(e)!==e})?n={}:p&&(n=u(n)),s(n[f])||c(n,f,function(){return this}),e.exports={IteratorPrototype:n,BUGGY_SAFARI_ITERATORS:g}},10418:function(e){"use strict";e.exports={}},6171:function(e,t,i){"use strict";var n=i(93221);e.exports=function(e){return n(e.length)}},39692:function(e,t,i){"use strict";var n=i(21287),a=i(87584),o=i(26838),r=i(18280),s=i(95851),l=i(99397).CONFIGURABLE,u=i(30139),d=i(60472),c=d.enforce,m=d.get,p=String,f=Object.defineProperty,g=n("".slice),h=n("".replace),b=n([].join),k=s&&!a(function(){return 8!==f(function(){},"length",{value:8}).length}),v=String(String).split("String"),y=e.exports=function(e,t,i){"Symbol("===g(p(t),0,7)&&(t="["+h(p(t),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),i&&i.getter&&(t="get "+t),i&&i.setter&&(t="set "+t),(!r(e,"name")||l&&e.name!==t)&&(s?f(e,"name",{value:t,configurable:!0}):e.name=t),k&&i&&r(i,"arity")&&e.length!==i.arity&&f(e,"length",{value:i.arity});try{i&&r(i,"constructor")&&i.constructor?s&&f(e,"prototype",{writable:!1}):e.prototype&&(e.prototype=void 0)}catch(e){}var n=c(e);return r(n,"source")||(n.source=b(v,"string"==typeof t?t:"")),e};Function.prototype.toString=y(function(){return o(this)&&m(this).source||u(this)},"toString")},68835:function(e,t,i){"use strict";var n=i(21287),a=Map.prototype;e.exports={Map:Map,set:n(a.set),get:n(a.get),has:n(a.has),remove:n(a.delete),proto:a}},71:function(e){"use strict";var t=Math.expm1,i=Math.exp;e.exports=!t||t(10)>22025.465794806718||22025.465794806718>t(10)||-2e-17!==t(-2e-17)?function(e){var t=+e;return 0===t?t:t>-1e-6&&t<1e-6?t+t*t/2:i(t)-1}:t},55493:function(e,t,i){"use strict";var n=i(83181),a=i(84393),o=Math.abs;e.exports=function(e,t,i,r){var s=+e,l=o(s),u=n(s);if(li||c!=c?1/0*u:u*c}},54354:function(e,t,i){"use strict";var n=i(55493);e.exports=Math.fround||function(e){return n(e,11920928955078125e-23,34028234663852886e22,11754943508222875e-54)}},91577:function(e){"use strict";var t=Math.log,i=Math.LOG10E;e.exports=Math.log10||function(e){return t(e)*i}},10329:function(e){"use strict";var t=Math.log;e.exports=Math.log1p||function(e){var i=+e;return i>-1e-8&&i<1e-8?i-i*i/2:t(1+i)}},4236:function(e){"use strict";var t=Math.log,i=Math.LN2;e.exports=Math.log2||function(e){return t(e)/i}},84393:function(e){"use strict";e.exports=function(e){return e+0x10000000000000-0x10000000000000}},83181:function(e){"use strict";e.exports=Math.sign||function(e){var t=+e;return 0===t||t!=t?t:t<0?-1:1}},66244:function(e){"use strict";var t=Math.ceil,i=Math.floor;e.exports=Math.trunc||function(e){var n=+e;return(n>0?i:t)(n)}},89632:function(e,t,i){"use strict";var n,a,o,r,s,l=i(78307),u=i(84582),d=i(2595),c=i(28004).set,m=i(74478),p=i(25505),f=i(40930),g=i(90079),h=i(46318),b=l.MutationObserver||l.WebKitMutationObserver,k=l.document,v=l.process,y=l.Promise,w=u("queueMicrotask");if(!w){var _=new m,S=function(){var e,t;for(h&&(e=v.domain)&&e.exit();t=_.get();)try{t()}catch(e){throw _.head&&n(),e}e&&e.enter()};p||h||g||!b||!k?!f&&y&&y.resolve?((r=y.resolve(void 0)).constructor=y,s=d(r.then,r),n=function(){s(S)}):h?n=function(){v.nextTick(S)}:(c=d(c,l),n=function(){c(S)}):(a=!0,o=k.createTextNode(""),new b(S).observe(o,{characterData:!0}),n=function(){o.data=a=!a}),w=function(e){_.head||n(),_.add(e)}}e.exports=w},3130:function(e,t,i){"use strict";var n=i(11459),a=TypeError,o=function(e){var t,i;this.promise=new e(function(e,n){if(void 0!==t||void 0!==i)throw new a("Bad Promise constructor");t=e,i=n}),this.resolve=n(t),this.reject=n(i)};e.exports.f=function(e){return new o(e)}},78244:function(e,t,i){"use strict";var n=i(39940);e.exports=function(e,t){return void 0===e?arguments.length<2?"":t:n(e)}},13862:function(e){"use strict";var t=RangeError;e.exports=function(e){if(e==e)return e;throw new t("NaN is not allowed")}},74022:function(e,t,i){"use strict";var n=i(65867),a=TypeError;e.exports=function(e){if(n(e))throw new a("The method doesn't accept regular expressions");return e}},50705:function(e,t,i){"use strict";var n=i(78307).isFinite;e.exports=Number.isFinite||function(e){return"number"==typeof e&&n(e)}},77761:function(e,t,i){"use strict";var n=i(78307),a=i(87584),o=i(21287),r=i(39940),s=i(92269).trim,l=i(93743),u=o("".charAt),d=n.parseFloat,c=n.Symbol,m=c&&c.iterator,p=1/d(l+"-0")!=-1/0||m&&!a(function(){d(Object(m))});e.exports=p?function(e){var t=s(r(e)),i=d(t);return 0===i&&"-"===u(t,0)?-0:i}:d},31566:function(e,t,i){"use strict";var n=i(78307),a=i(87584),o=i(21287),r=i(39940),s=i(92269).trim,l=i(93743),u=n.parseInt,d=n.Symbol,c=d&&d.iterator,m=/^[+-]?0x/i,p=o(m.exec),f=8!==u(l+"08")||22!==u(l+"0x16")||c&&!a(function(){u(Object(c))});e.exports=f?function(e,t){var i=s(r(e));return u(i,t>>>0||(p(m,i)?16:10))}:u},11622:function(e,t,i){"use strict";var n=i(95851),a=i(21287),o=i(79830),r=i(87584),s=i(22695),l=i(42750),u=i(41378),d=i(76998),c=i(10518),m=Object.assign,p=Object.defineProperty,f=a([].concat);e.exports=!m||r(function(){if(n&&1!==m({b:1},m(p({},"a",{enumerable:!0,get:function(){p(this,"b",{value:3,enumerable:!1})}}),{b:2})).b)return!0;var e={},t={},i=Symbol("assign detection"),a="abcdefghijklmnopqrst";return e[i]=7,a.split("").forEach(function(e){t[e]=e}),7!==m({},e)[i]||s(m({},t)).join("")!==a})?function(e,t){for(var i=d(e),a=arguments.length,r=1,m=l.f,p=u.f;a>r;)for(var g,h=c(arguments[r++]),b=m?f(s(h),m(h)):s(h),k=b.length,v=0;k>v;)g=b[v++],(!n||o(p,h,g))&&(i[g]=h[g]);return i}:m},1127:function(e,t,i){"use strict";var n,a=i(78700),o=i(3144),r=i(80708),s=i(15526),l=i(61156),u=i(57004),d=i(87286),c="prototype",m="script",p=d("IE_PROTO"),f=function(){},g=function(e){return"<"+m+">"+e+""},h=function(e){e.write(g("")),e.close();var t=e.parentWindow.Object;return e=null,t},b=function(){var e,t=u("iframe");return t.style.display="none",l.appendChild(t),t.src=String("java"+m+":"),(e=t.contentWindow.document).open(),e.write(g("document.F=Object")),e.close(),e.F},k=function(){try{n=new ActiveXObject("htmlfile")}catch(e){}k="undefined"!=typeof document?document.domain&&n?h(n):b():h(n);for(var e=r.length;e--;)delete k[c][r[e]];return k()};s[p]=!0,e.exports=Object.create||function(e,t){var i;return null!==e?(f[c]=a(e),i=new f,f[c]=null,i[p]=e):i=k(),void 0===t?i:o.f(i,t)}},3144:function(e,t,i){"use strict";var n=i(95851),a=i(64121),o=i(45392),r=i(78700),s=i(770),l=i(22695);t.f=n&&!a?Object.defineProperties:function(e,t){r(e);for(var i,n=s(t),a=l(t),u=a.length,d=0;u>d;)o.f(e,i=a[d++],n[i]);return e}},45392:function(e,t,i){"use strict";var n=i(95851),a=i(22148),o=i(64121),r=i(78700),s=i(38042),l=TypeError,u=Object.defineProperty,d=Object.getOwnPropertyDescriptor,c="enumerable",m="configurable",p="writable";t.f=n?o?function(e,t,i){if(r(e),t=s(t),r(i),"function"==typeof e&&"prototype"===t&&"value"in i&&p in i&&!i[p]){var n=d(e,t);n&&n[p]&&(e[t]=i.value,i={configurable:m in i?i[m]:n[m],enumerable:c in i?i[c]:n[c],writable:!1})}return u(e,t,i)}:u:function(e,t,i){if(r(e),t=s(t),r(i),a)try{return u(e,t,i)}catch(e){}if("get"in i||"set"in i)throw new l("Accessors not supported");return"value"in i&&(e[t]=i.value),e}},18994:function(e,t,i){"use strict";var n=i(95851),a=i(79830),o=i(41378),r=i(7221),s=i(770),l=i(38042),u=i(18280),d=i(22148),c=Object.getOwnPropertyDescriptor;t.f=n?c:function(e,t){if(e=s(e),t=l(t),d)try{return c(e,t)}catch(e){}if(u(e,t))return r(!a(o.f,e,t),e[t])}},56355:function(e,t,i){"use strict";var n=i(64955),a=i(770),o=i(84519).f,r=i(89887),s="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],l=function(e){try{return o(e)}catch(e){return r(s)}};e.exports.f=function(e){return s&&"Window"===n(e)?l(e):o(a(e))}},84519:function(e,t,i){"use strict";var n=i(18649),a=i(80708).concat("length","prototype");t.f=Object.getOwnPropertyNames||function(e){return n(e,a)}},42750:function(e,t){"use strict";t.f=Object.getOwnPropertySymbols},78792:function(e,t,i){"use strict";var n=i(18280),a=i(26838),o=i(76998),r=i(87286),s=i(97722),l=r("IE_PROTO"),u=Object,d=u.prototype;e.exports=s?u.getPrototypeOf:function(e){var t=o(e);if(n(t,l))return t[l];var i=t.constructor;return a(i)&&t instanceof i?i.prototype:t instanceof u?d:null}},19457:function(e,t,i){"use strict";var n=i(87584),a=i(90897),o=i(64955),r=i(88683),s=Object.isExtensible,l=n(function(){s(1)});e.exports=l||r?function(e){return!!a(e)&&(!r||"ArrayBuffer"!==o(e))&&(!s||s(e))}:s},29020:function(e,t,i){"use strict";var n=i(21287);e.exports=n({}.isPrototypeOf)},18649:function(e,t,i){"use strict";var n=i(21287),a=i(18280),o=i(770),r=i(51872).indexOf,s=i(15526),l=n([].push);e.exports=function(e,t){var i,n=o(e),u=0,d=[];for(i in n)!a(s,i)&&a(n,i)&&l(d,i);for(;t.length>u;)a(n,i=t[u++])&&(~r(d,i)||l(d,i));return d}},22695:function(e,t,i){"use strict";var n=i(18649),a=i(80708);e.exports=Object.keys||function(e){return n(e,a)}},41378:function(e,t){"use strict";var i={}.propertyIsEnumerable,n=Object.getOwnPropertyDescriptor,a=n&&!i.call({1:2},1);t.f=a?function(e){var t=n(this,e);return!!t&&t.enumerable}:i},30636:function(e,t,i){"use strict";var n=i(55564),a=i(78307),o=i(87584),r=i(81974);e.exports=n||!o(function(){if(!r||!(r<535)){var e=Math.random();__defineSetter__.call(null,e,function(){}),delete a[e]}})},27572:function(e,t,i){"use strict";var n=i(595),a=i(90897),o=i(59899),r=i(70615);e.exports=Object.setPrototypeOf||("__proto__"in{}?function(){var e,t=!1,i={};try{(e=n(Object.prototype,"__proto__","set"))(i,[]),t=i instanceof Array}catch(e){}return function(i,n){return o(i),r(n),a(i)&&(t?e(i,n):i.__proto__=n),i}}():void 0)},36246:function(e,t,i){"use strict";var n=i(95851),a=i(87584),o=i(21287),r=i(78792),s=i(22695),l=i(770),u=o(i(41378).f),d=o([].push),c=n&&a(function(){var e=Object.create(null);return e[2]=2,!u(e,2)}),m=function(e){return function(t){for(var i,a=l(t),o=s(a),m=c&&null===r(a),p=o.length,f=0,g=[];p>f;)i=o[f++],(!n||(m?i in a:u(a,i)))&&d(g,e?[i,a[i]]:a[i]);return g}};e.exports={entries:m(!0),values:m(!1)}},58794:function(e,t,i){"use strict";var n=i(7083),a=i(81192);e.exports=n?({}).toString:function(){return"[object "+a(this)+"]"}},75121:function(e,t,i){"use strict";var n=i(79830),a=i(26838),o=i(90897),r=TypeError;e.exports=function(e,t){var i,s;if("string"===t&&a(i=e.toString)&&!o(s=n(i,e))||a(i=e.valueOf)&&!o(s=n(i,e))||"string"!==t&&a(i=e.toString)&&!o(s=n(i,e)))return s;throw new r("Can't convert object to primitive value")}},50758:function(e,t,i){"use strict";var n=i(30290),a=i(21287),o=i(84519),r=i(42750),s=i(78700),l=a([].concat);e.exports=n("Reflect","ownKeys")||function(e){var t=o.f(s(e)),i=r.f;return i?l(t,i(e)):t}},20386:function(e,t,i){"use strict";var n=i(78307);e.exports=n},95400:function(e){"use strict";e.exports=function(e){try{return{error:!1,value:e()}}catch(e){return{error:!0,value:e}}}},66611:function(e,t,i){"use strict";var n=i(78307),a=i(34011),o=i(26838),r=i(7539),s=i(30139),l=i(5012),u=i(88812),d=i(55564),c=i(17258),m=a&&a.prototype,p=l("species"),f=!1,g=o(n.PromiseRejectionEvent),h=r("Promise",function(){var e=s(a),t=e!==String(a);if(!t&&66===c||d&&!(m.catch&&m.finally))return!0;if(!c||c<51||!/native code/.test(e)){var i=new a(function(e){e(1)}),n=function(e){e(function(){},function(){})};if((i.constructor={})[p]=n,!(f=i.then(function(){})instanceof n))return!0}return!t&&("BROWSER"===u||"DENO"===u)&&!g});e.exports={CONSTRUCTOR:h,REJECTION_EVENT:g,SUBCLASSING:f}},34011:function(e,t,i){"use strict";var n=i(78307);e.exports=n.Promise},88557:function(e,t,i){"use strict";var n=i(78700),a=i(90897),o=i(3130);e.exports=function(e,t){if(n(e),a(t)&&t.constructor===e)return t;var i=o.f(e);return(0,i.resolve)(t),i.promise}},75310:function(e,t,i){"use strict";var n=i(34011),a=i(35765),o=i(66611).CONSTRUCTOR;e.exports=o||!a(function(e){n.all(e).then(void 0,function(){})})},71097:function(e,t,i){"use strict";var n=i(45392).f;e.exports=function(e,t,i){i in e||n(e,i,{configurable:!0,get:function(){return t[i]},set:function(e){t[i]=e}})}},74478:function(e){"use strict";var t=function(){this.head=null,this.tail=null};t.prototype={add:function(e){var t={item:e,next:null},i=this.tail;i?i.next=t:this.head=t,this.tail=t},get:function(){var e=this.head;if(e)return null===(this.head=e.next)&&(this.tail=null),e.item}},e.exports=t},35055:function(e,t,i){"use strict";var n=i(79830),a=i(78700),o=i(26838),r=i(64955),s=i(31960),l=TypeError;e.exports=function(e,t){var i=e.exec;if(o(i)){var u=n(i,e,t);return null!==u&&a(u),u}if("RegExp"===r(e))return n(s,e,t);throw new l("RegExp#exec called on incompatible receiver")}},31960:function(e,t,i){"use strict";var n,a,o=i(79830),r=i(21287),s=i(39940),l=i(47706),u=i(6914),d=i(5364),c=i(1127),m=i(60472).get,p=i(48834),f=i(85055),g=d("native-string-replace",String.prototype.replace),h=RegExp.prototype.exec,b=h,k=r("".charAt),v=r("".indexOf),y=r("".replace),w=r("".slice),_=(a=/b*/g,o(h,n=/a/,"a"),o(h,a,"a"),0!==n.lastIndex||0!==a.lastIndex),S=u.BROKEN_CARET,M=void 0!==/()??/.exec("")[1];(_||M||S||p||f)&&(b=function(e){var t,i,n,a,r,u,d,p=m(this),f=s(e),z=p.raw;if(z)return z.lastIndex=this.lastIndex,t=o(b,z,f),this.lastIndex=z.lastIndex,t;var j=p.groups,P=S&&this.sticky,A=o(l,this),R=this.source,T=0,C=f;if(P&&(-1===v(A=y(A,"y",""),"g")&&(A+="g"),C=w(f,this.lastIndex),this.lastIndex>0&&(!this.multiline||this.multiline&&"\n"!==k(f,this.lastIndex-1))&&(R="(?: "+R+")",C=" "+C,T++),i=RegExp("^(?:"+R+")",A)),M&&(i=RegExp("^"+R+"$(?!\\s)",A)),_&&(n=this.lastIndex),a=o(h,P?i:this,C),P?a?(a.input=w(a.input,T),a[0]=w(a[0],T),a.index=this.lastIndex,this.lastIndex+=a[0].length):this.lastIndex=0:_&&a&&(this.lastIndex=this.global?a.index+a[0].length:n),M&&a&&a.length>1&&o(g,a[0],i,function(){for(r=1;rb)","g");return"b"!==e.exec("b").groups.a||"bc"!=="b".replace(e,"$
c")})},59899:function(e,t,i){"use strict";var n=i(61852),a=TypeError;e.exports=function(e){if(n(e))throw new a("Can't call method on "+e);return e}},84582:function(e,t,i){"use strict";var n=i(78307),a=i(95851),o=Object.getOwnPropertyDescriptor;e.exports=function(e){if(!a)return n[e];var t=o(n,e);return t&&t.value}},16455:function(e){"use strict";e.exports=Object.is||function(e,t){return e===t?0!==e||1/e==1/t:e!=e&&t!=t}},55017:function(e,t,i){"use strict";var n,a=i(78307),o=i(76180),r=i(26838),s=i(88812),l=i(43950),u=i(89887),d=i(18535),c=a.Function,m=/MSIE .\./.test(l)||"BUN"===s&&((n=a.Bun.version.split(".")).length<3||"0"===n[0]&&(n[1]<3||"3"===n[1]&&"0"===n[2]));e.exports=function(e,t){var i=t?2:1;return m?function(n,a){var s=d(arguments.length,1)>i,l=r(n)?n:c(n),m=s?u(arguments,i):[],p=s?function(){o(l,this,m)}:l;return t?e(p,a):e(p)}:e}},16477:function(e,t,i){"use strict";var n=i(27853),a=i(6478),o=n.Set,r=n.add;e.exports=function(e){var t=new o;return a(e,function(e){r(t,e)}),t}},75405:function(e,t,i){"use strict";var n=i(54795),a=i(27853),o=i(16477),r=i(56923),s=i(9288),l=i(6478),u=i(95818),d=a.has,c=a.remove;e.exports=function(e){var t=n(this),i=s(e),a=o(t);return r(t)<=i.size?l(t,function(e){i.includes(e)&&c(a,e)}):u(i.getIterator(),function(e){d(t,e)&&c(a,e)}),a}},27853:function(e,t,i){"use strict";var n=i(21287),a=Set.prototype;e.exports={Set:Set,add:n(a.add),has:n(a.has),remove:n(a.delete),proto:a}},71263:function(e,t,i){"use strict";var n=i(54795),a=i(27853),o=i(56923),r=i(9288),s=i(6478),l=i(95818),u=a.Set,d=a.add,c=a.has;e.exports=function(e){var t=n(this),i=r(e),a=new u;return o(t)>i.size?l(i.getIterator(),function(e){c(t,e)&&d(a,e)}):s(t,function(e){i.includes(e)&&d(a,e)}),a}},23011:function(e,t,i){"use strict";var n=i(54795),a=i(27853).has,o=i(56923),r=i(9288),s=i(6478),l=i(95818),u=i(32070);e.exports=function(e){var t=n(this),i=r(e);if(o(t)<=i.size)return!1!==s(t,function(e){if(i.includes(e))return!1},!0);var d=i.getIterator();return!1!==l(d,function(e){if(a(t,e))return u(d,"normal",!1)})}},80879:function(e,t,i){"use strict";var n=i(54795),a=i(56923),o=i(6478),r=i(9288);e.exports=function(e){var t=n(this),i=r(e);return!(a(t)>i.size)&&!1!==o(t,function(e){if(!i.includes(e))return!1},!0)}},35798:function(e,t,i){"use strict";var n=i(54795),a=i(27853).has,o=i(56923),r=i(9288),s=i(95818),l=i(32070);e.exports=function(e){var t=n(this),i=r(e);if(o(t)3})}},9946:function(e,t,i){"use strict";var n=i(21287),a=i(47742),o=i(39940),r=i(59899),s=n("".charAt),l=n("".charCodeAt),u=n("".slice),d=function(e){return function(t,i){var n,d,c=o(r(t)),m=a(i),p=c.length;return m<0||m>=p?e?"":void 0:(n=l(c,m))<55296||n>56319||m+1===p||(d=l(c,m+1))<56320||d>57343?e?s(c,m):n:e?u(c,m,m+2):(n-55296<<10)+(d-56320)+65536}};e.exports={codeAt:d(!1),charAt:d(!0)}},68632:function(e,t,i){"use strict";var n=i(43950);e.exports=/Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(n)},54672:function(e,t,i){"use strict";var n=i(21287),a=i(93221),o=i(39940),r=i(21198),s=i(59899),l=n(r),u=n("".slice),d=Math.ceil,c=function(e){return function(t,i,n){var r,c,m=o(s(t)),p=a(i),f=m.length,g=void 0===n?" ":o(n);return p<=f||""===g?m:((c=l(g,d((r=p-f)/g.length))).length>r&&(c=u(c,0,r)),e?m+c:c+m)}};e.exports={start:c(!1),end:c(!0)}},14680:function(e,t,i){"use strict";var n=i(21287),a=/[^\0-\u007E]/,o=/[.\u3002\uFF0E\uFF61]/g,r="Overflow: input needs wider integers to process",s=RangeError,l=n(o.exec),u=Math.floor,d=String.fromCharCode,c=n("".charCodeAt),m=n([].join),p=n([].push),f=n("".replace),g=n("".split),h=n("".toLowerCase),b=function(e){for(var t=[],i=0,n=e.length;i=55296&&a<=56319&&i>1,e+=u(e/t);e>455;)e=u(e/35),n+=36;return u(n+36*e/(e+38))},y=function(e){var t,i,n=[],a=(e=b(e)).length,o=128,l=0,c=72;for(t=0;t=o&&iu((0x7fffffff-l)/y))throw new s(r);for(l+=(h-o)*y,o=h,t=0;t0x7fffffff)throw new s(r);if(i===o){for(var w=l,_=36;;){var S=_<=c?1:_>=c+26?26:_-c;if(w0;(s>>>=1)&&(t+=t))1&s&&(i+=t);return i}},17949:function(e,t,i){"use strict";var n=i(92269).end,a=i(36639);e.exports=a("trimEnd")?function(){return n(this)}:"".trimEnd},36639:function(e,t,i){"use strict";var n=i(99397).PROPER,a=i(87584),o=i(93743),r="​\x85᠎";e.exports=function(e){return a(function(){return!!o[e]()||r[e]()!==r||n&&o[e].name!==e})}},24852:function(e,t,i){"use strict";var n=i(92269).start,a=i(36639);e.exports=a("trimStart")?function(){return n(this)}:"".trimStart},92269:function(e,t,i){"use strict";var n=i(21287),a=i(59899),o=i(39940),r=i(93743),s=n("".replace),l=RegExp("^["+r+"]+"),u=RegExp("(^|[^"+r+"])["+r+"]+$"),d=function(e){return function(t){var i=o(a(t));return 1&e&&(i=s(i,l,"")),2&e&&(i=s(i,u,"$1")),i}};e.exports={start:d(1),end:d(2),trim:d(3)}},95161:function(e,t,i){"use strict";var n=i(78307),a=i(87584),o=i(17258),r=i(88812),s=n.structuredClone;e.exports=!!s&&!a(function(){if("DENO"===r&&o>92||"NODE"===r&&o>94||"BROWSER"===r&&o>97)return!1;var e=new ArrayBuffer(8),t=s(e,{transfer:[e]});return 0!==e.byteLength||8!==t.byteLength})},45154:function(e,t,i){"use strict";var n=i(17258),a=i(87584),o=i(78307).String;e.exports=!!Object.getOwnPropertySymbols&&!a(function(){var e=Symbol("symbol detection");return!o(e)||!(Object(e)instanceof Symbol)||!Symbol.sham&&n&&n<41})},50575:function(e,t,i){"use strict";var n=i(79830),a=i(30290),o=i(5012),r=i(98243);e.exports=function(){var e=a("Symbol"),t=e&&e.prototype,i=t&&t.valueOf,s=o("toPrimitive");t&&!t[s]&&r(t,s,function(e){return n(i,this)},{arity:1})}},57927:function(e,t,i){"use strict";var n=i(45154);e.exports=n&&!!Symbol.for&&!!Symbol.keyFor},28004:function(e,t,i){"use strict";var n,a,o,r,s=i(78307),l=i(76180),u=i(2595),d=i(26838),c=i(18280),m=i(87584),p=i(61156),f=i(89887),g=i(57004),h=i(18535),b=i(25505),k=i(46318),v=s.setImmediate,y=s.clearImmediate,w=s.process,_=s.Dispatch,S=s.Function,M=s.MessageChannel,z=s.String,j=0,P={},A="onreadystatechange";m(function(){n=s.location});var R=function(e){if(c(P,e)){var t=P[e];delete P[e],t()}},T=function(e){return function(){R(e)}},C=function(e){R(e.data)},E=function(e){s.postMessage(z(e),n.protocol+"//"+n.host)};v&&y||(v=function(e){h(arguments.length,1);var t=d(e)?e:S(e),i=f(arguments,1);return P[++j]=function(){l(t,void 0,i)},a(j),j},y=function(e){delete P[e]},k?a=function(e){w.nextTick(T(e))}:_&&_.now?a=function(e){_.now(T(e))}:M&&!b?(r=(o=new M).port2,o.port1.onmessage=C,a=u(r.postMessage,r)):s.addEventListener&&d(s.postMessage)&&!s.importScripts&&n&&"file:"!==n.protocol&&!m(E)?(a=E,s.addEventListener("message",C,!1)):a=A in g("script")?function(e){p.appendChild(g("script"))[A]=function(){p.removeChild(this),R(e)}}:function(e){setTimeout(T(e),0)}),e.exports={set:v,clear:y}},12539:function(e,t,i){"use strict";var n=i(21287);e.exports=n(1..valueOf)},68757:function(e,t,i){"use strict";var n=i(47742),a=Math.max,o=Math.min;e.exports=function(e,t){var i=n(e);return i<0?a(i+t,0):o(i,t)}},51855:function(e,t,i){"use strict";var n=i(32032),a=TypeError;e.exports=function(e){var t=n(e,"number");if("number"==typeof t)throw new a("Can't convert number to bigint");return BigInt(t)}},81973:function(e,t,i){"use strict";var n=i(47742),a=i(93221),o=RangeError;e.exports=function(e){if(void 0===e)return 0;var t=n(e),i=a(t);if(t!==i)throw new o("Wrong length or index");return i}},770:function(e,t,i){"use strict";var n=i(10518),a=i(59899);e.exports=function(e){return n(a(e))}},47742:function(e,t,i){"use strict";var n=i(66244);e.exports=function(e){var t=+e;return t!=t||0===t?0:n(t)}},93221:function(e,t,i){"use strict";var n=i(47742),a=Math.min;e.exports=function(e){var t=n(e);return t>0?a(t,0x1fffffffffffff):0}},76998:function(e,t,i){"use strict";var n=i(59899),a=Object;e.exports=function(e){return a(n(e))}},44714:function(e,t,i){"use strict";var n=i(27349),a=RangeError;e.exports=function(e,t){var i=n(e);if(i%t)throw new a("Wrong offset");return i}},27349:function(e,t,i){"use strict";var n=i(47742),a=RangeError;e.exports=function(e){var t=n(e);if(t<0)throw new a("The argument can't be less than 0");return t}},32032:function(e,t,i){"use strict";var n=i(79830),a=i(90897),o=i(47102),r=i(95211),s=i(75121),l=i(5012),u=TypeError,d=l("toPrimitive");e.exports=function(e,t){if(!a(e)||o(e))return e;var i,l=r(e,d);if(l){if(void 0===t&&(t="default"),!a(i=n(l,e,t))||o(i))return i;throw new u("Can't convert object to primitive value")}return void 0===t&&(t="number"),s(e,t)}},38042:function(e,t,i){"use strict";var n=i(32032),a=i(47102);e.exports=function(e){var t=n(e,"string");return a(t)?t:t+""}},7083:function(e,t,i){"use strict";var n=i(5012)("toStringTag"),a={};a[n]="z",e.exports="[object z]"===String(a)},39940:function(e,t,i){"use strict";var n=i(81192),a=String;e.exports=function(e){if("Symbol"===n(e))throw TypeError("Cannot convert a Symbol value to a string");return a(e)}},96634:function(e){"use strict";var t=Math.round;e.exports=function(e){var i=t(e);return i<0?0:i>255?255:255&i}},31524:function(e){"use strict";var t=String;e.exports=function(e){try{return t(e)}catch(e){return"Object"}}},7312:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(79830),r=i(95851),s=i(15918),l=i(43413),u=i(24515),d=i(72720),c=i(7221),m=i(45790),p=i(98542),f=i(93221),g=i(81973),h=i(44714),b=i(96634),k=i(38042),v=i(18280),y=i(81192),w=i(90897),_=i(47102),S=i(1127),M=i(29020),z=i(27572),j=i(84519).f,P=i(80922),A=i(67754).forEach,R=i(9050),T=i(25039),C=i(45392),E=i(18994),I=i(30161),x=i(60472),D=i(58728),O=x.get,L=x.set,V=x.enforce,N=C.f,U=E.f,F=a.RangeError,B=u.ArrayBuffer,H=B.prototype,K=u.DataView,q=l.NATIVE_ARRAY_BUFFER_VIEWS,$=l.TYPED_ARRAY_TAG,W=l.TypedArray,G=l.TypedArrayPrototype,Y=l.isTypedArray,Q="BYTES_PER_ELEMENT",Z="Wrong length",J=function(e,t){T(e,t,{configurable:!0,get:function(){return O(this)[t]}})},X=function(e){var t;return M(H,e)||"ArrayBuffer"===(t=y(e))||"SharedArrayBuffer"===t},ee=function(e,t){return Y(e)&&!_(t)&&t in e&&p(+t)&&t>=0},et=function(e,t){return ee(e,t=k(t))?c(2,e[t]):U(e,t)},ei=function(e,t,i){return ee(e,t=k(t))&&w(i)&&v(i,"value")&&!v(i,"get")&&!v(i,"set")&&!i.configurable&&(!v(i,"writable")||i.writable)&&(!v(i,"enumerable")||i.enumerable)?(e[t]=i.value,e):N(e,t,i)};r?(q||(E.f=et,C.f=ei,J(G,"buffer"),J(G,"byteOffset"),J(G,"byteLength"),J(G,"length")),n({target:"Object",stat:!0,forced:!q},{getOwnPropertyDescriptor:et,defineProperty:ei}),e.exports=function(e,t,i){var r=e.match(/\d+/)[0]/8,l=e+(i?"Clamped":"")+"Array",u="get"+e,c="set"+e,p=a[l],k=p,v=k&&k.prototype,y={},_=function(e,t){var i=O(e);return i.view[u](t*r+i.byteOffset,!0)},M=function(e,t,n){var a=O(e);a.view[c](t*r+a.byteOffset,i?b(n):n,!0)},T=function(e,t){N(e,t,{get:function(){return _(this,t)},set:function(e){return M(this,t,e)},enumerable:!0})};q?s&&(k=t(function(e,t,i,n){return d(e,v),D(w(t)?X(t)?void 0!==n?new p(t,h(i,r),n):void 0!==i?new p(t,h(i,r)):new p(t):Y(t)?I(k,t):o(P,k,t):new p(g(t)),e,k)}),z&&z(k,W),A(j(p),function(e){e in k||m(k,e,p[e])}),k.prototype=v):(k=t(function(e,t,i,n){d(e,v);var a,s,l,u=0,c=0;if(w(t)){if(X(t)){a=t,c=h(i,r);var m=t.byteLength;if(void 0===n){if(m%r||(s=m-c)<0)throw new F(Z)}else if((s=f(n)*r)+c>m)throw new F(Z);l=s/r}else if(Y(t))return I(k,t);else return o(P,k,t)}else a=new B(s=(l=g(t))*r);for(L(e,{buffer:a,byteOffset:c,byteLength:s,length:l,view:new K(a)});u1?arguments[1]:void 0,M=void 0!==S,z=u(w);if(z&&!d(z))for(v=(k=l(w,z)).next,w=[];!(b=a(v,k)).done;)w.push(b.value);for(M&&_>2&&(S=n(S,arguments[2])),i=s(w),g=c(f=new(m(y))(i)),t=0;i>t;t++)h=M?S(w[t],t):w[t],f[t]=g?p(h):+h;return f}},61239:function(e,t,i){"use strict";var n=i(21287),a=0,o=Math.random(),r=n(1..toString);e.exports=function(e){return"Symbol("+(void 0===e?"":e)+")_"+r(++a+o,36)}},39859:function(e,t,i){"use strict";var n=i(87584),a=i(5012),o=i(95851),r=i(55564),s=a("iterator");e.exports=!n(function(){var e=new URL("b?a=1&b=2&c=3","https://a"),t=e.searchParams,i=new URLSearchParams("a=1&a=2&b=3"),n="";return e.pathname="c%20d",t.forEach(function(e,i){t.delete("b"),n+=i+e}),i.delete("a",2),i.delete("b",void 0),r&&(!e.toJSON||!i.has("a",1)||i.has("a",2)||!i.has("a",void 0)||i.has("b"))||!t.size&&(r||!o)||!t.sort||"https://a/c%20d?a=1&c=3"!==e.href||"3"!==t.get("c")||"a=1"!==String(new URLSearchParams("?a=1"))||!t[s]||"a"!==new URL("https://a@b").username||"b"!==new URLSearchParams(new URLSearchParams("a=b")).get("a")||"xn--e1aybc"!==new URL("https://тест").host||"#%D0%B1"!==new URL("https://a#б").hash||"a1c3"!==n||"x"!==new URL("https://x",void 0).host})},51723:function(e,t,i){"use strict";var n=i(45154);e.exports=n&&!Symbol.sham&&"symbol"==typeof Symbol.iterator},64121:function(e,t,i){"use strict";var n=i(95851),a=i(87584);e.exports=n&&a(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype})},18535:function(e){"use strict";var t=TypeError;e.exports=function(e,i){if(ek&&m(n,arguments[k]),n});if(M.prototype=_,"Error"!==y?s?s(M,S):l(M,S,{name:!0}):f&&b in w&&(u(M,w,b),u(M,w,"prepareStackTrace")),l(M,w),!g)try{_.name!==y&&o(_,"name",y),_.constructor=M}catch(e){}return M}}},343:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(76180),r=i(87584),s=i(93658),l="AggregateError",u=a(l),d=!r(function(){return 1!==u([1]).errors[0]})&&r(function(){return 7!==u([1],l,{cause:7}).cause});n({global:!0,constructor:!0,arity:2,forced:d},{AggregateError:s(l,function(e){return function(t,i){return o(e,this,arguments)}},d,!0)})},51668:function(e,t,i){"use strict";var n=i(21911),a=i(29020),o=i(78792),r=i(27572),s=i(39207),l=i(1127),u=i(45790),d=i(7221),c=i(84639),m=i(40472),p=i(48747),f=i(78244),g=i(5012)("toStringTag"),h=Error,b=[].push,k=function(e,t){var i,n=a(v,this);r?i=r(new h,n?o(this):v):u(i=n?this:l(v),g,"Error"),void 0!==t&&u(i,"message",f(t)),m(i,k,i.stack,1),arguments.length>2&&c(i,arguments[2]);var s=[];return p(e,b,{that:s}),u(i,"errors",s),i};r?r(k,h):s(k,h,{name:!0});var v=k.prototype=l(h.prototype,{constructor:d(1,k),message:d(1,""),name:d(1,"AggregateError")});n({global:!0,constructor:!0,arity:2},{AggregateError:k})},86098:function(e,t,i){"use strict";i(51668)},55712:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(24515),r=i(9050),s="ArrayBuffer",l=o[s];n({global:!0,constructor:!0,forced:a[s]!==l},{ArrayBuffer:l}),r(s)},75548:function(e,t,i){"use strict";var n=i(95851),a=i(25039),o=i(94423),r=ArrayBuffer.prototype;!n||"detached"in r||a(r,"detached",{configurable:!0,get:function(){return o(this)}})},96534:function(e,t,i){"use strict";var n=i(21911),a=i(43413);n({target:"ArrayBuffer",stat:!0,forced:!a.NATIVE_ARRAY_BUFFER_VIEWS},{isView:a.isView})},99406:function(e,t,i){"use strict";var n=i(21911),a=i(98293),o=i(87584),r=i(24515),s=i(78700),l=i(68757),u=i(93221),d=r.ArrayBuffer,c=r.DataView,m=c.prototype,p=a(d.prototype.slice),f=a(m.getUint8),g=a(m.setUint8);n({target:"ArrayBuffer",proto:!0,unsafe:!0,forced:o(function(){return!new d(2).slice(1,void 0).byteLength})},{slice:function(e,t){if(p&&void 0===t)return p(s(this),e);for(var i=s(this).byteLength,n=l(e,i),a=l(void 0===t?i:t,i),o=new d(u(a-n)),r=new c(this),m=new c(o),h=0;n=0?n:i+n;return s<0||s>=i?void 0:t[s]}}),s("at")},64941:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(95493),r=i(90897),s=i(76998),l=i(6171),u=i(19580),d=i(44083),c=i(52844),m=i(97068),p=i(5012),f=i(17258),g=p("isConcatSpreadable"),h=f>=51||!a(function(){var e=[];return e[g]=!1,e.concat()[0]!==e}),b=function(e){if(!r(e))return!1;var t=e[g];return void 0!==t?!!t:o(e)};n({target:"Array",proto:!0,arity:1,forced:!h||!m("concat")},{concat:function(e){var t,i,n,a,o,r=s(this),m=c(r,0),p=0;for(t=-1,n=arguments.length;t1?arguments[1]:void 0)}})},3876:function(e,t,i){"use strict";var n=i(21911),a=i(50356),o=i(2960);n({target:"Array",proto:!0},{fill:a}),o("fill")},59811:function(e,t,i){"use strict";var n=i(21911),a=i(67754).filter;n({target:"Array",proto:!0,forced:!i(97068)("filter")},{filter:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}})},66947:function(e,t,i){"use strict";var n=i(21911),a=i(67754).findIndex,o=i(2960),r="findIndex",s=!0;r in[]&&[,][r](function(){s=!1}),n({target:"Array",proto:!0,forced:s},{findIndex:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}}),o(r)},12062:function(e,t,i){"use strict";var n=i(21911),a=i(26864).findLastIndex,o=i(2960);n({target:"Array",proto:!0},{findLastIndex:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}}),o("findLastIndex")},53903:function(e,t,i){"use strict";var n=i(21911),a=i(26864).findLast,o=i(2960);n({target:"Array",proto:!0},{findLast:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}}),o("findLast")},38286:function(e,t,i){"use strict";var n=i(21911),a=i(67754).find,o=i(2960),r="find",s=!0;r in[]&&[,][r](function(){s=!1}),n({target:"Array",proto:!0,forced:s},{find:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}}),o(r)},34561:function(e,t,i){"use strict";var n=i(21911),a=i(20106),o=i(11459),r=i(76998),s=i(6171),l=i(52844);n({target:"Array",proto:!0},{flatMap:function(e){var t,i=r(this),n=s(i);return o(e),(t=l(i,0)).length=a(t,i,i,n,0,1,e,arguments.length>1?arguments[1]:void 0),t}})},48430:function(e,t,i){"use strict";var n=i(21911),a=i(20106),o=i(76998),r=i(6171),s=i(47742),l=i(52844);n({target:"Array",proto:!0},{flat:function(){var e=arguments.length?arguments[0]:void 0,t=o(this),i=r(t),n=l(t,0);return n.length=a(n,t,t,i,0,void 0===e?1:s(e)),n}})},57046:function(e,t,i){"use strict";var n=i(21911),a=i(92166);n({target:"Array",proto:!0,forced:[].forEach!==a},{forEach:a})},8569:function(e,t,i){"use strict";var n=i(21911),a=i(35657);n({target:"Array",stat:!0,forced:!i(35765)(function(e){Array.from(e)})},{from:a})},7184:function(e,t,i){"use strict";var n=i(21911),a=i(51872).includes,o=i(87584),r=i(2960);n({target:"Array",proto:!0,forced:o(function(){return![,].includes()})},{includes:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}}),r("includes")},34587:function(e,t,i){"use strict";var n=i(21911),a=i(98293),o=i(51872).indexOf,r=i(45395),s=a([].indexOf),l=!!s&&1/s([1],1,-0)<0;n({target:"Array",proto:!0,forced:l||!r("indexOf")},{indexOf:function(e){var t=arguments.length>1?arguments[1]:void 0;return l?s(this,e,t)||0:o(this,e,t)}})},97109:function(e,t,i){"use strict";i(21911)({target:"Array",stat:!0},{isArray:i(95493)})},47895:function(e,t,i){"use strict";var n=i(770),a=i(2960),o=i(10418),r=i(60472),s=i(45392).f,l=i(41979),u=i(75562),d=i(55564),c=i(95851),m="Array Iterator",p=r.set,f=r.getterFor(m);e.exports=l(Array,"Array",function(e,t){p(this,{type:m,target:n(e),index:0,kind:t})},function(){var e=f(this),t=e.target,i=e.index++;if(!t||i>=t.length)return e.target=null,u(void 0,!0);switch(e.kind){case"keys":return u(i,!1);case"values":return u(t[i],!1)}return u([i,t[i]],!1)},"values");var g=o.Arguments=o.Array;if(a("keys"),a("values"),a("entries"),!d&&c&&"values"!==g.name)try{s(g,"name",{value:"values"})}catch(e){}},43721:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(10518),r=i(770),s=i(45395),l=a([].join);n({target:"Array",proto:!0,forced:o!==Object||!s("join",",")},{join:function(e){return l(r(this),void 0===e?",":e)}})},15580:function(e,t,i){"use strict";var n=i(21911),a=i(62348);n({target:"Array",proto:!0,forced:a!==[].lastIndexOf},{lastIndexOf:a})},85699:function(e,t,i){"use strict";var n=i(21911),a=i(67754).map;n({target:"Array",proto:!0,forced:!i(97068)("map")},{map:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}})},15480:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(3776),r=i(44083),s=Array;n({target:"Array",stat:!0,forced:a(function(){function e(){}return!(s.of.call(e)instanceof e)})},{of:function(){for(var e=0,t=arguments.length,i=new(o(this)?this:s)(t);t>e;)r(i,e,arguments[e++]);return i.length=t,i}})},80445:function(e,t,i){"use strict";var n=i(21911),a=i(76998),o=i(6171),r=i(66894),s=i(19580);n({target:"Array",proto:!0,arity:1,forced:i(87584)(function(){return 0x100000001!==[].push.call({length:0x100000000},1)})||!function(){try{Object.defineProperty([],"length",{writable:!1}).push()}catch(e){return e instanceof TypeError}}()},{push:function(e){var t=a(this),i=o(t),n=arguments.length;s(i+n);for(var l=0;l79&&r<83||!o("reduceRight")},{reduceRight:function(e){return a(this,e,arguments.length,arguments.length>1?arguments[1]:void 0)}})},3895:function(e,t,i){"use strict";var n=i(21911),a=i(7751).left,o=i(45395),r=i(17258);n({target:"Array",proto:!0,forced:!i(46318)&&r>79&&r<83||!o("reduce")},{reduce:function(e){var t=arguments.length;return a(this,e,t,t>1?arguments[1]:void 0)}})},77387:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(95493),r=a([].reverse),s=[1,2];n({target:"Array",proto:!0,forced:String(s)===String(s.reverse())},{reverse:function(){return o(this)&&(this.length=this.length),r(this)}})},10991:function(e,t,i){"use strict";var n=i(21911),a=i(95493),o=i(3776),r=i(90897),s=i(68757),l=i(6171),u=i(770),d=i(44083),c=i(5012),m=i(97068),p=i(89887),f=m("slice"),g=c("species"),h=Array,b=Math.max;n({target:"Array",proto:!0,forced:!f},{slice:function(e,t){var i,n,c,m=u(this),f=l(m),k=s(e,f),v=s(void 0===t?f:t,f);if(a(m)&&(o(i=m.constructor)&&(i===h||a(i.prototype))?i=void 0:r(i)&&null===(i=i[g])&&(i=void 0),i===h||void 0===i))return p(m,k,v);for(c=0,n=new(void 0===i?h:i)(b(v-k,0));k1?arguments[1]:void 0)}})},96181:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(11459),r=i(76998),s=i(6171),l=i(24339),u=i(39940),d=i(87584),c=i(54917),m=i(45395),p=i(70724),f=i(24388),g=i(17258),h=i(81974),b=[],k=a(b.sort),v=a(b.push),y=d(function(){b.sort(void 0)}),w=d(function(){b.sort(null)}),_=m("sort"),S=!d(function(){if(g)return g<70;if(!p||!(p>3)){if(f)return!0;if(h)return h<603;var e,t,i,n,a="";for(e=65;e<76;e++){switch(t=String.fromCharCode(e),e){case 66:case 69:case 70:case 72:i=3;break;case 68:case 71:i=4;break;default:i=2}for(n=0;n<47;n++)b.push({k:t+n,v:i})}for(b.sort(function(e,t){return t.v-e.v}),n=0;nu(i)?1:-1}),t=s(a),i=0;iy-n+i;h--)m(v,h-1)}else if(i>n)for(h=y-n;h>w;h--)b=h+n-1,k=h+i-1,b in v?v[k]=v[b]:m(v,k);for(h=0;h>>15,i=e>>>10&31,n=1023&e;return 31===i?0===n?0===t?1/0:-1/0:NaN:0===i?n*(0===t?r:-r):o(2,i-15)*(0===t?1+9765625e-10*n:-1-9765625e-10*n)},l=a(DataView.prototype.getUint16);n({target:"DataView",proto:!0},{getFloat16:function(e){var t=l(this,e,arguments.length>1&&arguments[1]);return s(t)}})},30096:function(e,t,i){"use strict";i(93342)},93494:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(88281),r=i(81973),s=i(4236),l=i(84393),u=Math.pow,d=function(e){if(e!=e)return 32256;if(0===e)return(1/e==-1/0)<<15;var t=e<0;if(t&&(e=-e),e>=65520)return t<<15|31744;if(e<61005353927612305e-21)return t<<15|l(0x1000000*e);var i=0|s(e);if(-15===i)return t<<15|1024;var n=l((e*u(2,-i)-1)*1024);return 1024===n?t<<15|i+16<<10:t<<15|i+15<<10|n},c=a(DataView.prototype.setUint16);n({target:"DataView",proto:!0},{setFloat16:function(e,t){return o(this),c(this,r(e),d(+t),arguments.length>2&&arguments[2])}})},36626:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(87584)(function(){return 120!==new Date(16e11).getYear()}),r=a(Date.prototype.getFullYear);n({target:"Date",proto:!0,forced:o},{getYear:function(){return r(this)-1900}})},92390:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=Date,r=a(o.prototype.getTime);n({target:"Date",stat:!0},{now:function(){return r(new o)}})},3646:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(47742),r=Date.prototype,s=a(r.getTime),l=a(r.setFullYear);n({target:"Date",proto:!0},{setYear:function(e){s(this);var t=o(e);return l(this,t>=0&&t<=99?t+1900:t)}})},2296:function(e,t,i){"use strict";i(21911)({target:"Date",proto:!0},{toGMTString:Date.prototype.toUTCString})},1215:function(e,t,i){"use strict";var n=i(21911),a=i(80689);n({target:"Date",proto:!0,forced:Date.prototype.toISOString!==a},{toISOString:a})},20316:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(76998),r=i(32032);n({target:"Date",proto:!0,arity:1,forced:a(function(){return null!==new Date(NaN).toJSON()||1!==Date.prototype.toJSON.call({toISOString:function(){return 1}})})},{toJSON:function(e){var t=o(this),i=r(t,"number");return"number"!=typeof i||isFinite(i)?t.toISOString():null}})},14693:function(e,t,i){"use strict";var n=i(18280),a=i(98243),o=i(92803),r=i(5012)("toPrimitive"),s=Date.prototype;n(s,r)||a(s,r,o)},27195:function(e,t,i){"use strict";var n=i(21287),a=i(98243),o=Date.prototype,r="Invalid Date",s="toString",l=n(o[s]),u=n(o.getTime);String(new Date(NaN))!==r&&a(o,s,function(){var e=u(this);return e==e?l(this):r})},57801:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(76180),r=i(93658),s="WebAssembly",l=a[s],u=7!==Error("e",{cause:7}).cause,d=function(e,t){var i={};i[e]=r(e,t,u),n({global:!0,constructor:!0,arity:1,forced:u},i)},c=function(e,t){if(l&&l[e]){var i={};i[e]=r(s+"."+e,t,u),n({target:s,stat:!0,constructor:!0,arity:1,forced:u},i)}};d("Error",function(e){return function(t){return o(e,this,arguments)}}),d("EvalError",function(e){return function(t){return o(e,this,arguments)}}),d("RangeError",function(e){return function(t){return o(e,this,arguments)}}),d("ReferenceError",function(e){return function(t){return o(e,this,arguments)}}),d("SyntaxError",function(e){return function(t){return o(e,this,arguments)}}),d("TypeError",function(e){return function(t){return o(e,this,arguments)}}),d("URIError",function(e){return function(t){return o(e,this,arguments)}}),c("CompileError",function(e){return function(t){return o(e,this,arguments)}}),c("LinkError",function(e){return function(t){return o(e,this,arguments)}}),c("RuntimeError",function(e){return function(t){return o(e,this,arguments)}})},47103:function(e,t,i){"use strict";var n=i(98243),a=i(16099),o=Error.prototype;o.toString!==a&&n(o,"toString",a)},33587:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(39940),r=a("".charAt),s=a("".charCodeAt),l=a(/./.exec),u=a(1..toString),d=a("".toUpperCase),c=/[\w*+\-./@]/,m=function(e,t){for(var i=u(e,16);i.length94906265.62425156?r(t)+l:a(t-1+s(t-1)*s(t+1))}})},79849:function(e,t,i){"use strict";var n=i(21911),a=Math.asinh,o=Math.log,r=Math.sqrt;n({target:"Math",stat:!0,forced:!(a&&1/a(0)>0)},{asinh:function e(t){var i=+t;return isFinite(i)&&0!==i?i<0?-e(-i):o(i+r(i*i+1)):i}})},15602:function(e,t,i){"use strict";var n=i(21911),a=Math.atanh,o=Math.log;n({target:"Math",stat:!0,forced:!(a&&1/a(-0)<0)},{atanh:function(e){var t=+e;return 0===t?t:o((1+t)/(1-t))/2}})},64029:function(e,t,i){"use strict";var n=i(21911),a=i(83181),o=Math.abs,r=Math.pow;n({target:"Math",stat:!0},{cbrt:function(e){var t=+e;return a(t)*r(o(t),1/3)}})},26422:function(e,t,i){"use strict";var n=i(21911),a=Math.floor,o=Math.log,r=Math.LOG2E;n({target:"Math",stat:!0},{clz32:function(e){var t=e>>>0;return t?31-a(o(t+.5)*r):32}})},40127:function(e,t,i){"use strict";var n=i(21911),a=i(71),o=Math.cosh,r=Math.abs,s=Math.E;n({target:"Math",stat:!0,forced:!o||o(710)===1/0},{cosh:function(e){var t=a(r(e)-1)+1;return s/2*(t+1/(t*s*s))}})},81097:function(e,t,i){"use strict";var n=i(21911),a=i(71);n({target:"Math",stat:!0,forced:a!==Math.expm1},{expm1:a})},54009:function(e,t,i){"use strict";var n=i(21911),a=i(55493);n({target:"Math",stat:!0},{f16round:function(e){return a(e,9765625e-10,65504,6103515625e-14)}})},49264:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{fround:i(54354)})},62114:function(e,t,i){"use strict";var n=i(21911),a=Math.hypot,o=Math.abs,r=Math.sqrt;n({target:"Math",stat:!0,arity:2,forced:!!a&&a(1/0,NaN)!==1/0},{hypot:function(e,t){for(var i,n,a=0,s=0,l=arguments.length,u=0;s0?a+=(n=i/u)*n:a+=i;return u===1/0?1/0:u*r(a)}})},24929:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=Math.imul;n({target:"Math",stat:!0,forced:a(function(){return -5!==o(0xffffffff,5)||2!==o.length})},{imul:function(e,t){var i=+e,n=+t,a=65535&i,o=65535&n;return 0|a*o+((65535&i>>>16)*o+a*(65535&n>>>16)<<16>>>0)}})},80123:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{log10:i(91577)})},64251:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{log1p:i(10329)})},97646:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{log2:i(4236)})},35687:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{sign:i(83181)})},16344:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(71),r=Math.abs,s=Math.exp,l=Math.E;n({target:"Math",stat:!0,forced:a(function(){return -2e-17!==Math.sinh(-2e-17)})},{sinh:function(e){var t=+e;return 1>r(t)?(o(t)-o(-t))/2:(s(t-1)-s(-t-1))*(l/2)}})},5659:function(e,t,i){"use strict";var n=i(21911),a=i(71),o=Math.exp;n({target:"Math",stat:!0},{tanh:function(e){var t=+e,i=a(t),n=a(-t);return i===1/0?1:n===1/0?-1:(i-n)/(o(t)+o(-t))}})},58744:function(e,t,i){"use strict";i(30380)(Math,"Math",!0)},54082:function(e,t,i){"use strict";i(21911)({target:"Math",stat:!0},{trunc:i(66244)})},88591:function(e,t,i){"use strict";var n=i(21911),a=i(55564),o=i(95851),r=i(78307),s=i(20386),l=i(21287),u=i(7539),d=i(18280),c=i(58728),m=i(29020),p=i(47102),f=i(32032),g=i(87584),h=i(84519).f,b=i(18994).f,k=i(45392).f,v=i(12539),y=i(92269).trim,w="Number",_=r[w],S=s[w],M=_.prototype,z=r.TypeError,j=l("".slice),P=l("".charCodeAt),A=function(e){var t=f(e,"number");return"bigint"==typeof t?t:R(t)},R=function(e){var t,i,n,a,o,r,s,l,u=f(e,"number");if(p(u))throw new z("Cannot convert a Symbol value to a number");if("string"==typeof u&&u.length>2){if(43===(t=P(u=y(u),0))||45===t){if(88===(i=P(u,2))||120===i)return NaN}else if(48===t){switch(P(u,1)){case 66:case 98:n=2,a=49;break;case 79:case 111:n=8,a=55;break;default:return+u}for(s=0,r=(o=j(u,2)).length;sa)return NaN;return parseInt(o,n)}}return+u},T=u(w,!_(" 0o1")||!_("0b1")||_("+0x1")),C=function(e){var t,i=arguments.length<1?0:_(A(e));return(t=this,m(M,t)&&g(function(){v(t)}))?c(Object(i),this,C):i};C.prototype=M,T&&!a&&(M.constructor=C),n({global:!0,constructor:!0,wrap:!0,forced:T},{Number:C});var E=function(e,t){for(var i,n=o?h(t):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,fromString,range".split(","),a=0;n.length>a;a++)d(t,i=n[a])&&!d(e,i)&&k(e,i,b(t,i))};a&&S&&E(s[w],S),(T||a)&&E(s[w],_)},44113:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{EPSILON:2220446049250313e-31})},47427:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0},{isFinite:i(50705)})},41056:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0},{isInteger:i(98542)})},36987:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0},{isNaN:function(e){return e!=e}})},39357:function(e,t,i){"use strict";var n=i(21911),a=i(98542),o=Math.abs;n({target:"Number",stat:!0},{isSafeInteger:function(e){return a(e)&&0x1fffffffffffff>=o(e)}})},66268:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MAX_SAFE_INTEGER:0x1fffffffffffff})},11766:function(e,t,i){"use strict";i(21911)({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MIN_SAFE_INTEGER:-0x1fffffffffffff})},40615:function(e,t,i){"use strict";var n=i(21911),a=i(77761);n({target:"Number",stat:!0,forced:Number.parseFloat!==a},{parseFloat:a})},18904:function(e,t,i){"use strict";var n=i(21911),a=i(31566);n({target:"Number",stat:!0,forced:Number.parseInt!==a},{parseInt:a})},62044:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(47742),r=i(12539),s=i(21198),l=i(91577),u=i(87584),d=RangeError,c=String,m=isFinite,p=Math.abs,f=Math.floor,g=Math.pow,h=Math.round,b=a(1..toExponential),k=a(s),v=a("".slice),y="-6.9000e-11"===b(-69e-12,4)&&"1.25e+0"===b(1.255,2)&&"1.235e+4"===b(12345,3)&&"3e+1"===b(25,0);n({target:"Number",proto:!0,forced:!y||!(u(function(){b(1,1/0)})&&u(function(){b(1,-1/0)}))||!!u(function(){b(1/0,1/0),b(NaN,1/0)})},{toExponential:function(e){var t,i,n,a,s=r(this);if(void 0===e)return b(s);var u=o(e);if(!m(s))return String(s);if(u<0||u>20)throw new d("Incorrect fraction digits");if(y)return b(s,u);var w="";if(s<0&&(w="-",s=-s),0===s)i=0,t=k("0",u+1);else{var _=g(10,(i=f(l(s)))-u),S=h(s/_);2*s>=(2*S+1)*_&&(S+=1),S>=g(10,u+1)&&(S/=10,i+=1),t=c(S)}return 0!==u&&(t=v(t,0,1)+"."+v(t,1)),0===i?(n="+",a="0"):(n=i>0?"+":"-",a=c(p(i))),w+(t+="e"+n+a)}})},92213:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(47742),r=i(12539),s=i(21198),l=i(87584),u=RangeError,d=String,c=Math.floor,m=a(s),p=a("".slice),f=a(1..toFixed),g=function(e,t,i){return 0===t?i:t%2==1?g(e,t-1,i*e):g(e*e,t/2,i)},h=function(e){for(var t=0,i=e;i>=4096;)t+=12,i/=4096;for(;i>=2;)t+=1,i/=2;return t},b=function(e,t,i){for(var n=-1,a=i;++n<6;)a+=t*e[n],e[n]=a%1e7,a=c(a/1e7)},k=function(e,t){for(var i=6,n=0;--i>=0;)n+=e[i],e[i]=c(n/t),n=n%t*1e7},v=function(e){for(var t=6,i="";--t>=0;)if(""!==i||0===t||0!==e[t]){var n=d(e[t]);i=""===i?n:i+m("0",7-n.length)+n}return i};n({target:"Number",proto:!0,forced:l(function(){return"0.000"!==f(8e-5,3)||"1"!==f(.9,0)||"1.25"!==f(1.255,2)||"1000000000000000128"!==f(0xde0b6b3a7640080,0)})||!l(function(){f({})})},{toFixed:function(e){var t,i,n,a,s=r(this),l=o(e),c=[0,0,0,0,0,0],f="",y="0";if(l<0||l>20)throw new u("Incorrect fraction digits");if(s!=s)return"NaN";if(s<=-1e21||s>=1e21)return d(s);if(s<0&&(f="-",s=-s),s>1e-21){if(i=((t=h(s*g(2,69,1))-69)<0?s*g(2,-t,1):s/g(2,t,1))*0x10000000000000,(t=52-t)>0){for(b(c,0,i),n=l;n>=7;)b(c,1e7,0),n-=7;for(b(c,g(10,n,1),0),n=t-1;n>=23;)k(c,8388608),n-=23;k(c,1<0?f+((a=y.length)<=l?"0."+m("0",l-a)+y:p(y,0,a-l)+"."+p(y,a-l)):f+y}})},40619:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(87584),r=i(12539),s=a(1..toPrecision);n({target:"Number",proto:!0,forced:o(function(){return"1"!==s(1,void 0)})||!o(function(){s({})})},{toPrecision:function(e){return void 0===e?s(r(this)):s(r(this),e)}})},25152:function(e,t,i){"use strict";var n=i(21911),a=i(11622);n({target:"Object",stat:!0,arity:2,forced:Object.assign!==a},{assign:a})},22137:function(e,t,i){"use strict";i(21911)({target:"Object",stat:!0,sham:!i(95851)},{create:i(1127)})},6892:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(30636),r=i(11459),s=i(76998),l=i(45392);a&&n({target:"Object",proto:!0,forced:o},{__defineGetter__:function(e,t){l.f(s(this),e,{get:r(t),enumerable:!0,configurable:!0})}})},32782:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(3144).f;n({target:"Object",stat:!0,forced:Object.defineProperties!==o,sham:!a},{defineProperties:o})},40322:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(45392).f;n({target:"Object",stat:!0,forced:Object.defineProperty!==o,sham:!a},{defineProperty:o})},87144:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(30636),r=i(11459),s=i(76998),l=i(45392);a&&n({target:"Object",proto:!0,forced:o},{__defineSetter__:function(e,t){l.f(s(this),e,{set:r(t),enumerable:!0,configurable:!0})}})},70325:function(e,t,i){"use strict";var n=i(21911),a=i(36246).entries;n({target:"Object",stat:!0},{entries:function(e){return a(e)}})},21330:function(e,t,i){"use strict";var n=i(21911),a=i(59397),o=i(87584),r=i(90897),s=i(40104).onFreeze,l=Object.freeze;n({target:"Object",stat:!0,forced:o(function(){l(1)}),sham:!a},{freeze:function(e){return l&&r(e)?l(s(e)):e}})},61780:function(e,t,i){"use strict";var n=i(21911),a=i(48747),o=i(44083);n({target:"Object",stat:!0},{fromEntries:function(e){var t={};return a(e,function(e,i){o(t,e,i)},{AS_ENTRIES:!0}),t}})},79112:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(770),r=i(18994).f,s=i(95851);n({target:"Object",stat:!0,forced:!s||a(function(){r(1)}),sham:!s},{getOwnPropertyDescriptor:function(e,t){return r(o(e),t)}})},54615:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(50758),r=i(770),s=i(18994),l=i(44083);n({target:"Object",stat:!0,sham:!a},{getOwnPropertyDescriptors:function(e){for(var t,i,n=r(e),a=s.f,u=o(n),d={},c=0;u.length>c;)void 0!==(i=a(n,t=u[c++]))&&l(d,t,i);return d}})},65133:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(56355).f;n({target:"Object",stat:!0,forced:a(function(){return!Object.getOwnPropertyNames(1)})},{getOwnPropertyNames:o})},14812:function(e,t,i){"use strict";var n=i(21911),a=i(45154),o=i(87584),r=i(42750),s=i(76998);n({target:"Object",stat:!0,forced:!a||o(function(){r.f(1)})},{getOwnPropertySymbols:function(e){var t=r.f;return t?t(s(e)):[]}})},25594:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(76998),r=i(78792),s=i(97722);n({target:"Object",stat:!0,forced:a(function(){r(1)}),sham:!s},{getPrototypeOf:function(e){return r(o(e))}})},44662:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(21287),r=i(11459),s=i(59899),l=i(38042),u=i(48747),d=i(87584),c=Object.groupBy,m=a("Object","create"),p=o([].push);n({target:"Object",stat:!0,forced:!c||d(function(){return 1!==c("ab",function(e){return e}).a.length})},{groupBy:function(e,t){s(e),r(t);var i=m(null),n=0;return u(e,function(e){var a=l(t(e,n++));a in i?p(i[a],e):i[a]=[e]}),i}})},12628:function(e,t,i){"use strict";i(21911)({target:"Object",stat:!0},{hasOwn:i(18280)})},69383:function(e,t,i){"use strict";var n=i(21911),a=i(19457);n({target:"Object",stat:!0,forced:Object.isExtensible!==a},{isExtensible:a})},50028:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(90897),r=i(64955),s=i(88683),l=Object.isFrozen;n({target:"Object",stat:!0,forced:s||a(function(){l(1)})},{isFrozen:function(e){return!o(e)||!!s&&"ArrayBuffer"===r(e)||!!l&&l(e)}})},41678:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(90897),r=i(64955),s=i(88683),l=Object.isSealed;n({target:"Object",stat:!0,forced:s||a(function(){l(1)})},{isSealed:function(e){return!o(e)||!!s&&"ArrayBuffer"===r(e)||!!l&&l(e)}})},47409:function(e,t,i){"use strict";i(21911)({target:"Object",stat:!0},{is:i(16455)})},64673:function(e,t,i){"use strict";var n=i(21911),a=i(76998),o=i(22695);n({target:"Object",stat:!0,forced:i(87584)(function(){o(1)})},{keys:function(e){return o(a(e))}})},44535:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(30636),r=i(76998),s=i(38042),l=i(78792),u=i(18994).f;a&&n({target:"Object",proto:!0,forced:o},{__lookupGetter__:function(e){var t,i=r(this),n=s(e);do if(t=u(i,n))return t.get;while(i=l(i))}})},50131:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(30636),r=i(76998),s=i(38042),l=i(78792),u=i(18994).f;a&&n({target:"Object",proto:!0,forced:o},{__lookupSetter__:function(e){var t,i=r(this),n=s(e);do if(t=u(i,n))return t.set;while(i=l(i))}})},14478:function(e,t,i){"use strict";var n=i(21911),a=i(90897),o=i(40104).onFreeze,r=i(59397),s=i(87584),l=Object.preventExtensions;n({target:"Object",stat:!0,forced:s(function(){l(1)}),sham:!r},{preventExtensions:function(e){return l&&a(e)?l(o(e)):e}})},53799:function(e,t,i){"use strict";var n=i(95851),a=i(25039),o=i(90897),r=i(56662),s=i(76998),l=i(59899),u=Object.getPrototypeOf,d=Object.setPrototypeOf,c=Object.prototype,m="__proto__";if(n&&u&&d&&!(m in c))try{a(c,m,{configurable:!0,get:function(){return u(s(this))},set:function(e){var t=l(this);r(e)&&o(t)&&d(t,e)}})}catch(e){}},64332:function(e,t,i){"use strict";var n=i(21911),a=i(90897),o=i(40104).onFreeze,r=i(59397),s=i(87584),l=Object.seal;n({target:"Object",stat:!0,forced:s(function(){l(1)}),sham:!r},{seal:function(e){return l&&a(e)?l(o(e)):e}})},23086:function(e,t,i){"use strict";i(21911)({target:"Object",stat:!0},{setPrototypeOf:i(27572)})},77908:function(e,t,i){"use strict";var n=i(7083),a=i(98243),o=i(58794);n||a(Object.prototype,"toString",o,{unsafe:!0})},27879:function(e,t,i){"use strict";var n=i(21911),a=i(36246).values;n({target:"Object",stat:!0},{values:function(e){return a(e)}})},69650:function(e,t,i){"use strict";var n=i(21911),a=i(77761);n({global:!0,forced:parseFloat!==a},{parseFloat:a})},64565:function(e,t,i){"use strict";var n=i(21911),a=i(31566);n({global:!0,forced:parseInt!==a},{parseInt:a})},3798:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(11459),r=i(3130),s=i(95400),l=i(48747);n({target:"Promise",stat:!0,forced:i(75310)},{allSettled:function(e){var t=this,i=r.f(t),n=i.resolve,u=i.reject,d=s(function(){var i=o(t.resolve),r=[],s=0,u=1;l(e,function(e){var o=s++,l=!1;u++,a(i,t,e).then(function(e){!l&&(l=!0,r[o]={status:"fulfilled",value:e},--u||n(r))},function(e){!l&&(l=!0,r[o]={status:"rejected",reason:e},--u||n(r))})}),--u||n(r)});return d.error&&u(d.value),i.promise}})},13706:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(11459),r=i(3130),s=i(95400),l=i(48747);n({target:"Promise",stat:!0,forced:i(75310)},{all:function(e){var t=this,i=r.f(t),n=i.resolve,u=i.reject,d=s(function(){var i=o(t.resolve),r=[],s=0,d=1;l(e,function(e){var o=s++,l=!1;d++,a(i,t,e).then(function(e){!l&&(l=!0,r[o]=e,--d||n(r))},u)}),--d||n(r)});return d.error&&u(d.value),i.promise}})},8971:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(11459),r=i(30290),s=i(3130),l=i(95400),u=i(48747),d=i(75310),c="No one promise resolved";n({target:"Promise",stat:!0,forced:d},{any:function(e){var t=this,i=r("AggregateError"),n=s.f(t),d=n.resolve,m=n.reject,p=l(function(){var n=o(t.resolve),r=[],s=0,l=1,p=!1;u(e,function(e){var o=s++,u=!1;l++,a(n,t,e).then(function(e){u||p||(p=!0,d(e))},function(e){!u&&!p&&(u=!0,r[o]=e,--l||m(new i(r,c)))})}),--l||m(new i(r,c))});return p.error&&m(p.value),n.promise}})},32646:function(e,t,i){"use strict";var n=i(21911),a=i(55564),o=i(66611).CONSTRUCTOR,r=i(34011),s=i(30290),l=i(26838),u=i(98243),d=r&&r.prototype;if(n({target:"Promise",proto:!0,forced:o,real:!0},{catch:function(e){return this.then(void 0,e)}}),!a&&l(r)){var c=s("Promise").prototype.catch;d.catch!==c&&u(d,"catch",c,{unsafe:!0})}},67589:function(e,t,i){"use strict";var n,a,o,r,s=i(21911),l=i(55564),u=i(46318),d=i(78307),c=i(79830),m=i(98243),p=i(27572),f=i(30380),g=i(9050),h=i(11459),b=i(26838),k=i(90897),v=i(72720),y=i(33326),w=i(28004).set,_=i(89632),S=i(21236),M=i(95400),z=i(74478),j=i(60472),P=i(34011),A=i(66611),R=i(3130),T="Promise",C=A.CONSTRUCTOR,E=A.REJECTION_EVENT,I=A.SUBCLASSING,x=j.getterFor(T),D=j.set,O=P&&P.prototype,L=P,V=O,N=d.TypeError,U=d.document,F=d.process,B=R.f,H=B,K=!!(U&&U.createEvent&&d.dispatchEvent),q="unhandledrejection",$=function(e){var t;return!!(k(e)&&b(t=e.then))&&t},W=function(e,t){var i,n,a,o=t.value,r=1===t.state,s=r?e.ok:e.fail,l=e.resolve,u=e.reject,d=e.domain;try{s?(r||(2===t.rejection&&J(t),t.rejection=1),!0===s?i=o:(d&&d.enter(),i=s(o),d&&(d.exit(),a=!0)),i===e.promise?u(new N("Promise-chain cycle")):(n=$(i))?c(n,i,l,u):l(i)):u(o)}catch(e){d&&!a&&d.exit(),u(e)}},G=function(e,t){e.notified||(e.notified=!0,_(function(){for(var i,n=e.reactions;i=n.get();)W(i,e);e.notified=!1,t&&!e.rejection&&Q(e)}))},Y=function(e,t,i){var n,a;K?((n=U.createEvent("Event")).promise=t,n.reason=i,n.initEvent(e,!1,!0),d.dispatchEvent(n)):n={promise:t,reason:i},!E&&(a=d["on"+e])?a(n):e===q&&S("Unhandled promise rejection",i)},Q=function(e){c(w,d,function(){var t,i=e.facade,n=e.value;if(Z(e)&&(t=M(function(){u?F.emit("unhandledRejection",n,i):Y(q,i,n)}),e.rejection=u||Z(e)?2:1,t.error))throw t.value})},Z=function(e){return 1!==e.rejection&&!e.parent},J=function(e){c(w,d,function(){var t=e.facade;u?F.emit("rejectionHandled",t):Y("rejectionhandled",t,e.value)})},X=function(e,t,i){return function(n){e(t,n,i)}},ee=function(e,t,i){e.done||(e.done=!0,i&&(e=i),e.value=t,e.state=2,G(e,!0))},et=function(e,t,i){if(!e.done){e.done=!0,i&&(e=i);try{if(e.facade===t)throw new N("Promise can't be resolved itself");var n=$(t);n?_(function(){var i={done:!1};try{c(n,t,X(et,i,e),X(ee,i,e))}catch(t){ee(i,t,e)}}):(e.value=t,e.state=1,G(e,!1))}catch(t){ee({done:!1},t,e)}}};if(C&&(V=(L=function(e){v(this,V),h(e),c(n,this);var t=x(this);try{e(X(et,t),X(ee,t))}catch(e){ee(t,e)}}).prototype,(n=function(e){D(this,{type:T,done:!1,notified:!1,parent:!1,reactions:new z,rejection:!1,state:0,value:null})}).prototype=m(V,"then",function(e,t){var i=x(this),n=B(y(this,L));return i.parent=!0,n.ok=!b(e)||e,n.fail=b(t)&&t,n.domain=u?F.domain:void 0,0===i.state?i.reactions.add(n):_(function(){W(n,i)}),n.promise}),a=function(){var e=new n,t=x(e);this.promise=e,this.resolve=X(et,t),this.reject=X(ee,t)},R.f=B=function(e){return e===L||e===o?new a(e):H(e)},!l&&b(P)&&O!==Object.prototype)){r=O.then,I||m(O,"then",function(e,t){var i=this;return new L(function(e,t){c(r,i,e,t)}).then(e,t)},{unsafe:!0});try{delete O.constructor}catch(e){}p&&p(O,V)}s({global:!0,constructor:!0,wrap:!0,forced:C},{Promise:L}),f(L,T,!1,!0),g(T)},55574:function(e,t,i){"use strict";var n=i(21911),a=i(55564),o=i(34011),r=i(87584),s=i(30290),l=i(26838),u=i(33326),d=i(88557),c=i(98243),m=o&&o.prototype;if(n({target:"Promise",proto:!0,real:!0,forced:!!o&&r(function(){m.finally.call({then:function(){}},function(){})})},{finally:function(e){var t=u(this,s("Promise")),i=l(e);return this.then(i?function(i){return d(t,e()).then(function(){return i})}:e,i?function(i){return d(t,e()).then(function(){throw i})}:e)}}),!a&&l(o)){var p=s("Promise").prototype.finally;m.finally!==p&&c(m,"finally",p,{unsafe:!0})}},47879:function(e,t,i){"use strict";i(67589),i(13706),i(32646),i(23572),i(88666),i(17829)},23572:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(11459),r=i(3130),s=i(95400),l=i(48747);n({target:"Promise",stat:!0,forced:i(75310)},{race:function(e){var t=this,i=r.f(t),n=i.reject,u=s(function(){var r=o(t.resolve);l(e,function(e){a(r,t,e).then(i.resolve,n)})});return u.error&&n(u.value),i.promise}})},88666:function(e,t,i){"use strict";var n=i(21911),a=i(3130);n({target:"Promise",stat:!0,forced:i(66611).CONSTRUCTOR},{reject:function(e){var t=a.f(this);return(0,t.reject)(e),t.promise}})},17829:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(55564),r=i(34011),s=i(66611).CONSTRUCTOR,l=i(88557),u=a("Promise"),d=o&&!s;n({target:"Promise",stat:!0,forced:o||s},{resolve:function(e){return l(d&&this===u?r:this,e)}})},80832:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(76180),r=i(89887),s=i(3130),l=i(11459),u=i(95400),d=a.Promise,c=!1;n({target:"Promise",stat:!0,forced:!d||!d.try||u(function(){d.try(function(e){c=8===e},8)}).error||!c},{try:function(e){var t=arguments.length>1?r(arguments,1):[],i=s.f(this),n=u(function(){return o(l(e),void 0,t)});return(n.error?i.reject:i.resolve)(n.value),i.promise}})},9643:function(e,t,i){"use strict";var n=i(21911),a=i(3130);n({target:"Promise",stat:!0},{withResolvers:function(){var e=a.f(this);return{promise:e.promise,resolve:e.resolve,reject:e.reject}}})},78797:function(e,t,i){"use strict";var n=i(21911),a=i(76180),o=i(11459),r=i(78700);n({target:"Reflect",stat:!0,forced:!i(87584)(function(){Reflect.apply(function(){})})},{apply:function(e,t,i){return a(o(e),t,r(i))}})},12832:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(76180),r=i(37965),s=i(79079),l=i(78700),u=i(90897),d=i(1127),c=i(87584),m=a("Reflect","construct"),p=Object.prototype,f=[].push,g=c(function(){function e(){}return!(m(function(){},[],e)instanceof e)}),h=!c(function(){m(function(){})}),b=g||h;n({target:"Reflect",stat:!0,forced:b,sham:b},{construct:function(e,t){s(e),l(t);var i=arguments.length<3?e:s(arguments[2]);if(h&&!g)return m(e,t,i);if(e===i){switch(t.length){case 0:return new e;case 1:return new e(t[0]);case 2:return new e(t[0],t[1]);case 3:return new e(t[0],t[1],t[2]);case 4:return new e(t[0],t[1],t[2],t[3])}var n=[null];return o(f,n,t),new(o(r,e,n))}var a=i.prototype,c=d(u(a)?a:p),b=o(e,c,t);return u(b)?b:c}})},47554:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(78700),r=i(38042),s=i(45392);n({target:"Reflect",stat:!0,forced:i(87584)(function(){Reflect.defineProperty(s.f({},1,{value:1}),1,{value:2})}),sham:!a},{defineProperty:function(e,t,i){o(e);var n=r(t);o(i);try{return s.f(e,n,i),!0}catch(e){return!1}}})},68922:function(e,t,i){"use strict";var n=i(21911),a=i(78700),o=i(18994).f;n({target:"Reflect",stat:!0},{deleteProperty:function(e,t){var i=o(a(e),t);return(!i||!!i.configurable)&&delete e[t]}})},33288:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(78700),r=i(18994);n({target:"Reflect",stat:!0,sham:!a},{getOwnPropertyDescriptor:function(e,t){return r.f(o(e),t)}})},69338:function(e,t,i){"use strict";var n=i(21911),a=i(78700),o=i(78792);n({target:"Reflect",stat:!0,sham:!i(97722)},{getPrototypeOf:function(e){return o(a(e))}})},72649:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(90897),r=i(78700),s=i(23206),l=i(18994),u=i(78792);n({target:"Reflect",stat:!0},{get:function e(t,i){var n,d,c=arguments.length<3?t:arguments[2];return r(t)===c?t[i]:(n=l.f(t,i))?s(n)?n.value:void 0===n.get?void 0:a(n.get,c):o(d=u(t))?e(d,i,c):void 0}})},1669:function(e,t,i){"use strict";i(21911)({target:"Reflect",stat:!0},{has:function(e,t){return t in e}})},43719:function(e,t,i){"use strict";var n=i(21911),a=i(78700),o=i(19457);n({target:"Reflect",stat:!0},{isExtensible:function(e){return a(e),o(e)}})},78518:function(e,t,i){"use strict";i(21911)({target:"Reflect",stat:!0},{ownKeys:i(50758)})},65966:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(78700);n({target:"Reflect",stat:!0,sham:!i(59397)},{preventExtensions:function(e){o(e);try{var t=a("Object","preventExtensions");return t&&t(e),!0}catch(e){return!1}}})},82446:function(e,t,i){"use strict";var n=i(21911),a=i(78700),o=i(70615),r=i(27572);r&&n({target:"Reflect",stat:!0},{setPrototypeOf:function(e,t){a(e),o(t);try{return r(e,t),!0}catch(e){return!1}}})},9165:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(78700),r=i(90897),s=i(23206),l=i(87584),u=i(45392),d=i(18994),c=i(78792),m=i(7221);n({target:"Reflect",stat:!0,forced:l(function(){var e=function(){},t=u.f(new e,"a",{configurable:!0});return!1!==Reflect.set(e.prototype,"a",1,t)})},{set:function e(t,i,n){var l,p,f,g=arguments.length<4?t:arguments[3],h=d.f(o(t),i);if(!h){if(r(p=c(t)))return e(p,i,n,g);h=m(0)}if(s(h)){if(!1===h.writable||!r(g))return!1;if(l=d.f(g,i)){if(l.get||l.set||!1===l.writable)return!1;l.value=n,u.f(g,i,l)}else u.f(g,i,m(0,n))}else{if(void 0===(f=h.set))return!1;a(f,g,n)}return!0}})},27377:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(30380);n({global:!0},{Reflect:{}}),o(a.Reflect,"Reflect",!0)},35467:function(e,t,i){"use strict";var n=i(95851),a=i(78307),o=i(21287),r=i(7539),s=i(58728),l=i(45790),u=i(1127),d=i(84519).f,c=i(29020),m=i(65867),p=i(39940),f=i(8219),g=i(6914),h=i(71097),b=i(98243),k=i(87584),v=i(18280),y=i(60472).enforce,w=i(9050),_=i(5012),S=i(48834),M=i(85055),z=_("match"),j=a.RegExp,P=j.prototype,A=a.SyntaxError,R=o(P.exec),T=o("".charAt),C=o("".replace),E=o("".indexOf),I=o("".slice),x=/^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/,D=/a/g,O=/a/g,L=new j(D)!==D,V=g.MISSED_STICKY,N=g.UNSUPPORTED_Y,U=n&&(!L||V||S||M||k(function(){return O[z]=!1,j(D)!==D||j(O)===O||"/a/i"!==String(j(D,"i"))})),F=function(e){for(var t,i=e.length,n=0,a="",o=!1;n<=i;n++){if("\\"===(t=T(e,n))){a+=t+T(e,++n);continue}o||"."!==t?("["===t?o=!0:"]"===t&&(o=!1),a+=t):a+="[\\s\\S]"}return a},B=function(e){for(var t,i=e.length,n=0,a="",o=[],r=u(null),s=!1,l=!1,d=0,c="";n<=i;n++){if("\\"===(t=T(e,n)))t+=T(e,++n);else if("]"===t)s=!1;else if(!s)switch(!0){case"["===t:s=!0;break;case"("===t:if(a+=t,"?:"===I(e,n+1,n+3))continue;R(x,I(e,n+1))&&(n+=2,l=!0),d++;continue;case">"===t&&l:if(""===c||v(r,c))throw new A("Invalid capture group name");r[c]=!0,o[o.length]=[c,d],l=!1,c="";continue}l?c+=t:a+=t}return[a,o]};if(r("RegExp",U)){for(var H=function(e,t){var i,n,a,o,r,u,d=c(P,this),g=m(e),h=void 0===t,b=[],k=e;if(!d&&g&&h&&e.constructor===H)return e;if((g||c(P,e))&&(e=e.source,h&&(t=f(k))),e=void 0===e?"":p(e),t=void 0===t?"":p(t),k=e,S&&"dotAll"in D&&(n=!!t&&E(t,"s")>-1)&&(t=C(t,/s/g,"")),i=t,V&&"sticky"in D&&(a=!!t&&E(t,"y")>-1)&&N&&(t=C(t,/y/g,"")),M&&(e=(o=B(e))[0],b=o[1]),r=s(j(e,t),d?this:P,H),(n||a||b.length)&&(u=y(r),n&&(u.dotAll=!0,u.raw=H(F(e),i)),a&&(u.sticky=!0),b.length&&(u.groups=b)),e!==k)try{l(r,"source",""===k?"(?:)":k)}catch(e){}return r},K=d(j),q=0;K.length>q;)h(H,j,K[q++]);P.constructor=H,H.prototype=P,b(a,"RegExp",H,{constructor:!0})}w("RegExp")},46046:function(e,t,i){"use strict";var n=i(95851),a=i(48834),o=i(64955),r=i(25039),s=i(60472).get,l=RegExp.prototype,u=TypeError;n&&a&&r(l,"dotAll",{configurable:!0,get:function(){if(this!==l){if("RegExp"===o(this))return!!s(this).dotAll;throw new u("Incompatible receiver, RegExp required")}}})},47984:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(20078),r=i(18280),s=i(54672).start,l=i(93743),u=Array,d=RegExp.escape,c=a("".charAt),m=a("".charCodeAt),p=a(1.1.toString),f=a([].join),g=/^[0-9a-z]/i,h=/^[$()*+./?[\\\]^{|}]/,b=RegExp("^[!\"#%&',\\-:;<=>@`~"+l+"]"),k=a(g.exec),v={" ":"t","\n":"n","\v":"v","\f":"f","\r":"r"},y=function(e){var t=p(m(e,0),16);return t.length<3?"\\x"+s(t,2,"0"):"\\u"+s(t,4,"0")};n({target:"RegExp",stat:!0,forced:!d||"\\x61b"!==d("ab")},{escape:function(e){o(e);for(var t=e.length,i=u(t),n=0;n=56320||n+1>=t||(64512&m(e,n+1))!=56320?i[n]=y(a):(i[n]=a,i[++n]=c(e,n))}}return f(i,"")}})},35594:function(e,t,i){"use strict";var n=i(21911),a=i(31960);n({target:"RegExp",proto:!0,forced:/./.exec!==a},{exec:a})},5e4:function(e,t,i){"use strict";var n=i(78307),a=i(95851),o=i(25039),r=i(47706),s=i(87584),l=n.RegExp,u=l.prototype;a&&s(function(){var e=!0;try{l(".","d")}catch(t){e=!1}var t={},i="",n=e?"dgimsy":"gimsy",a=function(e,n){Object.defineProperty(t,e,{get:function(){return i+=n,!0}})},o={dotAll:"s",global:"g",ignoreCase:"i",multiline:"m",sticky:"y"};for(var r in e&&(o.hasIndices="d"),o)a(r,o[r]);return Object.getOwnPropertyDescriptor(u,"flags").get.call(t)!==n||i!==n})&&o(u,"flags",{configurable:!0,get:r})},73712:function(e,t,i){"use strict";var n=i(95851),a=i(6914).MISSED_STICKY,o=i(64955),r=i(25039),s=i(60472).get,l=RegExp.prototype,u=TypeError;n&&a&&r(l,"sticky",{configurable:!0,get:function(){if(this!==l){if("RegExp"===o(this))return!!s(this).sticky;throw new u("Incompatible receiver, RegExp required")}}})},2827:function(e,t,i){"use strict";i(35594);var n,a,o=i(21911),r=i(79830),s=i(26838),l=i(78700),u=i(39940),d=(n=!1,(a=/[ac]/).exec=function(){return n=!0,/./.exec.apply(this,arguments)},!0===a.test("abc")&&n),c=/./.test;o({target:"RegExp",proto:!0,forced:!d},{test:function(e){var t=l(this),i=u(e),n=t.exec;if(!s(n))return r(c,t,i);var a=r(n,t,i);return null!==a&&(l(a),!0)}})},15614:function(e,t,i){"use strict";var n=i(99397).PROPER,a=i(98243),o=i(78700),r=i(39940),s=i(87584),l=i(8219),u="toString",d=RegExp.prototype,c=d[u],m=s(function(){return"/a/b"!==c.call({source:"a",flags:"b"})}),p=n&&c.name!==u;(m||p)&&a(d,u,function(){var e=o(this);return"/"+r(e.source)+"/"+r(l(e))},{unsafe:!0})},80892:function(e,t,i){"use strict";i(44781)("Set",function(e){return function(){return e(this,arguments.length?arguments[0]:void 0)}},i(80157))},37979:function(e,t,i){"use strict";var n=i(21911),a=i(75405);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("difference",function(e){return 0===e.size})},{difference:a})},28565:function(e,t,i){"use strict";var n=i(21911),a=i(87584),o=i(71263);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("intersection",function(e){return 2===e.size&&e.has(1)&&e.has(2)})||a(function(){return"3,2"!==String(Array.from(new Set([1,2,3]).intersection(new Set([3,2]))))})},{intersection:o})},83104:function(e,t,i){"use strict";var n=i(21911),a=i(23011);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("isDisjointFrom",function(e){return!e})},{isDisjointFrom:a})},1941:function(e,t,i){"use strict";var n=i(21911),a=i(80879);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("isSubsetOf",function(e){return e})},{isSubsetOf:a})},60054:function(e,t,i){"use strict";var n=i(21911),a=i(35798);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("isSupersetOf",function(e){return!e})},{isSupersetOf:a})},75514:function(e,t,i){"use strict";i(80892)},41485:function(e,t,i){"use strict";var n=i(21911),a=i(26775);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("symmetricDifference")},{symmetricDifference:a})},83329:function(e,t,i){"use strict";var n=i(21911),a=i(54755);n({target:"Set",proto:!0,real:!0,forced:!i(38281)("union")},{union:a})},97810:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("anchor")},{anchor:function(e){return a(this,"a","name",e)}})},20304:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(59899),r=i(47742),s=i(39940),l=i(87584),u=a("".charAt);n({target:"String",proto:!0,forced:l(function(){return"\uD842"!=="\uD842\uDFB7".at(-2)})},{at:function(e){var t=s(o(this)),i=t.length,n=r(e),a=n>=0?n:i+n;return a<0||a>=i?void 0:u(t,a)}})},4609:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("big")},{big:function(){return a(this,"big","","")}})},28729:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("blink")},{blink:function(){return a(this,"blink","","")}})},41080:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("bold")},{bold:function(){return a(this,"b","","")}})},87939:function(e,t,i){"use strict";var n=i(21911),a=i(9946).codeAt;n({target:"String",proto:!0},{codePointAt:function(e){return a(this,e)}})},32874:function(e,t,i){"use strict";var n,a=i(21911),o=i(98293),r=i(18994).f,s=i(93221),l=i(39940),u=i(74022),d=i(59899),c=i(98811),m=i(55564),p=o("".slice),f=Math.min,g=c("endsWith");a({target:"String",proto:!0,forced:!(!m&&!g&&(n=r(String.prototype,"endsWith"))&&!n.writable)&&!g},{endsWith:function(e){var t=l(d(this));u(e);var i=arguments.length>1?arguments[1]:void 0,n=t.length,a=void 0===i?n:f(s(i),n),o=l(e);return p(t,a-o.length,a)===o}})},90773:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("fixed")},{fixed:function(){return a(this,"tt","","")}})},52999:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("fontcolor")},{fontcolor:function(e){return a(this,"font","color",e)}})},20411:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("fontsize")},{fontsize:function(e){return a(this,"font","size",e)}})},98742:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(68757),r=RangeError,s=String.fromCharCode,l=String.fromCodePoint,u=a([].join);n({target:"String",stat:!0,arity:1,forced:!!l&&1!==l.length},{fromCodePoint:function(e){for(var t,i=[],n=arguments.length,a=0;n>a;){if(t=+arguments[a++],o(t,1114111)!==t)throw new r(t+" is not a valid code point");i[a]=t<65536?s(t):s(((t-=65536)>>10)+55296,t%1024+56320)}return u(i,"")}})},18934:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(74022),r=i(59899),s=i(39940),l=i(98811),u=a("".indexOf);n({target:"String",proto:!0,forced:!l("includes")},{includes:function(e){return!!~u(s(r(this)),s(o(e)),arguments.length>1?arguments[1]:void 0)}})},71074:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(59899),r=i(39940),s=a("".charCodeAt);n({target:"String",proto:!0},{isWellFormed:function(){for(var e=r(o(this)),t=e.length,i=0;i=56320||++i>=t||(64512&s(e,i))!=56320))return!1}return!0}})},1202:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("italics")},{italics:function(){return a(this,"i","","")}})},94005:function(e,t,i){"use strict";var n=i(9946).charAt,a=i(39940),o=i(60472),r=i(41979),s=i(75562),l="String Iterator",u=o.set,d=o.getterFor(l);r(String,"String",function(e){u(this,{type:l,string:a(e),index:0})},function(){var e,t=d(this),i=t.string,a=t.index;return a>=i.length?s(void 0,!0):(e=n(i,a),t.index+=e.length,s(e,!1))})},6919:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("link")},{link:function(e){return a(this,"a","href",e)}})},87684:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(98293),r=i(44137),s=i(75562),l=i(59899),u=i(93221),d=i(39940),c=i(78700),m=i(90897),p=i(64955),f=i(65867),g=i(8219),h=i(95211),b=i(98243),k=i(87584),v=i(5012),y=i(33326),w=i(2132),_=i(35055),S=i(60472),M=i(55564),z=v("matchAll"),j="RegExp String",P=j+" Iterator",A=S.set,R=S.getterFor(P),T=RegExp.prototype,C=TypeError,E=o("".indexOf),I=o("".matchAll),x=!!I&&!k(function(){I("a",/./)}),D=r(function(e,t,i,n){A(this,{type:P,regexp:e,string:t,global:i,unicode:n,done:!1})},j,function(){var e=R(this);if(e.done)return s(void 0,!0);var t=e.regexp,i=e.string,n=_(t,i);return null===n?(e.done=!0,s(void 0,!0)):(e.global?""===d(n[0])&&(t.lastIndex=w(i,u(t.lastIndex),e.unicode)):e.done=!0,s(n,!1))}),O=function(e){var t,i,n,a=c(this),o=d(e),r=y(a,RegExp),s=d(g(a));return t=new r(r===RegExp?a.source:a,s),i=!!~E(s,"g"),n=!!~E(s,"u"),t.lastIndex=u(a.lastIndex),new D(t,o,i,n)};n({target:"String",proto:!0,forced:x},{matchAll:function(e){var t,i,n,o=l(this);if(m(e)){if(f(e)&&!~E(d(l(g(e))),"g"))throw new C("`.matchAll` does not allow non-global regexes");if(x)return I(o,e);if(void 0===(i=h(e,z))&&M&&"RegExp"===p(e)&&(i=O),i)return a(i,e,o)}else if(x)return I(o,e);return t=d(o),n=RegExp(e,"g"),M?a(O,n,t):n[z](t)}}),M||z in T||b(T,z,O)},84778:function(e,t,i){"use strict";var n=i(79830),a=i(74529),o=i(78700),r=i(90897),s=i(93221),l=i(39940),u=i(59899),d=i(95211),c=i(2132),m=i(35055);a("match",function(e,t,i){return[function(t){var i=u(this),a=r(t)?d(t,e):void 0;return a?n(a,t,i):new RegExp(t)[e](l(i))},function(e){var n,a=o(this),r=l(e),u=i(t,a,r);if(u.done)return u.value;if(!a.global)return m(a,r);var d=a.unicode;a.lastIndex=0;for(var p=[],f=0;null!==(n=m(a,r));){var g=l(n[0]);p[f]=g,""===g&&(a.lastIndex=c(r,s(a.lastIndex),d)),f++}return 0===f?null:p}]})},22358:function(e,t,i){"use strict";var n=i(21911),a=i(54672).end;n({target:"String",proto:!0,forced:i(68632)},{padEnd:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}})},49451:function(e,t,i){"use strict";var n=i(21911),a=i(54672).start;n({target:"String",proto:!0,forced:i(68632)},{padStart:function(e){return a(this,e,arguments.length>1?arguments[1]:void 0)}})},84153:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(770),r=i(76998),s=i(39940),l=i(6171),u=a([].push),d=a([].join);n({target:"String",stat:!0},{raw:function(e){var t=o(r(e).raw),i=l(t);if(!i)return"";for(var n=arguments.length,a=[],c=0;;){if(u(a,s(t[c++])),c===i)return d(a,"");co.length?-1:k(o,f,z+M);return A=P&&(j+=z(s,P,x)+E,P=x+I.length)}return j+z(s,P)}]},!!s(function(){var e=/./;return e.exec=function(){var e=[];return e.groups={a:"7"},e},"7"!=="".replace(e,"$")})||!j||P)},24051:function(e,t,i){"use strict";var n=i(79830),a=i(74529),o=i(78700),r=i(90897),s=i(59899),l=i(16455),u=i(39940),d=i(95211),c=i(35055);a("search",function(e,t,i){return[function(t){var i=s(this),a=r(t)?d(t,e):void 0;return a?n(a,t,i):new RegExp(t)[e](u(i))},function(e){var n=o(this),a=u(e),r=i(t,n,a);if(r.done)return r.value;var s=n.lastIndex;l(s,0)||(n.lastIndex=0);var d=c(n,a);return l(n.lastIndex,s)||(n.lastIndex=s),null===d?-1:d.index}]})},69004:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("small")},{small:function(){return a(this,"small","","")}})},53871:function(e,t,i){"use strict";var n=i(79830),a=i(21287),o=i(74529),r=i(78700),s=i(90897),l=i(59899),u=i(33326),d=i(2132),c=i(93221),m=i(39940),p=i(95211),f=i(35055),g=i(6914),h=i(87584),b=g.UNSUPPORTED_Y,k=Math.min,v=a([].push),y=a("".slice),w=!h(function(){var e=/(?:)/,t=e.exec;e.exec=function(){return t.apply(this,arguments)};var i="ab".split(e);return 2!==i.length||"a"!==i[0]||"b"!==i[1]}),_="c"==="abbc".split(/(b)*/)[1]||4!=="test".split(/(?:)/,-1).length||2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length;o("split",function(e,t,i){var a="0".split(void 0,0).length?function(e,i){return void 0===e&&0===i?[]:n(t,this,e,i)}:t;return[function(t,i){var o=l(this),r=s(t)?p(t,e):void 0;return r?n(r,t,o,i):n(a,m(o),t,i)},function(e,n){var o=r(this),s=m(e);if(!_){var l=i(a,o,s,n,a!==t);if(l.done)return l.value}var p=u(o,RegExp),g=o.unicode,h=(o.ignoreCase?"i":"")+(o.multiline?"m":"")+(o.unicode?"u":"")+(b?"g":"y"),w=new p(b?"^(?:"+o.source+")":o,h),S=void 0===n?0xffffffff:n>>>0;if(0===S)return[];if(0===s.length)return null===f(w,s)?[s]:[];for(var M=0,z=0,j=[];z1?arguments[1]:void 0,t.length)),n=l(e);return p(t,i,i+n.length)===n}})},25061:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("strike")},{strike:function(){return a(this,"strike","","")}})},63229:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("sub")},{sub:function(){return a(this,"sub","","")}})},47374:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(59899),r=i(47742),s=i(39940),l=a("".slice),u=Math.max,d=Math.min;n({target:"String",proto:!0,forced:!"".substr||"b"!=="ab".substr(-1)},{substr:function(e,t){var i,n,a=s(o(this)),c=a.length,m=r(e);return(m===1/0&&(m=0),m<0&&(m=u(c+m,0)),(i=void 0===t?c:r(t))<=0||i===1/0)?"":(n=d(m+i,c),m>=n?"":l(a,m,n))}})},85003:function(e,t,i){"use strict";var n=i(21911),a=i(96667);n({target:"String",proto:!0,forced:i(6304)("sup")},{sup:function(){return a(this,"sup","","")}})},73567:function(e,t,i){"use strict";var n=i(21911),a=i(79830),o=i(21287),r=i(59899),s=i(39940),l=i(87584),u=Array,d=o("".charAt),c=o("".charCodeAt),m=o([].join),p="".toWellFormed,f=p&&l(function(){return"1"!==a(p,1)});n({target:"String",proto:!0,forced:f},{toWellFormed:function(){var e=s(r(this));if(f)return a(p,e);for(var t=e.length,i=u(t),n=0;n=56320||n+1>=t||(64512&c(e,n+1))!=56320?i[n]="�":(i[n]=d(e,n),i[++n]=d(e,n))}return m(i,"")}})},6119:function(e,t,i){"use strict";i(35780);var n=i(21911),a=i(17949);n({target:"String",proto:!0,name:"trimEnd",forced:"".trimEnd!==a},{trimEnd:a})},75781:function(e,t,i){"use strict";var n=i(21911),a=i(24852);n({target:"String",proto:!0,name:"trimStart",forced:void 0!==a},{trimLeft:a})},35780:function(e,t,i){"use strict";var n=i(21911),a=i(17949);n({target:"String",proto:!0,name:"trimEnd",forced:void 0!==a},{trimRight:a})},59930:function(e,t,i){"use strict";i(75781);var n=i(21911),a=i(24852);n({target:"String",proto:!0,name:"trimStart",forced:"".trimStart!==a},{trimStart:a})},48363:function(e,t,i){"use strict";var n=i(21911),a=i(92269).trim;n({target:"String",proto:!0,forced:i(36639)("trim")},{trim:function(){return a(this)}})},17697:function(e,t,i){"use strict";i(82658)("asyncIterator")},14566:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(79830),r=i(21287),s=i(55564),l=i(95851),u=i(45154),d=i(87584),c=i(18280),m=i(29020),p=i(78700),f=i(770),g=i(38042),h=i(39940),b=i(7221),k=i(1127),v=i(22695),y=i(84519),w=i(56355),_=i(42750),S=i(18994),M=i(45392),z=i(3144),j=i(41378),P=i(98243),A=i(25039),R=i(5364),T=i(87286),C=i(15526),E=i(61239),I=i(5012),x=i(6140),D=i(82658),O=i(50575),L=i(30380),V=i(60472),N=i(67754).forEach,U=T("hidden"),F="Symbol",B="prototype",H=V.set,K=V.getterFor(F),q=Object[B],$=a.Symbol,W=$&&$[B],G=a.RangeError,Y=a.TypeError,Q=a.QObject,Z=S.f,J=M.f,X=w.f,ee=j.f,et=r([].push),ei=R("symbols"),en=R("op-symbols"),ea=R("wks"),eo=!Q||!Q[B]||!Q[B].findChild,er=function(e,t,i){var n=Z(q,t);n&&delete q[t],J(e,t,i),n&&e!==q&&J(q,t,n)},es=l&&d(function(){return 7!==k(J({},"a",{get:function(){return J(this,"a",{value:7}).a}})).a})?er:J,el=function(e,t){var i=ei[e]=k(W);return H(i,{type:F,tag:e,description:t}),l||(i.description=t),i},eu=function(e,t,i){e===q&&eu(en,t,i),p(e);var n=g(t);return(p(i),c(ei,n))?(i.enumerable?(c(e,U)&&e[U][n]&&(e[U][n]=!1),i=k(i,{enumerable:b(0,!1)})):(c(e,U)||J(e,U,b(1,k(null))),e[U][n]=!0),es(e,n,i)):J(e,n,i)},ed=function(e,t){p(e);var i=f(t);return N(v(i).concat(ef(i)),function(t){(!l||o(ec,i,t))&&eu(e,t,i[t])}),e},ec=function(e){var t=g(e),i=o(ee,this,t);return(!(this===q&&c(ei,t))||!!c(en,t))&&(!(i||!c(this,t)||!c(ei,t)||c(this,U)&&this[U][t])||i)},em=function(e,t){var i=f(e),n=g(t);if(!(i===q&&c(ei,n))||c(en,n)){var a=Z(i,n);return a&&c(ei,n)&&!(c(i,U)&&i[U][n])&&(a.enumerable=!0),a}},ep=function(e){var t=X(f(e)),i=[];return N(t,function(e){c(ei,e)||c(C,e)||et(i,e)}),i},ef=function(e){var t=e===q,i=X(t?en:f(e)),n=[];return N(i,function(e){c(ei,e)&&(!t||c(q,e))&&et(n,ei[e])}),n};u||(P(W=($=function(){if(m(W,this))throw new Y("Symbol is not a constructor");var e=arguments.length&&void 0!==arguments[0]?h(arguments[0]):void 0,t=E(e),i=function(e){var n=void 0===this?a:this;n===q&&o(i,en,e),c(n,U)&&c(n[U],t)&&(n[U][t]=!1);var r=b(1,e);try{es(n,t,r)}catch(e){if(!(e instanceof G))throw e;er(n,t,r)}};return l&&eo&&es(q,t,{configurable:!0,set:i}),el(t,e)})[B],"toString",function(){return K(this).tag}),P($,"withoutSetter",function(e){return el(E(e),e)}),j.f=ec,M.f=eu,z.f=ed,S.f=em,y.f=w.f=ep,_.f=ef,x.f=function(e){return el(I(e),e)},l&&(A(W,"description",{configurable:!0,get:function(){return K(this).description}}),s||P(q,"propertyIsEnumerable",ec,{unsafe:!0}))),n({global:!0,constructor:!0,wrap:!0,forced:!u,sham:!u},{Symbol:$}),N(v(ea),function(e){D(e)}),n({target:F,stat:!0,forced:!u},{useSetter:function(){eo=!0},useSimple:function(){eo=!1}}),n({target:"Object",stat:!0,forced:!u,sham:!l},{create:function(e,t){return void 0===t?k(e):ed(k(e),t)},defineProperty:eu,defineProperties:ed,getOwnPropertyDescriptor:em}),n({target:"Object",stat:!0,forced:!u},{getOwnPropertyNames:ep}),O(),L($,F),C[U]=!0},54224:function(e,t,i){"use strict";var n=i(21911),a=i(95851),o=i(78307),r=i(21287),s=i(18280),l=i(26838),u=i(29020),d=i(39940),c=i(25039),m=i(39207),p=o.Symbol,f=p&&p.prototype;if(a&&l(p)&&(!("description"in f)||void 0!==p().description)){var g={},h=function(){var e=arguments.length<1||void 0===arguments[0]?void 0:d(arguments[0]),t=u(f,this)?new p(e):void 0===e?p():p(e);return""===e&&(g[t]=!0),t};m(h,p),h.prototype=f,f.constructor=h;var b="Symbol(description detection)"===String(p("description detection")),k=r(f.valueOf),v=r(f.toString),y=/^Symbol\((.*)\)[^)]+$/,w=r("".replace),_=r("".slice);c(f,"description",{configurable:!0,get:function(){var e=k(this);if(s(g,e))return"";var t=v(e),i=b?_(t,7,-1):w(t,y,"$1");return""===i?void 0:i}}),n({global:!0,constructor:!0,forced:!0},{Symbol:h})}},21837:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(18280),r=i(39940),s=i(5364),l=i(57927),u=s("string-to-symbol-registry"),d=s("symbol-to-string-registry");n({target:"Symbol",stat:!0,forced:!l},{for:function(e){var t=r(e);if(o(u,t))return u[t];var i=a("Symbol")(t);return u[t]=i,d[i]=t,i}})},32e3:function(e,t,i){"use strict";i(82658)("hasInstance")},85605:function(e,t,i){"use strict";i(82658)("isConcatSpreadable")},26990:function(e,t,i){"use strict";i(82658)("iterator")},27704:function(e,t,i){"use strict";i(14566),i(21837),i(23307),i(44029),i(14812)},23307:function(e,t,i){"use strict";var n=i(21911),a=i(18280),o=i(47102),r=i(31524),s=i(5364),l=i(57927),u=s("symbol-to-string-registry");n({target:"Symbol",stat:!0,forced:!l},{keyFor:function(e){if(!o(e))throw TypeError(r(e)+" is not a symbol");if(a(u,e))return u[e]}})},48805:function(e,t,i){"use strict";i(82658)("matchAll")},32983:function(e,t,i){"use strict";i(82658)("match")},25466:function(e,t,i){"use strict";i(82658)("replace")},67180:function(e,t,i){"use strict";i(82658)("search")},52744:function(e,t,i){"use strict";i(82658)("species")},37294:function(e,t,i){"use strict";i(82658)("split")},18849:function(e,t,i){"use strict";var n=i(82658),a=i(50575);n("toPrimitive"),a()},53438:function(e,t,i){"use strict";var n=i(30290),a=i(82658),o=i(30380);a("toStringTag"),o(n("Symbol"),"Symbol")},75313:function(e,t,i){"use strict";i(82658)("unscopables")},38403:function(e,t,i){"use strict";var n=i(43413),a=i(6171),o=i(47742),r=n.aTypedArray;(0,n.exportTypedArrayMethod)("at",function(e){var t=r(this),i=a(t),n=o(e),s=n>=0?n:i+n;return s<0||s>=i?void 0:t[s]})},11195:function(e,t,i){"use strict";var n=i(21287),a=i(43413),o=n(i(31118)),r=a.aTypedArray;(0,a.exportTypedArrayMethod)("copyWithin",function(e,t){return o(r(this),e,t,arguments.length>2?arguments[2]:void 0)})},61687:function(e,t,i){"use strict";var n=i(43413),a=i(67754).every,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("every",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},2819:function(e,t,i){"use strict";var n=i(43413),a=i(50356),o=i(51855),r=i(81192),s=i(79830),l=i(21287),u=i(87584),d=n.aTypedArray,c=n.exportTypedArrayMethod,m=l("".slice);c("fill",function(e){var t=arguments.length;return d(this),s(a,this,"Big"===m(r(this),0,3)?o(e):+e,t>1?arguments[1]:void 0,t>2?arguments[2]:void 0)},u(function(){var e=0;return new Int8Array(2).fill({valueOf:function(){return e++}}),1!==e}))},57312:function(e,t,i){"use strict";var n=i(43413),a=i(67754).filter,o=i(56827),r=n.aTypedArray;(0,n.exportTypedArrayMethod)("filter",function(e){var t=a(r(this),e,arguments.length>1?arguments[1]:void 0);return o(this,t)})},30652:function(e,t,i){"use strict";var n=i(43413),a=i(67754).findIndex,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("findIndex",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},46563:function(e,t,i){"use strict";var n=i(43413),a=i(26864).findLastIndex,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("findLastIndex",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},93614:function(e,t,i){"use strict";var n=i(43413),a=i(26864).findLast,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("findLast",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},93225:function(e,t,i){"use strict";var n=i(43413),a=i(67754).find,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("find",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},94391:function(e,t,i){"use strict";i(7312)("Float32",function(e){return function(t,i,n){return e(this,t,i,n)}})},88560:function(e,t,i){"use strict";i(7312)("Float64",function(e){return function(t,i,n){return e(this,t,i,n)}})},98053:function(e,t,i){"use strict";var n=i(43413),a=i(67754).forEach,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("forEach",function(e){a(o(this),e,arguments.length>1?arguments[1]:void 0)})},8066:function(e,t,i){"use strict";var n=i(15918);(0,i(43413).exportTypedArrayStaticMethod)("from",i(80922),n)},79023:function(e,t,i){"use strict";var n=i(43413),a=i(51872).includes,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("includes",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},57076:function(e,t,i){"use strict";var n=i(43413),a=i(51872).indexOf,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("indexOf",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},87886:function(e,t,i){"use strict";i(7312)("Int16",function(e){return function(t,i,n){return e(this,t,i,n)}})},49032:function(e,t,i){"use strict";i(7312)("Int32",function(e){return function(t,i,n){return e(this,t,i,n)}})},27621:function(e,t,i){"use strict";i(7312)("Int8",function(e){return function(t,i,n){return e(this,t,i,n)}})},73624:function(e,t,i){"use strict";var n=i(78307),a=i(87584),o=i(21287),r=i(43413),s=i(47895),l=i(5012)("iterator"),u=n.Uint8Array,d=o(s.values),c=o(s.keys),m=o(s.entries),p=r.aTypedArray,f=r.exportTypedArrayMethod,g=u&&u.prototype,h=!a(function(){g[l].call([1])}),b=!!g&&g.values&&g[l]===g.values&&"values"===g.values.name,k=function(){return d(p(this))};f("entries",function(){return m(p(this))},h),f("keys",function(){return c(p(this))},h),f("values",k,h||!b,{name:"values"}),f(l,k,h||!b,{name:"values"})},4990:function(e,t,i){"use strict";var n=i(43413),a=i(21287),o=n.aTypedArray,r=n.exportTypedArrayMethod,s=a([].join);r("join",function(e){return s(o(this),e)})},59937:function(e,t,i){"use strict";var n=i(43413),a=i(76180),o=i(62348),r=n.aTypedArray;(0,n.exportTypedArrayMethod)("lastIndexOf",function(e){var t=arguments.length;return a(o,r(this),t>1?[e,arguments[1]]:[e])})},36630:function(e,t,i){"use strict";var n=i(43413),a=i(67754).map,o=n.aTypedArray,r=n.getTypedArrayConstructor;(0,n.exportTypedArrayMethod)("map",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0,function(e,t){return new(r(e))(t)})})},14659:function(e,t,i){"use strict";var n=i(43413),a=i(15918),o=n.aTypedArrayConstructor;(0,n.exportTypedArrayStaticMethod)("of",function(){for(var e=0,t=arguments.length,i=new(o(this))(t);t>e;)i[e]=arguments[e++];return i},a)},43303:function(e,t,i){"use strict";var n=i(43413),a=i(7751).right,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("reduceRight",function(e){var t=arguments.length;return a(o(this),e,t,t>1?arguments[1]:void 0)})},72304:function(e,t,i){"use strict";var n=i(43413),a=i(7751).left,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("reduce",function(e){var t=arguments.length;return a(o(this),e,t,t>1?arguments[1]:void 0)})},57234:function(e,t,i){"use strict";var n=i(43413),a=n.aTypedArray,o=n.exportTypedArrayMethod,r=Math.floor;o("reverse",function(){for(var e,t=a(this).length,i=r(t/2),n=0;n1?arguments[1]:void 0,1),i=l(e);if(h)return a(p,this,i,t);var n=this.length,o=r(i),u=0;if(o+t>n)throw new d("Wrong length");for(;ua;)u[a]=i[a++];return u},a(function(){new Int8Array(1).slice()}))},9142:function(e,t,i){"use strict";var n=i(43413),a=i(67754).some,o=n.aTypedArray;(0,n.exportTypedArrayMethod)("some",function(e){return a(o(this),e,arguments.length>1?arguments[1]:void 0)})},73078:function(e,t,i){"use strict";var n=i(78307),a=i(98293),o=i(87584),r=i(11459),s=i(54917),l=i(43413),u=i(70724),d=i(24388),c=i(17258),m=i(81974),p=l.aTypedArray,f=l.exportTypedArrayMethod,g=n.Uint16Array,h=g&&a(g.prototype.sort),b=!!h&&!(o(function(){h(new g(2),null)})&&o(function(){h(new g(2),{})})),k=!!h&&!o(function(){if(c)return c<74;if(u)return u<67;if(d)return!0;if(m)return m<602;var e,t,i=new g(516),n=Array(516);for(e=0;e<516;e++)t=e%4,i[e]=515-e,n[e]=e-2*t+3;for(h(i,function(e,t){return(e/4|0)-(t/4|0)}),e=0;e<516;e++)if(i[e]!==n[e])return!0});f("sort",function(e){return(void 0!==e&&r(e),k)?h(this,e):s(p(this),function(t,i){return void 0!==e?+e(t,i)||0:i!=i?-1:t!=t?1:0===t&&0===i?1/t>0&&1/i<0?1:-1:t>i})},!k||b)},89069:function(e,t,i){"use strict";var n=i(43413),a=i(93221),o=i(68757),r=n.aTypedArray,s=n.getTypedArrayConstructor;(0,n.exportTypedArrayMethod)("subarray",function(e,t){var i=r(this),n=i.length,l=o(e,n);return new(s(i))(i.buffer,i.byteOffset+l*i.BYTES_PER_ELEMENT,a((void 0===t?n:o(t,n))-l))})},44878:function(e,t,i){"use strict";var n=i(78307),a=i(76180),o=i(43413),r=i(87584),s=i(89887),l=n.Int8Array,u=o.aTypedArray,d=o.exportTypedArrayMethod,c=[].toLocaleString,m=!!l&&r(function(){c.call(new l(1))});d("toLocaleString",function(){return a(c,m?s(u(this)):u(this),s(arguments))},r(function(){return[1,2].toLocaleString()!==new l([1,2]).toLocaleString()})||!r(function(){l.prototype.toLocaleString.call([1,2])}))},7686:function(e,t,i){"use strict";var n=i(6059),a=i(43413),o=a.aTypedArray,r=a.exportTypedArrayMethod,s=a.getTypedArrayConstructor;r("toReversed",function(){return n(o(this),s(this))})},78497:function(e,t,i){"use strict";var n=i(43413),a=i(21287),o=i(11459),r=i(30161),s=n.aTypedArray,l=n.getTypedArrayConstructor,u=n.exportTypedArrayMethod,d=a(n.TypedArrayPrototype.sort);u("toSorted",function(e){void 0!==e&&o(e);var t=s(this);return d(r(l(t),t),e)})},72293:function(e,t,i){"use strict";var n=i(43413).exportTypedArrayMethod,a=i(87584),o=i(78307),r=i(21287),s=o.Uint8Array,l=s&&s.prototype||{},u=[].toString,d=r([].join);a(function(){u.call({})})&&(u=function(){return d(this)});var c=l.toString!==u;n("toString",u,c)},48389:function(e,t,i){"use strict";i(7312)("Uint16",function(e){return function(t,i,n){return e(this,t,i,n)}})},48899:function(e,t,i){"use strict";i(7312)("Uint32",function(e){return function(t,i,n){return e(this,t,i,n)}})},1604:function(e,t,i){"use strict";i(7312)("Uint8",function(e){return function(t,i,n){return e(this,t,i,n)}})},12319:function(e,t,i){"use strict";i(7312)("Uint8",function(e){return function(t,i,n){return e(this,t,i,n)}},!0)},32110:function(e,t,i){"use strict";var n=i(94857),a=i(43413),o=i(60186),r=i(47742),s=i(51855),l=a.aTypedArray,u=a.getTypedArrayConstructor;(0,a.exportTypedArrayMethod)("with",{with:function(e,t){var i=l(this),a=r(e),d=o(i)?s(t):+t;return n(i,u(i),a,d)}}.with,!function(){try{new Int8Array(1).with(2,{valueOf:function(){throw 8}})}catch(e){return 8===e}}())},56060:function(e,t,i){"use strict";var n=i(21911),a=i(21287),o=i(39940),r=String.fromCharCode,s=a("".charAt),l=a(/./.exec),u=a("".slice),d=/^[\da-f]{2}$/i,c=/^[\da-f]{4}$/i;n({global:!0},{unescape:function(e){for(var t,i,n=o(e),a="",m=n.length,p=0;p>(-2*M&6)));return l}})},33006:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(30290),r=i(21287),s=i(79830),l=i(87584),u=i(39940),d=i(18535),c=i(2073).i2c,m=o("btoa"),p=r("".charAt),f=r("".charCodeAt),g=!!m&&!l(function(){return"aGk="!==m("hi")}),h=g&&!l(function(){m()}),b=g&&l(function(){return"bnVsbA=="!==m(null)}),k=g&&1!==m.length;n({global:!0,bind:!0,enumerable:!0,forced:!g||h||b||k},{btoa:function(e){if(d(arguments.length,1),g)return s(m,a,u(e));for(var t,i,n=u(e),r="",l=0,h=c;p(n,l)||(h="=",l%1);){if((i=f(n,l+=3/4))>255)throw new(o("DOMException"))("The string contains characters outside of the Latin1 range","InvalidCharacterError");r+=p(h,63&(t=t<<8|i)>>8-l%1*8)}return r}})},15211:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(28004).clear;n({global:!0,bind:!0,enumerable:!0,forced:a.clearImmediate!==o},{clearImmediate:o})},55225:function(e,t,i){"use strict";var n=i(78307),a=i(76155),o=i(5377),r=i(92166),s=i(45790),l=function(e){if(e&&e.forEach!==r)try{s(e,"forEach",r)}catch(t){e.forEach=r}};for(var u in a)a[u]&&l(n[u]&&n[u].prototype);l(o)},78636:function(e,t,i){"use strict";var n=i(78307),a=i(76155),o=i(5377),r=i(47895),s=i(45790),l=i(30380),u=i(5012)("iterator"),d=r.values,c=function(e,t){if(e){if(e[u]!==d)try{s(e,u,d)}catch(t){e[u]=d}if(l(e,t,!0),a[t]){for(var i in r)if(e[i]!==r[i])try{s(e,i,r[i])}catch(t){e[i]=r[i]}}}};for(var m in a)c(n[m]&&n[m].prototype,m);c(o,"DOMTokenList")},18248:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(42160),r=i(87584),s=i(1127),l=i(7221),u=i(45392).f,d=i(98243),c=i(25039),m=i(18280),p=i(72720),f=i(78700),g=i(16099),h=i(78244),b=i(98597),k=i(17294),v=i(60472),y=i(95851),w=i(55564),_="DOMException",S="DATA_CLONE_ERR",M=a("Error"),z=a(_)||function(){try{new(a("MessageChannel")||o("worker_threads").MessageChannel)().port1.postMessage(new WeakMap)}catch(e){if(e.name===S&&25===e.code)return e.constructor}}(),j=z&&z.prototype,P=M.prototype,A=v.set,R=v.getterFor(_),T="stack"in new M(_),C=function(e){return m(b,e)&&b[e].m?b[e].c:0},E=function(){p(this,I);var e=arguments.length,t=h(e<1?void 0:arguments[0]),i=h(e<2?void 0:arguments[1],"Error"),n=C(i);if(A(this,{type:_,name:i,message:t,code:n}),y||(this.name=i,this.message=t,this.code=n),T){var a=new M(t);a.name=_,u(this,"stack",l(1,k(a.stack,1)))}},I=E.prototype=s(P),x=function(e){return{enumerable:!0,configurable:!0,get:e}},D=function(e){return x(function(){return R(this)[e]})};y&&(c(I,"code",D("code")),c(I,"message",D("message")),c(I,"name",D("name"))),u(I,"constructor",l(1,E));var O=r(function(){return!(new z instanceof M)}),L=O||r(function(){return P.toString!==g||"2: 1"!==String(new z(1,2))}),V=O||r(function(){return 25!==new z(1,"DataCloneError").code}),N=O||25!==z[S]||25!==j[S],U=w?L||V||N:O;n({global:!0,constructor:!0,forced:U},{DOMException:U?E:z});var F=a(_),B=F.prototype;for(var H in L&&(w||z===F)&&d(B,"toString",g),V&&y&&z===F&&c(B,"code",x(function(){return C(f(this).name)})),b)if(m(b,H)){var K=b[H],q=K.s,$=l(6,K.c);m(F,q)||u(F,q,$),m(B,q)||u(B,q,$)}},85656:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(30290),r=i(7221),s=i(45392).f,l=i(18280),u=i(72720),d=i(58728),c=i(78244),m=i(98597),p=i(17294),f=i(95851),g=i(55564),h="DOMException",b=o("Error"),k=o(h),v=function(){u(this,y);var e=arguments.length,t=c(e<1?void 0:arguments[0]),i=c(e<2?void 0:arguments[1],"Error"),n=new k(t,i),a=new b(t);return a.name=h,s(n,"stack",r(1,p(a.stack,1))),d(n,this,v),n},y=v.prototype=k.prototype,w="stack"in new b(h),_="stack"in new k(1,2),S=k&&f&&Object.getOwnPropertyDescriptor(a,h),M=!!S&&!(S.writable&&S.configurable),z=w&&!M&&!_;n({global:!0,constructor:!0,forced:g||z},{DOMException:z?v:k});var j=o(h),P=j.prototype;if(P.constructor!==j){for(var A in g||s(P,"constructor",r(1,j)),m)if(l(m,A)){var R=m[A],T=R.s;l(j,T)||s(j,T,r(6,R.c))}}},89752:function(e,t,i){"use strict";var n=i(30290),a=i(30380),o="DOMException";a(n(o),o)},42547:function(e,t,i){"use strict";i(15211),i(67178)},35949:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(89632),r=i(11459),s=i(18535),l=i(87584),u=i(95851);n({global:!0,enumerable:!0,dontCallGetSet:!0,forced:l(function(){return u&&1!==Object.getOwnPropertyDescriptor(a,"queueMicrotask").value.length})},{queueMicrotask:function(e){s(arguments.length,1),o(r(e))}})},50742:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(25039),r=i(95851),s=TypeError,l=Object.defineProperty,u=a.self!==a;try{if(r){var d=Object.getOwnPropertyDescriptor(a,"self");!u&&d&&d.get&&d.enumerable||o(a,"self",{get:function(){return a},set:function(e){if(this!==a)throw new s("Illegal invocation");l(a,"self",{value:e,writable:!0,configurable:!0,enumerable:!0})},configurable:!0,enumerable:!0})}else n({global:!0,simple:!0,forced:u},{self:a})}catch(e){}},67178:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(28004).set,r=i(55017),s=a.setImmediate?r(o,!1):o;n({global:!0,bind:!0,enumerable:!0,forced:a.setImmediate!==s},{setImmediate:s})},73702:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(55017)(a.setInterval,!0);n({global:!0,bind:!0,forced:a.setInterval!==o},{setInterval:o})},5452:function(e,t,i){"use strict";var n=i(21911),a=i(78307),o=i(55017)(a.setTimeout,!0);n({global:!0,bind:!0,forced:a.setTimeout!==o},{setTimeout:o})},13847:function(e,t,i){"use strict";var n=i(55564),a=i(21911),o=i(78307),r=i(30290),s=i(21287),l=i(87584),u=i(61239),d=i(26838),c=i(3776),m=i(61852),p=i(90897),f=i(47102),g=i(48747),h=i(78700),b=i(81192),k=i(18280),v=i(44083),y=i(45790),w=i(6171),_=i(18535),S=i(8219),M=i(68835),z=i(27853),j=i(6478),P=i(8892),A=i(98300),R=i(95161),T=o.Object,C=o.Array,E=o.Date,I=o.Error,x=o.TypeError,D=o.PerformanceMark,O=r("DOMException"),L=M.Map,V=M.has,N=M.get,U=M.set,F=z.Set,B=z.add,H=z.has,K=r("Object","keys"),q=s([].push),$=s((!0).valueOf),W=s(1..valueOf),G=s("".valueOf),Y=s(E.prototype.getTime),Q=u("structuredClone"),Z="DataCloneError",J="Transferring",X=function(e){return!l(function(){var t=new o.Set([7]),i=e(t),n=e(T(7));return i===t||!i.has(7)||!p(n)||7!=+n})&&e},ee=function(e,t){return!l(function(){var i=new t,n=e({a:i,b:i});return!(n&&n.a===n.b&&n.a instanceof t&&n.a.stack===i.stack)})},et=o.structuredClone,ei=n||!ee(et,I)||!ee(et,O)||!!l(function(){var e=et(new o.AggregateError([1],Q,{cause:3}));return"AggregateError"!==e.name||1!==e.errors[0]||e.message!==Q||3!==e.cause}),en=!et&&X(function(e){return new D(Q,{detail:e}).detail}),ea=X(et)||en,eo=function(e){throw new O("Uncloneable type: "+e,Z)},er=function(e,t){throw new O((t||"Cloning")+" of "+e+" cannot be properly polyfilled in this engine",Z)},es=function(e,t){return ea||er(t),ea(e)},el=function(){var e;try{e=new o.DataTransfer}catch(t){try{e=new o.ClipboardEvent("").clipboardData}catch(e){}}return e&&e.items&&e.files?e:null},eu=function(e,t,i){if(V(t,e))return N(t,e);if("SharedArrayBuffer"===(i||b(e)))n=ea?ea(e):e;else{var n,a,r,s,l,u,c=o.DataView;c||d(e.slice)||er("ArrayBuffer");try{if(d(e.slice)&&!e.resizable)n=e.slice(0);else for(u=0,a=e.byteLength,r=("maxByteLength"in e)?{maxByteLength:e.maxByteLength}:void 0,n=new ArrayBuffer(a,r),s=new c(e),l=new c(n);u1&&!m(arguments[1])?h(arguments[1]):void 0,a=n?n.transfer:void 0;void 0!==a&&(i=em(a,t=new L));var o=ec(e,t);return i&&ep(i),o}})},63730:function(e,t,i){"use strict";i(73702),i(5452)},31453:function(e,t,i){"use strict";i(47895),i(98742);var n=i(21911),a=i(78307),o=i(84582),r=i(30290),s=i(79830),l=i(21287),u=i(95851),d=i(39859),c=i(98243),m=i(25039),p=i(42726),f=i(30380),g=i(44137),h=i(60472),b=i(72720),k=i(26838),v=i(18280),y=i(2595),w=i(81192),_=i(78700),S=i(90897),M=i(39940),z=i(1127),j=i(7221),P=i(23e3),A=i(40876),R=i(75562),T=i(18535),C=i(5012),E=i(54917),I=C("iterator"),x="URLSearchParams",D=x+"Iterator",O=h.set,L=h.getterFor(x),V=h.getterFor(D),N=o("fetch"),U=o("Request"),F=o("Headers"),B=U&&U.prototype,H=F&&F.prototype,K=a.TypeError,q=a.encodeURIComponent,$=String.fromCharCode,W=r("String","fromCodePoint"),G=parseInt,Y=l("".charAt),Q=l([].join),Z=l([].push),J=l("".replace),X=l([].shift),ee=l([].splice),et=l("".split),ei=l("".slice),en=l(/./.exec),ea=/\+/g,eo=/^[0-9a-f]+$/i,er=function(e,t){var i=ei(e,t,t+2);return en(eo,i)?G(i,16):NaN},es=function(e){for(var t=0,i=128;i>0&&(e&i)!=0;i>>=1)t++;return t},el=function(e){var t=null;switch(e.length){case 1:t=e[0];break;case 2:t=(31&e[0])<<6|63&e[1];break;case 3:t=(15&e[0])<<12|(63&e[1])<<6|63&e[2];break;case 4:t=(7&e[0])<<18|(63&e[1])<<12|(63&e[2])<<6|63&e[3]}return t>1114111?null:t},eu=function(e){for(var t=(e=J(e,ea," ")).length,i="",n=0;nt){i+="%",n++;continue}var o=er(e,n+1);if(o!=o){i+=a,n++;continue}n+=2;var r=es(o);if(0===r)a=$(o);else{if(1===r||r>4){i+="�",n++;continue}for(var s=[o],l=1;lt)&&"%"===Y(e,n);){var u=er(e,n+1);if(u!=u){n+=3;break}if(u>191||u<128)break;Z(s,u),n+=2,l++}if(s.length!==r){i+="�";continue}var d=el(s);null===d?i+="�":a=W(d)}}i+=a,n++}return i},ed=/[!'()~]|%20/g,ec={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"},em=function(e){return ec[e]},ep=function(e){return J(q(e),ed,em)},ef=g(function(e,t){O(this,{type:D,target:L(e).entries,index:0,kind:t})},x,function(){var e=V(this),t=e.target,i=e.index++;if(!t||i>=t.length)return e.target=null,R(void 0,!0);var n=t[i];switch(e.kind){case"keys":return R(n.key,!1);case"values":return R(n.value,!1)}return R([n.key,n.value],!1)},!0),eg=function(e){this.entries=[],this.url=null,void 0!==e&&(S(e)?this.parseObject(e):this.parseQuery("string"==typeof e?"?"===Y(e,0)?ei(e,1):e:M(e)))};eg.prototype={type:x,bindURL:function(e){this.url=e,this.update()},parseObject:function(e){var t,i,n,a,o,r,l,u=this.entries,d=A(e);if(d)for(i=(t=P(e,d)).next;!(n=s(i,t)).done;){if((r=s(o=(a=P(_(n.value))).next,a)).done||(l=s(o,a)).done||!s(o,a).done)throw new K("Expected sequence with length 2");Z(u,{key:M(r.value),value:M(l.value)})}else for(var c in e)v(e,c)&&Z(u,{key:c,value:M(e[c])})},parseQuery:function(e){if(e)for(var t,i,n=this.entries,a=et(e,"&"),o=0;o0?arguments[0]:void 0,t=O(this,new eg(e));u||(this.size=t.entries.length)},eb=eh.prototype;if(p(eb,{append:function(e,t){var i=L(this);T(arguments.length,2),Z(i.entries,{key:M(e),value:M(t)}),!u&&this.length++,i.updateURL()},delete:function(e){for(var t=L(this),i=T(arguments.length,1),n=t.entries,a=M(e),o=i<2?void 0:arguments[1],r=void 0===o?o:M(o),s=0;st.key?1:-1}),e.updateURL()},forEach:function(e){for(var t,i=L(this).entries,n=y(e,arguments.length>1?arguments[1]:void 0),a=0;a1?ey(arguments[1]):{})}}),k(U)){var ew=function(e){return b(this,B),new U(e,arguments.length>1?ey(arguments[1]):{})};B.constructor=ew,ew.prototype=B,n({global:!0,constructor:!0,dontCallGetSet:!0,forced:!0},{Request:ew})}}e.exports={URLSearchParams:eh,getState:L}},59750:function(e,t,i){"use strict";var n=i(98243),a=i(21287),o=i(39940),r=i(18535),s=URLSearchParams,l=s.prototype,u=a(l.append),d=a(l.delete),c=a(l.forEach),m=a([].push),p=new s("a=1&a=2&b=3");p.delete("a",1),p.delete("b",void 0),p+""!="a=2"&&n(l,"delete",function(e){var t,i=arguments.length,n=i<2?void 0:arguments[1];if(i&&void 0===n)return d(this,e);var a=[];c(this,function(e,t){m(a,{key:t,value:e})}),r(i,1);for(var s=o(e),l=o(n),p=0,f=0,g=!1,h=a.length;p?@[\\\]^|]/,ei=/[\0\t\n\r #/:<>?@[\\\]^|]/,en=/^[\u0000-\u0020]+/,ea=/(^|[^\u0000-\u0020])[\u0000-\u0020]+$/,eo=/[\t\n\r]/g,er=function(e){var t,i,n,a,o,r,s,l=F(e,".");if(l.length&&""===l[l.length-1]&&l.length--,(t=l.length)>4)return e;for(n=0,i=[];n1&&"0"===I(a,0)&&(o=x(Z,a)?16:8,a=B(a,8===o?1:2)),""===a)r=0;else{if(!x(10===o?X:8===o?J:ee,a))return e;r=T(a,o)}V(i,r)}for(n=0;n=E(256,5-t))return null}else if(r>255)return null;for(n=0,s=L(i);n6))return;for(n=0;m();){if(a=null,n>0){if("."!==m()||!(n<4))return;c++}if(!x(Q,m()))return;for(;x(Q,m());){if(o=T(m(),10),null===a)a=o;else{if(0===a)return;a=10*a+o}if(a>255)return;c++}l[u]=256*l[u]+a,(2==++n||4===n)&&u++}if(4!==n)return;break}if(":"===m()){if(c++,!m())return}else if(m())return;l[u++]=t}if(null!==d)for(r=u-d,u=7;0!==u&&r>0;)s=l[u],l[u--]=l[d+r-1],l[d+--r]=s;else if(8!==u)return;return l},el=function(e){for(var t=null,i=1,n=null,a=0,o=0;o<8;o++)0!==e[o]?(a>i&&(t=n,i=a),n=null,a=0):(null===n&&(n=o),++a);return a>i?n:t},eu=function(e){var t,i,n,a;if("number"==typeof e){for(i=0,t=[];i<4;i++)K(t,e%256),e=C(e/256);return D(t,".")}if("object"==typeof e){for(i=0,t="",n=el(e);i<8;i++)(!a||0!==e[i])&&(a&&(a=!1),n===i?(t+=i?":":"::",a=!0):(t+=O(e[i],16),i<7&&(t+=":")));return"["+t+"]"}return e},ed={},ec=f({},ed,{" ":1,'"':1,"<":1,">":1,"`":1}),em=f({},ec,{"#":1,"?":1,"{":1,"}":1}),ep=f({},em,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),ef=function(e,t){var i=b(e,0);return i>32&&i<127&&!p(t,e)?e:encodeURIComponent(e)},eg={ftp:21,file:null,http:80,https:443,ws:80,wss:443},eh=function(e,t){var i;return 2===e.length&&x(G,I(e,0))&&(":"===(i=I(e,1))||!t&&"|"===i)},eb=function(e){var t;return e.length>1&&eh(B(e,0,2))&&(2===e.length||"/"===(t=I(e,2))||"\\"===t||"?"===t||"#"===t)},ek={},ev={},ey={},ew={},e_={},eS={},eM={},ez={},ej={},eP={},eA={},eR={},eT={},eC={},eE={},eI={},ex={},eD={},eO={},eL={},eV={},eN=function(e,t,i){var n,a,o,r=v(e);if(t){if(a=this.parse(r))throw new R(a);this.searchParams=null}else{if(void 0!==i&&(n=new eN(i,!0)),a=this.parse(r,null,n))throw new R(a);(o=P(new j)).bindURL(this),this.searchParams=o}};eN.prototype={type:"URL",parse:function(e,t,i){var a=t||ek,o=0,r="",s=!1,l=!1,u=!1;for(e=v(e),t||(this.scheme="",this.username="",this.password="",this.host=null,this.port=null,this.path=[],this.query=null,this.fragment=null,this.cannotBeABaseURL=!1,e=N(e,en,""),e=N(e,ea,"$1")),d=g(e=N(e,eo,""));o<=d.length;){switch(c=d[o],a){case ek:if(c&&x(G,c))r+=H(c),a=ev;else{if(t)return q;a=ey;continue}break;case ev:if(c&&(x(Y,c)||"+"===c||"-"===c||"."===c))r+=H(c);else if(":"===c){if(t&&(this.isSpecial()!==p(eg,r)||"file"===r&&(this.includesCredentials()||null!==this.port)||"file"===this.scheme&&!this.host))return;if(this.scheme=r,t){this.isSpecial()&&eg[this.scheme]===this.port&&(this.port=null);return}r="","file"===this.scheme?a=eC:this.isSpecial()&&i&&i.scheme===this.scheme?a=ew:this.isSpecial()?a=ez:"/"===d[o+1]?(a=e_,o++):(this.cannotBeABaseURL=!0,V(this.path,""),a=eO)}else{if(t)return q;r="",a=ey,o=0;continue}break;case ey:if(!i||i.cannotBeABaseURL&&"#"!==c)return q;if(i.cannotBeABaseURL&&"#"===c){this.scheme=i.scheme,this.path=h(i.path),this.query=i.query,this.fragment="",this.cannotBeABaseURL=!0,a=eV;break}a="file"===i.scheme?eC:eS;continue;case ew:if("/"===c&&"/"===d[o+1])a=ej,o++;else{a=eS;continue}break;case e_:if("/"===c){a=eP;break}a=eD;continue;case eS:if(this.scheme=i.scheme,c===n)this.username=i.username,this.password=i.password,this.host=i.host,this.port=i.port,this.path=h(i.path),this.query=i.query;else if("/"===c||"\\"===c&&this.isSpecial())a=eM;else if("?"===c)this.username=i.username,this.password=i.password,this.host=i.host,this.port=i.port,this.path=h(i.path),this.query="",a=eL;else if("#"===c)this.username=i.username,this.password=i.password,this.host=i.host,this.port=i.port,this.path=h(i.path),this.query=i.query,this.fragment="",a=eV;else{this.username=i.username,this.password=i.password,this.host=i.host,this.port=i.port,this.path=h(i.path),this.path.length--,a=eD;continue}break;case eM:if(this.isSpecial()&&("/"===c||"\\"===c))a=ej;else if("/"===c)a=eP;else{this.username=i.username,this.password=i.password,this.host=i.host,this.port=i.port,a=eD;continue}break;case ez:if(a=ej,"/"!==c||"/"!==I(r,o+1))continue;o++;break;case ej:if("/"!==c&&"\\"!==c){a=eP;continue}break;case eP:if("@"===c){s&&(r="%40"+r),s=!0,m=g(r);for(var d,c,m,f,b,k,y=0;y65535)return W;this.port=this.isSpecial()&&S===eg[this.scheme]?null:S,r=""}if(t)return;a=ex;continue}break;case eC:if(this.scheme="file","/"===c||"\\"===c)a=eE;else if(i&&"file"===i.scheme)switch(c){case n:this.host=i.host,this.path=h(i.path),this.query=i.query;break;case"?":this.host=i.host,this.path=h(i.path),this.query="",a=eL;break;case"#":this.host=i.host,this.path=h(i.path),this.query=i.query,this.fragment="",a=eV;break;default:eb(D(h(d,o),""))||(this.host=i.host,this.path=h(i.path),this.shortenPath()),a=eD;continue}else{a=eD;continue}break;case eE:if("/"===c||"\\"===c){a=eI;break}i&&"file"===i.scheme&&!eb(D(h(d,o),""))&&(eh(i.path[0],!0)?V(this.path,i.path[0]):this.host=i.host),a=eD;continue;case eI:if(c===n||"/"===c||"\\"===c||"?"===c||"#"===c){if(!t&&eh(r))a=eD;else if(""===r){if(this.host="",t)return;a=ex}else{if(f=this.parseHost(r))return f;if("localhost"===this.host&&(this.host=""),t)return;r="",a=ex}continue}r+=c;break;case ex:if(this.isSpecial()){if(a=eD,"/"!==c&&"\\"!==c)continue}else if(t||"?"!==c){if(t||"#"!==c){if(c!==n&&(a=eD,"/"!==c))continue}else this.fragment="",a=eV}else this.query="",a=eL;break;case eD:if(c===n||"/"===c||"\\"===c&&this.isSpecial()||!t&&("?"===c||"#"===c)){if(".."===(b=H(b=r))||"%2e."===b||".%2e"===b||"%2e%2e"===b?(this.shortenPath(),"/"===c||"\\"===c&&this.isSpecial()||V(this.path,"")):"."===(k=r)||"%2e"===H(k)?"/"===c||"\\"===c&&this.isSpecial()||V(this.path,""):("file"===this.scheme&&!this.path.length&&eh(r)&&(this.host&&(this.host=""),r=I(r,0)+":"),V(this.path,r)),r="","file"===this.scheme&&(c===n||"?"===c||"#"===c))for(;this.path.length>1&&""===this.path[0];)U(this.path);"?"===c?(this.query="",a=eL):"#"===c&&(this.fragment="",a=eV)}else r+=ef(c,em);break;case eO:"?"===c?(this.query="",a=eL):"#"===c?(this.fragment="",a=eV):c!==n&&(this.path[0]+=ef(c,ed));break;case eL:t||"#"!==c?c!==n&&("'"===c&&this.isSpecial()?this.query+="%27":"#"===c?this.query+="%23":this.query+=ef(c,ed)):(this.fragment="",a=eV);break;case eV:c!==n&&(this.fragment+=ef(c,ec))}o++}},parseHost:function(e){var t,i,n;if("["===I(e,0)){if("]"!==I(e,e.length-1)||!(t=es(B(e,1,-1))))return $;this.host=t}else if(this.isSpecial()){if(x(et,e=k(e))||null===(t=er(e)))return $;this.host=t}else{if(x(ei,e))return $;for(n=0,t="",i=g(e);n1?arguments[1]:void 0,n=M(t,new eN(e,!1,i));o||(t.href=n.serialize(),t.origin=n.getOrigin(),t.protocol=n.getProtocol(),t.username=n.getUsername(),t.password=n.getPassword(),t.host=n.getHost(),t.hostname=n.getHostname(),t.port=n.getPort(),t.pathname=n.getPathname(),t.search=n.getSearch(),t.searchParams=n.getSearchParams(),t.hash=n.getHash())},eF=eU.prototype,eB=function(e,t){return{get:function(){return z(this)[e]()},set:t&&function(e){return z(this)[t](e)},configurable:!0,enumerable:!0}};if(o&&(c(eF,"href",eB("serialize","setHref")),c(eF,"origin",eB("getOrigin")),c(eF,"protocol",eB("getProtocol","setProtocol")),c(eF,"username",eB("getUsername","setUsername")),c(eF,"password",eB("getPassword","setPassword")),c(eF,"host",eB("getHost","setHost")),c(eF,"hostname",eB("getHostname","setHostname")),c(eF,"port",eB("getPort","setPort")),c(eF,"pathname",eB("getPathname","setPathname")),c(eF,"search",eB("getSearch","setSearch")),c(eF,"searchParams",eB("getSearchParams")),c(eF,"hash",eB("getHash","setHash"))),d(eF,"toJSON",function(){return z(this).serialize()},{enumerable:!0}),d(eF,"toString",function(){return z(this).serialize()},{enumerable:!0}),A){var eH=A.createObjectURL,eK=A.revokeObjectURL;eH&&d(eU,"createObjectURL",l(eH,A)),eK&&d(eU,"revokeObjectURL",l(eK,A))}y(eU,"URL"),a({global:!0,constructor:!0,forced:!r,sham:!o},{URL:eU})},40371:function(e,t,i){"use strict";i(48409)},28626:function(e,t,i){"use strict";var n=i(21911),a=i(30290),o=i(18535),r=i(39940),s=i(39859),l=a("URL");n({target:"URL",stat:!0,forced:!s},{parse:function(e){var t=o(arguments.length,1),i=r(e),n=t<2||void 0===arguments[1]?void 0:r(arguments[1]);try{return new l(i,n)}catch(e){return null}}})},29075:function(e,t,i){"use strict";var n=i(21911),a=i(79830);n({target:"URL",proto:!0,enumerable:!0},{toJSON:function(){return a(URL.prototype.toString,this)}})},95810:function(e,t,i){"use strict";i(27704),i(54224),i(17697),i(32e3),i(85605),i(26990),i(32983),i(48805),i(25466),i(67180),i(52744),i(37294),i(18849),i(53438),i(75313),i(57801),i(47103),i(86098),i(343),i(24780),i(64941),i(43198),i(57770),i(3876),i(59811),i(38286),i(66947),i(53903),i(12062),i(48430),i(34561),i(57046),i(8569),i(7184),i(34587),i(97109),i(47895),i(43721),i(15580),i(85699),i(15480),i(80445),i(3895),i(31880),i(77387),i(10991),i(629),i(96181),i(6583),i(86165),i(89339),i(22908),i(15209),i(74909),i(47994),i(31736),i(98585),i(55712),i(96534),i(99406),i(30096),i(40026),i(93494),i(75548),i(73813),i(76925),i(36626),i(92390),i(3646),i(2296),i(1215),i(20316),i(14693),i(27195),i(33587),i(70999),i(74488),i(50267),i(94508),i(99948),i(60219),i(89955),i(23484),i(16045),i(61738),i(25089),i(85446),i(47410),i(8828),i(41338),i(26089),i(15487),i(44029),i(94348),i(77728),i(46655),i(69266),i(79849),i(15602),i(64029),i(26422),i(40127),i(81097),i(49264),i(54009),i(62114),i(24929),i(80123),i(64251),i(97646),i(35687),i(16344),i(5659),i(58744),i(54082),i(88591),i(44113),i(47427),i(41056),i(36987),i(39357),i(66268),i(11766),i(40615),i(18904),i(62044),i(92213),i(40619),i(25152),i(22137),i(6892),i(32782),i(40322),i(87144),i(70325),i(21330),i(61780),i(79112),i(54615),i(65133),i(25594),i(44662),i(12628),i(47409),i(69383),i(50028),i(41678),i(64673),i(44535),i(50131),i(14478),i(53799),i(64332),i(23086),i(77908),i(27879),i(69650),i(64565),i(47879),i(3798),i(8971),i(55574),i(80832),i(9643),i(78797),i(12832),i(47554),i(68922),i(72649),i(33288),i(69338),i(1669),i(43719),i(78518),i(65966),i(9165),i(82446),i(27377),i(35467),i(47984),i(46046),i(35594),i(5e4),i(73712),i(2827),i(15614),i(75514),i(37979),i(28565),i(83104),i(1941),i(60054),i(41485),i(83329),i(20304),i(87939),i(32874),i(98742),i(18934),i(71074),i(94005),i(84778),i(87684),i(22358),i(49451),i(84153),i(23068),i(5135),i(61165),i(24051),i(53871),i(79279),i(47374),i(73567),i(48363),i(6119),i(59930),i(97810),i(4609),i(28729),i(41080),i(90773),i(52999),i(20411),i(1202),i(6919),i(69004),i(25061),i(63229),i(85003),i(94391),i(88560),i(27621),i(87886),i(49032),i(1604),i(12319),i(48389),i(48899),i(38403),i(11195),i(61687),i(2819),i(57312),i(93225),i(30652),i(93614),i(46563),i(98053),i(8066),i(79023),i(57076),i(73624),i(4990),i(59937),i(36630),i(14659),i(72304),i(43303),i(57234),i(53828),i(66326),i(9142),i(73078),i(89069),i(44878),i(7686),i(78497),i(72293),i(32110),i(56060),i(55879),i(44761),i(17232),i(33006),i(55225),i(78636),i(18248),i(85656),i(89752),i(42547),i(35949),i(50742),i(13847),i(63730),i(40371),i(45425),i(28626),i(29075),i(33343),i(59750),i(94141),i(65968),i(20386)}},t={};function i(n){var a=t[n];if(void 0!==a)return a.exports;var o=t[n]={id:n,exports:{}};return e[n].call(o.exports,o,o.exports,i),o.exports}i.d=function(e,t){for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="bundles/molliepayments/",window?.__sw__?.assetPath&&(i.p=window.__sw__.assetPath+"/bundles/molliepayments/"),function(){"use strict";i(12617),i(95810),i(89982);class e{equals(e,t){return this.compare(e,t,"=")}notEquals(e,t){return this.compare(e,t,"!=")}greater(e,t){return this.compare(e,t,">")}greaterOrEqual(e,t){return this.compare(e,t,">=")}lesser(e,t){return this.compare(e,t,"<")}lesserOrEqual(e,t){return this.compare(e,t,"<=")}compare(e,t,i="="){let n=this.matchVersion(e),a=this.matchVersion(t);if(null===n||null===a)return!1;switch(i){case"=":case"==":case"===":case"eq":return n.major===a.major&&n.minor===a.minor&&n.patch===a.patch&&n.build===a.build;case"!=":case"!==":case"neq":return!(n.major===a.major&&n.minor===a.minor&&n.patch===a.patch&&n.build===a.build);case">":case"gt":if(n.major>a.major||n.minor>a.minor||n.patch>a.patch)return!0;return n.build>a.build;case">=":case"gte":if(n.major=a.build;case"<":case"lt":if(n.majorn.major||a.minor>n.minor||a.patch>n.patch)return!0;return a.build>=n.build}return!1}matchVersion(e){let t=e.match(/(?(?\d+)\.?(?\d+)\.?(?\d+)\.?(?\d*))-?(?[a-z]+)?\.?(?\d+(?:.\d+)*)?/i);if(null===t)return console.warn(`${e} is not a valid version string.`),null;let i=t.groups;return["major","minor","patch","build"].forEach(e=>{i[e]=parseInt(i[e])||0}),i}getHumanReadableVersion(e){let t=this.matchVersion(e);if(null===t)return e;let i=`v${t.version}`;return t.prerelease?i+=` ${this.getHumanReadablePrereleaseText(t.prerelease)}`:i+=" Stable Version",t.prereleaseDigits&&(i+=` ${t.prereleaseDigits}`),i}getHumanReadablePrereleaseText(e){switch(e){case"dp":return"Developer Preview";case"rc":return"Release Candidate";case"dev":return"Developer Version";case"ea":return"Early Access";default:return e}}}let{Component:t,Mixin:n}=Shopware;t.register("mollie-pluginconfig-section-info",{template:'\n
\n
\n {{ $tc(\'mollie-payments.config.info.title\', 0, { userName: userName}) }}\n
\n
\n {{ $tc(\'mollie-payments.config.info.descriptionTop\') }}
\n
\n
    \n
  1. \n {{ $tc(\'mollie-payments.config.info.onboardingStep1\') }}
    \n \n https://www.mollie.com/signup\n \n
  2. \n
  3. \n {{ $tc(\'mollie-payments.config.info.onboardingStep2\') }}
    \n {{ $tc(\'mollie-payments.config.info.onboardingStep2TestMode\') }}\n
  4. \n
  5. \n {{ $tc(\'mollie-payments.config.info.onboardingStep3\') }}
    \n \n {{ $tc(\'mollie-payments.config.info.onboardingStep3Link\') }}\n \n
  6. \n
\n
\n {{ $tc(\'mollie-payments.config.info.descriptionBottom\') }}\n
\n \n
\n
\n \n \n {{ $tc(\'mollie-payments.config.info.btnDocumentation\') }}\n \n \n \n {{ $tc(\'mollie-payments.config.info.btnRequestSupport\') }}\n \n \n {{ $tc(\'mollie-payments.config.info.btnTroubleshooting\') }}\n \n
\n \n
\n',mixins:[n.getByName("notification")],data(){return{isSupportOpen:!1,versionCompare:null}},shortcuts:{"SYSTEMKEY+i":"openConfigImport"},created(){this.versionCompare=new e},computed:{userName(){let e=this.getCurrentUser();return e?""===e.firstName?e.username:e.firstName:""},hasSalesChannelList(){return this.versionCompare.greaterOrEqual(Shopware.Context.app.config.version,"6.4.2")}},methods:{openConfigImport(){},getCurrentUser(){let e=Shopware.State.get("session");return void 0===e&&(e=Shopware.Store.get("session")),e.currentUser},openSupport(){this.isSupportOpen=!0},closeSupport(){this.isSupportOpen=!1}}}),i(54878);let{Component:a,Mixin:o}=Shopware;a.register("mollie-pluginconfig-section-api",{template:'\n \n {{ $tc(\'mollie-payments.config.api.testButton\') }}\n \n \n {{ $tc(\'mollie-payments.config.api.apiLinkButton\') }}\n \n\n',inject:["MolliePaymentsConfigService"],mixins:[o.getByName("notification")],methods:{onTestButtonClicked(){let e=this,t=document.querySelector('input[name="MolliePayments.config.liveApiKey"],*[class*="field-mollie-payments-config-live-api-key"] input'),i=document.querySelector('input[name="MolliePayments.config.testApiKey"],*[class*="field-mollie-payments-config-test-api-key"] input'),n=t?t.value:null,a=i?i.value:null;this.MolliePaymentsConfigService.testApiKeys({liveApiKey:n,testApiKey:a}).then(n=>{n.results.forEach(function(n){let a={title:e.$tc("mollie-payments.config.api.testApiKeys.title"),message:`${e.$tc("mollie-payments.config.api.testApiKeys.apiKey")} "${n.key}" (${n.mode}) ${!0===n.valid?e.$tc("mollie-payments.config.api.testApiKeys.isValid"):e.$tc("mollie-payments.config.api.testApiKeys.isInvalid")}.`},o="live"===n.mode?t:i;o&&o.parentNode.parentNode.classList.remove("has--error"),!0===n.valid?e.createNotificationSuccess(a):(e.createNotificationError(a),o&&o.parentNode.parentNode.classList.add("has--error"))})})}}}),i(16e3);let{Component:r,Mixin:s}=Shopware;r.register("mollie-pluginconfig-section-payments",{template:'\n\n \n {{ $tc(\'mollie-payments.config.payments.updatePaymentMethods.button\') }}\n \n\n \n {{ $tc(\'mollie-payments.config.payments.mollieLimits.link\') }}\n \n\n\n',inject:["MolliePaymentsPaymentMethodService"],mixins:[s.getByName("notification")],data(){return{updatePaymentMethodsIsLoading:!1}},methods:{onUpdatePaymentMethodsButtonClicked(){let e=this;this.startUpdatePaymentMethod(),this.MolliePaymentsPaymentMethodService.updatePaymentMethods().then(t=>{let i={title:e.$tc("mollie-payments.config.payments.updatePaymentMethods.title"),message:e.$tc("mollie-payments.config.payments.updatePaymentMethods.succeeded")};!0===t.success?e.createNotificationSuccess(i):(i.message=e.$tc("mollie-payments.config.payments.updatePaymentMethods.failed")+"\n\nException:\n"+t.message,e.createNotificationError(i)),this.updatePaymentMethodsIsDone()}).catch(()=>{this.updatePaymentMethodsIsDone()})},startUpdatePaymentMethod(){this.updatePaymentMethodsIsLoading=!0},updatePaymentMethodsIsDone(){this.updatePaymentMethodsIsLoading=!1}}}),i(31722);class l{isNullOrEmpty(e){return null==e||""===e}replace(e,t,i){if(!i)return"";let n=RegExp(e,"g");return i.replace(n,t)}}let{Component:u}=Shopware;u.register("mollie-pluginconfig-section-payments-format",{template:'\n\n
\n {{ $tc(\'mollie-payments.config.payments.format.placeholder\') }}: {ordernumber}, {customernumber}
\n {{ $tc(\'mollie-payments.config.payments.format.preview\') }}: "{{ sample1 }}", "{{ sample2 }}", ...\n
\n\n
\n',inject:["actualConfigData","currentSalesChannelId"],computed:{sample1(){return this.getFormat("1000","5000")},sample2(){return this.getFormat("5023","2525")}},methods:{getFormat(e,t){let i=this.actualConfigData?.[this.currentSalesChannelId]?.["MolliePayments.config.formatOrderNumber"]||"",n=new l,a=n.replace("{ordernumber}",e,i);return n.replace("{customernumber}",t,a)}}}),i(75862);let{Component:d}=Shopware;d.register("mollie-pluginconfig-section-rounding",{template:'\n \n {{ $tc(\'mollie-payments.config.rounding.info1\') }}
\n
\n {{ $tc(\'mollie-payments.config.rounding.info2\') }}
\n
\n {{ $tc(\'mollie-payments.config.rounding.info3\') }}\n
\n
\n',data(){return{}},computed:{},methods:{}}),i(9174);let{Application:c,Component:m,Context:p,Mixin:f,State:g}=Shopware,{Criteria:h}=Shopware.Data,{string:b}=Shopware.Utils;m.register("mollie-pluginconfig-support-modal",{template:'\n\n \n \n\n \n {{ $tc(\'mollie-payments.config.support.success\') }}\n \n\n \n \n \n \n \n \n \n \n \n \n \n \n \n\n \n \n
{{ $tc(\'mollie-payments.config.support.data.header\') }}
\n
{{ $tc(\'mollie-payments.config.support.data.shopwareVersion\') }}
\n
{{ shopwareVersion }}
\n \n
{{ $tc(\'mollie-payments.config.support.data.other\') }}
\n
\n {{ $tc(\'mollie-payments.config.support.data.pluginLogs\', 0, {\n plugin: molliePlugin.label\n }) }}\n
\n
\n {{ $tc(\'mollie-payments.config.support.data.pluginConfiguration\', 0, {\n plugin: molliePlugin.label\n }) }}\n \n
\n
\n {{ $tc(\'mollie-payments.config.support.data.paymentMethods\') }}\n \n
\n \n
\n\n \n \n {{ $tc(\'mollie-payments.config.info.btnDocumentation\') }}\n \n\n \n \n {{ $tc(\'mollie-payments.config.support.btnSupport\') }}\n \n
\n\n \n
\n\n \n
\n',inject:{shopwareExtensionService:{default:null},MolliePaymentsSupportService:{},repositoryFactory:{}},mixins:[f.getByName("notification")],data(){return{mailSent:!1,isSubmitting:!1,name:"",email:"",subject:"",message:"",recipientLocale:"",recipientOptions:[{label:"International Support (info@mollie.com)",value:null},{label:"German Support (meinsupport@mollie.com)",value:"de-DE"}],versionCompare:null}},computed:{isLoading(){return this.shopwareExtensionService?this.getShopwareExtensions().loading:this.isLoadingPlugins},canSubmit(){return!b.isEmptyOrSpaces(this.contactName)&&!b.isEmptyOrSpaces(this.contactEmail)&&!b.isEmptyOrSpaces(this.subject)&&!b.isEmptyOrSpaces(this.message)},contactName:{get(){return b.isEmptyOrSpaces(name)?this.userName:this.name},set(e){this.name=e}},contactEmail:{get(){return b.isEmptyOrSpaces(this.email)?this.user.email:this.email},set(e){this.email=e}},locale(){return c.getContainer("factory").locale.getLastKnownLocale()},user(){let e=Shopware.State.get("session");return void 0===e&&(e=Shopware.Store.get("session")),e.currentUser},userName(){if(!this.user)return"";let e=`${this.user.firstName} ${this.user.lastName}`.trim();return b.isEmptyOrSpaces(e)?this.user.username:e},plugins(){if(this.shopwareExtensionService)return this.getShopwareExtensions().data||[];let e=Shopware.State.get("swPlugin");return void 0===e&&(e=Shopware.Store.get("swPlugin")),e.plugins||[]},molliePlugin(){return this.plugins.find(e=>"MolliePayments"===e.name)},mollieVersion(){return this.molliePlugin?this.versionCompare.getHumanReadableVersion(this.molliePlugin.version):""},shopwareVersion(){return this.versionCompare.getHumanReadableVersion(p.app.config.version)}},created(){this.versionCompare=new e},mounted(){this.mountedComponent()},methods:{mountedComponent(){this.determineDefaultSupportDesk(),0===this.plugins.length&&(this.shopwareExtensionService?this.shopwareExtensionService.updateExtensionData():this.loadPluginsLegacy())},getShopwareExtensions(){let e=Shopware.State.get("shopwareExtensions");return void 0===e&&(e=Shopware.Store.get("shopwareExtensions")),e.myExtensions},determineDefaultSupportDesk(){this.recipientLocale=this.recipientOptions.some(e=>e.value===this.locale)?this.locale:null},loadPluginsLegacy(){this.isLoadingPlugins=!0;let e=new h;e.setTerm("Mollie");let t={criteria:e,repository:this.repositoryFactory.create("plugin"),context:p.api};g.dispatch("swPlugin/updatePluginList",t).finally(()=>{this.isLoadingPlugins=!1})},onRequestSupport(){this.isSubmitting=!0,this.MolliePaymentsSupportService.request(this.contactName,this.contactEmail,this.recipientLocale,this.subject,this.message).then(e=>{if(!e.success){this._showNotificationError(this.$tc("mollie-payments.config.support.error")),this.mailSent=!1;return}this.mailSent=!0,this._showNotificationSuccess(this.$tc("mollie-payments.config.support.success"))}).catch(e=>{this._showNotificationError(e)}).finally(()=>this.isSubmitting=!1)},_showNotificationSuccess(e){this.createNotificationSuccess({message:e})},_showNotificationError(e){this.createNotificationError({message:e})}}});class k{constructor(){this.maximumOrderLifeTimeKlarna=28,this.maximumOrderLifeTime=100}isOderLifeTimeLimitReached(e){return e>this.maximumOrderLifeTime}isKlarnaOrderLifeTimeReached(e){return e>this.maximumOrderLifeTimeKlarna&&e<=this.maximumOrderLifeTime}}i(55856);let{Component:v,Mixin:y}=Shopware;v.register("mollie-pluginconfig-section-order-lifetime-warning",{template:'\n \n {{ $tc(\'mollie-payments.config.order.bankTransferDueDateKlarnaLimitReached\') }}\n \n \n {{ $tc(\'mollie-payments.config.order.bankTransferDueDateLimitReached\') }}\n \n\n',inject:["MolliePaymentsConfigService"],mixins:[y.getByName("notification")],data(){return{oderLifeTimeLimitReached:!1,klarnaOrderLifeTimeReached:!1}},created(){this.createdComponent()},methods:{createdComponent(){let e=new k,t=setInterval(()=>{let i=document.querySelector('input[name="MolliePayments.config.orderLifetimeDays"],[class*="mollie-payments-config-order-lifetime-days"] input');if(null===i)return;clearInterval(t);let n=parseInt(i.value);this.oderLifeTimeLimitReached=e.isOderLifeTimeLimitReached(n),this.klarnaOrderLifeTimeReached=e.isKlarnaOrderLifeTimeReached(n),i.addEventListener("keyup",t=>{let i=parseInt(t.target.value);this.oderLifeTimeLimitReached=e.isOderLifeTimeLimitReached(i),this.klarnaOrderLifeTimeReached=e.isKlarnaOrderLifeTimeReached(i)},!0)},500)}}}),i(45501);let w=Shopware.Classes.ApiService;class _ extends w{constructor(e,t,i){super(e,t,"mollie"),this.currentLocale=i}testApiKeys(e={liveApiKey:null,testApiKey:null}){let t=this.getBasicHeaders();return this.httpClient.post(`_action/${this.getApiBasePath()}/config/test-api-keys`,JSON.stringify(e),{headers:t}).then(e=>w.handleResponse(e))}validateFlowBuilder(){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/validate/flowbuilder`,{locale:this.currentLocale},{headers:this.getBasicHeaders()}).then(e=>w.handleResponse(e))}getSubscriptionConfig(){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/subscription`,{locale:this.currentLocale},{headers:this.getBasicHeaders()}).then(e=>w.handleResponse(e))}getRefundManagerConfig(e,t){return this.httpClient.post(`_action/${this.getApiBasePath()}/config/refund-manager`,{salesChannelId:e,orderId:t},{headers:this.getBasicHeaders()}).then(e=>w.handleResponse(e))}}let S=Shopware.Classes.ApiService;var M=class extends S{constructor(e,t,i="mollie"){super(e,t,i)}getPaymentUrl(e={orderId:null}){let t=this.getBasicHeaders();return this.httpClient.post(`_action/${this.getApiBasePath()}/order/payment-url`,JSON.stringify(e),{headers:t}).then(e=>S.handleResponse(e))}};let z=Shopware.Classes.ApiService;var j=class extends z{constructor(e,t,i="mollie"){super(e,t,i)}updatePaymentMethods(){let e=this.getBasicHeaders();return this.httpClient.get(`_action/${this.getApiBasePath()}/payment-method/update-methods`,{headers:e}).then(e=>z.handleResponse(e))}};let P=Shopware.Classes.ApiService;class A extends P{constructor(e,t,i="mollie"){super(e,t,i)}getRefundManagerData(e={orderId:null}){return this.__post("/refund-manager/data",e)}list(e={orderId:null}){return this.__post("/refund/list",e)}refund(e={orderId:null,amount:null,description:"",internalDescription:"",items:[]}){return this.__post("/refund",e)}refundAll(e={orderId:null,description:"",internalDescription:""}){return this.__post("/refund",e)}cancel(e={orderId:null,refundId:null}){return this.__post("/refund/cancel",e)}__post(e="",t={},i={}){return this.httpClient.post(`_action/${this.getApiBasePath()}${e}`,JSON.stringify(t),{headers:this.getBasicHeaders(i)}).then(e=>P.handleResponse(e)).catch(e=>P.handleResponse(e.response))}}let R=Shopware.Classes.ApiService;var T=class extends R{constructor(e,t,i="mollie"){super(e,t,i)}shipOrder(e,t,i,n,a){return this.__post("",{orderId:e,trackingCarrier:t,trackingCode:i,trackingUrl:n,items:a})}shipItem(e={orderId:null,itemId:null,quantity:null,trackingCarrier:null,trackingCode:null,trackingUrl:null}){return this.__post("/item",e)}status(e={orderId:null}){return this.__post("/status",e)}total(e={orderId:null}){return this.__post("/total",e)}__post(e="",t={},i={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/ship${e}`,JSON.stringify(t),{headers:this.getBasicHeaders(i)}).then(e=>R.handleResponse(e))}};let C=Shopware.Classes.ApiService;class E extends C{constructor(e,t,i="mollie"){super(e,t,i)}__post(e="",t={},i={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/support${e}`,JSON.stringify(t),{headers:this.getBasicHeaders(i)}).then(e=>C.handleResponse(e))}request(e,t,i,n,a){return this.__post("/request",{name:e,email:t,recipientLocale:i,subject:n,message:a})}}let I=Shopware.Classes.ApiService;class x extends I{constructor(e,t,i="mollie"){super(e,t,i)}cancel(e={id:null,customerId:null,salesChannelId:null}){return this.__post("/cancel",e)}pause(e={id:null,customerId:null,salesChannelId:null}){return this.__post("/pause",e)}resume(e={id:null,customerId:null,salesChannelId:null}){return this.__post("/resume",e)}skip(e={id:null,customerId:null,salesChannelId:null}){return this.__post("/skip",e)}getUserSubscriptions(e={id:null,salesChannelId:null}){return this.__get("/"+e.id)}cancelByMollieId(e={mollieCustomerId:null,mollieSubscriptionId:null,mandateId:null,salesChannelId:null}){return this.__get(`/cancel/${e.mollieCustomerId}/${e.mollieSubscriptionId}/${e.mandateId}/${e.salesChannelId}`)}__get(e=""){return this.httpClient.get(`_action/${this.getApiBasePath()}/subscriptions${e}`,{headers:this.getBasicHeaders({})}).then(e=>I.handleResponse(e)).catch(e=>I.handleResponse(e.response))}__post(e="",t={},i={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/subscriptions${e}`,JSON.stringify(t),{headers:this.getBasicHeaders(i)}).then(e=>I.handleResponse(e)).catch(e=>I.handleResponse(e.response))}}let D=Shopware.Classes.ApiService;class O extends D{constructor(e,t,i="mollie"){super(e,t,i)}status(e={mollieOrderId:null}){return this.__post("/status",e)}cancel(e={mollieOrderId:null,mollieLineId:null,shopwareLineId:null,canceledQuantity:0,resetStock:!1}){return this.__post("/cancel",e)}__post(e="",t={},i={}){return this.httpClient.post(`_action/${this.getApiBasePath()}/cancel-item${e}`,JSON.stringify(t),{headers:this.getBasicHeaders(i)}).then(e=>D.handleResponse(e)).catch(e=>D.handleResponse(e.response))}}Shopware.Component.extend("mollie-lineitem-subscription-rule","sw-condition-base",{template:'{% block sw_condition_value_content %}\n \n \n{% endblock %}\n',computed:{selectValues(){return[{label:this.$tc("global.sw-condition.condition.yes"),value:!0},{label:this.$tc("global.sw-condition.condition.no"),value:!1}]},isSubscription:{get(){return this.ensureValueExist(),null==this.condition.value.isSubscription&&(this.condition.value.isSubscription=!1),this.condition.value.isSubscription},set(e){this.ensureValueExist(),this.condition.value={...this.condition.value,isSubscription:e}}}}}),Shopware.Component.extend("mollie-cart-subscription-rule","sw-condition-base",{template:'{% block sw_condition_value_content %}\n \n \n{% endblock %}\n',computed:{selectValues(){return[{label:this.$tc("global.sw-condition.condition.yes"),value:!0},{label:this.$tc("global.sw-condition.condition.no"),value:!1}]},isSubscription:{get(){return this.ensureValueExist(),null==this.condition.value.isSubscription&&(this.condition.value.isSubscription=!1),this.condition.value.isSubscription},set(e){this.ensureValueExist(),this.condition.value={...this.condition.value,isSubscription:e}}}}});let{Application:L}=Shopware;L.addServiceProvider("MolliePaymentsConfigService",e=>{let t=L.getContainer("init"),i=L.getContainer("factory").locale.getLastKnownLocale();return new _(t.httpClient,e.loginService,i)}),L.addServiceProvider("MolliePaymentsOrderService",e=>new M(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsPaymentMethodService",e=>new j(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsRefundService",e=>new A(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsShippingService",e=>new T(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsSupportService",e=>new E(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsSubscriptionService",e=>new x(L.getContainer("init").httpClient,e.loginService)),L.addServiceProvider("MolliePaymentsItemCancelService",e=>new O(L.getContainer("init").httpClient,e.loginService)),L.addServiceProviderDecorator("ruleConditionDataProviderService",e=>(e.addCondition("mollie_lineitem_subscription_rule",{component:"mollie-lineitem-subscription-rule",label:"mollie-payments.rules.itemSubscriptionRule",scopes:["lineitem"],group:"item"}),e.addCondition("mollie_cart_subscription_rule",{component:"mollie-cart-subscription-rule",label:"mollie-payments.rules.cartSubscriptionRule",scopes:["cart"],group:"cart"}),e)),L.addServiceProviderDecorator("searchTypeService",e=>(e.upsertType("mollie_subscription",{entityName:"mollie_subscription",placeholderSnippet:"mollie-payments.searchPlaceholder",listingRoute:"mollie.payments.subscriptions"}),e));let V=Object.freeze({MOLLIE_SHIP_ORDER:"action.mollie.order.ship",MOLLIE_REFUND_ORDER:"action.mollie.order.refund"}),{Component:N}=Shopware;N.override("sw-flow-sequence-action",{computed:{modalName(){return this.selectedAction===V.MOLLIE_SHIP_ORDER?"mollie-payments-flowsequence-action-order-ship-modal":this.selectedAction===V.MOLLIE_REFUND_ORDER?"mollie-payments-flowsequence-action-order-refund-modal":this.$super("modalName")},actionDescription(){return{...this.$super("actionDescription"),[V.MOLLIE_SHIP_ORDER]:e=>this.$tc("mollie-payments.sw-flow.actions.shipOrder.editor.description"),[V.MOLLIE_REFUND_ORDER]:e=>this.$tc("mollie-payments.sw-flow.actions.refundOrder.editor.description")}}},methods:{getActionTitle(e){return e===V.MOLLIE_SHIP_ORDER?{value:e,icon:"default-package-open",label:this.$tc("mollie-payments.sw-flow.actions.shipOrder.editor.title")}:e===V.MOLLIE_REFUND_ORDER?{value:e,icon:"default-symbol-euro",label:this.$tc("mollie-payments.sw-flow.actions.refundOrder.editor.title")}:this.$super("getActionTitle",e)}}}),Shopware.Component.override("sw-search-bar-item",{template:'{% block sw_search_bar_item_cms_page %}\n {% parent %}\n\n \n {% block sw_search_bar_item_mollie_subscription_label %}\n \n \n \n \n {% endblock %}\n \n\n{% endblock %}\n'}),i(68958);let{Component:U}=Shopware;U.register("mollie-payments-flowsequence-action-order-ship-modal",{template:'\n
\n \n \n {{ $tc(\'mollie-payments.sw-flow.actions.shipOrder.modal.title\') }}\n \n \n \n \n
\n
\n {{ $tc(\'mollie-payments.sw-flow.actions.shipOrder.modal.description\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.sw-flow.actions.shipOrder.modal.warningConfig\') }}\n
    \n
  • \n {{ $tc(\'mollie-payments.sw-flow.actions.shipOrder.modal.noWarnings\') }}\n
  • \n
\n
    \n
  • {{ warning }}
  • \n
\n
\n
\n \n
\n',inject:["MolliePaymentsConfigService"],props:{sequence:{type:Object,required:!0}},data(){return{tags:[],warnings:[]}},created(){this.createdComponent(),this.MolliePaymentsConfigService.validateFlowBuilder().then(e=>{this.warnings=e.actions.shipping.warnings})},methods:{createdComponent(){this.sequence&&this.sequence.config?this.tags=this.sequence.config.tags:this.tags=[]},onClose(){this.$emit("modal-close")},onAddAction(){let e={...this.sequence,config:{...this.config,tags:this.tags}};this.$emit("process-finish",e)}}}),i(50230);let{Component:F}=Shopware;F.register("mollie-payments-flowsequence-action-order-refund-modal",{template:'\n
\n \n \n {{ $tc(\'mollie-payments.sw-flow.actions.refundOrder.modal.title\') }}\n \n \n \n \n
\n
\n {{ $tc(\'mollie-payments.sw-flow.actions.refundOrder.modal.description\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.sw-flow.actions.refundOrder.modal.warning\') }}\n \n \n {{ $tc(\'mollie-payments.sw-flow.actions.refundOrder.modal.warningConfig\') }}\n \n
\n \n
\n',inject:["MolliePaymentsConfigService"],props:{sequence:{type:Object,required:!0}},data(){return{tags:[]}},created(){this.createdComponent()},methods:{createdComponent(){this.sequence&&this.sequence.config?this.tags=this.sequence.config.tags:this.tags=[]},onClose(){this.$emit("modal-close")},onAddAction(){let e={...this.sequence,config:{...this.config,tags:this.tags}};this.$emit("process-finish",e)}}}),i(41825);let{Component:B}=Shopware;B.register("mollie-credit-card-logo",{template:'{% block credit_card_logo %}\n
\n \n \n \n \n
\n{% endblock %}\n',props:{creditCardCompany:{type:String,required:!0,default:""}},methods:{getImageNameForCreditcard(e){switch(e){case"American Express":return"amex";case"Carta Si":return"cartasi";case"Carte Bleue":return"cartebancaire";case"Maestro":return"maestro";case"Mastercard":return"mastercard";case"Visa":return"visa";default:return"creditcard"}}},computed:{creditCardComponentName(){let e=this.getImageNameForCreditcard(this.creditCardCompany);return`mollie-credit-card-logo-${e}`}}});var H={_searchable:!0,description:{_searchable:!0,_score:500}};i(14461);let{Application:K}=Shopware;class q{buildColumns(){let e=K.getApplicationRoot();return e?[{property:"createdAt",label:e.$tc("mollie-payments.subscriptions.list.columns.createdAt"),allowResize:!0},{property:"customerId",label:e.$tc("mollie-payments.subscriptions.list.columns.customer"),allowResize:!0},{property:"description",label:e.$tc("mollie-payments.subscriptions.list.columns.description"),allowResize:!0},{property:"status",label:e.$tc("mollie-payments.subscriptions.list.columns.status"),allowResize:!0,sortable:!0},{property:"amount",label:e.$tc("mollie-payments.subscriptions.list.columns.amount"),allowResize:!0,align:"right"},{property:"nextPaymentAt",label:e.$tc("mollie-payments.subscriptions.list.columns.nextPaymentAt"),allowResize:!0},{property:"lastRemindedAt",label:e.$tc("mollie-payments.subscriptions.list.columns.prePaymentReminder"),allowResize:!0},{property:"canceledAt",dataIndex:"canceledAt",label:e.$tc("mollie-payments.subscriptions.list.columns.canceledAt"),visible:!0}]:[]}}class ${constructor(e){this._app=e}getStatusTranslation(e){return((""===e||null===e)&&(e=""),["pending","active","canceled","suspended","completed","paused","resumed","skipped"].includes(e))?this._app.$tc("mollie-payments.subscriptions.status."+e):e}getStatusColor(e){return""===e||null===e?"neutral":"active"===e||"resumed"===e?"success":"canceled"===e||"suspended"===e||"completed"===e?"neutral":"skipped"===e?"info":"pending"===e||"paused"===e?"warning":"danger"}isCancellationAllowed(e){return"canceled"!==e&&"pending"!==e}isSkipAllowed(e){return"active"===e||"resumed"===e}isPauseAllowed(e){return"active"===e||"resumed"===e}isResumeAllowed(e){return"paused"===e||"canceled"===e}}let{Component:W,Mixin:G,Application:Y,Filter:Q}=Shopware,{Criteria:Z}=Shopware.Data;W.register("mollie-subscriptions-list",{template:'{% block mollie_payments_subscription_list %}\n \n {% block mollie_payments_subscription_list_search_bar %}\n \n {% endblock %}\n\n {% block mollie_payments_subscription_list_smart_bar_header %}\n \n {% endblock %}\n \n\n \n \n{% endblock %}\n',inject:["systemConfigApiService","MolliePaymentsSubscriptionService","repositoryFactory","acl"],mixins:[G.getByName("notification"),G.getByName("listing"),G.getByName("placeholder")],data(){return{isLoading:!0,systemConfig:null,subscriptions:null,sortBy:"createdAt",sortDirection:"DESC",naturalSorting:!0,showHelp:!1,searchConfigEntity:"mollie_subscription"}},metaInfo(){return{title:this.$createTitle()}},computed:{repoSubscriptions(){return this.repositoryFactory.create("mollie_subscription")},subscriptionService(){return new $(Y.getApplicationRoot())},prePaymentReminderEmail(){return this.systemConfig&&void 0!==this.systemConfig["MolliePayments.config.prePaymentReminderEmail"]?this.systemConfig["MolliePayments.config.prePaymentReminderEmail"]:null},totalSubscriptions(){return this.subscriptions.length},compatibilityIcons(){return{refresh:W.getComponentRegistry().has("icons-regular-undo")?"regular-undo":"default-arrow-360-left"}},currencyFilter(){return Q.getByName("currency")},dateFilter(){return Q.getByName("date")}},methods:{gridColumns(){return new q().buildColumns()},async getList(){this.isLoading=!0,this.naturalSorting="createdAt"===this.sortBy;let e=new Z;"addQueryScores"in this?e=await this.addQueryScores(this.term,e):e.setTerm(this.term),e.addSorting(Z.sort(this.sortBy,this.sortDirection,this.naturalSorting)),e.addAssociation("customer"),e.addAssociation("currency"),this.repoSubscriptions.search(e,Shopware.Context.api).then(e=>{this.subscriptions=e,this.isLoading=!1})},statusTranslation(e){return this.subscriptionService.getStatusTranslation(e)},statusColor(e){return this.subscriptionService.getStatusColor(e)}}}),i(4749);let{Component:J,Mixin:X,Application:ee,ApiService:et,Filter:ei}=Shopware,{Criteria:en}=Shopware.Data;J.register("mollie-subscriptions-detail",{template:'{% block sw_order_detail %}\n \n\n \n\n {% block sw_order_detail_actions %}\n \n {% endblock %}\n\n \n \n{% endblock %}\n',inject:["MolliePaymentsSubscriptionService","repositoryFactory","acl"],mixins:[X.getByName("notification"),X.getByName("placeholder")],data(){return{isLoading:!0,allowPauseResume:!1,allowSkip:!1,showConfirmCancel:!1,showConfirmPause:!1,showConfirmResume:!1,showConfirmSkip:!1,subscription:null,history:[],customerFullName:"",translatedStatus:"",formattedCreateAt:"",formattedNextPaymentAt:"",formattedLastRemindedAt:"",formattedCanceledAt:""}},metaInfo(){return{title:this.$createTitle()}},computed:{repoSubscriptions(){return this.repositoryFactory.create("mollie_subscription")},subscriptionService(){return new $(ee.getApplicationRoot())},subscriptionId(){return this.$route.params.id},isAclEditAllowed(){return this.acl.can("mollie_subscription:update")},isAclCancelAllowed(){return this.acl.can("mollie_subscription_custom:cancel")},isCancellationAllowed(){return null!==this.subscription&&this.subscriptionService.isCancellationAllowed(this.subscription.status)},isPauseAllowed(){return null!==this.subscription&&this.subscriptionService.isPauseAllowed(this.subscription.status)},isResumeAllowed(){return null!==this.subscription&&this.subscriptionService.isResumeAllowed(this.subscription.status)},isSkipAllowed(){return null!==this.subscription&&this.subscriptionService.isSkipAllowed(this.subscription.status)},cardTitleHistory(){return this.$tc("mollie-payments.subscriptions.detail.history.cardTitle")+" ("+this.history.length+")"},dateFilter(){return ei.getByName("date")}},created(){this.createdComponent()},methods:{createdComponent(){this.loadDetails()},loadDetails(){this.isLoading=!0;let e=new en;e.addFilter(en.equals("id",this.subscriptionId)),e.addAssociation("addresses"),e.addAssociation("historyEntries"),e.addAssociation("customer"),e.addAssociation("currency"),this.repoSubscriptions.search(e,Shopware.Context.api).then(e=>{this.subscription=e[0],this.customerFullName=this.subscription.customer.firstName+" "+this.subscription.customer.lastName,this.translatedStatus=this.statusTranslation(this.subscription.status),this.formattedCreateAt=this.getFormattedDate(this.subscription.createdAt),this.formattedNextPaymentAt=this.getFormattedDate(this.subscription.nextPaymentAt),this.formattedLastRemindedAt=this.getFormattedDate(this.subscription.lastRemindedAt),this.formattedCanceledAt=this.getFormattedDate(this.subscription.canceledAt),this.history=this.subscription.historyEntries,this.history.sort(function(e,t){return new Date(t.createdAt)-new Date(e.createdAt)}),this.history.forEach(e=>{e.statusFromTranslated=this.subscriptionService.getStatusTranslation(e.statusFrom),e.statusToTranslated=this.subscriptionService.getStatusTranslation(e.statusTo)}),this.isLoading=!1}),et.getByName("systemConfigApiService").getValues("MolliePayments").then(e=>{this.allowPauseResume=e["MolliePayments.config.subscriptionsAllowPauseResume"],this.allowSkip=e["MolliePayments.config.subscriptionsAllowSkip"]})},statusTranslation(e){return this.subscriptionService.getStatusTranslation(e)},statusColor(e){return this.subscriptionService.getStatusColor(e)},getFormattedDate(e){if(null===e||""===e)return"";let t=Shopware;if(t.Utils.format.dateWithUserTimezone){let i=t.Utils.format.dateWithUserTimezone(new Date(e));return i.toLocaleDateString()+" "+i.toLocaleTimeString()}return t.Utils.format.date(new Date(e))},btnCancel_Click(){this.isAclCancelAllowed&&(this.showConfirmCancel=!0)},btnPause_Click(){this.showConfirmPause=!0},btnResume_Click(){this.showConfirmResume=!0},btnSkip_Click(){this.showConfirmSkip=!0},btnCloseAnyModal_Click(){this.showConfirmCancel=!1,this.showConfirmPause=!1,this.showConfirmResume=!1,this.showConfirmSkip=!1},btnConfirmCancel_Click(){this.showConfirmCancel=!1,this.isAclCancelAllowed&&this.MolliePaymentsSubscriptionService.cancel({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.cancelSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmPause_Click(){this.showConfirmPause=!1,this.MolliePaymentsSubscriptionService.pause({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.pauseSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmResume_Click(){this.showConfirmResume=!1,this.MolliePaymentsSubscriptionService.resume({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.resumeSuccess")})):this.createNotificationError({message:e.errors[0]})})},btnConfirmSkip_Click(){this.showConfirmSkip=!1,this.MolliePaymentsSubscriptionService.skip({id:this.subscription.id}).then(e=>{e.success?(this.loadDetails(),this.createNotificationSuccess({message:this.$tc("mollie-payments.subscriptions.alerts.skipSuccess")})):this.createNotificationError({message:e.errors[0]})})}}});let{Module:ea,Plugin:eo,Service:er}=Shopware,es=eo.addBootPromise();er("MolliePaymentsConfigService").getSubscriptionConfig().then(e=>{let t=[];!0===e.enabled&&t.push({id:"mollie-subscriptions",label:"mollie-payments.subscriptions.navigation.title",path:"mollie.payments.subscriptions",parent:"sw-order",position:10,privilege:"mollie_subscription:read"}),ea.register("mollie-payments",{type:"plugin",title:"mollie-payments.general.mainMenuItemGeneral",description:"mollie-payments.general.descriptionTextModule",version:"1.0.0",targetVersion:"1.0.0",color:"#333",icon:"regular-shopping-bag",entity:"mollie_subscription",routes:{subscriptions:{component:"mollie-subscriptions-list",path:"subscriptions",meta:{privilege:"mollie_subscription:read"}},subscription_detail:{component:"mollie-subscriptions-detail",path:"subscription/detail/:id",props:{default:e=>({subscriptionId:e.params.id})},meta:{parentPath:"mollie.payments.subscriptions",privilege:"mollie_subscription:read"}}},navigation:t,defaultSearchConfiguration:H})}).finally(()=>{es()}),Shopware.Component.override("sw-customer-detail",{template:'{% block sw_customer_detail_content_tab_after %}\n {% parent %}\n \n {{ $tc(\'mollie-payments.subscriptions.navigation.title\')}}\n \n{% endblock %}\n',computed:{subscriptionRoute(){return{name:"sw.customer.detail.mollie-subscriptions",params:{id:this.customerId},query:{edit:this.editMode}}},hasMollieData(){return null!==this.customer&&this.customer.customFields?.mollie_payments?.customer_ids!==void 0}}}),Shopware.Component.register("sw-customer-mollie-subscriptions",{template:'\n\n \n\n \n\n \n\n \n\n \n\n \n \n \n\n\n\n\n',props:{customer:{type:Object,required:!0}},inject:["MolliePaymentsSubscriptionService"],data(){return{isLoading:!1,subscriptions:[]}},created(){this.createdComponent()},computed:{columns(){return[{property:"id",label:"ID",sortable:!0},{property:"status",label:this.$tc("mollie-payments.subscriptions.list.columns.status"),sortable:!0},{property:"description",label:this.$tc("mollie-payments.subscriptions.list.columns.description")},{property:"startDate",label:this.$tc("mollie-payments.subscriptions.list.columns.createdAt"),sortable:!0},{property:"interval",label:"Interval",sortable:!0},{property:"nextPaymentDate",label:this.$tc("mollie-payments.subscriptions.list.columns.nextPaymentAt"),sortable:!0},{property:"canceledAt",label:this.$tc("mollie-payments.subscriptions.list.columns.canceledAt"),sortable:!0},{property:"amount",label:this.$tc("mollie-payments.subscriptions.list.columns.amount"),sortable:!0}]},assetFilter(){return Shopware.Filter.getByName("asset")}},watch:{async customer(){await this.createdComponent()}},methods:{async cancelSubscription(e){this.isLoading=!0;let t=(await this.MolliePaymentsSubscriptionService.cancelByMollieId({mollieCustomerId:e.customerId,mollieSubscriptionId:e.id,mandateId:e.mandateId,salesChannelId:this.customer.salesChannelId})).subscription;void 0!==t&&this.subscriptions.forEach((e,i)=>{e.id===t.id&&(this.subscriptions[i].status=t.status)}),this.isLoading=!1},async createdComponent(){this.isLoading=!0;let e=await this.MolliePaymentsSubscriptionService.getUserSubscriptions({id:this.customer.id});this.subscriptions=e.subscriptions,this.isLoading=!1},statusColor(e){return""===e||null===e?"neutral":"active"===e||"resumed"===e?"success":"canceled"===e||"suspended"===e||"completed"===e?"neutral":"skipped"===e?"info":"pending"===e||"paused"===e?"warning":"danger"}}});let{Module:el}=Shopware;el.register("mollie-sw-customer-detail",{type:"plugin",name:"customer-route",title:"mollie-payments.pluginTitle",description:"mollie-payments.pluginDescription",version:"1.0.0",targetVersion:"1.0.0",color:"#333",icon:"default-action-settings",routeMiddleware(e,t){"sw.customer.detail"===t.name&&t.children.push({name:"sw.customer.detail.mollie-subscriptions",path:"/sw/customer/detail/:id/mollie-subscriptions",component:"sw-customer-mollie-subscriptions",meta:{parentPath:"sw.customer.index"}}),e(t)}}),Shopware.Component.override("sw-product-detail",{template:'{% block sw_product_detail_content_tabs_cross_selling %}\n {% parent %}\n\n \n Mollie\n \n{% endblock %}'}),i(6683),Shopware.Component.register("sw-product-detail-mollie",{template:'
\n {% block sw_product_detail_mollie_vouchers %}\n \n \n\n \n \n {{ $tc(\'mollie-payments.vouchers.VOUCHER_INFO_TITLE\') }}\n \n \n\n \n \n\n \n

\n {{ $tc(\'mollie-payments.vouchers.VOUCHER_INFO_DESCRIPTION\') }}\n

\n
\n\n \n
\n \n {{ $tc(\'mollie-payments.vouchers.VOUCHER_BTN_READMORE\') }}\n \n
\n\n \n\n \n \n \n\n \n\n \n \n {{ $tc(\'mollie-payments.vouchers.VOUCHER_INFO_DEFAULTLANGUAGE\') }}\n \n \n\n
\n
\n {% endblock %}\n\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n\n {% block sw_product_detail_mollie_subscription %}\n \n \n \n \n {{ $tc(\'mollie-payments.subscriptions.product.title\') }}\n \n \n \n

\n {{ $tc(\'mollie-payments.subscriptions.product.description\') }}\n

\n
\n \n
\n \n {{ $tc(\'mollie-payments.subscriptions.product.btnReadMore\') }}\n \n
\n\n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n \n \n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n \n \n \n \n \n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n \n \n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n \n {{ $tc(\'mollie-payments.subscriptions.product.infoDefaultLanguage\') }}\n \n \n
\n
\n {% endblock %}\n
\n',inject:["repositoryFactory"],metaInfo(){return{title:"Mollie"}},data(){return{}},watch:{product(){this.initFields()},parentProduct(){this.initFields()}},created(){this.initFields()},computed:{productId(){return this.$route.params.id},product(){let e=Shopware.State.get("swProductDetail");return void 0===e&&(e=Shopware.Store.get("swProductDetail")),e.product},parentProduct(){let e=Shopware.State.get("swProductDetail");return void 0===e&&(e=Shopware.Store.get("swProductDetail")),e.parentProduct},isLoading(){let e=Shopware.State.get("swProductDetail");return void 0===e&&(e=Shopware.Store.get("swProductDetail")),e.isLoading},context(){let e=Shopware.State.get("context");return void 0===e&&(e=Shopware.Store.get("context")),e},languageId(){return this.context.languageId},systemLanguageId(){return this.context.systemLanguageId},isSystemDefaultLanguage(){return this.context.isSystemDefaultLanguage},voucherTypes(){return[{value:1,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_ECO")},{value:2,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_MEAL")},{value:3,label:this.$tc("mollie-payments.vouchers.VOUCHER_TYPE_VALUE_VOUCHER")}]},voucherTypeNONE(){return"0"},subscriptionIntervalTypes(){return[{value:"days",label:this.$tc("mollie-payments.subscriptions.TYPE_DAYS")},{value:"weeks",label:this.$tc("mollie-payments.subscriptions.TYPE_WEEKS")},{value:"months",label:this.$tc("mollie-payments.subscriptions.TYPE_MONTHS")}]},isDefaultLanguage(){return this.languageId===this.systemLanguageId}},methods:{initFields(){this.product&&(this.product.customFields||(this.product.customFields={}),this.product.customFields.mollie_payments_product_voucher_type&&!Array.isArray(this.product.customFields.mollie_payments_product_voucher_type)&&(this.product.customFields.mollie_payments_product_voucher_type=[this.product.customFields.mollie_payments_product_voucher_type])),this.parentProduct&&(this.parentProduct.customFields||(this.parentProduct.customFields={}),this.parentProduct.customFields.mollie_payments_product_voucher_type&&!Array.isArray(this.parentProduct.customFields.mollie_payments_product_voucher_type)&&(this.parentProduct.customFields.mollie_payments_product_voucher_type=[this.parentProduct.customFields.mollie_payments_product_voucher_type]))}}});let{Module:eu}=Shopware;eu.register("mollie-sw-product-detail",{type:"plugin",name:"MolliePayments",title:"mollie-payments.pluginTitle",description:"mollie-payments.pluginDescription",version:"1.0.0",targetVersion:"1.0.0",color:"#333",icon:"default-action-settings",routeMiddleware(e,t){"sw.product.detail"===t.name&&t.children.push({name:"sw.product.detail.mollie",path:"/sw/product/detail/:id/mollie",component:"sw-product-detail-mollie",meta:{parentPath:"sw.product.index"}}),e(t)}}),i(1174),i(48245);class ed{constructor(e){if(this._audience="",this._countryCode="",this._feeRegion="",this._holder="",this._label="",this._number="",this._security="",null===e)return;return this._audience=this._convertString(e.creditCardAudience),this._countryCode=this._convertString(e.creditCardCountryCode),this._feeRegion=this._convertString(e.creditCardFeeRegion),this._holder=this._convertString(e.creditCardHolder),this._label=this._convertString(e.creditCardLabel),this._number=this._convertString(e.creditCardNumber),this._security=this._convertString(e.creditCardSecurity),null}hasCreditCardData(){return!!this._audience&&!!this._countryCode&&!!this._feeRegion&&!!this._holder&&!!this._label&&!!this._number}getAudience(){return this._audience}getCountryCode(){return this._countryCode}getFeeRegion(){return this._feeRegion}getHolder(){return this._holder}getLabel(){return this._label}getNumber(){return this._number}getSecurity(){return this._security}_convertString(e){return null==e?"":String(e)}}class ec{constructor(e){if(this._orderId="",this._paymentId="",this._swSubscriptionId="",this._creditCardAttributes=null,this._paymentRef=null,this._isMolliePayments=!1,null===e)return;let t=e.transactions,i=t?.first();if(t.length>1&&t.forEach(function(e){e.createdAt>i.createdAt&&(i=e)}),!i||!i.paymentMethod?.customFields?.mollie_payment_method_name||(this._isMolliePayments=!0,this.customFields=e.customFields,null===this.customFields||void 0===this.customFields||void 0===this.customFields.mollie_payments||null===this.customFields.mollie_payments))return;let n=this.customFields.mollie_payments;this._orderId=this._convertString(n.order_id),this._paymentId=this._convertString(n.payment_id),this._swSubscriptionId=this._convertString(n.swSubscriptionId),this._paymentRef=this._convertString(n.third_party_payment_id),this._creditCardAttributes=new ed(n)}isMollieOrder(){return this._isMolliePayments&&null!==this.customFields&&"mollie_payments"in this.customFields}getCreditCardAttributes(){return this._creditCardAttributes}getOrderId(){return this._orderId}getPaymentId(){return this._paymentId}getMollieID(){return""!==this.getOrderId()?this.getOrderId():""!==this.getPaymentId()?this.getPaymentId():null}isSubscription(){return""!==this.getSwSubscriptionId()}getSwSubscriptionId(){return this._swSubscriptionId}getPaymentRef(){return this._paymentRef}_convertString(e){return null==e?"":String(e)}}class em{constructor(e,t){this._configService=e,this._acl=t}async isRefundManagerAvailable(e,t){if("authorized"===(t?.transactions?.[0]?.stateMachineState?.technicalName??"unknown")||!this._acl.can("mollie_refund_manager:read"))return!1;let i=!1;return await this._configService.getRefundManagerConfig(e,t.id).then(e=>{i=e.enabled}),i}}class ep{constructor(e){this._shippingService=e}async isShippingPossible(e){if(""===new ec(e).getOrderId())return!1;let t=await this.getShippableItems(e);for(let e=0;e0)return!0;return!1}async getShippableItems(e){await this._shippingService.status({orderId:e.id}).then(e=>{this.shippedLineItems=e});let t=[];for(let i=0;i\n {% block sw_order_line_items_grid_line_item_filter %}\n {% parent %}\n {% endblock %}\n {#\n ===================================================================================================================\n MOLLIE ACTIONS\n ===================================================================================================================\n #}\n {% block sw_order_line_items_grid_mollie_actions %}\n
\n \n {% block sw_order_line_items_grid_mollie_actions_button %}\n \n \n {{ $tc(\'mollie-payments.general.btnMollieActions\') }} ({{ possibleActionsCount }})\n \n {% endblock %}\n {% block sw_order_line_items_grid_mollie_actions_context_button %}\n \n \n {% block sw_order_line_items_grid_mollie_actions_dropdown %}\n {% block sw_order_line_items_grid_mollie_actions_dropdown_ship %}\n \n {{ $tc(\'mollie-payments.general.shipThroughMollie\') }}\n \n {% endblock %}\n {% block sw_order_line_items_grid_mollie_actions_dropdown_refund %}\n \n {{ $tc(\'sw-order.detailExtended.refundManager.btnOpenRefundManager\') }}\n \n {% endblock %}\n {% endblock %}\n \n {% endblock %}\n \n
\n {% endblock %}\n \n\n \n {#\n ===================================================================================================================\n REFUND MANAGER\n ===================================================================================================================\n #}\n \n \n \n \n \n {#\n ===================================================================================================================\n SHIPPING\n ===================================================================================================================\n #}\n \n \n \n \n \n \n{% endblock %}\n\n\n{% block sw_order_line_items_grid_grid_columns %}\n {% parent %}\n \n \n{% endblock %}\n\n\n{% block sw_order_line_items_grid_grid_actions_modals_items %}\n {% parent %}\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal %}\n \n\n \n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_product %}\n
{{ $tc(\'mollie-payments.modals.shipping.item.label\') }} {{ item.label }}
\n {% endblock %}\n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_description %}\n \n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary %}\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary_shipped %}\n
{{ $tc(\'mollie-payments.modals.shipping.item.summary.shipped\') }}
\n
{{ shippedQuantity(item) }}
\n {% endblock %}\n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_summary_shippable %}\n
{{ $tc(\'mollie-payments.modals.shipping.item.summary.shippable\') }}
\n
{{ shippableQuantity(item) }}
\n {% endblock %}\n {% endblock %}\n
\n {% endblock %}\n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_quantity %}\n \n \n \n \n {% endblock %}\n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_tracking %}\n \n \n \n \n {% endblock %}\n
\n\n \n
\n {% endblock %}\n {% block sw_order_line_items_grid_grid_mollie_cancel_item_modal %}\n \n\n \n {% endblock %}\n{% endblock %}\n\n{% block sw_order_line_items_grid_grid_actions_show %}\n {% parent %}\n \n {{ $tc(\'mollie-payments.general.shipThroughMollie\') }}\n \n\n \n {{ $tc(\'mollie-payments.general.cancelMollieItem\') }}\n \n{% endblock %}\n',mixins:[eh.getByName("notification")],inject:["MolliePaymentsConfigService","MolliePaymentsShippingService","MolliePaymentsItemCancelService","acl"],props:{shopwareVersion:{type:Number,default:6.4}},data(){return{isLoading:!1,configShowRefundManager:!0,showRefundModal:!1,isRefundManagerPossible:!1,isShippingPossible:!1,showShipOrderModal:!1,isShipOrderLoading:!1,isShipItemLoading:!1,shipQuantity:0,showShipItemModal:null,cancelItemModal:null,shippingStatus:null,cancelStatus:null,tracking:{carrier:"",code:"",url:""},showTrackingInfo:!1,refundedManagerService:null,shippingManagerService:null,EVENT_TOGGLE_REFUND_MANAGER:"toggle-refund-manager-modal"}},computed:{getLineItemColumns(){let e=this.$super("getLineItemColumns");return e.push({property:"shippedQuantity",label:this.$tc("sw-order.detailExtended.columnShipped"),allowResize:!1,align:"right",inlineEdit:!1,width:"100px"}),e.push({property:"canceledQuantity",label:this.$tc("sw-order.detailExtended.columnCanceled"),allowResize:!1,align:"right",inlineEdit:!1,width:"100px"}),e},isMollieOrder(){return new ec(this.order).isMollieOrder()},mollieId(){return new ec(this.order).getMollieID()},possibleActionsCount(){let e=0;return this.isShippingPossible&&(e+=1),this.isRefundManagerPossible&&(e+=1),e}},created(){this.createdComponent()},methods:{createdComponent(){this.isMollieOrder&&(this.$root&&this.$root.$on?this.$root.$on(ef.EventShippedOrder,()=>{this.onCloseShipOrderModal()}):Shopware.Utils.EventBus.on(ef.EventShippedOrder,()=>{this.onCloseShipOrderModal()}),this.refundedManagerService=new em(this.MolliePaymentsConfigService,this.acl),this.shippingManagerService=new ep(this.MolliePaymentsShippingService),this.reloadData())},async reloadData(){this.isShippingPossible=await this.shippingManagerService?.isShippingPossible(this.order)||!1,this.isRefundManagerPossible=await this.refundedManagerService?.isRefundManagerAvailable(this.order.salesChannelId,this.order.id)||!1,await this.loadMollieShippingStatus(),await this.loadMollieCancelStatus()},onOpenRefundManager(){this.showRefundModal=!0},onCloseRefundManager(){this.showRefundModal=!1,location.reload()},onOpenShipOrderModal(){this.showShipOrderModal=!0},onCloseShipOrderModal(){this.showShipOrderModal=!1,this.reloadData()},onOpenShipItemModal(e){this.showShipItemModal=e.id,this.updateTrackingPrefilling()},onOpenCancelItemModal(e){this.cancelItemModal=e.id},closeCancelItemModal(){this.cancelItemModal=null},onCloseShipItemModal(){this.isShipItemLoading=!1,this.showShipItemModal=!1,this.shipQuantity=0,this.resetTracking(),this.reloadData()},async loadMollieShippingStatus(){await this.MolliePaymentsShippingService.status({orderId:this.order.id}).then(e=>{this.shippingStatus=e})},async loadMollieCancelStatus(){await this.MolliePaymentsItemCancelService.status({mollieOrderId:this.mollieId}).then(e=>{this.cancelStatus=e})},onConfirmShipItem(e){if(0===this.shipQuantity){this.createNotificationError({message:this.$tc("mollie-payments.modals.shipping.item.noQuantity")});return}if(this.showTrackingInfo&&!this.validateTracking()){this.createNotificationError({message:this.$tc("mollie-payments.modals.shipping.tracking.invalid")});return}!0!==this.isShipItemLoading&&(this.isShipItemLoading=!0,this.MolliePaymentsShippingService.shipItem({orderId:this.order.id,itemId:e.id,quantity:this.shipQuantity,trackingCarrier:this.tracking.carrier,trackingCode:this.tracking.code,trackingUrl:this.tracking.url}).then(()=>{this.isShipItemLoading=!1,this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.shipping.item.success")}),this.onCloseShipItemModal(),this.$root.$emit(ef.EventShippedOrder)}).then(()=>{this.$emit("ship-item-success")}).catch(e=>{this.isShipItemLoading=!1,this.createNotificationError({message:e.response.data.message})}))},setMaxQuantity(e){this.shipQuantity=this.shippableQuantity(e)},isShippable(e){return this.shippableQuantity(e)>0},shippableQuantity(e){if(null===this.shippingStatus||void 0===this.shippingStatus)return"~";let t=this.shippingStatus[e.id];return null==t?"~":t.quantityShippable},shippedQuantity(e){if(null===this.shippingStatus||void 0===this.shippingStatus)return"~";let t=this.shippingStatus[e.id];return null==t?"~":t.quantityShipped},canceledQuantity(e){if(void 0===this.cancelStatus||null===this.cancelStatus)return"~";let t=this.cancelStatus[e.id];return null==t?"~":t.quantityCanceled},isCancelable(e){if(void 0===this.cancelStatus||null===this.cancelStatus)return!1;let t=this.cancelStatus[e.id];return null!=t&&t.isCancelable},getCancelData(e){if(void 0===this.cancelStatus||null===this.cancelStatus)return{};let t=this.cancelStatus[e.id];return void 0===t?{}:(t.shopwareItemId=e.id,t.label=e.label,t.payload=e.payload,t)},updateTrackingPrefilling(){if(this.order.deliveries.length){let e=this.order.deliveries.first();this.showTrackingInfo=e.trackingCodes.length>=1}else this.showTrackingInfo=!1},validateTracking(){return!eb.isEmptyOrSpaces(this.tracking.carrier)&&!eb.isEmptyOrSpaces(this.tracking.code)},resetTracking(){this.showTrackingInfo=!1,this.tracking={carrier:"",code:"",url:""}}}}),i(52977);let{Component:ek}=Shopware;ek.override("sw-order-user-card",{template:'\n{% block sw_order_detail_base_secondary_info_payment %}\n {% parent %}\n\n \n{% endblock %}\n',inject:["MolliePaymentsOrderService"],data(){return{isMolliePaymentUrlLoading:!1,molliePaymentUrl:null,molliePaymentUrlCopied:!1}},computed:{isMollieOrder(){return new ec(this.currentOrder).isMollieOrder()},hasCreditCardData(){return this._creditCardData().hasCreditCardData()},creditCardLabel(){return this._creditCardData().getLabel()},creditCardNumber(){return"**** **** **** "+this._creditCardData().getNumber()},creditCardHolder(){return this._creditCardData().getHolder()},mollieOrderId(){return new ec(this.currentOrder).getMollieID()},mollieThirdPartyPaymentId(){return new ec(this.currentOrder).getPaymentRef()},isSubscription(){return new ec(this.currentOrder).isSubscription()},subscriptionId(){return new ec(this.currentOrder).getSwSubscriptionId()},hasPaymentLink(){return""!==this.molliePaymentUrl}},created(){this.createdComponent()},methods:{createdComponent(){this.$super("createdComponent"),this.molliePaymentUrl="",this.mollieOrderId&&(this.isMolliePaymentUrlLoading=!0,this.MolliePaymentsOrderService.getPaymentUrl({orderId:this.currentOrder.id}).then(e=>{this.molliePaymentUrl=null!==e.url?e.url:""}).finally(()=>{this.isMolliePaymentUrlLoading=!1}))},_creditCardData(){return new ec(this.currentOrder).getCreditCardAttributes()},copyPaymentUrlToClipboard(){Shopware.Utils.dom.copyToClipboard(this.molliePaymentUrl),this.molliePaymentUrlCopied=!0},onMolliePaymentUrlProcessFinished(e){this.molliePaymentUrlCopied=e}}});let{Component:ev,Mixin:ey,Filter:ew}=Shopware;ev.override("sw-order-detail-base",{template:'\n{% block sw_order_detail_base_line_items_summary_entries %}\n {% parent %}\n
\n {{ $tc(\'sw-order.detailExtended.totalRefunds\') }}\n
\n
\n {{ currencyFilter( refundedAmount, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n\n
\n {{ $tc(\'sw-order.detailExtended.totalRefundsPending\') }}\n
\n
\n {{ currencyFilter( refundAmountPending, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n\n
\n {{ $tc(\'sw-order.detailExtended.totalShipments\', 0, { quantity: shippedQuantity }) }}\n
\n
\n {{ currencyFilter( shippedAmount, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n{% endblock %}\n\n',mixins:[ey.getByName("notification")],inject:["MolliePaymentsRefundService","MolliePaymentsShippingService"],data(){return{remainingAmount:0,refundedAmount:0,voucherAmount:0,refundAmountPending:0,existingRefunds:[],shippedAmount:0,shippedQuantity:0}},computed:{isMollieOrder(){return new ec(this.order).isMollieOrder()},currencyFilter(){return ew.getByName("currency")}},watch:{order(){this.loadMollieData()}},methods:{createdComponent(){this.$super("createdComponent"),this.$root.$on(ef.EventShippedOrder,()=>{this.loadMollieData()}),this.loadMollieData()},loadMollieData(){this.isMollieOrder&&(this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(e=>{this.remainingAmount=e.totals.remaining,this.refundedAmount=e.totals.refunded,this.voucherAmount=e.totals.voucherAmount,this.refundAmountPending=e.totals.pendingRefunds,this.existingRefunds=e.refunds}).catch(e=>{this.createNotificationError({message:e.message})}),this.MolliePaymentsShippingService.total({orderId:this.order.id}).then(e=>{this.shippedAmount=Math.round(100*e.amount)/100,this.shippedQuantity=e.quantity}))}}}),i(4473);let{Component:e_,Mixin:eS,Filter:eM}=Shopware;e_.override("sw-order-detail-general",{template:'\n{% block sw_order_detail_general_info_card %}\n {% parent %}\n\n \n\n \n {% block sw_order_detail_general_mollie_refund_manager %}\n \n \n \n \n \n {% endblock %}\n\n \n {% block sw_order_detail_general_mollie_shipping %}\n \n \n \n \n \n {% endblock %}\n\n \n {% block sw_order_detail_general_mollie_info %}\n \n
\n {% block sw_order_detail_general_mollie_info_property_creditcard %}\n
\n
\n {{ $tc(\'sw-order.detailExtended.titleCreditCardData\') }}\n
\n
\n \n {{ creditCardLabel }}\n \n
\n
\n {{ creditCardNumber }}\n
\n
\n {{ creditCardHolder }}\n
\n
\n {% endblock %}\n {% block sw_order_detail_general_mollie_info_property_orderid %}\n
\n
\n {{ $tc(\'sw-order.detailExtended.labelMollieOrderId\') }}\n
\n
\n {{ mollieOrderId }}\n
\n \n \n {{ $tc(\'sw-order.detailExtended.subscriptionBadge\') }}\n \n \n
\n
\n
\n {% endblock %}\n {% block sw_order_detail_general_mollie_info_property_paymentref %}\n
\n
\n {{ $tc(\'sw-order.detailExtended.labelMollieThirdPartyPaymentId\') }}\n
\n
\n {{ mollieThirdPartyPaymentId }}\n
\n
\n {% endblock %}\n {% block sw_order_detail_general_mollie_info_property_paymentlink %}\n
\n
\n {{ $tc(\'sw-order.detailExtended.labelMolliePaymentLink\') }}\n
\n
\n \n {{ $tc(\'sw-order.detailExtended.buttonMolliePaymentLink\') }}\n \n
\n
\n {% endblock %}\n
\n
\n \n {% block sw_order_detail_general_mollie_info_action_buttons %}\n \n {% block sw_order_detail_general_mollie_info_action_buttons_order_shipping %}\n \n {{ $tc(\'mollie-payments.general.shipThroughMollie\') }}\n {% endblock %}\n {% block sw_order_detail_general_mollie_info_action_buttons_refund_manager %}\n \n {{ $tc(\'sw-order.detailExtended.refundManager.btnOpenRefundManager\') }}\n {% endblock %}\n \n {% endblock %}\n
\n
\n {% endblock %}\n\n
\n\n{% endblock %}\n\n\n{% block sw_order_detail_general_line_items_summary_entries %}\n {% parent %}\n\n
\n {{ $tc(\'sw-order.detailExtended.totalRefunds\') }}\n
\n
\n {{ currencyFilter( refundedAmount, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n
\n {{ $tc(\'sw-order.detailExtended.totalRefundsPending\') }}\n
\n
\n {{ currencyFilter( refundAmountPending, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n
\n {{ $tc(\'sw-order.detailExtended.totalShipments\', 0, { quantity: shippedQuantity }) }}\n
\n
\n {{ currencyFilter( shippedAmount, order.currency.isoCode, order.totalRounding.decimals) }}\n
\n{% endblock %}\n',mixins:[eS.getByName("notification")],inject:["MolliePaymentsRefundService","MolliePaymentsShippingService","MolliePaymentsOrderService","MolliePaymentsConfigService","acl"],data(){return{refundManagerService:null,shippingManagerService:null,molliePaymentUrl:"",molliePaymentUrlCopied:!1,isRefundManagerPossible:!1,showRefundModal:!1,isShippingPossible:!1,showShippingModal:!1,remainingAmount:0,refundedAmount:0,voucherAmount:0,refundAmountPending:0,shippedAmount:0,shippedQuantity:0}},computed:{isMollieOrder(){return new ec(this.order).isMollieOrder()},hasCreditCardData(){return this._creditCardData()?.hasCreditCardData()??!1},creditCardLabel(){return this._creditCardData().getLabel()},creditCardNumber(){return"**** **** **** "+this._creditCardData().getNumber()},creditCardHolder(){return this._creditCardData().getHolder()},mollieOrderId(){return new ec(this.order).getMollieID()},mollieThirdPartyPaymentId(){return new ec(this.order).getPaymentRef()},isSubscription(){return new ec(this.order).isSubscription()},subscriptionId(){return new ec(this.order).getSwSubscriptionId()},hasPaymentLink(){return""!==this.molliePaymentUrl},currencyFilter(){return eM.getByName("currency")}},watch:{order(){this.getMollieData()}},created(){this.createdComponent()},methods:{createdComponent(){this.molliePaymentUrl="",this.isShippingPossible=!1,this.isRefundManagerPossible=!1,this.mollieOrderId&&(this.refundedManagerService=new em(this.MolliePaymentsConfigService,this.acl),this.shippingManagerService=new ep(this.MolliePaymentsShippingService),this.$root&&this.$root.$on?this.$root.$on(ef.EventShippedOrder,()=>{this.onCloseShippingManager(),location.reload()}):Shopware.Utils.EventBus.on(ef.EventShippedOrder,()=>{this.onCloseShippingManager(),location.reload()}),this.getMollieData())},onOpenRefundManager(){this.showRefundModal=!0},onCloseRefundManager(){this.showRefundModal=!1,location.reload()},onOpenShippingManager(){this.showShippingModal=!0},onCloseShippingManager(){this.showShippingModal=!1},_creditCardData(){return new ec(this.order).getCreditCardAttributes()},copyPaymentUrlToClipboard(){let e=async function(e){await navigator.clipboard.writeText(e)};("function"==typeof Shopware.Utils.dom.copyToClipboard?Shopware.Utils.dom.copyToClipboard:e)(this.molliePaymentUrl),this.molliePaymentUrlCopied=!0},onMolliePaymentUrlProcessFinished(e){this.molliePaymentUrlCopied=e},getMollieData(){this.isMollieOrder&&(this.MolliePaymentsOrderService.getPaymentUrl({orderId:this.order.id}).then(e=>{this.molliePaymentUrl=null!==e.url?e.url:""}),this.shippingManagerService||(this.shippingManagerService=new ep(this.MolliePaymentsShippingService)),this.shippingManagerService.isShippingPossible(this.order).then(e=>{this.isShippingPossible=e}),this.refundedManagerService||(this.refundedManagerService=new em(this.MolliePaymentsConfigService,this.acl)),this.refundedManagerService.isRefundManagerAvailable(this.order.salesChannelId,this.order).then(e=>{this.isRefundManagerPossible=e}),this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(e=>{this.remainingAmount=e.totals.remaining,this.refundedAmount=e.totals.refunded,this.voucherAmount=e.totals.voucherAmount,this.refundAmountPending=e.totals.pendingRefunds}).catch(e=>{this.createNotificationError({message:e.message})}),this.MolliePaymentsShippingService.total({orderId:this.order.id}).then(e=>{this.shippedAmount=Math.round(100*e.amount)/100,this.shippedQuantity=e.quantity}))}}});let{Component:ez}=Shopware;ez.override("sw-order-list",{template:'{% block sw_order_list_grid_columns %}\n {% parent %}\n {% block sw_order_list_grid_columns_mollie_abo %}\n \n {% endblock %}\n{% endblock %}',computed:{orderCriteria(){let e=this.$super("orderCriteria");return e.addAssociation("transactions.paymentMethod"),e}},methods:{getOrderColumns(){let e=this.$super("getOrderColumns");return e.push({property:"mollie",label:"mollie-payments.sw-order-list.columns.mollie",allowResize:!0,primary:!1}),e},isMollie(e){let t=new ec(e);return""!==t.getOrderId()||""!==t.getPaymentId()},getMollieId(e){let t=new ec(e);return""!==t.getOrderId()?t.getOrderId():""!==t.getPaymentId()?t.getPaymentId():""},isMollieSubscription(e){return""!==new ec(e).getSwSubscriptionId()}}}),i(12395),i(14838);let{Component:ej}=Shopware,{string:eP}=Shopware.Utils;ej.register("mollie-tracking-info",{template:'{% block mollie_tracking_info %}\n \n \n \n\n \n \n\n \n \n \n \n \n \n{% endblock %}\n',props:{delivery:{type:Object,required:!0,default(){return null}},tracking:{type:Object,required:!0,default(){return{carrier:"",code:"",url:""}}}},created(){this.createdComponent()},methods:{createdComponent(){1===this.delivery.trackingCodes.length&&this.prefillTrackingInfo(this.delivery.trackingCodes[0],this.delivery.shippingMethod)},prefillTrackingInfo(e,t){this.tracking.carrier=t.name,this.tracking.code=e,eP.isEmptyOrSpaces(t.trackingUrl)||(this.tracking.url=this.renderTrackingUrl(e,t))},renderTrackingUrl(e,t){let i=t?t.trackingUrl:null;return i?i.replace("%s",encodeURIComponent(e)):""}}}),i(1258);let{Application:eA}=Shopware;class eR{buildColumns(){let e=eA.getApplicationRoot();return[{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.item"),property:"shopware.label",align:"left"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.productNumber"),property:"shopware.productNumber",align:"left"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.unitPrice"),property:"shopware.unitPrice",width:"90px",align:"right"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.quantity"),property:"shopware.quantity",width:"50px",align:"right"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.refunded"),property:"refunded",width:"50px",align:"right"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.refundQuantity"),property:"inputQuantity",width:"140px",align:"center"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.totalPrice"),property:"shopware.totalPrice",width:"110px",align:"right"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.refundAmount"),property:"inputAmount",width:"150px",align:"center"},{label:"",property:"inputConsiderTax",align:"center"},{label:"",property:"inputConsiderPromotion",align:"center"},{label:e.$tc("mollie-payments.refund-manager.cart.grid.columns.resetStock"),property:"inputStock",width:"135px",align:"center"}]}}let{Application:eT}=Shopware;class eC{buildColumns(){let e=eT.getApplicationRoot();return[{property:"amount.value",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.amount"),width:"120px",align:"right",sortable:!0},{property:"status",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.status"),width:"190px",sortable:!0},{property:"description",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.description")},{property:"internalDescription",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.internalDescription")},{property:"composition",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.composition"),width:"100px"},{property:"createdAt",label:e.$tc("mollie-payments.refund-manager.refunds.grid.columns.date"),width:"100px",sortable:!0}]}}let eE="quantity",eI="amount";class ex{isTypePromotion(e){return e.shopware.isPromotion}isTypeDelivery(e){return e.shopware.isDelivery}isDiscounted(e){return e.shopware.promotion.discount>0}isRefundable(e){return 0!==e.shopware.unitPrice}setStockReset(e,t){e.resetStock>0||(e.resetStock=t)}setFullRefund(e){e.refundQuantity=e.shopware.quantity-e.refunded,this.onQuantityChanged(e)}resetRefundData(e){e.refundMode="none",e.refundQuantity=0,e.refundAmount=0,e.resetStock=0,e.refundPromotion=!1,e.refundTax=!1}onQuantityChanged(e){if(e.refundMode===eI)return;let t=e.shopware.quantity-e.refunded;e.refundQuantity>t&&(e.refundQuantity=t),e.refundMode=eE,this._calculateItemAmount(e)}onAmountChanged(e){e.refundMode!==eE&&(e.refundMode=eI,e.refundQuantity<=0&&(e.refundQuantity=parseInt(e.refundAmount/e.shopware.unitPrice)))}onRefundTaxChanged(e){e.refundMode!==eI&&this._calculateItemAmount(e)}onPromotionDeductionChanged(e){e.refundMode!==eI&&this._calculateItemAmount(e)}_calculateItemAmount(e){let t=e.shopware.unitPrice*e.refundQuantity,i=0;if(e.refundTax){i+=e.shopware.tax.perItemTax*e.refundQuantity,e.refundQuantity>0&&e.refundQuantity+e.refunded===e.shopware.quantity&&(i+=e.shopware.tax.totalToPerItemRoundingDiff);let t=0;e.refundTax&&e.shopware.promotion.taxValue>0&&(t=e.shopware.promotion.taxValue/e.shopware.promotion.quantity*e.refundQuantity),i-=t}if(e.refundPromotion){let n=e.shopware.promotion.discount/e.shopware.promotion.quantity,a=e.refundQuantity*n;e.refundAmount=t+i-a}else e.refundAmount=t+i}}let{Component:eD,Mixin:eO,Filter:eL}=Shopware;eD.register("mollie-refund-manager",{template:'\n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n
\n \n \n {{ $tc(\'mollie-payments.refund-manager.cart.btnSelectAll\') }}\n \n \n {{ $tc(\'mollie-payments.refund-manager.cart.btnResetForm\') }}\n \n \n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.cart.linkHowTo\') }}\n \n
\n
\n \n\n \n\n \n \n \n \n \n \n \n \n \n \n \n
\n {{ $tc(\'mollie-payments.refund-manager.cart.roundDiffItemAdded\') }} ({{ currencyFilter( roundingDiff , order.currency.isoCode, order.totalRounding.decimals) }})\n
\n
\n \n
\n \n {{ $tc(\'mollie-payments.refund-manager.acl.warningCancel\') }}\n \n \n {{ $tc(\'mollie-payments.refund-manager.refunds.linkMore\') }}\n \n
\n \n \n \n \n \n \n \n
\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n \n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.linkResetTutorials\') }}\n \n
\n
\n \n \n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titleFullRefund\') }}\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textFullRefund\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titleRoundingDiff\') }}\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textRoundingDiff\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n\n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titleStockReset\') }}
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textStockReset\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titleShipping\') }}
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textShipping\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n
\n \n {# --------------------------------------------------------------------------------------------- #}\n \n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titlePartialAmount\') }}
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textPartialAmount\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titlePartialItems\') }}\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textPartialItems\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n \n
\n
\n {{ $tc(\'mollie-payments.refund-manager.instructions.titlePartialPromotions\') }}
\n {{ $tc(\'mollie-payments.refund-manager.instructions.textPartialPromotions\') }}\n
\n
\n \n {{ $tc(\'mollie-payments.refund-manager.instructions.btnToggleTutorial\') }}\n \n
\n
\n
\n \n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n \n
\n \n {{ $tc(\'mollie-payments.refund-manager.summary.dataLoading\') }}\n \n
\n {# --------------------------------------------------------------------------------------------- #}\n \n {% block sw_order_line_items_grid_refund_summary %}\n
\n
{{ $tc(\'mollie-payments.refund-manager.summary.headerExcludingVat\') }}
\n
{{ $tc(\'mollie-payments.refund-manager.summary.headerIncludingVat\') }}
\n {% block sw_order_line_items_grid_refund_summary_amount_total %}\n \n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_amount_free_tax %}\n \n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_rounding_diff %}\n \n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_amount_voucher %}\n \n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_amount_pending_refunds %}\n
\n {{ $tc(\'mollie-payments.refund-manager.summary.captionPendingRefunds\') }}\n
\n
\n
\n - {{ currencyFilter( pendingRefunds , order.currency.isoCode, order.totalRounding.decimals) }}\n
\n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_amount_refunded %}\n
\n {{ $tc(\'mollie-payments.refund-manager.summary.captionRefunded\') }}\n
\n
\n
\n - {{ currencyFilter( refundedAmount , order.currency.isoCode, order.totalRounding.decimals) }}\n
\n {% endblock %}\n {% block sw_order_line_items_grid_refund_summary_amount_remaining %}\n
\n {{ $tc(\'mollie-payments.refund-manager.summary.captionRemaining\') }}\n
\n
\n
\n \n = {{ currencyFilter( remainingAmount , order.currency.isoCode, order.totalRounding.decimals) }}\n \n
\n {% endblock %}\n {% endblock %}\n
\n {# --------------------------------------------------------------------------------------------- #}\n \n \n \n \n \n {{ $tc(\'mollie-payments.refund-manager.summary.btnFixDiff\') }}\n \n \n {# --------------------------------------------------------------------------------------------- #}\n \n \n {# --------------------------------------------------------------------------------------------- #}\n \n \n {# --------------------------------------------------------------------------------------------- #}\n \n \n {# --------------------------------------------------------,------------------------------------- #}\n \n {{ $tc(\'mollie-payments.refund-manager.acl.warningCreate\') }}\n \n\n \n {{ $tc(\'mollie-payments.refund-manager.summary.btnRefund\') }}\n \n
\n \n {{ $tc(\'mollie-payments.refund-manager.summary.btnFullRefund\') }}\n \n
\n
\n
\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n {# --------------------------------------------------------------------------------------------- #}\n\n
\n
\n',mixins:[eO.getByName("notification")],inject:["MolliePaymentsConfigService","MolliePaymentsRefundService","acl"],props:{order:{type:Object,required:!0}},data(){return{itemService:null,configVerifyRefund:!0,configAutoStockReset:!0,configShowInstructions:!0,isRefundDataLoading:!1,isRefunding:!1,orderItems:[],mollieRefunds:[],remainingAmount:0,refundAmount:0,refundedAmount:0,voucherAmount:0,pendingRefunds:0,checkVerifyRefund:!1,refundDescription:"",refundInternalDescription:"",roundingDiff:0,tutorialFullRefundVisible:!1,tutorialPartialAmountRefundVisible:!1,tutorialPartialQuantityVisible:!1,tutorialPartialPromotionsVisible:!1,tutorialResetStock:!1,tutorialRefundShipping:!1}},created(){this.createdComponent()},computed:{titleCardOrder(){return this.$tc("mollie-payments.refund-manager.cart.title").replace("##orderNumber##",this.order.orderNumber)},gridCartColumns(){return new eR().buildColumns()},gridMollieRefundsColumns(){return new eC().buildColumns()},isAclRefundAllowed(){return this.acl.can("mollie_refund_manager:create")},isAclCancelAllowed(){return this.acl.can("mollie_refund_manager:delete")},descriptionCharacterCountingTitle(){return this.$tc("mollie-payments.refund-manager.summary.lblDescription",0,{characters:this.refundDescription.length})},currencyFilter(){return eL.getByName("currency")},dateFilter(){return eL.getByName("date")}},methods:{createdComponent(){if(this.itemService=new ex,this.order){this._fetchFormData();let e=this;this.MolliePaymentsConfigService.getRefundManagerConfig(this.order.salesChannelId,this.order.id).then(t=>{e.configVerifyRefund=t.verifyRefund,e.configAutoStockReset=t.autoStockReset,e.configShowInstructions=t.showInstructions})}},isItemPromotion(e){return this.itemService.isTypePromotion(e)},isItemDelivery(e){return this.itemService.isTypeDelivery(e)},isItemDiscounted(e){return this.itemService.isDiscounted(e)},isItemRefundable(e){return this.itemService.isRefundable(e)},isTaxStatusGross(){return"gross"===this.order.taxStatus},btnSelectAllItems_Click(){let e=this;this.orderItems.forEach(function(t){e.itemService.setFullRefund(t)}),this._calculateFinalAmount()},btnResetCartForm_Click(){let e=this;this.orderItems.forEach(function(t){e.itemService.resetRefundData(t)}),this._calculateFinalAmount(),this.checkVerifyRefund=!1,this.refundDescription="",this.refundInternalDescription=""},onItemQtyChanged(e){this.itemService.onQuantityChanged(e),this.configAutoStockReset&&this.itemService.setStockReset(e,e.refundQuantity),this._calculateFinalAmount()},onItemAmountChanged(e){this.itemService.onAmountChanged(e),this._calculateFinalAmount()},onItemRefundTaxChanged(e){this.itemService.onRefundTaxChanged(e),this._calculateFinalAmount()},onItemPromotionDeductionChanged(e){this.itemService.onPromotionDeductionChanged(e),this._calculateFinalAmount()},btnResetLine_Click(e){this.itemService.resetRefundData(e),this._calculateFinalAmount()},btnToggleTutorialFull_Click(){this.tutorialFullRefundVisible=!this.tutorialFullRefundVisible},btnToggleTutorialPartialAmount_Click(){this.tutorialPartialAmountRefundVisible=!this.tutorialPartialAmountRefundVisible},btnToggleTutorialPartialQuantities_Click(){this.tutorialPartialQuantityVisible=!this.tutorialPartialQuantityVisible},btnToggleTutorialPartialPromotions_Click(){this.tutorialPartialPromotionsVisible=!this.tutorialPartialPromotionsVisible},btnToggleTutorialStock_Click(){this.tutorialResetStock=!this.tutorialResetStock},btnToggleTutorialShipping_Click(){this.tutorialRefundShipping=!this.tutorialRefundShipping},btnResetTutorials_Click(){this.tutorialFullRefundVisible=!1,this.tutorialPartialAmountRefundVisible=!1,this.tutorialPartialQuantityVisible=!1,this.tutorialPartialPromotionsVisible=!1,this.tutorialResetStock=!1,this.tutorialRefundShipping=!1},isButtonFixDiffAvailable(){let e=Math.abs(this.refundAmount-this.remainingAmount);return e>0&&e<=.07},btnFixDiff_Click(){this.refundAmount=this.remainingAmount},btnRefund_Click(){if(this.isAclRefundAllowed){if(this.refundAmount<=0){this._showNotificationWarning(this.$tc("mollie-payments.refund-manager.notifications.error.low-amount"));return}var e=[];this.orderItems.forEach(function(t){let i={id:t.shopware.id,label:t.shopware.label,quantity:t.refundQuantity,amount:t.refundAmount,resetStock:t.resetStock};e.push(i)}),this.isRefunding=!0,this.MolliePaymentsRefundService.refund({orderId:this.order.id,amount:this.refundAmount,description:this.refundDescription,internalDescription:this.refundInternalDescription,items:e}).then(e=>{e.success?this._handleRefundSuccess(e):this._showNotificationError(e.errors[0])}).finally(()=>{this.isRefunding=!1})}},btnRefundFull_Click(){this.isAclRefundAllowed&&(this.isRefunding=!1,this.MolliePaymentsRefundService.refundAll({orderId:this.order.id,description:this.refundDescription,internalDescription:this.refundInternalDescription}).then(e=>{e.success?this._handleRefundSuccess(e):this._showNotificationError(e.errors[0])}).finally(()=>{this.isRefunding=!1}))},getRefundStatusName(e){return this.$tc("mollie-payments.refunds.status."+e)},getRefundStatusDescription(e){return this.$tc("mollie-payments.refunds.status.description."+e)},getRefundCompositions(e){if(!e||!e.metadata||!e.metadata.composition||e.metadata.composition.length<=0)return[this.$tc("mollie-payments.refund-manager.refunds.grid.lblNoComposition")];let t=this,i=[];return e.metadata.composition.forEach(function(e){let n=e.label;e.swReference.length>0&&(n=e.swReference),e.quantity>0?i.push(n+" ("+e.quantity+" x "+e.amount+" "+t.order.currency.symbol+")"):i.push(n+" ("+e.amount+" "+t.order.currency.symbol+")")}),i},getRefundStatusBadge(e){return"refunded"===e?"success":"warning"},isRefundCancelable(e){return e.isPending||e.isQueued},btnCancelRefund_Click(e){this.isAclCancelAllowed&&this.MolliePaymentsRefundService.cancel({orderId:this.order.id,refundId:e.id}).then(e=>{e.success?(this._showNotificationSuccess(this.$tc("mollie-payments.refund-manager.notifications.success.refund-canceled")),this.$emit("refund-cancelled"),this._fetchFormData()):this._showNotificationError(e.errors[0])}).catch(e=>{this._showNotificationError(e.error)})},_fetchFormData(){this.isRefundDataLoading=!0;let e=this;this.MolliePaymentsRefundService.getRefundManagerData({orderId:this.order.id}).then(t=>{this.mollieRefunds=t.refunds,this.remainingAmount=t.totals.remaining,this.refundedAmount=t.totals.refunded,this.voucherAmount=t.totals.voucherAmount,this.pendingRefunds=t.totals.pendingRefunds,this.roundingDiff=t.totals.roundingDiff,this.orderItems=[],t.cart.forEach(function(t){let i={refunded:t.refunded,shopware:t.shopware};e.itemService.resetRefundData(i),e.orderItems.push(i)}),this.isRefundDataLoading=!1})},_calculateFinalAmount(){var e=0;this.orderItems.forEach(function(t){e+=parseFloat(t.refundAmount)}),this.refundAmount=this._roundToTwo(e)},_roundToTwo(e){return+(Math.round(e+"e+2")+"e-2")},_showNotification(e){this.createNotificationWarning({message:this.$tc(e)})},_showNotificationWarning(e){this.createNotificationWarning({message:this.$tc(e)})},_showNotificationSuccess(e){this.createNotificationSuccess({message:e})},_showNotificationError(e){this.createNotificationError({message:e})},_handleRefundSuccess(e){if(this.isRefunding=!1,!e.success){this._showNotificationError(this.$tc("mollie-payments.refund-manager.notifications.error.refund-created"));return}this._showNotificationSuccess(this.$tc("mollie-payments.refund-manager.notifications.success.refund-created")),this.$emit("refund-success"),this._fetchFormData(),this.btnResetCartForm_Click()}}}),i(13334);let{Component:eV,Mixin:eN}=Shopware;eV.register("mollie-ship-order",{template:'\n

{{ $tc(\'mollie-payments.modals.shipping.order.description\') }}

\n\n \n \n {{ $tc(\'mollie-payments.modals.shipping.selectAllButton\') }}\n \n \n {{ $tc(\'mollie-payments.modals.shipping.resetButton\') }}\n \n \n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_items %}\n \n\n \n\n \n\n \n {% endblock %}\n\n \n
\n \n {{ $tc(\'mollie-payments.modals.shipping.confirmButton\') }}\n \n
\n\n {% block sw_order_line_items_grid_grid_mollie_ship_item_modal_tracking %}\n \n \n \n \n {% endblock %}\n\n
\n',mixins:[eN.getByName("notification")],inject:["MolliePaymentsShippingService","MolliePaymentsConfigService","acl"],props:{order:{type:Object,required:!0}},data(){return{shippableLineItems:[],shippedLineItems:[],showTrackingInfo:!1,tracking:{carrier:"",code:"",url:""}}},created(){this.createdComponent()},computed:{getShipOrderColumns(){return[{property:"itemselect",label:""},{property:"label",label:this.$tc("mollie-payments.modals.shipping.order.itemHeader")},{property:"quantity",label:this.$tc("mollie-payments.modals.shipping.order.quantityHeader"),width:"160px"},{property:"originalQuantity",label:this.$tc("mollie-payments.modals.shipping.order.originalQuantityHeader"),width:"160px"}]}},methods:{async createdComponent(){if(this.showTrackingInfo=!1,this.tracking={carrier:"",code:"",url:""},await this.MolliePaymentsShippingService.status({orderId:this.order.id}).then(e=>{this.shippedLineItems=e}),new ep(this.MolliePaymentsShippingService).getShippableItems(this.order).then(e=>{for(let t=0;t=1}},btnSelectAllItems_Click(){for(let e=0;e0&&(t.selected=!0)}},btnResetItems_Click(){for(let e=0;e{this.$root.$emit(ef.EventShippedOrder),this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.shipping.item.success")})}).catch(e=>{let t=e.response.data.message?e.response.data.message:e.response.data.errors[0];this.createNotificationError({message:t})})}}});let{Component:eU,Mixin:eF}=Shopware;eU.register("mollie-cancel-item",{template:'\n\n \n
\n \n \n
\n
\n
\n \n
\n {{ item.label }}\n
\n
\n
\n
\n \n {{ item.label }}\n \n
\n
\n
\n\n \n \n \n',props:{item:{type:Object,required:!0}},data(){return{cancelableQuantity:0,canceledQuantity:1,resetStock:!1,isLoading:!1}},mixins:[eF.getByName("notification")],inject:["MolliePaymentsItemCancelService"],methods:{submit(){this.isLoading||(this.isLoading=!0,this.MolliePaymentsItemCancelService.cancel({mollieOrderId:this.item.mollieOrderId,mollieLineId:this.item.mollieId,shopwareLineId:this.item.shopwareItemId,canceledQuantity:this.canceledQuantity,resetStock:this.resetStock}).then(e=>{this.isLoading=!1,e.success?this.createNotificationSuccess({message:this.$tc("mollie-payments.modals.cancel.item.success")}):this.createNotificationError({message:this.$tc("mollie-payments.modals.cancel.item.failed."+e.message)}),this.$emit("update-cancel-status"),this.$emit("close")}).catch(e=>{this.isLoading=!1,this.createNotificationError({message:e.response.data.message}),this.$emit("close")}))},close(){this.$emit("close")}}});var eB=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Abonnement | Mollie Abonnements"},"businessEvents":{"mollie_checkout_order_success":" Bestellung erfolgreich","mollie_checkout_order_failed":" Bestellung fehlgeschlagen","mollie_checkout_order_canceled":" Bestellung abgebrochen","mollie_webhook_received_All":" Mollie Webhook empfangen (Alle)","mollie_webhook_received_status_authorized":" Mollie Webhook empfangen (Authorisiert)","mollie_webhook_received_status_failed":" Mollie Webhook empfangen (Fehler)","mollie_webhook_received_status_canceled":" Mollie Webhook empfangen (Abgebrochen)","mollie_webhook_received_status_expired":" Mollie Webhook empfangen (Abgelaufen)","mollie_webhook_received_status_pending":" Mollie Webhook empfangen (Wartend)","mollie_webhook_received_status_paid":" Mollie Webhook empfangen (Bezahlt)","mollie_webhook_received_status_completed":" Mollie Webhook empfangen (Komplett)","mollie_webhook_received_status_refunded":" Mollie Webhook empfangen (R\xfcckerstattet)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook empfangen (Teilweise R\xfcckerstattet)","mollie_refund_started":" Mollie R\xfcckerstattung gestartet","mollie_subscription_started":" Mollie Abonnement gestartet","mollie_subscription_ended":" Mollie Abonnement abgeschlossen","mollie_subscription_cancelled":" Mollie Abonnement abgebrochen","mollie_subscription_paused":" Mollie Abonnement pausiert","mollie_subscription_resumed":" Mollie Abonnement fortgesetzt","mollie_subscription_skipped":" Mollie Abonnement ausgesetzt","mollie_subscription_renewed":" Mollie Abonnement erneuert","mollie_subscription_renewal_reminder":" Mollie Erinnerung zur Abonnement Erneuerung"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"In Abonnements suchen...","general":{"mainMenuItemGeneral":"Mollie Payments Zahlungen","descriptionTextModule":"Mollie Payments Zahlungen","btnMollieActions":"Mollie Aktionen","refundThroughMollie":"R\xfcckerstattung \xfcber Mollie","shipThroughMollie":"Versand melden","cancelMollieItem":"Abbrechen \xfcber Mollie"},"config":{"info":{"title":"Hallo {userName}, Willkommen bei Mollie!","descriptionTop":"Starten mit Mollie ist einfach!","descriptionBottom":"Das ist alles!","descriptionFooter":"Wenn du mehr \xfcber unser Plugin lernen m\xf6chtest, besuche bitte unsere offizielle Dokumentation.","onboardingStep1":"Registriere dich f\xfcr ein Mollie Konto.","onboardingStep2":"Gib deine API Schl\xfcssel weiter unten ein.","onboardingStep2TestMode":"Aktiviere den \'Testmodus\' wenn du Zahlungen nur testen m\xf6chtest.","onboardingStep3":"Weise die Zahlungsarten deinen Verkaufskan\xe4len zu.","onboardingStep3Link":"Verkaufskan\xe4le \xf6ffnen","btnDocumentation":"Dokumentation","btnRequestSupport":"Support","btnTroubleshooting":"zu den Fehlerbehebungen"},"api":{"apiLinkButton":"Erhalten Sie Ihre API Keys vom Mollie Dashboard","testButton":"Teste API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API Schl\xfcssel","isValid":"ist g\xfcltig","isInvalid":"ist ung\xfcltig"}},"payments":{"format":{"placeholder":"Platzhalter","preview":"Vorschau"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Zahlungsarten aktualisieren","succeeded":"Die Zahlungsarten wurden erfolgreich aktualisiert.","failed":"Die Zahlungsarten konnten nicht aktualisiert werden."},"mollieLimits":{"link":"Zeige Mollie-Verf\xfcgbarkeitregeln f\xfcr Zahlungsmethoden"}},"rounding":{"info1":"Shopware kann anhand von W\xe4hrungseinstellungen berechnen, wie die Gesamtsumme einer Bestellung gerundet wird. Dazu geh\xf6ren die Anzahl der Dezimalstellen in den Produktpreisen und das n\xe4chste Rundungsintervall, z. B. 0,50 oder 1,00.","info2":"Diese Einstellungen k\xf6nnen zu einer anderen Gesamtsumme als der Gesamtsumme der Einzelposten f\xfchren. Wenn Mollie diese Betr\xe4ge abgleicht und feststellt, dass sie nicht \xfcbereinstimmen, verursacht dies einen Fehler.","info3":"Sie k\xf6nnen diese Funktion verwenden, um Rundungsprobleme in Ihrem Checkout zu vermeiden. Wenn diese aktiviert ist, f\xfcgt sie eine separate Position im Mollie-Dashboard f\xfcr die Rundungsdifferenz hinzu, und die Kunden zahlen die von Shopware berechnete Gesamtsumme."},"order":{"bankTransferDueDateKlarnaLimitReached":"Es ist nicht m\xf6glich, Klarna Pay now, Klarna Slice it oder Klarna Pay later als Zahlungsmethode zu verwenden, wenn Ihr Ablaufdatum mehr als 28 Tage in der Zukunft liegt, es sei denn, zwischen dem H\xe4ndler und Klarna wurde eine andere H\xf6chstgrenze vereinbart.","bankTransferDueDateLimitReached":"Es ist nicht m\xf6glich, die Bestelllaufzeit auf mehr als 100 Tage festzulegen."},"support":{"modalTitle":"Unterst\xfctzung von Mollie anfordern","btnCancel":"Abbrechen","btnConfirm":"Unterst\xfctzung anfordern","btnSupport":"Mehr \xfcber unseren Support","form":{"name":"Ihr Name","email":"Ihre E-Mail","recipient":"Anfrage senden an","subject":"Betreff","message":"Nachricht"},"data":{"header":"Datentransfer zu Mollie:","other":"Andere:","shopwareVersion":"Shopware-Version","pluginLogs":"{plugin} log files","pluginConfiguration":"{plugin}-Konfiguration","pluginConfigurationHelpText":"API-Schl\xfcssel sind ausgeschlossen.","paymentMethods":"Daten zur Zahlungsmethode","paymentMethodsHelpText":"Enth\xe4lt Informationen dar\xfcber, welche Zahlungsmethoden aktiv sind, welche den einzelnen Vertriebskan\xe4len zugeordnet sind, sowie deren Status in Ihrem Mollie-Konto."},"success":"Die Supportanfrage wurde erfolgreich versendet. Wir geben unser Bestes f\xfcr eine schnelle Antwort.","error":"Es gab leider ein Problem beim Versand \xfcber Shopware. Bitte probieren Sie es erneut oder kontaktieren uns direkt per E-Mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart has subscription items (Mollie)"},"refunds":{"status":{"queued":"Warteschlange","pending":"Ausstehend","processing":"Processing","refunded":"Erstattet","failed":"Gescheitert","description":{"queued":"Die R\xfcckerstattung steht in der Warteschlange, bis gen\xfcgend Guthaben vorhanden ist, um die R\xfcckerstattung zu verarbeiten. Sie k\xf6nnen die R\xfcckerstattung noch stornieren.","pending":"Die R\xfcckerstattung wird am n\xe4chsten Werktag an die Bank gesendet. Sie k\xf6nnen die R\xfcckerstattung immer noch stornieren.","processing":"Die R\xfcckerstattung wurde an die Bank gesendet. Der R\xfcckerstattungsbetrag wird so schnell wie m\xf6glich auf das Kundenkonto \xfcberwiesen.","refunded":"Der R\xfcckerstattungsbetrag wurde an den Kunden \xfcberwiesen.","failed":"Die R\xfcckerstattung ist nach der Bearbeitung fehlgeschlagen. Zum Beispiel hat der Kunde sein Bankkonto geschlossen. Das Geld wird auf das Konto zur\xfcck\xfcberwiesen."}}},"refund-manager":{"general":{"unitQuantity":"Stk."},"acl":{"warningCreate":"Sie besitzen keine Berechtigungen, um R\xfcckerstattungen durchzuf\xfchren","warningCancel":"Sie besitzen keine Berechtigungen, um R\xfcckerstattungen abzubrechen"},"cart":{"title":"Bestellung ##orderNumber##","btnSelectAll":"Alle ausw\xe4hlen","btnResetForm":"Formular zur\xfccksetzen","linkHowTo":"Wie benutze ich dieses Formular?","grid":{"columns":{"item":"Position","productNumber":"Produktnummer","unitPrice":"St\xfcckpreis","quantity":"Anzahl","refunded":"R\xfcckerstattet","refundQuantity":"R\xfcckerstatten","totalPrice":"Gesamt","refundAmount":"R\xfcckerstatten","resetStock":"Lagerbestand zur\xfccksetzen"},"btnResetLine":"Zeile zur\xfccksetzen","checkDeductPromotion":"Rabatt abziehen","checkRefundTax":"BTW terugbetalen"},"roundDiffItemAdded":"Automatische Position f\xfcr Rundungen wurde hinzugef\xfcgt"},"instructions":{"linkResetTutorials":"Tutorials zur\xfccksetzen","btnToggleTutorial":"Tutorial anzeigen/verstecken","titleFullRefund":"Vollst\xe4ndige R\xfcckerstattung","textFullRefund":"Verwenden Sie einfach die Schaltfl\xe4che f\xfcr die vollst\xe4ndige R\xfcckerstattung. Dadurch wird sichergestellt, dass alle Ihre Artikel als erstattet markiert werden und der volle Betrag an den Kunden zur\xfcckerstattet wird.","titleStockReset":"Lagerbestand zur\xfccksetzen","textStockReset":"Sie k\xf6nnen den verf\xfcgbaren Bestand automatisch erh\xf6hen, indem Sie die Menge eingeben, die Sie wieder auf Lager haben m\xf6chten. Geben Sie es einfach ein, bevor Sie mit einer vollst\xe4ndigen oder teilweisen R\xfcckerstattung fortfahren. Das Zur\xfccksetzen des Bestands kann flexibel mit dem eigentlichen R\xfcckerstattungsprozess kombiniert werden.","titleShipping":"Versandkosten","textShipping":"Versandartikel k\xf6nnen wie alle anderen Produktartikel erstattet werden. Geben Sie entweder die volle Menge oder einen benutzerdefinierten Teilbetrag ein und fahren Sie mit der R\xfcckerstattung fort. Die R\xfcckerstattung der Versandkosten kann flexibel mit dem eigentlichen R\xfcckerstattungsprozess von Artikeln kombiniert werden.","titlePartialAmount":"Teilweise R\xfcckerstattung (nur Betrag)","textPartialAmount":"Geben Sie einfach den Teilbetrag in das Textfeld ein und starten Sie die R\xfcckerstattung.","titlePartialItems":"Teilweise R\xfcckerstattung (mit Positionen)","textPartialItems":"Wenn Sie Mengen und Artikel in Mollie als erstattet markieren m\xf6chten, verwenden Sie das obige Formular. Legen Sie Ihre Mengen fest und geben Sie einen benutzerdefinierten Betrag f\xfcr jeden Artikel an, der erstattet wird. Die Gesamtsumme wird dann im Textfeld des finalen Erstattungsbetrages angezeigt. Denken Sie daran, dass es immer noch m\xf6glich ist, diesen endg\xfcltigen Betrag anzupassen, bevor Sie mit der R\xfcckerstattung beginnen.","titlePartialPromotions":"Teilweise R\xfcckerstattung (mit Rabatten)","textPartialPromotions":"Wenn Sie eine oder mehrere Rabatte in Ihrem Warenkorb haben, dann sind diese in Shopware als eigene Position in der Bestellung angelegt. Wenn Sie nun alle rabattierten Artikel erstatten m\xf6chten, erstatten Sie einfach alle Positionen der Artikel sowie die gesamte Rabattposition selbst. Wenn Sie jedoch nur einen Teil der rabattierten Artikel erstatten m\xf6chten, k\xf6nnen Sie den angewendeten Rabatt automatisch f\xfcr jeden einzelnen Artikel abziehen lassen. Sie k\xf6nnen Werte nat\xfcrlich jederzeit \xe4ndern, wenn sie nicht korrekt sind.","titleRoundingDiff":"Rundungsdifferenz","textRoundingDiff":"Bei einer vollst\xe4ndigen R\xfcckerstattung werden Rundungsdifferenzen mit erstattet"},"summary":{"dataLoading":"Daten werden geladen...","headerExcludingVat":"Exkl. MwSt.","headerIncludingVat":"Inkl. MwSt.","captionTotal":"Gesamtsumme","captionTotalTaxFree":"Gesamtsumme","captionPendingRefunds":"Warten auf R\xfcckerstattung","captionVouchers":"Gutscheine","captionRefunded":"R\xfcckerstattete Menge","captionRemaining":"R\xfcckerstattbar","btnFixDiff":"Differenz ausf\xfcllen","placeholderDescription":"Geben Sie eine Beschreibung f\xfcr den Kontoauszug bzw. Kartenabrechnung an. Max. 140 Zeichen","lblDescription":"Beschreibung (optional) ({characters}/140 Zeichen)","descriptionHelp":"Dies wird, wenn m\xf6glich, auf der Bank- oder Kartenabrechnung des Verbrauchers angezeigt. Die Nachricht wird nach 140 Zeichen abgeschnitten.","placeholderInternalDescription":"Geben Sie Ihre interne Beschreibung ein","lblInternalDescription":"Interne Beschreibung (optional)","internalDescriptionHelp":"Dies wird als lokale Beschreibung in der Verwaltungsschnittstelle angezeigt.","checkVerification":"Ich habe den Betrag der R\xfcckerstattung gepr\xfcft und die Anzahl der Positionen f\xfcr Erstattung und Lagerbestand konfiguriert.","btnRefund":"R\xfcckerstatten","btnFullRefund":"Vollst\xe4ndig r\xfcckerstatten","roundDiffItemAdded":"Position f\xfcr Rundungen"},"refunds":{"title":"R\xfcckerstattungen im Mollie Dashboard","linkMore":"Mehr \xfcber R\xfcckerstattungen","grid":{"columns":{"amount":"Betrag","status":"Status","description":"Beschreibung","internalDescription":"Interne beschreibung","composition":"Zusammensetzung","date":"Datum"},"lblNoComposition":"Keine Zusammensetzung verf\xfcgbar","btnCancelRefund":"Diese R\xfcckerstattung stornieren"}},"notifications":{"success":{"refund-created":"Es wurde eine R\xfcckerstattung bei Mollie erstellt. Es kann bis zu 2 Stunden dauern, bis die R\xfcckerstattung abgeschlossen ist. Bis dahin k\xf6nnen Sie die R\xfcckerstattung stornieren.","refund-canceled":"Die ausstehende R\xfcckerstattung wurde erfolgreich storniert und entfernt."},"error":{"low-amount":"Bitte geben Sie einen zu erstattenden Betrag ein.","refund-created":"Beim Erstellen einer R\xfcckerstattung ist etwas schief gelaufen.","refund-canceled":"Es gab ein Problem beim L\xf6schen der ausstehenden R\xfcckertattung. Bitte versuche es erneut im Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Gutscheine","VOUCHER_INFO_TITLE":"Gutschein Bezahlung","VOUCHER_INFO_DESCRIPTION":"Mit Mollie k\xf6nnen Sie ganz einfach Zahlungen in Ihrem Online-Shop mit \xd6ko-, Geschenk- und Essensgutscheinen akzeptieren – eine clevere Wahl, um den Umsatz zu steigern und Ihre Kunden zufrieden zu stellen. Die Zahlungsmethode \\"Gutschein\\" ist nur sichtbar, wenn Sie mindestens 1 Produkt in Ihrem Warenkorb haben, das mit einem konfigurierten Gutscheintyp berechtigt ist.","VOUCHER_INFO_DEFAULTLANGUAGE":"Bitte beachten Sie, dass diese Konfiguration nur in der Standard Sprache durchgef\xfchrt werden kann. \xc4ndern Sie die hier angezeigte Sprache um den Gutscheintyp ver\xe4ndern zu k\xf6nnen.","VOUCHER_BTN_READMORE":"Mehr lesen","VOUCHER_TYPE_CAPTION":"Gutschein Typ f\xfcr Produkt","VOUCHER_TYPE_VALUE_NONE":"Kein Gutschein Typ","VOUCHER_TYPE_VALUE_ECO":"\xd6ko","VOUCHER_TYPE_VALUE_MEAL":"Mahlzeit","VOUCHER_TYPE_VALUE_VOUCHER":"Geschenk"},"modals":{"shipping":{"title":"Versand an Mollie melden","item":{"label":"Artikel:","noQuantity":"Bitte geben Sie eine Menge f\xfcr den Versand ein.","shipAll":"Alles versenden","summary":{"quantity":"Zu versendende Menge","shipped":"Versendete Menge","shippable":"Zu versendende Menge"},"success":"Die Bestellung wurde erfolgreich als versendet markiert."},"order":{"description":"Die folgenden Artikelmengen werden versandt.","itemHeader":"Artikel","quantityHeader":"Menge","originalQuantityHeader":"Menge (verschickbar)"},"availableTracking":{"label":"Verf\xfcgbare Tracking-Codes","hint":"Klicken Sie auf einen dieser Tracking-Codes, um alle Daten automatisch auszuf\xfcllen."},"showTracking":"Tracking-Informationen f\xfcr diese Sendung hinzuf\xfcgen","tracking":{"carrier":"Spediteur","code":"Code","url":"Url","invalid":"Bitte geben Sie sowohl Spediteur als auch Code ein"},"confirmButton":"Bestellung versenden","cancelButton":"Abbrechen","selectAllButton":"Alle ausw\xe4hlen","resetButton":"Zur\xfccksetzen"},"cancel":{"title":"Produkt in Mollie abbrechen","confirmButton":"Produkt in Mollie abbrechen","cancelButton":"Schlie\xdfen","resetStock":"Bestand zur\xfccksetzen","item":{"success":"Produkt erfolgreich abgebrochen","failed":{"quantityZero":"Menge ist 0","invalidLine":"Produkt exestiert nicht in der Bestellung","quantityTooHigh":"Menge ist zu hoch"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Bestellung verschicken (Mollie)","description":"Bestellung wird in Mollie als verschickt markiert."},"modal":{"title":"Bestellung verschicken","description":"Diese Aktion markiert automatisch eine Bestellung in Mollie als \'versendet\'. Dabei wird aus der Sequenz die Bestellnummer gelesen und an die Mollie API \xfcbergeben. Erfolgreiche sowie fehlgeschlagene Aktionen sind dabei in den Mollie Logs einsehbar.","warningConfig":"Bitte deaktivieren Sie alle zus\xe4tzlichen Automatisierungen, die mit dieser Flow Builder Aktion kolidieren k\xf6nnen.\\nDie folgenden aktivierten Features dieses Plugins k\xf6nnen sich mit dieser Aktion \xfcberschneiden:","noWarnings":"Keine Warnungen"}},"refundOrder":{"editor":{"title":"Bestellung erstatten (Mollie)","description":"Bestellung wird via Mollie zur\xfcckerstattet."},"modal":{"title":"Bestellung erstatten","description":"Diese Aktion startet eine R\xfcckerstattung via Mollie. Dabei wird aus der Sequenz die Bestellnummer gelesen und an die Mollie API \xfcbergeben. Erfolgreiche sowie fehlgeschlagene Aktionen sind dabei in den Mollie Logs einsehbar.","warning":"Bitte beachten Sie, dass eine R\xfcckerstattung bis zu 2 Stunden dauern kann, bis diese im Shop sichtbar ist. Bis dahin k\xf6nnen sie eingeleitete Erstattungen jederzeit auf der Bestellseite im Shop, oder direkt im Mollie Dashboard abbrechen.","warningConfig":"Bitte deaktivieren Sie alle zus\xe4tzlichen Automatisierungen, die mit dieser Flow Builder Aktion kolidieren k\xf6nnen."}},"warnings":{"automaticShipping":"Automatischer Versand in Plugin Konfiguration"}}},"subscriptions":{"status":{"pending":"Ausstehend","active":"Aktiv","canceled":"Abgebrochen","suspended":"Ausgesetzt","completed":"Abgeschlossen","paused":"Pausiert","resumed":"Fortgesetzt","skipped":"Ausgesetzt"},"navigation":{"title":"Mollie Abonnements"},"TYPE_DAYS":"Tage","TYPE_WEEKS":"Woche(n)","TYPE_MONTHS":"Monat(e)","confirm":{"cancelTitle":"Abonnement beenden?","cancel":"K\xfcndigen Sie das Abonnement Ihres Kunden.","pauseTitle":"Abonnement pausieren?","pause":"Pausieren Sie das Abonnement, bis Sie es wieder fortsetzen.","resumeTitle":"Abonnement fortsetzen?","resume":"Das Abonnement erneut fortsetzen.","skipTitle":"N\xe4chste Rate \xfcberspringen?","skip":"\xdcberspringen Sie die n\xe4chste Rate im Abonnement. Es wird danach automatisch fortgesetzt."},"alerts":{"cancelSuccess":"Das Abonnement wurde erfolgreich gek\xfcndigt","pauseSuccess":"Das Abonnement wurde erfolgreich pausiert","resumeSuccess":"Das Abonnement wurde erfolgreich fortgesetzt","skipSuccess":"Das Abonnement wurde erfolgreich ausgesetzt. Das Datum der n\xe4chsten Zahlung wurde aktualisiert."},"list":{"title":"Mollie Abonnements","columns":{"customer":"Kunde","status":"Status","description":"Beschreibung","amount":"Betrag","nextPaymentAt":"N\xe4chste Zahlung","prePaymentReminder":"Erinnert am","canceledAt":"Gek\xfcndigt","createdAt":"Erstellt"},"action":{"edit":"Abonnement bearbeiten"},"deletedCustomer":"Gel\xf6schter Kunde"},"detail":{"title":"Mollie Abonnements","buttonCancelSubscription":"Abonnement k\xfcndigen","labelDescription":"Beschreibung","labelAmount":"Betrag","labelQuantity":"St\xfcck","labelMollieSubscription":"Mollie Abo","labelMollieCustomer":"Mollie Kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware Kunde","labelCreatedAt":"Erstellt am","buttonShowShopwareOrder":"Shopware Bestellung anzeigen","buttonShowShopwareCustomer":"Shopware Kunde anzeigen","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"N\xe4chste Zahlung am","labelLastRemindedAt":"Zuletzt erinnert am","labelCanceledAt":"Gek\xfcndigt am","buttonPauseSubscription":"Abonnement pausieren","buttonResumeSubscription":"Abonnement fortsetzen","buttonSkipSubscription":"Abonnement aussetzen","history":{"cardTitle":"Statushistorie","colDate":"Datum","colComment":"Kommentar","colStatusFrom":"Status (von)","colStatusTo":"Status (zu)","colMollieSubscription":"Mollie Abo"}},"product":{"card-title":"Abonnement","title":"Mollie-Abonnements","description":"Die Verwaltung Ihrer wiederkehrenden Zahlungen ist mit unseren hilfreichen Funktionen einfacher denn je. Bringen Sie Ihr Unternehmen mit effizienten Tracking-Optionen, einfachen Integrationen und mehr auf die n\xe4chste Stufe. Mit Mollie-Abonnements k\xf6nnen Sie ganz einfach Abonnementprodukte erstellen und wiederkehrende Zahlungen so planen, dass sie im konfigurierten Intervall und Zeitraum stattfinden.","mollieSubscriptionProduct":"Ist das ein Abo-Produkt?","mollieSubscriptionIntervalAmount":"Zahlung wiederholen alle","mollieSubscriptionIntervalType":"Abonnement-Intervall-Typ","mollieSubscriptionRepetitionAmount":"Zahlung wiederholen","mollieSubscriptionRepetitionPlaceholder":"Nummer eingeben oder leer lassen","infoDefaultLanguage":"Bitte beachten Sie, dass diese Konfiguration nur in Ihrer Standardsprache bearbeitet werden kann. Bitte \xe4ndern Sie Ihre Sprache, um die Abonnementeinstellungen dieses Produkts zu \xe4ndern.","btnReadMore":"Mehr lesen"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abo Bestellung"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kreditkartendaten","buttonMolliePaymentLink":"In die Zwischenablage kopieren","columnRefunded":"R\xfcckerstattet","columnShipped":"Versandt","columnCanceled":"Abgebrochen","labelMollieOrderId":"Mollie Bestell ID","labelMollieThirdPartyPaymentId":"Zahlungsreferenz","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"R\xfcckerstattete Menge","totalRefundsPending":"Warten auf R\xfcckerstattung","totalRemaining":"R\xfcckerstattbar","totalVouchers":"Gutscheine","totalShipments":"Versandte Menge ({quantity} St\xfcck)","subscriptionBadge":"Abo Bestellung","refundManager":{"title":"R\xfcckerstattung \xfcber Mollie","btnOpenRefundManager":"Refund Manager \xf6ffnen","btnCloseRefundManager":"Refund Manager schlie\xdfen"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Bevorzugter iDeal Aussteller"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refund Manager"},"mollie_subscription":{"label":"Abonnements"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Beschreibung"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"R\xfcckerstattung","subscription":"Abonnement","webhookReceived":"Webhooks","status":"Status","started":"Gestartet","ended":"Beendet","paused":"Pausiert","renewalReminder":"Verl\xe4ngerungserinnerung","renewed":"Erneuert","resumed":"Verl\xe4ngert","skipped":"Ausgesetzt","all":"Alle","canceled":"Abgebrochen","expired":"Abgelaufen","partiallyRefunded":"R\xfcckerstattet (teilweise)","orderSuccess":"Bestellung erfolgreich","orderFailed":"Bestellung fehlgeschlagen","orderCanceled":"Bestellung abgebrochen"}}}'),eH=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Subscription | Mollie Subscriptions"},"businessEvents":{"mollie_checkout_order_success":" Order successful","mollie_checkout_order_failed":" Order failed","mollie_checkout_order_canceled":" Order canceled","mollie_webhook_received_All":" Mollie Webhook Received (All)","mollie_webhook_received_status_authorized":" Mollie Webhook Received (Authorized)","mollie_webhook_received_status_failed":" Mollie Webhook Received (Failed)","mollie_webhook_received_status_canceled":" Mollie Webhook Received (Canceled)","mollie_webhook_received_status_expired":" Mollie Webhook Received (Expired)","mollie_webhook_received_status_pending":" Mollie Webhook Received (Pending)","mollie_webhook_received_status_paid":" Mollie Webhook Received (Paid)","mollie_webhook_received_status_completed":" Mollie Webhook Received (Completed)","mollie_webhook_received_status_refunded":" Mollie Webhook Received (Refunded)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Received (Partially Refunded)","mollie_refund_started":" Mollie refund started","mollie_subscription_started":" Mollie subscription started","mollie_subscription_ended":" Mollie subscription completed","mollie_subscription_cancelled":" Mollie subscription cancelled","mollie_subscription_paused":" Mollie subscription paused","mollie_subscription_resumed":" Mollie subscription resumed","mollie_subscription_skipped":" Mollie subscription skipped","mollie_subscription_renewed":" Mollie subscription renewed","mollie_subscription_renewal_reminder":" Mollie reminder for subscription renewal"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Search subscriptions...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Refund through Mollie","shipThroughMollie":"Ship through Mollie","cancelMollieItem":"Cancel through Mollie"},"config":{"info":{"title":"Hi {userName}, Welcome to Mollie!","descriptionTop":"Onboarding is easy with Mollie!","descriptionBottom":"That\'s it!","descriptionFooter":"If you want to learn more about our plugin, please visit our official documentation page.","onboardingStep1":"Sign up for a Mollie Account.","onboardingStep2":"Enter your API keys in the section below.","onboardingStep2TestMode":"Turn on \'Test Mode\' if you want to only test payments.","onboardingStep3":"Assign payment methods to your sales channel.","onboardingStep3Link":"to your sales channels","btnDocumentation":"Documentation","btnRequestSupport":"Support","btnTroubleshooting":"Troubleshooting Guide"},"api":{"apiLinkButton":"Get your API keys from the Mollie Dashboard","testButton":"Test API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API key","isValid":"is valid","isInvalid":"is invalid"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Preview"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Update payment methods","succeeded":"The payment methods are successfully updated.","failed":"The payment methods couldn\'t be updated."},"mollieLimits":{"link":"Show mollie availability rules for payment methods"}},"rounding":{"info1":"Shopware can use currency settings to calculate how it rounds an order’s grand total. This includes the number of decimals in your product pricing and the nearest rounding interval, such as 0.50 or 1.00.","info2":"These settings can lead to a different grand total than the total sum of line items. When Mollie cross-checks these amounts and finds that they don’t match, it causes a checkout error.","info3":"You can use this feature to avoid rounding issues in your checkout. When enabled, it adds a separate line item in your Mollie Dashboard for the difference in rounding, and your customers pay the grand total calculated by Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"It is not possible to use Klarna Pay now, Klarna Slice it or Klarna Pay later as method when your expiry date is more than 28 days in the future, unless another maximum is agreed between the merchant and Klarna.","bankTransferDueDateLimitReached":"It is not possible to set the order life time higher than 100 days."},"support":{"modalTitle":"Request support from Mollie","btnCancel":"Cancel","btnConfirm":"Request support","btnSupport":"More about our support","form":{"name":"Your name","email":"Your email","recipient":"Send request to","subject":"Subject","message":"Message"},"data":{"header":"Data sent to Mollie:","other":"Other:","shopwareVersion":"Shopware version","pluginLogs":"{plugin} log files","pluginConfiguration":"{plugin} configuration","pluginConfigurationHelpText":"API keys are excluded.","paymentMethods":"Payment method data","paymentMethodsHelpText":"Contains information about which payment methods are active, assigned to each sales channel, as well as their status in your Mollie account."},"success":"The suport request has been successfully sent. We do our best to reply as soon as possible","error":"There was a problem when sending the mail through Shopware. Please try it again or contact us directly per e-mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart with subscriptions (Mollie)"},"refunds":{"status":{"queued":"Queued","pending":"Pending","processing":"Processing","refunded":"Refunded","failed":"Failed","description":{"queued":"The refund is queued until there is enough balance to process te refund. You can still cancel the refund.","pending":"The refund will be sent to the bank on the next business day. You can still cancel the refund.","processing":"The refund has been sent to the bank. The refund amount will be transferred to the consumer account as soon as possible.","refunded":"The refund amount has been transferred to the consumer.","failed":"The refund has failed after processing. For example, the customer has closed his / her bank account. The funds will be returned to your account."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"You don\'t have permissions to create refunds","warningCancel":"You don\'t have permissions to cancel refunds"},"cart":{"title":"Order ##orderNumber##","btnSelectAll":"Select All","btnResetForm":"Reset Form","linkHowTo":"How to use this form?","grid":{"columns":{"item":"Item","productNumber":"Product Number","unitPrice":"Unit Price","quantity":"Quantity","refunded":"Refunded","refundQuantity":"Refund","totalPrice":"Total","refundAmount":"Refund","resetStock":"Reset Stock"},"btnResetLine":"Reset Line","checkDeductPromotion":"Deduct promotion","checkRefundTax":"Refund VAT"},"roundDiffItemAdded":"Automatic rounding item was added"},"instructions":{"linkResetTutorials":"Reset Tutorials","btnToggleTutorial":"Show/Hide Tutorial","titleFullRefund":"Full Refund","textFullRefund":"Just use the button for the full refund. This makes sure that all your items are marked as refunded and the full amount is returned to the customer.","titleStockReset":"Stock Reset","textStockReset":"You can automatically increase the available stock by entering the quantity that you would like to put back in stock. Just enter it before proceeding with a full or partial refund. Resetting the stock can be combined with the actual refund process in a flexible way.","titleShipping":"Shipping","textShipping":"Shipping items can be refunded as any other produt item. Either enter the full quantity or a custom partial amount and proceed with the refund. Refunding shipping costs can be combined with the actual refund process of items in a flexible way.","titlePartialAmount":"Partial Refund (only amount)","textPartialAmount":"Just enter the partial amount in the text field and start the refund.","titlePartialItems":"Partial Refund (with items)","textPartialItems":"If you want to mark quantities and items as refunded in Mollie, use the form above. Set your quantities and provide a custom amount for every item that will be refunded. The total sum will then be visible in the final refund amount text field. Remember, it\'s still possible to adjust this final amount before starting your refund.","titlePartialPromotions":"Partial Refund (with promotions)","textPartialPromotions":"If you have a promotion in your cart, then your promotion is a separate line item. If you want to refund all discounted items, go ahead and refund their total values and the full promotion line item itself. However, if you only want to refund a few items that were discounted, you can deduct the applied discount automatically for every single line item. You can of course always change values if they are not correct.","titleRoundingDiff":"Rounding difference","textRoundingDiff":"A full refund will include rounding differences"},"summary":{"dataLoading":"Data is loading...","headerExcludingVat":"Excl. VAT","headerIncludingVat":"Incl. VAT","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Waiting to be refunded","captionVouchers":"Voucher amount","captionRefunded":"Refunded amount","captionRemaining":"Refundable amount","btnFixDiff":"Fix Difference","placeholderDescription":"Enter bank/card statement description for consumer. Max 140 characters","lblDescription":"Description (optional) ({characters}/140 characters)","descriptionHelp":"This will be shown on the consumer\'s bank or card statement when possible. The message will be truncated after 140 characters.","placeholderInternalDescription":"Enter your internal description","lblInternalDescription":"Internal description (optional)","internalDescriptionHelp":"This will be shown as a local description in the administration interface.","checkVerification":"I have verified the total refund amount and the configured quantities to refund and re-stock.","btnRefund":"Refund","btnFullRefund":"Full Refund","roundDiffItemAdded":"Rounding item"},"refunds":{"title":"Refunds in the Mollie Dashboard","linkMore":"More about refunds","grid":{"columns":{"amount":"Amount","status":"Status","description":"Description","internalDescription":"Internal description","composition":"Composition","date":"Date"},"lblNoComposition":"No composition available","btnCancelRefund":"Cancel this refund"}},"notifications":{"success":{"refund-created":"A refund has been created in Mollie. It may take 2 hours for the refund to complete. Until this time, you can cancel the refund.","refund-canceled":"The pending refund has been successfully cancelled and removed."},"error":{"low-amount":"Please enter an amount to be refunded.","refund-created":"Something went wrong creating a refund.","refund-canceled":"There was a problem when cancelling the pending refund. Please try it again in the Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucher Payments","VOUCHER_INFO_DESCRIPTION":"Mollie lets you easily accept payments in your online shop using Eco-, gift- and meal vouchers—a smart choice for boosting sales and satisfying your customers. The payment method \\"voucher\\" is only visible, if you have at least 1 product with an assigned voucher type in the cart.","VOUCHER_INFO_DEFAULTLANGUAGE":"Please note, this configuration can only be edited in your default language. Please change your language to modify the voucher type of this product.","VOUCHER_BTN_READMORE":"Read more","VOUCHER_TYPE_CAPTION":"Voucher type of product","VOUCHER_TYPE_VALUE_NONE":"None","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Meal","VOUCHER_TYPE_VALUE_VOUCHER":"Gift"},"modals":{"shipping":{"title":"Ship through Mollie","item":{"label":"Item:","noQuantity":"Please enter a quantity to ship.","shipAll":"Ship all","summary":{"quantity":"Quantity to ship","shipped":"Quantity shipped","shippable":"Quantity shippable"},"success":"The order has been successfully shipped."},"order":{"description":"The following item quantities will be shipped.","itemHeader":"Item","quantityHeader":"Quantity","originalQuantityHeader":"Quantity (shippable)"},"availableTracking":{"label":"Available tracking codes","hint":"Click one of these tracking codes to automatically fill in all data."},"showTracking":"Add tracking info for this shipment","tracking":{"carrier":"Carrier","code":"Code","url":"Url","invalid":"Please enter both Carrier and Code"},"confirmButton":"Ship order","cancelButton":"Cancel","selectAllButton":"Select all","resetButton":"Reset"},"cancel":{"title":"Cancel item through mollie","confirmButton":"Cancel item through mollie","cancelButton":"Close modal","resetStock":"Reset stocks","item":{"success":"Product canceled successfully","failed":{"quantityZero":"Quantity is 0","invalidLine":"Product does not exist in the order","quantityTooHigh":"Quantity is too high"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Ship Order (Mollie)","description":"Ship order in Mollie."},"modal":{"title":"Ship Order","description":"This action will automatically ship an order through Mollie. The flow sequence will receive the order number, and pass this on to the Mollie API. Successful shipments and failed shipments will be visible in the Mollie log files.","warningConfig":"Please make sure to turn off any additional automation for this type of action to avoid any interferences.\\nThe following activated features of this plugin might interfere with this action:","noWarnings":"No warnings"}},"refundOrder":{"editor":{"title":"Refund Order (Mollie)","description":"Refund order through Mollie."},"modal":{"title":"Refund Order","description":"This action will automatically start a refund through Mollie. The flow sequence will receive the order number, and pass this on to the Mollie API. Successful refunds and failed refunds will be visible in the Mollie log files.","warning":"Please keep in mind, that refunds might take up to 2 hours to be finalized and visible in the shop. Until then you can always cancel a pending refund either from the order page in Shopware or from the Mollie Dashboard.","warningConfig":"Please make sure to turn off any additional automation for this type of action to avoid any interferences."}},"warnings":{"automaticShipping":"Automatic shipping in plugin configuration"}}},"subscriptions":{"status":{"pending":"Pending","active":"Active","canceled":"Canceled","suspended":"Suspended","completed":"Completed","paused":"Paused","resumed":"Resumed","skipped":"Skipped"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Day(s)","TYPE_WEEKS":"Week(s)","TYPE_MONTHS":"Month(s)","confirm":{"cancelTitle":"End subscription?","cancel":"Cancel your customer\'s subscription.","pauseTitle":"Pause subscription?","pause":"Put the subscription on hold until you resume it again.","resumeTitle":"Resume subscription?","resume":"Continue the subscription again.","skipTitle":"Skip next instalment?","skip":"Skip the next instalment in the subscription. It continues automatically afterwards."},"alerts":{"cancelSuccess":"The subscription has been canceled successfully","pauseSuccess":"The subscription has been paused successfully","resumeSuccess":"The subscription has been resumed successfully","skipSuccess":"The subscription has been skipped successfully. The next payment has been updated."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Customer","status":"Status","description":"Description","amount":"Amount","nextPaymentAt":"Next Payment","prePaymentReminder":"Reminded at","canceledAt":"Canceled at","createdAt":"Created at"},"action":{"edit":"Edit subscription"},"deletedCustomer":"Deleted customer"},"detail":{"title":"Mollie subscription","buttonCancelSubscription":"Cancel subscription","labelDescription":"Description","labelAmount":"Amount","labelQuantity":"Quantity","labelMollieSubscription":"Mollie Subscription","labelMollieCustomer":"Mollie customer","labelMandateId":"Mandate","labelShopwareCustomer":"Shopware customer","labelCreatedAt":"Created at","buttonShowShopwareOrder":"Show Shopware order","buttonShowShopwareCustomer":"Show Shopware customer","cardTitleSubscription":"Subscription","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Next payment at","labelLastRemindedAt":"Last reminded at","labelCanceledAt":"Canceled at","buttonPauseSubscription":"Pause subscription","buttonResumeSubscription":"Resume subscription","buttonSkipSubscription":"Skip subscription","history":{"cardTitle":"History","colDate":"Date","colComment":"Comment","colStatusFrom":"Status (from)","colStatusTo":"Status (to)","colMollieSubscription":"Mollie subscription"}},"product":{"card-title":"Subscription","title":"Mollie Subscriptions","description":"Managing your recurring payments is easier than ever with our helpful features. Take your business to the next level with efficient tracking options, simple integrations, and more. With Mollie subscriptions, you can easily create subscription products and schedule recurring payments to take place at the configured interval and period.","mollieSubscriptionProduct":"Subscription Product","mollieSubscriptionIntervalAmount":"Repeat Payment every","mollieSubscriptionIntervalType":"Interval Unit","mollieSubscriptionRepetitionAmount":"Number or repetitions","mollieSubscriptionRepetitionPlaceholder":"Enter number or leave empty","infoDefaultLanguage":"Please note, this configuration can only be edited in your default language. Please change your language to modify the subscription settings of this product.","btnReadMore":"Read more"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subscription"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Credit Card data","buttonMolliePaymentLink":"Copy to Clipboard","columnRefunded":"Refunded","columnShipped":"Shipped","columnCanceled":"Canceled","labelMollieOrderId":"Mollie Order ID","labelMollieThirdPartyPaymentId":"Payment Reference","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Refunded amount","totalRefundsPending":"Waiting to be refunded","totalRemaining":"Refundable amount","totalVouchers":"Voucher amount","totalShipments":"Shipped amount ({quantity} items)","subscriptionBadge":"Subscription Order","refundManager":{"title":"Mollie Refund Manager","btnOpenRefundManager":"Open Refund Manager","btnCloseRefundManager":"Close Refund Manager"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Preferred iDeal issuer"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refund Manager"},"mollie_subscription":{"label":"Subscriptions"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Description"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Refund","subscription":"Subscription","webhookReceived":"Webhooks","status":"Status","started":"Started","ended":"Ended","paused":"Paused","renewalReminder":"Renewal Reminder","renewed":"Renewed","resumed":"Resumed","skipped":"Skipped","all":"All","canceled":"Canceled","expired":"Expired","partiallyRefunded":"Refunded (partially)","orderSuccess":"Order successful","orderFailed":"Order failed","orderCanceled":"Order canceled"}}}'),eK=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Abonnement | Mollie Abonnementen"},"businessEvents":{"mollie_checkout_order_success":" Bestelling succesvol","mollie_checkout_order_failed":" Bestelling mislukt","mollie_checkout_order_canceled":" Bestelling geannuleerd","mollie_webhook_received_All":" Mollie Webhook Ontvangen (Alle)","mollie_webhook_received_status_authorized":" Mollie Webhook Ontvangen (Geautoriseerd)","mollie_webhook_received_status_failed":" Mollie Webhook Ontvangen (Mislukt)","mollie_webhook_received_status_canceled":" Mollie Webhook Ontvangen (Geannuleerd)","mollie_webhook_received_status_expired":" Mollie Webhook Ontvangen (Vervallen)","mollie_webhook_received_status_pending":" Mollie Webhook Ontvangen (In Afwachting)","mollie_webhook_received_status_paid":" Mollie Webhook Ontvangen (Betaald)","mollie_webhook_received_status_completed":" Mollie Webhook Ontvangen (Voltooid)","mollie_webhook_received_status_refunded":" Mollie Webhook Ontvangen (Terugbetaald)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Ontvangen (Gedeeltelijk terugbetaald)","mollie_refund_started":" Mollie terugbetaling gestart","mollie_subscription_started":" Mollie abonnement gestart","mollie_subscription_ended":" Mollie abonnement voltooid","mollie_subscription_cancelled":" Mollie abonnement opgezegd","mollie_subscription_paused":" Mollie abonnement gepauzeerd","mollie_subscription_resumed":" Mollie abonnement hervat","mollie_subscription_skipped":" Mollie abonnement overgeslagen","mollie_subscription_renewed":" Mollie abonnement verlengd","mollie_subscription_renewal_reminder":" Mollie herinnering voor abonnementsverlenging"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Zoek in abonnementen...","general":{"mainMenuItemGeneral":"Mollie betalingen","descriptionTextModule":"Mollie betalingen","btnMollieActions":"Mollie acties","refundThroughMollie":"Terugbetaling via Mollie","shipThroughMollie":"Verzending door Mollie","cancelMollieItem":"Opzeggen via Mollie"},"config":{"info":{"title":"Hi {userName}, Welkom bij Mollie!","descriptionTop":"Onboarding is eenvoudig bij Mollie!","descriptionBottom":"Dat is alles!","descriptionFooter":"Als je meer wilt weten over onze plugin, bezoek dan onze offici\xeble documentatie pagina.","onboardingStep1":"Meld je aan voor een Mollie Account.","onboardingStep2":"Voer je API sleutels in de sectie hieronder in.","onboardingStep2TestMode":"Zet \'Test Mode\' aan als je alleen betalingen wilt testen.","onboardingStep3":"Wijs betaalmethoden toe aan je verkoopkanaal.","onboardingStep3Link":"naar je verkoopkanalen","btnDocumentation":"Documentatie","btnRequestSupport":"Support","btnTroubleshooting":"Troubleshooting Gids"},"api":{"apiLinkButton":"Haal jouw API sleutels van het Mollie Dashboard","testButton":"Controlle API Keys","testApiKeys":{"title":"Mollie Payments","apiKey":"API Key","isValid":"is geldig","isInvalid":"is ongeldig"}},"payments":{"format":{"placeholder":"Plaatshouder","preview":"Preview"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Betaalmethoden updaten","succeeded":"De betaalmethoden zijn succesvol geupdated.","failed":"De betaalmethoden konden niet worden geupdated."},"mollieLimits":{"link":"Toon Mollie-beschikbaarheidsregels voor betaalmethoden"}},"rounding":{"info1":"Shopware kan valuta-instellingen gebruiken om te berekenen hoe het totaal van een bestelling wordt afgerond. Dit omvat het aantal decimalen in jouw productprijzen en het dichtstbijzijnde afrondingsinterval, zoals 0,50 of 1,00.","info2":"Deze instellingen kunnen leiden tot een andere totale som dan de totale som van lineitems. Wanneer Mollie deze bedragen kruiselings controleert en vaststelt dat ze niet overeenkomen, ontstaat er een fout bij het afrekenen.","info3":"Je kunt deze functie gebruiken om afrondingsproblemen bij het afrekenen te voorkomen. Indien ingeschakeld, voegt het een apart lineitem toe aan je Mollie Dashboard met het afrondingsverschil, en betalen je klanten de totale som zoals berekend door Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Het is niet mogelijk om Klarna Pay now, Klarna Slice it of Klarna Pay later als methode te gebruiken wanneer de vervaldatum meer dan 28 dagen in de toekomst ligt, tenzij een ander maximum is overeengekomen tussen de merchant en Klarna.","bankTransferDueDateLimitReached":"Het is niet mogelijk om de orderlevensduur langer dan 100 dagen in te stellen."},"support":{"modalTitle":"Verzoek support van Mollie","btnCancel":"Cancel","btnConfirm":"Verzoek support","btnSupport":"Meer over onze ondersteuning","form":{"name":"Uw naam","email":"Uw e-mail","recipient":"Stuur verzoek naar","subject":"Onderwerp","message":"Message"},"data":{"header":"Gegevens verzonden naar Mollie:","other":"Andere:","shopwareVersion":"Shopwareversie","pluginLogs":"{plugin} logbestanden","pluginConfiguration":"{plugin} configuratie","pluginConfigurationHelpText":"API-sleutels zijn uitgesloten.","paymentMethods":"Informatie over betaalmethoden","paymentMethodsHelpText":"Bevat informatie over betaalmethoden, welke zijn gekoppeld aan de verkoopkanalen, en de betreffende status ervan in uw Mollie account."},"success":"Het ondersteuningsverzoek is succesvol verzonden. We doen ons best om zo snel mogelijk te antwoorden","error":"Helaas was er een probleem met de verzending via Shopware. Probeer het opnieuw of stuur ons direct een e-mail."}},"rules":{"itemSubscriptionRule":"Item is subscription (Mollie)","cartSubscriptionRule":"Cart has subscription items (Mollie)"},"refunds":{"status":{"queued":"In wachtrij","pending":"In afwachting","processing":"In behandeling","refunded":"Terugbetaald","failed":"Mislukt","description":{"queued":"De terugbetaling wordt in de wachtrij geplaatst totdat er voldoende saldo is om de terugbetaling te verwerken. U kunt de terugbetaling nog steeds annuleren.","pending":"De terugbetaling wordt de volgende werkdag naar de bank gestuurd. U kunt de terugbetaling nog annuleren.","processing":"De terugbetaling is naar de bank gestuurd. Het bedrag wordt zo spoedig mogelijk overgemaakt op de rekening van de klant.","refunded":"Het restitutiebedrag is overgemaakt naar de klant.","failed":"De terugbetaling is mislukt na verwerking. De klant heeft bijvoorbeeld zijn/haar bankrekening opgeheven. Het geld zal worden teruggestort op de rekening."}}},"refund-manager":{"general":{"unitQuantity":"st."},"acl":{"warningCreate":"U heeft geen rechten om terugbetalingen te maken","warningCancel":"U heeft geen rechten om terugbetalingen te annuleren"},"cart":{"title":"Bestelling ##orderNumber##","btnSelectAll":"Alles selecteren","btnResetForm":"Formulier resetten","linkHowTo":"Hoe gebruik je dit formulier?","grid":{"columns":{"item":"Artikel","productNumber":"Artikelnummer","unitPrice":"Prijs per eenheid","quantity":"Aantal","refunded":"Vergoed","refundQuantity":"Vergoeding","totalPrice":"Totaal","refundAmount":"Vergoeding","resetStock":"Voorraad resetten"},"btnResetLine":"Rij resetten","checkDeductPromotion":"Promotie aftrekken","checkRefundTax":"Refund VAT"},"roundDiffItemAdded":"Automatisch afrondingsitem toegevoegd"},"instructions":{"linkResetTutorials":"Handleidingen resetten","btnToggleTutorial":"Handleidingen tonen/verbergen","titleFullRefund":"Volledige terugbetaling","textFullRefund":"Gebruik gewoon de knop voor de volledige terugbetaling. Dit zorgt ervoor dat alle artikelen worden gemarkeerd als terugbetaald en het volledige bedrag wordt vergoed aan de klant.","titleStockReset":"Voorraad resetten","textStockReset":"Je kunt de beschikbare voorraad automatisch verhogen door de hoeveelheid in te voeren die u weer op voorraad wilt hebben. Dit moet je invoeren voordat je overgaat tot een volledige of gedeeltelijke terugbetaling. Het terugzetten van de voorraad kan op een flexibele manier gecombineerd worden met het eigenlijke terugbetalingsproces.","titleShipping":"Verzendkosten","textShipping":"Verzendkosten kunnen worden terugbetaald zoals elk ander artikel. Voer de volledige hoeveelheid in of een aangepast deelbedrag en ga verder met de terugbetaling. Het terugbetalen van verzendkosten kan op een flexibele manier gecombineerd worden met het eigenlijke terugbetalingsproces van artikelen.","titlePartialAmount":"Gedeeltelijke terugbetaling (enkel een bedrag)","textPartialAmount":"Voer gewoon het deelbedrag in het tekstveld in en start de terugbetaling.","titlePartialItems":"Gedeeltelijke terugbetaling (met artikelen)","textPartialItems":"Als u hoeveelheden en artikelen als terugbetaald wilt markeren in Mollie, gebruik dan bovenstaand formulier. Stel uw hoeveelheden in en geef een aangepast bedrag op voor elk item dat zal worden terugbetaald. De totale som zal dan zichtbaar zijn in het tekstveld met het finale terugbetalingsbedrag. Vergeet niet dat het nog steeds mogelijk is om dit eindbedrag aan te passen voordat u de terugbetaling start.","titlePartialPromotions":"Gedeeltelijke terugbetaling (met promotions)","textPartialPromotions":"Als je een promotion in je winkelwagen hebt, dan is de promotion een eigen line item. Als je alle afgeprijsde artikelen wilt terugbetalen, dan kann je de totale waarde van alle artikelen terugbetalen en ook de promotie zelf. Als u echter slechts een paar afgeprijsde artikelen wilt terugbetalen, kunt je de aangepaste korting automatisch aftrekken voor elk afzonderlijk artikel. Je kunt natuurlijk altijd de waarden veranderen mochten ze niet juist zijn.","titleRoundingDiff":"Afrondingsverschil","textRoundingDiff":"Een volledige terugbetaling is inclusief afrondingsverschillen"},"summary":{"dataLoading":"Gegevens worden geladen...","headerExcludingVat":"Excl. BTW","headerIncludingVat":"Incl. BTW","captionTotal":"Totaal","captionTotalTaxFree":"Totaal","captionPendingRefunds":"Wachtend op terugbetaling","captionVouchers":"Voucher bedrag","captionRefunded":"Terugbetaald bedrag","captionRemaining":"Terugbetaalbaar bedrag","btnFixDiff":"Herstel verschil","placeholderDescription":"Voer uw bank/card statement beschrijving in. Max. 140 tekens","lblDescription":"Beschrijving (optioneel) ({characters}/140 tekens)","descriptionHelp":"Dit wordt indien mogelijk getoond op het bank- of kaartafschrift van de consument. Het bericht wordt afgekapt na 140 tekens.","placeholderInternalDescription":"Voer uw interne beschrijving in.","lblInternalDescription":"Interne beschrijving (optioneel)","internalDescriptionHelp":"Dit wordt getoond als een lokale beschrijving in de administratie-interface.","checkVerification":"Ik heb het totale restitutiebedrag en de geconfigureerde hoeveelheden voor restitutie en herbevoorrading geverifieerd.","btnRefund":"Terugbetaling","btnFullRefund":"Volledige terugbetaling","roundDiffItemAdded":"Afrondingsitem"},"refunds":{"title":"Terugbetalingen in het Mollie Dashboard","linkMore":"Meer over terugbetalingen","grid":{"columns":{"amount":"Bedrag","status":"Status","description":"Beschrijving","internalDescription":"Interne beschrijving","composition":"Samenstelling","date":"Datum"},"lblNoComposition":"Geen samenstelling beschikbaar","btnCancelRefund":"Annuleer deze terugbetaling"}},"notifications":{"success":{"refund-created":"Er is een terugbetaling aangemaakt in Mollie. Het kan 2 uur duren voordat de terugbetaling is voltooid. Tot die tijd kan de terugbetaling worden geannuleerd.","refund-canceled":"De uitstaande terugbetaling is met succes geannuleerd en verwijderd."},"error":{"low-amount":"Vull een terug te betalen bedrag in","refund-created":"Er is iets misgegaan bij het aanmaken van een terugbetaling.","refund-canceled":"Er is een probleem opgetreden bij het annuleren van de uitstaande terugbetaling. Probeer het opnieuw in het Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucher Betalingen","VOUCHER_INFO_DESCRIPTION":"Met Mollie kunt u in uw online winkel eenvoudig betalingen accepteren met Eco-, cadeau- en maaltijdcheques - een slimme keuze om de verkoop te stimuleren en uw klanten tevreden te stellen. De betaalmethode \\"voucher\\" is alleen zichtbaar als u ten minste 1 product met de toegewezen type \\"voucher\\", in de winkelwagen heeft.","VOUCHER_INFO_DEFAULTLANGUAGE":"Let op, deze configuratie kan alleen worden bewerkt in uw standaard taal. Wijzig uw taal om het vouchertype van dit product te veranderen.","VOUCHER_BTN_READMORE":"Lees meer","VOUCHER_TYPE_CAPTION":"Vouchertype voor product","VOUCHER_TYPE_VALUE_NONE":"Geen vouchertype","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Meal","VOUCHER_TYPE_VALUE_VOUCHER":"Gift"},"modals":{"shipping":{"title":"Verzenden bij Mollie","item":{"label":"Product:","noQuantity":"Voer een hoeveelheid in om te verzenden.","shipAll":"Verzend alles","summary":{"quantity":"Te verzenden hoeveelheid","shipped":"Verzonden hoeveelheid","shippable":"Verzendbare hoeveelheid"},"success":"De bestelling is succesvol verzonden."},"order":{"description":"De volgende product aantallen zullen worden verzonden.","itemHeader":"Product","quantityHeader":"Aantal","originalQuantityHeader":"Aantal (verzendbaar)"},"availableTracking":{"label":"Beschikbare tracking codes","hint":"Klik op een van deze tracking codes om automatisch alle gegevens in te vullen."},"showTracking":"Voeg tracking info toe aan deze zending","tracking":{"carrier":"Carrier","code":"Code","url":"Url","invalid":"Voer zowel Carrier als Code in"},"confirmButton":"Bestelling verzenden","cancelButton":"Annuleren","selectAllButton":"Selecteer alles","resetButton":"Resetten"},"cancel":{"title":"Product in Mollie afkorting","confirmButton":"Product in Mollie afkorting","cancelButton":"Annuleren","resetStock":"Voorraad resetten","item":{"success":"Product geannuleerd","failed":{"quantityZero":"Aantal is 0","invalidLine":"Product bestaat niet in de bestelling","quantityTooHigh":"Het aantal is te hoog"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Bestelling verzenden (Mollie)","description":"Bestelling is gemarkeerd als verzonden in Mollie."},"modal":{"title":"Bestelling verzenden","description":"Deze actie zal automatisch een bestelling verzenden via Mollie. De flow sequence ontvangt het ordernummer, en geeft dit door aan de Mollie API. Succesvolle verzendingen en mislukte verzendingen zullen zichtbaar zijn in de Mollie logbestanden.","warningConfig":"Schakel alle extra automatiseringen uit die eventueel in conflict komen met deze Flow Builder actie. De volgende geactiveerde features in deze plugin kunnen elkaar kruisen met deze actie:","noWarnings":"Geen waarschuwingen"}},"refundOrder":{"editor":{"title":"Bestelling terugbetalen (Mollie)","description":"Bestelling zal worden terugbetaald via Mollie."},"modal":{"title":"Bestelling terugbetalen","description":"Deze actie zal automatisch een terugbetaling starten via Mollie. De flow sequence ontvangt het ordernummer, en geeft dit door aan de Mollie API. Succesvolle refunds en mislukte refunds zullen zichtbaar zijn in de Mollie logbestanden.","warning":"Houd er rekening mee dat het tot 2 uur kan duren voordat een terugbetaling zichtbaar is in de shop. Tot die tijd kunt u ge\xefnitieerde terugbetalingen op elk moment annuleren op de bestelpagina in de shop, of direct in het Mollie Dashboard.","warningConfig":"Deactiveer alle extra automatiseringen die kunnen collideren met deze Flow Builder actie."}},"warnings":{"automaticShipping":"Automatische verzending in plugin configuratie"}}},"subscriptions":{"status":{"pending":"In afwachting","active":"Actief","canceled":"Geannuleerd","suspended":"Gepauzeerd","completed":"Voltooid","paused":"Onderbroken","resumed":"Hervat","skipped":"Overgeslagen"},"navigation":{"title":"Mollie Abonnementen"},"TYPE_DAYS":"Dag(en)","TYPE_WEEKS":"Weken","TYPE_MONTHS":"Maanden","confirm":{"cancelTitle":"Abonnement be\xebindigen?","cancel":"Annuleer het abonnement van uw klant.","pauseTitle":"Abonnement pauzeren?","pause":"Zet het abonnement in de wacht totdat je het weer hervat.","resumeTitle":"Abonnement hervatten?","resume":"Zet het abonnement weer voort.","skipTitle":"Volgende betaling overslaan?","skip":"Sla het volgende betaling van het abonnement over. Daarna gaat het automatisch verder."},"alerts":{"cancelSuccess":"Het abonnement is succesvol opgezegd","pauseSuccess":"Het abonnement is succesvol onderbroken","resumeSuccess":"Het abonnement is succesvol voortgezet","skipSuccess":"Het abonnement is succesvol opgeschort. De volgende betalingsdatum is bijgewerkt."},"list":{"title":"Mollie Abonnementen","columns":{"customer":"Klant","status":"Status","description":"Beschrijving","amount":"Bedrag","nextPaymentAt":"Volgende betaling","prePaymentReminder":"Herinnerd op","canceledAt":"Geannuleerd op","createdAt":"Gecre\xeberd op"},"action":{"edit":"Abonnement bewerken"},"deletedCustomer":"Klant verwijderd"},"detail":{"title":"Mollie Abonnement","buttonCancelSubscription":"Abonnement opzeggen","labelDescription":"Omschrijving","labelAmount":"Bedrag","labelQuantity":"Hoeveelheid","labelMollieSubscription":"Mollie Abonnement","labelMollieCustomer":"Mollie klant","labelMandateId":"Mandaat","labelShopwareCustomer":"Shopware klant","labelCreatedAt":"Gecre\xeberd op","buttonShowShopwareOrder":"Toon Shopware bestelling","buttonShowShopwareCustomer":"Show Shopware klant","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Volgende betaling op","labelLastRemindedAt":"Laatst herinnerd op","labelCanceledAt":"Geannuleerd op","buttonPauseSubscription":"Abonnement pauzeren","buttonResumeSubscription":"Abonnement hervatten","buttonSkipSubscription":"Bestelling overslaan","history":{"cardTitle":"Historie","colDate":"Datum","colComment":"commentaar","colStatusFrom":"Status (van)","colStatusTo":"Status (tot)","colMollieSubscription":"Mollie Abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie Abonnementen","description":"Het beheren van uw terugkerende betalingen is eenvoudiger dan ooit met onze handige functies. Breng uw bedrijf naar een hoger niveau met effici\xebnte trackingopties, eenvoudige integraties en meer. Met Mollie-abonnementen kun je eenvoudig abonnementsproducten maken en terugkerende betalingen plannen die plaatsvinden op het ingestelde interval en de ingestelde periode.","mollieSubscriptionProduct":"Is dit een abonnementsproduct?","mollieSubscriptionIntervalAmount":"Herhaal betaling elke","mollieSubscriptionIntervalType":"Type abonnementsinterval","mollieSubscriptionRepetitionAmount":"Herhaal betaling","mollieSubscriptionRepetitionPlaceholder":"Nummer invoeren of leeg laten","infoDefaultLanguage":"Let op, deze configuratie kan alleen in uw standaardtaal worden bewerkt. Wijzig uw taal om de abonnementsinstellingen van dit product te wijzigen.","btnReadMore":"Lees meer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Credit Card data","buttonMolliePaymentLink":"Kopieer naar Klembord","columnRefunded":"Terugbetaald","columnShipped":"Verzonden","columnCanceled":"Geannuleerd","labelMollieOrderId":"Mollie Order ID","labelMollieThirdPartyPaymentId":"Betalingskenmerk","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Terugbetaald bedrag","totalRefundsPending":"Wachtend op terugbetaling","totalRemaining":"Terug te betalen","totalVouchers":"Voucher","totalShipments":"Verzonden bedrag ({quantity} items)","subscriptionBadge":"Abonnement besteling","refundManager":{"title":"Terugbetaling via Mollie","btnOpenRefundManager":"Refund Manager openen","btnCloseRefundManager":"Refund Manager sluiten"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Voorkeur iDeal verstrekker"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refund Manager"},"mollie_subscription":{"label":"Abonnementen"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Beschrijving"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Terugbetaling","subscription":"Abonnement","webhookReceived":"Webhook","status":"Toestand","started":"Begonnen","ended":"Ge\xebindigd","paused":"Onderbroken","renewalReminder":"Verlengingsherinnering","renewed":"Vernieuwd","resumed":"Hervat","skipped":"Overgeslagen","all":"Alle","canceled":"Geannuleerd","expired":"Verlopen","partiallyRefunded":"Terugbetaald (gedeeltelijk)","orderSuccess":"Bestelling succesvol","orderFailed":"Bestelling mislukt","orderCanceled":"Bestelling geannuleerd"}}}'),eq=JSON.parse('{"global":{"entities":{"mollie_subscription":"Abbonamento Mollie | Abbonamenti Mollie"},"businessEvents":{"mollie_checkout_order_success":" Ordine riuscito","mollie_checkout_order_failed":" Ordine non riuscito","mollie_checkout_order_canceled":" Ordine annullato","mollie_webhook_received_All":" Webhook Mollie ricevuto (tutti)","mollie_webhook_received_status_authorized":" Webhook Mollie ricevuto (autorizzato)","mollie_webhook_received_status_failed":" Webhook Mollie ricevuto (fallito)","mollie_webhook_received_status_canceled":" Webhook Mollie ricevuto (annullato)","mollie_webhook_received_status_expired":" Webhook ricevuto da Mollie (scaduto)","mollie_webhook_received_status_pending":" Webhook Mollie ricevuto (in attesa)","mollie_webhook_received_status_paid":" Webhook Mollie ricevuto (pagato)","mollie_webhook_received_status_completed":" Webhook Mollie ricevuto (completato)","mollie_webhook_received_status_refunded":" Webhook Mollie ricevuto (rimborsato)","mollie_webhook_received_status_partially_refunded":" Webhook Mollie ricevuto (parzialmente rimborsato)","mollie_refund_started":" Rimborso Mollie iniziato","mollie_subscription_started":" Abbonamento Mollie iniziato","mollie_subscription_ended":" Abbonamento Mollie completato","mollie_subscription_cancelled":" Abbonamento Mollie annullato","mollie_subscription_paused":" Abbonamento Mollie messo in pausa","mollie_subscription_resumed":" Abbonamento Mollie ripreso","mollie_subscription_skipped":" Abbonamento Mollie saltato","mollie_subscription_renewed":" Abbonamento Mollie rinnovato","mollie_subscription_renewal_reminder":" Promemoria Mollie per il rinnovo dell\'abbonamento"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Modulo Mollie","searchPlaceholder":"Cerca abbonamenti...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Azioni Mollie","refundThroughMollie":"Rimborsa tramite Mollie","shipThroughMollie":"Spedizione tramite Mollie","cancelMollieItem":"Annulla tramite Mollie"},"config":{"info":{"title":"Ciao {userName}, benvenuto su Mollie!","descriptionTop":"L\'onboarding \xe8 facile con Mollie!","descriptionBottom":"Ecco fatto!","descriptionFooter":"Se vuoi saperne di pi\xf9 sul nostro plugin, visita la nostra pagina di documentazione ufficiale.","onboardingStep1":"Iscriviti per un account Mollie.","onboardingStep2":"Inserisci le tue chiavi API nella sezione sottostante.","onboardingStep2TestMode":"Attiva la modalit\xe0 \\"Test\\" se desideri testare solo i pagamenti.","onboardingStep3":"Assegna i metodi di pagamento al tuo canale di vendita.","onboardingStep3Link":"ai tuoi canali di vendita","btnDocumentation":"Documentazione","btnRequestSupport":"Assistenza","btnTroubleshooting":"Guida alla risoluzione dei problemi"},"api":{"apiLinkButton":"Ottieni le chiavi API dalla Mollie Dashboard","testButton":"Chiavi Test API","testApiKeys":{"title":"Mollie Payments","apiKey":"Chiave API","isValid":"\xe8 valido","isInvalid":"non \xe8 valido"}},"payments":{"format":{"placeholder":"Segnaposto","preview":"Anteprima"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Aggiorna i metodi di pagamento","succeeded":"I metodi di pagamento sono stati aggiornati con successo.","failed":"Non \xe8 stato possibile aggiornare i metodi di pagamento."},"mollieLimits":{"link":"Mostra le regole di disponibilit\xe0 di Mollie per i metodi di pagamento"}},"rounding":{"info1":"Shopware pu\xf2 utilizzare le impostazioni di valuta per calcolare come arrotonda il totale finale di un ordine. Questo include il numero di decimali nei prezzi dei tuoi prodotti e l\'intervallo di arrotondamento pi\xf9 vicino, come 0,50 o 1,00.","info2":"Queste impostazioni possono portare a un totale finale diverso dalla somma totale delle righe dell\'ordine. Quando Mollie verifica questi importi e scopre che non corrispondono, si verifica un errore al momento del checkout.","info3":"Puoi utilizzare questa funzione per evitare problemi di arrotondamento durante il checkout. Quando abilitata, aggiunge una riga separata nella tua Mollie Dashboard per la differenza di arrotondamento e i tuoi clienti pagano il totale finale calcolato da Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Non \xe8 possibile utilizzare Klarna Pay now, Klarna Slice it o Klarna Pay later come metodo quando la data di scadenza \xe8 oltre 28 giorni nel futuro, a meno che non venga concordato un altro massimo tra il commerciante e Klarna.","bankTransferDueDateLimitReached":"Non \xe8 possibile impostare la durata dell\'ordine superiore a 100 giorni."},"support":{"modalTitle":"Richiedi assistenza da Mollie","btnCancel":"Annulla","btnConfirm":"Richiedi assistenza","btnSupport":"Per saperne di pi\xf9 sulla nostra assistenza","form":{"name":"Il tuo nome","email":"Il tuo indirizzo e-mail","recipient":"Invia la richiesta a","subject":"Oggetto","message":"Messaggio"},"data":{"header":"Dati inviati a Mollie:","other":"Altro:","shopwareVersion":"Versione Shopware","pluginLogs":"File di log {plugin}","pluginConfiguration":"Configurazione {plugin}","pluginConfigurationHelpText":"Le chiavi API sono escluse.","paymentMethods":"Dati sul metodo di pagamento","paymentMethodsHelpText":"Contiene informazioni su quali metodi di pagamento sono attivi, assegnati a ciascun canale di vendita e sul loro stato nel tuo account Mollie."},"success":"La richiesta di assistenza \xe8 stata inviata con successo. Faremo del nostro meglio per rispondere il prima possibile","error":"Si \xe8 verificato un problema durante l\'invio della mail tramite Shopware. Per favore riprova o contattaci direttamente tramite e-mail."}},"rules":{"itemSubscriptionRule":"Articolo in abbonamento (Mollie)","cartSubscriptionRule":"Carrello con abbonamenti (Mollie)"},"refunds":{"status":{"queued":"In coda","pending":"In attesa","processing":"Elaborazione in corso","refunded":"Rimborsato","failed":"Non riuscito","description":{"queued":"Il rimborso \xe8 in coda fino a quando non ci sar\xe0 abbastanza saldo per elaborarlo. Puoi comunque annullare il rimborso.","pending":"Il rimborso sar\xe0 inviato alla banca il giorno lavorativo successivo. Puoi comunque annullare il rimborso.","processing":"Il rimborso \xe8 stato inviato alla banca. L\'importo del rimborso sar\xe0 trasferito sul conto del consumatore il prima possibile.","refunded":"L\'importo del rimborso \xe8 stato trasferito al consumatore.","failed":"Il rimborso non \xe8 riuscito dopo l\'elaborazione. Ad esempio, il cliente ha chiuso il proprio conto bancario. I fondi saranno restituiti sul tuo conto."}}},"refund-manager":{"general":{"unitQuantity":"quantit\xe0"},"acl":{"warningCreate":"Non hai i permessi per creare rimborsi","warningCancel":"Non hai i permessi per annullare i rimborsi"},"cart":{"title":"Ordine ##orderNumber##","btnSelectAll":"Seleziona tutti","btnResetForm":"Reimposta modulo","linkHowTo":"Come usare questo modulo?","grid":{"columns":{"item":"Articolo","productNumber":"Numero di prodotto","unitPrice":"Prezzo unitario","quantity":"Quantit\xe0","refunded":"Rimborsato","refundQuantity":"Rimborso","totalPrice":"Totale","refundAmount":"Rimborso","resetStock":"Reimposta stock"},"btnResetLine":"Reimposta la linea","checkDeductPromotion":"Deduci promozione","checkRefundTax":"Rimborsa IVA"},"roundDiffItemAdded":"\xc8 stato aggiunto un elemento di arrotondamento automatico"},"instructions":{"linkResetTutorials":"Reimposta tutorial","btnToggleTutorial":"Mostra/Nascondi Tutorial","titleFullRefund":"Rimborso totale","textFullRefund":"Utilizza semplicemente il pulsante per il rimborso totale. In questo modo, tutti i tuoi articoli saranno contrassegnati come rimborsati e l\'intero importo sar\xe0 restituito al cliente.","titleStockReset":"Reimpostazione stock","textStockReset":"Puoi aumentare automaticamente lo stock disponibile inserendo la quantit\xe0 che desideri rimettere in stock. Basta inserirla prima di procedere con un rimborso totale o parziale. La reimpostazione dello stock pu\xf2 essere combinata in modo flessibile con il processo effettivo di rimborso.","titleShipping":"Spedizione","textShipping":"Gli articoli di spedizione possono essere rimborsati come qualsiasi altro articolo di prodotto. Inserisci la quantit\xe0 totale o un importo parziale personalizzato e procedi con il rimborso. Il rimborso dei costi di spedizione pu\xf2 essere combinato in modo flessibile con il processo effettivo di rimborso degli articoli.","titlePartialAmount":"Rimborso parziale (solo l\'importo)","textPartialAmount":"Basta inserire l\'importo parziale nel campo di testo e avviare il rimborso.","titlePartialItems":"Rimborso parziale (con articoli)","textPartialItems":"Se desideri segnare quantit\xe0 e articoli come rimborsati in Mollie, utilizza il modulo sopra. Imposta le tue quantit\xe0 e fornisci un importo personalizzato per ogni articolo che verr\xe0 rimborsato. La somma totale sar\xe0 poi visibile nel campo di testo dell\'importo finale del rimborso. Ricorda, \xe8 ancora possibile modificare questo importo finale prima di avviare il rimborso.","titlePartialPromotions":"Rimborso parziale (con promozioni)","textPartialPromotions":"Se hai una promozione nel tuo carrello, allora la promozione \xe8 un articolo separato nella riga. Se desideri rimborsare tutti gli articoli scontati, procedi e rimborsa i loro valori totali e l\'intero articolo della promozione. Tuttavia, se desideri rimborsare solo alcuni articoli scontati, puoi dedurre automaticamente lo sconto applicato per ogni singolo articolo nella riga. Puoi ovviamente sempre modificare i valori se non sono corretti.","titleRoundingDiff":"Differenza di arrotondamento","textRoundingDiff":"Un rimborso completo includer\xe0 le differenze di arrotondamento"},"summary":{"dataLoading":"Caricamento dei dati in corso...","headerExcludingVat":"IVA esclusa","headerIncludingVat":"IVA inclusa","captionTotal":"Totale","captionTotalTaxFree":"Totale","captionPendingRefunds":"In attesa del rimborso","captionVouchers":"Importo del voucher","captionRefunded":"Importo rimborsato","captionRemaining":"Importo rimborsabile","btnFixDiff":"Correggi la differenza","placeholderDescription":"Inserisci la descrizione dell\'estratto conto bancario/carta per il consumatore. Massimo 140 caratteri","lblDescription":"Descrizione (opzionale) ({characters}/140 caratteri)","descriptionHelp":"Questo verr\xe0 mostrato sul resoconto bancario o della carta del consumatore quando possibile. Il messaggio sar\xe0 troncato dopo 140 caratteri.","placeholderInternalDescription":"Inserisci la tua descrizione interna","lblInternalDescription":"Descrizione interna (opzionale)","internalDescriptionHelp":"Questo sar\xe0 mostrato come descrizione locale nell\'interfaccia di amministrazione.","checkVerification":"Ho verificato l\'importo totale del rimborso e le quantit\xe0 configurate per il rimborso e il reintegro dello stock.","btnRefund":"Rimborso","btnFullRefund":"Rimborso totale","roundDiffItemAdded":"Elemento di arrotondamento"},"refunds":{"title":"Rimborsi nella Mollie Dashboard","linkMore":"Maggiori informazioni sui rimborsi","grid":{"columns":{"amount":"Importo","status":"Stato","description":"Descrizione","internalDescription":"Descrizione interna","composition":"Composizione","date":"Data"},"lblNoComposition":"Nessuna composizione disponibile","btnCancelRefund":"Annulla questo rimborso"}},"notifications":{"success":{"refund-created":"Un rimborso \xe8 stato creato in Mollie. Potrebbero essere necessarie fino a 2 ore per completare il rimborso. Fino a quel momento, puoi annullare il rimborso.","refund-canceled":"Il rimborso in attesa \xe8 stato annullato e rimosso con successo."},"error":{"low-amount":"Inserisci un importo da rimborsare.","refund-created":"Si \xe8 verificato un problema durante la creazione del rimborso.","refund-canceled":"Si \xe8 verificato un problema durante l\'annullamento del rimborso in attesa. Riprova nella Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Buono","VOUCHER_INFO_TITLE":"Pagamenti con buono","VOUCHER_INFO_DESCRIPTION":"Mollie ti permette di accettare facilmente pagamenti nel tuo negozio online utilizzando buoni ecologici, buoni regalo e buoni pasto, una scelta intelligente per aumentare le vendite e soddisfare i tuoi clienti. Il metodo di pagamento \\"voucher\\" \xe8 visibile solo se hai almeno 1 prodotto con un tipo di voucher assegnato nel carrello.","VOUCHER_INFO_DEFAULTLANGUAGE":"Si prega di notare che questa configurazione pu\xf2 essere modificata solo nella lingua predefinita. Cambia la tua lingua per modificare il tipo di voucher di questo prodotto.","VOUCHER_BTN_READMORE":"Leggi di pi\xf9","VOUCHER_TYPE_CAPTION":"Tipo di buono del prodotto","VOUCHER_TYPE_VALUE_NONE":"Nessuno","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Pasto","VOUCHER_TYPE_VALUE_VOUCHER":"Regalo"},"modals":{"shipping":{"title":"Spedisci tramite Mollie","item":{"label":"Articolo:","noQuantity":"Inserisci una quantit\xe0 da spedire.","shipAll":"Spedisci tutto","summary":{"quantity":"Quantit\xe0 da spedire","shipped":"Quantit\xe0 spedita","shippable":"Quantit\xe0 spedibile"},"success":"L\'ordine \xe8 stato spedito con successo."},"order":{"description":"Le seguenti quantit\xe0 di articoli saranno spedite.","itemHeader":"Articolo","quantityHeader":"Quantit\xe0","originalQuantityHeader":"Quantit\xe0 (spedibile)"},"availableTracking":{"label":"Codici di tracciamento disponibili","hint":"Fai clic su uno di questi codici di tracciamento per compilare automaticamente tutti i dati."},"showTracking":"Aggiungi le informazioni di tracciamento per questa spedizione","tracking":{"carrier":"Vettore","code":"Codice","url":"Url","invalid":"Per favore, inserisci sia il vettore che il codice"},"confirmButton":"Spedisci l\'ordine","cancelButton":"Annulla","selectAllButton":"Seleziona tutto","resetButton":"Reimposta"},"cancel":{"title":"Annulla l\'articolo tramite Mollie","confirmButton":"Annulla l\'articolo tramite Mollie","cancelButton":"Chiudi finestra modale","resetStock":"Reimposta stock","item":{"success":"Prodotto annullato con successo","failed":{"quantityZero":"La quantit\xe0 \xe8 0","invalidLine":"Il prodotto non esiste nell\'ordine","quantityTooHigh":"La quantit\xe0 \xe8 troppo alta"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Spedisci l\'ordine (Mollie)","description":"Spedisci l\'ordine in Mollie."},"modal":{"title":"Spedisci l\'ordine","description":"Questa azione spedir\xe0 automaticamente un ordine tramite Mollie. La sequenza del flusso ricever\xe0 il numero dell\'ordine e lo trasmetter\xe0 al Mollie API. Le spedizioni riuscite e quelle fallite saranno visibili nei file di log di Mollie.","warningConfig":"Assicurati di disattivare qualsiasi automazione aggiuntiva per questo tipo di azione per evitare interferenze.\\nLe seguenti funzionalit\xe0 attivate di questo plugin potrebbero interferire con questa azione:","noWarnings":"Nessun avviso"}},"refundOrder":{"editor":{"title":"Rimborsa ordine (Mollie)","description":"Rimborsa ordine tramite Mollie."},"modal":{"title":"Rimborsa ordine","description":"Questa azione avvier\xe0 automaticamente un rimborso tramite Mollie. La sequenza del flusso ricever\xe0 il numero dell\'ordine e lo trasmetter\xe0 al Mollie API. I rimborsi riusciti e quelli falliti saranno visibili nei file di log di Mollie.","warning":"Si prega di tenere presente che i rimborsi potrebbero richiedere fino a 2 ore per essere finalizzati e visibili nel negozio. Fino ad allora, \xe8 sempre possibile annullare un rimborso in sospeso sia dalla pagina dell\'ordine in Shopware che dalla Mollie Dashboard.","warningConfig":"Assicurati di disattivare qualsiasi automazione aggiuntiva per questo tipo di azione per evitare interferenze."}},"warnings":{"automaticShipping":"Spedizione automatica nella configurazione del plugin"}}},"subscriptions":{"status":{"pending":"In attesa","active":"Attivo","canceled":"Annullato","suspended":"Sospeso","completed":"Completato","paused":"In pausa","resumed":"Ripreso","skipped":"Saltato"},"navigation":{"title":"Abbonamenti Mollie"},"TYPE_DAYS":"Giorno/i","TYPE_WEEKS":"Settimana/e","TYPE_MONTHS":"Mese/i","confirm":{"cancelTitle":"Termina l\'abbonamento?","cancel":"Annulla l\'abbonamento del tuo cliente.","pauseTitle":"Metti l\'abbonamento in pausa?","pause":"Metti in pausa l\'abbonamento finch\xe9 non lo riprendi.","resumeTitle":"Riprendere l\'abbonamento?","resume":"Continua l\'abbonamento di nuovo.","skipTitle":"Saltare la prossima rata?","skip":"Salta la prossima rata dell\'abbonamento. Successivamente, l\'abbonamento continuer\xe0 automaticamente."},"alerts":{"cancelSuccess":"L\'abbonamento \xe8 stato annullato con successo","pauseSuccess":"L\'abbonamento \xe8 stato messo in pausa con successo","resumeSuccess":"L\'abbonamento \xe8 stato ripreso con successo","skipSuccess":"L\'abbonamento \xe8 stato saltato con successo. Il prossimo pagamento \xe8 stato aggiornato."},"list":{"title":"Abbonamenti Mollie","columns":{"customer":"Cliente","status":"Stato","description":"Descrizione","amount":"Importo","nextPaymentAt":"Prossimo pagamento","prePaymentReminder":"Ricordato alle","canceledAt":"Annullato alle","createdAt":"Creato alle"},"action":{"edit":"Modifica abbonamento"},"deletedCustomer":"Cliente eliminato"},"detail":{"title":"Abbonamento Mollie","buttonCancelSubscription":"Annulla l\'abbonamento","labelDescription":"Descrizione","labelAmount":"Importo","labelQuantity":"Quantit\xe0","labelMollieSubscription":"Abbonamento Mollie","labelMollieCustomer":"Cliente Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente Shopware","labelCreatedAt":"Creato alle","buttonShowShopwareOrder":"Mostra l\'ordine Shopware","buttonShowShopwareCustomer":"Mostra il cliente Shopware","cardTitleSubscription":"Abbonamento","cardTitleStatus":"Stato","labelStatus":"Stato","labelNextPaymentAt":"Prossimo pagamento alle","labelLastRemindedAt":"Ultimo ricordo alle","labelCanceledAt":"Annullato alle","buttonPauseSubscription":"Metti in pausa l\'abbonamento","buttonResumeSubscription":"Riprendi abbonamento","buttonSkipSubscription":"Salta l\'abbonamento","history":{"cardTitle":"Cronologia","colDate":"Data","colComment":"Commento","colStatusFrom":"Stato (da)","colStatusTo":"Stato (a)","colMollieSubscription":"Abbonamento Mollie"}},"product":{"card-title":"Abbonamento","title":"Abbonamenti Mollie","description":"Gestire i tuoi pagamenti ricorrenti \xe8 pi\xf9 facile che mai grazie alle nostre utili funzionalit\xe0. Porta la tua attivit\xe0 al livello successivo con opzioni di tracciamento efficienti, integrazioni semplici e molto altro. Con gli abbonamenti Mollie, puoi facilmente creare prodotti in abbonamento e programmare pagamenti ricorrenti che avvengano all\'intervallo e periodo configurati.","mollieSubscriptionProduct":"Prodotto in abbonamento","mollieSubscriptionIntervalAmount":"Ripeti il pagamento ogni","mollieSubscriptionIntervalType":"Unit\xe0 di intervallo","mollieSubscriptionRepetitionAmount":"Numero di ripetizioni","mollieSubscriptionRepetitionPlaceholder":"Inserisci numero o lascia vuoto","infoDefaultLanguage":"Si prega di notare che questa configurazione pu\xf2 essere modificata solo nella lingua predefinita. Cambia la tua lingua per modificare le impostazioni di abbonamento di questo prodotto.","btnReadMore":"Leggi di pi\xf9"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abbonamento"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Dati della carta di credito","buttonMolliePaymentLink":"Copia negli Appunti","columnRefunded":"Rimborsato","columnShipped":"Spedito","columnCanceled":"Annullato","labelMollieOrderId":"ID ordine Mollie","labelMollieThirdPartyPaymentId":"Riferimento pagamento","labelMolliePaymentLink":"URL di Checkout Mollie","totalRefunds":"Importo rimborsato","totalRefundsPending":"In attesa del rimborso","totalRemaining":"Importo rimborsabile","totalVouchers":"Importo del voucher","totalShipments":"Importo spedito ({quantity} articoli)","subscriptionBadge":"Ordine di Abbonamento","refundManager":{"title":"Gestore Rimborsi Mollie","btnOpenRefundManager":"Apri Gestore Rimborsi","btnCloseRefundManager":"Chiudi Gestore Rimborsi"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Emittente iDEAL preferito"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Gestore Rimborsi"},"mollie_subscription":{"label":"Abbonamenti"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Descrizione"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Rimborso","subscription":"Abbonamento","webhookReceived":"Webhook","status":"Stato","started":"Iniziato","ended":"Terminato","paused":"In pausa","renewalReminder":"Promemoria di rinnovo","renewed":"Rinnovato","resumed":"Ripreso","skipped":"Saltato","all":"Tutto","canceled":"Annullato","expired":"Scaduto","partiallyRefunded":"Rimborsato (parzialmente)","orderSuccess":"Ordine completato con successo","orderFailed":"Ordine non riuscito","orderCanceled":"Ordine annullato"}}}'),e$=JSON.parse('{"global":{"entities":{"mollie_subscription":"Subscri\xe7\xe3o Mollie | Subscri\xe7\xf5es Mollie"},"businessEvents":{"mollie_checkout_order_success":" Encomenda efetuada com sucesso","mollie_checkout_order_failed":" A encomenda falhou","mollie_checkout_order_canceled":" Encomenda cancelada","mollie_webhook_received_All":" Mollie Webhook recebido (todos)","mollie_webhook_received_status_authorized":" Mollie Webhook recebido (Autorizado)","mollie_webhook_received_status_failed":" Mollie Webhook Recebido (N\xe3o efetuado)","mollie_webhook_received_status_canceled":" Mollie Webhook recebido (Cancelado)","mollie_webhook_received_status_expired":" Mollie Webhook Recebido (Expirado)","mollie_webhook_received_status_pending":" Mollie Webhook recebido (Pendente)","mollie_webhook_received_status_paid":" Mollie Webhook Recebido (Pago)","mollie_webhook_received_status_completed":" Mollie Webhook recebido (Conclu\xeddo)","mollie_webhook_received_status_refunded":" Mollie Webhook Recebido (Reembolsado)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook recebido (Parcialmente Reembolsado)","mollie_refund_started":" Reembolso da Mollie iniciado","mollie_subscription_started":" Subscri\xe7\xe3o da Mollie iniciada","mollie_subscription_ended":" Subscri\xe7\xe3o da Mollie conclu\xedda","mollie_subscription_cancelled":" Subscri\xe7\xe3o da Mollie cancelada","mollie_subscription_paused":" Subscri\xe7\xe3o da Mollie colocada em pausa","mollie_subscription_resumed":" Subscri\xe7\xe3o da Mollie retomada","mollie_subscription_skipped":" Subscri\xe7\xe3o da Mollie ignorada","mollie_subscription_renewed":" Subscri\xe7\xe3o da Mollie renovada","mollie_subscription_renewal_reminder":" Lembrete da Mollie para renovar a subscri\xe7\xe3o"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"M\xf3dulo Mollie","searchPlaceholder":"Pesquisar subscri\xe7\xf5es...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Reembolsar atrav\xe9s da Mollie","shipThroughMollie":"Enviar atrav\xe9s da Mollie","cancelMollieItem":"Cancelar atrav\xe9s da Mollie"},"config":{"info":{"title":"Ol\xe1 {userName}, Bem-vindo(a) \xe0 Mollie!","descriptionTop":"A integra\xe7\xe3o \xe9 f\xe1cil com a Mollie!","descriptionBottom":"\xc9 tudo!","descriptionFooter":"Se quiser saber mais sobre o nosso plugin, visite a nossa p\xe1gina de documenta\xe7\xe3o oficial.","onboardingStep1":"Crie uma conta Mollie.","onboardingStep2":"Insira suas chaves de API na sec\xe7\xe3o abaixo.","onboardingStep2TestMode":"Ative o \\"Modo de teste\\" se pretender apenas testar pagamentos.","onboardingStep3":"Atribua m\xe9todos de pagamento ao seu canal de vendas.","onboardingStep3Link":"para os seus canais de vendas","btnDocumentation":"Documenta\xe7\xe3o","btnRequestSupport":"Ajuda","btnTroubleshooting":"Guia de Resolu\xe7\xe3o de Problemas"},"api":{"apiLinkButton":"Obtenha as suas chaves de API no Painel de Controlo Mollie","testButton":"Chaves de API de teste","testApiKeys":{"title":"Mollie Payments","apiKey":"Chave de API","isValid":"\xe9 v\xe1lido","isInvalid":"\xe9 inv\xe1lido"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Pr\xe9-visualiza\xe7\xe3o"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Atualizar m\xe9todos de pagamento","succeeded":"Os m\xe9todos de pagamento foram atualizados com sucesso.","failed":"N\xe3o foi poss\xedvel atualizar os m\xe9todos de pagamento."},"mollieLimits":{"link":"Mostrar as regras de disponibilidade da Mollie para os m\xe9todos de pagamento"}},"rounding":{"info1":"O Shopware pode usar as defini\xe7\xf5es de moeda para calcular como arredonda o total de uma encomenda. Isso inclui o n\xfamero de casas decimais nos pre\xe7os dos seus produtos e o intervalo de arredondamento mais pr\xf3ximo, como 0,50 ou 1,00.","info2":"Estas defini\xe7\xf5es podem resultar um total diferente do total da soma dos itens. Quando a Mollie verifica que essas quantias n\xe3o correspondem, cria um erro de checkout.","info3":"Pode utilizar esta fun\xe7\xe3o para evitar problemas de arredondamento no seu checkout. Quando ativada, ela adiciona um item de linha separado no seu Painel de Controlo Mollie para a diferen\xe7a no arredondamento, e os seus clientes pagam o total calculado pelo Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"N\xe3o \xe9 poss\xedvel usar o Klarna Pagar Agora, Klarna Financiamento ou Klarna Pagar e 30 dias como m\xe9todo quando a sua data de validade \xe9 superior a 28 dias, a menos que outro m\xe1ximo seja acordado entre o comerciante e o Klarna.","bankTransferDueDateLimitReached":"N\xe3o \xe9 poss\xedvel definir um tempo de vida superior a 100 dias para uma encomenda."},"support":{"modalTitle":"Pedir ajuda \xe0 Mollie","btnCancel":"Cancelar","btnConfirm":"Pedir ajuda","btnSupport":"Mais sobre a nossa ajuda","form":{"name":"O seu nome","email":"O seu e-mail","recipient":"Enviar pedido para","subject":"Assunto","message":"Mensagem"},"data":{"header":"Dados enviados para a Mollie:","other":"Outro:","shopwareVersion":"Vers\xe3o do Shopware","pluginLogs":"{plugin} arquivos de log","pluginConfiguration":"{plugin} configura\xe7\xe3o","pluginConfigurationHelpText":"As chaves de API est\xe3o exclu\xeddas.","paymentMethods":"Dados do m\xe9todo de pagamento","paymentMethodsHelpText":"Cont\xe9m informa\xe7\xf5es sobre que m\xe9todos de pagamento est\xe3o ativos e atribu\xeddos a cada canal de vendas, bem como o seu estado na sua conta Mollie."},"success":"O pedido de ajuda foi enviado com sucesso. Faremos o nosso melhor para responder o mais rapidamente poss\xedvel.","error":"Ocorreu um problema ao enviar o e-mail pelo Shopware. Por favor, tente novamente ou entre em contacto diretamente por e-mail."}},"rules":{"itemSubscriptionRule":"Item \xe9 uma subscri\xe7\xe3o (Mollie)","cartSubscriptionRule":"Carrinho com subscri\xe7\xf5es (Mollie)"},"refunds":{"status":{"queued":"Em fila de espera","pending":"Pendente","processing":"A processar","refunded":"Reembolsado","failed":"N\xe3o efetuado","description":{"queued":"O reembolso \xe9 colocado em fila de espera at\xe9 que haja saldo suficiente para o processar. Ainda \xe9 poss\xedvel cancelar o reembolso.","pending":"O reembolso ser\xe1 enviado ao banco no pr\xf3ximo dia \xfatil. Ainda \xe9 poss\xedvel cancelar o reembolso.","processing":"O reembolso foi enviado para o banco. O montante do reembolso ser\xe1 transferido para a conta do consumidor o mais rapidamente poss\xedvel.","refunded":"O montante do reembolso foi transferido para o consumidor.","failed":"O reembolso falhou ap\xf3s o processamento. Por exemplo, o cliente fechou a sua conta banc\xe1ria. Os fundos ser\xe3o devolvidos \xe0 sua conta."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"N\xe3o tem permiss\xf5es para criar reembolsos","warningCancel":"N\xe3o tem permiss\xf5es para cancelar reembolsos"},"cart":{"title":"Encomenda ##orderNumber##","btnSelectAll":"Selecionar Tudo","btnResetForm":"Reiniciar Formul\xe1rio","linkHowTo":"Como utilizar este formul\xe1rio?","grid":{"columns":{"item":"Item","productNumber":"N\xfamero do Produto","unitPrice":"Pre\xe7o Unit\xe1rio","quantity":"Quantidade","refunded":"Reembolsado","refundQuantity":"Reembolso","totalPrice":"Total","refundAmount":"Reembolso","resetStock":"Repor o stock"},"btnResetLine":"Redefinir Linha","checkDeductPromotion":"Deduzir promo\xe7\xe3o","checkRefundTax":"Reembolsar o IVA"},"roundDiffItemAdded":"Item de arredondamento autom\xe1tico adicionado"},"instructions":{"linkResetTutorials":"Repor Tutoriais","btnToggleTutorial":"Mostrar/Ocultar Tutorial","titleFullRefund":"Reembolso Total","textFullRefund":"Basta utilizar o bot\xe3o para o reembolso total. Isto garante que todos os seus itens s\xe3o marcados como reembolsados e que o montante total \xe9 devolvido ao cliente.","titleStockReset":"Reposi\xe7\xe3o de stock","textStockReset":"Pode aumentar automaticamente o stock dispon\xedvel, introduzindo a quantidade que pretende repor em stock. Basta introduzi-la antes de proceder a um reembolso total ou parcial. A reposi\xe7\xe3o do stock pode ser combinada com o processo de reembolso de forma flex\xedvel.","titleShipping":"Envio","textShipping":"Os itens de envio podem ser reembolsados como qualquer outro artigo. Basta inserir a quantidade total ou um montante parcial personalizado e prosseguir com o reembolso. O reembolso dos custos de envio pode ser combinado com o processo de reembolso efetivo de itens de forma flex\xedvel.","titlePartialAmount":"Reembolso parcial (apenas o montante)","textPartialAmount":"Basta introduzir o montante parcial no campo de texto e iniciar o reembolso.","titlePartialItems":"Reembolso parcial (com artigos)","textPartialItems":"Se pretender marcar quantidades e itens como reembolsados na Mollie, utilize o formul\xe1rio acima. Defina as suas quantidades e forne\xe7a um montante personalizado para cada artigo que ser\xe1 reembolsado. A soma total ser\xe1 ent\xe3o vis\xedvel no campo de texto do valor final do reembolso. Lembre-se que ainda \xe9 poss\xedvel ajustar esse valor final antes de iniciar o reembolso.","titlePartialPromotions":"Reembolso Parcial (com promo\xe7\xf5es)","textPartialPromotions":"Se tiver uma promo\xe7\xe3o no seu carrinho, a promo\xe7\xe3o \xe9 um item de linha separado. Se pretender reembolsar todos os artigos com desconto, reembolse os seus valores totais e a totalidade do item de linha da promo\xe7\xe3o. No entanto, se pretender reembolsar apenas alguns itens com desconto, pode deduzir automaticamente o desconto aplicado a cada item. \xc9 claro que pode sempre alterar os valores se estes n\xe3o estiverem corretos.","titleRoundingDiff":"Diferen\xe7a de arredondamento","textRoundingDiff":"O reembolso total incluir\xe1 as diferen\xe7as de arredondamento"},"summary":{"dataLoading":"Os dados est\xe3o a ser carregados...","headerExcludingVat":"Sem IVA","headerIncludingVat":"Com IVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"A aguardar reembolso","captionVouchers":"Montante do cup\xe3o","captionRefunded":"Montante reembolsado","captionRemaining":"Montante reembols\xe1vel","btnFixDiff":"Corrigir a diferen\xe7a","placeholderDescription":"Introduzir a descri\xe7\xe3o do extrato do banco/cart\xe3o para o consumidor. M\xe1ximo de 140 caracteres","lblDescription":"Descri\xe7\xe3o (opcional) ({characters}/140 caracteres)","descriptionHelp":"Sempre que poss\xedvel, esta mensagem ser\xe1 apresentada no extrato banc\xe1rio ou do cart\xe3o do consumidor. A mensagem ser\xe1 truncada ap\xf3s 140 caracteres.","placeholderInternalDescription":"Introduza a sua descri\xe7\xe3o interna","lblInternalDescription":"Descri\xe7\xe3o interna (opcional)","internalDescriptionHelp":"Isto ser\xe1 mostrado como uma descri\xe7\xe3o local na interface de administra\xe7\xe3o.","checkVerification":"Verifiquei o montante total do reembolso e as quantidades configuradas para reembolsar e repor em stock.","btnRefund":"Reembolso","btnFullRefund":"Reembolso Total","roundDiffItemAdded":"Item de arredondamento"},"refunds":{"title":"Reembolsos no Painel de Controlo Mollie","linkMore":"Mais sobre reembolsos","grid":{"columns":{"amount":"Montante","status":"Estado","description":"Descri\xe7\xe3o","internalDescription":"Descri\xe7\xe3o interna","composition":"Composi\xe7\xe3o","date":"Data"},"lblNoComposition":"Nenhuma composi\xe7\xe3o dispon\xedvel","btnCancelRefund":"Cancelar este reembolso"}},"notifications":{"success":{"refund-created":"Foi criado um reembolso na Mollie. Este pode demorar 2 horas a ficar conclu\xeddo. At\xe9 l\xe1, pode cancelar o reembolso.","refund-canceled":"O reembolso pendente foi cancelado e eliminado com sucesso."},"error":{"low-amount":"Introduza o montante a reembolsar.","refund-created":"Algo correu mal ao criar um reembolso.","refund-canceled":"Ocorreu um problema ao cancelar o reembolso pendente. Por favor, tente novamente no Painel de Controlo Mollie."}}},"vouchers":{"CARD_TITLE":"Cup\xe3o","VOUCHER_INFO_TITLE":"Pagamentos com cup\xe3o","VOUCHER_INFO_DESCRIPTION":"A Mollie permite-lhe aceitar facilmente pagamentos na sua loja virtual utilizando cup\xe3o Eco, de oferta e de refei\xe7\xe3o - uma escolha inteligente para aumentar as suas vendas e a satisfa\xe7\xe3o dos seus clientes. O m\xe9todo de pagamento \\"cup\xe3o\\" s\xf3 \xe9 vis\xedvel se tiver pelo menos um produto com um tipo de vale atribu\xeddo no carrinho.","VOUCHER_INFO_DEFAULTLANGUAGE":"Aten\xe7\xe3o, esta configura\xe7\xe3o s\xf3 pode ser editada na sua l\xedngua predefinida. Altere a sua l\xedngua para modificar o tipo de cup\xe3o deste produto.","VOUCHER_BTN_READMORE":"Ler mais","VOUCHER_TYPE_CAPTION":"Tipo de cup\xe3o do produto","VOUCHER_TYPE_VALUE_NONE":"Nenhum","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Refei\xe7\xe3o","VOUCHER_TYPE_VALUE_VOUCHER":"Presente"},"modals":{"shipping":{"title":"Enviar atrav\xe9s da Mollie","item":{"label":"Item:","noQuantity":"Por favor, introduza a quantidade a enviar.","shipAll":"Enviar tudo","summary":{"quantity":"Quantidade a enviar","shipped":"Quantidade enviada","shippable":"Quantidade envi\xe1vel"},"success":"A encomenda foi enviada com sucesso."},"order":{"description":"As seguintes quantidades de itens ser\xe3o enviadas.","itemHeader":"Item","quantityHeader":"Quantidade","originalQuantityHeader":"Quantidade (envi\xe1vel)"},"availableTracking":{"label":"C\xf3digos de rastreio dispon\xedveis","hint":"Clique em um destes c\xf3digos de rastreio para preencher automaticamente todos os dados."},"showTracking":"Adicionar informa\xe7\xf5es de rastreio para este envio","tracking":{"carrier":"Transportadora","code":"C\xf3digo","url":"URL","invalid":"Por favor, introduza a Transportadora e o C\xf3digo"},"confirmButton":"Enviar encomenda","cancelButton":"Cancelar","selectAllButton":"Selecionar tudo","resetButton":"Repor"},"cancel":{"title":"Cancelar item atrav\xe9s da Mollie","confirmButton":"Cancelar item atrav\xe9s da Mollie","cancelButton":"Fechar modal","resetStock":"Repor stock","item":{"success":"Produto cancelado com sucesso","failed":{"quantityZero":"A quantidade \xe9 0","invalidLine":"O produto n\xe3o existe na encomenda","quantityTooHigh":"A quantidade \xe9 demasiado elevada"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Enviar Encomenda (Mollie)","description":"Enviar encomenda na Mollie."},"modal":{"title":"Enviar Encomenda","description":"Esta a\xe7\xe3o enviar\xe1 automaticamente uma encomenda atrav\xe9s da Mollie. A sequ\xeancia de fluxo receber\xe1 o n\xfamero da encomenda e transmiti-lo-\xe1 \xe0 API da Mollie. Envios bem-sucedidos e falhados ser\xe3o vis\xedveis nos arquivos de log da Mollie.","warningConfig":"Certifique-se de que desativa qualquer automa\xe7\xe3o adicional para este tipo de a\xe7\xe3o para evitar quaisquer interfer\xeancias.\\nAs seguintes funcionalidades ativadas deste plugin podem interferir com esta a\xe7\xe3o:","noWarnings":"Sem avisos"}},"refundOrder":{"editor":{"title":"Reembolsar Encomenda (Mollie)","description":"Reembolsar encomenda atrav\xe9s da Mollie."},"modal":{"title":"Reembolsar Encomenda","description":"Esta a\xe7\xe3o iniciar\xe1 automaticamente um reembolso atrav\xe9s da Mollie. A sequ\xeancia de fluxo receber\xe1 o n\xfamero da encomenda e o transmiti-lo-\xe1 \xe0 API da Mollie. Reembolsos bem-sucedidos e falhados ser\xe3o vis\xedveis nos arquivos de log da Mollie.","warning":"Por favor, lembre-se de que os reembolsos podem levar at\xe9 2 horas para serem finalizados e vis\xedveis na loja. At\xe9 l\xe1, pode sempre cancelar um reembolso pendente, seja na p\xe1gina da encomenda no Shopware ou no Painel de Controlo da Mollie.","warningConfig":"Por favor, certifique-se de que desativa qualquer automa\xe7\xe3o adicional para este tipo de a\xe7\xe3o para evitar qualquer interfer\xeancia."}},"warnings":{"automaticShipping":"Envio autom\xe1tico na configura\xe7\xe3o do plugin"}}},"subscriptions":{"status":{"pending":"Pendente","active":"Ativo","canceled":"Cancelado","suspended":"Suspenso","completed":"Conclu\xeddo","paused":"Em pausa","resumed":"Retomado","skipped":"Ignorado"},"navigation":{"title":"Subscri\xe7\xf5es Mollie"},"TYPE_DAYS":"Dia(s)","TYPE_WEEKS":"Semana(s)","TYPE_MONTHS":"M\xeas(es)","confirm":{"cancelTitle":"Cancelar a subscri\xe7\xe3o?","cancel":"Cancelar a subscri\xe7\xe3o do seu cliente.","pauseTitle":"Colocar a subscri\xe7\xe3o em espera?","pause":"Colocar a subscri\xe7\xe3o em pausa at\xe9 retom\xe1-la novamente.","resumeTitle":"Retomar a subscri\xe7\xe3o?","resume":"Continuar a subscri\xe7\xe3o novamente.","skipTitle":"Saltar a pr\xf3xima presta\xe7\xe3o?","skip":"Saltar a pr\xf3xima presta\xe7\xe3o na subscri\xe7\xe3o. Continuar\xe1 automaticamente depois disso."},"alerts":{"cancelSuccess":"A subscri\xe7\xe3o foi cancelada com sucesso","pauseSuccess":"A subscri\xe7\xe3o foi colocada em pausa com sucesso","resumeSuccess":"A subscri\xe7\xe3o foi retomada com sucesso","skipSuccess":"A subscri\xe7\xe3o foi saltada com sucesso. O pr\xf3ximo pagamento foi atualizado."},"list":{"title":"Subscri\xe7\xf5es Mollie","columns":{"customer":"Cliente","status":"Estado","description":"Descri\xe7\xe3o","amount":"Montante","nextPaymentAt":"Pr\xf3ximo pagamento","prePaymentReminder":"Relembrado em","canceledAt":"Cancelado em","createdAt":"Criado em"},"action":{"edit":"Editar subscri\xe7\xe3o"},"deletedCustomer":"Cliente eliminado"},"detail":{"title":"Subscri\xe7\xe3o Mollie","buttonCancelSubscription":"Cancelar subscri\xe7\xe3o","labelDescription":"Descri\xe7\xe3o","labelAmount":"Montante","labelQuantity":"Quantidade","labelMollieSubscription":"Subscri\xe7\xe3o Mollie","labelMollieCustomer":"Cliente Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente Shopware","labelCreatedAt":"Criado em","buttonShowShopwareOrder":"Mostrar ordem do Shopware","buttonShowShopwareCustomer":"Mostrar cliente do Shopware","cardTitleSubscription":"Subscri\xe7\xe3o","cardTitleStatus":"Estado","labelStatus":"Estado","labelNextPaymentAt":"Pr\xf3ximo pagamento em","labelLastRemindedAt":"Lembrado pela \xfaltima vez em","labelCanceledAt":"Cancelado em","buttonPauseSubscription":"Colocar subscri\xe7\xe3o em pausa","buttonResumeSubscription":"Retomar subscri\xe7\xe3o","buttonSkipSubscription":"Ignorar subscri\xe7\xe3o","history":{"cardTitle":"Hist\xf3rico","colDate":"Data","colComment":"Coment\xe1rio","colStatusFrom":"Estado (de)","colStatusTo":"Estado (para)","colMollieSubscription":"Subscri\xe7\xe3o Mollie"}},"product":{"card-title":"Subscri\xe7\xe3o","title":"Subscri\xe7\xf5es Mollie","description":"Gerir os seus pagamentos recorrentes \xe9 mais f\xe1cil do que nunca com as nossas funcionalidades \xfateis. Leve o seu neg\xf3cio ao pr\xf3ximo n\xedvel com op\xe7\xf5es de acompanhamento eficientes, integra\xe7\xf5es simples e muito mais. Com as subscri\xe7\xf5es Mollie, pode criar facilmente produtos de subscri\xe7\xe3o e programar pagamentos recorrentes para ocorrerem no intervalo e per\xedodo configurados.","mollieSubscriptionProduct":"Produto de Subscri\xe7\xe3o","mollieSubscriptionIntervalAmount":"Repetir pagamento a cada","mollieSubscriptionIntervalType":"Unidade de intervalo","mollieSubscriptionRepetitionAmount":"N\xfamero de repeti\xe7\xf5es","mollieSubscriptionRepetitionPlaceholder":"Introduzir o n\xfamero ou deixar em branco","infoDefaultLanguage":"Aten\xe7\xe3o: esta configura\xe7\xe3o s\xf3 pode ser editada na sua l\xedngua predefinida. Altere a sua l\xedngua para modificar as defini\xe7\xf5es de subscri\xe7\xe3o deste produto.","btnReadMore":"Ler mais"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subscri\xe7\xe3o"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Dados do cart\xe3o de cr\xe9dito","buttonMolliePaymentLink":"Copiar para a \xe1rea de transfer\xeancia","columnRefunded":"Reembolsado","columnShipped":"Enviado","columnCanceled":"Cancelado","labelMollieOrderId":"ID de Encomenda da Mollie","labelMollieThirdPartyPaymentId":"Refer\xeancia de pagamento","labelMolliePaymentLink":"URL do Mollie Checkout","totalRefunds":"Montante reembolsado","totalRefundsPending":"A aguardar reembolso","totalRemaining":"Montante reembols\xe1vel","totalVouchers":"Montante do cup\xe3o","totalShipments":"Montante enviado ({quantity} itens)","subscriptionBadge":"Pedido de subscri\xe7\xe3o","refundManager":{"title":"Gestor de Reembolsos da Mollie","btnOpenRefundManager":"Abrir Gestor de Reembolsos","btnCloseRefundManager":"Fechar Gerente de Reembolsos"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Emissor iDeal preferido"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Gestor de Reembolsos"},"mollie_subscription":{"label":"Subscri\xe7\xf5es"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Descri\xe7\xe3o"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Reembolso","subscription":"Subscri\xe7\xe3o","webhookReceived":"Webhooks","status":"Estado","started":"Iniciado","ended":"Terminado","paused":"Em pausa","renewalReminder":"Lembrete de Renova\xe7\xe3o","renewed":"Renovado","resumed":"Retomado","skipped":"Ignorado","all":"Todos","canceled":"Cancelado","expired":"Expirado","partiallyRefunded":"Reembolsado (parcialmente)","orderSuccess":"Encomenda bem sucedida","orderFailed":"Encomenda n\xe3o efetuada","orderCanceled":"Encomenda cancelada"}}}'),eW=JSON.parse('{"global":{"entities":{"mollie_subscription":"Suscripciones Mollie | Suscripci\xf3n Mollie"},"businessEvents":{"mollie_checkout_order_success":" Pedido realizado","mollie_checkout_order_failed":" Pedido fallido","mollie_checkout_order_canceled":" Pedido cancelado","mollie_webhook_received_All":" Mollie Webhook Recibido (Todo)","mollie_webhook_received_status_authorized":" Mollie Webhook Recibido (Autorizado)","mollie_webhook_received_status_failed":" Mollie Webhook Recibido (Fallido)","mollie_webhook_received_status_canceled":" Mollie Webhook Recibido (Cancelado)","mollie_webhook_received_status_expired":" Mollie Webhook Recibido (Expirado)","mollie_webhook_received_status_pending":" Mollie Webhook Recibido (Pendiente)","mollie_webhook_received_status_paid":" Mollie Webhook Recibido (Pagado)","mollie_webhook_received_status_completed":" Mollie Webhook Recibido (Completado)","mollie_webhook_received_status_refunded":" Mollie Webhook Recibido (Reembolsado)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Recibido (Reembolso parcial)","mollie_refund_started":"Reembolso de Mollie iniciado","mollie_subscription_started":"Suscripci\xf3n de Mollie iniciada","mollie_subscription_ended":"Suscripci\xf3n de Mollie completada","mollie_subscription_cancelled":"Suscripci\xf3n de Mollie cancelada","mollie_subscription_paused":"Suscripci\xf3n de Mollie en pausa","mollie_subscription_resumed":"Suscripci\xf3n de Mollie reanudada","mollie_subscription_skipped":" Suscripci\xf3n de Mollie pospuesta","mollie_subscription_renewed":"Suscripci\xf3n de Mollie renovada","mollie_subscription_renewal_reminder":"Recordatorio de suscripci\xf3n de Mollie"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"M\xf3dulo Mollie","searchPlaceholder":"Buscar suscripciones...","general":{"mainMenuItemGeneral":"Pagos Mollie","descriptionTextModule":"Pagos Mollie","btnMollieActions":"Mollie Actions","refundThroughMollie":"Reembolso a trav\xe9s de Mollie","shipThroughMollie":"Enviar a trav\xe9s de Mollie","cancelMollieItem":"Cancelar a trav\xe9s de Mollie"},"config":{"info":{"title":"Hola {userName}, \xa1bienvenid@ a Mollie!","descriptionTop":"\xa1La integraci\xf3n con Mollie es f\xe1cil!","descriptionBottom":"\xa1Eso es todo!","descriptionFooter":"Si deseas m\xe1s informaci\xf3n sobre nuestro plugin, visita nuestra p\xe1gina oficial de documentaci\xf3n.","onboardingStep1":"Crea una cuenta con Mollie.","onboardingStep2":"Introduce tus claves API en la secci\xf3n de abajo.","onboardingStep2TestMode":"Activa el \'Modo de prueba\' si \xfanicamente deseas probar los pagos.","onboardingStep3":"Establece los m\xe9todos de pago en tus canales de venta.","onboardingStep3Link":"en tus canales de venta","btnDocumentation":"Documentaci\xf3n","btnRequestSupport":"Ayuda","btnTroubleshooting":"Gu\xeda de resoluci\xf3n de problemas"},"api":{"apiLinkButton":"Accede a tus claves API desde Mollie Dashboard","testButton":"Claves API de prueba","testApiKeys":{"title":"Pagos Mollie","apiKey":"Clave API","isValid":"es v\xe1lido","isInvalid":"no es v\xe1lido"}},"payments":{"format":{"placeholder":"Texto de muestra","preview":"Vista previa"},"updatePaymentMethods":{"title":"Pagos Mollie","button":"Actualizar m\xe9todos de pago","succeeded":"Los m\xe9todos de pago se han actualizado correctamente.","failed":"No ha sido posible actualizar los m\xe9todos de pago."},"mollieLimits":{"link":"Mostrar reglas de disponibilidad de Mollie para m\xe9todos de pago"}},"rounding":{"info1":"Shopware utiliza los ajustes sobre la moneda para calcular el redondeo del importe total de un pedido. Esto incluye el n\xfamero de decimales en la fijaci\xf3n de precios de productos y el intervalo de redondeo como 0,50 o 1,00.","info2":"Estos ajustes pueden generar un importe total diferente al importe de los art\xedculos. Al verificar Mollie estas cantidades y no coincidir, se produce un error en el proceso de pago.","info3":"Puedes utilizar esta funci\xf3n para evitar problemas de redondeo en tu proceso de pago. Cuando se activa esta funci\xf3n, se a\xf1ade una nueva l\xednea de art\xedculo en el Mollie Dashboard con la diferencia del redondeo, y tus clientes pagan el total calculado por Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"No es posible elegir Klarna (paga ahora, paga en cuotas o paga m\xe1s tarde) como m\xe9todo de pago si el plazo de vencimiento es superior a 28 d\xedas, salvo que haya un acuerdo especial entre Klarna y el comerciante para extenderlo.","bankTransferDueDateLimitReached":"No es posible establecer el tiempo de vida de un pedido superior a 100 d\xedas."},"support":{"modalTitle":"Solicitar ayuda de Mollie","btnCancel":"Cancelar","btnConfirm":"Solicitar ayuda","btnSupport":"M\xe1s sobre nuestra ayuda","form":{"name":"Nombre","email":"Correo electr\xf3nico","recipient":"Enviar solicitud a","subject":"Asunto","message":"Mensaje"},"data":{"header":"Datos enviados a Mollie:","other":"Otros:","shopwareVersion":"Versi\xf3n de Shopware","pluginLogs":"archivos de registro de {plugin}","pluginConfiguration":"configuraci\xf3n de {plugin}","pluginConfigurationHelpText":"Las claves API no est\xe1n incluidas.","paymentMethods":"Datos de m\xe9todos de pago","paymentMethodsHelpText":"Contiene informaci\xf3n sobre qu\xe9 m\xe9todos de pago est\xe1n activos, asignados a cada canal de venta, as\xed como su estado en tu cuenta de Mollie."},"success":"La solicitud de ayuda se ha enviado correctamente. Haremos el mayor esfuerzo para responder lo antes posible","error":"Ha habido un problema al enviar el correo a trav\xe9s de Shopware. Por favor, int\xe9ntalo de nuevo o cont\xe1ctanos por correo electr\xf3nico."}},"rules":{"itemSubscriptionRule":"El art\xedculo es una suscripci\xf3n (Mollie)","cartSubscriptionRule":"Carrito con suscripciones (Mollie)"},"refunds":{"status":{"queued":"En cola","pending":"Pendiente","processing":"Procesando","refunded":"Reembolsado","failed":"Fallido","description":{"queued":"El reembolso est\xe1 en la cola hasta que haya suficiente saldo para procesarlo. Todav\xeda puedes cancelar el reembolso.","pending":"El reembolso se enviar\xe1 al banco el siguiente d\xeda h\xe1bil. Todav\xeda puedes cancelar el reembolso.","processing":"El reembolso ha sido enviado al banco. La cantidad reembolsada se transferir\xe1 a la cuenta del consumidor lo antes posible.","refunded":"La cantidad reembolsada ha sido transferida al consumidor.","failed":"No ha sido posible abonar el reembolso tras procesarlo. Es posible que el cliente haya cerrado su cuenta bancaria. Los fondos ser\xe1n devueltos a tu cuenta."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"No tienes permisos para crear reembolsos","warningCancel":"No tienes permisos para cancelar reembolsos"},"cart":{"title":"Pedido ##orderNumber##","btnSelectAll":"Seleccionar todo","btnResetForm":"Restablecer formulario","linkHowTo":"\xbfC\xf3mo usar este formulario?","grid":{"columns":{"item":"Art\xedculo","productNumber":"N\xfamero de producto","unitPrice":"Precio unitario","quantity":"Cantidad","refunded":"Reembolsado","refundQuantity":"Reembolso","totalPrice":"Total","refundAmount":"Reembolso","resetStock":"Restablecer stock"},"btnResetLine":"Restablecer l\xednea","checkDeductPromotion":"Deducir la promoci\xf3n","checkRefundTax":"Devolver IVA"},"roundDiffItemAdded":"Se ha a\xf1adido autom\xe1ticamente un art\xedculo con redondeo"},"instructions":{"linkResetTutorials":"Restablecer tutoriales","btnToggleTutorial":"Mostrar/Ocultar tutorial","titleFullRefund":"Reembolso completo","textFullRefund":"Usa este bot\xf3n para el reembolso completo. Esto garantiza que todos tus art\xedculos est\xe1n marcados como reembolsados y la cantidad total se reembolsa al cliente.","titleStockReset":"Restablecer el stock","textStockReset":"Puedes aumentar el stock disponible de manera autom\xe1tica a\xf1adiendo la cantidad a reponer. Simplemente a\xf1ade la informaci\xf3n antes de continuar con un reembolso total o parcial. Restablecer el stock se puede combinar con el proceso de reembolso.","titleShipping":"Env\xedo","textShipping":"Los art\xedculos con env\xedo se pueden reembolsar como cualquier otro producto. Simplemente escribe la cantidad total o la deseada y procede con el reembolso. Reembolsar los costes de env\xedo se puede combinar con el proceso de reembolso de art\xedculos.","titlePartialAmount":"Reembolso parcial (solo importe)","textPartialAmount":"Simplemente a\xf1ade el importe parcial en el campo de texto e inicia el reembolso.","titlePartialItems":"Reembolso parcial (con art\xedculos)","textPartialItems":"Utiliza el formulario de arriba para marcar cantidades y art\xedculos reembolsados en Mollie. Establece tus cantidades y a\xf1ade el importe \xfanico para cada art\xedculo reembolsado. La suma total ser\xe1 visible en el campo de texto de importe total reembolsado. Recuerda que puedes ajustar el importe final antes de empezar con el reembolso.","titlePartialPromotions":"Reembolso parcial (con promociones)","textPartialPromotions":"Si tienes una promoci\xf3n en el carrito, la promoci\xf3n aparecer\xe1 como una l\xednea de art\xedculo nueva. Si quieres reembolsar todos los art\xedculos con descuento, tienes que devolver la l\xednea del valor total y la l\xednea de art\xedculo con promoci\xf3n. Si quieres reembolsar solo algunos art\xedculos con descuento, puedes deducir el descuento aplicado para cada art\xedculo de l\xednea de manera autom\xe1tica. Por supuesto, siempre puedes cambiar los valores si no son correctos.","titleRoundingDiff":"Diferencia de redondeo","textRoundingDiff":"Un reembolso completo incluir\xe1 diferencias de redondeo"},"summary":{"dataLoading":"Cargando datos...","headerExcludingVat":"Sin IVA","headerIncludingVat":"Con IVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Esperando reembolso","captionVouchers":"Importe del vale","captionRefunded":"Importe reembolsado","captionRemaining":"Importe reembolsable","btnFixDiff":"Corregir diferencia","placeholderDescription":"Introduce la descripci\xf3n del movimiento en la cuenta bancaria/tarjeta del consumidor. M\xe1x. 140 caracteres","lblDescription":"Descripci\xf3n (opcional) ({characters}/140 caracteres)","descriptionHelp":"El texto se mostrar\xe1 en el extracto del banco o en la tarjeta del consumidor. Pasados los 140 caracteres, el mensaje no ser\xe1 visible.","placeholderInternalDescription":"Introduce la descripci\xf3n interna","lblInternalDescription":"Descripci\xf3n interna (opcional)","internalDescriptionHelp":"El texto se mostrar\xe1 como una descripci\xf3n local en la interfaz de administraci\xf3n.","checkVerification":"He verificado el importe total del reembolso, las cantidades configuradas del reembolso y el stock.","btnRefund":"Reembolso","btnFullRefund":"Reembolso completo","roundDiffItemAdded":"Art\xedculo de redondeo"},"refunds":{"title":"Reembolsos en el Mollie Dashboard","linkMore":"M\xe1s sobre reembolsos","grid":{"columns":{"amount":"Importe","status":"Estado","description":"Descripci\xf3n","internalDescription":"Descripci\xf3n interna","composition":"Composici\xf3n","date":"Fecha"},"lblNoComposition":"No hay composici\xf3n disponible","btnCancelRefund":"Cancelar este reembolso"}},"notifications":{"success":{"refund-created":"Se ha creado un reembolso en Mollie. Puede tardar hasta 2 horas en completarse. Pasado este tiempo, no se podr\xe1 cancelar.","refund-canceled":"El reembolso pendiente ha sido cancelado y eliminado."},"error":{"low-amount":"Por favor, introduce el importe a devolver.","refund-created":"Algo sali\xf3 mal al crear un reembolso.","refund-canceled":"Ha habido un error al cancelar el reembolso pendiente. Por favor, int\xe9ntalo de nuevo en el Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vale","VOUCHER_INFO_TITLE":"Pagos con vales","VOUCHER_INFO_DESCRIPTION":"Mollie permite aceptar pagos de tu tienda online con vales ecol\xf3gicos, de regalo y de comida. Esta opci\xf3n puede aumentar las ventas y satisfacer a tus clientes. El m\xe9todo de pago con un \\"vale\\" es visible solo si tienes al menos 1 producto con un tipo de vale asignado en el carrito.","VOUCHER_INFO_DEFAULTLANGUAGE":"Ten en cuenta que esta configuraci\xf3n solo puede ser editada en tu idioma predeterminado. Por favor, cambia tu idioma para modificar el tipo de vale de este producto.","VOUCHER_BTN_READMORE":"Seguir leyendo","VOUCHER_TYPE_CAPTION":"Art\xedculos tipo vale","VOUCHER_TYPE_VALUE_NONE":"Ninguno","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Comida","VOUCHER_TYPE_VALUE_VOUCHER":"Regalo"},"modals":{"shipping":{"title":"Enviar a trav\xe9s de Mollie","item":{"label":"Art\xedculo:","noQuantity":"Por favor, introduce la cantidad a enviar.","shipAll":"Enviar todo","summary":{"quantity":"Cantidad a enviar","shipped":"Cantidad enviada","shippable":"Cantidad enviable"},"success":"El pedido ha sido enviado con \xe9xito."},"order":{"description":"Las siguientes cantidades de art\xedculos ser\xe1n enviadas.","itemHeader":"Art\xedculo","quantityHeader":"Cantidad","originalQuantityHeader":"Cantidad (enviable)"},"availableTracking":{"label":"C\xf3digos de seguimiento disponibles","hint":"Haz clic en uno de los c\xf3digos de seguimiento para completar todos los datos."},"showTracking":"A\xf1adir informaci\xf3n de seguimiento para este env\xedo","tracking":{"carrier":"Empresa de transporte","code":"C\xf3digo","url":"Url","invalid":"Por favor, introduce tanto la empresa de transporte como el c\xf3digo"},"confirmButton":"Enviar pedido","cancelButton":"Cancelar","selectAllButton":"Seleccionar todo","resetButton":"Restablecer"},"cancel":{"title":"Cancelar art\xedculo a trav\xe9s de mollie","confirmButton":"Cancelar art\xedculo a trav\xe9s de mollie","cancelButton":"Cerrar modal","resetStock":"Restablecer stocks","item":{"success":"Producto cancelado con \xe9xito","failed":{"quantityZero":"La cantidad es 0","invalidLine":"El producto no existe en el pedido","quantityTooHigh":"La cantidad es demasiado alta"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Enviar pedido (Mollie)","description":"Enviar pedido a trav\xe9s de Mollie."},"modal":{"title":"Enviar pedido","description":"Esta acci\xf3n enviar\xe1 el pedido a trav\xe9s de Mollie de forma autom\xe1tica. La secuencia de flujo recibir\xe1 el n\xfamero del pedido y lo pasar\xe1 a la API de Mollie. Los env\xedos procesados y los fallidos ser\xe1n visibles en el registro de Mollie.","warningConfig":"Por favor, desactiva cualquier automatizaci\xf3n adicional para acciones de este tipo y evitar interferencias.\\nLos siguientes par\xe1metros est\xe1n activados y podr\xedan interferir con la acci\xf3n:","noWarnings":"Sin advertencias"}},"refundOrder":{"editor":{"title":"Reembolsar pedido (Mollie)","description":"Reembolsar pedido a trav\xe9s de Mollie."},"modal":{"title":"Reembolsar pedido","description":"Esta acci\xf3n iniciar\xe1 el reembolso a trav\xe9s de Mollie de forma autom\xe1tica. La secuencia de flujo recibir\xe1 el n\xfamero del pedido y lo pasar\xe1 a la API de Mollie. Los reembolsos procesados y fallidos ser\xe1n visibles en el registro de Mollie.","warning":"Por favor, ten en cuenta que los reembolsos tardan hasta 2 horas en completarse y ser visibles en la tienda. Antes de este tiempo, siempre puedes cancelar un reembolso pendiente, bien desde la p\xe1gina del pedido en Shopware o desde el Mollie Dashboard.","warningConfig":"Por favor, aseg\xfarate de desactivar cualquier automatizaci\xf3n adicional para este tipo de acciones para evitar interferencias."}},"warnings":{"automaticShipping":"Env\xedo autom\xe1tico en la configuraci\xf3n del plugin"}}},"subscriptions":{"status":{"pending":"Pendiente","active":"Activo","canceled":"Cancelado","suspended":"Suspendido","completed":"Completado","paused":"En pausa","resumed":"Reanudado","skipped":"Pospuesto"},"navigation":{"title":"Suscripciones de Mollie"},"TYPE_DAYS":"D\xeda(s)","TYPE_WEEKS":"Semana(s)","TYPE_MONTHS":"Mes(es)","confirm":{"cancelTitle":"\xbfFinalizar suscripci\xf3n?","cancel":"Cancelar la suscripci\xf3n de tu cliente.","pauseTitle":"\xbfPausar suscripci\xf3n?","pause":"Pausar la suscripci\xf3n hasta nuevo aviso.","resumeTitle":"\xbfReanudar suscripci\xf3n?","resume":"Continuar con la suscripci\xf3n.","skipTitle":"\xbfSaltar el pago de la cuota?","skip":"Posp\xf3n el pago de la siguiente cuota de suscripci\xf3n. Contin\xfaa despu\xe9s autom\xe1ticamente."},"alerts":{"cancelSuccess":"La suscripci\xf3n se ha cancelado con \xe9xito","pauseSuccess":"La suscripci\xf3n est\xe1 en pausa","resumeSuccess":"La suscripci\xf3n se ha reanudado con \xe9xito","skipSuccess":"El pago de la suscripci\xf3n se ha pospuesto. El siguiente pago ha sido actualizado."},"list":{"title":"Suscripciones de Mollie","columns":{"customer":"Cliente","status":"Estado","description":"Descripci\xf3n","amount":"Importe","nextPaymentAt":"Pr\xf3ximo pago","prePaymentReminder":"Recordado el","canceledAt":"Cancelado el","createdAt":"Creado el"},"action":{"edit":"Editar suscripci\xf3n"},"deletedCustomer":"Cliente eliminado"},"detail":{"title":"Suscripci\xf3n de Mollie","buttonCancelSubscription":"Cancelar suscripci\xf3n","labelDescription":"Descripci\xf3n","labelAmount":"Importe","labelQuantity":"Cantidad","labelMollieSubscription":"Suscripci\xf3n de Mollie","labelMollieCustomer":"Cliente de Mollie","labelMandateId":"Mandato","labelShopwareCustomer":"Cliente de Shopware","labelCreatedAt":"Creado el","buttonShowShopwareOrder":"Mostrar pedido de Shopware","buttonShowShopwareCustomer":"Mostrar cliente de Shopware","cardTitleSubscription":"Suscripci\xf3n","cardTitleStatus":"Estado","labelStatus":"Estado","labelNextPaymentAt":"Pr\xf3ximo pago el","labelLastRemindedAt":"\xdaltimo recordatorio el","labelCanceledAt":"Cancelado el","buttonPauseSubscription":"Pausar suscripci\xf3n","buttonResumeSubscription":"Reanudar suscripci\xf3n","buttonSkipSubscription":"Posponer suscripci\xf3n","history":{"cardTitle":"Historial","colDate":"Fecha","colComment":"Comentario","colStatusFrom":"Estado (de)","colStatusTo":"Estado (a)","colMollieSubscription":"Suscripci\xf3n Mollie"}},"product":{"card-title":"Suscripci\xf3n","title":"Suscripciones Mollie","description":"Es muy f\xe1cil gestionar pagos recurrentes gracias a las funciones que ofrecemos. Lleva tu negocio al siguiente nivel con opciones de seguimiento, integraciones sencillas y m\xe1s. Con las suscripciones Mollie, puedes crear suscripciones y programar pagos recurrentes con el cobro en un intervalo y per\xedodo establecido.","mollieSubscriptionProduct":"Producto de suscripci\xf3n","mollieSubscriptionIntervalAmount":"Repetir pago cada","mollieSubscriptionIntervalType":"Unidad de intervalo","mollieSubscriptionRepetitionAmount":"N\xfamero de repeticiones","mollieSubscriptionRepetitionPlaceholder":"Introduce un n\xfamero o deja vac\xedo","infoDefaultLanguage":"Ten en cuenta que esta configuraci\xf3n solo puede ser editada en tu idioma predeterminado. Por favor, cambia tu idioma para modificar la configuraci\xf3n de la suscripci\xf3n.","btnReadMore":"Seguir leyendo"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Suscripci\xf3n"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Datos de tarjeta de cr\xe9dito","buttonMolliePaymentLink":"Copiar al portapapeles","columnRefunded":"Reembolsado","columnShipped":"Enviado","columnCanceled":"Cancelado","labelMollieOrderId":"N\xfam. de pedido de Mollie","labelMollieThirdPartyPaymentId":"Referencia de pago","labelMolliePaymentLink":"URL de pago de Mollie","totalRefunds":"Cantidad reembolsada","totalRefundsPending":"Reembolso pendiente","totalRemaining":"Cantidad reembolsable","totalVouchers":"Importe del vale","totalShipments":"Cantidad enviada ({quantity} art\xedculos)","subscriptionBadge":"Pedido de suscripci\xf3n","refundManager":{"title":"Administrador de reembolsos Mollie","btnOpenRefundManager":"Abrir administrador de reembolsos","btnCloseRefundManager":"Cerrar administrador de reembolsos"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Emisor iDeal preferido"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Administrador de reembolsos"},"mollie_subscription":{"label":"Suscripciones"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Descripci\xf3n"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Reembolso","subscription":"Suscripci\xf3n","webhookReceived":"Webhooks","status":"Estado","started":"Iniciado","ended":"Finalizado","paused":"En pausa","renewalReminder":"Recordatorio de renovaci\xf3n","renewed":"Renovado","resumed":"Reanudado","skipped":"Pospuesto","all":"Todos","canceled":"Cancelado","expired":"Caducado","partiallyRefunded":"Reembolsado (parcialmente)","orderSuccess":"Pedido realizado","orderFailed":"Pedido fallido","orderCanceled":"Pedido cancelado"}}}'),eG=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Prenumeration | Mollie Prenumerationer"},"businessEvents":{"mollie_checkout_order_success":" Lyckad best\xe4llning","mollie_checkout_order_failed":" Misslyckad best\xe4llning","mollie_checkout_order_canceled":" Avbruten best\xe4llningen","mollie_webhook_received_All":" Mollie Webhook Mottagen (Alla)","mollie_webhook_received_status_authorized":" Mollie Webhook Mottagen (Auktoriserad)","mollie_webhook_received_status_failed":" Mollie Webhook Mottagen (Misslyckad)","mollie_webhook_received_status_canceled":" Mollie Webhook Mottagen (Avbruten)","mollie_webhook_received_status_expired":" Mollie Webhook Mottagen (Har utg\xe5tt)","mollie_webhook_received_status_pending":" Mollie Webhook Mottagen (P\xe5g\xe5ende)","mollie_webhook_received_status_paid":" Mollie Webhook Mottagen (Betald)","mollie_webhook_received_status_completed":" Mollie Webhook Mottagen (Slutf\xf6rd)","mollie_webhook_received_status_refunded":" Mollie Webhook Mottagen (\xc5terbetald)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Mottagen (Delvis \xe5terbetalad)","mollie_refund_started":" Mollie \xe5terbetalning p\xe5b\xf6rjad","mollie_subscription_started":" Mollie-prenumerationen har startat","mollie_subscription_ended":" Mollie-prenumerationen slutf\xf6rd","mollie_subscription_cancelled":" Mollie prenumeration avbruten","mollie_subscription_paused":" Mollie-prenumerationen har pausats","mollie_subscription_resumed":" Mollie-prenumerationen har \xe5terupptagits","mollie_subscription_skipped":" Mollie-prenumerationen har hoppats \xf6ver","mollie_subscription_renewed":" Mollie prenumeration f\xf6rnyad","mollie_subscription_renewal_reminder":" Mollie p\xe5minnelse f\xf6r prenumerationsf\xf6rnyelse"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"S\xf6k prenumerationer...","general":{"mainMenuItemGeneral":"Mollie Betalningar","descriptionTextModule":"Mollie Betalningar","btnMollieActions":"Mollie \xe5tg\xe4rder","refundThroughMollie":"\xc5terbetalning genom Mollie","shipThroughMollie":"Frakta genom Mollie","cancelMollieItem":"Avbryt genom Mollie"},"config":{"info":{"title":"Hej {userName}, V\xe4lkommen till Mollie!","descriptionTop":"Att b\xf6rja med Mollie \xe4r enkelt!","descriptionBottom":"Det var allt!","descriptionFooter":"Om du vill l\xe4ra dig mer om v\xe5rt plugin, v\xe4nligen bes\xf6k v\xe5r officiella dokumentationssida.","onboardingStep1":"Registrera dig f\xf6r ett Mollie-konto.","onboardingStep2":"Ange dina API-nycklar i avsnittet nedan.","onboardingStep2TestMode":"Sl\xe5 p\xe5 \'Test Mode\' om du endast vill testa betalningar.","onboardingStep3":"Tilldela betalningsmetoder till din f\xf6rs\xe4ljningskanal.","onboardingStep3Link":"till dina f\xf6rs\xe4ljningskanaler","btnDocumentation":"Dokumentation","btnRequestSupport":"St\xf6d","btnTroubleshooting":"Fels\xf6kningsguide"},"api":{"apiLinkButton":"H\xe4mta dina API-nycklar fr\xe5n Mollie Dashboard","testButton":"Test API-nycklar","testApiKeys":{"title":"Mollie Betalningar","apiKey":"API-nyckel","isValid":"\xe4r giltig","isInvalid":"\xe4r ogiltigt"}},"payments":{"format":{"placeholder":"Platsh\xe5llare","preview":"F\xf6rhandsvisning"},"updatePaymentMethods":{"title":"Mollie Betalningar","button":"Uppdatera betalningsmetoder","succeeded":"Betalningsmetoderna har uppdaterats framg\xe5ngsrikt.","failed":"Betalningsmetoderna kunde inte uppdateras."},"mollieLimits":{"link":"Visa mollie tillg\xe4nglighetsregler f\xf6r betalningsmetoder"}},"rounding":{"info1":"Shopware kan anv\xe4nda valuta-inst\xe4llningar f\xf6r att ber\xe4kna hur den avrundar en best\xe4llnings totala belopp. Detta inkluderar antalet decimaler i din produktpriss\xe4ttning och det n\xe4rmaste avrundningsintervallet, s\xe5som 0,50 eller 1,00.","info2":"Dessa inst\xe4llningar kan leda till ett annat totalbelopp \xe4n den totala summan av radposter. N\xe4r Mollie kontrollerar dessa belopp och uppt\xe4cker att de inte st\xe4mmer, orsakar det ett checkoutfel.","info3":"Du kan anv\xe4nda den h\xe4r funktionen f\xf6r att undvika avrundningsproblem i din checkout. N\xe4r den \xe4r aktiverad l\xe4ggs en separat radpost till i ditt Mollie Dashboard f\xf6r skillnaden i avrundning, och dina kunder betalar det totala belopp som ber\xe4knats av Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det \xe4r inte m\xf6jligt att anv\xe4nda Klarna Betala nu, Klarna Slice it eller Klarna Betala senare som metod n\xe4r ditt utg\xe5ngsdatum \xe4r mer \xe4n 28 dagar fram\xe5t i tiden, om inte en annan maximal tid har \xf6verenskommits mellan handlaren och Klarna.","bankTransferDueDateLimitReached":"Det \xe4r inte m\xf6jligt att st\xe4lla in best\xe4llningens livsl\xe4ngd h\xf6gre \xe4n 100 dagar."},"support":{"modalTitle":"Beg\xe4r hj\xe4lp fr\xe5n Mollie","btnCancel":"Avbryt","btnConfirm":"Beg\xe4ran hj\xe4lp","btnSupport":"Mer om v\xe5rt hj\xe4lp","form":{"name":"Ditt namn","email":"Din e-post","recipient":"Skicka beg\xe4ran till","subject":"\xc4mne","message":"Meddelande"},"data":{"header":"Data skickat till Mollie:","other":"\xd6vrigt:","shopwareVersion":"Shopware-version","pluginLogs":"{plugin} loggfiler","pluginConfiguration":"{plugin} konfiguration","pluginConfigurationHelpText":"API-nycklar \xe4r uteslutna.","paymentMethods":"Betalningsmetoddata","paymentMethodsHelpText":"Inneh\xe5ller information om vilka betalningsmetoder som \xe4r aktiva, tilldelade varje f\xf6rs\xe4ljningskanal, samt deras status i ditt Mollie-konto."},"success":"F\xf6rfr\xe5gan om hj\xe4lp har skickats framg\xe5ngsrikt. Vi g\xf6r v\xe5rt b\xe4sta f\xf6r att svara s\xe5 snart som m\xf6jligt","error":"Det uppstod ett problem n\xe4r mailet skickades via Shopware. V\xe4nligen f\xf6rs\xf6k igen eller kontakta oss direkt via e-post."}},"rules":{"itemSubscriptionRule":"Objektet \xe4r en prenumeration (Mollie)","cartSubscriptionRule":"Varukorg med prenumerationer (Mollie)"},"refunds":{"status":{"queued":"K\xf6ad","pending":"P\xe5g\xe5ende","processing":"Bearbetar","refunded":"\xc5terbetald","failed":"Misslyckad","description":{"queued":"\xc5terbetalningen \xe4r k\xf6ad tills det finns tillr\xe4ckligt med saldo f\xf6r att bearbeta \xe5terbetalningen. Du kan fortfarande avbryta \xe5terbetalningen.","pending":"\xc5terbetalningen kommer att skickas till banken n\xe4sta arbetsdag. Du kan fortfarande avbryta \xe5terbetalningen.","processing":"\xc5terbetalningen har skickats till banken. \xc5terbetalt belopp kommer att \xf6verf\xf6ras till konsumentens konto s\xe5 snart som m\xf6jligt.","refunded":"\xc5terbetalat belopp har \xf6verf\xf6rts till konsumenten.","failed":"\xc5terbetalningen har misslyckats efter bearbetningen. Till exempel har kunden st\xe4ngt sitt bankkonto. Medlen kommer att \xe5terf\xf6ras till ditt konto."}}},"refund-manager":{"general":{"unitQuantity":"st."},"acl":{"warningCreate":"Du har inte beh\xf6righet att skapa \xe5terbetalningar","warningCancel":"Du har inte beh\xf6righet att avboka \xe5terbetalningar"},"cart":{"title":"Best\xe4llning ##orderNumber##","btnSelectAll":"V\xe4lj Alla","btnResetForm":"\xc5terst\xe4llnings Formul\xe4r","linkHowTo":"Hur anv\xe4nder jag detta formul\xe4r?","grid":{"columns":{"item":"Objekt","productNumber":"Produktnummer","unitPrice":"Enhetspris","quantity":"Antal","refunded":"\xc5terbetald","refundQuantity":"\xc5terbetalning","totalPrice":"Totalt","refundAmount":"\xc5terbetalning","resetStock":"\xc5terst\xe4ll lager"},"btnResetLine":"\xc5terst\xe4ll rad","checkDeductPromotion":"Dra av kampanj","checkRefundTax":"\xc5terbetalning av moms"},"roundDiffItemAdded":"Automatiskt avrundningsobjekt har lagts till"},"instructions":{"linkResetTutorials":"\xc5terst\xe4ll handledningar","btnToggleTutorial":"Visa/D\xf6lj handledning","titleFullRefund":"Full \xe5terbetalning","textFullRefund":"Anv\xe4nd bara knappen f\xf6r full \xe5terbetalning. Detta s\xe4kerst\xe4ller att alla dina objekt markeras som \xe5terbetalda och hela beloppet \xe5terg\xe5r till kunden.","titleStockReset":"Lager\xe5terst\xe4llning","textStockReset":"Du kan automatiskt \xf6ka det tillg\xe4ngliga lagret genom att ange den m\xe4ngd du vill s\xe4tta tillbaka i lager. Ange det innan du g\xe5r vidare med en fullst\xe4ndig eller delvis \xe5terbetalning. \xc5terst\xe4llning av lagret kan kombineras med den faktiska \xe5terbetalningsprocessen p\xe5 ett flexibelt s\xe4tt.","titleShipping":"Frakt","textShipping":"Fraktartiklar kan \xe5terbetalas som alla andra produktartiklar. Antingen anger du hela m\xe4ngden eller ett anpassat delbelopp och g\xe5r vidare med \xe5terbetalningen. \xc5terbetalning av fraktkostnader kan kombineras med den faktiska \xe5terbetalningsprocessen f\xf6r artiklar p\xe5 ett flexibelt s\xe4tt.","titlePartialAmount":"Delvis \xe5terbetalning (endast belopp)","textPartialAmount":"Ange bara delbeloppet i textf\xe4ltet och starta \xe5terbetalningen.","titlePartialItems":"Delvis \xe5terbetalning (med artiklar)","textPartialItems":"Om du vill markera m\xe4ngder och artiklar som \xe5terbetalda i Mollie, anv\xe4nd formul\xe4ret ovan. St\xe4ll in dina m\xe4ngder och ange ett anpassat belopp f\xf6r varje produkt som ska \xe5terbetalas. Totalsumman kommer sedan att synas i det slutliga \xe5terbetalningsbeloppets textf\xe4lt. Kom ih\xe5g, det \xe4r fortfarande m\xf6jligt att justera detta slutliga belopp innan du startar din \xe5terbetalning.","titlePartialPromotions":"Delvis \xe5terbetalning (med kampanjer)","textPartialPromotions":"Om du har en kampanj i din varukorg s\xe5 \xe4r din kampanj en separat artikelrad. Om du vill \xe5terbetala alla rabatterade artiklar, g\xe5 vidare och \xe5terbetala deras totalsummor och hela kampanjartikeln i sig. Men om du bara vill \xe5terbetala n\xe5gra f\xe5 artiklar som \xe4r rabatterade kan du dra av den till\xe4mpade rabatten automatiskt f\xf6r varje enskild artikelrad. Du kan sj\xe4lvklart alltid \xe4ndra v\xe4rden om de inte \xe4r korrekta.","titleRoundingDiff":"Avrundningsskillnad","textRoundingDiff":"En full \xe5terbetalning kommer att inkludera avrundningsskillnader"},"summary":{"dataLoading":"Data laddas...","headerExcludingVat":"Exkl. moms","headerIncludingVat":"Inkl. moms","captionTotal":"Totalt","captionTotalTaxFree":"Totalt","captionPendingRefunds":"V\xe4ntar p\xe5 att \xe5terbetalas","captionVouchers":"V\xe4rde av voucher","captionRefunded":"\xc5terbetalt belopp","captionRemaining":"\xc5terbetalningsbart belopp","btnFixDiff":"Fixa skillnaden","placeholderDescription":"Ange bank-/korttransaktionsbeskrivning f\xf6r konsumenten. Max 140 tecken","lblDescription":"Beskrivning (valfritt) ({characters}/140 tecken)","descriptionHelp":"Detta kommer att visas p\xe5 konsumentens bank- eller kortutdrag n\xe4r det \xe4r m\xf6jligt. Meddelandet kommer att avkortas efter 140 tecken.","placeholderInternalDescription":"Ange din interna beskrivning","lblInternalDescription":"Intern beskrivning (valfritt)","internalDescriptionHelp":"Detta kommer att visas som en lokal beskrivning i admingr\xe4nssnittet.","checkVerification":"Jag har kontrollerat det totala \xe5terbetalningsbeloppet och de konfigurerade m\xe4ngderna f\xf6r att \xe5terbetala och lagra p\xe5 nytt.","btnRefund":"\xc5terbetalning","btnFullRefund":"Full \xe5terbetalning","roundDiffItemAdded":"Avrundningsobjekt"},"refunds":{"title":"\xc5terbetalningar i Mollie Dashboard","linkMore":"Mer om \xe5terbetalningar","grid":{"columns":{"amount":"Belopp","status":"Status","description":"Beskrivning","internalDescription":"Intern beskrivning","composition":"Komposition","date":"Datum"},"lblNoComposition":"Ingen tillg\xe4nglig komposition","btnCancelRefund":"Avbryt denna \xe5terbetalning"}},"notifications":{"success":{"refund-created":"En \xe5terbetalning har skapats i Mollie. Det kan ta 2 timmar f\xf6r \xe5terbetalningen att slutf\xf6ras. Fram till dess kan du avbryta \xe5terbetalningen.","refund-canceled":"Den p\xe5g\xe5ende \xe5terbetalningen har framg\xe5ngsrikt avbrutits och tagits bort."},"error":{"low-amount":"Ange ett belopp som ska \xe5terbetalas.","refund-created":"N\xe5got gick fel n\xe4r en \xe5terbetalning skapades.","refund-canceled":"Det uppstod ett problem n\xe4r den p\xe5g\xe5ende \xe5terbetalningen avbr\xf6ts. V\xe4nligen f\xf6rs\xf6k igen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Voucherbetalningar","VOUCHER_INFO_DESCRIPTION":"Mollie l\xe5ter dig enkelt ta emot betalningar i din webbutik med hj\xe4lp av Eco-, present- och m\xe5ltidsvouchers – ett smart val f\xf6r att \xf6ka f\xf6rs\xe4ljningen och tillfredsst\xe4lla dina kunder. Betalningsmetoden \\"voucher\\" \xe4r endast synlig om du har minst 1 produkt med en tilldelad vouchertyp i varukorgen.","VOUCHER_INFO_DEFAULTLANGUAGE":"Observera att denna konfiguration endast kan redigeras p\xe5 ditt standardspr\xe5k. V\xe4nligen \xe4ndra ditt spr\xe5k f\xf6r att modifiera vouchertypen f\xf6r denna produkt.","VOUCHER_BTN_READMORE":"L\xe4s mer","VOUCHER_TYPE_CAPTION":"Vouchertyp av produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"Ekologisk","VOUCHER_TYPE_VALUE_MEAL":"M\xe5ltid","VOUCHER_TYPE_VALUE_VOUCHER":"Present"},"modals":{"shipping":{"title":"Frakta genom Mollie","item":{"label":"Artikel:","noQuantity":"V\xe4nligen ange en kvantitet att frakta.","shipAll":"Frakta allt","summary":{"quantity":"Antal att frakta","shipped":"M\xe4ngd skickad","shippable":"M\xe4ngd som kan skickas"},"success":"Best\xe4llningen har fraktats framg\xe5ngsrikt."},"order":{"description":"De f\xf6ljande artikelm\xe4ngderna kommer att skickas.","itemHeader":"Artikel","quantityHeader":"M\xe4ngd","originalQuantityHeader":"Kvantitet (leveransbar)"},"availableTracking":{"label":"Tillg\xe4ngliga sp\xe5rningskoder","hint":"Klicka p\xe5 en av dessa sp\xe5rningskoder f\xf6r att automatiskt fylla i all data."},"showTracking":"L\xe4gg till sp\xe5rningsinformation f\xf6r denna leverans","tracking":{"carrier":"Transport\xf6r","code":"Kod","url":"Url","invalid":"Ange b\xe5de transport\xf6r och kod"},"confirmButton":"Frakta best\xe4llning","cancelButton":"Avbryt","selectAllButton":"V\xe4lj alla","resetButton":"\xc5terst\xe4ll"},"cancel":{"title":"Avbryt objekt genom mollie","confirmButton":"Avbryt objekt genom mollie","cancelButton":"St\xe4ng modal","resetStock":"\xc5terst\xe4ll lager","item":{"success":"Produkt avbokad framg\xe5ngsrikt","failed":{"quantityZero":"Kvantitet \xe4r 0","invalidLine":"Produkten finns inte i best\xe4llningen","quantityTooHigh":"Kvantiteten \xe4r f\xf6r h\xf6g"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Frakta best\xe4llning (Mollie)","description":"Frakta order i Mollie."},"modal":{"title":"Frakta best\xe4llning","description":"Denna \xe5tg\xe4rd kommer automatiskt att frakta en best\xe4llning genom Mollie. Anv\xe4ndarfl\xf6det kommer att ta emot best\xe4llningsnumret och vidarebefordra det till Mollie API. Frakt som lyckas och frakt som misslyckas kommer att synas i Mollie-loggfilerna.","warningConfig":"V\xe4nligen se till att st\xe4nga av alla ytterligare automatiseringar f\xf6r denna typ av \xe5tg\xe4rd f\xf6r att undvika st\xf6rningar.\\nDe f\xf6ljande aktiverade funktionerna i denna plugin kan st\xf6ra denna \xe5tg\xe4rd:","noWarnings":"Inga varningar"}},"refundOrder":{"editor":{"title":"\xc5terbetalning av order (Mollie)","description":"\xc5terbetala order genom Mollie."},"modal":{"title":"\xc5terbetalning av order","description":"Denna \xe5tg\xe4rd kommer automatiskt att frakta en best\xe4llning genom Mollie. Anv\xe4ndarfl\xf6det kommer att ta emot best\xe4llningsnumret och vidarebefordra det till Mollie API. Frakt som lyckas och frakt som misslyckas kommer att synas i Mollie-loggfilerna.","warning":"Var v\xe4nlig observera att \xe5terbetalningar kan ta upp till 2 timmar att slutf\xf6ras och bli synliga i butiken. Fram till dess kan du alltid avbryta en p\xe5g\xe5ende \xe5terbetalning antingen fr\xe5n best\xe4llningssidan i Shopware eller fr\xe5n Mollie Dashboard.","warningConfig":"V\xe4nligen se till att st\xe4nga av alla ytterligare automatiseringar f\xf6r denna typ av \xe5tg\xe4rd f\xf6r att undvika st\xf6rningar."}},"warnings":{"automaticShipping":"Automatisk frakt i plugin-konfiguration"}}},"subscriptions":{"status":{"pending":"P\xe5g\xe5ende","active":"Aktiv","canceled":"Avbruten","suspended":"Avst\xe4ngd","completed":"Slutf\xf6rd","paused":"Pausad","resumed":"\xc5terupptagen","skipped":"Hoppade \xf6ver"},"navigation":{"title":"Mollie Prenumerationer"},"TYPE_DAYS":"Dag(ar)","TYPE_WEEKS":"Vecka(or)","TYPE_MONTHS":"M\xe5nad(er)","confirm":{"cancelTitle":"Avsluta prenumerationen?","cancel":"Avbryt din kunds prenumeration.","pauseTitle":"Pausa prenumeration?","pause":"S\xe4tt prenumerationen p\xe5 paus tills du \xe5terupptar den igen.","resumeTitle":"\xc5teruppta prenumeration?","resume":"Forts\xe4tt prenumerationen igen.","skipTitle":"Hoppa \xf6ver n\xe4sta betalning?","skip":"Hoppa \xf6ver n\xe4sta avbetalning i prenumerationen. Den forts\xe4tter automatiskt efter\xe5t."},"alerts":{"cancelSuccess":"Prenumerationen har avbrutits framg\xe5ngsrikt","pauseSuccess":"Prenumerationen har pausats framg\xe5ngsrikt","resumeSuccess":"Prenumerationen har \xe5terupptagits framg\xe5ngsrikt","skipSuccess":"Prenumerationen har hoppa \xf6verts framg\xe5ngsrikt. N\xe4sta betalning har uppdaterats."},"list":{"title":"Mollie Prenumerationer","columns":{"customer":"Kund","status":"Status","description":"Beskrivning","amount":"Belopp","nextPaymentAt":"N\xe4sta betalning","prePaymentReminder":"P\xe5mind klockan","canceledAt":"Avbruten klockan","createdAt":"Skapad klockan"},"action":{"edit":"Redigera prenumeration"},"deletedCustomer":"Raderad kund"},"detail":{"title":"Mollie prenumeration","buttonCancelSubscription":"Avbryt prenumeration","labelDescription":"Beskrivning","labelAmount":"Belopp","labelQuantity":"Kvantitet","labelMollieSubscription":"Mollie Prenumeration","labelMollieCustomer":"Mollie kund","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware kund","labelCreatedAt":"Skapad klockan","buttonShowShopwareOrder":"Visa Shopware best\xe4llning","buttonShowShopwareCustomer":"Visa Shopware kund","cardTitleSubscription":"Prenumeration","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"N\xe4sta betalning klockan","labelLastRemindedAt":"Senaste p\xe5minnelse klockan","labelCanceledAt":"Avbruten klockan","buttonPauseSubscription":"Pausa prenumeration","buttonResumeSubscription":"\xc5teruppta prenumeration","buttonSkipSubscription":"Hoppa \xf6ver prenumeration","history":{"cardTitle":"Historik","colDate":"Datum","colComment":"Kommentar","colStatusFrom":"Status (fr\xe5n)","colStatusTo":"Status (till)","colMollieSubscription":"Mollie prenumeration"}},"product":{"card-title":"Prenumeration","title":"Mollie Prenumerationer","description":"Att hantera dina \xe5terkommande betalningar \xe4r enklare \xe4n n\xe5gonsin med v\xe5ra hj\xe4lpsamma funktioner. Ta din verksamhet till n\xe4sta niv\xe5 med effektiva sp\xe5rningsalternativ, enkla integrationer och mer. Med Mollie-prenumerationer kan du enkelt skapa prenumerationsprodukter och schemal\xe4gga \xe5terkommande betalningar att \xe4ga rum vid det konfigurerade intervallet och perioden.","mollieSubscriptionProduct":"Prenumerationsprodukt","mollieSubscriptionIntervalAmount":"Upprepa betalning varje","mollieSubscriptionIntervalType":"Intervall enhet","mollieSubscriptionRepetitionAmount":"Antal upprepningar","mollieSubscriptionRepetitionPlaceholder":"Ange nummer eller l\xe4mna tomt","infoDefaultLanguage":"V\xe4nligen observera att denna konfiguration endast kan redigeras p\xe5 ditt standardspr\xe5k. V\xe4nligen \xe4ndra ditt spr\xe5k f\xf6r att \xe4ndra prenumerationsinst\xe4llningarna f\xf6r denna produkt.","btnReadMore":"L\xe4s mer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Prenumeration"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kreditkort data","buttonMolliePaymentLink":"Kopiera till urklipp","columnRefunded":"\xc5terbetald","columnShipped":"Fraktad","columnCanceled":"Avbruten","labelMollieOrderId":"Mollie Best\xe4llnings-ID","labelMollieThirdPartyPaymentId":"Betalningsreferens","labelMolliePaymentLink":"Mollie Checkout-URL","totalRefunds":"\xc5terbetalt belopp","totalRefundsPending":"V\xe4ntar p\xe5 att bli \xe5terbetald","totalRemaining":"Belopp f\xf6r \xe5terbetalning","totalVouchers":"V\xe4rde av voucher","totalShipments":"Fraktbelopp ({quantity} artiklar)","subscriptionBadge":"Prenumerationsbest\xe4llning","refundManager":{"title":"Mollie \xc5terbetalningshanterare","btnOpenRefundManager":"\xd6ppna \xe5terbetalningshanterare","btnCloseRefundManager":"St\xe4ng \xe5terbetalningshanterare"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"\xd6nskad iDeal-utgivare"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"\xc5terbetalningshanterare"},"mollie_subscription":{"label":"Prenumerationer"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Beskrivning"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"\xc5terbetalning","subscription":"Prenumeration","webhookReceived":"Webhooks","status":"Status","started":"Startad","ended":"Avslutad","paused":"Pausad","renewalReminder":"P\xe5minnelse om f\xf6rnyelse","renewed":"F\xf6rnyad","resumed":"\xc5terupptagen","skipped":"Hoppade \xf6ver","all":"Alla","canceled":"Avbruten","expired":"Utg\xe5tt","partiallyRefunded":"\xc5terbetald (delvis)","orderSuccess":"Best\xe4llning lyckad","orderFailed":"Best\xe4llning misslyckades","orderCanceled":"Best\xe4llning avbruten"}}}'),eY=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie-abonnement | Mollie-abonnementer"},"businessEvents":{"mollie_checkout_order_success":"Bestilling vellykket","mollie_checkout_order_failed":"Bestilling mislyktes","mollie_checkout_order_canceled":"Bestilling kansellert","mollie_webhook_received_All":"Mollie Webhook Mottatt (Alle)","mollie_webhook_received_status_authorized":"Mollie Webhook Mottatt (Autorisert)","mollie_webhook_received_status_failed":"Mollie Webhook Mottatt (Mislyktes)","mollie_webhook_received_status_canceled":"Mollie Webhook Mottatt (Kansellert)","mollie_webhook_received_status_expired":"Mollie Webhook Mottatt (Utl\xf8pt)","mollie_webhook_received_status_pending":"Mollie Webhook Mottatt (Ventende)","mollie_webhook_received_status_paid":"Mollie Webhook Mottatt (Betalt)","mollie_webhook_received_status_completed":"Mollie Webhook Mottatt (Fullf\xf8rt)","mollie_webhook_received_status_refunded":"Mollie Webhook Mottatt (Refundert)","mollie_webhook_received_status_partially_refunded":"Mollie Webhook Mottatt (Delvis refundert)","mollie_refund_started":"Mollie refusjon startet","mollie_subscription_started":"Mollie abonnement startet","mollie_subscription_ended":"Mollie abonnement fullf\xf8rt","mollie_subscription_cancelled":"Mollie abonnement kansellert","mollie_subscription_paused":"Mollie abonnement satt p\xe5 pause","mollie_subscription_resumed":"Mollie abonnement gjenopptatt","mollie_subscription_skipped":"Mollie abonnement hoppet over","mollie_subscription_renewed":"Mollie abonnement fornyet","mollie_subscription_renewal_reminder":"Mollie p\xe5minnelse om fornyelse av abonnement"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"S\xf8k abonnementer...","general":{"mainMenuItemGeneral":"Mollie Betalinger","descriptionTextModule":"Mollie Betalinger","btnMollieActions":"Mollie Handlinger","refundThroughMollie":"Refusjon gjennom Mollie","shipThroughMollie":"Frakt gjennom Mollie","cancelMollieItem":"Kanseller gjennom Mollie"},"config":{"info":{"title":"Hei {userName}, Velkommen til Mollie!","descriptionTop":"Onboarding er enkelt med Mollie!","descriptionBottom":"Det er det!","descriptionFooter":"Hvis du \xf8nsker \xe5 l\xe6re mer om v\xe5r plugin, vennligst bes\xf8k v\xe5r offisielle dokumentasjonside.","onboardingStep1":"Registrer deg for en Mollie konto.","onboardingStep2":"Oppgi API-n\xf8klene dine i seksjonen nedenfor.","onboardingStep2TestMode":"Aktiver \'Testmodus\' hvis du kun \xf8nsker \xe5 teste betalinger.","onboardingStep3":"Tildel betalingsmetoder til salgs kanalen din.","onboardingStep3Link":"til dine salgskanaler","btnDocumentation":"Dokumentasjon","btnRequestSupport":"Support","btnTroubleshooting":"Feils\xf8kingsguide"},"api":{"apiLinkButton":"Hent API-n\xf8klene dine fra Mollie Dashboard","testButton":"Test API n\xf8kler","testApiKeys":{"title":"Mollie Betalinger","apiKey":"API-n\xf8kkel","isValid":"er gyldig","isInvalid":"er ugyldig"}},"payments":{"format":{"placeholder":"Plassholder","preview":"Forh\xe5ndsvisning"},"updatePaymentMethods":{"title":"Mollie Betalinger","button":"Oppdater betalingsmetoder","succeeded":"Betalingsmetodene er oppdatert.","failed":"Betalingsmetodene kunne ikke oppdateres."},"mollieLimits":{"link":"Vis mollie tilgjengelighetsregler for betalingsmetoder"}},"rounding":{"info1":"Shopware kan bruke valutainnstillinger for \xe5 beregne hvordan den avrunder totalbel\xf8pet for en bestilling. Dette inkluderer antall desimaler i produktprisene dine og n\xe6rmeste avrundingsintervall, som for eksempel 0,50 eller 1,00.","info2":"Disse innstillingene kan f\xf8re til et annet totalbel\xf8p enn totalsummen av linjeelementene. N\xe5r Mollie kryssjekker disse bel\xf8pene og finner ut at de ikke stemmer overens, for\xe5rsaker det en feil ved utsjekking.","info3":"Du kan bruke denne funksjonen for \xe5 unng\xe5 avrundingsproblemer ved utsjekking. N\xe5r den er aktivert, legger den til et eget linjeelement i ditt Mollie Dashboard for forskjellen i avrunding, og kundene dine betaler totalbel\xf8pet beregnet av Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det er ikke mulig \xe5 bruke Klarna Betal n\xe5, Klarna Delbetaling eller Klarna Betal senere som metode n\xe5r utl\xf8psdatoen er mer enn 28 dager frem i tid, med mindre en annen maksimumsperiode er avtalt mellom selgern og Klarna.","bankTransferDueDateLimitReached":"Det er ikke mulig \xe5 sette bestillingens levetid h\xf8yere enn 100 dager."},"support":{"modalTitle":"Be om support fra Mollie","btnCancel":"Avbryt","btnConfirm":"Be om st\xf8tte","btnSupport":"Mer om v\xe5r st\xf8tte","form":{"name":"Ditt navn","email":"Din e-post","recipient":"Send foresp\xf8rsel til","subject":"Emne","message":"Melding"},"data":{"header":"Data sendt til Mollie:","other":"Annet:","shopwareVersion":"Shopware-versjon","pluginLogs":"{plugin} loggfiler","pluginConfiguration":"{plugin} konfigurasjon","pluginConfigurationHelpText":"API-n\xf8kler er ekskludert.","paymentMethods":"Betalingsmetode-data","paymentMethodsHelpText":"Inneholder informasjon om hvilke betalingsmetoder som er aktive, tildelt hver salgskanal, samt deres status i Mollie-kontoen din."},"success":"St\xf8tteforesp\xf8selen har blitt sendt. Vi gj\xf8r v\xe5rt beste for \xe5 svare s\xe5 snart som mulig","error":"Det oppstod et problem da e-posten ble sendt gjennom Shopware. Vennligst pr\xf8v igjen eller kontakt oss direkte via e-post."}},"rules":{"itemSubscriptionRule":"Vare er abonnement (Mollie)","cartSubscriptionRule":"Handlekurv med abonnementer (Mollie)"},"refunds":{"status":{"queued":"K\xf8et","pending":"Ventende","processing":"Behandles","refunded":"Refundert","failed":"Mislyktes","description":{"queued":"Refusjonen er satt i k\xf8 til det er tilstrekkelig saldo for \xe5 behandle refusjonen. Du kan fortsatt kansellere refusjonen.","pending":"Refusjonen vil bli sendt til banken neste virkedag. Du kan fortsatt kansellere refusjonen.","processing":"Refusjonen har blitt sendt til banken. Refundert bel\xf8p vil bli overf\xf8rt til forbrukerkontoen s\xe5 snart som mulig.","refunded":"Refundert bel\xf8p har blitt overf\xf8rt til forbrukeren.","failed":"Refusjonen har mislyktes etter behandling. For eksempel, kunden har stengt sin bankkonto. Midlene vil bli overf\xf8rt til kontoen din."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Du har ikke tillatelse til \xe5 opprette refusjoner","warningCancel":"Du har ikke tillatelse til \xe5 kansellere refusjoner"},"cart":{"title":"Bestilling ##orderNumber##","btnSelectAll":"Velg alle","btnResetForm":"Nullstill skjema","linkHowTo":"Hvordan bruke dette skjemaet?","grid":{"columns":{"item":"Vare","productNumber":"Produktnummer","unitPrice":"Enhetspris","quantity":"Antall","refunded":"Refundert","refundQuantity":"Refusjon","totalPrice":"Totalt","refundAmount":"Refusjon","resetStock":"Nullstill lager"},"btnResetLine":"Nullstill linje","checkDeductPromotion":"Trekk fra rabatt","checkRefundTax":"Refusjon av MVA"},"roundDiffItemAdded":"Automatisk avrunding av vare ble lagt til"},"instructions":{"linkResetTutorials":"Nullstill veiledninger","btnToggleTutorial":"Vis/Skjul veiledning","titleFullRefund":"Full refusjon","textFullRefund":"Bare bruk knappen for full refusjon. Dette sikrer at alle varene blir merket som refusert og at hele bel\xf8pet blir betakebetalt til kunden.","titleStockReset":"Lager nullstilling","textStockReset":"Du kan automatisk \xf8ke tilgjengelig lager ved \xe5 skrive inn antallet du \xf8nsker \xe5 sette tilbake p\xe5 lager. Bare skriv det inn f\xf8r du fortsetter med en full eller delvis refusjon. Nullstilling av lageret kan kombineres med selve refusjonsprosessen p\xe5 en fleksibel m\xe5te.","titleShipping":"Frakt","textShipping":"Fraktvarer kan refunderes som andre produktvarer. Enten angi hele antallet eller et tilpasset delbel\xf8p, og fortsett med refusjonen. Refusjon av fraktkostnader kan kombineres med selve refusjonsprosessen for varer p\xe5 en fleksibel m\xe5te.","titlePartialAmount":"Delvis refusjon (kun bel\xf8p)","textPartialAmount":"Bare angi delbel\xf8pet i tekstfeltet og start refusjonen.","titlePartialItems":"Delvis refusjon (med varer)","textPartialItems":"Hvis du vil merke antall og varer som refundert i Mollie, bruk skjemaet ovenfor. Sett antallet og angi et tilpasset bel\xf8p for hver vare som skal refunderes. Den totale summen vil deretter vises i textfeltet for det endelige refusjonsbel\xf8pet. Husk at det fortsatt er mulig \xe5 justere dette sluttbel\xf8pet f\xf8r du starter refusjonen.","titlePartialPromotions":"Delvis refusjon (med rabatter)","textPartialPromotions":"Hvis du har en rabatt i handlekurven, s\xe5 er rabatten en egen linjevare. Hvis du \xf8nsker \xe5 refundere alle rabatterte varer, kan du refundere deres totale verdi og hele rabattlinjen. Hvis du derimot kun \xf8nsker \xe5 refundere noen f\xe5 rabatterte varer, kan du automatisk trekke fra den brukte rabatten for hver enkelt linjevare. Du kan selvf\xf8lgelig alltid endre verdier hvis de ikke er korrekte.","titleRoundingDiff":"Avrundingsforskjell","textRoundingDiff":"En full refusjon vil inkludere avrundingsforskjeller"},"summary":{"dataLoading":"Data lastes...","headerExcludingVat":"Ekskl. MVA","headerIncludingVat":"Inkl. MVA","captionTotal":"Totalt","captionTotalTaxFree":"Totalt","captionPendingRefunds":"Venter p\xe5 \xe5 bli refundert","captionVouchers":"Kupongbel\xf8p","captionRefunded":"Refundert bel\xf8p","captionRemaining":"Refunderbart bel\xf8p","btnFixDiff":"Juster forskjell","placeholderDescription":"Angi beskrivelse for bank-/kortutskrift for forbrukeren. Maks 140 tegn","lblDescription":"Beskrivelse (valgfritt) ({characters}/140 tegn)","descriptionHelp":"Dette vil vises p\xe5 forbrukerens bank- eller kortutskrift n\xe5r det er mulig. Meldingen vil bli avkortet etter 140 tegn.","placeholderInternalDescription":"Angi din interne beskrivelse","lblInternalDescription":"Intern beskrivelse (valgfritt)","internalDescriptionHelp":"Dette vil bli vist som en lokal beskrivelse i administrasjonsgrensesnittet.","checkVerification":"Jeg har bekreftet det totale refusjonsbel\xf8pet og de konfigurerte antallene som skal refunderes og tillbake p\xe5 lager.","btnRefund":"Refusjon","btnFullRefund":"Full refusjon","roundDiffItemAdded":"Avrundingspost"},"refunds":{"title":"Refusjoner i Mollie Dashboard","linkMore":"Mer om refusjoner","grid":{"columns":{"amount":"Bel\xf8p","status":"Status","description":"Beskrivelse","internalDescription":"Intern beskrivelse","composition":"Sammensetning","date":"Dato"},"lblNoComposition":"Ingen sammensetning tilgjengelig","btnCancelRefund":"Kanseller denne refusjonen"}},"notifications":{"success":{"refund-created":"En refusjon har blitt opprettet i Mollie. Det kan ta opptil 2 timer f\xf8r refusjonen er fullf\xf8rt. Inntil da kan du kansellere refusjonen.","refund-canceled":"Den ventende refusjonen er kansellert og fjernet."},"error":{"low-amount":"Vennligst oppgi et bel\xf8p som skal refunderes.","refund-created":"Noe gikk galt ved oppretting av refusjonen.","refund-canceled":"Det oppstod et problem ved kansellering av den ventende refusjonen. Vennligst pr\xf8v igjen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Kupong","VOUCHER_INFO_TITLE":"Kupongbetalinger","VOUCHER_INFO_DESCRIPTION":"Mollie lar deg enkelt akseptere betalinger i nettbutikken ved bruk av \xf8ko-, gave- og m\xe5ltidskuponger—et smart valg for \xe5 \xf8ke salg og gj\xf8re kundene forn\xf8yde. Betalingsmetoden \\"kupong\\" er kun synlig hvis du har minst 1 produkt med en tildelt kupongtype i handlekurven.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vennligst v\xe6r oppmerksom p\xe5 at denne konfigurasjonen kun kan redigeres p\xe5 ditt standardspr\xe5k. Vennligst endre spr\xe5ket ditt for \xe5 endre kupongtypen for dette produktet.","VOUCHER_BTN_READMORE":"Les mer","VOUCHER_TYPE_CAPTION":"Kupongtype for produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"\xd8ko","VOUCHER_TYPE_VALUE_MEAL":"M\xe5ltid","VOUCHER_TYPE_VALUE_VOUCHER":"Gave"},"modals":{"shipping":{"title":"Frakt gjennom Mollie","item":{"label":"Vare:","noQuantity":"Vennligst oppgi et antall som skal sendes.","shipAll":"Send alt","summary":{"quantity":"Antall som skal sendes","shipped":"Antall sendt","shippable":"Antall som kan sendes"},"success":"Bestillingen har blitt sendt."},"order":{"description":"F\xf8lgende vareantall vil bli sendt.","itemHeader":"Vare","quantityHeader":"Antall","originalQuantityHeader":"Antall (kan sendes)"},"availableTracking":{"label":"Tilgjengelige sporingskoder","hint":"Klikk p\xe5 en av disse sporingskodene for \xe5 fylle inn all data automatisk."},"showTracking":"Legg til sporingsinformasjon for denne forsendelsen","tracking":{"carrier":"Leverand\xf8r","code":"Kode","url":"Url","invalid":"Vennligst oppgi b\xe5de leverand\xf8r og kode"},"confirmButton":"Send bestilling","cancelButton":"Kanseller","selectAllButton":"Velg alt","resetButton":"Nullstill"},"cancel":{"title":"Kanseller vare gjennom mollie","confirmButton":"Kanseller vare gjennom mollie","cancelButton":"Lukk modal","resetStock":"Nullstill lager","item":{"success":"Produktet ble kansellert","failed":{"quantityZero":"Antallet er 0","invalidLine":"Produktet eksisterer ikke i bestillingen","quantityTooHigh":"Antallet er for h\xf8yt"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Send bestilling (Mollie)","description":"Send bestilling i Mollie."},"modal":{"title":"Send bestilling","description":"Denne handlingen vil automatisk sende en bestilling gjennom Mollie. Flytsekvensen vil motta bestillingsnummeret og sende det videre til Mollie API. Vellykkede forsendelser og mislykkede forsendelser vil v\xe6re synlige i Mollie-loggfilene.","warningConfig":"Vennligst deaktiver all ekstra automatisering for denne typen handling for \xe5 unng\xe5 forstyrrelser.\\nDe f\xf8lgende aktiverte funksjonene i dette plugin kan forstyrre handlingen:","noWarnings":"Ingen varsler"}},"refundOrder":{"editor":{"title":"Refusjon av bestilling (Mollie)","description":"Refunder bestilling gjennom Mollie."},"modal":{"title":"Refusjon av bestilling","description":"Denne handlingen vil automatisk starte en refusjon gjennom Mollie. Flytsekvensen vil motta bestillingsnummeret og sende dette videre til Mollie API. Vellykkede refusjoner og mislykkede refusjoner vil v\xe6re synlige i Mollie-loggfilene.","warning":"Vennligst husk at refusjoner kan ta opptil 2 timer f\xf8r de er fullf\xf8rt og synlig i butikken. Inntil da kan du alltid kansellere en ventende refusjon, enten fra bestillingssiden i Shopware eller fra Mollie Dashboard.","warningConfig":"Vennligst s\xf8rg for \xe5 deaktivere all automatikk for denne typen handling for \xe5 unng\xe5 forstyrrelser."}},"warnings":{"automaticShipping":"Automatisk frakt i plugin-konfigurasjonen"}}},"subscriptions":{"status":{"pending":"Ventende","active":"Aktiv","canceled":"Kansellert","suspended":"Suspendert","completed":"Fullf\xf8rt","paused":"Pauset","resumed":"Gjenopptatt","skipped":"Hoppet over"},"navigation":{"title":"Mollie Abonnementer"},"TYPE_DAYS":"Dag(er)","TYPE_WEEKS":"Uke(r)","TYPE_MONTHS":"M\xe5ned(er)","confirm":{"cancelTitle":"Avslutt abonnement?","cancel":"Kanseller kundens abonnementet.","pauseTitle":"Pause abonnement?","pause":"Sett abonnementet p\xe5 pause til du gjenopptar det igjen.","resumeTitle":"Gjenoppta abonnement?","resume":"Fortsett abonnementet igjen.","skipTitle":"Hopp over neste avbetaling?","skip":"Hopp over neste avbetaling i abonnementet. Det fortsetter automatisk etterp\xe5."},"alerts":{"cancelSuccess":"Abonnementet har blitt kansellert","pauseSuccess":"Abonnementet har blitt pauset","resumeSuccess":"Abonnementet har blitt gjenopptatt","skipSuccess":"Abonnementet har blitt hoppet over. Neste betaling er oppdatert."},"list":{"title":"Mollie Abonnementer","columns":{"customer":"Kunde","status":"Status","description":"Beskrivelse","amount":"Bel\xf8p","nextPaymentAt":"Neste betaling","prePaymentReminder":"P\xe5minnet ved","canceledAt":"Kansellert ved","createdAt":"Opprettet ved"},"action":{"edit":"Rediger abonnement"},"deletedCustomer":"Slettet kunde"},"detail":{"title":"Mollie-abonnement","buttonCancelSubscription":"Kanseller abonnement","labelDescription":"Beskrivelse","labelAmount":"Bel\xf8p","labelQuantity":"Antall","labelMollieSubscription":"Mollie-abonnement","labelMollieCustomer":"Mollie-kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware-kunde","labelCreatedAt":"Opprettet ved","buttonShowShopwareOrder":"Vis Shopware-bestilling","buttonShowShopwareCustomer":"Vis Shopware-kunde","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Neste betaling den","labelLastRemindedAt":"Sist p\xe5minnet den","labelCanceledAt":"Kansellert den","buttonPauseSubscription":"Sett abonnement p\xe5 pause","buttonResumeSubscription":"Gjenoppta abonnement","buttonSkipSubscription":"Hopp over abonnement","history":{"cardTitle":"Historikk","colDate":"Dato","colComment":"Kommentar","colStatusFrom":"Status (fra)","colStatusTo":"Status (til)","colMollieSubscription":"Mollie-abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie-abonnementer","description":"H\xe5ndtering av gjentakende betalinger er enklere enn noen gang med v\xe5re praktiske funksjoner. Ta bedriften din til neste niv\xe5 med effektive sporingsalternativer, enkle integrasjoner og mer. Med Mollie-abonnementer kan du enkelt opprette abonnementsprodukter og planlegge gjentakende betalinger som skjer p\xe5 det konfigurerte intervallet og perioden.","mollieSubscriptionProduct":"Abonnementsprodukt","mollieSubscriptionIntervalAmount":"Gjenta betaling hver","mollieSubscriptionIntervalType":"Intervalenhet","mollieSubscriptionRepetitionAmount":"Antall repetisjoner","mollieSubscriptionRepetitionPlaceholder":"Oppgi antall eller la det st\xe5 tomt","infoDefaultLanguage":"Vennligst v\xe6r oppmerksom p\xe5 at denne konfigurasjonen kun kan redigeres p\xe5 ditt standardspr\xe5k. Vennligst endre spr\xe5ket ditt for \xe5 endre abonnementsinnstillingene for dette produktet.","btnReadMore":"Les mer"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kredittkortdata","buttonMolliePaymentLink":"Kopier til utklippstavlen","columnRefunded":"Refundert","columnShipped":"Fraktet","columnCanceled":"Kansellert","labelMollieOrderId":"Mollie Bestillings-ID","labelMollieThirdPartyPaymentId":"Betalingsreferanse","labelMolliePaymentLink":"Mollie Checkout-URL","totalRefunds":"Refundert bel\xf8p","totalRefundsPending":"Venter p\xe5 \xe5 bli refundert","totalRemaining":"Refunderbart bel\xf8p","totalVouchers":"Kupongbel\xf8p","totalShipments":"Fraktet bel\xf8p ({quantity} varer)","subscriptionBadge":"Abonnementsbestilling","refundManager":{"title":"Mollie Refusjonsansvarlig","btnOpenRefundManager":"\xc5pne refusjonsansvarlig","btnCloseRefundManager":"Lukk refusjonsansvarlig"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Foretrukket iDeal-leverand\xf8r"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refusjonsansvarlig"},"mollie_subscription":{"label":"Abonnementer"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Beskrivelse"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Refusjon","subscription":"Abonnement","webhookReceived":"Webhooks","status":"Status","started":"Startet","ended":"Avsluttet","paused":"Pauset","renewalReminder":"P\xe5minnelse om fornyelse","renewed":"Fornyet","resumed":"Gjenopptatt","skipped":"Hoppet over","all":"Alle","canceled":"Kansellert","expired":"Utl\xf8pt","partiallyRefunded":"Refundert (delvis)","orderSuccess":"Bestilling vellykket","orderFailed":"Bestilling mislyktes","orderCanceled":"Bestilling kansellert"}}}'),eQ=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Subscription | Mollie Subscriptions"},"businessEvents":{"mollie_checkout_order_success":" Zam\xf3wienie zrealizowane","mollie_checkout_order_failed":" Zam\xf3wienie nieudane","mollie_checkout_order_canceled":" Zam\xf3wienie anulowane","mollie_webhook_received_All":" Otrzymano webhooki Mollie (wszystkie)","mollie_webhook_received_status_authorized":" Otrzymano webhook Mollie (Autoryzowany)","mollie_webhook_received_status_failed":" Otrzymano webhook Mollie (Nieudany)","mollie_webhook_received_status_canceled":" Otrzymano webhook Mollie (Anulowany)","mollie_webhook_received_status_expired":" Otrzymano webhook Mollie (Wygasły)","mollie_webhook_received_status_pending":" Otrzymano webhook Mollie (Oczekiwanie na płatność)","mollie_webhook_received_status_paid":" Otrzymano webhook Mollie (Płatność zrealizowana)","mollie_webhook_received_status_completed":" Otrzymano webhook Mollie (Zakończony)","mollie_webhook_received_status_refunded":" Otrzymano webhook Mollie (Zwr\xf3cony)","mollie_webhook_received_status_partially_refunded":" Otrzymano webhook Mollie (Częściowo zwr\xf3cony)","mollie_refund_started":" Rozpoczęto zwrot Mollie","mollie_subscription_started":" Rozpoczęto subskrypcję Mollie","mollie_subscription_ended":" Ukończono subskrypcję Mollie","mollie_subscription_cancelled":" Anulowano subskrypcję Mollie","mollie_subscription_paused":" Wstrzymano subskrypcję Mollie","mollie_subscription_resumed":" Wznowiono subskrypcję Mollie","mollie_subscription_skipped":" Pominięto subskrypcję Mollie","mollie_subscription_renewed":" Odnowiono subskrypcję Mollie","mollie_subscription_renewal_reminder":" Przypomnienie Mollie o odnowieniu subskrypcji"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Moduł Mollie","searchPlaceholder":"Szukaj subskrypcji...","general":{"mainMenuItemGeneral":"Płatności Mollie","descriptionTextModule":"Płatności Mollie","btnMollieActions":"Mollie Actions","refundThroughMollie":"Zwr\xf3ć poprzez Mollie","shipThroughMollie":"Wyślij poprzez Mollie","cancelMollieItem":"Anuluj poprzez Mollie"},"config":{"info":{"title":"Cześć {userName}, Witaj w Mollie!","descriptionTop":"Onboarding jest łatwy z Mollie!","descriptionBottom":"To wszystko!","descriptionFooter":"Jeśli chcesz dowiedzieć się więcej o naszej wtyczce, odwiedź naszą oficjalną stronę z dokumentacją.","onboardingStep1":"Zarejestruj się w Mollie.","onboardingStep2":"Wprowadź swoje klucze API w sekcji poniżej.","onboardingStep2TestMode":"Włącz \'Tryb testowy\', jeśli chcesz tylko testować płatności.","onboardingStep3":"Przypisz metody płatności do Twojego kanału sprzedaży.","onboardingStep3Link":"do Twoich kanał\xf3w sprzedaży","btnDocumentation":"Dokumentacja","btnRequestSupport":"Wsparcie","btnTroubleshooting":"Przewodnik rozwiązywania problem\xf3w"},"api":{"apiLinkButton":"Pozyskaj swoje klucze API z zakładki Mollie Dashboard","testButton":"Testowe Klucze API","testApiKeys":{"title":"Płatności Mollie","apiKey":"Klucz API","isValid":"jest ważny","isInvalid":"jest nieważny"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Podgląd"},"updatePaymentMethods":{"title":"Płatności Mollie","button":"Aktualizuj metody płatności","succeeded":"Metody płatności zostały pomyślnie zaktualizowane.","failed":"Nie udało się zaktualizować metod płatności."},"mollieLimits":{"link":"Pokaż zasady dostępności Mollie dla metod płatności"}},"rounding":{"info1":"Shopware może korzystać z ustawień waluty, aby obliczyć zaokrąglenie całkowitej kwoty zam\xf3wienia. Obejmuje to liczbę miejsc po przecinku w cenach produkt\xf3w oraz najbliższy interwał zaokrąglenia, na przykład 0,50 lub 1,00.","info2":"Te ustawienia mogą prowadzić do sytuacji, w kt\xf3rej całkowita kwota zam\xf3wienia r\xf3żni się od sumy pozycji na fakturze. Mogą występować błędy podczas realizacji płatności z powodu niezgodności kwot wykrytej podczas kontroli Mollie.","info3":"Możesz użyć tej funkcji, aby uniknąć problem\xf3w z zaokrąglaniem w procesie realizacji zam\xf3wienia. Po jej włączeniu, w Twoim panelu Mollie pojawi się oddzielna pozycja dla r\xf3żnicy wynikającej z zaokrąglenia, a klienci zapłacą całkowitą kwotę obliczoną przez Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nie jest możliwe użycie Klarna: Zapłać za 30 dni jako metody płatności, gdy data ważności zam\xf3wienia jest dłuższa niż 28 dni, chyba, że inny maksymalny okres zostanie uzgodniony między sprzedawcą a Klarna.","bankTransferDueDateLimitReached":"Nie można ustawić okresu aktywności zam\xf3wienia na więcej niż 100 dni."},"support":{"modalTitle":"Poproś o pomoc od Mollie","btnCancel":"Anuluj","btnConfirm":"Poproś o pomoc","btnSupport":"Więcej o naszym centrum pomocy","form":{"name":"Imię","email":"Tw\xf3j e-mail","recipient":"Wyślij wniosek do","subject":"Temat","message":"Wiadomość"},"data":{"header":"Dane wysłane do Mollie:","other":"Inne:","shopwareVersion":"Wersja Shopware","pluginLogs":"{plugin} pliki logu","pluginConfiguration":"{plugin} konfiguracja","pluginConfigurationHelpText":"Klucze API nie są uwzględnione.","paymentMethods":"Dane metody płatności","paymentMethodsHelpText":"Zawiera informacje o tym, kt\xf3re metody płatności są aktywne, przypisane do poszczeg\xf3lnych kanał\xf3w sprzedaży, a także o ich statusie na Twoim koncie Mollie."},"success":"Prośba o pomoc została pomyślnie wysłana. Dokładamy wszelkich starań, aby odpowiedzieć tak szybko, jak to możliwe","error":"Wystąpił problem przy wysyłaniu maila przez Shopware. Proszę spr\xf3bować ponownie lub skontaktować się z nami bezpośrednio przez e-mail."}},"rules":{"itemSubscriptionRule":"Przedmiot to subskrypcja (Mollie)","cartSubscriptionRule":"Koszyk z subskrypcjami (Mollie)"},"refunds":{"status":{"queued":"W kolejce","pending":"Oczekujące","processing":"Przetwarzanie","refunded":"Zwr\xf3cony","failed":"Nieudany","description":{"queued":"Zwrot jest oczekujący do czasu, gdy saldo będzie wystarczające na jego realizację. Wciąż możliwe jest anulowanie zwrotu.","pending":"Zwrot zostanie wysłany do banku w następny dzień roboczy. Wciąż możliwe jest anulowanie zwrotu.","processing":"Zwrot został wysłany do banku. Kwota zwrotu zostanie przelana na konto konsumenta tak szybko, jak to możliwe.","refunded":"Kwota zwrotu została przelana na konto konsumenta.","failed":"Nie udało się przetworzyć zwrotu. Powodem może być zamknięcie konta bankowego przez klienta. Środki zostaną zwr\xf3cone na Twoje konto."}}},"refund-manager":{"general":{"unitQuantity":"szt."},"acl":{"warningCreate":"Nie masz uprawnień do tworzenia zwrot\xf3w","warningCancel":"Nie masz uprawnień do anulowania zwrot\xf3w"},"cart":{"title":"Zam\xf3wienie ##orderNumber##","btnSelectAll":"Zaznacz wszystko","btnResetForm":"Zresetuj formularz","linkHowTo":"Jak korzystać z tego formularza?","grid":{"columns":{"item":"Pozycja","productNumber":"Numer produktu","unitPrice":"Cena jednostkowa","quantity":"Ilość","refunded":"Zwr\xf3cony","refundQuantity":"Zwrot","totalPrice":"Łącznie","refundAmount":"Zwrot","resetStock":"Zresetuj stan magazynowy"},"btnResetLine":"Zresetuj linię","checkDeductPromotion":"Odlicz promocję","checkRefundTax":"Zwr\xf3ć VAT"},"roundDiffItemAdded":"Dodano automatyczny element zaokrąglający"},"instructions":{"linkResetTutorials":"Zresetuj samouczki","btnToggleTutorial":"Pokaż/Ukryj samouczek","titleFullRefund":"Pełny zwrot","textFullRefund":"Po prostu użyj przycisku do pełnego zwrotu. Dzięki temu wszystkie przedmioty zostaną oznaczone jako zwr\xf3cone, a pełna kwota zostanie zwr\xf3cona klientowi.","titleStockReset":"Reset stanu magazynowego","textStockReset":"Możesz automatycznie zwiększyć dostępny stan magazynowy, wpisując ilość, kt\xf3rą chcesz z powrotem umieścić w magazynie. Wprowadź ją przed przystąpieniem do pełnego lub częściowego zwrotu. Reset stanu magazynowego można elastycznie łączyć z procesem zwrotu.","titleShipping":"Wysyłka","textShipping":"Koszty wysyłki mogą zostać zwr\xf3cone jak każdy inny produkt. Wprowadź pełną lub częściową kwotę i przejdź do zwrotu. Zwrot koszt\xf3w wysyłki można elastycznie łączyć z procesem zwrotu produkt\xf3w.","titlePartialAmount":"Zwrot częściowy (tylko kwota)","textPartialAmount":"Po prostu wprowadź kwotę częściową w polu tekstowym i rozpocznij zwrot.","titlePartialItems":"Zwrot częściowy (z produktami)","textPartialItems":"Jeśli chcesz oznaczyć ilości i produkty jako zwr\xf3cone w Mollie, skorzystaj z powyższego formularza. Ustaw odpowiednią liczbę i podaj niestandardową kwotę dla każdego przedmiotu, kt\xf3ry ma zostać zwr\xf3cony. Całkowita kwota zostanie wyświetlona w polu tekstowym z końcową kwotą zwrotu. Pamiętaj, że nadal możesz dostosować tę kwotę przed rozpoczęciem zwrotu.","titlePartialPromotions":"Zwrot częściowy (z promocjami)","textPartialPromotions":"Jeśli masz promocję w swoim koszyku, będzie ona oddzielnym elementem w zam\xf3wieniu. Jeśli chcesz zwr\xf3cić wszystkie przedmioty objęte rabatem, wykonaj zwrot pełnej wartości tych przedmiot\xf3w oraz pełnej kwoty rabatu. Jeśli chcesz zwr\xf3cić tylko niekt\xf3re przedmioty objęte rabatem, możesz automatycznie odjąć zastosowany rabat od każdej pozycji. Zawsze możesz dostosować te wartości, jeśli będą one nieprawidłowe.","titleRoundingDiff":"R\xf3żnica zaokrąglenia","textRoundingDiff":"Całkowity zwrot będzie zawierał r\xf3żnicę zaokrąglenia"},"summary":{"dataLoading":"Dane są ładowane...","headerExcludingVat":"Netto","headerIncludingVat":"Brutto","captionTotal":"Łącznie","captionTotalTaxFree":"Łącznie","captionPendingRefunds":"Oczekuje na zwrot","captionVouchers":"Kwota vouchera","captionRefunded":"Zwr\xf3cona kwota","captionRemaining":"Kwota do zwrotu","btnFixDiff":"Napraw r\xf3żnicę","placeholderDescription":"Wprowadź opis transakcji bankowej dla konsumenta. Maks. 140 znak\xf3w","lblDescription":"Opis (opcjonalnie) ({characters}/140 znak\xf3w)","descriptionHelp":"Ta informacja będzie wyświetlona na wyciągu bankowym lub wyciągu z karty konsumenta, jeśli będzie to możliwe. Wiadomość zostanie obcięta po 140 znakach.","placeholderInternalDescription":"Wprowadź opis","lblInternalDescription":"Opis wewnętrzny (opcjonalnie)","internalDescriptionHelp":"Ten tekst zostanie wyświetlony jako lokalny opis w interfejsie administracyjnym.","checkVerification":"Zweryfikowałem całkowitą kwotę zwrotu oraz ilości do zwrotu i ponownego umieszczenia w magazynie.","btnRefund":"Zwrot","btnFullRefund":"Całkowity zwrot","roundDiffItemAdded":"Element zaokrąglający"},"refunds":{"title":"Zwroty w zakładce Mollie Dashboard","linkMore":"Więcej o zwrotach","grid":{"columns":{"amount":"Kwota","status":"Status","description":"Opis","internalDescription":"Opis wewnętrzny","composition":"Kompozycja","date":"Data"},"lblNoComposition":"Brak dostępnej kompozycji","btnCancelRefund":"Anuluj ten zwrot"}},"notifications":{"success":{"refund-created":"Zwrot został utworzony w Mollie. Sfinalizowanie zwrotu może zająć do 2 godzin. Do tego czasu możesz anulować zwrot.","refund-canceled":"Oczekujący zwrot został pomyślnie anulowany i usunięty."},"error":{"low-amount":"Proszę wprowadzić kwotę do zwrotu.","refund-created":"Coś poszło nie tak podczas tworzenia zwrotu.","refund-canceled":"Wystąpił problem podczas anulowania oczekującego zwrotu. Proszę spr\xf3bować ponownie w zakładce Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Płatności poprzez voucher","VOUCHER_INFO_DESCRIPTION":"Mollie pozwala łatwo akceptować płatności w Twoim sklepie internetowym za pomocą voucher\xf3w ekologicznych, prezentowych i posiłkowych — to mądry wyb\xf3r, aby zwiększyć sprzedaż i zadowolić klient\xf3w. Metoda płatności \\"voucher\\" jest widoczna tylko w przypadku, gdy w koszyku znajduje się co najmniej 1 produkt z przypisanym typem vouchera.","VOUCHER_INFO_DEFAULTLANGUAGE":"Proszę pamiętać, że ta konfiguracja może być edytowana tylko w domyślnym języku. Zmień język, aby zmodyfikować typ vouchera dla tego produktu.","VOUCHER_BTN_READMORE":"Czytaj więcej","VOUCHER_TYPE_CAPTION":"Typ vouchera","VOUCHER_TYPE_VALUE_NONE":"Brak","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Posiłek","VOUCHER_TYPE_VALUE_VOUCHER":"Prezent"},"modals":{"shipping":{"title":"Wyślij przez Mollie","item":{"label":"Pozycja:","noQuantity":"Proszę wprowadzić ilość do wysłania.","shipAll":"Wyślij wszystko","summary":{"quantity":"Ilość do wysłania","shipped":"Ilość wysłana","shippable":"Ilość do wysłania"},"success":"Zam\xf3wienie zostało pomyślnie wysłane."},"order":{"description":"Następujące ilości przedmiot\xf3w zostaną wysłane.","itemHeader":"Pozycja","quantityHeader":"Ilość","originalQuantityHeader":"Ilość (do wysłania)"},"availableTracking":{"label":"Dostępne kody śledzenia","hint":"Kliknij jeden z tych kod\xf3w, aby automatycznie uzupełnić wszystkie dane."},"showTracking":"Dodaj informacje o śledzeniu dla tej przesyłki","tracking":{"carrier":"Przewoźnik","code":"Kod","url":"Url","invalid":"Proszę wprowadzić zar\xf3wno przewoźnika, jak i kod"},"confirmButton":"Wyślij zam\xf3wienie","cancelButton":"Anuluj","selectAllButton":"Wybierz wszystko","resetButton":"Zresetuj"},"cancel":{"title":"Anuluj pozycję poprzez Mollie","confirmButton":"Anuluj pozycję poprzez Mollie","cancelButton":"Zamknij modal","resetStock":"Zresetuj stany magazynowe","item":{"success":"Produkt został pomyślnie anulowany","failed":{"quantityZero":"Ilość wynosi 0","invalidLine":"Nie odnaleziono produktu w zam\xf3wieniu","quantityTooHigh":"Zbyt duża ilość"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Wyślij zam\xf3wienie (Mollie)","description":"Wyślij zam\xf3wienie przez Mollie."},"modal":{"title":"Wyślij zam\xf3wienie","description":"To działanie automatycznie zrealizuje wysyłkę zam\xf3wienia przez Mollie. Sekwencja przepływu odbierze numer zam\xf3wienia i przekaże go do API Mollie. Zar\xf3wno zakończone pomyślnie, jak i nieudane wysyłki będą widoczne w plikach dziennika Mollie.","warningConfig":"Upewnij się, że wszelkie dodatkowe automatyzacje dla tego typu działania zostały wyłączone, aby uniknąć jakichkolwiek zakł\xf3ceń.\\nNastępujące aktywowane funkcje wtyczki mogą zakł\xf3cać to działanie:","noWarnings":"Brak ostrzeżeń"}},"refundOrder":{"editor":{"title":"Zwr\xf3ć zam\xf3wienie (Mollie)","description":"Zwr\xf3ć zam\xf3wienie poprzez Mollie."},"modal":{"title":"Zwr\xf3ć zam\xf3wienie","description":"To działanie automatycznie rozpocznie proces zwrotu za pośrednictwem Mollie. Sekwencja przepływu odbierze numer zam\xf3wienia i przekaże go do API Mollie. Zar\xf3wno zakończone pomyślnie, jak i nieudane zwroty będą widoczne w plikach dziennika Mollie.","warning":"Proszę pamiętać, że proces finalizacji zwrot\xf3w może zająć do 2 godzin, zanim będą one widoczne w sklepie. Do tego czasu możliwe jest anulowanie oczekującego zwrotu, korzystając z widoku zam\xf3wienia w Shopware lub z poziomu Mollie Dashboard.","warningConfig":"Upewnij się, że wszelkie dodatkowe automatyzacje dla tego typu działania zostały wyłączone, aby uniknąć jakichkolwiek zakł\xf3ceń."}},"warnings":{"automaticShipping":"Automatyczna wysyłka w konfiguracji wtyczki"}}},"subscriptions":{"status":{"pending":"Oczekujący","active":"Aktywny","canceled":"Anulowany","suspended":"Wstrzymany","completed":"Zakończony","paused":"Wstrzymany","resumed":"Wznowiony","skipped":"Pominięty"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Dzień (dni)","TYPE_WEEKS":"Tydzień (tygodnie)","TYPE_MONTHS":"Miesiąc (miesiące)","confirm":{"cancelTitle":"Zakończyć subskrypcję?","cancel":"Anuluj subskrypcję swojego klienta.","pauseTitle":"Wstrzymaj subskrypcję?","pause":"Wstrzymaj subskrypcję do czasu jej wznowienia.","resumeTitle":"Wzn\xf3w subskrypcję?","resume":"Wzn\xf3w subskrypcję ponownie.","skipTitle":"Pominąć następną ratę?","skip":"Pomiń następną ratę w subskrypcji. Subskrypcja będzie automatycznie kontynuowana po tym okresie."},"alerts":{"cancelSuccess":"Subskrypcja została pomyślnie anulowana","pauseSuccess":"Subskrypcja została pomyślnie wstrzymana","resumeSuccess":"Subskrypcja została pomyślnie wznowiona","skipSuccess":"Subskrypcja została pomyślnie pominięta. Zaktualizowano kolejną płatność."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Klient","status":"Status","description":"Opis","amount":"Kwota","nextPaymentAt":"Następna płatność","prePaymentReminder":"Przypomniano o","canceledAt":"Anulowano o","createdAt":"Utworzono"},"action":{"edit":"Edytuj subskrypcję"},"deletedCustomer":"Usunięty klient"},"detail":{"title":"Subskrypcja Mollie","buttonCancelSubscription":"Anuluj subskrypcję","labelDescription":"Opis","labelAmount":"Kwota","labelQuantity":"Ilość","labelMollieSubscription":"Subskrypcja Mollie","labelMollieCustomer":"Klient Mollie","labelMandateId":"Mandat","labelShopwareCustomer":"Klient Shopware","labelCreatedAt":"Utworzono","buttonShowShopwareOrder":"Pokaż zam\xf3wienie Shopware","buttonShowShopwareCustomer":"Pokaż klienta Shopware","cardTitleSubscription":"Subskrypcja","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Następna płatność w","labelLastRemindedAt":"Ostatnie przypomnienie w","labelCanceledAt":"Anulowano","buttonPauseSubscription":"Wstrzymaj subskrypcję","buttonResumeSubscription":"Wzn\xf3w subskrypcję","buttonSkipSubscription":"Pomiń subskrypcję","history":{"cardTitle":"Historia","colDate":"Data","colComment":"Komentarz","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Subskrypcja Mollie"}},"product":{"card-title":"Subskrypcja","title":"Subskrypcje Mollie","description":"Zarządzanie płatnościami cyklicznymi nigdy nie było prostsze dzięki naszym pomocnym funkcjom. Dzięki Mollie możesz łatwo tworzyć produkty subskrypcyjne i ustawiać cykliczne płatności w zaplanowanych odstępach czasowych. Nasze narzędzia umożliwiają efektywne śledzenie, prostą integrację oraz inne funkcje, kt\xf3re pozwolą Ci przenieść Tw\xf3j biznes na wyższy poziom.","mollieSubscriptionProduct":"Produkt subskrypcyjny","mollieSubscriptionIntervalAmount":"Powtarzaj płatność co","mollieSubscriptionIntervalType":"Jednostka interwału","mollieSubscriptionRepetitionAmount":"Liczba powt\xf3rzeń","mollieSubscriptionRepetitionPlaceholder":"Wprowadź liczbę lub pozostaw puste","infoDefaultLanguage":"Proszę pamiętać, że ta konfiguracja może być edytowana tylko w domyślnym języku. Zmień język, aby zmodyfikować ustawienia subskrypcji dla tego produktu.","btnReadMore":"Czytaj więcej"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Subskrypcja"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Dane karty kredytowej","buttonMolliePaymentLink":"Kopiuj do schowka","columnRefunded":"Zwr\xf3cony","columnShipped":"Wysłano","columnCanceled":"Anulowano","labelMollieOrderId":"ID zam\xf3wienia Mollie","labelMollieThirdPartyPaymentId":"Referencja płatności","labelMolliePaymentLink":"Link do Mollie Checkout","totalRefunds":"Zwr\xf3cona kwota","totalRefundsPending":"Oczekuje na zwrot","totalRemaining":"Kwota do zwrotu","totalVouchers":"Kwota vouchera","totalShipments":"Wysłana ilość ({quantity} przedmiot\xf3w)","subscriptionBadge":"Produkt subskrypcyjny","refundManager":{"title":"Mollie Menedżer Zwrot\xf3w","btnOpenRefundManager":"Otw\xf3rz Menedżera Zwrot\xf3w","btnCloseRefundManager":"Zamknij Menedżera Zwrot\xf3w"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Preferowany emitent iDeal"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Menedżer Zwrot\xf3w"},"mollie_subscription":{"label":"Subskrypcje"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Opis"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Zwrot","subscription":"Subskrypcja","webhookReceived":"Webhooki","status":"Status","started":"Rozpoczęto","ended":"Zakończono","paused":"Wstrzymano","renewalReminder":"Przypomnienie o odnowieniu","renewed":"Odnowiony","resumed":"Wznowiony","skipped":"Pominięty","all":"Wszystko","canceled":"Anulowano","expired":"Wygasły","partiallyRefunded":"Zwr\xf3cono (częściowo)","orderSuccess":"Zam\xf3wienie zrealizowane","orderFailed":"Zam\xf3wienie nieudane","orderCanceled":"Zam\xf3wienie anulowane"}}}'),eZ=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Předplatn\xe9 | Mollie Předplatn\xe1"},"businessEvents":{"mollie_checkout_order_success":" Objedn\xe1vka byla \xfaspěšn\xe1","mollie_checkout_order_failed":" Objedn\xe1vka selhala","mollie_checkout_order_canceled":" Objedn\xe1vka byla zrušena","mollie_webhook_received_All":" Mollie Webhook Přijat (Vše)","mollie_webhook_received_status_authorized":" Mollie Webhook Přijat (Opr\xe1vněno)","mollie_webhook_received_status_failed":" Mollie Webhook Přijat (Selhalo)","mollie_webhook_received_status_canceled":" Mollie Webhook Přijat (Zrušeno)","mollie_webhook_received_status_expired":" Mollie Webhook Přijat (Vypršelo)","mollie_webhook_received_status_pending":" Mollie Webhook Přijat (Čekaj\xedc\xed)","mollie_webhook_received_status_paid":" Mollie Webhook Přijat (Zaplaceno)","mollie_webhook_received_status_completed":" Mollie Webhook Přijat (Dokončeno)","mollie_webhook_received_status_refunded":" Mollie Webhook Přijat (Vr\xe1ceno)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Přijat (Č\xe1stečně vr\xe1ceno)","mollie_refund_started":" Mollie vr\xe1cen\xed peněz zah\xe1jeno","mollie_subscription_started":" Mollie předplatn\xe9 zah\xe1jeno","mollie_subscription_ended":" Mollie předplatn\xe9 dokončeno","mollie_subscription_cancelled":" Mollie předplatn\xe9 zrušeno","mollie_subscription_paused":" Mollie předplatn\xe9 pozastaveno","mollie_subscription_resumed":" Mollie předplatn\xe9 pokračuje","mollie_subscription_skipped":" Mollie předplatn\xe9 přeskočeno","mollie_subscription_renewed":" Mollie předplatn\xe9 obnoveno","mollie_subscription_renewal_reminder":" Mollie připom\xednka pro obnoven\xed předplatn\xe9ho"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Hledat předplatn\xe1...","general":{"mainMenuItemGeneral":"Mollie Platby","descriptionTextModule":"Mollie Platby","btnMollieActions":"Mollie Akce","refundThroughMollie":"Vr\xe1cen\xed peněz přes Mollie","shipThroughMollie":"Odeslat přes Mollie","cancelMollieItem":"Zrušit přes Mollie"},"config":{"info":{"title":"Ahoj {userName}, v\xedtejte v Mollie!","descriptionTop":"Onboarding je s Mollie snadn\xfd!","descriptionBottom":"To je vše!","descriptionFooter":"Pokud se chcete dozvědět v\xedce o našem pluginu, navštivte pros\xedm naši ofici\xe1ln\xed str\xe1nku dokumentace.","onboardingStep1":"Zaregistrujte se do Mollie \xfačtu.","onboardingStep2":"Zadejte sv\xe9 API kl\xedče v sekci n\xedže.","onboardingStep2TestMode":"Povolte \'Testovac\xed režim\', pokud chcete platby pouze testovat.","onboardingStep3":"Přiřaďte způsoby platby k vašemu prodejn\xedmu kan\xe1lu.","onboardingStep3Link":"k vašim prodejn\xedm kan\xe1lům","btnDocumentation":"Dokumentace","btnRequestSupport":"Podpora","btnTroubleshooting":"Průvodce řešen\xedm probl\xe9mů"},"api":{"apiLinkButton":"Z\xedskejte sv\xe9 API kl\xedče z Mollie Dashboard","testButton":"Testovac\xed API kl\xedče","testApiKeys":{"title":"Mollie Platby","apiKey":"API kl\xedč","isValid":"je platn\xfd","isInvalid":"je neplatn\xfd"}},"payments":{"format":{"placeholder":"Z\xe1stupn\xfd symbol","preview":"N\xe1hled"},"updatePaymentMethods":{"title":"Mollie Platby","button":"Aktualizovat způsoby platby","succeeded":"Způsoby platby byly \xfaspěšně aktualizov\xe1ny.","failed":"Způsob platby se nepodařilo aktualizovat."},"mollieLimits":{"link":"Zobrazit pravidla př\xedstupnosti mollie pro platebn\xed metodz"}},"rounding":{"info1":"Shopware může využ\xedt nastaven\xed měny k v\xfdpočtu zaokrouhlen\xed celkov\xe9 č\xe1stky objedn\xe1vky. To zahrnuje počet desetinn\xfdch m\xedst v cen\xe1ch vašich produktů a nejbližš\xed interval zaokrouhlen\xed, např\xedklad 0,50 nebo 1,00.","info2":"Tato nastaven\xed mohou v\xe9st k jin\xe9mu celkov\xe9mu součtu než součet jednotliv\xfdch položek. Když Mollie zkontroluje tyto č\xe1stky a zjist\xed, že se neshoduj\xed, způsob\xed to chybu při pokladně.","info3":"Tuto funkci můžete použ\xedt k vyhnut\xed se probl\xe9mům se zaokrouhlov\xe1n\xedm při pokladně. Po jej\xedm aktivov\xe1n\xed se v přehledu Mollie přid\xe1 samostatn\xe1 položka pro rozd\xedl v zaokrouhlov\xe1n\xed a vaši z\xe1kazn\xedci zaplat\xed celkovou č\xe1stku vypoč\xedtanou Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Použit\xed Klarna Rozděl to nebo Klarna zaplať později nen\xed možn\xe9 pokud je datum vypršen\xed delš\xed než 28 dn\xed, za předpokladu, že mezi obchodn\xedkem a Klarna nen\xed dohodnuta jin\xe1 maxim\xe1ln\xed doba.","bankTransferDueDateLimitReached":"Nen\xed možn\xe9 nastavit dobu platnosti objedn\xe1vky na v\xedce než 100 dn\xed."},"support":{"modalTitle":"Pož\xe1dat o podporu od Mollie","btnCancel":"Zrušit","btnConfirm":"Pož\xe1dat o podporu","btnSupport":"V\xedce o naš\xed podpoře","form":{"name":"Vaše jm\xe9no","email":"V\xe1š e-mail","recipient":"Odeslat ž\xe1dost na","subject":"Předmět","message":"Zpr\xe1va"},"data":{"header":"Informace odeslan\xe9 Mollie:","other":"Ostatn\xed:","shopwareVersion":"Verze Shopware","pluginLogs":"{plugin} soubory protokolu","pluginConfiguration":"{plugin} konfigurace","pluginConfigurationHelpText":"API kl\xedče jsou vyloučeny.","paymentMethods":"\xdadaje o způsobu platby","paymentMethodsHelpText":"Obsahuje informace o tom, kter\xe9 platebn\xed metody jsou aktivn\xed, jejich přiřazen\xed k jednotliv\xfdm prodejn\xedm kan\xe1lům a jejich stav ve vašem \xfačtu Mollie."},"success":"Ž\xe1dost o podporu byla \xfaspěšně odesl\xe1na. Děl\xe1me vše pro to, abychom odpověděli co nejdř\xedve","error":"Došlo k probl\xe9mu při odes\xedl\xe1n\xed e-mailu přes Shopware. Pros\xedm zkuste to znovu nebo n\xe1s kontaktujte př\xedmo e-mailem."}},"rules":{"itemSubscriptionRule":"Položka je předplatn\xe9 (Mollie)","cartSubscriptionRule":"Koš\xedk s předplatn\xfdm (Mollie)"},"refunds":{"status":{"queued":"Ve frontě","pending":"Čekaj\xedc\xed","processing":"Zpracov\xe1v\xe1 se","refunded":"Vr\xe1ceno","failed":"Selhalo","description":{"queued":"Vr\xe1cen\xed platby je zařazeno do fronty, dokud nebude dostatečn\xfd zůstatek pro jeho zpracov\xe1n\xed. Vr\xe1cen\xed platby můžete st\xe1le zrušit.","pending":"Vr\xe1cen\xed platby bude odesl\xe1no bance n\xe1sleduj\xedc\xed pracovn\xed den. Vr\xe1cen\xed platby můžete st\xe1le zrušit","processing":"Vr\xe1cen\xe1 platba byla odesl\xe1na na banku. Vr\xe1cen\xe1 č\xe1stka bude na \xfačet z\xe1kazn\xedka převedena co nejdř\xedve.","refunded":"Vr\xe1cen\xe1 č\xe1stka byla převedena na \xfačet z\xe1kazn\xedka.","failed":"Vr\xe1cen\xed peněz se po zpracov\xe1n\xed nepodařilo, např\xedklad protože z\xe1kazn\xedk zavřel svůj bankovn\xed \xfačet. Prostředky budou vr\xe1ceny na v\xe1š \xfačet."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nem\xe1te opr\xe1vněn\xed k proveden\xed vr\xe1cen\xed peněz","warningCancel":"Nem\xe1te opr\xe1vněn\xed k zrušen\xed vr\xe1cen\xed peněz"},"cart":{"title":"Objedn\xe1vka ##orderNumber##","btnSelectAll":"Vybrat vše","btnResetForm":"Resetovat formul\xe1ř","linkHowTo":"Jak použ\xedvat tento formul\xe1ř?","grid":{"columns":{"item":"Položka","productNumber":"Č\xedslo produktu","unitPrice":"Jednotkov\xe1 cena","quantity":"Množstv\xed","refunded":"Vr\xe1ceno","refundQuantity":"Vr\xe1cen\xed peněz","totalPrice":"Celkov\xe1 č\xe1stka","refundAmount":"Vr\xe1cen\xed peněz","resetStock":"Resetovat z\xe1soby"},"btnResetLine":"Resetovat ř\xe1dek","checkDeductPromotion":"Odeč\xedst slevu","checkRefundTax":"Vr\xe1tit DPH"},"roundDiffItemAdded":"Automatick\xe9 zaokrouhlen\xed položky bylo přid\xe1no"},"instructions":{"linkResetTutorials":"Resetovat n\xe1vody","btnToggleTutorial":"Zobrazit/Skr\xfdt n\xe1vod","titleFullRefund":"\xdapln\xe9 vr\xe1cen\xed peněz","textFullRefund":"Stač\xed použ\xedt tlač\xedtko pro \xfapln\xe9 vr\xe1cen\xed peněz. T\xedm zajist\xedte, že všechny vaše položky jsou označeny jako vr\xe1cen\xe9 a cel\xe1 č\xe1stka je vr\xe1cena z\xe1kazn\xedkovi.","titleStockReset":"Resetov\xe1n\xed z\xe1sob","textStockReset":"Můžete automaticky zv\xfdšit dostupn\xe9 z\xe1soby zad\xe1n\xedm množstv\xed, kter\xe9 chcete vr\xe1tit zpět do z\xe1sob. Toto množstv\xed zadejte před proveden\xedm \xfapln\xe9ho nebo č\xe1stečn\xe9ho vr\xe1cen\xed platby. Obnoven\xed z\xe1sob můžete flexibilně spojit s procesem vr\xe1cen\xed platby.","titleShipping":"Doprava","textShipping":"Poštovn\xe9 lze vr\xe1tit stejně jako jak\xe9koli jin\xe9 produktov\xe9 položky. Zadejte celou nebo požadovanou č\xe1stku a pokračujte ve vr\xe1cen\xed platby. Vr\xe1cen\xed n\xe1kladů na poštovn\xe9 lze flexibilně spojit s vr\xe1cen\xedm platby za položky.","titlePartialAmount":"Č\xe1stečn\xe9 vr\xe1cen\xed peněz (pouze č\xe1stka)","textPartialAmount":"Jednoduše zadejte požadovanou č\xe1stku do textov\xe9ho pole a zahajte vr\xe1cen\xed peněz.","titlePartialItems":"Č\xe1stečn\xe9 vr\xe1cen\xed peněz (s položkami)","textPartialItems":"Pokud chcete označit množstv\xed a položky jako vr\xe1cen\xe9 v Mollie, použijte formul\xe1ř v\xfdše. Nastavte množstv\xed a zadejte vlastn\xed č\xe1stku pro každou položku, kter\xe1 bude vr\xe1cena. Celkov\xe1 č\xe1stka se n\xe1sledně zobraz\xed v textov\xe9m poli pro konečnou č\xe1stku vr\xe1cen\xed. Nezapomeňte, že tuto konečnou č\xe1stku je st\xe1le možn\xe9 upravit před zah\xe1jen\xedm vr\xe1cen\xed platby.","titlePartialPromotions":"Č\xe1stečn\xe9 vr\xe1cen\xed peněz (včetně slev)","textPartialPromotions":"Pokud m\xe1te v koš\xedku položku se slevou, bude tato sleva zobrazena jako samostatn\xe1 položka. Pokud chcete vr\xe1tit všechny položky se slevou, vraťte jejich celkov\xe9 hodnoty a celou položku se slevou. Pokud chcete vr\xe1tit pouze někter\xe9 položky se slevou, můžete automaticky odeč\xedst slevu u každ\xe9 jednotliv\xe9 položky. Samozřejmě nespr\xe1vn\xe9 hodnoty můžete vždy upravit.","titleRoundingDiff":"Rozd\xedl zaokroulen\xed","textRoundingDiff":"\xdapln\xe9 vr\xe1cen\xed peněz zahrne rozd\xedly v zaokroulen\xed"},"summary":{"dataLoading":"Data se nač\xedtaj\xed...","headerExcludingVat":"Bez DPH","headerIncludingVat":"S DPH","captionTotal":"Celkem","captionTotalTaxFree":"Celkem","captionPendingRefunds":"Ček\xe1 na vr\xe1cen\xed peněz","captionVouchers":"Č\xe1stka poukazu","captionRefunded":"Vr\xe1cen\xe1 č\xe1stka","captionRemaining":"Vr\xe1titeln\xe1 č\xe1stka","btnFixDiff":"Opravit rozd\xedl","placeholderDescription":"Zadejte popis pro v\xfdpis z banky/karty pro z\xe1kazn\xedka. Max. 140 znaků","lblDescription":"Popis (voliteln\xe9) ({characters}/140 znaků)","descriptionHelp":"Toto bude zobrazeno na v\xfdpisu z banky nebo karty z\xe1kazn\xedka, pokud to bude možn\xe9. Zpr\xe1va bude zkr\xe1cena po 140 znac\xedch.","placeholderInternalDescription":"Zadejte popis pro intern\xed použit\xed","lblInternalDescription":"Intern\xed popis (voliteln\xe9)","internalDescriptionHelp":"Toto bude zobrazeno jako m\xedstn\xed popis v administr\xe1torsk\xe9m rozhran\xed.","checkVerification":"Ověřil(a) jsem celkovou č\xe1stku vr\xe1cen\xed platby a nastaven\xe9 množstv\xed pro vr\xe1cen\xed a opětovn\xe9 naskladněn\xed.","btnRefund":"Vr\xe1tit","btnFullRefund":"\xdapln\xe9 vr\xe1cen\xed","roundDiffItemAdded":"Položka zaokroulen\xed"},"refunds":{"title":"Vr\xe1cen\xed peněz v Mollie Dashboard","linkMore":"V\xedce o vr\xe1cen\xed peněz","grid":{"columns":{"amount":"Č\xe1stka","status":"Status","description":"Popis","internalDescription":"Intern\xed popis","composition":"Složen\xed","date":"Datum"},"lblNoComposition":"Ž\xe1dn\xe9 dostupn\xe9 složen\xed","btnCancelRefund":"Zrušit toto vr\xe1cen\xed peněz"}},"notifications":{"success":{"refund-created":"Vr\xe1cen\xed platby bylo vytvořeno v Mollie. Může trvat až 2 hodiny, než bude vr\xe1cen\xed platby dokončeno. Během t\xe9to doby můžete vr\xe1cen\xed platby zrušit.","refund-canceled":"Prob\xedhaj\xedc\xed vr\xe1cen\xed platby bylo \xfaspěšně zrušeno a odstraněno."},"error":{"low-amount":"Pros\xedm zadejte č\xe1stku, kter\xe1 m\xe1 b\xfdt vr\xe1cena.","refund-created":"Při vytv\xe1řen\xed vr\xe1cen\xed platby došlo k chybě.","refund-canceled":"Při zrušen\xed prob\xedhaj\xedc\xedho vr\xe1cen\xed platby došlo k probl\xe9mu. Pros\xedm, zkuste to znovu v Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Poukaz","VOUCHER_INFO_TITLE":"Platby poukazy","VOUCHER_INFO_DESCRIPTION":"Mollie v\xe1m umožňuje snadno přij\xedmat platby ve vašem online obchodě pomoc\xed Eco-, d\xe1rkov\xfdch a stravenkov\xfdch poukazů – chytr\xfd způsob, jak zv\xfdšit prodeje a uspokojit vaše z\xe1kazn\xedky. Platebn\xed metoda \'poukaz\' je viditeln\xe1 pouze v př\xedpadě, že m\xe1te v koš\xedku alespoň 1 produkt s přiřazen\xfdm typem poukazu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vezměte pros\xedm na vědom\xed, že tuto konfiguraci lze upravit pouze v nastaven\xe9m v\xfdchoz\xedm jazyce. Změňte pros\xedm jazyk, abyste mohli upravit typ poukazu u tohoto produktu.","VOUCHER_BTN_READMORE":"Zjistit v\xedce","VOUCHER_TYPE_CAPTION":"Typ poukazu produktu","VOUCHER_TYPE_VALUE_NONE":"Ž\xe1dn\xfd","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Stravenky","VOUCHER_TYPE_VALUE_VOUCHER":"D\xe1rkov\xfd"},"modals":{"shipping":{"title":"Odeslat přes Mollie","item":{"label":"Položka:","noQuantity":"Pros\xedm zadejte množstv\xed k odesl\xe1n\xed.","shipAll":"Odeslat vše","summary":{"quantity":"Množstv\xed k odesl\xe1n\xed","shipped":"Odeslan\xe9 množstv\xed","shippable":"Množstv\xed, kter\xe9 lze odeslat"},"success":"Objedn\xe1vka byla \xfaspěšně odesl\xe1na."},"order":{"description":"N\xe1sleduj\xedc\xed množstv\xed položek bude odesl\xe1no.","itemHeader":"Položka","quantityHeader":"Množstv\xed","originalQuantityHeader":"Množstv\xed (k odesl\xe1n\xed)"},"availableTracking":{"label":"Dostupn\xe9 sledovac\xed k\xf3dy","hint":"Kliknut\xedm na jeden z těchto sledovac\xedch k\xf3dů se všechna data automaticky vypln\xed."},"showTracking":"Přidat informace o sledov\xe1n\xed pro tuto z\xe1silku","tracking":{"carrier":"Dopravce","code":"K\xf3d","url":"Url","invalid":"Pros\xedm zadejte Dopravce i K\xf3d"},"confirmButton":"Odeslat objedn\xe1vku","cancelButton":"Zrušit","selectAllButton":"Vybrat vše","resetButton":"Resetovat"},"cancel":{"title":"Zrušit položku prostřednictv\xedm Mollie","confirmButton":"Zrušit položku prostřednictv\xedm Mollie","cancelButton":"Zavř\xedt modal","resetStock":"Obnovit z\xe1soby","item":{"success":"Produkt byl \xfaspěšně zrušen","failed":{"quantityZero":"Množstv\xed je 0","invalidLine":"Produkt neexistuje v objedn\xe1vce","quantityTooHigh":"Množstv\xed je př\xedliš vysok\xe9"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Odeslat objedn\xe1vku (Mollie)","description":"Odeslat objedn\xe1vku v Mollie."},"modal":{"title":"Odeslat objedn\xe1vku","description":"Tato akce automaticky odešle objedn\xe1vku prostřednictv\xedm Mollie. Sekvence toku obdrž\xed č\xedslo objedn\xe1vky a před\xe1 jej do API Mollie. \xdaspěšn\xe9 a ne\xfaspěšn\xe9 z\xe1silky budou viditeln\xe9 v protokolech Mollie.","warningConfig":"Ujistěte se, že vypnete jakoukoli dalš\xed automatizaci pro tento typ akce, aby nedošlo k ž\xe1dn\xfdm rušen\xedm. N\xe1sleduj\xedc\xed aktivovan\xe9 funkce tohoto pluginu mohou s touto akc\xed kolidovat:","noWarnings":"Ž\xe1dn\xe1 upozorněn\xed"}},"refundOrder":{"editor":{"title":"Vr\xe1cen\xed peněz za objedn\xe1vku (Mollie)","description":"Vr\xe1cen\xed peněz za objedn\xe1vku skrze Mollie."},"modal":{"title":"Vr\xe1cen\xed peněz za objedn\xe1vku","description":"Tato akce automaticky spust\xed vr\xe1cen\xed platby prostřednictv\xedm Mollie. Sekvence toku obdrž\xed č\xedslo objedn\xe1vky a před\xe1 ho do Mollie API. \xdaspěšn\xe1 a ne\xfaspěšn\xe1 vr\xe1cen\xed platby budou viditeln\xe1 v protokolech Mollie.","warning":"Mějte pros\xedm na paměti, že vr\xe1cen\xed platby může trvat až 2 hodiny, než bude dokončeno a zobrazeno v obchodě. Během t\xe9to doby můžete vždy zrušit prob\xedhaj\xedc\xed vr\xe1cen\xed platby buď z objedn\xe1vky v Shopware, nebo z Mollie Dashboard.","warningConfig":"Pros\xedm ujistěte se, že jste vypnuli veškerou dalš\xed automatizaci pro tento typ akce, abyste předešli možn\xfdm probl\xe9mům."}},"warnings":{"automaticShipping":"Automatick\xe9 odes\xedl\xe1n\xed v konfiguraci pluginu"}}},"subscriptions":{"status":{"pending":"Čekaj\xedc\xed","active":"Aktivn\xed","canceled":"Zrušeno","suspended":"Pozastaveno","completed":"Dokončeno","paused":"Pozastaveno","resumed":"Obnoveno","skipped":"Přeskočeno"},"navigation":{"title":"Mollie Předplatn\xe1"},"TYPE_DAYS":"Den (dny)","TYPE_WEEKS":"T\xfdden(y)","TYPE_MONTHS":"Měs\xedc(e)","confirm":{"cancelTitle":"Zrušit předplatn\xe9?","cancel":"Zrušit předplatn\xe9 vašeho z\xe1kazn\xedka.","pauseTitle":"Pozastavit předplatn\xe9?","pause":"Pozastavit předplatn\xe9, dokud jej znovu neobnov\xedte.","resumeTitle":"Obnovit předplatn\xe9?","resume":"Pokračovat znovu v předplatn\xe9m.","skipTitle":"Přeskočit př\xedšt\xed spl\xe1tku?","skip":"Přeskočte př\xedšt\xed spl\xe1tku v předplatn\xe9m. Pot\xe9 bude pokračovat automaticky."},"alerts":{"cancelSuccess":"Předplatn\xe9 bylo \xfaspěšně zrušeno","pauseSuccess":"Předplatn\xe9 bylo \xfaspěšně pozastaveno","resumeSuccess":"Předplatn\xe9 bylo \xfaspěšně obnoveno","skipSuccess":"Předplatn\xe9 bylo \xfaspěšně přeskočeno. N\xe1sleduj\xedc\xed platba byla aktualizov\xe1na."},"list":{"title":"Mollie Předplatn\xe1","columns":{"customer":"Z\xe1kazn\xedk","status":"Status","description":"Popis","amount":"Č\xe1stka","nextPaymentAt":"Dalš\xed platba","prePaymentReminder":"Připomenuto k","canceledAt":"Zrušeno k","createdAt":"Vytvořeno k"},"action":{"edit":"Upravit předplatn\xe9"},"deletedCustomer":"Smazan\xfd z\xe1kazn\xedk"},"detail":{"title":"Mollie předplatn\xe9","buttonCancelSubscription":"Zrušit předplatn\xe9","labelDescription":"Popis","labelAmount":"Č\xe1stka","labelQuantity":"Množstv\xed","labelMollieSubscription":"Mollie předplatn\xe9","labelMollieCustomer":"Mollie z\xe1kazn\xedk","labelMandateId":"Pověřen\xed","labelShopwareCustomer":"Shopware z\xe1kazn\xedk","labelCreatedAt":"Vytvořeno k","buttonShowShopwareOrder":"Zobrazit objedn\xe1vku Shopware","buttonShowShopwareCustomer":"Zobrazit z\xe1kazn\xedka Shopware","cardTitleSubscription":"Předplatn\xe9","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Dalš\xed platba k","labelLastRemindedAt":"Posledn\xed připomenut\xed k","labelCanceledAt":"Zrušeno k","buttonPauseSubscription":"Pozastavit předplatn\xe9","buttonResumeSubscription":"Obnovit předplatn\xe9","buttonSkipSubscription":"Přeskočit předplatn\xe9","history":{"cardTitle":"Historie","colDate":"Datum","colComment":"Koment\xe1ř","colStatusFrom":"Status (od)","colStatusTo":"Stav (do)","colMollieSubscription":"Mollie předplatn\xe9"}},"product":{"card-title":"Předplatn\xe9","title":"Mollie Předplatn\xe9","description":"Spr\xe1va vašich opakovan\xfdch plateb je snadnějš\xed než kdy dř\xedve d\xedky našim užitečn\xfdm funkc\xedm. Posuňte sv\xe9 podnik\xe1n\xed na novou \xfaroveň s efektivn\xedmi možnostmi sledov\xe1n\xed, jednoduch\xfdmi integracemi a dalš\xedmi funkcemi. S předplatn\xfdmi Mollie můžete snadno vytv\xe1řet produkty na předplatn\xe9 i napl\xe1novat opakovan\xe9 platby, kter\xe9 budou prob\xedhat v nastaven\xe9m intervalu a obdob\xed.","mollieSubscriptionProduct":"Produkt předplatn\xe9ho","mollieSubscriptionIntervalAmount":"Opakovat platbu každ\xfd","mollieSubscriptionIntervalType":"Jednotka intervalu","mollieSubscriptionRepetitionAmount":"Počet opakov\xe1n\xed","mollieSubscriptionRepetitionPlaceholder":"Zadejte č\xedslo nebo nechte pr\xe1zdn\xe9","infoDefaultLanguage":"Vezměte pros\xedm na vědom\xed, že tuto konfiguraci lze upravit pouze ve vašem v\xfdchoz\xedm jazyce. Pros\xedm změňte svůj jazyk pro \xfapravu nastaven\xed předplatn\xe9ho tohoto produktu.","btnReadMore":"Zjistit v\xedce"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Předplatn\xe9"}},"sw-order":{"detailExtended":{"titleCreditCardData":"\xdadaje o kreditn\xed kartě","buttonMolliePaymentLink":"Kop\xedrovat do schr\xe1nky","columnRefunded":"Vr\xe1ceno","columnShipped":"Odesl\xe1no","columnCanceled":"Zrušeno","labelMollieOrderId":"ID objedn\xe1vky Mollie","labelMollieThirdPartyPaymentId":"Reference platby","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Vr\xe1cen\xe1 č\xe1stka","totalRefundsPending":"Ček\xe1 na vr\xe1cen\xed","totalRemaining":"Č\xe1stka, kter\xe1 může b\xfdt vr\xe1cena","totalVouchers":"Č\xe1stka poukazu","totalShipments":"Odeslan\xe1 č\xe1stka ({quantity} položek)","subscriptionBadge":"Objedn\xe1vka předplatn\xe9ho","refundManager":{"title":"Mollie Manager Vr\xe1cen\xed","btnOpenRefundManager":"Otevř\xedt Manager Vr\xe1cen\xed","btnCloseRefundManager":"Zavř\xedt Spr\xe1vce Vr\xe1cen\xed Peněz"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Preferovan\xfd iDEAL emitent"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Spr\xe1vce vr\xe1cen\xed peněz"},"mollie_subscription":{"label":"Předplatn\xe1"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Popis"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Vr\xe1cen\xed peněz","subscription":"Předplatn\xe9","webhookReceived":"Webhooky","status":"Status","started":"Zah\xe1jeno","ended":"Ukončeno","paused":"Pozastaveno","renewalReminder":"Upom\xednka na obnoven\xed","renewed":"Obnoven\xfd","resumed":"Pokračuje","skipped":"Přeskočeno","all":"Vše","canceled":"Zrušeno","expired":"Vypršelo","partiallyRefunded":"Vr\xe1ceno (č\xe1stečně)","orderSuccess":"Objedn\xe1vka byla \xfaspěšn\xe1","orderFailed":"Objedn\xe1vka selhala","orderCanceled":"Objedn\xe1vka byla zrušena"}}}'),eJ=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie naročnina | Mollie naročnine"},"businessEvents":{"mollie_checkout_order_success":" Naročilo uspešno","mollie_checkout_order_failed":" Naročilo neuspešno","mollie_checkout_order_canceled":" Naročilo preklicano","mollie_webhook_received_All":" Prejeto avtomatizirano obvestilo Mollie (vsa)","mollie_webhook_received_status_authorized":" Prejeto avtomatizirano obvestilo Mollie (avtorizirano)","mollie_webhook_received_status_failed":" Mollie avtomatizirano obvestilo prejeto (neuspešno)","mollie_webhook_received_status_canceled":" Mollie avtomatizirano obvestilo prejeto (preklicano)","mollie_webhook_received_status_expired":" Mollie avtomatizirano obvestilo prejeto (potekel)","mollie_webhook_received_status_pending":" Mollie avtomatizirano obvestilo prejeto (v teku)","mollie_webhook_received_status_paid":" Mollie avtomatizirano obvestilo prejeto (plačano)","mollie_webhook_received_status_completed":" Mollie avtomatizirano obvestilo prejeto (končano)","mollie_webhook_received_status_refunded":" Mollie avtomatizirano obvestilo prejeto (vrnjeno)","mollie_webhook_received_status_partially_refunded":" Mollie avtomatizirano obvestilo prejeto (delno vrnjeno)","mollie_refund_started":" Mollie vračilo je bilo začeto","mollie_subscription_started":" Mollie naročnina se je začela","mollie_subscription_ended":" Mollie naročnina se je končala","mollie_subscription_cancelled":" Mollie naročnina je preklicana","mollie_subscription_paused":" Mollie naročnina je začasno ustavljena","mollie_subscription_resumed":" Mollie naročnina se nadaljuje","mollie_subscription_skipped":" Mollie naročnina ni bila izvedena","mollie_subscription_renewed":" Mollie naročnina je obnovljena","mollie_subscription_renewal_reminder":" Mollie opomnik za obnovitev naročnine"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie modul","searchPlaceholder":"Iskanje naročnin...","general":{"mainMenuItemGeneral":"Mollie plačila","descriptionTextModule":"Mollie plačila","btnMollieActions":"Dejanja Mollie","refundThroughMollie":"Vračilo preko Mollie","shipThroughMollie":"Pošiljanje preko Mollie","cancelMollieItem":"Preklici preko Mollie"},"config":{"info":{"title":"Pozdravljeni {userName}, dobrodošli v Mollie!","descriptionTop":"Uvajanje z Mollie je enostavno!","descriptionBottom":"To je vse!","descriptionFooter":"Če želite izvedeti več o našem vtičniku, prosimo, obiščite našo uradno stran z dokumentacijo.","onboardingStep1":"Registrirajte se v Mollie račun.","onboardingStep2":"Vnesite svoje ključe API v spodnji razdelek.","onboardingStep2TestMode":"Vklopite \'Testni način\', če želite plačila le testirati.","onboardingStep3":"Dodelite načine plačila vašemu prodajnemu kanalu.","onboardingStep3Link":"vašim prodajnim kanalom","btnDocumentation":"Dokumentacija","btnRequestSupport":"Podpora","btnTroubleshooting":"Priročnik za odpravljanje težav"},"api":{"apiLinkButton":"Pridobite svoje ključe API iz Mollie Dashboard","testButton":"Testni ključi API","testApiKeys":{"title":"Mollie plačila","apiKey":"ključ API","isValid":"je veljaven","isInvalid":"je neveljaven"}},"payments":{"format":{"placeholder":"Vmesno besedilo","preview":"Predogled"},"updatePaymentMethods":{"title":"Mollie plačila","button":"Posodobi načine plačil","succeeded":"Načini plačila so bili uspešno posodobljeni.","failed":"Načinov plačila ni mogoče posodobiti."},"mollieLimits":{"link":"Prikaži pravila razpoložljivosti Mollie za načine plačila"}},"rounding":{"info1":"Shopware lahko uporablja nastavitve valute za izračun, kako zaokroži skupni znesek naročila. To vključuje število decimalnih mest v cenah vaših izdelkov in najbližji interval zaokroževanja, kot je 0,50 ali 1,00.","info2":"Te nastavitve lahko vodijo do drugačne končne cene, kot je skupna vsota vseh postavk. Ko Mollie preveri te zneske in ugotovi, da se ne ujemajo, pride do napake pri nakupu.","info3":"To funkcijo lahko uporabite, da se izognete težavam z zaokroževanjem pri nakupu. Ko je vklopljena, doda ločeno postavko v vašem Mollie Dashboardu za razliko v zaokroževanju, vaši kupci pa plačajo končno skupno ceno, izračunano v programu Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Uporaba Klarna Slice it ali Klarna Pay later kot način plačila ni mogoč, ko je datum poteka daljši od 28 dni, razen če je dogovor med trgovcem in Klarno drugačen.","bankTransferDueDateLimitReached":"Ni mogoče nastaviti življenjske dobe naročila nad 100 dni."},"support":{"modalTitle":"Zahtevajte podporo od Mollie","btnCancel":"Prekliči","btnConfirm":"Zahteva za podporo","btnSupport":"Več o naši podpori","form":{"name":"Vaše ime","email":"Vaš e-poštni naslov","recipient":"Pošlji zahtevo na","subject":"Predmet","message":"Sporočilo"},"data":{"header":"Podatki poslani Mollie:","other":"Drugo:","shopwareVersion":"Različica Shopware","pluginLogs":"{plugin} datoteke dnevnika","pluginConfiguration":"{plugin} konfiguracija","pluginConfigurationHelpText":"Ključi API so izključeni.","paymentMethods":"Podatki o načinu plačila","paymentMethodsHelpText":"Vsebuje informacije o tem, kateri načini plačila so aktivni, dodeljeni vsakemu prodajnemu kanalu, ter njihov status v vašem Mollie računu."},"success":"Zahteva za podporo je bila uspešno poslana. Potrudili se bomo, da odgovorimo čim prej.","error":"Prišlo je do težave pri pošiljanju e-pošte prek Shopware. Poskusite znova ali nas kontaktirajte neposredno po e-pošti."}},"rules":{"itemSubscriptionRule":"Izdelek je naročnina (Mollie)","cartSubscriptionRule":"Košarica z naročninami (Mollie)"},"refunds":{"status":{"queued":"Na čakanju","pending":"V teku","processing":"Obdelava","refunded":"Vrnjeno","failed":"Neuspešno","description":{"queued":"Vračilo je na čakanju, dokler ni dovolj stanja za obdelavo vračila. Vračilo še lahko prekličete.","pending":"Vračilo bo poslano na banko naslednji delovni dan. Vračilo še lahko prekličete.","processing":"Vračilo je bilo poslano na banko. Znesek vračila bo čim prej prenesen na račun potrošnika.","refunded":"Znesek vračila je bil nakazan potrošniku.","failed":"Vračilo je bilo po obdelavi neuspešno. Možno je, da je stranka zaprla svoj bančni račun. Sredstva bodo vrnjena na vaš račun."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nimate dovoljenj za ustvarjanje vračil","warningCancel":"Nimate dovoljenj za preklic vračil"},"cart":{"title":"Naročilo ##orderNumber##","btnSelectAll":"Izberite vse","btnResetForm":"Ponastavite obrazec","linkHowTo":"Kako uporabiti ta obrazec?","grid":{"columns":{"item":"Izdelek","productNumber":"Številka izdelka","unitPrice":"Cena na enoto","quantity":"Količina","refunded":"Vrnjeno","refundQuantity":"Vračilo","totalPrice":"Skupaj","refundAmount":"Vračilo","resetStock":"Ponastavi zalogo"},"btnResetLine":"Ponastavi vrstico","checkDeductPromotion":"Odštej popust","checkRefundTax":"Vrnite DDV"},"roundDiffItemAdded":"Postavka za samodejno zaokroževanje je bil dodan"},"instructions":{"linkResetTutorials":"Ponastavi navodila","btnToggleTutorial":"Prikaži/skrij navodilo","titleFullRefund":"Polno vračilo","textFullRefund":"Preprosto uporabite gumb za celotno vračilo. Tako zagotovite, da so vsi vaši predmeti označeni kot vrnjeni in da je celoten znesek vrnjen stranki.","titleStockReset":"Ponastavitev zaloge","textStockReset":"Razpoložljivo zalogo lahko samodejno povečate tako, da vnesete količino, ki jo želite vrniti. Preprosto jo vnesite preden nadaljujejte s polnim ali delnim vračilom. Ponastavitev zaloge se lahko prilagodi procesu vračila na fleksibilen način.","titleShipping":"Pošiljanje","textShipping":"Odposlani predmet se lahko vrne kot kateri koli drugi produkt. Vnesite celotno količino ali po meri določen delni znesek in nadaljujte s vračilom. Vračilo stroškov pošiljanja je mogoče združiti s procesom vračila predmetov na fleksibilen način.","titlePartialAmount":"Delno vračilo (samo znesek)","textPartialAmount":"Preprosto vnesite delni znesek v polje z besedilom in začnite vračilo.","titlePartialItems":"Delno vračilo (z izdelki)","textPartialItems":"Če želite označiti količine in izdelke kot vrnjene v Mollie, uporabite zgornji obrazec. Nastavite svoje količine in navedite prilagojen znesek za vsak izdelek, ki bo vrnjen. Skupni znesek bo nato viden v končnem polju z besedilom za vračilo.","titlePartialPromotions":"Delno vračilo (s popusti)","textPartialPromotions":"Če imate popust v svoji košarici, potem je vaša promocija ločena postavka. Če želite vrniti vse znižane izdelke, se lotite in vrnite njihovo celotno vrednost in celoten popust. Vendar pa lahko, če želite vrniti le nekaj znižanih izdelkov, avtomatsko odštejete uporabljeni popust za vsako postavko. Seveda lahko vedno spremenite vrednosti, če niso pravilne.","titleRoundingDiff":"Razlika pri zaokroževanju","textRoundingDiff":"Polno vračilo bo vključevalo razlike pri zaokroževanju"},"summary":{"dataLoading":"Podatki se nalagajo...","headerExcludingVat":"Brez DDV","headerIncludingVat":"Z DDV","captionTotal":"Skupaj","captionTotalTaxFree":"Skupaj","captionPendingRefunds":"Čaka na vračilo","captionVouchers":"Znesek vavčerja","captionRefunded":"Znesek vračila","captionRemaining":"Znesek, ki ga je mogoče vrniti","btnFixDiff":"Odpravi razliko","placeholderDescription":"Vnesite opis izpiska za potrošnika. Maksimalno 140 znakov","lblDescription":"Opis (neobvezno) ({characters}/140 znakov)","descriptionHelp":"Ta opis bo prikazan na bančnem ali kartičnem izpisku potrošnika, kadar bo to mogoče. Sporočilo bo skrajšano po 140 znakih.","placeholderInternalDescription":"Vnesite svoj opis za interno uporabo","lblInternalDescription":"Interni opis (neobvezno)","internalDescriptionHelp":"Ta opis bo prikazan kot lokalni opis v vmesniku za upravljanje.","checkVerification":"Preveril(-a) sem skupni znesek vračila in nastavljene količine za vračilo in ponovno zalogo.","btnRefund":"Vračilo","btnFullRefund":"Polno vračilo","roundDiffItemAdded":"Razlika pri zaokroževanju"},"refunds":{"title":"Vračila v Mollie Dashboardu","linkMore":"Več o vračilih","grid":{"columns":{"amount":"Znesek","status":"Status","description":"Opis","internalDescription":"Notranji opis","composition":"Sestava","date":"Datum"},"lblNoComposition":"Nobena sestava ni na voljo","btnCancelRefund":"Prekliči to vračilo"}},"notifications":{"success":{"refund-created":"Vračilo je bilo ustvarjeno v Mollie. Zaključitev vračila lahko traja do 2 uri. Do tega trenutka lahko prekličete vračilo.","refund-canceled":"Vračilo v teku je bilo uspešno preklicano in odstranjeno."},"error":{"low-amount":"Prosimo, vnesite znesek, ki ga želite vrniti.","refund-created":"Pri ustvarjanju vračila je prišlo do napake.","refund-canceled":"Pri preklicu čakajočega vračila je prišlo do težave. Prosimo, poskusite znova v Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vavčer","VOUCHER_INFO_TITLE":"Vavčer plačila","VOUCHER_INFO_DESCRIPTION":"Mollie vam omogoča enostavno sprejemanje plačil v vaši spletni trgovini z uporabo ekoloških, darilnih in obročnih vavčerjev—pametni izbor za povečanje prodaje in zadovoljstvo vaših kupcev. Način plačila \\"vavčer\\" je viden le, če imate vsaj 1 izdelek z dodeljeno vrsto vavčerja v nakupovalni košarici.","VOUCHER_INFO_DEFAULTLANGUAGE":"Prosimo, upoštevajte, da je to nastavitev mogoče urediti samo v vašem privzetem jeziku. Spremenite svoj jezik, da spremenite vrsto vavčerja za ta izdelek.","VOUCHER_BTN_READMORE":"Preberite več","VOUCHER_TYPE_CAPTION":"Vrsta vavčerja izdelka","VOUCHER_TYPE_VALUE_NONE":"Noben","VOUCHER_TYPE_VALUE_ECO":"Ekološki","VOUCHER_TYPE_VALUE_MEAL":"Obrok","VOUCHER_TYPE_VALUE_VOUCHER":"Darilo"},"modals":{"shipping":{"title":"Odpošlji prek Mollie","item":{"label":"Izdelek:","noQuantity":"Prosimo, vnesite količino za pošiljanje.","shipAll":"Odpošlji vse","summary":{"quantity":"Količina za pošiljanje","shipped":"Količina, ki je bila poslana","shippable":"Količina, ki jo lahko pošljemo"},"success":"Naročilo je bilo uspešno odposlano."},"order":{"description":"Naslednje količine predmetov bodo odposlane.","itemHeader":"Izdelek","quantityHeader":"Količina","originalQuantityHeader":"Količina (ki jo lahko pošljemo)"},"availableTracking":{"label":"Razpoložljive številke za sledenje","hint":"Kliknite na eno od teh številk za sledenje, da samodejno izpolnite vse podatke."},"showTracking":"Dodajte informacije o sledenju za to pošiljko","tracking":{"carrier":"Prevoznik","code":"Številka","url":"URL","invalid":"Prosimo, vnesite tako Prevoznika kot Številko"},"confirmButton":"Odpošlji naročilo","cancelButton":"Prekliči","selectAllButton":"Izberi vse","resetButton":"Ponastavi"},"cancel":{"title":"Prekliči izdelek preko Mollie","confirmButton":"Prekliči izdelek preko Mollie","cancelButton":"Zapri okno","resetStock":"Ponastavite zalogo","item":{"success":"Izdelek je bil uspešno preklicano","failed":{"quantityZero":"Količina je 0","invalidLine":"Izdelek ne obstaja v naročilu","quantityTooHigh":"Količina je prekoračena"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Odpošlji naročilo (Mollie)","description":"Odpošlji naročilo v Mollie."},"modal":{"title":"Odpošlji naročilo","description":"Ta ukaz bo samodejno odposlal naročilo preko Mollie. Postopek bo prejel številko naročila in ta bo posredovana Mollie API-ju. Uspešna in neuspešna odpošiljanja bodo vidna v Mollie dnevniških datotekah.","warningConfig":"Prosimo, prepričajte se, da ste izklopili vse dodatne avtomatizacije za to vrsto ukaza, da se izognete morebitnim motnjam.\\nNekatere aktivirane funkcije tega vtičnika lahko motijo ta ukaz:","noWarnings":"Brez opozoril"}},"refundOrder":{"editor":{"title":"Vračilo naročila (Mollie)","description":"Vračilo naročila preko Mollie."},"modal":{"title":"Vračilo naročila","description":"Ta ukaz bo samodejno odposlal naročilo preko Mollie. Postopek bo prejel številko naročila in ta bo posredovana Mollie API-ju. Uspešna in neuspešna odpošiljanja bodo vidna v Mollie dnevniških datotekah.","warning":"Prosimo, upoštevajte, da lahko vračila trajajo do 2 uri, da se zaključijo in postanejo vidna v trgovini. Do takrat lahko vedno prekličete čakajoče vračilo bodisi s strani naročila v Shopware bodisi iz Mollie Dashboard.","warningConfig":"Prosimo, prepričajte se, da ste izklopili vse dodatne avtomatizacije za to vrsto ukaza, da se izognete morebitnim motnjam."}},"warnings":{"automaticShipping":"Samodejno pošiljanje v konfiguraciji vtičnika"}}},"subscriptions":{"status":{"pending":"V teku","active":"Aktivno","canceled":"Preklicano","suspended":"Suspendiran","completed":"Končano","paused":"Na pavzi","resumed":"Nadaljevanje","skipped":"Izpuščeno"},"navigation":{"title":"Mollie naročnine"},"TYPE_DAYS":"Dan(denvi)","TYPE_WEEKS":"Teden(i)","TYPE_MONTHS":"Mesec(i)","confirm":{"cancelTitle":"Prekliči naročnino?","cancel":"Prekličite naročnino vašega kupca.","pauseTitle":"Začasno zaustavi naročnino?","pause":"Naročnino obdržite do ponovnega nadaljevanja.","resumeTitle":"Nadaljujte naročnino?","resume":"Nadaljujte naročnino.","skipTitle":"Preskoči naslednje obročno plačilo?","skip":"Preskočite naslednje obročno plačilo v naročnini. Nato se bo samodejno nadaljevala."},"alerts":{"cancelSuccess":"Naročnina je bila uspešno preklicana","pauseSuccess":"Naročnina je bila uspešno začasno zaustavljena","resumeSuccess":"Naročnina je bila uspešno obnovljena","skipSuccess":"Naročnina je bila uspešno izpuščena. Naslednje plačilo je bilo posodobljeno."},"list":{"title":"Mollie naročnine","columns":{"customer":"Stranka","status":"Status","description":"Opis","amount":"Znesek","nextPaymentAt":"Naslednje plačilo","prePaymentReminder":"Opomnik na","canceledAt":"Preklicano ob","createdAt":"Ustvarjeno ob"},"action":{"edit":"Uredi naročnino"},"deletedCustomer":"Izbrisana stranka"},"detail":{"title":"Mollie naročnina","buttonCancelSubscription":"Prekliči naročnino","labelDescription":"Opis","labelAmount":"Znesek","labelQuantity":"Količina","labelMollieSubscription":"Mollie naročnina","labelMollieCustomer":"Mollie stranka","labelMandateId":"Mandat","labelShopwareCustomer":"Stranka Shopware","labelCreatedAt":"Ustvarjeno ob","buttonShowShopwareOrder":"Prikaži naročilo Shopware","buttonShowShopwareCustomer":"Prikaži stranko Shopware","cardTitleSubscription":"Naročnina","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Naslednje plačilo ob","labelLastRemindedAt":"Zadnji opomnik ob","labelCanceledAt":"Preklicano ob","buttonPauseSubscription":"Začasno zaustavi naročnino","buttonResumeSubscription":"Nadaljuj naročnino","buttonSkipSubscription":"Preskoči naročnino","history":{"cardTitle":"Zgodovina","colDate":"Datum","colComment":"Komentar","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Mollie naročnina"}},"product":{"card-title":"Naročnina","title":"Mollie naročnine","description":"Upravljajte vaša ponavljajoča se plačila lažje kot kdaj koli prej z našimi uporabnimi funkcijami. Popeljite svoj posel na naslednjo raven z učinkovitimi možnostmi sledenja, preprostimi integracijami in še več. S pomočjo Mollie naročnin lahko enostavno ustvarite naročniške izdelke in načrtujete ponavljajoča se plačila, ki bodo izvedena ob nastavljenem intervalu in obdobju.","mollieSubscriptionProduct":"Izdelki naročnin","mollieSubscriptionIntervalAmount":"Ponovite plačilo vsak","mollieSubscriptionIntervalType":"Enota intervala","mollieSubscriptionRepetitionAmount":"Število ponovitev","mollieSubscriptionRepetitionPlaceholder":"Vnesite število ali pustite prazno","infoDefaultLanguage":"Prosimo, upoštevajte, da lahko to nastavitev uredite samo v svojem privzetem jeziku. Prosimo, spremenite svoj jezik, da uredite nastavitve naročnine tega izdelka.","btnReadMore":"Preberite več"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Naročnina"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Podatki o kreditni kartici","buttonMolliePaymentLink":"Kopiraj v odložišče","columnRefunded":"Vrnjeno","columnShipped":"Odposlano","columnCanceled":"Preklicano","labelMollieOrderId":"ID naročila Mollie","labelMollieThirdPartyPaymentId":"Referenca plačila","labelMolliePaymentLink":"URL Mollie Checkout","totalRefunds":"Vrnjeni znesek","totalRefundsPending":"Čaka na vračilo","totalRemaining":"Znesek, ki se lahko vrne","totalVouchers":"Znesek vavčerja","totalShipments":"Poslana količina ({quantity} izdelkov)","subscriptionBadge":"Naročilo naročnine","refundManager":{"title":"Mollie upravitelj vračil","btnOpenRefundManager":"Odpri upravitelja vračil","btnCloseRefundManager":"Zapri upravitelja vračil"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Prednostni izdajatelj iDeal"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Upravitelj vračil"},"mollie_subscription":{"label":"Naročnine"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Opis"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Vračilo","subscription":"Naročnina","webhookReceived":"Avtomatizirana obvestila","status":"Status","started":"Začeto","ended":"Končano","paused":"Na pavzi","renewalReminder":"Opomnik za obnovitev","renewed":"Obnovljeno","resumed":"Se nadaljuje","skipped":"Izpuščeno","all":"Vse","canceled":"Preklicano","expired":"Potekel","partiallyRefunded":"Povrnjeno (delno)","orderSuccess":"Naročilo uspešno","orderFailed":"Naročilo neuspešno","orderCanceled":"Naročilo preklicano"}}}'),eX=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie előfizet\xe9s | Mollie előfizet\xe9sek"},"businessEvents":{"mollie_checkout_order_success":" A rendel\xe9s sikeres","mollie_checkout_order_failed":" A rendel\xe9s sikertelen","mollie_checkout_order_canceled":" A rendel\xe9s t\xf6r\xf6lve","mollie_webhook_received_All":" Mollie Webhook be\xe9rkezett (Minden)","mollie_webhook_received_status_authorized":" Mollie Webhook be\xe9rkezett (Enged\xe9lyezett)","mollie_webhook_received_status_failed":" Mollie Webhook be\xe9rkezett (Sikertelen)","mollie_webhook_received_status_canceled":" Mollie Webhook be\xe9rkezett (T\xf6r\xf6lve)","mollie_webhook_received_status_expired":" Mollie Webhook be\xe9rkezett (Lej\xe1rt)","mollie_webhook_received_status_pending":" Mollie Webhook be\xe9rkezett (F\xfcggőben)","mollie_webhook_received_status_paid":" Mollie Webhook be\xe9rkezett (Fizetve)","mollie_webhook_received_status_completed":" Mollie Webhook be\xe9rkezett (Befejezett)","mollie_webhook_received_status_refunded":" Mollie Webhook be\xe9rkezett (Visszat\xe9r\xedtve)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook be\xe9rkezett (R\xe9szben visszat\xe9r\xedtve)","mollie_refund_started":" Mollie visszat\xe9r\xedt\xe9s megkezdőd\xf6tt","mollie_subscription_started":" Mollie előfizet\xe9s megkezdőd\xf6tt","mollie_subscription_ended":" Mollie előfizet\xe9s befejeződ\xf6tt","mollie_subscription_cancelled":" Mollie előfizet\xe9s t\xf6r\xf6lve","mollie_subscription_paused":" Mollie előfizet\xe9s sz\xfcneteltetve","mollie_subscription_resumed":" Mollie előfizet\xe9s folytatva","mollie_subscription_skipped":" Mollie előfizet\xe9s \xe1tugorva","mollie_subscription_renewed":" Mollie előfizet\xe9s meg\xfaj\xedtva","mollie_subscription_renewal_reminder":" Mollie eml\xe9keztető az előfizet\xe9s meg\xfaj\xedt\xe1s\xe1hoz"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Search subscriptions...","general":{"mainMenuItemGeneral":"Mollie Fizet\xe9sek","descriptionTextModule":"Mollie Fizet\xe9sek","btnMollieActions":"Mollie Akci\xf3k","refundThroughMollie":"Visszat\xe9r\xedt\xe9s Mollie-n kereszt\xfcl","shipThroughMollie":"Sz\xe1ll\xedt\xe1s Mollie-n kereszt\xfcl","cancelMollieItem":"T\xf6rl\xe9s Mollie-n kereszt\xfcl"},"config":{"info":{"title":"Szia {userName}, \xfcdv\xf6z\xf6lj\xfck a Mollie-n\xe1l!","descriptionTop":"A Mollie-n\xe1l k\xf6nnyű a bevezet\xe9s!","descriptionBottom":"Ez ennyi!","descriptionFooter":"Ha t\xf6bbet szeretne megtudni a plugin-r\xf3l, k\xe9rj\xfck, l\xe1togassa meg hivatalos dokument\xe1ci\xf3s oldalunkat.","onboardingStep1":"Regisztr\xe1ljon egy Mollie Fi\xf3kra.","onboardingStep2":"Adja meg az API kulcsait az al\xe1bbi szekci\xf3ban.","onboardingStep2TestMode":"\'Teszt k\xf6rnyezet\' bekapcsol\xe1sa, ha csak a kifizet\xe9seket szeretn\xe9 tesztelni.","onboardingStep3":"Fizet\xe9si m\xf3dokat rendeljen elad\xe1si csatorn\xe1j\xe1hoz.","onboardingStep3Link":"az elad\xe1si csatorn\xe1ihoz","btnDocumentation":"Dokument\xe1ci\xf3","btnRequestSupport":"T\xe1mogat\xe1s","btnTroubleshooting":"Hibaelh\xe1r\xedt\xe1si \xfatmutat\xf3"},"api":{"apiLinkButton":"Szerezze meg API kulcsait a Mollie Ir\xe1ny\xedt\xf3pultr\xf3l","testButton":"Teszt API Kulcsok","testApiKeys":{"title":"Mollie Fizet\xe9sek","apiKey":"API kulcs","isValid":"\xe9rv\xe9nyes","isInvalid":"\xe9rv\xe9nytelen"}},"payments":{"format":{"placeholder":"Helyőrző","preview":"Előn\xe9zet"},"updatePaymentMethods":{"title":"Mollie Fizet\xe9sek","button":"Fizet\xe9si m\xf3dok friss\xedt\xe9se","succeeded":"A fizet\xe9si m\xf3dok sikeresen friss\xedtve lettek.","failed":"A fizet\xe9si m\xf3dokat nem siker\xfclt friss\xedteni."},"mollieLimits":{"link":"Mollie el\xe9rhetős\xe9gi szab\xe1lyok megjelen\xedt\xe9se a fizet\xe9si m\xf3dokhoz"}},"rounding":{"info1":"A Shopware p\xe9nznembe\xe1ll\xedt\xe1sokat haszn\xe1l a rendel\xe9s teljes \xf6sszeg\xe9nek kerek\xedt\xe9s\xe9nek kisz\xe1m\xedt\xe1s\xe1hoz. Ez mag\xe1ban foglalja a term\xe9k\xe1rak tizedesjegyeinek sz\xe1m\xe1t \xe9s a kerek\xedt\xe9si intervallumot, p\xe9ld\xe1ul 0.50 vagy 1.00.","info2":"Ezek a m\xf3dos\xedt\xe1sok a t\xe9telek \xf6sszeg\xe9től elt\xe9rő teljes \xf6sszeget eredm\xe9nyezhetnek. Amikor Mollie ellenőrzi ezeket az \xf6sszegeket, \xe9s nem egyeznek, a fizet\xe9si folyamat meghi\xfasul.","info3":"Ezzel a funkci\xf3val elker\xfclheti a kerek\xedt\xe9si probl\xe9m\xe1kat a fizet\xe9si folyamat sor\xe1n. Ha ez a funkci\xf3 be van kapcsolva, egy \xfaj t\xe9telsor ker\xfcl a Mollie Dashboardba a kerek\xedt\xe9si k\xfcl\xf6nbs\xe9ggel, \xe9s \xfcgyfelei kifizetik a Shopware \xe1ltal kisz\xe1m\xedtott v\xe9g\xf6sszeget."},"order":{"bankTransferDueDateKlarnaLimitReached":"28 napn\xe1l hosszabb esed\xe9kess\xe9g eset\xe9n a Klarna (fizessen most, fizessen r\xe9szletben vagy ut\xf3lag) fizet\xe9si m\xf3dk\xe9nt nem v\xe1laszthat\xf3, kiv\xe9ve, ha a Klarna \xe9s a kereskedő k\xfcl\xf6n meg\xe1llapod\xe1st k\xf6t\xf6tt ennek meghosszabb\xedt\xe1s\xe1ra.","bankTransferDueDateLimitReached":"Nem lehets\xe9ges a rendel\xe9s \xe9lettartam\xe1t 100 napn\xe1l magasabbra \xe1ll\xedtani."},"support":{"modalTitle":"K\xe9rjen seg\xedts\xe9get Mollie-t\xf3l","btnCancel":"T\xf6rl\xe9s","btnConfirm":"K\xe9rjen t\xe1mogat\xe1st","btnSupport":"T\xf6bb inform\xe1ci\xf3 t\xe1mogat\xe1sunkr\xf3l","form":{"name":"Az \xd6n neve","email":"Az \xd6n email c\xedme","recipient":"K\xe9relem elk\xfcld\xe9se","subject":"T\xe1rgy","message":"\xdczenet"},"data":{"header":"Adatok elk\xfcldve a Mollie-nak:","other":"M\xe1s:","shopwareVersion":"Shopware verzi\xf3","pluginLogs":"{plugin} napl\xf3f\xe1jlok","pluginConfiguration":"{plugin} konfigur\xe1ci\xf3","pluginConfigurationHelpText":"API kulcsok ki vannak z\xe1rva.","paymentMethods":"Fizet\xe9si m\xf3d adat","paymentMethodsHelpText":"Inform\xe1ci\xf3kat tartalmaz arr\xf3l, hogy mely fizet\xe9si m\xf3dok akt\xedvak, az egyes \xe9rt\xe9kes\xedt\xe9si csatorn\xe1khoz vannak hozz\xe1rendelve, valamint azok \xe1llapot\xe1r\xf3l a Mollie-fi\xf3kj\xe1ban."},"success":"The suport request has been successfully sent. We do our best to reply as soon as possible","error":"Probl\xe9ma l\xe9pett fel a lev\xe9l Shopware-en kereszt\xfcli elk\xfcld\xe9sekor. K\xe9rj\xfck, pr\xf3b\xe1lja \xfajra, vagy l\xe9pjen k\xf6zvetlen\xfcl kapcsolatba vel\xfcnk emailben."}},"rules":{"itemSubscriptionRule":"A term\xe9k előfizet\xe9s (Mollie)","cartSubscriptionRule":"Kos\xe1r előfizet\xe9sekkel (Mollie)"},"refunds":{"status":{"queued":"Folyamatban","pending":"F\xfcggőben","processing":"Feldolgoz\xe1s alatt","refunded":"Visszat\xe9r\xedtve","failed":"Sikertelen","description":{"queued":"A visszat\xe9r\xedt\xe9s addig van sorban, am\xedg elegendő egyenleg nem \xe1ll rendelkez\xe9sre a feldolgoz\xe1s\xe1hoz. Tov\xe1bbra is lemondhatja a visszat\xe9r\xedt\xe9st.","pending":"A visszat\xe9r\xedt\xe9st a k\xf6vetkező munkanapon k\xfcldik a banknak. A visszat\xe9r\xedt\xe9s m\xe9g mindig t\xf6r\xf6lhető.","processing":"A visszat\xe9r\xedt\xe9st elk\xfcldt\xfck a banknak. A visszat\xe9r\xedtett \xf6sszeg a lehető leghamarabb \xe1t lesz utalva a fogyaszt\xf3i sz\xe1ml\xe1ra.","refunded":"A visszat\xe9r\xedtett \xf6sszeg \xe1t lett utalva a fogyaszt\xf3nak.","failed":"A visszat\xe9r\xedt\xe9s feldolgoz\xe1s ut\xe1n meghi\xfasult. P\xe9ld\xe1ul a v\xe1s\xe1rl\xf3 bez\xe1rta a banksz\xe1ml\xe1j\xe1t. Az \xf6sszeg visszaker\xfcl az \xd6n sz\xe1ml\xe1j\xe1ra."}}},"refund-manager":{"general":{"unitQuantity":"pc."},"acl":{"warningCreate":"Nincs jogosults\xe1ga a visszat\xe9r\xedt\xe9sek l\xe9trehoz\xe1s\xe1ra","warningCancel":"Nincs jogosults\xe1ga a visszat\xe9r\xedt\xe9sek t\xf6rl\xe9s\xe9re"},"cart":{"title":"Megrendel\xe9s ##orderNumber##","btnSelectAll":"\xd6sszes kiv\xe1laszt\xe1sa","btnResetForm":"Űrlap vissza\xe1ll\xedt\xe1sa","linkHowTo":"Hogyan haszn\xe1ljam ezt az űrlapot?","grid":{"columns":{"item":"Term\xe9k","productNumber":"Term\xe9ksz\xe1m","unitPrice":"Egys\xe9g\xe1r","quantity":"Mennyis\xe9g","refunded":"Visszat\xe9r\xedtve","refundQuantity":"Visszat\xe9r\xedt\xe9s","totalPrice":"\xd6sszesen","refundAmount":"Visszat\xe9r\xedt\xe9s","resetStock":"K\xe9szlet vissza\xe1ll\xedt\xe1sa"},"btnResetLine":"Sor vissza\xe1ll\xedt\xe1sa","checkDeductPromotion":"Prom\xf3ci\xf3 levon\xe1sa","checkRefundTax":"\xc1FA visszat\xe9r\xedt\xe9se"},"roundDiffItemAdded":"Automatikus kerek\xedt\xe9si elem ker\xfclt hozz\xe1ad\xe1sra"},"instructions":{"linkResetTutorials":"\xdatmutat\xf3k vissza\xe1ll\xedt\xe1sa","btnToggleTutorial":"\xdatmutat\xf3 megjelen\xedt\xe9se/elrejt\xe9se","titleFullRefund":"Teljes visszat\xe9r\xedt\xe9s","textFullRefund":"Csak haszn\xe1lja a teljes visszat\xe9r\xedt\xe9s gombot. Ez biztos\xedtja, hogy az \xf6sszes elem\xe9t visszat\xe9r\xedtettnek jel\xf6lj\xf6n meg, \xe9s a teljes \xf6sszeg visszat\xe9r\xedt\xe9st ny\xfajtsa a v\xe1s\xe1rl\xf3nak.","titleStockReset":"K\xe9szlet vissza\xe1ll\xedt\xe1s","textStockReset":"A felt\xf6ltendő mennyis\xe9g hozz\xe1ad\xe1s\xe1val automatikusan n\xf6velheti a rendelkez\xe9sre \xe1ll\xf3 k\xe9szletet. Egyszerűen adja meg az inform\xe1ci\xf3kat, mielőtt folytatn\xe1 a teljes vagy r\xe9szleges visszat\xe9r\xedt\xe9st. Az \xe1llom\xe1ny helyre\xe1ll\xedt\xe1sa kombin\xe1lhat\xf3 a visszat\xe9r\xedt\xe9si folyamattal.","titleShipping":"Sz\xe1ll\xedt\xe1s","textShipping":"A kisz\xe1ll\xedt\xe1sra ker\xfclő t\xe9teleket ugyan\xfagy vissza lehet t\xe9r\xedteni, mint b\xe1rmely m\xe1s term\xe9ket. Egyszerűen \xedrja be a teljes vagy a k\xedv\xe1nt \xf6sszeget, \xe9s folytassa a visszat\xe9r\xedt\xe9ssel. A sz\xe1ll\xedt\xe1si k\xf6lts\xe9gek visszat\xe9r\xedt\xe9se kombin\xe1lhat\xf3 a t\xe9tel-visszat\xe9r\xedt\xe9si folyamattal.","titlePartialAmount":"R\xe9szleges Visszat\xe9r\xedt\xe9s (csak \xf6sszeg)","textPartialAmount":"Csak \xedrja be a r\xe9szlet\xf6sszeget a sz\xf6vegmezőbe, \xe9s kezdje meg a visszat\xe9r\xedt\xe9st.","titlePartialItems":"R\xe9szleges Visszat\xe9r\xedt\xe9s (term\xe9kekkel)","textPartialItems":"A fenti űrlap seg\xedts\xe9g\xe9vel jel\xf6lje meg a Mollie-n\xe1l visszat\xe9r\xedtett \xf6sszegeket \xe9s t\xe9teleket. \xc1ll\xedtsa be a mennyis\xe9geket, \xe9s adja hozz\xe1 az egyszeri \xf6sszeget minden egyes visszat\xe9r\xedtett t\xe9telhez. A teljes \xf6sszeg a teljes visszat\xe9r\xedtett \xf6sszeg sz\xf6vegmezőben lesz l\xe1that\xf3. Ne feledje, hogy a visszat\xe9r\xedt\xe9s megkezd\xe9se előtt m\xf3dos\xedthatja a v\xe9gső \xf6sszeget.","titlePartialPromotions":"R\xe9szleges Visszat\xe9r\xedt\xe9s (prom\xf3ci\xf3kkal)","textPartialPromotions":"Ha van egy akci\xf3 a kosar\xe1ban, az akci\xf3 \xfaj t\xe9telsork\xe9nt jelenik meg. Ha az \xf6sszes kedvezm\xe9nyes term\xe9ket vissza k\xedv\xe1nja t\xe9r\xedteni, vissza kell adnia az \xf6ssz\xe9rt\xe9k sort \xe9s a prom\xf3ci\xf3s t\xe9tel sort. Ha csak n\xe9h\xe1ny akci\xf3s t\xe9telt szeretne visszafizetni, akkor az egyes sorokra alkalmazott kedvezm\xe9nyt automatikusan levonhatja. Term\xe9szetesen b\xe1rmikor m\xf3dos\xedthatja az \xe9rt\xe9keket, ha nem megfelelőek.","titleRoundingDiff":"Kerek\xedt\xe9si k\xfcl\xf6nbs\xe9g","textRoundingDiff":"A teljes visszat\xe9r\xedt\xe9s tartalmazni fogja a kerek\xedt\xe9si k\xfcl\xf6nbs\xe9geket"},"summary":{"dataLoading":"Adatok bet\xf6lt\xe9se...","headerExcludingVat":"Nett\xf3","headerIncludingVat":"Brutt\xf3","captionTotal":"\xd6sszesen","captionTotalTaxFree":"\xd6sszesen","captionPendingRefunds":"Visszat\xe9r\xedt\xe9sre v\xe1r","captionVouchers":"Kupon \xf6sszege","captionRefunded":"Visszat\xe9r\xedtett \xf6sszeg","captionRemaining":"Visszat\xe9r\xedthető \xf6sszeg","btnFixDiff":"K\xfcl\xf6nbs\xe9g jav\xedt\xe1sa","placeholderDescription":"\xcdrja be a bank/k\xe1rtya kimutat\xe1s le\xedr\xe1s\xe1t a fogyaszt\xf3 sz\xe1m\xe1ra. Max 140 karakter","lblDescription":"Le\xedr\xe1s (opcion\xe1lis) ({characters}/140 karakter)","descriptionHelp":"Ez meg fog jelenni a fogyaszt\xf3 bank- vagy k\xe1rtyakimutat\xe1s\xe1n, amikor lehets\xe9ges. Az \xfczenet 140 karakter ut\xe1n trunkolva lesz.","placeholderInternalDescription":"Adja meg a belső le\xedr\xe1s\xe1t","lblInternalDescription":"Belső le\xedr\xe1s (opcion\xe1lis)","internalDescriptionHelp":"Ez a helyi le\xedr\xe1sa fog megjelenni az adminisztr\xe1ci\xf3s fel\xfcleten.","checkVerification":"Ellenőriztem a teljes visszat\xe9r\xedt\xe9si \xf6sszeget \xe9s a konfigur\xe1lt mennyis\xe9geket a visszat\xe9r\xedt\xe9shez \xe9s a k\xe9szletvisszahelyez\xe9shez.","btnRefund":"Visszat\xe9r\xedt\xe9s","btnFullRefund":"Teljes visszat\xe9r\xedt\xe9s","roundDiffItemAdded":"Kerek\xedt\xe9si elem"},"refunds":{"title":"Visszat\xe9r\xedt\xe9sek a Mollie Ir\xe1ny\xedt\xf3pulton","linkMore":"T\xf6bb inform\xe1ci\xf3 a visszat\xe9r\xedt\xe9sekről","grid":{"columns":{"amount":"\xd6sszeg","status":"\xc1llapot","description":"Le\xedr\xe1s","internalDescription":"Belső le\xedr\xe1s","composition":"\xd6sszet\xe9tel","date":"D\xe1tum"},"lblNoComposition":"Nincs el\xe9rhető \xf6sszet\xe9tel","btnCancelRefund":"T\xf6r\xf6lje ezt a visszat\xe9r\xedt\xe9st"}},"notifications":{"success":{"refund-created":"Egy visszat\xe9r\xedt\xe9st l\xe9trehoztak Mollie-ban. A visszat\xe9r\xedt\xe9s teljes\xedt\xe9se legfeljebb 2 \xf3r\xe1t vehet ig\xe9nybe. Ezen idő alatt t\xf6r\xf6lheti a visszat\xe9r\xedt\xe9st.","refund-canceled":"A f\xfcggőben l\xe9vő visszat\xe9r\xedt\xe9st sikeresen t\xf6r\xf6lt\xe9k \xe9s elt\xe1vol\xedtott\xe1k."},"error":{"low-amount":"K\xe9rj\xfck, adjon meg egy visszat\xe9r\xedtendő \xf6sszeget.","refund-created":"Valami elromlott a visszat\xe9r\xedt\xe9s l\xe9trehoz\xe1sakor.","refund-canceled":"Probl\xe9ma t\xf6rt\xe9nt a f\xfcggőben l\xe9vő visszat\xe9r\xedt\xe9s t\xf6rl\xe9sekor. K\xe9rj\xfck, pr\xf3b\xe1lja \xfajra a Mollie Ir\xe1ny\xedt\xf3pulton."}}},"vouchers":{"CARD_TITLE":"Kupon","VOUCHER_INFO_TITLE":"Kuponos kifizet\xe9sek","VOUCHER_INFO_DESCRIPTION":"A Mollie lehetőv\xe9 teszi, hogy \xf6kol\xf3giai, aj\xe1nd\xe9k- \xe9s \xe9lelmiszerutalv\xe1nyokkal fogadjon be fizet\xe9seket online \xe1ruh\xe1z\xe1b\xf3l. Ez a lehetős\xe9g n\xf6velheti az elad\xe1sokat, \xe9s kiel\xe9g\xedtheti \xfcgyfeleit. Az \\"utalv\xe1nyos\\" fizet\xe9si m\xf3d csak akkor l\xe1that\xf3, ha a kos\xe1rban legal\xe1bb 1 db utalv\xe1nyt\xedpushoz rendelt term\xe9k van.","VOUCHER_INFO_DEFAULTLANGUAGE":"K\xe9rj\xfck, vegye figyelembe, hogy ezt a be\xe1ll\xedt\xe1st csak az alapnyelv\xe9n tudja szerkeszteni. K\xe9rj\xfck, v\xe1ltson nyelvet, hogy m\xf3dos\xedthassa ennek a term\xe9knek a kupon t\xedpus\xe1t.","VOUCHER_BTN_READMORE":"Tov\xe1bbi inform\xe1ci\xf3","VOUCHER_TYPE_CAPTION":"Term\xe9k kupon t\xedpusa","VOUCHER_TYPE_VALUE_NONE":"Nincs","VOUCHER_TYPE_VALUE_ECO":"\xd6ko","VOUCHER_TYPE_VALUE_MEAL":"\xc9tkez\xe9s","VOUCHER_TYPE_VALUE_VOUCHER":"Aj\xe1nd\xe9k"},"modals":{"shipping":{"title":"Sz\xe1ll\xedt\xe1s Mollie-on kereszt\xfcl","item":{"label":"Term\xe9k:","noQuantity":"K\xe9rj\xfck, adjon meg egy mennyis\xe9get a sz\xe1ll\xedt\xe1shoz.","shipAll":"Minden sz\xe1ll\xedt\xe1sa","summary":{"quantity":"Sz\xe1ll\xedtand\xf3 mennyis\xe9g","shipped":"Sz\xe1ll\xedtott mennyis\xe9g","shippable":"Sz\xe1ll\xedthat\xf3 mennyis\xe9g"},"success":"A rendel\xe9st sikeresen sz\xe1ll\xedtott\xe1k."},"order":{"description":"A k\xf6vetkező term\xe9kek mennyis\xe9ge lesz sz\xe1ll\xedtva.","itemHeader":"Term\xe9k","quantityHeader":"Mennyis\xe9g","originalQuantityHeader":"Mennyis\xe9g (sz\xe1ll\xedthat\xf3)"},"availableTracking":{"label":"El\xe9rhető nyomk\xf6vet\xe9si k\xf3dok","hint":"Kattintson az egyik nyomk\xf6vet\xe9si k\xf3dra, hogy automatikusan kit\xf6lthesse az \xf6sszes adatot."},"showTracking":"Adjon meg nyomk\xf6vet\xe9si inform\xe1ci\xf3t ehhez a sz\xe1ll\xedt\xe1shoz","tracking":{"carrier":"Fuvaroz\xf3","code":"K\xf3d","url":"Url","invalid":"K\xe9rj\xfck, adja meg a Fuvaroz\xf3t \xe9s a K\xf3dot"},"confirmButton":"Rendel\xe9s sz\xe1ll\xedt\xe1sa","cancelButton":"T\xf6rl\xe9s","selectAllButton":"Mind kiv\xe1laszt\xe1sa","resetButton":"Vissza\xe1ll\xedt\xe1s"},"cancel":{"title":"T\xf6r\xf6lje a t\xe9telt Mollie-on kereszt\xfcl","confirmButton":"T\xf6r\xf6lje a t\xe9telt Mollie-on kereszt\xfcl","cancelButton":"Modal bez\xe1r\xe1sa","resetStock":"K\xe9szletek vissza\xe1ll\xedt\xe1sa","item":{"success":"A term\xe9k sikeresen t\xf6r\xf6lve","failed":{"quantityZero":"A mennyis\xe9g 0","invalidLine":"A term\xe9k nem l\xe9tezik a rendel\xe9sben","quantityTooHigh":"A mennyis\xe9g t\xfal magas"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Rendel\xe9s sz\xe1ll\xedt\xe1sa (Mollie)","description":"Rendel\xe9s sz\xe1ll\xedt\xe1sa Mollie-val."},"modal":{"title":"Rendel\xe9s sz\xe1ll\xedt\xe1sa","description":"Ez a művelet automatikusan sz\xe1ll\xedtja a rendel\xe9st Mollie-n kereszt\xfcl. A folyamat fel fogja venni a rendel\xe9si sz\xe1mot, \xe9s tov\xe1bb\xedtja azt a Mollie API-nak. A sikeres \xe9s sikertelen sz\xe1ll\xedt\xe1sok l\xe1that\xf3ak lesznek a Mollie napl\xf3f\xe1jljaiban.","warningConfig":"K\xe9rj\xfck, kapcsoljon ki minden tov\xe1bbi automatiz\xe1l\xe1st az ilyen t\xedpus\xfa műveletekhez a zavar\xe1s elker\xfcl\xe9se \xe9rdek\xe9ben.\\nA k\xf6vetkező param\xe9terek aktiv\xe1lva vannak, \xe9s zavarhatj\xe1k a műveletet:","noWarnings":"Nincsenek figyelmeztet\xe9sek"}},"refundOrder":{"editor":{"title":"Rendel\xe9s visszat\xe9r\xedt\xe9se (Mollie)","description":"Rendel\xe9s visszat\xe9r\xedt\xe9se Mollie-n kereszt\xfcl."},"modal":{"title":"Rendel\xe9s visszat\xe9r\xedt\xe9se","description":"Ez a művelet automatikusan elind\xedt egy visszat\xe9r\xedt\xe9st Mollie-n kereszt\xfcl. A folyamat fel fogja venni a rendel\xe9si sz\xe1mot, \xe9s tov\xe1bb\xedtja azt a Mollie API-nak. A sikeres \xe9s sikertelen visszat\xe9r\xedt\xe9sek l\xe1that\xf3ak lesznek a Mollie napl\xf3f\xe1jljaiban.","warning":"Felh\xedvjuk figyelm\xe9t, hogy a visszat\xe9r\xedt\xe9s legfeljebb 2 \xf3r\xe1t vesz ig\xe9nybe, \xe9s az \xfczletben l\xe1that\xf3. Ez előtt az idő előtt b\xe1rmikor t\xf6r\xf6lhet egy f\xfcggőben l\xe9vő visszat\xe9r\xedt\xe9st, ak\xe1r a Shopware rendel\xe9si oldal\xe1n, ak\xe1r a Mollie ir\xe1ny\xedt\xf3pultj\xe1n.","warningConfig":"K\xe9rj\xfck, a zavar\xe1s elker\xfcl\xe9se \xe9rdek\xe9ben tiltsa le az ilyen t\xedpus\xfa műveletek tov\xe1bbi automatiz\xe1l\xe1s\xe1t."}},"warnings":{"automaticShipping":"Automatikus elk\xfcld\xe9s a plugin be\xe1ll\xedt\xe1saiban"}}},"subscriptions":{"status":{"pending":"F\xfcggőben","active":"Akt\xedv","canceled":"T\xf6r\xf6lve","suspended":"Felf\xfcggesztve","completed":"Befejezett","paused":"Felf\xfcggesztve","resumed":"Folyamatban","skipped":"\xc1tugrott"},"navigation":{"title":"Mollie Előfizet\xe9sek"},"TYPE_DAYS":"Nap(ek)","TYPE_WEEKS":"H\xe9t(ek)","TYPE_MONTHS":"H\xf3nap(ok)","confirm":{"cancelTitle":"Előfizet\xe9s lemond\xe1sa?","cancel":"Lemondja az \xfcgyf\xe9l előfizet\xe9s\xe9t.","pauseTitle":"Előfizet\xe9s felf\xfcggeszt\xe9se?","pause":"Tartsa az előfizet\xe9st a felf\xfcggeszt\xe9s\xe9ig.","resumeTitle":"Előfizet\xe9s folytat\xe1sa?","resume":"Folytassa az előfizet\xe9st.","skipTitle":"\xc1tugorja a k\xf6vetkező r\xe9szletet?","skip":"\xc1tugorja a k\xf6vetkező r\xe9szletet az előfizet\xe9sben. K\xe9sőbb automatikusan folytat\xf3dik."},"alerts":{"cancelSuccess":"Az előfizet\xe9sek sikeresen lemond\xe1sra ker\xfcltek","pauseSuccess":"Az előfizet\xe9s sikeresen felf\xfcggesztve","resumeSuccess":"Az előfizet\xe9s sikeresen folytatva","skipSuccess":"Az előfizet\xe9s sikeresen \xe1tugr\xe1sra ker\xfclt. A k\xf6vetkező kifizet\xe9s friss\xedtve lett."},"list":{"title":"Mollie Előfizet\xe9sek","columns":{"customer":"\xdcgyf\xe9l","status":"\xc1llapot","description":"Le\xedr\xe1s","amount":"\xd6sszeg","nextPaymentAt":"K\xf6vetkező kifizet\xe9s","prePaymentReminder":"Eml\xe9keztető","canceledAt":"Lemondva","createdAt":"L\xe9trehozva"},"action":{"edit":"Előfizet\xe9s szerkeszt\xe9se"},"deletedCustomer":"T\xf6r\xf6lt \xfcgyf\xe9l"},"detail":{"title":"Mollie előfizet\xe9s","buttonCancelSubscription":"Előfizet\xe9s lemond\xe1sa","labelDescription":"Le\xedr\xe1s","labelAmount":"\xd6sszeg","labelQuantity":"Mennyis\xe9g","labelMollieSubscription":"Mollie előfizet\xe9s","labelMollieCustomer":"Mollie \xfcgyf\xe9l","labelMandateId":"Mand\xe1tum","labelShopwareCustomer":"Shopware \xfcgyf\xe9l","labelCreatedAt":"L\xe9trehozva","buttonShowShopwareOrder":"Shopware rendel\xe9s megjelen\xedt\xe9se","buttonShowShopwareCustomer":"Shopware \xfcgyf\xe9l megjelen\xedt\xe9se","cardTitleSubscription":"Előfizet\xe9s","cardTitleStatus":"\xc1llapot","labelStatus":"\xc1llapot","labelNextPaymentAt":"K\xf6vetkező kifizet\xe9s időpontja","labelLastRemindedAt":"Utols\xf3 eml\xe9keztető","labelCanceledAt":"Lemondva","buttonPauseSubscription":"Előfizet\xe9s felf\xfcggeszt\xe9se","buttonResumeSubscription":"Előfizet\xe9s folytat\xe1sa","buttonSkipSubscription":"Előfizet\xe9s \xe1tugr\xe1sa","history":{"cardTitle":"T\xf6rt\xe9net","colDate":"D\xe1tum","colComment":"Megjegyz\xe9s","colStatusFrom":"\xc1llapot (től)","colStatusTo":"\xc1llapot (ig)","colMollieSubscription":"Mollie előfizet\xe9s"}},"product":{"card-title":"Előfizet\xe9s","title":"Mollie Előfizet\xe9sek","description":"Az \xe1ltalunk k\xedn\xe1lt funkci\xf3knak k\xf6sz\xf6nhetően nagyon egyszerű az ism\xe9tlődő fizet\xe9sek kezel\xe9se. Emelje v\xe1llalkoz\xe1s\xe1t a k\xf6vetkező szintre a nyomk\xf6vet\xe9si lehetős\xe9gekkel, az egyszerű integr\xe1ci\xf3kkal \xe9s sok m\xe1ssal. A Mollie Subscriptions seg\xedts\xe9g\xe9vel előfizet\xe9seket hozhat l\xe9tre, \xe9s \xfctemezheti az ism\xe9tlődő fizet\xe9seket meghat\xe1rozott idők\xf6z\xf6nk\xe9nt \xe9s időszakonk\xe9nti fizet\xe9ssel.","mollieSubscriptionProduct":"Előfizet\xe9si term\xe9k","mollieSubscriptionIntervalAmount":"Kifizet\xe9s ism\xe9tl\xe9se minden","mollieSubscriptionIntervalType":"Idők\xf6z t\xedpusa","mollieSubscriptionRepetitionAmount":"Ism\xe9tl\xe9sek sz\xe1ma","mollieSubscriptionRepetitionPlaceholder":"Adja meg a sz\xe1mot, vagy hagyja \xfcresen","infoDefaultLanguage":"K\xe9rj\xfck, vegye figyelembe, hogy ezt a be\xe1ll\xedt\xe1st csak az alapnyelv\xe9n tudja szerkeszteni. K\xe9rj\xfck, v\xe1ltson nyelvet, hogy m\xf3dos\xedthassa ennek a term\xe9knek az előfizet\xe9si be\xe1ll\xedt\xe1sait.","btnReadMore":"Tov\xe1bbi inform\xe1ci\xf3"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Előfizet\xe9s"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Hitelk\xe1rtya adatok","buttonMolliePaymentLink":"M\xe1sol\xe1s a v\xe1g\xf3lapra","columnRefunded":"Visszat\xe9r\xedtve","columnShipped":"Kisz\xe1ll\xedtva","columnCanceled":"T\xf6r\xf6lve","labelMollieOrderId":"Mollie Rendel\xe9s ID","labelMollieThirdPartyPaymentId":"Fizet\xe9si hivatkoz\xe1s","labelMolliePaymentLink":"Mollie Fizet\xe9s URL","totalRefunds":"Visszat\xe9r\xedtett \xf6sszeg","totalRefundsPending":"Visszat\xe9r\xedt\xe9sre v\xe1r","totalRemaining":"Visszat\xe9r\xedthető \xf6sszeg","totalVouchers":"Kupon \xf6sszeg","totalShipments":"Kisz\xe1ll\xedtott \xf6sszeg ({quantity} t\xe9tel)","subscriptionBadge":"Előfizet\xe9s Rendel\xe9s","refundManager":{"title":"Mollie Visszat\xe9r\xedt\xe9si Menedzser","btnOpenRefundManager":"Visszat\xe9r\xedt\xe9si Menedzser megnyit\xe1sa","btnCloseRefundManager":"Visszat\xe9r\xedt\xe9si Menedzser bez\xe1r\xe1sa"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Prefer\xe1lt iDeal kibocs\xe1t\xf3"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Visszat\xe9r\xedt\xe9si Menedzser"},"mollie_subscription":{"label":"Előfizet\xe9sek"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Le\xedr\xe1s"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Visszat\xe9r\xedt\xe9s","subscription":"Előfizet\xe9s","webhookReceived":"Webhookok","status":"\xc1llapot","started":"Kezdőd\xf6tt","ended":"Befejeződ\xf6tt","paused":"Felf\xfcggesztve","renewalReminder":"Meg\xfaj\xedt\xe1si eml\xe9keztető","renewed":"Meg\xfaj\xedtva","resumed":"Folytatva","skipped":"\xc1tugorva","all":"Mind","canceled":"T\xf6r\xf6lve","expired":"Lej\xe1rt","partiallyRefunded":"Refunded (partially)","orderSuccess":"A megrendel\xe9s sikeres","orderFailed":"A megrendel\xe9s sikertelen","orderCanceled":"A megrendel\xe9s t\xf6r\xf6lve"}}}'),e0=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie-tilaus | Mollie-tilaukset"},"businessEvents":{"mollie_checkout_order_success":" Tilaus onnistui","mollie_checkout_order_failed":" Tilaus ep\xe4onnistui","mollie_checkout_order_canceled":" Tilaus peruutettu","mollie_webhook_received_All":" Mollie Webhook vastaanotettu (Kaikki)","mollie_webhook_received_status_authorized":" Mollie Webhook vastaanotettu (Valtuutettu)","mollie_webhook_received_status_failed":" Mollie Webhook vastaanotettu (Ep\xe4onnistunut)","mollie_webhook_received_status_canceled":" Mollie Webhook vastaanotettu (Peruutettu)","mollie_webhook_received_status_expired":" Mollie Webhook vastaanotettu (Vanhentunut)","mollie_webhook_received_status_pending":" Mollie Webhook vastaanotettu (Kesken)","mollie_webhook_received_status_paid":" Mollie Webhook vastaanotettu (Maksettu)","mollie_webhook_received_status_completed":" Mollie Webhook vastaanotettu (Suoritettu)","mollie_webhook_received_status_refunded":" Mollie Webhook vastaanotettu (Hyvitetty)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook vastaanotettu (Osittain hyvitetty)","mollie_refund_started":" Mollie hyvityspyynt\xf6 aloitettu","mollie_subscription_started":" Mollie-tilaus aloitettu","mollie_subscription_ended":" Mollie-tilaus suoritettu","mollie_subscription_cancelled":" Mollie-tilaus peruutettu","mollie_subscription_paused":" Mollie-tilaus keskeytetty","mollie_subscription_resumed":" Mollie-tilaus jatkettu","mollie_subscription_skipped":" Mollie-tilaus ohitettu","mollie_subscription_renewed":" Mollie-tilaus uusittu","mollie_subscription_renewal_reminder":" Mollie muistutus tilauksen uusimisesta"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie-moduuli","searchPlaceholder":"Etsi tilauksia...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie Actions","refundThroughMollie":"Hyvitys Mollien kautta","shipThroughMollie":"Toimita Mollien kautta","cancelMollieItem":"Peruuta Mollien kautta"},"config":{"info":{"title":"Hei {userName}, Tervetuloa Mollieen!","descriptionTop":"Mollien k\xe4ytt\xf6\xf6notto on helppoa!","descriptionBottom":"Siin\xe4 se!","descriptionFooter":"Jos haluat lukea lis\xe4\xe4 laajennuksistamme, vieraile virallisella asiakirjasivullamme.","onboardingStep1":"Luo Mollie-tili.","onboardingStep2":"Sy\xf6t\xe4 API-avaimesi alla olevaan osioon.","onboardingStep2TestMode":"Ota k\xe4ytt\xf6\xf6n \'Test Mode\', jos haluat testata vain maksuja.","onboardingStep3":"M\xe4\xe4rit\xe4 maksutavat myyntikanavallesi.","onboardingStep3Link":"myyntikanavillesi","btnDocumentation":"Asiakirjat","btnRequestSupport":"Tuki","btnTroubleshooting":"Vianetsint\xe4opas"},"api":{"apiLinkButton":"Hanki API-avaimesi Mollie-hallintapaneelista","testButton":"Test API-avaimet","testApiKeys":{"title":"Mollie Payments","apiKey":"API-avain","isValid":"on voimassa","isInvalid":"on virheellinen"}},"payments":{"format":{"placeholder":"Paikkamerkki","preview":"Esikatselu"},"updatePaymentMethods":{"title":"Mollie Payments","button":"P\xe4ivit\xe4 maksutavat","succeeded":"Maksutavat on p\xe4ivitetty onnistuneesti.","failed":"Maksutapoja ei voitu p\xe4ivitt\xe4\xe4."},"mollieLimits":{"link":"N\xe4yt\xe4 Mollien saatavuus s\xe4\xe4nn\xf6t maksutavoille"}},"rounding":{"info1":"Shopware voi k\xe4ytt\xe4\xe4 valuutta-asetuksia laskeakseen, kuinka se py\xf6rist\xe4\xe4 tilauksen loppusumman. T\xe4m\xe4 sis\xe4lt\xe4\xe4 tuotteen hinnan desimaalien m\xe4\xe4r\xe4n ja l\xe4himm\xe4n py\xf6ristysv\xe4lin, kuten 0,50 tai 1,00.","info2":"N\xe4m\xe4 asetukset voivat johtaa erilaiseen loppusummaan kuin rivikohtien kokonaissumma. Kun Mollie tarkistaa n\xe4m\xe4 summat ja huomaa, ett\xe4 ne eiv\xe4t t\xe4sm\xe4\xe4, se aiheuttaa kassavirheen.","info3":"Voit k\xe4ytt\xe4\xe4 t\xe4t\xe4 ominaisuutta v\xe4ltt\xe4\xe4ksesi py\xf6ristysongelmia kassalla. Kun se on k\xe4yt\xf6ss\xe4, se lis\xe4\xe4 erillisen rivikohdan Mollie-hallintapaneeliin py\xf6ristyksen eroa varten, ja asiakkaasi maksavat Shopwaren laskeman loppusumman."},"order":{"bankTransferDueDateKlarnaLimitReached":"Ei ole mahdollista k\xe4ytt\xe4\xe4 Klarna Pay now, Klarna Slice it tai Klarna Pay later -menetelm\xe4\xe4, kun vanhenemisp\xe4iv\xe4si on yli 28 p\xe4iv\xe4n p\xe4\xe4ss\xe4, ellei kauppiaan ja Klarnan v\xe4lill\xe4 olla sovittu muuta maksimiarvoa.","bankTransferDueDateLimitReached":"Tilauksen kestoaikaa ei voi asettaa yli 100 p\xe4iv\xe4\xe4 pidemm\xe4ksi."},"support":{"modalTitle":"Pyyd\xe4 tukea Mollielta","btnCancel":"Peruuta","btnConfirm":"Pyyd\xe4 tukea","btnSupport":"Lis\xe4\xe4 tietoa tuestamme","form":{"name":"Nimesi","email":"S\xe4hk\xf6postisi","recipient":"L\xe4het\xe4 pyynt\xf6 osoitteeseen","subject":"Aihe","message":"Viesti"},"data":{"header":"Data l\xe4hetetty Mollielle:","other":"Muu:","shopwareVersion":"Shopware-versio","pluginLogs":"{plugin} lokitiedostot","pluginConfiguration":"{plugin} konfiguraatio","pluginConfigurationHelpText":"API-avaimet ovat suljettu pois.","paymentMethods":"Maksutavan tiedot","paymentMethodsHelpText":"Sis\xe4lt\xe4\xe4 tiedot aktiivisista maksutavoista, jotka on m\xe4\xe4ritetty kullekin myyntikanavalle, sek\xe4 niiden tilan Mollie-tilill\xe4si."},"success":"Tukipyynt\xf6 on l\xe4hetetty onnistuneesti. Teemme parhaamme vastataksemme sinulle mahdollisimman pian","error":"S\xe4hk\xf6postin l\xe4hett\xe4misess\xe4 Shopwaren kautta ilmeni ongelma. Yrit\xe4 uudelleen tai ota yhteytt\xe4 suoraan s\xe4hk\xf6postitse."}},"rules":{"itemSubscriptionRule":"Tuote on tilaus (Mollie)","cartSubscriptionRule":"Ostosk\xe4rry, jossa on tilauksia (Mollie)"},"refunds":{"status":{"queued":"Jonossa","pending":"Odottaa","processing":"K\xe4sittelyss\xe4","refunded":"Hyvitetty","failed":"Ep\xe4onnistunut","description":{"queued":"Hyvitys on jonossa, kunnes saldoa on riitt\xe4v\xe4sti hyvityksen k\xe4sittelyyn. Voit silti peruuttaa hyvityksen.","pending":"Hyvitys l\xe4hetet\xe4\xe4n pankkiin seuraavana arkip\xe4iv\xe4n\xe4. Voit silti peruuttaa hyvityksen.","processing":"Hyvitys on l\xe4hetetty pankkiin. Hyvityssumma siirret\xe4\xe4n kuluttajan tilille mahdollisimman pian.","refunded":"Hyvityssumma on siirretty kuluttajalle.","failed":"Hyvitys ep\xe4onnistui k\xe4sittelyn j\xe4lkeen. Esimerkiksi asiakas on sulkenut pankkitilins\xe4. Varat palautetaan tilillesi."}}},"refund-manager":{"general":{"unitQuantity":"kpl."},"acl":{"warningCreate":"Sinulla ei ole oikeuksia luoda hyvityksi\xe4","warningCancel":"Sinulla ei ole oikeuksia peruuttaa hyvityksi\xe4"},"cart":{"title":"Tilaus ##orderNumber##","btnSelectAll":"Valitse kaikki","btnResetForm":"Nollaa lomake","linkHowTo":"Kuinka k\xe4ytt\xe4\xe4 t\xe4t\xe4 lomaketta?","grid":{"columns":{"item":"Tuote","productNumber":"Tuotenumero","unitPrice":"Yksikk\xf6hinta","quantity":"M\xe4\xe4r\xe4","refunded":"Hyvitetty","refundQuantity":"Hyvitys","totalPrice":"Yhteens\xe4","refundAmount":"Hyvitys","resetStock":"Nollaa varasto"},"btnResetLine":"Nollaa rivi","checkDeductPromotion":"V\xe4henn\xe4 alennusta","checkRefundTax":"Hyvit\xe4 ALV"},"roundDiffItemAdded":"Automaattinen py\xf6ristysrivi lis\xe4ttiin"},"instructions":{"linkResetTutorials":"Nollaa oppat","btnToggleTutorial":"N\xe4yt\xe4/piilota opas","titleFullRefund":"Kokonaishyvitys","textFullRefund":"K\xe4yt\xe4 vain painiketta tehd\xe4ksesi t\xe4yden hyvityksen. T\xe4m\xe4 varmistaa, ett\xe4 kaikki tuotteet merkit\xe4\xe4n hyvitetyiksi ja koko summa palautetaan asiakkaalle.","titleStockReset":"Varaston nollaus","textStockReset":"Voit automaattisesti lis\xe4t\xe4 k\xe4ytett\xe4viss\xe4 olevaa varastoa sy\xf6tt\xe4m\xe4ll\xe4 m\xe4\xe4r\xe4n, jonka haluat palauttaa varastoon. Sy\xf6t\xe4 se ennen kuin jatkat t\xe4yden tai osittaisen hyvityksen kanssa. Varaston nollaus voidaan yhdist\xe4\xe4 joustavasti varsinaiseen palautusprosessiin.","titleShipping":"Toimitus","textShipping":"Toimituksessa olevat tuotteet voidaan palauttaa kuten mik\xe4 tahansa muu tuote. Sy\xf6t\xe4 joko koko m\xe4\xe4r\xe4 tai mukautettu osasumma ja jatka hyvityst\xe4. Toimituskulujen hyvitys voidaan yhdist\xe4\xe4 joustavasti tuotteiden varsinaiseen palautusprosessiin.","titlePartialAmount":"Osittainen hyvitys (vain summa)","textPartialAmount":"Sy\xf6t\xe4 vain osasumma tekstikentt\xe4\xe4n ja aloita hyvitys.","titlePartialItems":"Osittainen hyvitys (tuotteiden kanssa)","textPartialItems":"Jos haluat merkit\xe4 m\xe4\xe4r\xe4t ja tuotteet hyvitetyiksi Molliessa, k\xe4yt\xe4 yll\xe4 olevaa lomaketta. Sy\xf6t\xe4 m\xe4\xe4r\xe4t ja anna mukautettu summa jokaiselle hyvitett\xe4v\xe4lle tuotteelle. Kokonaissumma n\xe4kyy sitten lopullisen hyvityssumman tekstikent\xe4ss\xe4. Muista, ett\xe4 t\xe4t\xe4 lopullista summaa on edelleen mahdollista muuttaa ennen hyvityksen aloittamista.","titlePartialPromotions":"Osittainen hyvitys (sis\xe4lt\xe4en alennukset)","textPartialPromotions":"Jos ostoskorissasi on tarjous, tarjous on erillinen rivikohta. Jos haluat hyvitt\xe4\xe4 kaikki alennetut tuotteet, jatka ja hyvit\xe4 niiden kokonaisarvot ja koko tarjousrivikohta. Jos kuitenkin haluat hyvitt\xe4\xe4 vain tiettyj\xe4 alennettuja tuotteita, voit v\xe4hent\xe4\xe4 sovelletun alennuksen automaattisesti jokaisesta rivikohdasta. Voit aina muuttaa arvoja, jos ne eiv\xe4t ole oikein.","titleRoundingDiff":"Py\xf6ristysero","textRoundingDiff":"Kokonaishyvitys sis\xe4lt\xe4\xe4 py\xf6ristyseron"},"summary":{"dataLoading":"Tietoja ladataan...","headerExcludingVat":"Ei sis\xe4ll\xe4 alv.","headerIncludingVat":"Sis. ALV","captionTotal":"Yhteens\xe4","captionTotalTaxFree":"Yhteens\xe4","captionPendingRefunds":"Odottaa hyvityst\xe4","captionVouchers":"Kupongin arvo","captionRefunded":"Hyvitetty summa","captionRemaining":"Hyvitett\xe4v\xe4 summa","btnFixDiff":"Korjaa ero","placeholderDescription":"Sy\xf6t\xe4 pankki-/korttiotteen kuvaus kuluttajalle. Max 140 merkki\xe4","lblDescription":"Kuvaus (valinnainen) ({characters}/140 merkki\xe4)","descriptionHelp":"T\xe4m\xe4 n\xe4kyy mahdollisuuksien mukaan kuluttajan pankki- tai korttiotteella. Viesti katkaistaan ​​140 merkin j\xe4lkeen.","placeholderInternalDescription":"Sy\xf6t\xe4 sis\xe4inen kuvaus","lblInternalDescription":"Sis\xe4inen kuvaus (valinnainen)","internalDescriptionHelp":"T\xe4m\xe4 n\xe4ytet\xe4\xe4n paikallisena kuvauksena hallintoliittym\xe4ss\xe4.","checkVerification":"Olen tarkistanut palautuksen kokonaissumman ja m\xe4\xe4ritetyt m\xe4\xe4r\xe4t hyvitett\xe4v\xe4ksi ja varastoitavaksi.","btnRefund":"Hyvitys","btnFullRefund":"T\xe4ysi hyvitys","roundDiffItemAdded":"Py\xf6ristyskohde"},"refunds":{"title":"Hyvitykset Mollie-hallintapaneelissa","linkMore":"Lis\xe4\xe4 tietoa hyvityksist\xe4","grid":{"columns":{"amount":"Summa","status":"Tila","description":"Kuvaus","internalDescription":"Sis\xe4inen kuvaus","composition":"Rakenne","date":"P\xe4iv\xe4m\xe4\xe4r\xe4"},"lblNoComposition":"Ei k\xe4ytett\xe4viss\xe4 olevaa rakennetta","btnCancelRefund":"Peruuta t\xe4m\xe4 hyvitys"}},"notifications":{"success":{"refund-created":"Hyvitys on luotu Molliessa. Hyvityksen suorittaminen voi kest\xe4\xe4 2 tuntia. T\xe4h\xe4n asti voit peruuttaa hyvityksen.","refund-canceled":"Odottava hyvitys on onnistuneesti peruutettu ja poistettu."},"error":{"low-amount":"Ole hyv\xe4 ja sy\xf6t\xe4 hyvitett\xe4v\xe4 m\xe4\xe4r\xe4.","refund-created":"Jokin meni pieleen hyvityst\xe4 luotaessa.","refund-canceled":"Hyvityksen peruuttamisessa oli ongelma. Ole hyv\xe4 ja yrit\xe4 uudelleen Mollie-hallintapaneelissa."}}},"vouchers":{"CARD_TITLE":"Kuponki","VOUCHER_INFO_TITLE":"Kuponkimaksut","VOUCHER_INFO_DESCRIPTION":"Mollien avulla voit helposti hyv\xe4ksy\xe4 maksuja verkkokaupassasi k\xe4ytt\xe4m\xe4ll\xe4 eko-, lahja- ja ateriaseteleit\xe4 – fiksu valinta myynnin lis\xe4\xe4miseen ja asiakkaiden tyytyv\xe4isyyteen. Maksutapa \\"kunponki\\" n\xe4kyy vain, jos ostoskorissa on v\xe4hint\xe4\xe4n 1 tuote, jolle on m\xe4\xe4ritetty kuponkityyppi.","VOUCHER_INFO_DEFAULTLANGUAGE":"Huomaa, ett\xe4 t\xe4t\xe4 rakennetta voidaan muokata vain oletuskielell\xe4si. Vaihda kieli muuttaaksesi t\xe4m\xe4n tuotteen kuponkityyppi\xe4.","VOUCHER_BTN_READMORE":"Lue lis\xe4\xe4","VOUCHER_TYPE_CAPTION":"Tuotteen kuponkityyppi","VOUCHER_TYPE_VALUE_NONE":"Ei mit\xe4\xe4n","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Ateria","VOUCHER_TYPE_VALUE_VOUCHER":"Lahja"},"modals":{"shipping":{"title":"Toimita Mollien kautta","item":{"label":"Tuote:","noQuantity":"Ole hyv\xe4 ja sy\xf6t\xe4 l\xe4hett\xe4v\xe4 m\xe4\xe4r\xe4.","shipAll":"Toimita kaikki","summary":{"quantity":"L\xe4hetys m\xe4\xe4r\xe4","shipped":"L\xe4hetetty m\xe4\xe4r\xe4","shippable":"Toimitettava m\xe4\xe4r\xe4"},"success":"Tilaus on toimitettu onnistuneesti."},"order":{"description":"Seuraavat tuotem\xe4\xe4r\xe4t toimitetaan.","itemHeader":"Tuote","quantityHeader":"M\xe4\xe4r\xe4","originalQuantityHeader":"M\xe4\xe4r\xe4 (toimitettavissa)"},"availableTracking":{"label":"Saatavilla olevat seurantakoodit","hint":"T\xe4yt\xe4 kaikki tiedot automaattisesti napsauttamalla jotakin n\xe4ist\xe4 seurantakoodeista."},"showTracking":"Lis\xe4\xe4 seurantatietoja t\xe4lle l\xe4hetykselle","tracking":{"carrier":"Kuriiri","code":"Koodi","url":"Url","invalid":"Sy\xf6t\xe4 sek\xe4 kuriiri ett\xe4 koodi"},"confirmButton":"Toimita tilaus","cancelButton":"Peruuta","selectAllButton":"Valitse kaikki","resetButton":"Nollaa"},"cancel":{"title":"Peruuta tuote Mollien kautta","confirmButton":"Peruuta tuote Mollien kautta","cancelButton":"Sulje modaali","resetStock":"Nollaa varastot","item":{"success":"Tuote on peruutettu onnistuneesti","failed":{"quantityZero":"M\xe4\xe4r\xe4 on 0","invalidLine":"Tuotetta ei ole tilauksessa","quantityTooHigh":"M\xe4\xe4r\xe4 on liian suuri"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Toimita tilaus (Mollie)","description":"Toimita tilaus Molliessa."},"modal":{"title":"Toimita tilaus","description":"T\xe4m\xe4 toiminto l\xe4hett\xe4\xe4 tilauksen automaattisesti Mollien kautta. Prosessointij\xe4rjestelm\xe4 vastaanottaa tilausnumeron ja v\xe4litt\xe4\xe4 sen Mollie API:lle. Onnistuneet ja ep\xe4onnistuneet l\xe4hetykset n\xe4kyv\xe4t Mollien lokitiedostoissa.","warningConfig":"Varmista, ett\xe4 samantyyppisille toiminnoille ei ole k\xe4yt\xf6ss\xe4 muita automaatioita h\xe4iri\xf6iden v\xe4ltt\xe4miseksi.\\nSeuraavat t\xe4m\xe4n laajennuksen aktivoidut ominaisuudet saattavat h\xe4irit\xe4 t\xe4t\xe4 toimintoa:","noWarnings":"Ei varoituksia"}},"refundOrder":{"editor":{"title":"Hyvit\xe4 tilaus (Mollie)","description":"Hyvit\xe4 tilaus Mollien kautta."},"modal":{"title":"Hyvit\xe4 tilaus","description":"T\xe4m\xe4 toiminto aloittaa automaattisesti hyvityksen Mollien kautta. Prosessij\xe4rjestelm\xe4 vastaanottaa tilausnumeron ja v\xe4litt\xe4\xe4 sen Mollien API:lle. Onnistuneet hyvitykset ja ep\xe4onnistuneet hyvitykset n\xe4kyv\xe4t Mollien lokitiedostoissa.","warning":"Huomaa, ett\xe4 hyvitysten viimeistely ja n\xe4kyminen kaupassa voi kest\xe4\xe4 jopa 2 tuntia. Siihen asti voit peruuttaa odottavan hyvityksen joko Shopwaren tilaussivulta tai Mollie-hallintapaneelista.","warningConfig":"Varmista, ett\xe4 samantyyppisille toimille ei ole k\xe4yt\xf6ss\xe4 muita automaatioita h\xe4iri\xf6iden v\xe4ltt\xe4miseksi."}},"warnings":{"automaticShipping":"Automaattinen toimitus laajennusm\xe4\xe4rityksess\xe4"}}},"subscriptions":{"status":{"pending":"Odottaa","active":"Aktiivinen","canceled":"Peruutettu","suspended":"Keskeytetty","completed":"Suoritettu","paused":"Pys\xe4ytetty","resumed":"Jatkettu","skipped":"Ohitettu"},"navigation":{"title":"Mollie-tilaukset"},"TYPE_DAYS":"P\xe4iv\xe4(t)","TYPE_WEEKS":"Viikko(t)","TYPE_MONTHS":"Kuukausi/kuukaudet","confirm":{"cancelTitle":"Lopeta tilaus?","cancel":"Peruuta asiakkaasi tilaus.","pauseTitle":"Keskeyt\xe4 tilaus?","pause":"Laita tilaus pys\xe4ytet\xe4\xe4n, kunnes jatkat sit\xe4 uudelleen.","resumeTitle":"Jatketaanko tilausta?","resume":"Jatka tilausta uudelleen.","skipTitle":"Ohita seuraava er\xe4?","skip":"Ohita tilauksen seuraava er\xe4. Se jatkuu automaattisesti sen j\xe4lkeen."},"alerts":{"cancelSuccess":"Tilaus on peruutettu onnistuneesti","pauseSuccess":"Tilaus on keskeytetty onnistuneesti","resumeSuccess":"Tilausta on jatkettu onnistuneesti","skipSuccess":"Tilaus on ohitettu onnistuneesti. Seuraava maksu on p\xe4ivitetty."},"list":{"title":"Mollie-tilaukset","columns":{"customer":"Asiakas","status":"Tila","description":"Kuvaus","amount":"Summa","nextPaymentAt":"Seuraava maksu","prePaymentReminder":"Muistutettu","canceledAt":"Peruutettu","createdAt":"Luotu"},"action":{"edit":"Muokkaa tilausta"},"deletedCustomer":"Poistettu asiakas"},"detail":{"title":"Mollie-tilaus","buttonCancelSubscription":"Peruuta tilaus","labelDescription":"Kuvaus","labelAmount":"Summa","labelQuantity":"M\xe4\xe4r\xe4","labelMollieSubscription":"Mollie-tilaus","labelMollieCustomer":"Mollie-asiakas","labelMandateId":"Valtuutus","labelShopwareCustomer":"Shopware-asiakas","labelCreatedAt":"Luotu","buttonShowShopwareOrder":"N\xe4yt\xe4 Shopware-tilaus","buttonShowShopwareCustomer":"N\xe4yt\xe4 Shopware-asiakas","cardTitleSubscription":"Tilaus","cardTitleStatus":"Tila","labelStatus":"Tila","labelNextPaymentAt":"Seuraava maksu","labelLastRemindedAt":"Viimeksi muistutettu","labelCanceledAt":"Peruutettu","buttonPauseSubscription":"Keskeyt\xe4 tilaus","buttonResumeSubscription":"Jatka tilausta","buttonSkipSubscription":"Ohita tilaus","history":{"cardTitle":"Historia","colDate":"P\xe4iv\xe4m\xe4\xe4r\xe4","colComment":"Kommentti","colStatusFrom":"Tila (alkaen)","colStatusTo":"Tila (asti)","colMollieSubscription":"Mollie-tilaus"}},"product":{"card-title":"Tilaus","title":"Mollie-tilaukset","description":"Toistuvien maksujesi hallinta on helpompaa kuin koskaan hy\xf6dyllisten ominaisuuksiemme ansiosta. Vie yrityksesi uudelle tasolle tehokkailla seurantavaihtoehdoilla, yksinkertaisilla integroinneilla ja monilla muilla tavoilla. Mollie-tilausten avulla voit helposti luoda tilaustuotteita ja ajoittaa toistuvia maksuja suoritettavaksi m\xe4\xe4ritetyll\xe4 aikav\xe4lill\xe4 ja ajanjaksolla.","mollieSubscriptionProduct":"Tilaustuote","mollieSubscriptionIntervalAmount":"Toista maksu joka","mollieSubscriptionIntervalType":"Aikav\xe4liyksikk\xf6","mollieSubscriptionRepetitionAmount":"Toistojen m\xe4\xe4r\xe4","mollieSubscriptionRepetitionPlaceholder":"Sy\xf6t\xe4 numero tai j\xe4t\xe4 tyhj\xe4ksi","infoDefaultLanguage":"Huomaa, ett\xe4 t\xe4t\xe4 rakennetta voidaan muokata vain oletuskielell\xe4si. Vaihda kielesi, jotta voit muokata t\xe4m\xe4n tuotteen tilaushallinnan.","btnReadMore":"Lue lis\xe4\xe4"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Tilaus"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Luottokorttitiedot","buttonMolliePaymentLink":"Kopioi leikep\xf6yd\xe4lle","columnRefunded":"Hyvitetty","columnShipped":"Toimitettu","columnCanceled":"Peruutettu","labelMollieOrderId":"Mollie-tilaustunnus","labelMollieThirdPartyPaymentId":"Maksuviite","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Hyvitetty summa","totalRefundsPending":"Odottaa hyvityst\xe4","totalRemaining":"Hyvitett\xe4v\xe4 summa","totalVouchers":"Kuponkim\xe4\xe4r\xe4","totalShipments":"Toimitettu m\xe4\xe4r\xe4 ({quantity} tuotetta)","subscriptionBadge":"Tilaus","refundManager":{"title":"Mollie-hyvityshallinta","btnOpenRefundManager":"Avaa hyvityshallinta","btnCloseRefundManager":"Sulje hyvityshallinta"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Suositeltu iDeal-my\xf6nt\xe4j\xe4"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Hyvityshallinta"},"mollie_subscription":{"label":"Tilaukset"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Kuvaus"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Hyvitys","subscription":"Tilaus","webhookReceived":"Webhook","status":"Tila","started":"Aloitettu","ended":"P\xe4\xe4ttynyt","paused":"Keskeytetty","renewalReminder":"Uusimismuistutus","renewed":"Uusittu","resumed":"Jatkettu","skipped":"Ohitettu","all":"Kaikki","canceled":"Peruutettu","expired":"Vanhentunut","partiallyRefunded":"Hyvitetty (osittain)","orderSuccess":"Tilaus onnistui","orderFailed":"Tilaus ep\xe4onnistui","orderCanceled":"Tilaus peruutettu"}}}'),e1=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Abonnement | Mollie Abonnementer"},"businessEvents":{"mollie_checkout_order_success":" Bestilling gennemf\xf8rt","mollie_checkout_order_failed":" Bestilling mislykkedes","mollie_checkout_order_canceled":" Bestilling annulleret","mollie_webhook_received_All":" Mollie Webhook Modtaget (Alle)","mollie_webhook_received_status_authorized":" Mollie Webhook Modtaget (Autoriseret)","mollie_webhook_received_status_failed":" Mollie Webhook Modtaget (Mislykkedes)","mollie_webhook_received_status_canceled":" Mollie Webhook Modtaget (Annulleret)","mollie_webhook_received_status_expired":" Mollie Webhook Modtaget (Udl\xf8bet)","mollie_webhook_received_status_pending":" Mollie Webhook Modtaget (Afventer)","mollie_webhook_received_status_paid":" Mollie Webhook Modtaget (Betalt)","mollie_webhook_received_status_completed":" Mollie Webhook Modtaget (F\xe6rdiggjort)","mollie_webhook_received_status_refunded":" Mollie Webhook Modtaget (Refunderet)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Modtaget (Delvist Refunderet)","mollie_refund_started":" Mollie refundering igangsat","mollie_subscription_started":" Mollie abonnement startet","mollie_subscription_ended":" Mollie abonnement f\xe6rdiggjort","mollie_subscription_cancelled":" Mollie abonnement annulleret","mollie_subscription_paused":" Mollie abonnement sat p\xe5 pause","mollie_subscription_resumed":" Mollie abonnement genoptaget","mollie_subscription_skipped":" Mollie abonnement sprunget over","mollie_subscription_renewed":" Mollie abonnement fornyet","mollie_subscription_renewal_reminder":" Mollie p\xe5mindelse om fornyelse af abonnement"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"S\xf8g abonnementer...","general":{"mainMenuItemGeneral":"Mollie Betalinger","descriptionTextModule":"Mollie Betalinger","btnMollieActions":"Mollie Handlinger","refundThroughMollie":"Refunder gennem Mollie","shipThroughMollie":"Send gennem Mollie","cancelMollieItem":"Annuller gennem Mollie"},"config":{"info":{"title":"Hej {userName}, Velkommen til Mollie!","descriptionTop":"Onboarding er enkelt med Mollie!","descriptionBottom":"Det er det!","descriptionFooter":"Hvis du vil l\xe6re mere om vores plugin, s\xe5 bes\xf8g venligst vores officielle dokumentationsside.","onboardingStep1":"Tilmeld dig en Mollie Konto.","onboardingStep2":"Indtast dine API-n\xf8gler i sektionen nedenfor.","onboardingStep2TestMode":"Aktiver \'Testmode\', hvis du kun vil teste betalinger.","onboardingStep3":"Tildel betalingsmetoder til din salgskanal.","onboardingStep3Link":"til dine salgskanaler","btnDocumentation":"Dokumentation","btnRequestSupport":"Support","btnTroubleshooting":"Fejlfinding Guide"},"api":{"apiLinkButton":"Hent dine API-n\xf8gler fra Mollie Dashboard","testButton":"Test API-n\xf8gler","testApiKeys":{"title":"Mollie Betalinger","apiKey":"API-n\xf8gle","isValid":"er gyldig","isInvalid":"er ugyldig"}},"payments":{"format":{"placeholder":"Pladsholder","preview":"Forh\xe5ndsvisning"},"updatePaymentMethods":{"title":"Mollie Betalinger","button":"Opdater betalingsmetoder","succeeded":"Betalingsmetoderne er blevet opdateret.","failed":"Betalingsmetoderne kunne ikke opdateres."},"mollieLimits":{"link":"Vis mollie tilg\xe6ngelighedsregler for betalingsmetoder"}},"rounding":{"info1":"Shopware kan bruge valutaindstillinger til at beregne, hvordan den afrunder den samlede ordre. Dette inkluderer antallet af decimaler i priserne p\xe5 dine produkter og det n\xe6rmeste afrundingsinterval, som f.eks. 0,50 eller 1,00.","info2":"Disse indstillinger kan f\xf8re til et andet samlet bel\xf8b end den totale sum af linjeposterne. N\xe5r Mollie krydstjekker disse bel\xf8b og finder, at de ikke stemmer overens, for\xe5rsager det en fejl ved kassen.","info3":"Du kan bruge denne funktion til at undg\xe5 afrundingsproblemer ved kassen. N\xe5r den er aktiveret, tilf\xf8jer den et separat linjepunkt i dit Mollie Dashboard for forskellen i afrunding, og dine kunder betaler det samlede bel\xf8b beregnet af Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Det er ikke muligt at bruge Klarna Betal nu, Klarna Delbatalinger eller Klarna Betal senere som metode, n\xe5r din udl\xf8bsdato er mere end 28 dage frem, medmindre en anden maksimumsperiode er aftalt mellem forhandleren og Klarna.","bankTransferDueDateLimitReached":"Det er ikke muligt at s\xe6tte bestillingens levetid h\xf8jere end 100 dage."},"support":{"modalTitle":"Anmod om support fra Mollie","btnCancel":"Annuller","btnConfirm":"Anmod om support","btnSupport":"Mere om vores support","form":{"name":"Dit navn","email":"Din e-mail","recipient":"Send anmodning til","subject":"Emne","message":"Besked"},"data":{"header":"Data sendt til Mollie:","other":"Andre:","shopwareVersion":"Shopware-version","pluginLogs":"{plugin} logfiler","pluginConfiguration":"{plugin} konfiguration","pluginConfigurationHelpText":"API-n\xf8gler er udelukket.","paymentMethods":"Betalingsmetode-data","paymentMethodsHelpText":"Indeholder oplysninger om, hvilke betalingsmetoder der er aktive, tildelt hver salgskanal, samt deres status p\xe5 din Mollie-konto."},"success":"Supportanmodningen er sendt. Vi g\xf8r vores bedste for at svare s\xe5 hurtigt som muligt","error":"Der opstod et problem ved afsendelse af mailen gennem Shopware. Fors\xf8g venligst igen eller kontakt os direkte via e-mail."}},"rules":{"itemSubscriptionRule":"Varen er abonnement (Mollie)","cartSubscriptionRule":"Kurv med abonnementer (Mollie)"},"refunds":{"status":{"queued":"I k\xf8","pending":"Afventer","processing":"Behandles","refunded":"Refunderet","failed":"Mislykkedes","description":{"queued":"Refusionen er sat i k\xf8, indtil der er tilstr\xe6kkelig saldo til at behandle refusionen. Du kan stadig annullere refusionen.","pending":"Refusionen sendes til banken den n\xe6ste arbejdsdag. Du kan stadig annullere refusionen.","processing":"Refusionen er blevet sendt til banken. Refusionsbel\xf8bet vil blive overf\xf8rt til forbrugerens konto s\xe5 hurtigt som muligt.","refunded":"Refusionsbel\xf8bet er blevet overf\xf8rt til forbrugeren.","failed":"Refusionen mislykkedes efter behandling. For eksempel har kunden lukket sin bankkonto. Midlerne vil blive returneret til din konto."}}},"refund-manager":{"general":{"unitQuantity":"stk."},"acl":{"warningCreate":"Du har ikke tilladelse til at oprette refusioner","warningCancel":"Du har ikke tilladelse til at annullere refusioner"},"cart":{"title":"Ordre ##orderNumber##","btnSelectAll":"V\xe6lg Alle","btnResetForm":"Nulstil Formular","linkHowTo":"Hvordan bruger jeg denne formular?","grid":{"columns":{"item":"Vare","productNumber":"Produktnummer","unitPrice":"Enhedspris","quantity":"Antal","refunded":"Refunderet","refundQuantity":"Refusion","totalPrice":"Total","refundAmount":"Refusion","resetStock":"Nulstil Lager"},"btnResetLine":"Nulstil Linje","checkDeductPromotion":"Tr\xe6k rabat fra","checkRefundTax":"Refusion af moms"},"roundDiffItemAdded":"Automatisk afrundingspost blev tilf\xf8jet"},"instructions":{"linkResetTutorials":"Nulstil Vejledninger","btnToggleTutorial":"Vis/Skjul Vejledning","titleFullRefund":"Fuld Refusion","textFullRefund":"Brug knappen til fuld refusion. Dette sikrer, at alle dine elementer markeres som refunderet, og det fulde bel\xf8b returneres til kunden.","titleStockReset":"Nulstilling af lager","textStockReset":"Du kan automatisk \xf8ge det tilg\xe6ngelige lager ved at indtaste den m\xe6ngde, du \xf8nsker at s\xe6tte tilbage i lageret. Indtast det f\xf8r du g\xe5r videre med en fuld eller delvis refusion. Nulstilling af lageret kan kombineres fleksibelt med selve refusionsprocessen.","titleShipping":"Forsendelse","textShipping":"Forsendelsesvarer kan refunderes som enhver anden produktvare. Indtast enten den samlede m\xe6ngde eller et tilpasset delbel\xf8b, og forts\xe6t med refusionen. Refusion af forsendelsesomkostninger kan kombineres fleksibelt med den faktiske refusionsproces for varer.","titlePartialAmount":"Delvis Refusion (kun bel\xf8b)","textPartialAmount":"Indtast blot det delvise bel\xf8b i tekstfeltet og start refusionen.","titlePartialItems":"Delvis Refundering (med varer)","textPartialItems":"Hvis du vil markere m\xe6ngder og varer som refunderet i Mollie, skal du bruge formularen ovenfor. Indstil dine m\xe6ngder og angiv et tilpasset bel\xf8b for hver vare, der skal refunderes. Den totale sum vil derefter v\xe6re synlig i tekstfeltet for det endelige refundbel\xf8b. Husk, at det stadig er muligt at justere dette endelige bel\xf8b, f\xf8r du starter din refundering.","titlePartialPromotions":"Delvis Refundering (med rabatter)","textPartialPromotions":"Hvis du har en rabat i din indk\xf8bskurv, s\xe5 er din rabat en separat linjepost. Hvis du \xf8nsker at refundere alle rabatterede varer, skal du g\xe5 videre og refundere deres samlede v\xe6rdier samt hele kampagnelinjen. Hvis du kun \xf8nsker at refundere nogle varer, der var rabatterede, kan du automatisk tr\xe6kke den anvendte rabat fra for hver enkelt linjepost. Du kan selvf\xf8lgelig altid \xe6ndre v\xe6rdierne, hvis de ikke er korrekte.","titleRoundingDiff":"Afrundingsforskel","textRoundingDiff":"En fuld refundering vil inkludere afrundingsforskelle"},"summary":{"dataLoading":"Data indl\xe6ses...","headerExcludingVat":"Ekskl. moms","headerIncludingVat":"Inkl. moms","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Venter p\xe5 at blive refunderet","captionVouchers":"Voucherbel\xf8b","captionRefunded":"Refunderet bel\xf8b","captionRemaining":"Refunderbart bel\xf8b","btnFixDiff":"Ret forskel","placeholderDescription":"Indtast bank/kortudskrift for forbrugeren. Max 140 tegn","lblDescription":"Beskrivelse (valgfrit) ({characters}/140 tegn)","descriptionHelp":"Dette vil blive vist p\xe5 forbrugerens bank- eller kortudskrift, n\xe5r det er muligt. Beskeden vil blive afkortet efter 140 tegn.","placeholderInternalDescription":"Indtast din interne beskrivelse","lblInternalDescription":"Intern beskrivelse (valgfrit)","internalDescriptionHelp":"Dette vil blive vist som en lokal beskrivelse i administrationsgr\xe6nsesnittet.","checkVerification":"Jeg har bekr\xe6ftet det samlede refusionsbel\xf8b og de konfigurerede m\xe6ngder, der skal refunderes og genlagres.","btnRefund":"Refusion","btnFullRefund":"Fuld Refundering","roundDiffItemAdded":"Afrundingspost"},"refunds":{"title":"Refusioner i Mollie Dashboard","linkMore":"Mere om refusioner","grid":{"columns":{"amount":"Bel\xf8b","status":"Status","description":"Beskrivelse","internalDescription":"Intern beskrivelse","composition":"Sammens\xe6tning","date":"Dato"},"lblNoComposition":"Ingen sammens\xe6tning tilg\xe6ngelig","btnCancelRefund":"Annuller denne refundering"}},"notifications":{"success":{"refund-created":"En refundering er blevet oprettet i Mollie. Det kan tage 2 timer for refunderingen at blive fuldf\xf8rt. Indtil da kan du annullere refunderingen.","refund-canceled":"Den ventende refundering er blevet annulleret og fjernet."},"error":{"low-amount":"Indtast venligst et bel\xf8b, der skal refunderes.","refund-created":"Noget gik galt, da der blev oprettet en refundering.","refund-canceled":"Der opstod et problem ved annullering af den ventende refundering. Pr\xf8v venligst igen i Mollie Dashboard."}}},"vouchers":{"CARD_TITLE":"Vouchere","VOUCHER_INFO_TITLE":"Voucher betalinger","VOUCHER_INFO_DESCRIPTION":"Mollie lader dig nemt acceptere betalinger i din online butik ved brug af Eco-, gave- og m\xe5ltid vouchers — et smart valg til at \xf8ge salget og tilfredsstille dine kunder. Betalingsmetoden \\"voucher\\" er kun synlig, hvis du har mindst 1 produkt med en tildelt vouchertype i indk\xf8bskurven.","VOUCHER_INFO_DEFAULTLANGUAGE":"Bem\xe6rk, at denne konfiguration kun kan redigeres p\xe5 dit standardsprog. Venligst skift dit sprog for at \xe6ndre vouchertypen for dette produkt.","VOUCHER_BTN_READMORE":"L\xe6s mere","VOUCHER_TYPE_CAPTION":"Vouchertype for produkt","VOUCHER_TYPE_VALUE_NONE":"Ingen","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"M\xe5ltid","VOUCHER_TYPE_VALUE_VOUCHER":"Gave"},"modals":{"shipping":{"title":"Send gennem Mollie","item":{"label":"Vare:","noQuantity":"Indtast venligst en m\xe6ngde til forsendelse.","shipAll":"Send alt","summary":{"quantity":"M\xe6ngde til forsendelse","shipped":"M\xe6ngde sendt","shippable":"M\xe6ngde der kan sendes"},"success":"Bestillingen er blevet sendt."},"order":{"description":"F\xf8lgende varem\xe6ngder vil blive sendt.","itemHeader":"Vare","quantityHeader":"M\xe6ngde","originalQuantityHeader":"M\xe6ngde (til forsendelse)"},"availableTracking":{"label":"Tilg\xe6ngelige sporingskoder","hint":"Klik p\xe5 en af disse sporingskoder for automatisk at udfylde alle data."},"showTracking":"Tilf\xf8j sporingsinfo for denne forsendelse","tracking":{"carrier":"Transport\xf8r","code":"Kode","url":"URL","invalid":"Indtast b\xe5de Transport\xf8r og Kode"},"confirmButton":"Send ordre","cancelButton":"Annuller","selectAllButton":"V\xe6lg alle","resetButton":"Nulstil"},"cancel":{"title":"Annuller vare gennem Mollie","confirmButton":"Annuller vare gennem Mollie","cancelButton":"Luk modal","resetStock":"Nulstil lager","item":{"success":"Produkt blev annulleret","failed":{"quantityZero":"M\xe6ngden er 0","invalidLine":"Produktet findes ikke i ordren","quantityTooHigh":"M\xe6ngden er for h\xf8j"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Send ordre (Mollie)","description":"Send ordre i Mollie."},"modal":{"title":"Send ordre","description":"Denne handling vil automatisk sende en ordre gennem Mollie. Flow sekvensen vil modtage ordrenummeret og sende dette videre til Mollie API. Vellykkede forsendelser og mislykkede forsendelser vil v\xe6re synlige i Mollies logfiler.","warningConfig":"Venligst s\xf8rg for at deaktivere alle yderligere automatiseringer for denne type handling for at undg\xe5 forstyrrelser.\\nDe f\xf8lgende aktiverede funktioner i denne plugin kan interferere med denne handling:","noWarnings":"Ingen advarsler"}},"refundOrder":{"editor":{"title":"Refunder ordre (Mollie)","description":"Refunder ordre gennem Mollie."},"modal":{"title":"Refunder ordre","description":"Denne handling vil automatisk starte en refundering gennem Mollie. Flow sekvensen vil modtage ordrenummeret og sende dette videre til Mollie API. Vellykkede refusioner og mislykkede refusioner vil v\xe6re synlige i Mollies logfiler.","warning":"Venligst husk, at refusioner kan tage op til 2 timer at blive afsluttet og synlige i butikken. Indtil da kan du altid annullere en ventende refusion enten fra ordren siden i Shopware eller fra Mollie Dashboard.","warningConfig":"Venligst s\xf8rg for at deaktivere enhver yderligere automatisering for denne type handling for at undg\xe5 forstyrrelser."}},"warnings":{"automaticShipping":"Automatisk forsendelse i plugin konfiguration"}}},"subscriptions":{"status":{"pending":"Afventer","active":"Aktiv","canceled":"Annulleret","suspended":"Suspenderet","completed":"F\xe6rdiggjort","paused":"Sat p\xe5 pause","resumed":"Genoptaget","skipped":"Sprunget over"},"navigation":{"title":"Mollie Abonnementer"},"TYPE_DAYS":"Dag(e)","TYPE_WEEKS":"Uge(r)","TYPE_MONTHS":"M\xe5ned(er)","confirm":{"cancelTitle":"Afslut abonnement?","cancel":"Annuller din kundes abonnement.","pauseTitle":"Pause abonnement?","pause":"S\xe6t abonnementet p\xe5 pause, indtil du genoptager det igen.","resumeTitle":"Genoptag abonnement?","resume":"Forts\xe6t abonnementet igen.","skipTitle":"Spring n\xe6ste rate over?","skip":"Spring den n\xe6ste rate i abonnementet over. Det forts\xe6tter automatisk herefter."},"alerts":{"cancelSuccess":"Abonnementet er blevet annulleret","pauseSuccess":"Abonnementet er blevet sat p\xe5 pause","resumeSuccess":"Abonnementet er blevet genoptaget","skipSuccess":"Abonnementet er blevet sprunget over. Den n\xe6ste betaling er blevet opdateret."},"list":{"title":"Mollie Abonnementer","columns":{"customer":"Kunde","status":"Status","description":"Beskrivelse","amount":"Bel\xf8b","nextPaymentAt":"N\xe6ste betaling","prePaymentReminder":"P\xe5mindet ved","canceledAt":"Annulleret ved","createdAt":"Oprettet ved"},"action":{"edit":"Rediger abonnement"},"deletedCustomer":"Slettet kunde"},"detail":{"title":"Mollie abonnement","buttonCancelSubscription":"Annuller abonnement","labelDescription":"Beskrivelse","labelAmount":"Bel\xf8b","labelQuantity":"Antal","labelMollieSubscription":"Mollie abonnement","labelMollieCustomer":"Mollie kunde","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware kunde","labelCreatedAt":"Oprettet ved","buttonShowShopwareOrder":"Vis Shopware ordre","buttonShowShopwareCustomer":"Vis Shopware kunde","cardTitleSubscription":"Abonnement","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"N\xe6ste betaling ved","labelLastRemindedAt":"Sidst p\xe5mindet ved","labelCanceledAt":"Annulleret ved","buttonPauseSubscription":"S\xe6t abonnement p\xe5 pause","buttonResumeSubscription":"Genoptag abonnement","buttonSkipSubscription":"Spring abonnement over","history":{"cardTitle":"Historik","colDate":"Dato","colComment":"Kommentar","colStatusFrom":"Status (fra)","colStatusTo":"Status (til)","colMollieSubscription":"Mollie abonnement"}},"product":{"card-title":"Abonnement","title":"Mollie abonnementer","description":"At h\xe5ndtere dine gentagne betalinger er lettere end nogensinde med vores nyttige funktioner. Tag din virksomhed til n\xe6ste niveau med effektive sporingsmuligheder, enkle integrationer og mere. Med Mollie abonnementer kan du nemt oprette abonnementsprodukter og planl\xe6gge gentagne betalinger til at finde sted p\xe5 det konfigurerede interval og periode.","mollieSubscriptionProduct":"Abonnementsprodukt","mollieSubscriptionIntervalAmount":"Gentag betaling hver","mollieSubscriptionIntervalType":"Interval enhed","mollieSubscriptionRepetitionAmount":"Antal gentagelser","mollieSubscriptionRepetitionPlaceholder":"Indtast nummer eller efterlad tomt","infoDefaultLanguage":"Bem\xe6rk venligst, at denne konfiguration kun kan redigeres p\xe5 dit standardsprog. Skift venligst dit sprog for at \xe6ndre abonnementsindstillingerne for dette produkt.","btnReadMore":"L\xe6s mere"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonnement"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kreditkortdata","buttonMolliePaymentLink":"Kopier til udklipsholderen","columnRefunded":"Refunderet","columnShipped":"Afsendt","columnCanceled":"Annulleret","labelMollieOrderId":"Mollie Ordre ID","labelMollieThirdPartyPaymentId":"Betalingsreference","labelMolliePaymentLink":"Mollie Checkout-URL","totalRefunds":"Refunderet bel\xf8b","totalRefundsPending":"Afventer refundering","totalRemaining":"Refunderbart bel\xf8b","totalVouchers":"Voucherv\xe6rdi","totalShipments":"Forsendt bel\xf8b ({quantity} varer)","subscriptionBadge":"Abonnementsordre","refundManager":{"title":"Mollie Refusionsansvarlig","btnOpenRefundManager":"\xc5ben Refusion Manager","btnCloseRefundManager":"Luk Refusion Manager"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Foretrukken iDeal udsteder"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refusion Manager"},"mollie_subscription":{"label":"Abonnementer"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Beskrivelse"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Refundering","subscription":"Abonnement","webhookReceived":"Webhooks","status":"Status","started":"Startet","ended":"Afsluttet","paused":"Sat p\xe5 pause","renewalReminder":"P\xe5mindelse om fornyelse","renewed":"Fornyet","resumed":"Genoptaget","skipped":"Sprunget over","all":"Alle","canceled":"Annulleret","expired":"Udl\xf8bet","partiallyRefunded":"Refunderet (delvist)","orderSuccess":"Ordren var vellykket","orderFailed":"Ordren mislykkedes","orderCanceled":"Ordren blev annulleret"}}}'),e2=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Συνδρομή | Mollie Συνδρομές"},"businessEvents":{"mollie_checkout_order_success":" Η παραγγελία ήταν επιτυχής","mollie_checkout_order_failed":" Η παραγγελία απέτυχε","mollie_checkout_order_canceled":" Η παραγγελία ακυρώθηκε","mollie_webhook_received_All":" Λήφθηκε Webhook Mollie (Όλα)","mollie_webhook_received_status_authorized":" Λήφθηκε Webhook Mollie (Εγκεκριμένο)","mollie_webhook_received_status_failed":" Λήφθηκε Webhook Mollie (Απέτυχε)","mollie_webhook_received_status_canceled":" Λήφθηκε Webhook Mollie (Ακυρωμένο)","mollie_webhook_received_status_expired":" Λήφθηκε Webhook Mollie (Έληξε)","mollie_webhook_received_status_pending":" Λήφθηκε Webhook Mollie (Εκκρεμεί)","mollie_webhook_received_status_paid":" Λήφθηκε Webhook Mollie (Πληρωμένο)","mollie_webhook_received_status_completed":" Λήφθηκε Webhook Mollie (Ολοκληρωμένο)","mollie_webhook_received_status_refunded":" Λήφθηκε Webhook Mollie (Επιστράφηκε)","mollie_webhook_received_status_partially_refunded":" Λήφθηκε Webhook Mollie (Επιστράφηκε μερικώς)","mollie_refund_started":" Η επιστροφή Mollie ξεκίνησε","mollie_subscription_started":" Η συνδρομή Mollie ξεκίνησε","mollie_subscription_ended":" Η συνδρομή Mollie ολοκληρώθηκε","mollie_subscription_cancelled":" Η συνδρομή Mollie ακυρώθηκε","mollie_subscription_paused":" Η συνδρομή Mollie τέθηκε σε παύση","mollie_subscription_resumed":" Η συνδρομή Mollie συνεχίζεται","mollie_subscription_skipped":" Η συνδρομή Mollie παραλείφθηκε","mollie_subscription_renewed":" Η συνδρομή Mollie ανανεώθηκε","mollie_subscription_renewal_reminder":" Υπενθύμιση Mollie για ανανέωση συνδρομής"}},"mollie-payments":{"pluginTitle":" Mollie","pluginDescription":"Λειτουργία Mollie","searchPlaceholder":"Αναζήτηση συνδρομών...","general":{"mainMenuItemGeneral":"Πληρωμές Mollie","descriptionTextModule":"Πληρωμές Mollie","btnMollieActions":"Ενέργειες Mollie","refundThroughMollie":"Επιστροφή χρημάτων μέσω Mollie","shipThroughMollie":"Αποστολή μέσω Mollie","cancelMollieItem":"Ακύρωση μέσω Mollie"},"config":{"info":{"title":"Γεια σου {userName}, Καλώς ήρθες στην Mollie!","descriptionTop":"Η ενσωμάτωση είναι εύκολη με την Mollie!","descriptionBottom":"Αυτό είναι!","descriptionFooter":"Αν θέλεις να μάθεις περισσότερα για το πρόσθετο μας, επισκέψου παρακαλώ την επίσημη σελίδα εγγράφων μας.","onboardingStep1":"Εγγραφή για λογαριασμό Mollie.","onboardingStep2":"Εισάγετε τα API keys σας στην παρακάτω ενότητα.","onboardingStep2TestMode":"Ενεργοποιήστε τη \'Δοκιμαστική Λειτουργία\' αν θέλετε να δοκιμάσετε μόνο πληρωμές.","onboardingStep3":"Αναθέστε μεθόδους πληρωμής στο κανάλι πωλήσεών σας.","onboardingStep3Link":"στα κανάλια πωλήσεων σας","btnDocumentation":"Έγγραφα","btnRequestSupport":"Υποστήριξη","btnTroubleshooting":"Οδηγός Αντιμετώπισης Προβλημάτων"},"api":{"apiLinkButton":"Λάβετε τα API keys σας από το Mollie Dashboard","testButton":"Δοκιμαστικά API keys","testApiKeys":{"title":"Πληρωμές Mollie","apiKey":"API key","isValid":"είναι έγκυρο","isInvalid":"δεν είναι έγκυρο"}},"payments":{"format":{"placeholder":"Πλαίσιο κειμένου","preview":"Προεπισκόπηση"},"updatePaymentMethods":{"title":"Πληρωμές Mollie","button":"Ενημέρωση μεθόδων πληρωμής","succeeded":"Οι μέθοδοι πληρωμής ενημερώθηκαν επιτυχώς.","failed":"Οι μέθοδοι πληρωμής δεν μπόρεσαν να ενημερωθούν."},"mollieLimits":{"link":"Δείξε τους κανόνες διαθεσιμότητας mollie για τις μεθόδους πληρωμής"}},"rounding":{"info1":"Το Shopware μπορεί να χρησιμοποιήσει τις ρυθμίσεις νομίσματος για να υπολογίσει πώς στρογγυλοποιείται το συνολικό ποσό μιας παραγγελίας. Αυτό περιλαμβάνει τον αριθμό των δεκαδικών στις τιμές των προϊόντων σας και το πλησιέστερο διάστημα στρογγυλοποίησης, όπως 0,50 ή 1,00.","info2":"Αυτές οι ρυθμίσεις μπορεί να οδηγήσουν σε διαφορετικό συνολικό ποσό από το συνολικό άθροισμα των στοιχείων. Όταν η Mollie ελέγχει αυτά τα ποσά και διαπιστώνει ότι δεν ταιριάζουν, προκαλεί σφάλμα κατά την ολοκλήρωση της παραγγελίας.","info3":"Μπορείτε να χρησιμοποιήσετε αυτή τη δυνατότητα για να αποφύγετε ζητήματα στρογγυλοποίησης στη διαδικασία ολοκλήρωσης. Όταν είναι ενεργοποιημένη, προσθέτει μια ξεχωριστή γραμμή στοιχείου στο Mollie Dashboard για τη διαφορά στη στρογγυλοποίηση, και οι πελάτες σας πληρώνουν το συνολικό ποσό που υπολογίζεται από το Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Δεν είναι δυνατόν να χρησιμοποιήσετε το Klarna Pay Now, το Klarna Slice It ή το Klarna Pay Later ως μέθοδο όταν η ημερομηνία λήξης σας είναι περισσότερες από 28 ημέρες στο μέλλον, εκτός αν συμφωνηθεί διαφορετική προθεσμία μεταξύ του εμπόρου και της Klarna.","bankTransferDueDateLimitReached":"Δεν είναι δυνατόν να ορίσετε τη διάρκεια ζωής της παραγγελίας υψηλότερη από 100 ημέρες."},"support":{"modalTitle":"Ζητήστε υποστήριξη από την Mollie","btnCancel":"Ακυρώνω","btnConfirm":"Ζητήστε υποστήριξη","btnSupport":"Περισσότερα για την υποστήριξή μας","form":{"name":"Το όνομά σας","email":"Η ηλεκτρονική σας διεύθυνση","recipient":"Αποστολή αιτήματος στο","subject":"Θέμα","message":"Μήνυμα"},"data":{"header":"Δεδομένα που εστάλησαν στην Mollie:","other":"Άλλα:","shopwareVersion":"Έκδοση Shopware","pluginLogs":"Αρχεία καταγραφής {plugin}","pluginConfiguration":"Διαμόρφωση {plugin}","pluginConfigurationHelpText":"Τα API keys εξαιρούνται.","paymentMethods":"Δεδομένα μεθόδου πληρωμής","paymentMethodsHelpText":"Περιλαμβάνει πληροφορίες σχετικά με ποιες μέθοδοι πληρωμής είναι ενεργές, ποιες έχουν ανατεθεί σε κάθε κανάλι πωλήσεων, καθώς και την κατάσταση τους στον λογαριασμό σας Mollie."},"success":"Το αίτημα υποστήριξης εστάλη επιτυχώς. Κάνουμε το καλύτερο δυνατό για να απαντήσουμε το συντομότερο δυνατό","error":"Παρουσιάστηκε πρόβλημα κατά την αποστολή του email μέσω του Shopware. Παρακαλούμε προσπαθήστε ξανά ή επικοινωνήστε μαζί μας άμεσα μέσω email."}},"rules":{"itemSubscriptionRule":"Το αντικείμενο είναι συνδρομή (Mollie)","cartSubscriptionRule":"Καλάθι με συνδρομές (Mollie)"},"refunds":{"status":{"queued":"Σε ουρά","pending":"Εκκρεμεί","processing":"Σε επεξεργασία","refunded":"Επιστράφηκε","failed":"Απέτυχε","description":{"queued":"Η επιστροφή χρημάτων είναι σε ουρά μέχρι να υπάρχει επαρκής υπόλοιπο για να επεξεργαστεί. Μπορείτε ακόμα να ακυρώσετε την επιστροφή.","pending":"Η επιστροφή θα σταλεί στην τράπεζα την επόμενη εργάσιμη ημέρα. Μπορείτε ακόμα να ακυρώσετε την επιστροφή.","processing":"Η επιστροφή έχει σταλεί στην τράπεζα. Το ποσό της επιστροφής θα μεταφερθεί στον λογαριασμό του καταναλωτή το συντομότερο δυνατό.","refunded":"Το ποσό της επιστροφής έχει μεταφερθεί στον καταναλωτή.","failed":"Η επιστροφή απέτυχε μετά την επεξεργασία. Για παράδειγμα, ο πελάτης έχει κλείσει τον τραπεζικό του λογαριασμό. Τα κεφάλαια θα επιστραφούν στον λογαριασμό σας."}}},"refund-manager":{"general":{"unitQuantity":"τεμ."},"acl":{"warningCreate":"Δεν έχετε άδειες για να δημιουργήσετε επιστροφές χρημάτων","warningCancel":"Δεν έχετε άδειες για να ακυρώσετε επιστροφές"},"cart":{"title":"Παραγγελία ##orderNumber##","btnSelectAll":"Επιλογή όλων","btnResetForm":"Επαναφορά Φόρμας","linkHowTo":"Πώς να χρησιμοποιήσετε αυτή τη φόρμα;","grid":{"columns":{"item":"Αντικείμενο","productNumber":"Αριθμός Προϊόντος","unitPrice":"Τιμή Μονάδας","quantity":"Ποσότητα","refunded":"Επιστράφηκε","refundQuantity":"Επιστροφή χρημάτων","totalPrice":"Σύνολο","refundAmount":"Επιστροφή χρημάτων","resetStock":"Επαναφορά Αποθέματος"},"btnResetLine":"Επαναφορά Γραμμής","checkDeductPromotion":"Αφαίρεση προωθητικής ενέργειας","checkRefundTax":"Επιστροφή ΦΠΑ"},"roundDiffItemAdded":"Το αντικείμενο αυτόματης στρογγυλοποίησης προστέθηκε"},"instructions":{"linkResetTutorials":"Επαναφορά Οδηγιών","btnToggleTutorial":"Εμφάνιση/Απόκρυψη Οδηγιών","titleFullRefund":"Πλήρης Επιστροφή χρημάτων","textFullRefund":"Απλά χρησιμοποιήστε το κουμπί για την πλήρη επιστροφή χρημάτων. Αυτό εξασφαλίζει ότι όλα τα αντικείμενά σας θα σημειωθούν ως επιστραμμένα και το πλήρες ποσό θα επιστραφεί στον πελάτη.","titleStockReset":"Επαναφορά Αποθεμάτων","textStockReset":"Μπορείτε αυτόματα να αυξήσετε το διαθέσιμο απόθεμα εισάγοντας την ποσότητα που θέλετε να επιστρέψετε. Απλά το εισάγετε πριν προχωρήσετε σε πλήρη ή μερική επιστροφή χρημάτων. Η επαναφορά του αποθέματος μπορεί να συνδυαστεί με τη διαδικασία επιστροφής με ευέλικτο τρόπο.","titleShipping":"Αποστολή","textShipping":"Τα αντικείμενα αποστολής μπορούν να επιστραφούν όπως οποιοδήποτε άλλο προϊόν. Είτε εισάγετε την πλήρη ποσότητα είτε ένα προσαρμοσμένο μερικό ποσό και προχωράτε με την επιστροφή. Η επιστροφή των εξόδων αποστολής μπορεί να συνδυαστεί με τη διαδικασία επιστροφής των αντικειμένων με ευέλικτο τρόπο.","titlePartialAmount":"Μερική επιστροφή χρημάτων (μόνο ποσό)","textPartialAmount":"Απλά εισάγετε το μερικό ποσό στο πεδίο κειμένου και ξεκινήστε την επιστροφή.","titlePartialItems":"Μερική Επιστροφή (με είδη)","textPartialItems":"Εάν θέλετε να επισημάνετε ποσότητες και αντικείμενα ως επιστραμμένα στο Mollie, χρησιμοποιήστε την παραπάνω φόρμα. Ορίστε τις ποσότητες σας και δώστε ένα προσαρμοσμένο ποσό για κάθε αντικείμενο που θα επιστραφεί. Το συνολικό ποσό θα είναι στη συνέχεια ορατό στο τελικό πεδίο ποσού επιστροφής. Θυμηθείτε, είναι ακόμα δυνατό να προσαρμόσετε αυτό το τελικό ποσό πριν ξεκινήσετε την επιστροφή σας.","titlePartialPromotions":"Μερική επιστροφή (με προωθητικές ενέργειες)","textPartialPromotions":"Εάν έχετε μια προώθηση στο καλάθι σας, τότε η προώθηση είναι μια ξεχωριστή γραμμή. Εάν θέλετε να επιστρέψετε όλα τα αντικείμενα που έχουν έκπτωση, προχωρήστε και επιστρέψτε τις συνολικές τους τιμές καθώς και τη γραμμή προώθησης. Ωστόσο, αν θέλετε να επιστρέψετε μόνο μερικά αντικείμενα που είχαν έκπτωση, μπορείτε να αφαιρέσετε την εφαρμοσμένη έκπτωση αυτόματα για κάθε γραμμή. Βεβαίως, μπορείτε πάντα να αλλάξετε τις τιμές αν δεν είναι σωστές.","titleRoundingDiff":"Διαφορά στρογγυλοποίησης","textRoundingDiff":"Μια πλήρης επιστροφή χρημάτων θα περιλαμβάνει τις διαφορές στρογγυλοποίησης"},"summary":{"dataLoading":"Τα δεδομένα φορτώνονται...","headerExcludingVat":"Εξαιρ. ΦΠΑ","headerIncludingVat":"Συμπ. ΦΠΑ","captionTotal":"Σύνολο","captionTotalTaxFree":"Σύνολο","captionPendingRefunds":"Σε αναμονή για επιστροφή χρημάτων","captionVouchers":"Ποσό κουπονιού","captionRefunded":"Ποσό που επιστράφηκε","captionRemaining":"Επιστρεπτέο ποσό","btnFixDiff":"Διορθώστε τη διαφορά","placeholderDescription":"Εισάγετε την περιγραφή της ανάλυσης τράπεζας/κάρτας για τον καταναλωτή. Μέγιστο 140 χαρακτήρες","lblDescription":"Περιγραφή (προαιρετικά) ({characters}/140 χαρακτήρες)","descriptionHelp":"Αυτό θα εμφανίζεται στην ανάλυση της τράπεζας ή της κάρτας του καταναλωτή όταν είναι δυνατόν. Το μήνυμα θα περικοπεί μετά από 140 χαρακτήρες.","placeholderInternalDescription":"Εισάγετε την εσωτερική σας περιγραφή","lblInternalDescription":"Εσωτερική περιγραφή (προαιρετικά)","internalDescriptionHelp":"Αυτό θα εμφανίζεται ως τοπική περιγραφή στο περιβάλλον διαχείρισης.","checkVerification":"Έχω επαληθεύσει το συνολικό ποσό επιστροφής και τις διαμορφωμένες ποσότητες για επιστροφή και ανεφοδιασμό.","btnRefund":"Επιστροφή χρημάτων","btnFullRefund":"Πλήρης Επιστροφή χρημάτων","roundDiffItemAdded":"Αντικείμενο στρογγυλοποίησης"},"refunds":{"title":"Επιστροφές στο Κέντρο Ελέγχου Mollie","linkMore":"Περισσότερα για τις επιστροφές χρημάτων","grid":{"columns":{"amount":"Ποσό","status":"Κατάσταση","description":"Περιγραφή","internalDescription":"Εσωτερική περιγραφή","composition":"Σύνθεση","date":"Ημερομηνία"},"lblNoComposition":"Δεν υπάρχει διαθέσιμη σύνθεση","btnCancelRefund":"Ακυρώστε αυτήν την επιστροφή χρημάτων"}},"notifications":{"success":{"refund-created":"Έχει δημιουργηθεί μια επιστροφή χρημάτων στη Mollie. Μπορεί να χρειαστούν 2 ώρες για να ολοκληρωθεί η επιστροφή. Μέχρι τότε, μπορείτε να ακυρώσετε την επιστροφή.","refund-canceled":"Η εκκρεμής επιστροφή έχει ακυρωθεί και αφαιρεθεί με επιτυχία."},"error":{"low-amount":"Παρακαλώ εισάγετε ποσό προς επιστροφή.","refund-created":"Κάτι πήγε στραβά κατά τη δημιουργία επιστροφής.","refund-canceled":"Υπήρξε πρόβλημα κατά την ακύρωση της εκκρεμούς επιστροφής. Παρακαλώ δοκιμάστε ξανά στο Κέντρο Ελέγχου Mollie."}}},"vouchers":{"CARD_TITLE":"Κουπόνι","VOUCHER_INFO_TITLE":"Πληρωμές με Κουπόνια","VOUCHER_INFO_DESCRIPTION":"Η Mollie σας επιτρέπει να δέχεστε εύκολα πληρωμές στο ηλεκτρονικό σας κατάστημα χρησιμοποιώντας οικολογικά κουπόνια, δωροκάρτες και κουπόνια για γεύματα—μια έξυπνη επιλογή για αύξηση πωλήσεων και ικανοποίηση των πελατών σας. Ο τρόπος πληρωμής \\"κουπόνι\\" είναι ορατός μόνο αν έχετε τουλάχιστον 1 προϊόν με ανατεθεί τύπο κουπονιού στο καλάθι.","VOUCHER_INFO_DEFAULTLANGUAGE":"Σημειώστε ότι αυτή η ρύθμιση μπορεί να επεξεργαστεί μόνο στην προεπιλεγμένη σας γλώσσα. Παρακαλώ αλλάξτε τη γλώσσα σας για να τροποποιήσετε τον τύπο κουπονιού αυτού του προϊόντος.","VOUCHER_BTN_READMORE":"Διαβάστε περισσότερα","VOUCHER_TYPE_CAPTION":"Τύπος κουπονιού προϊόντος","VOUCHER_TYPE_VALUE_NONE":"Κανένα","VOUCHER_TYPE_VALUE_ECO":"Οικολογικό","VOUCHER_TYPE_VALUE_MEAL":"Γεύμα","VOUCHER_TYPE_VALUE_VOUCHER":"Δώρο"},"modals":{"shipping":{"title":"Αποστολή μέσω Mollie","item":{"label":"Αντικείμενο:","noQuantity":"Παρακαλώ εισάγετε μία ποσότητα προς αποστολή.","shipAll":"Αποστολή όλων","summary":{"quantity":"Ποσότητα προς αποστολή","shipped":"Ποσότητα που απεστάλη","shippable":"Ποσότητα που μπορεί να αποσταλεί"},"success":"Η παραγγελία έχει αποσταλεί με επιτυχία."},"order":{"description":"Οι παρακάτω ποσότητες στοιχείων θα αποσταλούν.","itemHeader":"Αντικείμενο","quantityHeader":"Ποσότητα","originalQuantityHeader":"Ποσότητα (προοριζόμενη για αποστολή)"},"availableTracking":{"label":"Διαθέσιμοι κωδικοί παρακολούθησης","hint":"Κάντε κλικ σε έναν από αυτούς τους κωδικούς παρακολούθησης για να συμπληρώσετε αυτόματα όλα τα στοιχεία."},"showTracking":"Προσθήκη πληροφοριών παρακολούθησης για αυτή τη αποστολή","tracking":{"carrier":"Μεταφορέας","code":"Κωδικός","url":"Url","invalid":"Παρακαλώ εισάγετε τον Μεταφορέα και τον Κωδικό"},"confirmButton":"Αποστολή παραγγελίας","cancelButton":"Ακύρωση","selectAllButton":"Επιλογή όλων","resetButton":"Επαναφορά"},"cancel":{"title":"Ακύρωση στοιχείου μέσω mollie","confirmButton":"Ακύρωση στοιχείου μέσω mollie","cancelButton":"Κλείσιμο παραθύρου","resetStock":"Επαναφορά αποθεμάτων","item":{"success":"Το προϊόν ακυρώθηκε επιτυχώς","failed":{"quantityZero":"Η ποσότητα είναι 0","invalidLine":"Το προϊόν δεν υπάρχει στην παραγγελία","quantityTooHigh":"Η ποσότητα είναι πολύ υψηλή"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Αποστολή παραγγελίας (Mollie)","description":"Αποστολή παραγγελίας μέσω Mollie."},"modal":{"title":"Αποστολή Παραγγελίας","description":"Αυτή η ενέργεια θα αποστείλει αυτόματα μια παραγγελία μέσω Mollie. Η ακολουθία ροής θα λάβει τον αριθμό παραγγελίας και θα τον μεταφέρει στο API της Mollie. Οι επιτυχείς και αποτυχημένες αποστολές θα είναι ορατές στα αρχεία καταγραφής της Mollie.","warningConfig":"Παρακαλώ βεβαιωθείτε ότι έχετε απενεργοποιήσει οποιαδήποτε πρόσθετη αυτοματοποίηση για αυτό το είδος ενέργειας ώστε να αποφευχθούν τυχόν παρεμβολές.\\nΟι ακόλουθες ενεργοποιημένες δυνατότητες αυτού του πρόσθετου μπορεί να παρεμποδίσουν αυτή την ενέργεια:","noWarnings":"Καμία προειδοποίηση"}},"refundOrder":{"editor":{"title":"Επιστροφή Χρημάτων Παραγγελίας (Mollie)","description":"Επιστροφή χρημάτων παραγγελίας μέσω Mollie."},"modal":{"title":"Επιστροφή Χρημάτων Παραγγελίας","description":"Αυτή η ενέργεια θα ξεκινήσει αυτόματα μια επιστροφή μέσω Mollie. Η ακολουθία ροής θα λάβει τον αριθμό παραγγελίας και θα τον μεταφέρει στο API της Mollie. Οι επιτυχείς και αποτυχημένες επιστροφές θα είναι ορατές στα αρχεία καταγραφής της Mollie.","warning":"Παρακαλώ έχετε υπόψη ότι οι επιστροφές μπορεί να διαρκέσουν έως 2 ώρες για να ολοκληρωθούν και να φανούν στο κατάστημα. Μέχρι τότε μπορείτε πάντα να ακυρώσετε μια εκκρεμή επιστροφή είτε από τη σελίδα παραγγελίας στο Shopware είτε από το Κέντρο Ελέγχου Mollie.","warningConfig":"Παρακαλώ βεβαιωθείτε ότι έχετε απενεργοποιήσει οποιαδήποτε πρόσθετη αυτοματοποίηση για αυτό το είδος ενέργειας ώστε να αποφευχθούν τυχόν παρεμβολές."}},"warnings":{"automaticShipping":"Αυτόματη αποστολή στη διαμόρφωση του πρόσθετου"}}},"subscriptions":{"status":{"pending":"Εκκρεμεί","active":"Ενεργό","canceled":"Ακυρώθηκε","suspended":"Σε αναστολή","completed":"Ολοκληρώθηκε","paused":"Σε παύση","resumed":"Επαναφέρθηκε","skipped":"Παραλείφθηκε"},"navigation":{"title":"Συνδρομές Mollie"},"TYPE_DAYS":"Ημέρα/ές","TYPE_WEEKS":"Εβδομάδα/ές","TYPE_MONTHS":"Μήνας/ες","confirm":{"cancelTitle":"Τερματισμός συνδρομής;","cancel":"Ακυρώστε τη συνδρομή του πελάτη σας.","pauseTitle":"Πάυση συνδρομής;","pause":"Βάλτε τη συνδρομή σε αναμονή μέχρι να την επαναφέρετε.","resumeTitle":"Επαναφορά συνδρομής;","resume":"Συνεχίστε ξανά τη συνδρομή.","skipTitle":"Παραλείψτε την επόμενη δόση;","skip":"Παραλείψτε την επόμενη δόση σε αυτή τη συνδρομή. Θα συνεχιστεί αυτόματα μετά."},"alerts":{"cancelSuccess":"Η συνδρομή ακυρώθηκε επιτυχώς","pauseSuccess":"Η συνδρομή παύθηκε επιτυχώς","resumeSuccess":"Η συνδρομή έχει επαναφερθεί επιτυχώς","skipSuccess":"Η συνδρομή παραλείφθηκε επιτυχώς. Η επόμενη πληρωμή έχει ενημερωθεί."},"list":{"title":"Συνδρομές Mollie","columns":{"customer":"Πελάτης","status":"Κατάσταση","description":"Περιγραφή","amount":"Ποσό","nextPaymentAt":"Επόμενη πληρωμή","prePaymentReminder":"Υπενθύμιση στις","canceledAt":"Ακυρώθηκε στις","createdAt":"Δημιουργήθηκε στις"},"action":{"edit":"Επεξεργασία συνδρομής"},"deletedCustomer":"Διαγραμμένος πελάτης"},"detail":{"title":"Συνδρομή Mollie","buttonCancelSubscription":"Ακύρωση συνδρομής","labelDescription":"Περιγραφή","labelAmount":"Ποσό","labelQuantity":"Ποσότητα","labelMollieSubscription":"Συνδρομή Mollie","labelMollieCustomer":"Πελάτης Mollie","labelMandateId":"Εντολή","labelShopwareCustomer":"Πελάτης Shopware","labelCreatedAt":"Δημιουργήθηκε στις","buttonShowShopwareOrder":"Εμφάνιση παραγγελίας Shopware","buttonShowShopwareCustomer":"Εμφάνιση πελάτη Shopware","cardTitleSubscription":"Συνδρομή","cardTitleStatus":"Κατάσταση","labelStatus":"Κατάσταση","labelNextPaymentAt":"Επόμενη πληρωμή στις","labelLastRemindedAt":"Τελευταία υπενθύμιση στις","labelCanceledAt":"Ακυρώθηκε στις","buttonPauseSubscription":"Παύση συνδρομής","buttonResumeSubscription":"Επαναφορά συνδρομής","buttonSkipSubscription":"Παράλειψη συνδρομής","history":{"cardTitle":"Ιστορικό","colDate":"Ημερομηνία","colComment":"Σχόλιο","colStatusFrom":"Κατάσταση (από)","colStatusTo":"Κατάσταση (σε)","colMollieSubscription":"Συνδρομή Mollie"}},"product":{"card-title":"Συνδρομή","title":"Συνδρομές Mollie","description":"Η διαχείριση των επαναλαμβανόμενων πληρωμών σας είναι πιο εύκολη από ποτέ με τις βοηθητικές δυνατότητες μας. Ανεβάστε την επιχείρησή σας σε νέο επίπεδο με αποτελεσματικές επιλογές παρακολούθησης, απλές ενσωματώσεις και πολλά άλλα. Με τις συνδρομές Mollie, μπορείτε εύκολα να δημιουργήσετε προϊόντα συνδρομής και να προγραμματίσετε επαναλαμβανόμενες πληρωμές που θα γίνονται στο καθορισμένο διάστημα και διάρκεια.","mollieSubscriptionProduct":"Προϊόν Συνδρομής","mollieSubscriptionIntervalAmount":"Επανάληψη πληρωμής κάθε","mollieSubscriptionIntervalType":"Μονάδα διαστήματος","mollieSubscriptionRepetitionAmount":"Αριθμός επαναλήψεων","mollieSubscriptionRepetitionPlaceholder":"Εισάγετε αριθμό ή αφήστε κενό","infoDefaultLanguage":"Σημειώστε ότι αυτή η ρύθμιση μπορεί να επεξεργαστεί μόνο στην προεπιλεγμένη γλώσσα σας. Αλλάξτε τη γλώσσα σας για να τροποποιήσετε τις ρυθμίσεις συνδρομής αυτού του προϊόντος.","btnReadMore":"Διαβάστε περισσότερα"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Συνδρομή"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Δεδομένα πιστωτικής κάρτας","buttonMolliePaymentLink":"Αντιγραφή στο πρόχειρο","columnRefunded":"Επιστράφηκε","columnShipped":"Απεστάλη","columnCanceled":"Ακυρώθηκε","labelMollieOrderId":"Αναγνωριστικό παραγγελίας Mollie","labelMollieThirdPartyPaymentId":"Αναφορά πληρωμής","labelMolliePaymentLink":"Διεύθυνση URL για Ταμείο Mollie","totalRefunds":"Επιστραφέν ποσό","totalRefundsPending":"Αναμονή για επιστροφή χρημάτων","totalRemaining":"Επιστρεπτέο ποσό","totalVouchers":"Ποσό κουπονιού","totalShipments":"Ποσό που απεστάλη ({quantity} αντικείμενα)","subscriptionBadge":"Παραγγελία Συνδρομής","refundManager":{"title":"Διαχειριστής Επιστροφών Mollie","btnOpenRefundManager":"Άνοιγμα Διαχειριστή Επιστροφών","btnCloseRefundManager":"Κλείσιμο Διαχειριστή Επιστροφών"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Προτιμώμενος εκδότης iDeal"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Διαχειριστής Επιστροφών"},"mollie_subscription":{"label":"Συνδρομές"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Περιγραφή"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Επιστροφή χρημάτων","subscription":"Συνδρομή","webhookReceived":"Webhooks","status":"Κατάσταση","started":"Ξεκίνησε","ended":"Έληξε","paused":"Σε παύση","renewalReminder":"Υπενθύμιση Ανανέωσης","renewed":"Ανανεώθηκε","resumed":"Επαναφέρθηκε","skipped":"Παραλείφθηκε","all":"Όλα","canceled":"Ακυρωμένο","expired":"Έληξε","partiallyRefunded":"Επιστράφηκε (μερικώς)","orderSuccess":"Η παραγγελία ήταν επιτυχής","orderFailed":"Η παραγγελία απέτυχε","orderCanceled":"Η παραγγελία ακυρώθηκε"}}}'),e8=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie pretplata | Mollie pretplate"},"businessEvents":{"mollie_checkout_order_success":" Narudžba uspješna","mollie_checkout_order_failed":" Narudžba neuspjela","mollie_checkout_order_canceled":" Narudžba otkazana","mollie_webhook_received_All":" Mollie Webhook Primljen (Svi)","mollie_webhook_received_status_authorized":" Mollie Webhook Primljen (Autorizirano)","mollie_webhook_received_status_failed":" Mollie Webhook Primljen (Neuspjelo)","mollie_webhook_received_status_canceled":" Mollie Webhook Primljen (Otkazano)","mollie_webhook_received_status_expired":" Mollie Webhook Primljen (Isteklo)","mollie_webhook_received_status_pending":" Mollie Webhook Primljen (Na čekanju)","mollie_webhook_received_status_paid":" Mollie Webhook Primljen (Plaćeno)","mollie_webhook_received_status_completed":" Mollie Webhook Primljen (Završeno)","mollie_webhook_received_status_refunded":" Mollie Webhook Primljen (Vraćeno)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook Primljen (Djelomično Vraćeno)","mollie_refund_started":" Mollie povrat započet","mollie_subscription_started":" Mollie pretplata započeta","mollie_subscription_ended":" Mollie pretplata završena","mollie_subscription_cancelled":" Mollie pretplata otkazana","mollie_subscription_paused":" Mollie pretplata pauzirana","mollie_subscription_resumed":" Mollie pretplata nastavljena","mollie_subscription_skipped":" Mollie pretplata preskočena","mollie_subscription_renewed":" Mollie pretplata obnovljena","mollie_subscription_renewal_reminder":" Mollie podsjetnik za obnovu pretplate"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Pretraži pretplate...","general":{"mainMenuItemGeneral":"Mollie Plaćanja","descriptionTextModule":"Mollie Plaćanja","btnMollieActions":"Mollie Radnje","refundThroughMollie":"Vrati putem Mollieja","shipThroughMollie":"Isporuka putem Mollieja","cancelMollieItem":"Otkazuj putem Mollie"},"config":{"info":{"title":"Bok {userName}, Dobrodošli u Mollie!","descriptionTop":"Uključivanje je jednostavno s Mollie!","descriptionBottom":"To je to!","descriptionFooter":"Ako želite saznati više o našem dodatku, posjetite našu službenu stranicu s dokumentacijom.","onboardingStep1":"Prijavite se za Mollie račun.","onboardingStep2":"Unesite API ključeve u sekciji ispod.","onboardingStep2TestMode":"Uključite \'Test Mode\' ako želite samo testirati plaćanja.","onboardingStep3":"Dodijelite metode plaćanja svojim prodajnim kanalima.","onboardingStep3Link":"na vaše prodajne kanale","btnDocumentation":"Dokumentacija","btnRequestSupport":"Podrška","btnTroubleshooting":"Vodič za rješavanje problema"},"api":{"apiLinkButton":"Preuzmite API ključeve iz Mollie Nadzorne ploče","testButton":"Test API ključevi","testApiKeys":{"title":"Mollie Plaćanja","apiKey":"API ključ","isValid":"je valjan","isInvalid":"je nevažeći"}},"payments":{"format":{"placeholder":"Rezervirano mjesto","preview":"Pregled"},"updatePaymentMethods":{"title":"Mollie Plaćanja","button":"Ažuriraj metode plaćanja","succeeded":"Metode plaćanja su uspješno ažurirane.","failed":"Metode plaćanja nije bilo moguće ažurirati."},"mollieLimits":{"link":"Prikaži mollie pravila dostupnosti za metode plaćanja"}},"rounding":{"info1":"Shopware može koristiti postavke valute za izračun načina zaokruživanja ukupnog iznosa narudžbe. To uključuje broj decimala u cijenama proizvoda i najbliži interval zaokruživanja, kao što su 0,50 ili 1,00.","info2":"Ove postavke mogu dovesti do toga da se ukupni iznos razlikuje od zbroja svih stavki. Kada Mollie usporedi te iznose i utvrdi da se ne podudaraju, dolazi do pogreške pri naplati.","info3":"Ovu značajku možete koristiti kako biste izbjegli probleme sa zaokruživanjem tijekom naplate. Kada je omogućena, u Mollie nadzornoj ploči dodaje se zasebna stavka za razliku zbog zaokruživanja, a vaši kupci plaćaju ukupni iznos koji izračuna Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nije moguće koristiti Klarna Pay now, Klarna Slice it ili Klarna Pay later kao metodu kada je vaš datum isteka više od 28 dana u budućnosti, osim ako se trgovac i Klarna ne dogovore drugačije.","bankTransferDueDateLimitReached":"Nije moguće postaviti trajanje narudžbe više od 100 dana."},"support":{"modalTitle":"Zatražite podršku od Mollie","btnCancel":"Otkaži","btnConfirm":"Zatraži podršku","btnSupport":"Više o našoj podršci","form":{"name":"Vaše ime","email":"Vaša email adresa","recipient":"Pošalji upit na","subject":"Predmet","message":"Poruka"},"data":{"header":"Podaci poslani Mollieju:","other":"Drugo:","shopwareVersion":"Shopware verzija","pluginLogs":"{plugin} log datoteke","pluginConfiguration":"{plugin} konfiguracija","pluginConfigurationHelpText":"API ključevi su isključeni.","paymentMethods":"Podaci o načinu plaćanja","paymentMethodsHelpText":"Sadrži informacije o tome koji načini plaćanja su aktivni, dodijeljeni svakom prodajnom kanalu, kao i njihov status na vašem Mollie računu."},"success":"Zahtjev za podršku je uspješno poslan. Dajemo sve od sebe kako bismo odgovorili što je brže moguće","error":"Došlo je do problema prilikom slanja e-pošte putem Shopware-a. Molimo pokušajte ponovno ili nas kontaktirajte izravno putem e-pošte."}},"rules":{"itemSubscriptionRule":"Stavka je pretplata (Mollie)","cartSubscriptionRule":"Košarica s pretplatama (Mollie)"},"refunds":{"status":{"queued":"U redu čekanja","pending":"Na čekanju","processing":"U obradi","refunded":"Vraćeno","failed":"Neuspjelo","description":{"queued":"Povrat je stavljen u red čekanja dok ne bude dovoljno sredstava na saldu za obradu povrata. Povrat i dalje možete otkazati.","pending":"Povrat će biti poslan u banku sljedeći radni dan. Još uvijek možete otkazati povrat.","processing":"Povrat je poslan u banku. Iznos povrata bit će prebačen na račun potrošača što je prije moguće.","refunded":"Iznos povrata je prenesen potrošaču.","failed":"Povrat nije uspio nakon obrade. Na primjer, kupac je zatvorio svoj bankovni račun. Sredstva će biti vraćena na vaš račun."}}},"refund-manager":{"general":{"unitQuantity":"kom."},"acl":{"warningCreate":"Nemate dopuštenje za kreiranje povrata","warningCancel":"Nemate dopuštenje za otkazivanje povrata"},"cart":{"title":"Narudžba ##orderNumber##","btnSelectAll":"Označi sve","btnResetForm":"Resetiraj obrazac","linkHowTo":"Kako koristiti ovaj obrazac?","grid":{"columns":{"item":"Stavka","productNumber":"Broj proizvoda","unitPrice":"Jedinična cijena","quantity":"Količina","refunded":"Vraćeno","refundQuantity":"Povrat","totalPrice":"Ukupno","refundAmount":"Povrat","resetStock":"Vrati zalihe"},"btnResetLine":"Resetiraj redak","checkDeductPromotion":"Oduzmi promociju","checkRefundTax":"Povrat PDV-a"},"roundDiffItemAdded":"Automatski dodano zaokruživanje stavke"},"instructions":{"linkResetTutorials":"Resetiraj vodiče","btnToggleTutorial":"Prikaži/Sakrij Vodič","titleFullRefund":"Puni povrat","textFullRefund":"Jednostavno upotrijebite gumb za puni povrat. Time se osigurava da su sve stavke označene kao refundirane i da se kupcu vraća puni iznos.","titleStockReset":"Resetiranje zaliha","textStockReset":"Možete automatski povećati dostupnu zalihu unosom količine koju želite vratiti na zalihu. Samo unesite količinu prije nastavka s punim ili djelomičnim povratom. Vraćanje zaliha može se fleksibilno kombinirati sa samim postupkom povrata.","titleShipping":"Otprema","textShipping":"Stavke dostave mogu se refundirati kao i bilo koja druga stavka proizvoda. Unesite punu količinu ili prilagođeni djelomični iznos i nastavite s povratom. Povrat troškova dostave može se fleksibilno kombinirati sa samim postupkom povrata stavki.","titlePartialAmount":"Djelomični povrat (samo iznos)","textPartialAmount":"Samo unesite djelomični iznos u tekstualno polje i započnite povrat.","titlePartialItems":"Djelomični povrat (s predmetima)","textPartialItems":"Ako želite označiti količine i stavke kao refundirane u Mollie, upotrijebite gornji obrazac. Postavite količine i unesite prilagođeni iznos za svaku stavku koja će biti refundirana. Ukupni zbroj zatim će biti prikazan u polju za konačni iznos povrata. Imajte na umu da je taj konačni iznos i dalje moguće prilagoditi prije pokretanja povrata.","titlePartialPromotions":"Djelomični povrat (s promocijama)","textPartialPromotions":"Ako imate promociju u košarici, ona se prikazuje kao zasebna stavka. Ako želite refundirati sve snižene stavke, refundirajte njihove ukupne vrijednosti i samu stavku promocije u cijelosti. Međutim, ako želite refundirati samo neke stavke koje su bile snižene, možete automatski odbiti primijenjeni popust za svaku pojedinačnu stavku. Naravno, uvijek možete ručno promijeniti vrijednosti ako nisu točne.","titleRoundingDiff":"Razlika u zaokruživanju","textRoundingDiff":"Puni povrat uključit će razlike u zaokruživanju"},"summary":{"dataLoading":"Podaci se učitavaju...","headerExcludingVat":"Bez PDV-a","headerIncludingVat":"S PDV-om","captionTotal":"Ukupno","captionTotalTaxFree":"Ukupno","captionPendingRefunds":"Čeka na povrat","captionVouchers":"Iznos vaučera","captionRefunded":"Vraćeni iznos","captionRemaining":"Iznos za povrat","btnFixDiff":"Popravite razliku","placeholderDescription":"Unesite opis za bankovni/računski izvod potrošača. Maksimalno 140 znakova","lblDescription":"Opis (nije obavezno) ({characters}/140 znakova)","descriptionHelp":"Ovo će biti prikazano na bankovnom ili kartičnom izvodu potrošača kada je moguće. Poruka će biti skraćena na 140 znakova.","placeholderInternalDescription":"Unesite vaš interni opis","lblInternalDescription":"Interni opis (opcionalno)","internalDescriptionHelp":"Ovo će se prikazati kao lokalni opis u administracijskom sučelju.","checkVerification":"Potvrdio sam ukupan iznos povrata i konfigurirane količine za povrat i ponovno skladištenje.","btnRefund":"Povrat","btnFullRefund":"Puni povrat","roundDiffItemAdded":"Povrat razlike u zaokruživanju"},"refunds":{"title":"Povrati u Mollie nadzornoj ploči","linkMore":"Više o povratima","grid":{"columns":{"amount":"Iznos","status":"Status","description":"Opis","internalDescription":"Unutarnji opis","composition":"Sastav","date":"Datum"},"lblNoComposition":"Sastav nije dostupan","btnCancelRefund":"Otkaži ovaj povrat"}},"notifications":{"success":{"refund-created":"Povrat je kreiran na Mollie. Može potrajati do 2 sata da se povrat dovrši. Za to vrijeme možete otkazati povrat.","refund-canceled":"Očekivani povrat uspješno je otkazan i uklonjen."},"error":{"low-amount":"Unesite iznos za povrat.","refund-created":"Nešto je pošlo po zlu pri kreiranju povrata.","refund-canceled":"Došlo je do problema pri otkazivanju očekivanog povrata. Molimo pokušajte ponovo u Mollie upravljačkoj ploči."}}},"vouchers":{"CARD_TITLE":"Vaučer","VOUCHER_INFO_TITLE":"Plaćanja vaučerima","VOUCHER_INFO_DESCRIPTION":"Mollie vam omogućuje jednostavno prihvaćanje plaćanja u vašoj online trgovini putem eko-bonova, poklon bonova i bonova za obrok — pametan izbor za povećanje prodaje i zadovoljstvo kupaca. Način plaćanja „bon” vidljiv je samo ako se u košarici nalazi barem jedan proizvod s dodijeljenom vrstom bona.","VOUCHER_INFO_DEFAULTLANGUAGE":"Napomena: Ovu konfiguraciju možete uređivati samo na zadanom jeziku. Promijenite jezik kako biste izmijenili vrstu bona za ovaj proizvod.","VOUCHER_BTN_READMORE":"Pročitaj više","VOUCHER_TYPE_CAPTION":"Tip vaučera proizvoda","VOUCHER_TYPE_VALUE_NONE":"Bez","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Obrok","VOUCHER_TYPE_VALUE_VOUCHER":"Poklon"},"modals":{"shipping":{"title":"Otpremi putem Mollie","item":{"label":"Stavka:","noQuantity":"Unesite količinu za otpremu.","shipAll":"Otpremi sve","summary":{"quantity":"Količina za otpremu","shipped":"Količina otpremljena","shippable":"Količina za otpremu"},"success":"Narudžba je uspješno otpremljena."},"order":{"description":"Sljedeće količine artikala će biti otpremljene.","itemHeader":"Stavka","quantityHeader":"Količina","originalQuantityHeader":"Količina (pošiljka moguća)"},"availableTracking":{"label":"Dostupni kodovi za praćenje","hint":"Kliknite na jedan od tih kodova za praćenje kako biste automatski popunili sve podatke."},"showTracking":"Dodajte podatke o praćenju za ovu pošiljku","tracking":{"carrier":"Dostavljač","code":"Kod","url":"Url","invalid":"Unesite i dostavljača i kod"},"confirmButton":"Otpremi narudžbu","cancelButton":"Otkaži","selectAllButton":"Odaberi sve","resetButton":"Poništi"},"cancel":{"title":"Otkaži stavku putem Mollie","confirmButton":"Otkaži stavku putem Mollie","cancelButton":"Zatvori modal","resetStock":"Ponovno postavi zalihe","item":{"success":"Proizvod uspješno otkazan","failed":{"quantityZero":"Količina je 0","invalidLine":"Proizvod ne postoji u narudžbi","quantityTooHigh":"Količina je previsoka"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Otpremi narudžbu (Mollie)","description":"Otpremi narudžbu u Mollie."},"modal":{"title":"Otpremi narudžbu","description":"Ova radnja automatski će kreirati pošiljku za narudžbu putem Mollie. Sekvenca tijeka primit će broj narudžbe i proslijediti ga Mollie API-ju. Uspješne i neuspješne pošiljke bit će vidljive u Mollie log datotekama.","warningConfig":"Molimo provjerite da ste isključili svu dodatnu automatizaciju za ovu vrstu radnje kako biste izbjegli moguće smetnje.\\nSljedeće aktivirane značajke ovog dodatka mogu ometati ovu radnju:","noWarnings":"Nema upozorenja"}},"refundOrder":{"editor":{"title":"Povrat narudžbe (Mollie)","description":"Povrat narudžbe putem Mollie."},"modal":{"title":"Povrat narudžbe","description":"Ova radnja automatski će pokrenuti povrat putem Mollie. Sekvenca tijeka primit će broj narudžbe i proslijediti ga Mollie API-ju. Uspješni i neuspješni povrati bit će vidljivi u Mollie log datotekama.","warning":"Imajte na umu da povrat može potrajati do 2 sata dok se ne dovrši i ne postane vidljiv u trgovini. Do tada uvijek možete otkazati povrat na čekanju, bilo na stranici narudžbe u Shopwareu ili u Mollie nadzornoj ploči.","warningConfig":"Molimo provjerite da ste isključili svu dodatnu automatizaciju za ovu vrstu radnje kako biste izbjegli moguće smetnje."}},"warnings":{"automaticShipping":"Automatska otprema u konfiguraciji dodatka"}}},"subscriptions":{"status":{"pending":"Na čekanju","active":"Aktivno","canceled":"Otkazano","suspended":"Suspendirano","completed":"Završeno","paused":"Pauzirano","resumed":"Nastavljeno","skipped":"Preskočeno"},"navigation":{"title":"Mollie Pretplate"},"TYPE_DAYS":"Dan(i)","TYPE_WEEKS":"Tjedni","TYPE_MONTHS":"Mjeseci","confirm":{"cancelTitle":"Prekinuti pretplatu?","cancel":"Otkažite pretplatu vašeg korisnika.","pauseTitle":"Pauziraj pretplatu?","pause":"Stavite pretplatu na čekanje dok je ponovo ne nastavite.","resumeTitle":"Nastavi pretplatu?","resume":"Nastavite pretplatu ponovno.","skipTitle":"Preskoči sljedeću uplatu?","skip":"Preskočite sljedeću uplatu u pretplati. Nastavak se odvija automatski nakon toga."},"alerts":{"cancelSuccess":"Pretplata je uspješno otkazana","pauseSuccess":"Pretplata je uspješno pauzirana","resumeSuccess":"Pretplata je uspješno nastavljena","skipSuccess":"Pretplata je uspješno preskočena. Sljedeća uplata je ažurirana."},"list":{"title":"Mollie pretplate","columns":{"customer":"Korisnik","status":"Status","description":"Opis","amount":"Iznos","nextPaymentAt":"Sljedeća uplata","prePaymentReminder":"Podsjetnik poslan","canceledAt":"Otkazano","createdAt":"Kreirano"},"action":{"edit":"Uredite pretplatu"},"deletedCustomer":"Obrisani korisnik"},"detail":{"title":"Mollie pretplata","buttonCancelSubscription":"Otkazivanje pretplate","labelDescription":"Opis","labelAmount":"Iznos","labelQuantity":"Količina","labelMollieSubscription":"Mollie pretplata","labelMollieCustomer":"Mollie korisnik","labelMandateId":"Mandat","labelShopwareCustomer":"Shopware korisnik","labelCreatedAt":"Kreirano","buttonShowShopwareOrder":"Prikaži Shopware narudžbu","buttonShowShopwareCustomer":"Prikaži Shopware korisnika","cardTitleSubscription":"Pretplata","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Sljedeća uplata","labelLastRemindedAt":"Posljednji podsjetnik","labelCanceledAt":"Otkazano","buttonPauseSubscription":"Pauziraj pretplatu","buttonResumeSubscription":"Nastavi pretplatu","buttonSkipSubscription":"Preskoči pretplatu","history":{"cardTitle":"Povijest","colDate":"Datum","colComment":"Komentar","colStatusFrom":"Status (od)","colStatusTo":"Status (do)","colMollieSubscription":"Mollie pretplata"}},"product":{"card-title":"Pretplata","title":"Mollie pretplate","description":"Upravljanje ponavljajućim plaćanjima lakše je nego ikad uz naše korisne značajke. Podignite svoje poslovanje na višu razinu uz učinkovite opcije praćenja, jednostavne integracije i još mnogo toga. Uz Mollie pretplate možete jednostavno kreirati pretplatničke proizvode i zakazati ponavljajuća plaćanja koja će se izvršavati prema postavljenom intervalu i razdoblju.","mollieSubscriptionProduct":"Pretplatnički proizvod","mollieSubscriptionIntervalAmount":"Ponavljaj uplatu svaki","mollieSubscriptionIntervalType":"Jedinica intervala","mollieSubscriptionRepetitionAmount":"Broj ponavljanja","mollieSubscriptionRepetitionPlaceholder":"Unesite broj ili ostavite prazno","infoDefaultLanguage":"Napomena: Ovu konfiguraciju možete uređivati samo na zadanom jeziku. Promijenite jezik kako biste izmijenili postavke pretplate za ovaj proizvod.","btnReadMore":"Pročitaj više"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Pretplata"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Podaci o kreditnoj kartici","buttonMolliePaymentLink":"Kopiraj u međuspremnik","columnRefunded":"Vraćeno","columnShipped":"Dostavljeno","columnCanceled":"Otkazano","labelMollieOrderId":"Mollie ID narudžbe","labelMollieThirdPartyPaymentId":"Referenca plaćanja","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Refundirani iznos","totalRefundsPending":"Čeka na povrat novca","totalRemaining":"Iznos koji se može refundirati","totalVouchers":"Iznos vaučera","totalShipments":"Dostavljeni iznos ({quantity} stavki)","subscriptionBadge":"Narudžba s pretplatom","refundManager":{"title":"Mollie Upravitelj povrata","btnOpenRefundManager":"Otvori Upravitelja povrata","btnCloseRefundManager":"Zatvori Upravitelja povrata"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Preferirani iDEAL izdavatelj"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Upravitelj povrata"},"mollie_subscription":{"label":"Pretplate"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Opis"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Povrat novca","subscription":"Pretplata","webhookReceived":"Webhookovi","status":"Status","started":"Početo","ended":"Završeno","paused":"Pauzirano","renewalReminder":"Podsjetnik za obnovu","renewed":"Obnovljeno","resumed":"Nastavljeno","skipped":"Preskočeno","all":"Sve","canceled":"Otkazano","expired":"Isteklo","partiallyRefunded":"Vraćeno (djelomično)","orderSuccess":"Narudžba uspješna","orderFailed":"Narudžba nije uspjela","orderCanceled":"Narudžba otkazana"}}}'),e7=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie tellimus | Mollie tellimused"},"businessEvents":{"mollie_checkout_order_success":"Tellimus edukas","mollie_checkout_order_failed":"Tellimus eba\xf5nnestus","mollie_checkout_order_canceled":"Tellimus t\xfchistatud","mollie_webhook_received_All":" Mollie Veebikonks Saadud (K\xf5ik)","mollie_webhook_received_status_authorized":" Mollie Veebikonks Saadud (Volitatud)","mollie_webhook_received_status_failed":" Mollie Veebikonks Saadud (Eba\xf5nnestunud)","mollie_webhook_received_status_canceled":" Mollie Veebikonks Saadud (T\xfchistatud)","mollie_webhook_received_status_expired":" Mollie Veebikonks Saadud (Aegunud)","mollie_webhook_received_status_pending":" Mollie Veebikonks Saadud (Ootel)","mollie_webhook_received_status_paid":" Mollie Veebikonks Saadud (Makstud)","mollie_webhook_received_status_completed":" Mollie Veebikonks Saadud (L\xf5petatud)","mollie_webhook_received_status_refunded":" Mollie Veebikonks Saadud (Tagastatud)","mollie_webhook_received_status_partially_refunded":" Mollie Veebikonks Saadud (Osaliselt tagastatud)","mollie_refund_started":" Mollie tagasimakse algatatud","mollie_subscription_started":" Mollie tellimus alustatud","mollie_subscription_ended":" Mollie tellimus l\xf5petatud","mollie_subscription_cancelled":" Mollie tellimus t\xfchistatud","mollie_subscription_paused":" Mollie tellimus peatatud","mollie_subscription_resumed":" Mollie tellimus taask\xe4ivitatud","mollie_subscription_skipped":" Mollie tellimus vahele j\xe4etud","mollie_subscription_renewed":" Mollie tellimus uuendatud","mollie_subscription_renewal_reminder":" Mollie meeldetuletus tellimuse uuendamiseks"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie moodul","searchPlaceholder":"Otsi tellimusi...","general":{"mainMenuItemGeneral":"Mollie maksed","descriptionTextModule":"Mollie maksed","btnMollieActions":"Mollie tegevused","refundThroughMollie":"Tagasta l\xe4bi Mollie","shipThroughMollie":"Saada l\xe4bi Mollie","cancelMollieItem":"T\xfchista l\xe4bi Mollie"},"config":{"info":{"title":"Tere {userName}, Tere tulemast Molliesse!","descriptionTop":"Molliega liitumine on lihtne!","descriptionBottom":"Ongi k\xf5ik!","descriptionFooter":"Kui soovid meie pluginast rohkem teada, k\xfclasta meie ametlikku dokumentatsioonilehte.","onboardingStep1":"Registreeri Mollie konto.","onboardingStep2":"Sisesta oma API v\xf5tmed allolevas jaotises.","onboardingStep2TestMode":"L\xfclita sisse \'Testimisrežiim\', kui soovid makseid ainult katsetada.","onboardingStep3":"M\xe4\xe4ra makseviisid oma m\xfc\xfcgikanalitele.","onboardingStep3Link":"oma m\xfc\xfcgikanalitele","btnDocumentation":"Dokumentatsioon","btnRequestSupport":"Tugi","btnTroubleshooting":"T\xf5rkeotsingu juhend"},"api":{"apiLinkButton":"Hankige oma API v\xf5tmed Mollie t\xf6\xf6laualt","testButton":"Testi API v\xf5tmeid","testApiKeys":{"title":"Mollie maksed","apiKey":"API v\xf5ti","isValid":"kehtib","isInvalid":"on kehtetu"}},"payments":{"format":{"placeholder":"Kohat\xe4ide","preview":"Eelvaade"},"updatePaymentMethods":{"title":"Mollie maksed","button":"Uuenda makseviise","succeeded":"Makseviisid on edukalt uuendatud.","failed":"Makseviise ei saanud uuendada."},"mollieLimits":{"link":"N\xe4ita makseviiside k\xe4ttesaadavuse reegleid"}},"rounding":{"info1":"Shopware v\xf5ib kasutada valuuta seadeid, et arvutada, kuidas \xfcmardada tellimuse kogusumma. See h\xf5lmab toote hinna k\xfcmnendkohtade arvu ja l\xe4hima \xfcmardamisintervalli, n\xe4iteks 0,50 v\xf5i 1,00.","info2":"Need seaded v\xf5ivad viia erineva kogusummani kui ridaelementide kogusumma. Kui Mollie kontrollib neid summasid ja leiab, et need ei klapi, tekitab see kassas vea.","info3":"V\xf5id kasutada seda funktsiooni, et v\xe4ltida \xfcmardamise probleeme kassas. Kui see on lubatud, lisab see sinu Mollie t\xf6\xf6lauale eraldi reaelemendi tasakaaluvahe jaoks, ja sinu kliendid maksavad Shopware\'i arvutatud kogusumma."},"order":{"bankTransferDueDateKlarnaLimitReached":"Klarna Pay now, Klarna Slice it v\xf5i Klarna Pay later makseviisi kasutamine ei ole v\xf5imalik, kui teie makset\xe4htaeg on rohkem kui 28 p\xe4eva tulevikus, v\xe4lja arvatud juhul, kui kaupmees ja Klarna on kokku leppinud teises maksimumsummas.","bankTransferDueDateLimitReached":"Tellimuse kehtivusaega ei ole v\xf5imalik m\xe4\xe4rata pikemaks kui 100 p\xe4eva."},"support":{"modalTitle":"Palu Mollielt abi","btnCancel":"T\xfchista","btnConfirm":"Palu abi","btnSupport":"Rohkem meie toe kohta","form":{"name":"Sinu nimi","email":"Sinu e-post","recipient":"Saada taotlus aadressile","subject":"Teema","message":"S\xf5num"},"data":{"header":"Molliele saadetud andmed:","other":"Muud:","shopwareVersion":"Shopware\'i versioon","pluginLogs":"{plugin} logifailid","pluginConfiguration":"{plugin} konfigureerimine","pluginConfigurationHelpText":"API v\xf5tmed on v\xe4listatud.","paymentMethods":"Makseviisi andmed","paymentMethodsHelpText":"Sisaldab teavet selle kohta, millised makseviisid on aktiivsed, millistele m\xfc\xfcgikanalitele need on m\xe4\xe4ratud ning milline on nende staatus sinu Mollie kontol."},"success":"Toetuse taotlus on edukalt saadetud. Teeme oma parima, et vastata v\xf5imalikult kiiresti","error":"E-kirja saatmisel Shopware\'i kaudu ilmnes probleem. Palun proovi uuesti v\xf5i v\xf5ta meiega otse \xfchendust e-posti teel."}},"rules":{"itemSubscriptionRule":"Toode on tellimus (Mollie)","cartSubscriptionRule":"Ostukorv tellimustega (Mollie)"},"refunds":{"status":{"queued":"J\xe4rjekorras","pending":"Ootel","processing":"T\xf6\xf6tlemisel","refunded":"Tagastatud","failed":"Eba\xf5nnestunud","description":{"queued":"Tagasimakse on j\xe4rjekorras, kuni saldo on piisav tagasimakse t\xf6\xf6tlemiseks. Sa saad endiselt tagasimakse t\xfchistada.","pending":"Tagasimakse saadetakse panka j\xe4rgmisel t\xf6\xf6p\xe4eval. Sa saad endiselt tagasimakse t\xfchistada.","processing":"Tagasimakse on saadetud panka. Tagastatav summa kantakse tarbija kontole niipea kui v\xf5imalik.","refunded":"Tagasimakstud summa on kantud tarbijale.","failed":"Tagasimakse eba\xf5nnestus p\xe4rast t\xf6\xf6tlemist. N\xe4iteks on klient sulgenud oma pangakonto. Raha tagastatakse sinu kontole."}}},"refund-manager":{"general":{"unitQuantity":"tk."},"acl":{"warningCreate":"Sul pole \xf5igust tagasimakseid teha","warningCancel":"Sul pole \xf5igust tagasimakseid t\xfchistada"},"cart":{"title":"Tellimus ##orderNumber##","btnSelectAll":"Vali k\xf5ik","btnResetForm":"Vormi l\xe4htestamine","linkHowTo":"Kuidas seda vormi kasutada?","grid":{"columns":{"item":"Ese","productNumber":"Toote number","unitPrice":"\xdchikuhind","quantity":"Kogus","refunded":"Tagastatud","refundQuantity":"Tagasimakse","totalPrice":"Kokku","refundAmount":"Tagasimakse","resetStock":"L\xe4htesta varud"},"btnResetLine":"L\xe4htesta read","checkDeductPromotion":"Eemalda allahindlus","checkRefundTax":"Tagasta k\xe4ibemaks"},"roundDiffItemAdded":"Lisati automaatne \xfcmardamisartikkel"},"instructions":{"linkResetTutorials":"Juhendite l\xe4htestamine","btnToggleTutorial":"N\xe4ita/Peida juhendid","titleFullRefund":"T\xe4ielik tagasimakse","textFullRefund":"Kasuta lihtsalt nuppu t\xe4ieliku tagasimakse saamiseks. See tagab, et k\xf5ik sinu kaubad m\xe4rgitakse tagastatuks ja kogu summa tagastatakse kliendile.","titleStockReset":"Varude l\xe4htestamine","textStockReset":"Sa saad automaatselt suurendada saadaval olevaid varusid, sisestades koguse, mida soovid varudesse lisada. Lihtsalt sisesta see enne kui j\xe4tkad t\xe4is- v\xf5i osalise tagasimakse tegemisega. Varude taastamist saab paindlikult kombineerida tegeliku tagasimaksete protsessiga.","titleShipping":"Saatmine","textShipping":"Saatmisartikleid saab tagastada nagu igat muud tootet. Sisesta t\xe4ielik kogus v\xf5i eraldi osaline summa ja j\xe4tka tagasimakset. Saate kulude h\xfcvitamise paindlikult kombineerida toodete tegeliku tagastamisega.","titlePartialAmount":"Osaline tagasimakse (ainult summa)","textPartialAmount":"Lihtsalt sisesta osaline summa tekstiv\xe4lja ja alusta tagasimakset.","titlePartialItems":"Osaline tagasimakse (artiklitega)","textPartialItems":"Kui soovid, et kogused ja esemed oleksid Mollies tagastatud, kasuta \xfclalolevat vormi. Sea oma kogused ja sisesta iga tagastatava toote jaoks kohandatud summa. Kogu summa kuvatakse seej\xe4rel l\xf5pliku tagasimakse summa tekstiv\xe4ljas. Pea meeles, et l\xf5pliku summat saab enne tagasimakse algatamist endiselt muuta.","titlePartialPromotions":"Osaline tagasimakse (koos soodustustega)","textPartialPromotions":"Kui sul on ostukorvis soodustus, on soodustus eraldi rida. Kui soovid tagastada k\xf5ik allahinnatud tooted, mine edasi ja tagasta nende koguv\xe4\xe4rtused ja terve soodustuse rida. Siiski, kui soovid vaid tagastada m\xf5ned allahinnatud tooted, saad iga tulu peaautomaatsete allahindluste automaatselt maha arvata. Loomulikult saad alati v\xe4\xe4rtusi muuta, kui need ei ole \xf5iged.","titleRoundingDiff":"\xdcmardamisvahe","textRoundingDiff":"T\xe4ielik tagasimakse h\xf5lmab \xfcmardamisest tulenevaid erinevusi"},"summary":{"dataLoading":"Andmeid laaditakse...","headerExcludingVat":"Ilma k\xe4ibemaksuta","headerIncludingVat":"K\xe4ibemaksuga","captionTotal":"Kokku","captionTotalTaxFree":"Kokku","captionPendingRefunds":"Ootab tagasimakset","captionVouchers":"Kinkekaardi summa","captionRefunded":"Tagastatud summa","captionRemaining":"Tagastatav summa","btnFixDiff":"Paranda erinevus","placeholderDescription":"Sisesta tarbija pangakonto/krediitkaardi v\xe4ljav\xf5tte kirjeldus. Max 140 t\xe4hem\xe4rki","lblDescription":"Kirjeldus (valikuline) ({characters}/140 t\xe4hem\xe4rki)","descriptionHelp":"V\xf5imalusel kuvatakse see tarbija pangakonto v\xf5i krediitkaardi v\xe4ljav\xf5ttel. S\xf5num k\xe4rbitakse p\xe4rast 140 t\xe4hem\xe4rki.","placeholderInternalDescription":"Sisesta oma sisekirjeldus","lblInternalDescription":"Sisekirjeldus (valikuline)","internalDescriptionHelp":"See kuvatakse haldusliideses kohaliku kirjeldusena.","checkVerification":"Olen kontrollinud tagasimakse kogusumma ja konfigureeritud tagasimakse- ja varude t\xe4iendamise kogused.","btnRefund":"Tagasimakse","btnFullRefund":"T\xe4ielik tagasimakse","roundDiffItemAdded":"\xdcmardamisartikkel"},"refunds":{"title":"Tagasimaksed Mollie t\xf6\xf6laual","linkMore":"Rohkem tagasimaksetest","grid":{"columns":{"amount":"Summa","status":"Staatus","description":"Kirjeldus","internalDescription":"Sisekirjeldus","composition":"Koostisosad","date":"Kuup\xe4ev"},"lblNoComposition":"Koostisosade puudumine","btnCancelRefund":"T\xfchista see tagasimakse"}},"notifications":{"success":{"refund-created":"Mollie\'s on loodud tagasimakse. Tagasimakse teostamine v\xf5ib v\xf5tta aega kuni 2 tundi. Selle aja jooksul on sul v\xf5imalik tagasimakse t\xfchistada.","refund-canceled":"Ootel tagasimakse on edukalt t\xfchistatud ja eemaldatud."},"error":{"low-amount":"Palun sisesta tagastatav summa.","refund-created":"Tagasimakse loomisel tekkis viga.","refund-canceled":"Ootel tagasimakse t\xfchistamisel tekkis probleem. Palun proovi uuesti Mollie t\xf6\xf6laual."}}},"vouchers":{"CARD_TITLE":"Kinkekaart","VOUCHER_INFO_TITLE":"Kinkekaardi maksed","VOUCHER_INFO_DESCRIPTION":"Mollie v\xf5imaldab sul oma veebipoes h\xf5lpsasti vastu v\xf5tta makseid \xf6ko-, kinkekaartide ja toidutalongidega – see on nutikas valik m\xfc\xfcgi suurendamiseks ja klientide rahulolu tagamiseks. Makseviis „kinkekaart” on n\xe4htav ainult siis, kui ostukorvis on v\xe4hemalt 1 toode, millele on m\xe4\xe4ratud kinkekaardi t\xfc\xfcp.","VOUCHER_INFO_DEFAULTLANGUAGE":"Palun pane t\xe4hele, et seda konfiguratsiooni saab redigeerida ainult sinu vaikimisi keeles. Palun muuda oma keelt, et muuta selle toote kinkekaardi t\xfc\xfcpi.","VOUCHER_BTN_READMORE":"Loe l\xe4hemalt","VOUCHER_TYPE_CAPTION":"Kinkekaardilaadne toode","VOUCHER_TYPE_VALUE_NONE":"Puudub","VOUCHER_TYPE_VALUE_ECO":"\xd6ko","VOUCHER_TYPE_VALUE_MEAL":"Eine","VOUCHER_TYPE_VALUE_VOUCHER":"Kink"},"modals":{"shipping":{"title":"Saada l\xe4bi Mollie","item":{"label":"Ese:","noQuantity":"Palun sisesta saadetav kogus.","shipAll":"Saada k\xf5ik","summary":{"quantity":"Saadetav kogus","shipped":"Saadetud kogus","shippable":"Saatmiseks valmisolev kogus"},"success":"Tellimus on edukalt saadetud."},"order":{"description":"J\xe4rgmised kogused saadetakse teele.","itemHeader":"Ese","quantityHeader":"Kogus","originalQuantityHeader":"Kogus (saadetav)"},"availableTracking":{"label":"Saadaval j\xe4lgimiskoodid","hint":"Kliki \xfchele neist j\xe4lgimiskoodidest, et k\xf5ik andmed t\xe4idetaks automaatselt."},"showTracking":"Lisa j\xe4lgimise info selle saadetise jaoks","tracking":{"carrier":"Vedaja","code":"Kood","url":"URL","invalid":"Palun sisesta nii vedaja kui ka kood"},"confirmButton":"Saada tellimus","cancelButton":"T\xfchista","selectAllButton":"Vali k\xf5ik","resetButton":"Nulli"},"cancel":{"title":"T\xfchista ese Mollie kaudu","confirmButton":"T\xfchista ese Mollie kaudu","cancelButton":"Sulge h\xfcpikaken","resetStock":"Taasta varud","item":{"success":"Toode on edukalt t\xfchistatud","failed":{"quantityZero":"Kogus on 0","invalidLine":"Toodet ei ole tellimuses","quantityTooHigh":"Kogus on liiga suur"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Saada tellimus (Mollie)","description":"Saada tellimus Mollies."},"modal":{"title":"Saada tellimus","description":"See toiming saadab tellimuse automaatselt l\xe4bi Mollie. Protsess saab tellimuse numbri ja edastab selle Mollie API-le. Edustatud ja eba\xf5nnestunud saadetised on n\xe4htavad Mollie logifailides.","warningConfig":"Palun veendu, et k\xf5ik t\xe4iendavad automatiseerimised seda t\xfc\xfcpi toimingutes on v\xe4lja l\xfclitatud, et v\xe4ltida segadust.\\nSelle pistikprogrammi j\xe4rgmised aktiveeritud funktsioonid v\xf5ivad seda toimingut h\xe4irida:","noWarnings":"Hoiatusi pole"}},"refundOrder":{"editor":{"title":"Tagasta tellimus (Mollie)","description":"Tagasta tellimus Mollie kaudu."},"modal":{"title":"Tagasta tellimus","description":"See toiming alustab automaatselt tagasimakset l\xe4bi Mollie. Protsess saab tellimuse numbri ja edastab selle Mollie API-le. Edukad ja eba\xf5nnestunud tagasimaksed on n\xe4htavad Mollie logifailides.","warning":"Palun pea meeles, et tagasimaksete l\xf5plikuks kinnitamiseks ja poes kuvamiseks v\xf5ib kuluda kuni 2 tundi. Seni saate ootava tagasimakse alati t\xfchistada kas Shopware\'i tellimuste lehelt v\xf5i Mollie t\xf6\xf6laualt.","warningConfig":"H\xe4irete v\xe4ltimiseks palun veendu, et sellist t\xfc\xfcpi toimingute jaoks on k\xf5ik lisafunktsioonid v\xe4lja l\xfclitatud."}},"warnings":{"automaticShipping":"Automaatne saadetis pistikprogrammi konfiguratsioonis"}}},"subscriptions":{"status":{"pending":"Ootel","active":"Aktiivne","canceled":"T\xfchistatud","suspended":"Peatatud","completed":"T\xe4idetud","paused":"Peatatud","resumed":"J\xe4tkatud","skipped":"Vahele j\xe4etud"},"navigation":{"title":"Mollie tellimused"},"TYPE_DAYS":"P\xe4ev(ad)","TYPE_WEEKS":"N\xe4dal(ad)","TYPE_MONTHS":"Kuu(d)","confirm":{"cancelTitle":"L\xf5peta tellimus?","cancel":"T\xfchista oma kliendi tellimus.","pauseTitle":"Peata tellimus?","pause":"Peata tellimus, kuni soovid seda uuesti j\xe4tkata.","resumeTitle":"J\xe4tka tellimust?","resume":"J\xe4tka tellimust uuesti.","skipTitle":"J\xe4ta j\xe4rgmine makse vahele?","skip":"J\xe4ta j\xe4rgmine osamakse tellimusest vahele. P\xe4rast seda j\xe4tkub tellimus automaatselt."},"alerts":{"cancelSuccess":"Tellimus on edukalt t\xfchistatud","pauseSuccess":"Tellimus on edukalt peatatud","resumeSuccess":"Tellimus on edukalt taastatud","skipSuccess":"Tellimus on edukalt vahele j\xe4etud. J\xe4rgmine makse on uuendatud."},"list":{"title":"Mollie Tellimused","columns":{"customer":"Klient","status":"Staatus","description":"Kirjeldus","amount":"Summa","nextPaymentAt":"J\xe4rgmine makse","prePaymentReminder":"Meenutatud","canceledAt":"T\xfchistatud","createdAt":"Loodud"},"action":{"edit":"Muuda tellimust"},"deletedCustomer":"Kustutatud klient"},"detail":{"title":"Mollie tellimus","buttonCancelSubscription":"T\xfchista tellimus","labelDescription":"Kirjeldus","labelAmount":"Summa","labelQuantity":"Kvantiteet","labelMollieSubscription":"Mollie tellimus","labelMollieCustomer":"Mollie klient","labelMandateId":"Mandaat","labelShopwareCustomer":"Shopware klient","labelCreatedAt":"Loodud","buttonShowShopwareOrder":"Kuva Shopware tellimus","buttonShowShopwareCustomer":"Kuva Shopware klient","cardTitleSubscription":"Tellimus","cardTitleStatus":"Staatus","labelStatus":"Staatus","labelNextPaymentAt":"J\xe4rgmine makse kell","labelLastRemindedAt":"Viimane meeldetuletus kell","labelCanceledAt":"T\xfchistatud","buttonPauseSubscription":"Pane tellimus pausile","buttonResumeSubscription":"J\xe4tka tellimust","buttonSkipSubscription":"T\xfchista tellimus","history":{"cardTitle":"Ajalugu","colDate":"Kuup\xe4ev","colComment":"Kommentaar","colStatusFrom":"Staatus (alates)","colStatusTo":"Staatus (kuni)","colMollieSubscription":"Mollie tellimus"}},"product":{"card-title":"Tellimus","title":"Mollie Tellimused","description":"Meie kasulike funktsioonide abil on korduvate maksete haldamine lihtsam kui kunagi varem. Vii oma \xe4ri uuele tasemele t\xf5husate j\xe4lgimisv\xf5imaluste, lihtsate integratsioonide ja muude funktsioonide abil. Mollie tellimustega saad h\xf5lpsasti luua tellimustooted ja planeerida korduvaid maksed, mis toimuvad konfigureeritud intervalli ja perioodi j\xe4rel.","mollieSubscriptionProduct":"Tellimuse toode","mollieSubscriptionIntervalAmount":"Korda makset iga","mollieSubscriptionIntervalType":"Ajavahemiku \xfchik","mollieSubscriptionRepetitionAmount":"Korduste arv","mollieSubscriptionRepetitionPlaceholder":"Sisesta number v\xf5i j\xe4ta t\xfchjaks","infoDefaultLanguage":"Palun pane t\xe4hele, et seda konfiguratsiooni saab redigeerida ainult teie vaikimisi keeles. Palun muuda oma keelt, et muuta selle toote tellimusseadistusi.","btnReadMore":"Loe l\xe4hemalt"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Tellimus"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Krediitkaardi andmed","buttonMolliePaymentLink":"Kopeeri l\xf5ikelauale","columnRefunded":"Tagastatud","columnShipped":"Saadetud","columnCanceled":"T\xfchistatud","labelMollieOrderId":"Mollie tellimuse ID","labelMollieThirdPartyPaymentId":"Makse viitenumber","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Tagastatud summa","totalRefundsPending":"Ootab tagastamist","totalRemaining":"Tagastatav summa","totalVouchers":"Kinkekaardi summa","totalShipments":"Saadetud summa ({quantity} toodet)","subscriptionBadge":"Tellimuse tellimine","refundManager":{"title":"Mollie Tagasimakse Haldur","btnOpenRefundManager":"Ava tagasimaksete haldur","btnCloseRefundManager":"Sulge tagasimaksete haldur"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Eelistatud iDeal v\xe4ljastaja"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Tagasimaksete haldur"},"mollie_subscription":{"label":"Tellimused"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Kirjeldus"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Tagasimakse","subscription":"Tellimus","webhookReceived":"Veebikonksud","status":"Staatus","started":"Alustatud","ended":"L\xf5petatud","paused":"Peatatud","renewalReminder":"Uuendamise meeldetuletus","renewed":"Uuendatud","resumed":"J\xe4tkatud","skipped":"Vahele j\xe4etud","all":"K\xf5ik","canceled":"T\xfchistatud","expired":"Aegunud","partiallyRefunded":"Tagastatud (osaliselt)","orderSuccess":"Tellimus \xf5nnestus","orderFailed":"Tellimus eba\xf5nnestus","orderCanceled":"Tellimus t\xfchistatud"}}}'),e9=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie \xe1skrift | Mollie \xe1skriftir"},"businessEvents":{"mollie_checkout_order_success":" P\xf6ntun \xe1r\xe1ngursr\xedk","mollie_checkout_order_failed":"P\xf6ntun misheppna\xf0ist","mollie_checkout_order_canceled":"P\xf6ntun afl\xfdst","mollie_webhook_received_All":" Mollie Webhook M\xf3ttekin (Allt)","mollie_webhook_received_status_authorized":" Mollie Webhook M\xf3ttekin (Vi\xf0urkennd)","mollie_webhook_received_status_failed":" Mollie Webhook M\xf3ttekin (Mist\xf3kst)","mollie_webhook_received_status_canceled":" Mollie Webhook M\xf3ttekin (Afl\xfdst)","mollie_webhook_received_status_expired":" Mollie Webhook M\xf3ttekin (\xfatrunnin)","mollie_webhook_received_status_pending":" Mollie Webhook M\xf3ttekin (\xcd vinnslu)","mollie_webhook_received_status_paid":" Mollie Webhook M\xf3ttekin (Greidd)","mollie_webhook_received_status_completed":" Mollie Webhook M\xf3ttekin (Fullunnin)","mollie_webhook_received_status_refunded":" Mollie Webhook M\xf3ttekin (Endurgreidd)","mollie_webhook_received_status_partially_refunded":" Mollie Webhook M\xf3ttekin (A\xf0 hluta til endurgreidd)","mollie_refund_started":"Endurgrei\xf0sla Mollie hafin","mollie_subscription_started":"Mollie \xe1skrift hafin","mollie_subscription_ended":"Mollie \xe1skrift loki\xf0","mollie_subscription_cancelled":"Mollie \xe1skrift afl\xfdst","mollie_subscription_paused":"Mollie \xe1skrift st\xf6\xf0vu\xf0","mollie_subscription_resumed":"Mollie \xe1skrift endurtekinn","mollie_subscription_skipped":"Mollie \xe1skrift sleppt","mollie_subscription_renewed":"Mollie \xe1skrift endurn\xfdju\xf0","mollie_subscription_renewal_reminder":"Mollie \xe1minning um endurn\xfdjun \xe1skriftar"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Eining","searchPlaceholder":"Leita a\xf0 \xe1skriftum...","general":{"mainMenuItemGeneral":"Mollie grei\xf0slur","descriptionTextModule":"Mollie grei\xf0slur","btnMollieActions":"Mollie a\xf0ger\xf0ir","refundThroughMollie":"Endurgrei\xf0sla \xed gegnum Mollie","shipThroughMollie":"Sending \xed gegnum Mollie","cancelMollieItem":"Afl\xfdsa \xed gegnum Mollie"},"config":{"info":{"title":"Hall\xf3 {userName}, velkomin/n til Mollie!","descriptionTop":"Innlei\xf0sla er au\xf0veld hj\xe1 Mollie!","descriptionBottom":"\xdea\xf0 er allt og sumt!","descriptionFooter":"Ef \xfe\xfa vilt l\xe6ra meira um vi\xf0b\xf3tina okkar, vinsamlegast heims\xe6ktu opinberu skjalas\xed\xf0una okkar.","onboardingStep1":"Skr\xe1\xf0u \xfeig inn til \xfeess a\xf0 f\xe1 Mollie reikning.","onboardingStep2":"Sl\xe1\xf0u inn API lyklana \xfe\xedna \xed hlutanum h\xe9r fyrir a\xf0 ne\xf0an.","onboardingStep2TestMode":"Kveiktu \xe1 \'Pr\xf3funarham\' ef \xfe\xfa vilt pr\xf3fa grei\xf0slurnar.","onboardingStep3":"Tilefndu grei\xf0slum\xe1ta til s\xf6lur\xe1sar \xfeinnar.","onboardingStep3Link":"til \xfeinnar s\xf6lur\xe1sar","btnDocumentation":"Skjalfesting","btnRequestSupport":"Stu\xf0ningur","btnTroubleshooting":"Lei\xf0beiningar um \xfarr\xe6\xf0aleit"},"api":{"apiLinkButton":"S\xe6ktu API lyklana \xfe\xedna \xed Stj\xf3rnbor\xf0i Mollie","testButton":"Pr\xf3fa API lykla","testApiKeys":{"title":"Mollie grei\xf0slur","apiKey":"API lykill","isValid":"er gildur","isInvalid":"er \xf3gildur"}},"payments":{"format":{"placeholder":"Sta\xf0gengill","preview":"Forsko\xf0un"},"updatePaymentMethods":{"title":"Mollie grei\xf0slur","button":"Uppf\xe6ra grei\xf0slum\xe1ta","succeeded":"Grei\xf0slum\xe1tar hafa veri\xf0 uppf\xe6r\xf0ir me\xf0 g\xf3\xf0um \xe1rangri.","failed":"Ekki var h\xe6gt a\xf0 uppf\xe6ra grei\xf0slum\xe1ta."},"mollieLimits":{"link":"S\xfdna a\xf0gengisreglur fyrir grei\xf0slum\xe1ta Mollie"}},"rounding":{"info1":"Shopware getur nota\xf0 gjaldmi\xf0lastillingar til \xfeess a\xf0 reikna \xfat hvernig \xfea\xf0 n\xe1mundar heildarver\xf0 p\xf6ntunnar. \xdeetta inniheldur fj\xf6lda aukastafa \xe1 ver\xf0i varanna \xfeinna og n\xe6sta n\xe1mundunarbili eins og 0,50 e\xf0a 1,00.","info2":"\xdeessar stillingar geta valdi\xf0 \xfev\xed a\xf0 heildarupph\xe6\xf0 ver\xf0ur \xf6nnur en heildarsumman af l\xednu\xfe\xe1ttum. \xdeegar Mollie athugar \xfeessa upph\xe6\xf0 og kemst a\xf0 \xfev\xed a\xf0 \xfe\xe6r passi ekki, veldur \xfea\xf0 villu \xed afgrei\xf0slu.","info3":"\xde\xfa getur nota\xf0 \xfeessan eiginleika til \xfeess a\xf0 for\xf0ast vandam\xe1l vi\xf0 n\xe1mundum \xed afgrei\xf0slu. \xdeegar \xfea\xf0 er virkt, b\xe6tir \xfea\xf0 vi\xf0 s\xe9r l\xednuhlut \xed Stj\xf3rnbor\xf0i Mollie fyrir mismun vi\xf0 n\xe1mundun, og vi\xf0skiptavinir \xfe\xednir grei\xf0a heildart\xf6lu sem Shopware reiknar."},"order":{"bankTransferDueDateKlarnaLimitReached":"\xdea\xf0 er ekki m\xf6gulegt a\xf0 nota Klarna Grei\xf0a n\xfana, Klarna Skera \xfea\xf0 e\xf0a Klarna Grei\xf0a s\xed\xf0ar sem a\xf0fer\xf0 \xfeegar gildist\xedminn \xfeinn er meira en 28 daga \xed framt\xed\xf0inni, nema anna\xf0 h\xe1mark s\xe9 sami\xf0 um milli seljanda og Klarna.","bankTransferDueDateLimitReached":"\xdea\xf0 er ekki h\xe6gt a\xf0 stilla l\xedft\xedma p\xf6ntunar h\xe6rri en 100 daga."},"support":{"modalTitle":"\xd3ska\xf0u eftir stu\xf0ningi fr\xe1 Mollie","btnCancel":"H\xe6tta vi\xf0","btnConfirm":"\xd3ska eftir stu\xf0ningi","btnSupport":"Meira um stu\xf0ninginn okkar","form":{"name":"Nafni\xf0 \xfeitt","email":"T\xf6lvup\xf3sturinn \xfeinn","recipient":"Senda bei\xf0ni til","subject":"Efni","message":"Skilabo\xf0"},"data":{"header":"G\xf6gn send til Mollie:","other":"Anna\xf0:","shopwareVersion":"Shopware \xfatg\xe1fa","pluginLogs":"{plugin} skr\xe1","pluginConfiguration":"{plugin} grunnstilling","pluginConfigurationHelpText":"API lyklar eru undanskildir.","paymentMethods":"G\xf6gn um grei\xf0slum\xe1ta","paymentMethodsHelpText":"Inniheldur uppl\xfdsingar um hva\xf0a grei\xf0slum\xe1tar eru virkir, tilnefndar hverju s\xf6lu\xfe\xe6tti og st\xf6\xf0u \xfeeirra \xed Mollie reikningnum \xfe\xednum."},"success":"Bei\xf0ni um stu\xf0ning hefur veri\xf0 send me\xf0 g\xf3\xf0um \xe1rangri. Vi\xf0 gerum okkar besta til a\xf0 svara eins flj\xf3tt og au\xf0i\xf0 er","error":"\xdea\xf0 kom upp vandam\xe1l \xfeegar sendingin var send me\xf0 Shopware. Vinsamlegast reyndu aftur e\xf0a haf\xf0u samband vi\xf0 okkur beint \xed gegnum t\xf6lvup\xf3st."}},"rules":{"itemSubscriptionRule":"Vara er \xe1skrift (Mollie)","cartSubscriptionRule":"Karfa me\xf0 \xe1skriftum (Mollie)"},"refunds":{"status":{"queued":"\xcd r\xf6\xf0","pending":"\xcd bi\xf0","processing":"\xcd vinnslu","refunded":"Endurgreidd","failed":"Mist\xf3kst","description":{"queued":"Endurgrei\xf0slan er \xed bi\xf0 \xfear til n\xe6gileg innist\xe6\xf0a finnst til a\xf0 vinna endurgrei\xf0sluna. \xde\xfa getur enn afskr\xe1\xf0 endurgrei\xf0sluna.","pending":"Endurgrei\xf0slan ver\xf0ur send til bankans \xe1 n\xe6sta vinnudegi. \xde\xfa getur enn afskr\xe1\xf0 endurgrei\xf0sluna.","processing":"Endurgrei\xf0slan hefur veri\xf0 send til bankans. Endurgrei\xf0slufj\xe1rh\xe6\xf0in mun ver\xf0a flutt \xe1 reikning neytenda eins flj\xf3tt og au\xf0i\xf0 er.","refunded":"Endurgrei\xf0slufj\xe1rh\xe6\xf0in hefur veri\xf0 flutt til neytandans.","failed":"Endurgrei\xf0slan hefur mistekist eftir vinnslu. Til d\xe6mis, g\xe6ti vi\xf0skiptavinurinn hafa loka\xf0 bankareikning s\xednum. Fj\xe1rmunirnir ver\xf0a sendir til \xfe\xedns reiknings."}}},"refund-manager":{"general":{"unitQuantity":"stk."},"acl":{"warningCreate":"\xde\xfa hefur ekki heimildir til a\xf0 b\xfaa til endurgrei\xf0slur","warningCancel":"\xde\xfa hefur ekki heimildir til a\xf0 h\xe6tta vi\xf0 endurgrei\xf0slur"},"cart":{"title":"P\xf6ntun ##orderNumber##","btnSelectAll":"Velja allt","btnResetForm":"Endurstilla ey\xf0ubla\xf0","linkHowTo":"Hvernig \xe1 a\xf0 nota \xfeetta ey\xf0ubla\xf0?","grid":{"columns":{"item":"Hlutur","productNumber":"V\xf6run\xfamer","unitPrice":"Ver\xf0 \xe1 einingu","quantity":"Magn","refunded":"Endurgreitt","refundQuantity":"Endurgrei\xf0sla","totalPrice":"Samtals","refundAmount":"Endurgrei\xf0sla","resetStock":"Endurstilla birg\xf0ir"},"btnResetLine":"Endurstilla l\xednu","checkDeductPromotion":"Draga fr\xe1 afsl\xe6tti","checkRefundTax":"Endurgrei\xf0a VSK"},"roundDiffItemAdded":"B\xe6tt var vi\xf0 sj\xe1lfvirka n\xe1mundun"},"instructions":{"linkResetTutorials":"Endurstilla lei\xf0beiningar","btnToggleTutorial":"S\xfdna/Fela lei\xf0beiningar","titleFullRefund":"Full endurgrei\xf0sla","textFullRefund":"Nota\xf0u einungis hnappinn til \xfeess a\xf0 f\xe1 fulla endurgrei\xf0slu. \xdeetta tryggir a\xf0 allar \xfe\xednar v\xf6rur s\xe9u merktar sem endurgreiddar og a\xf0 heildarfj\xe1rh\xe6\xf0inni s\xe9 skila\xf0 til vi\xf0skiptavinarins.","titleStockReset":"Endurstilling birg\xf0a","textStockReset":"\xde\xfa getur sj\xe1lfkrafa auki\xf0 f\xe1anlegar birg\xf0ir me\xf0 \xfev\xed a\xf0 sl\xe1 inn magn sem er aftur komi\xf0 \xe1 lager. Sl\xe1\xf0u \xfea\xf0 inn \xe1\xf0ur en \xfe\xfa hefur heila e\xf0a b\xfata\xf0a endurgrei\xf0slu. \xde\xfa getur sameina\xf0 endurstillingu birg\xf0a og endurgrei\xf0slu \xe1 sveigjanlegan m\xe1ta.","titleShipping":"Sending","textShipping":"V\xf6rur \xed sendingu m\xe1 endurgrei\xf0a eins og a\xf0rar v\xf6rur. Anna\xf0 hvort sl\xe1\xf0u inn fullt magn e\xf0a hluta magns og haltu \xe1fram me\xf0 endurgrei\xf0sluna. Endurgrei\xf0sla sendingarkostna\xf0s m\xe1 sameina \xe1 sveigjanlegan h\xe1tt vi\xf0 endurgrei\xf0sluferli v\xf6ru.","titlePartialAmount":"Sundru\xf0 endurgrei\xf0sla (einungis magn)","textPartialAmount":"Sl\xe1\xf0u einfaldlega inn hluta fj\xe1rh\xe6\xf0ar \xed reitinn og byrja\xf0u endurgrei\xf0sluna.","titlePartialItems":"Sundru\xf0 endurgrei\xf0sla (me\xf0 v\xf6rum)","textPartialItems":"Ef \xfe\xfa vilt merkja magn og v\xf6rur sem endurgreiddar \xed Mollie, skaltu nota ey\xf0ubla\xf0i\xf0 h\xe9r a\xf0 ofan. Stilltu magn og gef\xf0u s\xe9rstaka upp fj\xe1rh\xe6\xf0 fyrir hverja v\xf6ru sem ver\xf0ur endurgreidd. Heildarfj\xe1rh\xe6\xf0in mun \xfe\xe1 vera s\xfdnileg \xed textareitnum fyrir lokafj\xe1rh\xe6\xf0ina. Mundu eftir \xfev\xed a\xf0 enn er m\xf6gulegt a\xf0 breyta \xfeessari lokafj\xe1rh\xe6\xf0 \xe1\xf0ur en \xfe\xfa hefur endurgrei\xf0sluna.","titlePartialPromotions":"Hlutbundin endurgrei\xf0sla (me\xf0 afsl\xe1ttum)","textPartialPromotions":"Ef \xfe\xfa ert me\xf0 afsl\xe1tt \xed innkaupak\xf6rfunni \xfeinni, er afsl\xe1ttirinn a\xf0skilin l\xednuf\xe6rsla. Ef \xfe\xfa vilt endurgrei\xf0a allar afsl\xe1ttarv\xf6rur, skaltu halda \xe1fram og endurgrei\xf0a heildargildin \xfeeirra og alla afsl\xe1ttal\xednuv\xf6runa sj\xe1lfa. Hins vegar, ef \xfe\xfa vilt a\xf0eins endurgrei\xf0a nokkrar v\xf6rur sem voru afsl\xe1ttarv\xf6rur, getur\xf0u dregi\xf0 af br\xfaku\xf0um afsl\xe6tti sj\xe1lfkrafa fyrir hverja einstaka l\xednuv\xf6ru. \xde\xfa getur au\xf0vita\xf0 alltaf breytt gildum ef \xfeau eru vitlaus.","titleRoundingDiff":"Mismunur \xe1 n\xe1mundun","textRoundingDiff":"Full endurgrei\xf0sla mun fela \xed s\xe9r mismun \xed n\xe1mundun"},"summary":{"dataLoading":"G\xf6gn eru a\xf0 hla\xf0ast...","headerExcludingVat":"\xc1n VSK","headerIncludingVat":"Me\xf0 VSK","captionTotal":"Samtals","captionTotalTaxFree":"Samtals","captionPendingRefunds":"B\xed\xf0 eftir endurgrei\xf0slu","captionVouchers":"Upph\xe6\xf0 \xe1sl\xe1ttarmi\xf0a","captionRefunded":"Fj\xe1rh\xe6\xf0 sem endurgreidd","captionRemaining":"Fj\xe1rh\xe6\xf0 sem h\xe6gt er a\xf0 endurgrei\xf0a","btnFixDiff":"Laga mismun","placeholderDescription":"Sl\xe1\xf0u inn l\xfdsingu fyrir bankarreikning/kort fyrir neytandann. A\xf0 h\xe1marki 140 stafir","lblDescription":"L\xfdsing (valfrj\xe1ls) ({characters}/140 stafir)","descriptionHelp":"\xdeetta ver\xf0ur s\xfdnt \xed banka e\xf0a kortayfirliti neytandans \xfeegar \xfea\xf0 er m\xf6gulegt. Skilabo\xf0in ver\xf0a stytt eftir 140 stafi.","placeholderInternalDescription":"Sl\xe1\xf0u inn innri l\xfdsingu \xfe\xedna","lblInternalDescription":"Innri l\xfdsing (valfrj\xe1ls)","internalDescriptionHelp":"\xdeetta ver\xf0ur s\xfdnt sem sta\xf0bundin l\xfdsing \xed stj\xf3rnunara\xf0ger\xf0unum.","checkVerification":"\xc9g hef sta\xf0fest heildarfj\xe1rh\xe6\xf0 endurgrei\xf0slu og samstilltan fj\xf6lda sem \xe1 a\xf0 endurgrei\xf0a og birgja.","btnRefund":"Endurgrei\xf0sla","btnFullRefund":"Full endurgrei\xf0sla","roundDiffItemAdded":"N\xe1mundun hluts"},"refunds":{"title":"Endurgrei\xf0slur \xed Mollie stj\xf3rnbor\xf0inu","linkMore":"Meira um endurgrei\xf0slur","grid":{"columns":{"amount":"Fj\xe1rh\xe6\xf0","status":"Sta\xf0a","description":"L\xfdsing","internalDescription":"Innri l\xfdsing","composition":"Samsetning","date":"Dagsetning"},"lblNoComposition":"Engin samsetning tilt\xe6k","btnCancelRefund":"H\xe6tta vi\xf0 \xfeessa endurgrei\xf0slu"}},"notifications":{"success":{"refund-created":"Endurgrei\xf0sla hefur veri\xf0 stofnu\xf0 \xed Mollie. \xdea\xf0 getur teki\xf0 allt a\xf0 2 klukkustundir a\xf0 vinna endurgrei\xf0sluna. Upp a\xf0 \xfev\xed marki getur \xfe\xfa enn h\xe6tt vi\xf0 endurgrei\xf0sluna.","refund-canceled":"Endurgrei\xf0slan \xed bi\xf0 hefur veri\xf0 h\xe6tt vi\xf0 og fjarl\xe6g\xf0 me\xf0 g\xf3\xf0um \xe1rangri."},"error":{"low-amount":"Vinsamlegast sl\xe1\xf0u inn upph\xe6\xf0 sem \xe1 a\xf0 endurgrei\xf0a.","refund-created":"Eitthva\xf0 f\xf3r \xfarskei\xf0is vi\xf0 stofnun endurgrei\xf0slu.","refund-canceled":"\xdea\xf0 kom upp vandam\xe1l \xfeegar h\xe6tt var vi\xf0 endurgrei\xf0sluna \xed bi\xf0. Vinsamlegast reyndu aftur \xed Mollie stj\xf3rnbor\xf0inu."}}},"vouchers":{"CARD_TITLE":"Afsl\xe1ttarmi\xf0i","VOUCHER_INFO_TITLE":"Borgun afsl\xe1ttarmi\xf0a","VOUCHER_INFO_DESCRIPTION":"Mollie gerir \xfe\xe9r kleift a\xf0 \xfeiggja grei\xf0slur au\xf0veldlega \xed vefverslun \xfeinni me\xf0 Eco-, gjaf- og m\xe1lt\xed\xf0arafsl\xe1ttarmi\xf0a — snjallur kostur til \xfeess a\xf0 auka hagna\xf0 og fulln\xe6gja vi\xf0skiptavinum \xfe\xednum. Grei\xf0slum\xe1tinn \\"afsl\xe1ttarmi\xf0i\\" er a\xf0eins s\xfdnilegur ef \xfe\xfa hefur a\xf0 minnsta kosti 1 v\xf6ru me\xf0 tiltekinni tegund afsl\xe1ttarmi\xf0a \xed verslunark\xf6rfunni.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vinsamlegast athuga\xf0u a\xf0 \xfeessa uppsetningu m\xe1 a\xf0eins breyta \xe1 \xfe\xednu sj\xe1lfgefna tungum\xe1li. Vinsamlegast breyttu tungum\xe1linu \xfe\xednu til a\xf0 breyta tegund afsl\xe1ttarmi\xf0a \xfeessarar v\xf6ru.","VOUCHER_BTN_READMORE":"Lesa meira","VOUCHER_TYPE_CAPTION":"Tegund afsl\xe1ttarmi\xf0a v\xf6runnar","VOUCHER_TYPE_VALUE_NONE":"Enginn","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"M\xe1lt\xed\xf0","VOUCHER_TYPE_VALUE_VOUCHER":"Gj\xf6f"},"modals":{"shipping":{"title":"Senda \xed gegnum Mollie","item":{"label":"Vara:","noQuantity":"Vinsamlegast sl\xe1\xf0u inn fj\xf6lda til \xfeess a\xf0 hefja sendingu.","shipAll":"Senda allt","summary":{"quantity":"Fj\xf6ldi til sendingar","shipped":"Fj\xf6ldi sendur","shippable":"Fj\xf6ldi sem h\xe6gt er a\xf0 senda"},"success":"P\xf6ntun hefur veri\xf0 send me\xf0 g\xf3\xf0um \xe1rangri."},"order":{"description":"Eftirfarandi hlutir g\xe1tu ekki veri\xf0 sendir.","itemHeader":"Vara","quantityHeader":"Fj\xf6ldi","originalQuantityHeader":"Fj\xf6ldi (sem h\xe6gt er a\xf0 senda)"},"availableTracking":{"label":"Tilt\xe6kir k\xf3\xf0ar til rakningar","hint":"Smelltu \xe1 einn af \xfeessum sendingark\xf3\xf0um til a\xf0 fylla sj\xe1lfvirkt \xfat allar uppl\xfdsingar."},"showTracking":"B\xe6ta vi\xf0 uppl\xfdsingar um sendingu fyrir \xfeessa sendingu","tracking":{"carrier":"Flutningsa\xf0ili","code":"K\xf3\xf0i","url":"Url","invalid":"Vinsamlegast sl\xe1\xf0u inn b\xe6\xf0i flutningsa\xf0ila og k\xf3\xf0a"},"confirmButton":"Senda p\xf6ntun","cancelButton":"H\xe6tta vi\xf0","selectAllButton":"Velja allt","resetButton":"Endurstilla"},"cancel":{"title":"H\xe6tta vi\xf0 v\xf6ru \xed gegnum Mollie","confirmButton":"H\xe6tta vi\xf0 v\xf6ru \xed gegnum Mollie","cancelButton":"Loka glugga","resetStock":"Endurstilla birg\xf0ir","item":{"success":"V\xf6runni hefur veri\xf0 afl\xfdst me\xf0 g\xf3\xf0um \xe1rangri","failed":{"quantityZero":"Fj\xf6ldi er 0","invalidLine":"Varan er ekki til \xed p\xf6ntuninni","quantityTooHigh":"Fj\xf6ldi er of h\xe1r"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Senda p\xf6ntun (Mollie)","description":"Senda p\xf6ntun \xed Mollie."},"modal":{"title":"Senda p\xf6ntun","description":"\xdeessi a\xf0ger\xf0 mun sj\xe1lfkrafa senda p\xf6ntun \xed gegnum Mollie. Fl\xe6\xf0isr\xf6\xf0in mun taka \xe1 m\xf3ti p\xf6ntunarn\xfamerinu og senda \xfea\xf0 \xe1 Mollie API. \xc1r\xe1ngursr\xedkar sendingar og mislukka\xf0ar sendingar munu sj\xe1st \xed skr\xe1m Mollie.","warningConfig":"Vinsamlegast vertu viss um a\xf0 sl\xf6kkva \xe1 allri vi\xf0b\xf3tar sj\xe1lfvirkni fyrir \xfeessa tegund a\xf0ger\xf0ar til a\xf0 for\xf0ast truflanir.\\nVirkja\xf0ir eiginleikarnar \xed \xfeessari vi\xf0b\xf3t g\xe6tu trufla\xf0 \xfeessa a\xf0ger\xf0:","noWarnings":"Engar vi\xf0varanir"}},"refundOrder":{"editor":{"title":"Endurgrei\xf0sla p\xf6ntunar (Mollie)","description":"Endurgrei\xf0a p\xf6ntun \xed gegnum Mollie."},"modal":{"title":"Endurgrei\xf0sla p\xf6ntunar","description":"\xdeessi a\xf0ger\xf0 mun sj\xe1lfkrafa hefja endurgrei\xf0slu \xed gegnum Mollie. Fl\xe6\xf0isr\xf6\xf0in mun taka \xe1 m\xf3ti p\xf6ntunarn\xfamerinu og senda \xfea\xf0 \xe1 Mollie API. \xc1r\xe1ngursr\xedkar endurgrei\xf0slur og misheppana\xf0ar endurgrei\xf0slur munu sj\xe1st \xed Mollie skr\xe1ningu.","warning":"Vinsamlegast haf\xf0u \xed huga a\xf0 \xfea\xf0 g\xe6ti teki\xf0 allt a\xf0 2 klukkustundir \xfear til endurgrei\xf0slur eru sj\xe1anlegar \xed verslun. \xdeanga\xf0 til getur\xf0u alltaf h\xe6tt vi\xf0 endurgrei\xf0slu \xed vinnsly anna\xf0 hvort fr\xe1 p\xf6ntunars\xed\xf0unni \xed Shopware e\xf0a fr\xe1 Mollie stj\xf3rnbor\xf0inu.","warningConfig":"Vinsamlegast vertu viss um a\xf0 sl\xf6kkva \xe1 allri vi\xf0b\xf3tar sj\xe1lfvirkni fyrir \xfeessa tegund a\xf0ger\xf0ar til a\xf0 for\xf0ast truflanir."}},"warnings":{"automaticShipping":"Sj\xe1lfvirk sending \xed vi\xf0b\xf3tarstillingum"}}},"subscriptions":{"status":{"pending":"\xcd bi\xf0","active":"Virkur","canceled":"H\xe6tt vi\xf0","suspended":"Fresta\xf0","completed":"Loki\xf0","paused":"St\xf6\xf0va\xf0","resumed":"Endurn\xfdja\xf0","skipped":"Sleppt"},"navigation":{"title":"Mollie \xe1skriftir"},"TYPE_DAYS":"Dagur/dagar","TYPE_WEEKS":"Vika/vikur","TYPE_MONTHS":"M\xe1nu\xf0ur/m\xe1nu\xf0ir","confirm":{"cancelTitle":"Binda enda \xe1 \xe1skrift?","cancel":"H\xe6tta vi\xf0 \xe1skrift vi\xf0skiptavinarins.","pauseTitle":"St\xf6\xf0va \xe1skrift?","pause":"Setji \xe1skriftina \xe1 hl\xe9 \xfear til \xfe\xfa endurn\xfdjar hana aftur.","resumeTitle":"Endurn\xfdja \xe1skrift?","resume":"Halda \xe1fram \xe1skriftinni aftur.","skipTitle":"Sleppa n\xe6stu grei\xf0slu?","skip":"Sleppa n\xe6stu grei\xf0slu \xed \xe1skriftinni. H\xfan heldur \xe1fram sj\xe1lfkrafa eftir \xfea\xf0."},"alerts":{"cancelSuccess":"H\xe6tt var vi\xf0 p\xf6ntun me\xf0 g\xf3\xf0um \xe1rangri","pauseSuccess":"\xc1skriftin hefur veri\xf0 dregin \xed hl\xe9 me\xf0 g\xf3\xf0um \xe1rangri","resumeSuccess":"\xc1skriftin hefur veri\xf0 endurn\xfdju\xf0 me\xf0 g\xf3\xf0um \xe1rangri","skipSuccess":"\xc1skriftinni hefur veri\xf0 sleppt me\xf0 g\xf3\xf0um \xe1rangri. N\xe6sta grei\xf0sla hefur veri\xf0 uppf\xe6r\xf0."},"list":{"title":"Mollie \xe1skriftir","columns":{"customer":"Vi\xf0skiptavinur","status":"Sta\xf0a","description":"L\xfdsing","amount":"Upph\xe6\xf0","nextPaymentAt":"N\xe6sta grei\xf0sla","prePaymentReminder":"\xc1minning \xe1","canceledAt":"H\xe6tt vi\xf0 \xe1","createdAt":"B\xfai\xf0 til \xe1"},"action":{"edit":"Breyta \xe1skrift"},"deletedCustomer":"Eyddur vi\xf0skiptavinur"},"detail":{"title":"Mollie \xe1skrift","buttonCancelSubscription":"H\xe6tta vi\xf0 \xe1skrift","labelDescription":"L\xfdsing","labelAmount":"Upph\xe6\xf0","labelQuantity":"Magn","labelMollieSubscription":"Mollie \xe1skrift","labelMollieCustomer":"Mollie vi\xf0skiptavinur","labelMandateId":"Umbo\xf0","labelShopwareCustomer":"Shopware vi\xf0skiptavinur","labelCreatedAt":"B\xfai\xf0 til \xe1","buttonShowShopwareOrder":"S\xfdna Shopware p\xf6ntun","buttonShowShopwareCustomer":"S\xfdna Shopware vi\xf0skiptavin","cardTitleSubscription":"\xc1skrift","cardTitleStatus":"Sta\xf0a","labelStatus":"Sta\xf0a","labelNextPaymentAt":"N\xe6sta grei\xf0sla \xe1","labelLastRemindedAt":"S\xed\xf0ast \xe1minnt \xe1","labelCanceledAt":"Afskr\xe1\xf0 \xe1","buttonPauseSubscription":"St\xf6\xf0va \xe1skrift","buttonResumeSubscription":"Hefja \xe1skrift aftur","buttonSkipSubscription":"Sleppa \xe1skrift","history":{"cardTitle":"Saga","colDate":"Dagsetning","colComment":"Athugasemd","colStatusFrom":"Sta\xf0a (fr\xe1)","colStatusTo":"Sta\xf0a (til)","colMollieSubscription":"Mollie \xe1skrift"}},"product":{"card-title":"\xc1skrift","title":"Mollie \xe1skriftir","description":"A\xf0 st\xfdra endurteknum grei\xf0slum er au\xf0veldari en nokkru sinni fyrr me\xf0 nytsamlegu eiginleikunum okkar. F\xe6r\xf0u fyrirt\xe6ki \xfeitt \xe1 n\xe6sta stig me\xf0 virkri eftirfylgni, einf\xf6ldum sam\xfe\xe6ttingum og fleiru. Me\xf0 Mollie \xe1skriftum getur\xf0u au\xf0veldlega skapa\xf0 \xe1skriftarv\xf6rur og skipulagt endurteknar grei\xf0slur sem eiga a\xf0 eiga s\xe9r sta\xf0 \xe1 tilskildnu t\xedmabili.","mollieSubscriptionProduct":"\xc1skriftarvara","mollieSubscriptionIntervalAmount":"Endurtaka grei\xf0slu \xe1 hverju","mollieSubscriptionIntervalType":"T\xedmabilseining","mollieSubscriptionRepetitionAmount":"Fj\xf6ldi e\xf0a endurtekningar","mollieSubscriptionRepetitionPlaceholder":"Sl\xe1\xf0u inn fj\xf6lda e\xf0a skildu eftir autt","infoDefaultLanguage":"Vinsamlegast athugi\xf0 a\xf0 \xfeessi uppsetning er a\xf0eins breytanleg \xe1 \xfe\xednu sta\xf0al tungum\xe1li. Vinsamlegast breyttu tungum\xe1linu \xfe\xednu til a\xf0 breyta \xe1skriftarstillingum \xe1 \xfeessari v\xf6ru.","btnReadMore":"Lesa meira"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"\xc1skrift"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kreditkortag\xf6gn","buttonMolliePaymentLink":"Afrita \xed klippib\xfana\xf0","columnRefunded":"Endurgreitt","columnShipped":"Sent","columnCanceled":"H\xe6tt vi\xf0","labelMollieOrderId":"Mollie p\xf6ntunar ID","labelMollieThirdPartyPaymentId":"Grei\xf0sluau\xf0kenni","labelMolliePaymentLink":"Mollie Afgrei\xf0sla URL","totalRefunds":"Endurgreidd upph\xe6\xf0","totalRefundsPending":"B\xed\xf0 eftir endurgrei\xf0slu","totalRemaining":"Endurgreidd upph\xe6\xf0","totalVouchers":"Magn afsl\xe1ttarmi\xf0a","totalShipments":"Send upph\xe6\xf0 ({quantity} v\xf6rur)","subscriptionBadge":"P\xf6ntun \xe1skriftar","refundManager":{"title":"Mollie endurgrei\xf0slustj\xf3ri","btnOpenRefundManager":"Opna endurgrei\xf0slustj\xf3ra","btnCloseRefundManager":"Loka endurgrei\xf0slustj\xf3ra"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"\xc1kj\xf3sanlegur iDeal \xfatgefandi"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Endurgrei\xf0slustj\xf3ri"},"mollie_subscription":{"label":"\xc1skriftir"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"L\xfdsing"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Endurgrei\xf0sla","subscription":"\xc1skrift","webhookReceived":"Webhooks","status":"Sta\xf0a","started":"Byrja\xf0","ended":"Loki\xf0","paused":"St\xf6\xf0va\xf0","renewalReminder":"\xc1minning um endurn\xfdjun","renewed":"Endurn\xfdja\xf0","resumed":"Hafi\xf0 aftur","skipped":"Sleppt","all":"Allt","canceled":"H\xe6tt vi\xf0","expired":"\xdatrunni\xf0","partiallyRefunded":"Endurgreitt (a\xf0 hluta til)","orderSuccess":"P\xf6ntun \xe1r\xe1ngursr\xedk","orderFailed":"P\xf6ntun misheppna\xf0ist","orderCanceled":"H\xe6tt vi\xf0 p\xf6ntun"}}}'),e5=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie prenumerata | Mollie prenumeratos"},"businessEvents":{"mollie_checkout_order_success":"Užsakymas sėkmingas","mollie_checkout_order_failed":"Užsakymas nepavyko","mollie_checkout_order_canceled":"Užsakymas atšauktas","mollie_webhook_received_All":" Gautas Mollie „webhook“ (Visi)","mollie_webhook_received_status_authorized":"Gautas Mollie „webhook“ (Autorizuoti)","mollie_webhook_received_status_failed":"Gautas Mollie „webhook“ (Nepavykę)","mollie_webhook_received_status_canceled":"Gautas Mollie „webhook“ (Atšaukti)","mollie_webhook_received_status_expired":" Gautas Mollie „webhook“ (Nebegaliojantys)","mollie_webhook_received_status_pending":"Gautas Mollie „webhook“ (Laukiantys)","mollie_webhook_received_status_paid":"Gautas Mollie „webhook“ (Apmokėti)","mollie_webhook_received_status_completed":" Gautas Mollie „webhook“ (Įvykdyti)","mollie_webhook_received_status_refunded":" Gautas Mollie „webhook“ (Grąžinti)","mollie_webhook_received_status_partially_refunded":" Gautas Mollie „webhook“ (Iš dalies grąžinti)","mollie_refund_started":"Mollie grąžinimo procesas pradėtas","mollie_subscription_started":"Mollie prenumerata pradėta","mollie_subscription_ended":"Mollie prenumerata įvykdyta","mollie_subscription_cancelled":"Mollie prenumerata atšaukta","mollie_subscription_paused":"Mollie prenumerata sustabdyta","mollie_subscription_resumed":"Mollie prenumerata atnaujinta","mollie_subscription_skipped":"Mollie prenumerata praleista","mollie_subscription_renewed":"Mollie prenumerata atnaujinta","mollie_subscription_renewal_reminder":"Mollie priminimas apie prenumeratos atnaujinimą"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie modulis","searchPlaceholder":"Ieškoti prenumeratų...","general":{"mainMenuItemGeneral":"Mollie mokėjimai","descriptionTextModule":"Mollie mokėjimai","btnMollieActions":"Mollie veiksmai","refundThroughMollie":"Grąžinti per Mollie","shipThroughMollie":"Siųsti per Mollie","cancelMollieItem":"Atšaukti per Mollie"},"config":{"info":{"title":"Labas {userName}, Sveiki atvykę į Mollie!","descriptionTop":"Paprasta registracija su Mollie!","descriptionBottom":"Tai viskas!","descriptionFooter":"Jei norite sužinoti daugiau apie mūsų papildinį, apsilankykite oficialiame dokumentacijos puslapyje.","onboardingStep1":"Užsiregistruokite Mollie paskyrai.","onboardingStep2":"Įveskite savo API raktus į žemiau esančią eilutę.","onboardingStep2TestMode":"Įjunkite „Testavimo režimą“, jei norite tik išbandyti mokėjimus.","onboardingStep3":"Priskirkite mokėjimo būdus savo pardavimų kanalui.","onboardingStep3Link":"į jūsų pardavimo kanalus","btnDocumentation":"Dokumentacija","btnRequestSupport":"Pagalba","btnTroubleshooting":"Problemų sprendimo vadovas"},"api":{"apiLinkButton":"Gaukite savo API raktus iš Mollie valdymo skydelio","testButton":"Testavimo API raktai","testApiKeys":{"title":"Mollie mokėjimai","apiKey":"API raktas","isValid":"yra galiojantis","isInvalid":"yra negaliojantis"}},"payments":{"format":{"placeholder":"Vieta tekstui","preview":"Peržiūra"},"updatePaymentMethods":{"title":"Mollie mokėjimai","button":"Atnaujinti mokėjimo būdus","succeeded":"Mokėjimo būdai sėkmingai atnaujinti.","failed":"Nepavyko atnaujinti mokėjimo būdų."},"mollieLimits":{"link":"Rodyti Mollie mokėjimo būdų prieinamumo sąlygas"}},"rounding":{"info1":"Shopware gali naudoti valiutos nustatymus, kad apskaičiuotų, kaip suapvalinti bendrą užsakymo sumą. Tai apima skaičių po kablelio jūsų produktų kainose ir artimiausią apvalinimo intervalą, pavyzdžiui, 0,50 arba 1,00.","info2":"Dėl šių nustatymų galutinė suma gali skirtis nuo eilučių sumų bendros sumos. Kai Mollie sutikrina šias sumas ir nustato, kad jos nesutampa, atsiranda atsiskaitymo klaida.","info3":"Šią funkciją galite naudoti, kad išvengtumėte apvalinimo problemų atsiskaitymo metu. Įjungus, Mollie paskyros suvestinėje bus pridėta atskira eilutė su apvalinimo skirtumu, o klientai mokės bendrą sumą, apskaičiuotą Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Negalima naudoti Klarna Pay now, Klarna Slice it arba Klarna Pay later kaip mokėjimo būdo, jei Jūsų galiojimo pabaigos data yra daugiau nei 28 dienos ateityje, nebent tarp prekybininko ir Klarna būtų susitarta dėl kito didžiausio termino.","bankTransferDueDateLimitReached":"Negalima nustatyti užsakymo galiojimo trukmės ilgesnės nei 100 dienų."},"support":{"modalTitle":"Prašykite pagalbos iš Mollie","btnCancel":"Atšaukti","btnConfirm":"Prašyti pagalbos","btnSupport":"Daugiau apie mūsų pagalbą","form":{"name":"Jūsų vardas","email":"Jūsų el. paštas","recipient":"Siųsti prašymą","subject":"Tema","message":"Žinutė"},"data":{"header":"Duomenys, išsiųsti Mollie:","other":"Kita:","shopwareVersion":"Shopware versija","pluginLogs":"{plugin} žurnalo failai","pluginConfiguration":"{plugin} nustatymai","pluginConfigurationHelpText":"API raktai yra neįtraukti.","paymentMethods":"Mokėjimo būdo duomenys","paymentMethodsHelpText":"Įtraukta informacija apie tai, kurie mokėjimo būdai yra aktyvūs, priskirti kiekvienam pardavimo kanalui, taip pat apie jų būseną jūsų Mollie paskyroje."},"success":"Pagalbos užklausa buvo sėkmingai išsiųsta. Mes pasistengsime atsakyti kuo greičiau","error":"Siunčiant laišką per Shopware įvyko klaida. Bandykite dar kartą arba susisiekite su mumis tiesiogiai el. paštu."}},"rules":{"itemSubscriptionRule":"Prekė yra prenumerata (Mollie)","cartSubscriptionRule":"Krepšelis su prenumeratomis (Mollie)"},"refunds":{"status":{"queued":"Eilėje","pending":"Laukiama","processing":"Apdorojama","refunded":"Grąžinta","failed":"Nepavyko","description":{"queued":"Grąžinimas įtrauktas į eilę, kol bus pakankamai lėšų jo apdorojimui. Vis dar galite atšaukti šį grąžinimą.","pending":"Grąžinimas bus išsiųstas į banką kitą darbo dieną. Vis dar galite atšaukti šį grąžinimą.","processing":"Grąžinimas buvo išsiųstas į banką. Grąžinama suma bus pervesta į vartotojo sąskaitą kuo greičiau.","refunded":"Grąžinimo suma buvo pervesta vartotojui.","failed":"Grąžinimas nepavyko po apdorojimo. Pavyzdžiui, klientas uždarė savo banko sąskaitą. Lėšos bus grąžintos į jūsų sąskaitą."}}},"refund-manager":{"general":{"unitQuantity":"vnt."},"acl":{"warningCreate":"Neturite leidimų kurti grąžinimų","warningCancel":"Neturite leidimų atšaukti grąžinimų"},"cart":{"title":"Užsakymas ##orderNumber##","btnSelectAll":"Pasirinkti viską","btnResetForm":"Iš naujo nustatyti formą","linkHowTo":"Kaip naudoti šią formą?","grid":{"columns":{"item":"Prekė","productNumber":"Prekės numeris","unitPrice":"Vieneto kaina","quantity":"Kiekis","refunded":"Grąžinta","refundQuantity":"Grąžinimas","totalPrice":"Iš viso","refundAmount":"Grąžinimas","resetStock":"Iš naujo nustatyti atsargas"},"btnResetLine":"Iš naujo nustatyti eilutę","checkDeductPromotion":"Atimti nuolaidą","checkRefundTax":"Grąžinti PVM"},"roundDiffItemAdded":"Automatinis suapvalinimo elementas buvo pridėtas"},"instructions":{"linkResetTutorials":"Iš naujo nustatyti mokymus","btnToggleTutorial":"Rodyti/Slėpti mokymą","titleFullRefund":"Pilnas grąžinimas","textFullRefund":"Tiesiog naudokite mygtuką visam grąžinimui. Taip užtikrinama, kad visos jūsų prekės bus pažymėtos kaip grąžintos ir visa suma bus grąžinta klientui.","titleStockReset":"Atsargų atnaujinimas","textStockReset":"Galite automatiškai padidinti turimą atsargų kiekį, įvesdami kiekį, kurį norite grąžinti į sandėlį. Tiesiog įveskite jį prieš atlikdami visą arba dalinį grąžinimą. Atsargų atnaujinimą galima lanksčiai derinti su faktiniu grąžinimo procesu.","titleShipping":"Siuntimas","textShipping":"Siuntimo prekes galima grąžinti kaip bet kurią kitą prekę. Įveskite visą kiekį arba nurodykite pasirinktą dalinę sumą ir tęskite grąžinimo procesą. Siuntimo išlaidų grąžinimas gali būti derinamas su faktiniu prekių grąžinimo procesu lanksčiu būdu.","titlePartialAmount":"Dalinis grąžinimas (tik suma)","textPartialAmount":"Tiesiog įveskite dalinę sumą į teksto laukelį ir pradėkite grąžinimą.","titlePartialItems":"Dalinis grąžinimas (su prekėmis)","textPartialItems":"Jei norite Mollie sistemoje pažymėti kiekius ir prekes kaip grąžintas, naudokite aukščiau esančią formą. Nustatykite kiekius ir nurodykite pasirinktą sumą kiekvienai grąžinamai prekei. Bendra suma bus matoma galutinės grąžinimo sumos laukelyje. Prisiminkite, kad prieš pradėdami grąžinimą vis dar galite pakoreguoti šią galutinę sumą.","titlePartialPromotions":"Dalinis grąžinimas (su nuolaidomis)","textPartialPromotions":"Jei jūsų krepšelyje yra akcija, ji pateikiama kaip atskira eilutė. Jei norite grąžinti visas su nuolaida įsigytas prekes, grąžinkite jų bendras vertes ir visą akcijos eilutę. Tačiau jei norite grąžinti tik kelias nuolaidas gavusias prekes, galite automatiškai atimti pritaikytą nuolaidą kiekvienai eilutei atskirai. Žinoma, visada galite pakeisti vertes, jei jos neteisingos.","titleRoundingDiff":"Apvalinimo skirtumas","textRoundingDiff":"Visos sumos grąžinimas apims ir apvalinimo skirtumus"},"summary":{"dataLoading":"Duomenys kraunami...","headerExcludingVat":"Be PVM","headerIncludingVat":"Įskaitant PVM","captionTotal":"Iš viso","captionTotalTaxFree":"Iš viso","captionPendingRefunds":"Laukiama grąžinimo","captionVouchers":"Kupono suma","captionRefunded":"Grąžinta suma","captionRemaining":"Grąžinama suma","btnFixDiff":"Ištaisyti skirtumą","placeholderDescription":"Įveskite banko / kortelės išrašo aprašymą vartotojui. Daugiausia 140 simbolių","lblDescription":"Aprašymas (neprivalomas) ({characters}/140 simbolių)","descriptionHelp":"Kai įmanoma, tai bus rodoma vartotojo banko ar kortelės išraše. Pranešimas bus sutrumpintas po 140 simbolių.","placeholderInternalDescription":"Įveskite savo vidinį aprašymą","lblInternalDescription":"Vidinis aprašymas (neprivalomas)","internalDescriptionHelp":"Tai bus rodoma kaip vietinis aprašymas administravimo sąsajoje.","checkVerification":"Patikrinau visą grąžinamą sumą ir nustatytus kiekius grąžinimui bei grąžinimui į sandėlį.","btnRefund":"Grąžinimas","btnFullRefund":"Pilnas grąžinimas","roundDiffItemAdded":"Apvalinimo elementas"},"refunds":{"title":"Grąžinimai Mollie suvestinėje","linkMore":"Daugiau apie grąžinimus","grid":{"columns":{"amount":"Suma","status":"Būsena","description":"Aprašymas","internalDescription":"Vidinis aprašymas","composition":"Sudėtis","date":"Data"},"lblNoComposition":"Sudėtis neprieinama","btnCancelRefund":"Atšaukti šį grąžinimą"}},"notifications":{"success":{"refund-created":"Grąžinimas buvo sukurtas Mollie. Gali užtrukti iki 2 valandų, kol grąžinimas bus užbaigtas. Iki šio laiko galite atšaukti grąžinimą.","refund-canceled":"Laukiantis grąžinimas sėkmingai atšauktas ir pašalintas."},"error":{"low-amount":"Prašome įvesti sumą, kurią reikia grąžinti.","refund-created":"Įvyko klaida kuriant grąžinimą.","refund-canceled":"Atšaukiant grąžinimą įvyko klaida. Bandykite dar kartą Mollie valdymo skydelyje."}}},"vouchers":{"CARD_TITLE":"Kuponas","VOUCHER_INFO_TITLE":"Kupono mokėjimai","VOUCHER_INFO_DESCRIPTION":"Mollie leidžia lengvai priimti mokėjimus savo internetinėje parduotuvėje, naudojant eko, dovanų ir maisto kuponus – išmanus pasirinkimas padedantis didinti pardavimus ir patenkinti jūsų klientus. Mokėjimo būdas „kuponas“ bus matomas tik tuo atveju, jei krepšelyje yra bent 1 produktas su priskirtu kupono tipu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Atkreipkite dėmesį, kad šis nustatymas gali būti redaguojamas tik jūsų numatyta kalba. Norėdami pakeisti šio produkto kupono tipą, pakeiskite kalbą.","VOUCHER_BTN_READMORE":"Skaityti daugiau","VOUCHER_TYPE_CAPTION":"Kuponų produkto tipas","VOUCHER_TYPE_VALUE_NONE":"Nėra","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Maisto","VOUCHER_TYPE_VALUE_VOUCHER":"Dovanų"},"modals":{"shipping":{"title":"Siųsti per Mollie","item":{"label":"Prekė:","noQuantity":"Prašome įvesti siunčiamą kiekį.","shipAll":"Siųsti viską","summary":{"quantity":"Siunčiamas kiekis","shipped":"Išsiųstas kiekis","shippable":"Kiekis, kuris gali būti siunčiamas"},"success":"Užsakymas buvo sėkmingai išsiųstas."},"order":{"description":"Šios prekės kiekiai bus siunčiami.","itemHeader":"Prekė","quantityHeader":"Kiekis","originalQuantityHeader":"Kiekis (kuris gali būti siunčiamas)"},"availableTracking":{"label":"Pasiekiami sekimo kodai","hint":"Paspauskite vieną iš šių sekimo kodų, kad automatiškai užpildytumėte visus duomenis."},"showTracking":"Pridėti siuntos sekimo informaciją","tracking":{"carrier":"Vežėjas","code":"Kodas","url":"URL","invalid":"Prašome įvesti tiek vežėją, tiek kodą"},"confirmButton":"Siųsti užsakymą","cancelButton":"Atšaukti","selectAllButton":"Pasirinkti viską","resetButton":"Atstatyti"},"cancel":{"title":"Atšaukti prekę per Mollie","confirmButton":"Atšaukti prekę per Mollie","cancelButton":"Uždaryti modalinį langą","resetStock":"Iš naujo nustatyti atsargas","item":{"success":"Produktas sėkmingai atšauktas","failed":{"quantityZero":"Kiekis yra 0","invalidLine":"Produktas neegzistuoja užsakyme","quantityTooHigh":"Kiekis yra per didelis"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Siųsti užsakymą (Mollie)","description":"Siųsti užsakymą per Mollie."},"modal":{"title":"Siųsti užsakymą","description":"Šis veiksmas automatiškai išsiųs užsakymą per Mollie. Šis procesas gaus užsakymo numerį ir perduos jį Mollie API. Sėkmingos ir nepavykusios siuntos bus matomos Mollie žurnalo failuose.","warningConfig":"Prašome įsitikinti, kad išjungėte bet kokią papildomą automatizaciją šio tipo veiksmui, kad išvengtumėte bet kokių trikdžių.\\nŠios papildomos funkcijos gali trukdyti šiam veiksmui:","noWarnings":"Įspėjimų nėra"}},"refundOrder":{"editor":{"title":"Grąžinti užsakymą (Mollie)","description":"Grąžinti užsakymą per Mollie."},"modal":{"title":"Grąžinti užsakymą","description":"Šis veiksmas automatiškai pradės grąžinimą per Mollie. Šis procesas gaus užsakymo numerį ir perduos jį Mollie API. Sėkmingi ir nepavykę grąžinimai bus matomi Mollie žurnalo failuose.","warning":"Atminkite, kad grąžinimų užbaigimas ir jų matomumas parduotuvėje gali užtrukti iki 2 valandų. Iki tol visada galite atšaukti laukiantį grąžinimą iš užsakymo puslapio Shopware sistemoje arba iš Mollie valdymo skydelio.","warningConfig":"Prašome įsitikinti, kad išjungėte bet kokią papildomą automatizaciją šio tipo veiksmui, kad išvengtumėte bet kokių trikdžių."}},"warnings":{"automaticShipping":"Automatinis siuntimas papildinio nustatymuose"}}},"subscriptions":{"status":{"pending":"Laukiama","active":"Aktyvus","canceled":"Atšauktas","suspended":"Sustabdytas","completed":"Įvykdyta","paused":"Sustabdyta","resumed":"Atnaujinta","skipped":"Praleista"},"navigation":{"title":"Mollie Prenumeratos"},"TYPE_DAYS":"Diena(-os)","TYPE_WEEKS":"Savaitė(-s)","TYPE_MONTHS":"Mėnuo(-esiai)","confirm":{"cancelTitle":"Atšaukti prenumeratą?","cancel":"Atšaukti jūsų kliento prenumeratą.","pauseTitle":"Sustabdyti prenumeratą?","pause":"Sustabdykite prenumeratą, kol vėl ją atnaujinsite.","resumeTitle":"Atnaujinti prenumeratą?","resume":"Tęskite prenumeratą dar kartą.","skipTitle":"Praleisti kitą mokėjimą?","skip":"Praleiskite kitą prenumeratos mokėjimą. Vėliau ji tęsis automatiškai."},"alerts":{"cancelSuccess":"Prenumerata sėkmingai atšaukta","pauseSuccess":"Prenumerata sėkmingai sustabdyta","resumeSuccess":"Prenumerata sėkmingai atnaujinta","skipSuccess":"Prenumerata sėkmingai praleista. Kitas mokėjimas buvo atnaujintas."},"list":{"title":"Mollie prenumeratos","columns":{"customer":"Klientas","status":"Būsena","description":"Aprašymas","amount":"Suma","nextPaymentAt":"Kitas mokėjimas","prePaymentReminder":"Priminta","canceledAt":"Atšauktas","createdAt":"Sukurtas"},"action":{"edit":"Redaguoti prenumeratą"},"deletedCustomer":"Ištrintas klientas"},"detail":{"title":"Mollie prenumerata","buttonCancelSubscription":"Atšaukti prenumeratą","labelDescription":"Aprašymas","labelAmount":"Suma","labelQuantity":"Kiekis","labelMollieSubscription":"Mollie prenumerata","labelMollieCustomer":"Mollie klientas","labelMandateId":"Įgaliojimas","labelShopwareCustomer":"Shopware klientas","labelCreatedAt":"Sukurtas","buttonShowShopwareOrder":"Rodyti Shopware užsakymą","buttonShowShopwareCustomer":"Rodyti Shopware klientą","cardTitleSubscription":"Prenumerata","cardTitleStatus":"Būsena","labelStatus":"Būsena","labelNextPaymentAt":"Kitas mokėjimas","labelLastRemindedAt":"Paskutinį kartą priminta","labelCanceledAt":"Atšauktas","buttonPauseSubscription":"Sustabdyti prenumeratą","buttonResumeSubscription":"Pratęsti prenumeratą","buttonSkipSubscription":"Praleisti prenumeratą","history":{"cardTitle":"Istorija","colDate":"Data","colComment":"Komentaras","colStatusFrom":"Būsena (iš)","colStatusTo":"Būsena (į)","colMollieSubscription":"Mollie prenumerata"}},"product":{"card-title":"Prenumerata","title":"Mollie prenumeratos","description":"Valdyti pasikartojančius mokėjimus dar niekada nebuvo taip paprasta – padės mūsų naudingos funkcijos. Pakelkite savo verslą į kitą lygį naudodami efektyvias stebėjimo galimybes, paprastą integravimą ir dar daugiau. Naudodami Mollie prenumeratas, galite lengvai kurti prenumeruojamus produktus ir suplanuoti periodinius mokėjimus taip, kad jie būtų vykdomi nustatytu dažniu ir laikotarpiu.","mollieSubscriptionProduct":"Prenumeratos produktas","mollieSubscriptionIntervalAmount":"Kartoti mokėjimą kas","mollieSubscriptionIntervalType":"Intervalo vienetas","mollieSubscriptionRepetitionAmount":"Pasikartojimų skaičius","mollieSubscriptionRepetitionPlaceholder":"Įveskite skaičių arba palikite tuščią","infoDefaultLanguage":"Prašome atkreipti dėmesį, kad šis nustatymas gali būti redaguojamas tik jūsų numatyta kalba. Prašome pakeisti savo kalbą norint pakeisti produkto prenumeratos nustatymus.","btnReadMore":"Skaityti daugiau"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Prenumerata"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kredito kortelės duomenys","buttonMolliePaymentLink":"Kopijuoti į iškarpinę","columnRefunded":"Grąžinta","columnShipped":"Išsiųsta","columnCanceled":"Atšaukta","labelMollieOrderId":"Mollie užsakymo ID","labelMollieThirdPartyPaymentId":"Mokėjimo nuoroda","labelMolliePaymentLink":"Mollie atsiskaitymo URL","totalRefunds":"Grąžinta suma","totalRefundsPending":"Laukiama grąžinimo","totalRemaining":"Grąžinama suma","totalVouchers":"Kupono suma","totalShipments":"Išsiųsta suma ({quantity} vienetai)","subscriptionBadge":"Prenumeratos užsakymas","refundManager":{"title":"Mollie grąžinimų valdymas","btnOpenRefundManager":"Atidaryti grąžinimų valdymą","btnCloseRefundManager":"Uždaryti grąžinimų valdymą"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Pageidaujamas iDEAL bankas"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Grąžinimų valdymas"},"mollie_subscription":{"label":"Prenumeratos"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Aprašymas"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Grąžinimas","subscription":"Prenumerata","webhookReceived":"„Webhook“ pranešimai","status":"Būsena","started":"Pradėta","ended":"Baigta","paused":"Sustabdyta","renewalReminder":"Atnaujinimo priminimas","renewed":"Atnaujinta","resumed":"Pratęsta","skipped":"Praleista","all":"Visi","canceled":"Atšaukta","expired":"Nebegalioja","partiallyRefunded":"Grąžinta (dalinai)","orderSuccess":"Užsakymas sėkmingas","orderFailed":"Užsakymas nepavyko","orderCanceled":"Užsakymas atšauktas"}}}'),e4=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Subscription | Mollie Subscriptions"},"businessEvents":{"mollie_checkout_order_success":"Pasūtījums veiksmīgs ","mollie_checkout_order_failed":" Pasūtījums neizdevās","mollie_checkout_order_canceled":" Pasūtījums atcelts","mollie_webhook_received_All":" Mollie Webhook Saņemts (Visi)","mollie_webhook_received_status_authorized":"Mollie tīmekļa āķi saņemti (Autorizēti)","mollie_webhook_received_status_failed":"Mollie tīmekļa āķi saņemti (Neizdevušies)","mollie_webhook_received_status_canceled":"Mollie tīmekļa āķi saņemti (Atcelti)","mollie_webhook_received_status_expired":"Mollie tīmekļa āķi saņemti (Beigušies)","mollie_webhook_received_status_pending":"Mollie tīmekļa āķi saņemti (Procesā esoši)","mollie_webhook_received_status_paid":"Mollie tīmekļa āķi saņemti (Samaksāti)","mollie_webhook_received_status_completed":"Mollie tīmekļa āķi saņemti (Pabeigti)","mollie_webhook_received_status_refunded":"Mollie tīmekļa āķi saņemti (Atmaksāti)","mollie_webhook_received_status_partially_refunded":"Mollie tīmekļa āķi saņemti (Daļēji Atmaksāti)","mollie_refund_started":"Mollie atmaksa sākta","mollie_subscription_started":" Sākta Mollie abonēšana","mollie_subscription_ended":" Mollie abonēšana pabeigta","mollie_subscription_cancelled":"Mollie abonements atcelts","mollie_subscription_paused":"Mollie abonements apturēts","mollie_subscription_resumed":"Mollie abonements atsākts","mollie_subscription_skipped":"Mollie abonements izlaists","mollie_subscription_renewed":"Mollie abonements atjaunots","mollie_subscription_renewal_reminder":"Mollie atgādinājums par abonementa atjaunošanu"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Module","searchPlaceholder":"Meklēt abonementus...","general":{"mainMenuItemGeneral":"Mollie Payments","descriptionTextModule":"Mollie Payments","btnMollieActions":"Mollie darbības","refundThroughMollie":"Atmaksa caur Mollie","shipThroughMollie":"Nosūtīt caur Mollie","cancelMollieItem":"Atcelt caur Mollie"},"config":{"info":{"title":"Sveiks {userName}, laipni lūdzam Mollie!","descriptionTop":"Iepazīšanās ar Mollie ir vienkārša!","descriptionBottom":"Tas ir viss!","descriptionFooter":"Ja vēlies uzzināt vairāk par mūsu spraudni, lūdzu, apmeklē mūsu oficiālo dokumentācijas lapu.","onboardingStep1":"Reģistrēties Mollie kontam.","onboardingStep2":"Ievadiet savas API atslēgas zemāk esošajā sadaļā.","onboardingStep2TestMode":"Ieslēdziet \'Testa režīmu\', ja vēlaties tikai izmēģināt maksājumus.","onboardingStep3":"Piešķiriet maksājuma metodes savam pārdošanas kanālam.","onboardingStep3Link":"uz jūsu pārdošanas kanāliem","btnDocumentation":"Dokumentācija","btnRequestSupport":"Atbalsts","btnTroubleshooting":"Problēmu novēršanas rokasgrāmata"},"api":{"apiLinkButton":"Iegūstiet savas API atslēgas no Mollie Dashboard","testButton":"Test API atslēgas","testApiKeys":{"title":"Mollie Payments","apiKey":"API atslēga","isValid":"ir derīga","isInvalid":"ir nederīga"}},"payments":{"format":{"placeholder":"Aizvietotājs","preview":"Priekšskatījums"},"updatePaymentMethods":{"title":"Mollie Payments","button":"Atjaunot maksājumu metodes","succeeded":"Maksājumu metodes veiksmīgi atjaunotas.","failed":"Maksājuma metodes nevarēja tikt atjauninātas."},"mollieLimits":{"link":"Rādīt Mollie pieejamības noteikumus maksājumu metodēm"}},"rounding":{"info1":"Shopware var izmantot valūtas iestatījumus, lai aprēķinātu, kā tas noapaļo pasūtījuma kopējo summu. Tas ietver decimāldaļu skaitu jūsu produktu cenās un tuvāko noapaļošanas intervālu, piemēram, 0.50 vai 1.00.","info2":"Šie iestatījumi var novest pie kopējās summas, kas atšķiras no rindu elementu kopējās summas. Kad Mollie pārbauda šos apmērus un atklāj, ka tie nesakrīt, tas apmaksas kases kļūdu.","info3":"Šo funkciju varat izmantot, lai izvairītos no noapaļošanas problēmām jūsu apmaksā. Kad tā ir iespējota, tā pievieno atsevišķu rindu jūsu Mollie vadības panelī par starpību noapaļošanā, un jūsu klienti samaksā kopējo summu, ko aprēķina Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nav iespējams izmantot Klarna Pay now, Klarna Slice it vai Klarna Pay later kā metodi, kad jūsu derīguma termiņš ir vairāk nekā 28 dienas nākotnē, ja vien tirgotājs un Klarna nav vienojušies par citu maksimumu.","bankTransferDueDateLimitReached":"Nav iespējams iestatīt pasūtījuma ilgumu ilgāk par 100 dienām."},"support":{"modalTitle":"Pieprasīt Mollie atbalstu","btnCancel":"Atcelt","btnConfirm":"Pieprasīt atbalstu","btnSupport":"Vairāk par mūsu atbalstu","form":{"name":"Jūsu vārds","email":"Jūsu e-pasts","recipient":"Nosūtīt pieprasījumu uz","subject":"Temats","message":"Ziņojums"},"data":{"header":"Dati nosūtīti uz Mollie:","other":"Citi:","shopwareVersion":"Shopware versija","pluginLogs":"{plugin} žurnāla faili","pluginConfiguration":"{plugin} konfigurācija","pluginConfigurationHelpText":"API atslēgas ir izslēgtas.","paymentMethods":"Maksājumu metodes informācija","paymentMethodsHelpText":"Satur informāciju par to, kuras maksājuma metodes ir aktīvas un piešķirtas katram pārdošanas kanālam, kā arī to statusu jūsu Mollie kontā."},"success":"Atbalsta pieprasījums ir veiksmīgi nosūtīts. Mēs darām visu iespējamo, lai atbildētu cik ātri vien iespējams.","error":"Radās problēma, nosūtot e-pastu caur Shopware. Lūdzu, mēģiniet vēlreiz vai sazinieties ar mums tieši pa e-pastu."}},"rules":{"itemSubscriptionRule":"Prece ir abonements (Mollie)","cartSubscriptionRule":"Grozs ar abonementiem (Mollie)"},"refunds":{"status":{"queued":"Kārtots","pending":"Procesā esošs","processing":"Apstrādā","refunded":"Atmaksāts","failed":"Neizdevies","description":{"queued":"Atmaksa ir kārtota, līdz ir pietiekams atlikums, lai apstrādātu atmaksu. Jūs joprojām varat atcelt atmaksu.","pending":"Atmaksa tiks nosūtīta uz banku nākamajā darba dienā. Jūs joprojām varat atcelt atmaksu.","processing":"Atmaksa ir nosūtīta uz banku. Atmaksātā summa tiks pārskaitīta uz patērētāja kontu pēc iespējas ātrāk.","refunded":"Atmaksas summa ir pārsūtīts patērētājam.","failed":"Atmaksa neizdevās pēc apstrādes. Piemēram, klients ir slēdzis savu bankas kontu. Līdzekļi tiks atgriezti jūsu kontā."}}},"refund-manager":{"general":{"unitQuantity":"gab."},"acl":{"warningCreate":"Jums nav atļauju veidot atmaksas","warningCancel":"Jums nav atļauju atcelt atmaksas"},"cart":{"title":"Pasūtījums ##orderNumber##","btnSelectAll":"Atlasīt visus","btnResetForm":"Atjaunot formu","linkHowTo":"Kā izmantot šo formu?","grid":{"columns":{"item":"Prece","productNumber":"Produkta numurs","unitPrice":"Vienības cena","quantity":"Daudzums","refunded":"Atmaksāts","refundQuantity":"Atmaksa","totalPrice":"Kopā","refundAmount":"Atmaksa","resetStock":"Atjaunot krājumus"},"btnResetLine":"Atiestatīt rindu","checkDeductPromotion":"Atcelt akciju","checkRefundTax":"Atmaksāt PVN"},"roundDiffItemAdded":"Automātiskā noapaļošanas vienība tika pievienota"},"instructions":{"linkResetTutorials":"Atjaunot apmācības","btnToggleTutorial":"Rādīt/Slēpt apmācību","titleFullRefund":"Pilna atmaksa","textFullRefund":"Vienkārši izmantojiet pogu pilnīgai atmaksai. Tas nodrošina, ka visas jūsu preces tiek atzītas par atgrieztām un pilna summa tiek atgriezta klientam.","titleStockReset":"Krājuma atiestatīšana","textStockReset":"Jūs varat automātiski palielināt pieejamo krājumu, ievadot daudzumu, kuru vēlaties atgriezt krājumā. Vienkārši ievadiet to, pirms turpināt ar pilnu vai daļēju atmaksu. Krājumu atiestatīšanu var elastīgi apvienot ar faktiskā atmaksas procesa veikšanu.","titleShipping":"Piegāde","textShipping":"Piegādes priekšmetus var atmaksāt kā jebkuru citu preces priekšmetu. Ievadiet pilnu daudzumu vai pielāgotu daļēju summu un turpiniet ar atmaksu. Piegādes izmaksu atmaksa var tikt elastīgi kombinēta ar faktisko priekšmetu atmaksas procesu.","titlePartialAmount":"Daļēja atmaksa (tikai daudzums)","textPartialAmount":"Vienkārši ievadiet daļēju summu teksta laukā un sāciet atmaksu.","titlePartialItems":"Daļēja atmaksa (ar precēm)","textPartialItems":"Ja vēlaties atzīmēt daudzumus un priekšmetus kā atmaksātus Mollie, izmantojiet iepriekš minēto formu. Iestatiet savus daudzumus un norādiet pielāgotu summu katram priekšmetam, kas tiks atmaksāts. Kopējā summa tad būs redzama galīgās atmaksas summas tekstlaukā. Atcerieties, ka joprojām ir iespējams pielāgot šo galīgo summu pirms atmaksas uzsākšanas.","titlePartialPromotions":"Daļēja atmaksa (ar akcijām)","textPartialPromotions":"Ja jums ir akcija savā grozā, tad jūsu akcija ir atsevišķa rindas vienība. Ja vēlaties atmaksāt visas atlaides preces, turpiniet un atmaksājiet to kopējās vērtības un pilnīgu akcijas rindas vienību pati. Tomēr, ja vēlaties atmaksāt tikai dažas atlaides preces, jūs varat automātiski atņemt piemēroto atlaidi katram atsevišķam rindas vienībai. Protams, jūs vienmēr varat mainīt vērtības, ja tās nav pareizas.","titleRoundingDiff":"Noapaļošanas atšķirība","textRoundingDiff":"Pilna atmaksa iekļaus noapaļošanas atšķirības"},"summary":{"dataLoading":"Dati tiek ielādēti...","headerExcludingVat":"Bez PVN","headerIncludingVat":"Ar PVN","captionTotal":"Kopā","captionTotalTaxFree":"Kopā","captionPendingRefunds":"Gaida atgriešanu","captionVouchers":"Kupona summa","captionRefunded":"Atmaksātā summa","captionRemaining":"Atmaksājamā summa","btnFixDiff":"Labot atšķirību","placeholderDescription":"Ievadiet bankas/kartes izrakstu aprakstu patērētājam. Maks. 140 zīmes","lblDescription":"Apraksts (pēc izvēles) ({characters}/140 rakstzīmes)","descriptionHelp":"Kad tas ir iespējams, tas tiks rādīts patērētāja bankas vai kartes izrakstā. Ziņojums tiks saīsināts pēc 140 rakstzīmēm.","placeholderInternalDescription":"Ievadiet savu iekšējo aprakstu","lblInternalDescription":"Iekšējais apraksts (pēc izvēles)","internalDescriptionHelp":"Šis tiks rādīts kā vietējā apraksts administrācijas interfeisā.","checkVerification":"Es esmu pārbaudījis kopējo atmaksas summu un konfigurētos daudzumus atmaksai un piegādei.","btnRefund":"Atmaksa","btnFullRefund":"Pilna atmaksa","roundDiffItemAdded":"Noapaļošanas pozīcija"},"refunds":{"title":"Atmaksas Mollie vadības panelī","linkMore":"Vairāk par atmaksām","grid":{"columns":{"amount":"Daudzums","status":"Statuss","description":"Apraksts","internalDescription":"Iekšējais apraksts","composition":"Kompozīcija","date":"Datums"},"lblNoComposition":"Nav pieejama kompozīcija","btnCancelRefund":"Atcelt šo atmaksu"}},"notifications":{"success":{"refund-created":"Atmaksa ir izveidota Mollie. Var paiet 2 stundas, līdz atmaksas process pabeigts. Līdz tam brīdim jūs varat atcelt atmaksu.","refund-canceled":"Procesā esošā atmaksāšana ir veiksmīgi atcelta un noņemta."},"error":{"low-amount":"Lūdzu, ievadiet summu, kas jāatmaksā.","refund-created":"Kaut kas nogāja greizi, veidojot atmaksu.","refund-canceled":"Radās problēma, atceļot procesā esošo atmaksu. Lūdzu, mēģiniet vēlreiz Mollie informācijas paneļā."}}},"vouchers":{"CARD_TITLE":"Kupons","VOUCHER_INFO_TITLE":"Kupona maksājumi","VOUCHER_INFO_DESCRIPTION":"Mollie ļauj jums viegli pieņemt maksājumus jūsu tiešsaistes veikalā, izmantojot ekoloģiskos, dāvanu un ēdienu kuponus — gudra izvēle, lai palielinātu pārdošanu un apmierinātu jūsu klientus. Maksājuma metode \\"kupons\\" ir redzama tikai tad, ja grozā ir vismaz 1 produkts ar piešķirtu kupona veidu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Lūdzu, ņemiet vērā, ka šo konfigurāciju var rediģēt tikai jūsu noklusējuma valodā! Lūdzu, mainiet savu valodu, lai mainītu šī produkta kupona veidu!","VOUCHER_BTN_READMORE":"Lasiet vairāk","VOUCHER_TYPE_CAPTION":"Produkta kupona veids","VOUCHER_TYPE_VALUE_NONE":"Nav","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Maltīte","VOUCHER_TYPE_VALUE_VOUCHER":"Dāvana"},"modals":{"shipping":{"title":"Nosūtīt caur Mollie","item":{"label":"Prece:","noQuantity":"Lūdzu, ievadiet daudzumu, kas jānosūta!","shipAll":"Nosūtīt visu","summary":{"quantity":"Nosūtāmais daudzumu","shipped":"Nosūtītais daudzums","shippable":"Nosūtāmo preču daudzums"},"success":"Pasūtījums veiksmīgi nosūtīts."},"order":{"description":"Sekojamo preču daudzumi tiks nosūtīti.","itemHeader":"Prece","quantityHeader":"Daudzums","originalQuantityHeader":"Daudzums (nosūtāms)"},"availableTracking":{"label":"Pieejamie izsekošanas kodi","hint":"Noklikšķiniet uz viena no šiem izsekošanas kodiem, lai automātiski aizpildītu visus datus."},"showTracking":"Pievienot izsekošanas informāciju šai sūtījumam","tracking":{"carrier":"Pārvadātājs","code":"Kods","url":"Url","invalid":"Lūdzu, ievadiet gan pārvadātāju, gan kodu"},"confirmButton":"Nosūtīt pasūtījumu","cancelButton":"Atcelt","selectAllButton":"Izvēlēties visu","resetButton":"Atjaunot"},"cancel":{"title":"Atcelt preci caur Mollie","confirmButton":"Atcelt preci caur Mollie","cancelButton":"Aizvērt modālo logu","resetStock":"Atjaunot krājumus","item":{"success":"Produkts veiksmīgi atcelts","failed":{"quantityZero":"Daudzums ir 0","invalidLine":"Produkta nav pasūtījumā","quantityTooHigh":"Daudzums ir pārāk liels"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Nosūtīt pasūtījumu (Mollie)","description":"Nosūtīt pasūtījumu caur Mollie."},"modal":{"title":"Nosūtīt pasūtījumu","description":"Šī darbība automātiski nosūtīs pasūtījumu, izmantojot Mollie. Procesa secība saņems pasūtījuma numuru un nodos to Mollie API. Veiksmīgas nosūtīšanas un neizdevušās nosūtīšanas būs redzamas Mollie žurnāla failos.","warningConfig":"Lūdzu, pārliecinieties, ka izslēdzāt visas papildu automatizācijas šī veida darbībām, lai izvairītos no iejaukšanās.\\nŠīs spraudņa aktivētās funkcijas var traucēt šo darbību:","noWarnings":"Nav brīdinājumu"}},"refundOrder":{"editor":{"title":"Atmaksāt pasūtījumu (Mollie)","description":"Atmaksāt pasūtījumu caur Mollie."},"modal":{"title":"Atmaksāt pasūtījumu","description":"Šī darbība automātiski uzsāks atmaksu caur Mollie. Darbības secība saņems pasūtījuma numuru un nosūtīs to uz Mollie API. Veiksmīgās atmaksas un neveiksmīgās atmaksas būs redzamas Mollie žurnāla failos.","warning":"Lūdzu, ņemiet vērā, ka atmaksas var ilgt līdz 2 stundām, lai tiktu pabeigtas un redzamas veikalā. Līdz tam jūs vienmēr varat atcelt gaidošo atmaksu, vai nu no pasūtījuma lapas Shopware, vai no Mollie Dashboard.","warningConfig":"Lūdzu, pārliecinieties, ka izslēdzāt visas papildu automatizācijas šī veida darbībām, lai izvairītos no iejaukšanās."}},"warnings":{"automaticShipping":"Automātiskā piegāde spraudņa konfigurācijā"}}},"subscriptions":{"status":{"pending":"Procesā esošs","active":"Aktīvs","canceled":"Atcelts","suspended":"Pārtraukts","completed":"Pabeigts","paused":"Pauzēts","resumed":"Turpināts","skipped":"Izlaists"},"navigation":{"title":"Mollie Subscriptions"},"TYPE_DAYS":"Diena(-s)","TYPE_WEEKS":"Nedēļa(-s)","TYPE_MONTHS":"Mēnesis(-ši)","confirm":{"cancelTitle":"Atcelt abonementu?","cancel":"Atcelt klienta abonementu.","pauseTitle":"Pauzēt abonementu?","pause":"Nolikt abonementu uz gaidīšanu līdz jūs to atkal atsākat.","resumeTitle":"Atjaunot abonementu?","resume":"Turpināt abonementu vēlreiz.","skipTitle":"Izlaist nākamo iemaksu?","skip":"Izlaidiet nākamo maksājumu abonementā. Pēc tam tas automātiski turpinās."},"alerts":{"cancelSuccess":"Abonements tika veiksmīgi atcelts","pauseSuccess":"Abonements ir veiksmīgi pauzēts","resumeSuccess":"Abonements ir veiksmīgi atjaunots","skipSuccess":"Abonements ir veiksmīgi izlaists. Nākamais maksājums ir atjaunināts."},"list":{"title":"Mollie Subscriptions","columns":{"customer":"Klients","status":"Statuss","description":"Apraksts","amount":"Daudzums","nextPaymentAt":"Nākamais maksājums","prePaymentReminder":"Atgādināts par","canceledAt":"Atcelts pie","createdAt":"Izveidots pie"},"action":{"edit":"Rediģēt abonementu"},"deletedCustomer":"Izdzēsts klients"},"detail":{"title":"Mollie abonements","buttonCancelSubscription":"Atcelt abonementu","labelDescription":"Apraksts","labelAmount":"Daudzums","labelQuantity":"Daudzums","labelMollieSubscription":"Mollie Subscription","labelMollieCustomer":"Mollie klients","labelMandateId":"Pilnvarot","labelShopwareCustomer":"Shopware klients","labelCreatedAt":"Izveidots pie","buttonShowShopwareOrder":"Rādīt Shopware pasūtījumu","buttonShowShopwareCustomer":"Rādīt Shopware klientu","cardTitleSubscription":"Abonements","cardTitleStatus":"Statuss","labelStatus":"Statuss","labelNextPaymentAt":"Nākamais maksājums pie","labelLastRemindedAt":"Pēdējais atgādinājums pie","labelCanceledAt":"Atcelts pie","buttonPauseSubscription":"Pauzēt abonementu","buttonResumeSubscription":"Atjaunot abonementu","buttonSkipSubscription":"Izlaist abonementu","history":{"cardTitle":"Vēsture","colDate":"Datums","colComment":"Komentārs","colStatusFrom":"Statuss (no)","colStatusTo":"Statuss (uz)","colMollieSubscription":"Mollie abonements"}},"product":{"card-title":"Abonements","title":"Mollie Subscriptions","description":"Jūsu regulāro maksājumu pārvaldīšana ir vieglāka nekā jebkad agrāk ar mūsu noderīgajām funkcijām. Paceliet savu biznesu jaunā līmenī ar efektīvām izsekosanas iespējām, vienkāršām integrācijām un vairāk. Ar Mollie abonementiem jūs varat viegli izveidot abonementa produktus un ieplānot regulārus maksājumus, lai tie notiktu noteiktajos intervālos un periodos.","mollieSubscriptionProduct":"Abonementa Produkts","mollieSubscriptionIntervalAmount":"Atkārtot maksājumu katru","mollieSubscriptionIntervalType":"Intervāla vienība","mollieSubscriptionRepetitionAmount":"Atkārtojumu skaits","mollieSubscriptionRepetitionPlaceholder":"Ievadiet skaitli vai atstājiet tukšu","infoDefaultLanguage":"Lūdzu, ņemiet vērā, ka šo konfigurāciju varat rediģēt tikai savā noklusējuma valodā. Lūdzu, mainiet valodu, lai modificētu šī produkta abonementa iestatījumus.","btnReadMore":"Lasiet vairāk"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonements"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Kredītkartes dati","buttonMolliePaymentLink":"Kopēt uz starpliktuvi","columnRefunded":"Atmaksāts","columnShipped":"Nosūtīts","columnCanceled":"Atcelts","labelMollieOrderId":"Mollie Order ID","labelMollieThirdPartyPaymentId":"Maksājuma atsauce","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Atmaksātā summa","totalRefundsPending":"Gaidot atmaksu","totalRemaining":"Atmaksājamā summa","totalVouchers":"Kupona summa","totalShipments":"Nosūtītā summa ({quantity} priekšmeti)","subscriptionBadge":"Abonementa Pasūtījums","refundManager":{"title":"Mollie Refund Manager","btnOpenRefundManager":"Atvērt Refund Manager","btnCloseRefundManager":"Aizvērt Refund Manager"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Vēlamā iDEAL izsniedzējs"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Atmaksas pārvaldnieks"},"mollie_subscription":{"label":"Abonementi"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Apraksts"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Atmaksa","subscription":"Abonements","webhookReceived":"Webhooks","status":"Statuss","started":"Sācies","ended":"Beidzies","paused":"Pauzēts","renewalReminder":"Atjaunošanas atgādinājums","renewed":"Atjaunots","resumed":"Atjaunots","skipped":"Izlaists","all":"Visi","canceled":"Atcelts","expired":"Beidzies","partiallyRefunded":"Atmaksāts (daļēji)","orderSuccess":"Pasūtījums veiksmīgs","orderFailed":"Pasūtījums neizdevās","orderCanceled":"Pasūtījums atcelts"}}}'),e3=JSON.parse('{"global":{"entities":{"mollie_subscription":"Abonament Mollie | Abonamente Mollie"},"businessEvents":{"mollie_checkout_order_success":" Comandă reușită","mollie_checkout_order_failed":" Comandă eșuată","mollie_checkout_order_canceled":" Comandă anulată","mollie_webhook_received_All":" Webhook Mollie primit (Toate)","mollie_webhook_received_status_authorized":" Webhook Mollie primit (Autorizat)","mollie_webhook_received_status_failed":" Webhook Mollie primit (Eșuat)","mollie_webhook_received_status_canceled":"Webhook Mollie primit (Anulat)","mollie_webhook_received_status_expired":"Webhook Mollie primit (Expirat)","mollie_webhook_received_status_pending":" Webhook Mollie primit (\xcen așteptare)","mollie_webhook_received_status_paid":" Webhook Mollie primit (Plătit)","mollie_webhook_received_status_completed":" Webhook Mollie primit (Finalizat)","mollie_webhook_received_status_refunded":" Webhook Mollie primit (Rambursat)","mollie_webhook_received_status_partially_refunded":" Webhook Mollie primit (Rambursat parțial)","mollie_refund_started":" Rambursarea Mollie a \xeenceput","mollie_subscription_started":" Abonamentul Mollie a \xeenceput","mollie_subscription_ended":" Abonament Mollie finalizat","mollie_subscription_cancelled":" Abonament Mollie anulat","mollie_subscription_paused":" Abonament Mollie suspendat","mollie_subscription_resumed":" Abonamentul Mollie a fost reluat","mollie_subscription_skipped":" Abonamentul Mollie a fost omis","mollie_subscription_renewed":" Abonamentul Mollie s-a re\xeennoit","mollie_subscription_renewal_reminder":" Memento Mollie pentru re\xeennoirea abonamentului"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Modul Mollie","searchPlaceholder":"Căutați abonamente...","general":{"mainMenuItemGeneral":"Plăți Mollie","descriptionTextModule":"Plăți Mollie","btnMollieActions":"Acțiuni Mollie","refundThroughMollie":"Rambursare prin Mollie","shipThroughMollie":"Expediere prin Mollie","cancelMollieItem":"Anulare prin Mollie"},"config":{"info":{"title":"Bună {userName}, Bine ai venit la Mollie!","descriptionTop":"Onboardingul este ușor cu Mollie!","descriptionBottom":"Asta e tot!","descriptionFooter":"Dacă doriți să aflați mai multe despre pluginul nostru, vizitați pagina noastră oficială de informații.","onboardingStep1":"\xcenregistrează-te pentru un cont Mollie.","onboardingStep2":"Introduceți codurile dumneavoastră API \xeen secțiunea de mai jos.","onboardingStep2TestMode":"Activați \'Mod Test\' dacă doriți să testați doar plățile.","onboardingStep3":"Atribuiți metode de plată canalelor de v\xe2nzare.","onboardingStep3Link":"pentru canalele de v\xe2nzare","btnDocumentation":"Documentație","btnRequestSupport":"Asistență","btnTroubleshooting":"Ghid de soluționare a problemelor"},"api":{"apiLinkButton":"Obțineți codurile API de pe tabloul de bord Mollie","testButton":"Testează codurile API","testApiKeys":{"title":"Plăți Mollie","apiKey":"Cod API","isValid":"este valid","isInvalid":"este invalid"}},"payments":{"format":{"placeholder":"Placeholder","preview":"Previzualizare"},"updatePaymentMethods":{"title":"Plăți Mollie","button":"Actualizează metodele de plată","succeeded":"Metodele de plată au fost actualizate cu succes.","failed":"Metodele de plată nu au putut fi actualizate."},"mollieLimits":{"link":"Afișați regulile de disponibilitate Mollie pentru metodele de plată"}},"rounding":{"info1":"Shopware poate utiliza setările valutare pentru a calcula cum rotunjește suma totală a unei comenzi. Aceasta include numărul de zecimale din prețurile produselor și intervalul de rotunjire cel mai apropiat, cum ar fi 0,50 sau 1,00.","info2":"Aceste setări pot duce la un total general diferit față de suma totală a elementelor de linie. Atunci c\xe2nd Mollie verifică aceste sume și constată că nu se potrivesc, aceasta provoacă o eroare la finalizarea comenzii.","info3":"Puteți folosi această funcție pentru a evita problemele de rotunjire \xeen finalizarea comenzii. C\xe2nd este activată, ea adaugă un element de linie separat \xeen tabloul de bord Mollie pentru diferența de rotunjire, iar clienții dumneavoastră plătesc suma totală calculată de Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nu este posibil să folosiți Klarna Plătiți acum, Klarna \xcempărțiți sau Klarna Plătiți mai t\xe2rziu ca metodă atunci c\xe2nd data limită este mai mare de 28 de zile \xeen viitor, cu excepția cazului \xeen care un alt maxim este convenit \xeentre comerciant și Klarna.","bankTransferDueDateLimitReached":"Nu este posibil să setați durata de viață a comenzii mai mare de 100 de zile."},"support":{"modalTitle":"Solicitați asistență de la Mollie","btnCancel":"Anulați","btnConfirm":"Solicitați asistență","btnSupport":"Mai multe despre asistența noastră","form":{"name":"Numele dumneavoastră","email":"Emailul dumneavoastră","recipient":"Trimiteți cererea la","subject":"Subiect","message":"Mesaj"},"data":{"header":"Date trimise către Mollie:","other":"Altele:","shopwareVersion":"Versiunea Shopware","pluginLogs":"Fișierele log {plugin}","pluginConfiguration":"Configurația {plugin}","pluginConfigurationHelpText":"Codurile API sunt excluse.","paymentMethods":"Datele metodei de plată","paymentMethodsHelpText":"Conține informații despre care metode de plată sunt active, atribuite fiecărui canal de v\xe2nzare, precum și statusul lor \xeen contul dumneavoastră Mollie."},"success":"Cererea de asistență a fost trimisă cu succes. Facem tot posibilul să răspundem c\xe2t mai repede posibil","error":"A apărut o problemă la trimiterea mailului prin Shopware. Vă rugăm să \xeencercați din nou sau să ne contactați direct prin e-mail."}},"rules":{"itemSubscriptionRule":"Articolul este un abonament (Mollie)","cartSubscriptionRule":"Coș cu abonamente (Mollie)"},"refunds":{"status":{"queued":"\xcen așteptare","pending":"\xcen așteptare","processing":"Se procesează","refunded":"Rambursat","failed":"Eșuat","description":{"queued":"Rambursarea este \xeen așteptare p\xe2nă c\xe2nd există suficient sold pentru a procesa rambursarea. Puteți, de asemenea, să anulați rambursarea.","pending":"Rambursarea va fi trimisă băncii \xeen următoarea zi lucrătoare. Puteți, de asemenea, să anulați rambursarea.","processing":"Rambursarea a fost trimisă băncii. Suma rambursată va fi transferată contului consumatorului c\xe2t mai cur\xe2nd posibil.","refunded":"Suma rambursării a fost transferată către consumator.","failed":"Rambursarea a eșuat după procesare. De exemplu, clientul și-a \xeenchis contul bancar. Fondurile vor fi returnate \xeen contul dvs."}}},"refund-manager":{"general":{"unitQuantity":"buc."},"acl":{"warningCreate":"Nu aveți permisiuni pentru a crea rambursări","warningCancel":"Nu aveți permisiuni pentru a anula rambursările"},"cart":{"title":"Comanda ##orderNumber##","btnSelectAll":"Selectați tot","btnResetForm":"Resetați formularul","linkHowTo":"Cum să folosiți acest formular?","grid":{"columns":{"item":"Articol","productNumber":"Numărul produsului","unitPrice":"Preț unitar","quantity":"Cantitate","refunded":"Rambursat","refundQuantity":"Rambursare","totalPrice":"Total","refundAmount":"Rambursare","resetStock":"Resetați stocul"},"btnResetLine":"Resetați linia","checkDeductPromotion":"Scădeți promoția","checkRefundTax":"Rambursare TVA"},"roundDiffItemAdded":"Articolul de rotunjire a fost adăugat"},"instructions":{"linkResetTutorials":"Resetați tutorialele","btnToggleTutorial":"Arată/Ascunde tutorialul","titleFullRefund":"Rambursare totală","textFullRefund":"Trebuie doar să folosiți butonul pentru rambursarea totală. Acest lucru asigură că toate articolele dvs. sunt marcate ca fiind rambursate și \xeentreaga sumă este returnată clientului.","titleStockReset":"Resetare stoc","textStockReset":"Puteți crește automat stocul disponibil introduc\xe2nd cantitatea pe care doriți să o repuneți \xeen stoc. Introduceți-o \xeenainte de a continua cu o rambursare totală sau parțială. Resetarea stocului poate fi combinată cu procesul efectiv de rambursare \xeentr-un mod flexibil.","titleShipping":"Livrare","textShipping":"Articolele de livrare pot fi rambursate ca orice alt articol de produs. Fie introduceți cantitatea totală, fie o sumă parțială personalizată și continuați cu rambursarea. Rambursarea costurilor de livrare poate fi combinată cu procesul efectiv de rambursare a articolelor \xeentr-un mod flexibil.","titlePartialAmount":"Rambursare parțială (doar suma)","textPartialAmount":"Doar introduceți suma parțială \xeen c\xe2mpul de text și \xeencepeți rambursarea.","titlePartialItems":"Rambursare parțială (cu articole)","textPartialItems":"Dacă doriți să marcați cantitățile și articolele ca fiind rambursate \xeen Mollie, folosiți formularul de mai sus. Stabiliți cantitățile dvs. și oferiți o sumă personalizată pentru fiecare articol care va fi rambursat. Suma totală va fi apoi vizibilă \xeen c\xe2mpul de text pentru suma finală a rambursării. Amintiți-vă, este \xeencă posibil să ajustați această sumă finală \xeenainte de a \xeencepe rambursarea.","titlePartialPromotions":"Rambursare parțială (cu promoții)","textPartialPromotions":"Dacă aveți o promoție \xeen coșul dvs., atunci promoția dvs. este un element de linie separat. Dacă doriți să rambursați toate articolele reduse, continuați și rambursați valorile lor totale și \xeentreaga linie de promoție. Cu toate acestea, dacă doriți să rambursați doar c\xe2teva articole care au fost reduse, puteți scădea automat discountul aplicat pentru fiecare linie. Desigur, puteți \xeentotdeauna schimba valorile dacă nu sunt corecte.","titleRoundingDiff":"Diferență de rotunjire","textRoundingDiff":"O rambursare totală va include diferențele de rotunjire"},"summary":{"dataLoading":"Datele se \xeencarcă...","headerExcludingVat":"Excl. TVA","headerIncludingVat":"Incl. TVA","captionTotal":"Total","captionTotalTaxFree":"Total","captionPendingRefunds":"Așteaptă să fie rambursat","captionVouchers":"Suma voucherului","captionRefunded":"Suma rambursată","captionRemaining":"Suma rambursabilă","btnFixDiff":"Corectați diferența","placeholderDescription":"Introduceți descrierea extrasului bancar/de cont pentru consumator. Max 140 de caractere","lblDescription":"Descriere (opțională) ({characters}/140 de caractere)","descriptionHelp":"Aceasta va fi afișată pe extrasul bancar sau de cont al consumatorului, atunci c\xe2nd este posibil. Mesajul nu poate depăși 140 de caractere.","placeholderInternalDescription":"Introduceți descrierea dumneavoastră internă","lblInternalDescription":"Descriere internă (opțională)","internalDescriptionHelp":"Aceasta va fi afișată ca o descriere locală \xeen interfața de administrare.","checkVerification":"Am verificat suma totală a rambursării și cantitățile configurate pentru rambursare și re-stocare.","btnRefund":"Rambursare","btnFullRefund":"Rambursare totală","roundDiffItemAdded":"Articol de rotunjire"},"refunds":{"title":"Rambursări \xeen tabloul de bord Mollie","linkMore":"Mai multe despre rambursări","grid":{"columns":{"amount":"Sumă","status":"Status","description":"Descriere","internalDescription":"Descriere internă","composition":"Compoziție","date":"Dată"},"lblNoComposition":"Nicio compoziție disponibilă","btnCancelRefund":"Anulați această rambursare"}},"notifications":{"success":{"refund-created":"O rambursare a fost creată \xeen Mollie. Poate dura p\xe2nă la 2 ore pentru a finaliza rambursarea. P\xe2nă atunci, puteți anula rambursarea.","refund-canceled":"Rambursarea \xeen așteptare a fost anulată cu succes și eliminată."},"error":{"low-amount":"Vă rugăm să introduceți o sumă care să fie rambursată.","refund-created":"A apărut o problemă la crearea unei rambursări.","refund-canceled":"A existat o problemă la anularea rambursării \xeen așteptare. Vă rugăm să \xeencercați din nou \xeen tabloul de bord Mollie."}}},"vouchers":{"CARD_TITLE":"Voucher","VOUCHER_INFO_TITLE":"Plăți prin voucher","VOUCHER_INFO_DESCRIPTION":"Mollie vă permite să acceptați cu ușurință plăți \xeen magazinul dvs. online folosind vouchere ecologice, de cadou și de masă—o alegere inteligentă pentru a crește v\xe2nzările și a anticipa clienții dvs.. Metoda de plată \\"voucher\\" este vizibilă doar dacă aveți cel puțin 1 produs cu un tip de voucher asociat \xeen coș.","VOUCHER_INFO_DEFAULTLANGUAGE":"Vă rugăm să rețineți, că această configurație poate fi editată doar \xeen limba dvs. implicită. Vă rugăm să schimbați limba pentru a modifica tipul de voucher al acestui produs.","VOUCHER_BTN_READMORE":"Citiți mai mult","VOUCHER_TYPE_CAPTION":"Tip voucher al produsului","VOUCHER_TYPE_VALUE_NONE":"Niciunul","VOUCHER_TYPE_VALUE_ECO":"Eco","VOUCHER_TYPE_VALUE_MEAL":"Masă","VOUCHER_TYPE_VALUE_VOUCHER":"Cadou"},"modals":{"shipping":{"title":"Expediați prin Mollie","item":{"label":"Articol:","noQuantity":"Vă rugăm să introduceți o cantitate de expediat.","shipAll":"Expediați tot","summary":{"quantity":"Cantitate de expediat","shipped":"Cantitate expediată","shippable":"Cantitate expediabilă"},"success":"Comanda a fost expediată cu succes."},"order":{"description":"Următoarele cantități de articole vor fi expediate.","itemHeader":"Articol","quantityHeader":"Cantitate","originalQuantityHeader":"Cantitate (expediabilă)"},"availableTracking":{"label":"Coduri de urmărire disponibile","hint":"Faceți clic pe unul dintre aceste coduri de urmărire pentru a completa automat toate datele."},"showTracking":"Adăugați informații de urmărire pentru această expediere","tracking":{"carrier":"Transportator","code":"Cod","url":"Url","invalid":"Vă rugăm să introduceți at\xe2t Transportator, c\xe2t și Cod"},"confirmButton":"Expediați comanda","cancelButton":"Anulați","selectAllButton":"Selectați tot","resetButton":"Resetare"},"cancel":{"title":"Anulați articolul prin mollie","confirmButton":"Anulați articolul prin mollie","cancelButton":"\xcenchideți modalul","resetStock":"Resetare stocuri","item":{"success":"Produs anulat cu succes","failed":{"quantityZero":"Cantitatea este 0","invalidLine":"Produsul nu există \xeen comandă","quantityTooHigh":"Cantitatea este prea mare"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Expediați comanda (Mollie)","description":"Expediați comanda \xeen Mollie."},"modal":{"title":"Expediați comanda","description":"Această acțiune va expedia automat o comandă prin Mollie. Secvența de flux va primi numărul comenzii și \xeel va transmite la API-ul Mollie. Expedierile reușite și cele eșuate vor fi vizibile \xeen fișierele de jurnal Mollie.","warningConfig":"Vă rugăm să vă asigurați că opriți orice automatizare suplimentară pentru acest tip de acțiune pentru a evita interferențele.\\nUrmătoarele funcții activate ale acestui plugin ar putea interfera cu această acțiune:","noWarnings":"Nu există avertismente"}},"refundOrder":{"editor":{"title":"Rambursați comanda (Mollie)","description":"Rambursați comanda prin Mollie."},"modal":{"title":"Rambursați comanda","description":"Această acțiune va porni automat o rambursare prin Mollie. Secvența de flux va primi numărul comenzii și \xeel va transmite la API-ul Mollie. Rambursările reușite și cele eșuate vor fi vizibile \xeen fișierele de jurnal Mollie.","warning":"Vă rugăm să rețineți, că rambursările pot dura p\xe2nă la 2 ore pentru a fi finalizate și vizibile \xeen magazin. P\xe2nă atunci, puteți anula \xeentotdeauna o rambursare \xeen așteptare fie din pagina comenzii \xeen Shopware, fie din tabloul de bord Mollie.","warningConfig":"Vă rugăm să vă asigurați că opriți orice automatizare suplimentară pentru acest tip de acțiune pentru a evita interferențele."}},"warnings":{"automaticShipping":"Expediere automată \xeen configurația plugin-ului"}}},"subscriptions":{"status":{"pending":"\xcen așteptare","active":"Activ","canceled":"Anulat","suspended":"Suspendat","completed":"Finalizat","paused":"Suspendat","resumed":"Reluat","skipped":"Sărit"},"navigation":{"title":"Abonamente Mollie"},"TYPE_DAYS":"Zi(le)","TYPE_WEEKS":"Săptăm\xe2nă(i)","TYPE_MONTHS":"Lună(i)","confirm":{"cancelTitle":"Anulare abonament?","cancel":"Anulați abonamentul clientului dvs..","pauseTitle":"Suspendare abonament?","pause":"Pune abonamentul pe pauză p\xe2nă c\xe2nd decizi să \xeel reactivezi.","resumeTitle":"Reactivați abonamentul?","resume":"Reluați abonamentul din nou.","skipTitle":"Sari peste următoarea rată?","skip":"Sari peste următoarea tranșă din abonament. Acesta continuă automat după aceea."},"alerts":{"cancelSuccess":"Abonamentul a fost anulat cu succes","pauseSuccess":"Abonamentul a fost pus pe pauză cu succes","resumeSuccess":"Abonamentul a fost reluat cu succes","skipSuccess":"Abonamentul a fost sărit cu succes. Următoarea plată a fost actualizată."},"list":{"title":"Abonamente Mollie","columns":{"customer":"Client","status":"Status","description":"Descriere","amount":"Sumă","nextPaymentAt":"Următoarea plată","prePaymentReminder":"Reamintit la","canceledAt":"Anulat la","createdAt":"Creat la"},"action":{"edit":"Editați abonamentul"},"deletedCustomer":"Client șters"},"detail":{"title":"Abonament Mollie","buttonCancelSubscription":"Anulați abonamentul","labelDescription":"Descriere","labelAmount":"Sumă","labelQuantity":"Cantitate","labelMollieSubscription":"Abonament Mollie","labelMollieCustomer":"Client Mollie","labelMandateId":"Mandat","labelShopwareCustomer":"Client Shopware","labelCreatedAt":"Creat la","buttonShowShopwareOrder":"Arată comanda Shopware","buttonShowShopwareCustomer":"Arată clientul Shopware","cardTitleSubscription":"Abonament","cardTitleStatus":"Status","labelStatus":"Status","labelNextPaymentAt":"Următoarea plată la","labelLastRemindedAt":"Ultima reamintire la","labelCanceledAt":"Anulat la","buttonPauseSubscription":"Pauza abonament","buttonResumeSubscription":"Reiați abonamentul","buttonSkipSubscription":"Sari peste abonament","history":{"cardTitle":"Istoric","colDate":"Data","colComment":"Comentariu","colStatusFrom":"Status (de la)","colStatusTo":"Status (p\xe2nă la)","colMollieSubscription":"Abonament Mollie"}},"product":{"card-title":"Abonament","title":"Abonamente Mollie","description":"Gestionarea plăților recurente este mai ușoară ca niciodată cu caracteristicile noastre utile. Duceți-vă afacerea la nivelul următor cu opțiuni eficiente de urmărire, integrații simple și multe altele. Cu abonamentele Mollie, puteți crea cu ușurință produse de abonament și programa plăți recurente care să aibă loc la intervalul și perioada configurate.","mollieSubscriptionProduct":"Produs de abonament","mollieSubscriptionIntervalAmount":"Repetă plata la fiecare","mollieSubscriptionIntervalType":"Unitate de interval","mollieSubscriptionRepetitionAmount":"Numărul de repetiții","mollieSubscriptionRepetitionPlaceholder":"Introduceți numărul sau lăsați gol","infoDefaultLanguage":"Vă rugăm să rețineți că această configurație poate fi editată doar \xeen limba dvs. implicită. Vă rugăm să schimbați limba pentru a modifica setările abonamentului pentru acest produs.","btnReadMore":"Citiți mai mult"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Abonament"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Date card de credit","buttonMolliePaymentLink":"Copiați \xeen clipboard","columnRefunded":"Rambursat","columnShipped":"Expediat","columnCanceled":"Anulat","labelMollieOrderId":"ID comandă Mollie","labelMollieThirdPartyPaymentId":"Referință plată","labelMolliePaymentLink":"URL Mollie Checkout","totalRefunds":"Sumă rambursată","totalRefundsPending":"Așteaptă să fie rambursat","totalRemaining":"Sumă rambursabilă","totalVouchers":"Sumă voucher","totalShipments":"Cantitate expediată ({quantity} articole)","subscriptionBadge":"Comandă de abonament","refundManager":{"title":"Mollie Refund Manager","btnOpenRefundManager":"Deschideți Refund Manager","btnCloseRefundManager":"\xcenchideți Refund Manager"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Emitent iDeal recomandat"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Refund Manager"},"mollie_subscription":{"label":"Abonamente"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Descriere"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Rambursare","subscription":"Abonament","webhookReceived":"Webhooks","status":"Status","started":"\xcenceput","ended":"Finalizat","paused":"Pus pe pauză","renewalReminder":"Memento de re\xeennoire","renewed":"Re\xeennoit","resumed":"Reluat","skipped":"Sărit","all":"Toate","canceled":"Anulat","expired":"Expirat","partiallyRefunded":"Rambursat (parțial)","orderSuccess":"Comandă reușită","orderFailed":"Comandă eșuată","orderCanceled":"Comandă anulată"}}}'),e6=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Predplatn\xe9 | Mollie Predplatn\xe9"},"businessEvents":{"mollie_checkout_order_success":"Objedn\xe1vka bola \xfaspešn\xe1","mollie_checkout_order_failed":"Objedn\xe1vka zlyhala","mollie_checkout_order_canceled":"Objedn\xe1vka bola zrušen\xe1","mollie_webhook_received_All":"Prijat\xfd Webhook Mollie (všetky)","mollie_webhook_received_status_authorized":"Mollie Webhook prijat\xfd (Autorizovan\xfd)","mollie_webhook_received_status_failed":"Mollie Webhook prijat\xfd (Zlyhalo)","mollie_webhook_received_status_canceled":"Mollie Webhook prijat\xfd (Zrušen\xfd)","mollie_webhook_received_status_expired":"Mollie Webhook prijat\xfd (Existuj\xfaci)","mollie_webhook_received_status_pending":"Mollie Webhook prijat\xfd (Čakaj\xfaci)","mollie_webhook_received_status_paid":"Mollie Webhook prijat\xfd (Zaplaten\xfd)","mollie_webhook_received_status_completed":"Mollie Webhook prijat\xfd (Dokončen\xfd)","mollie_webhook_received_status_refunded":"Mollie Webhook prijat\xfd (Vr\xe1ten\xfd)","mollie_webhook_received_status_partially_refunded":"Mollie Webhook prijat\xfd (Čiastočne vr\xe1ten\xfd)","mollie_refund_started":"Mollie vr\xe1tenie peňaz\xed bolo spusten\xe9","mollie_subscription_started":"Predplatn\xe9 Mollie bolo spusten\xe9","mollie_subscription_ended":"Mollie predplatn\xe9 dokončen\xe9","mollie_subscription_cancelled":"Mollie predplatn\xe9 zrušen\xe9","mollie_subscription_paused":"Mollie predplatn\xe9 pozastaven\xe9","mollie_subscription_resumed":"Predplatn\xe9 Mollie bolo znovu aktivovan\xe9","mollie_subscription_skipped":"Mollie predplatn\xe9 preskočen\xe9","mollie_subscription_renewed":"Mollie predplatn\xe9 bolo obnoven\xe9","mollie_subscription_renewal_reminder":"Mollie pripomienka na obnovenie predplatn\xe9ho"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Modul","searchPlaceholder":"Vyhľadajte predplatn\xe9...","general":{"mainMenuItemGeneral":"Mollie platby","descriptionTextModule":"Mollie platby","btnMollieActions":"Mollie akcie","refundThroughMollie":"Vr\xe1tenie peňaz\xed cez Mollie","shipThroughMollie":"Odoslať cez Mollie","cancelMollieItem":"Zrušiť cez Mollie"},"config":{"info":{"title":"Ahoj {userName}, Vitajte v Mollie!","descriptionTop":"Onboarding je s Mollie jednoduch\xfd!","descriptionBottom":"To je všetko!","descriptionFooter":"Ak sa chcete dozvedieť viac o našom plugine, navšt\xedvte našu ofici\xe1lnu str\xe1nku s dokument\xe1ciou.","onboardingStep1":"Zaregistrujte sa do \xfačtu Mollie.","onboardingStep2":"Zadajte svoje API kľ\xfače do sekcie nižšie.","onboardingStep2TestMode":"Zapnite \'Testovac\xed režim\', ak chcete testovať platby","onboardingStep3":"Priraďte platobn\xe9 met\xf3dy k svojmu predajn\xe9mu kan\xe1lu.","onboardingStep3Link":"k vaš\xedm predajn\xfdm kan\xe1lom","btnDocumentation":"Dokument\xe1cia","btnRequestSupport":"Podpora","btnTroubleshooting":"Pr\xedručka pre riešenie probl\xe9mov"},"api":{"apiLinkButton":"Z\xedskajte svoje API kľ\xfače z Mollie Dashboard","testButton":"Testovať API kľ\xfače","testApiKeys":{"title":"Mollie platby","apiKey":"API kľ\xfač","isValid":"je platn\xfd","isInvalid":"je neplatn\xfd"}},"payments":{"format":{"placeholder":"Z\xe1stupn\xfd text (Placeholder)","preview":"N\xe1hľad"},"updatePaymentMethods":{"title":"Mollie platby","button":"Aktualizovať platobn\xe9 met\xf3dy","succeeded":"Platobn\xe9 met\xf3dy boli \xfaspešne aktualizovan\xe9.","failed":"Platobn\xe9 met\xf3dy sa nepodarilo aktualizovať."},"mollieLimits":{"link":"Zobraziť pravidl\xe1 dostupnosti Mollie pre platobn\xe9 met\xf3dy"}},"rounding":{"info1":"Shopware m\xf4že použiť nastavenia meny na v\xfdpočet sp\xf4sobu zaokr\xfahľovania celkovej sumy objedn\xe1vky. To zahŕňa počet desatinn\xfdch miest v cen\xe1ch produktov a najbližš\xed interval zaokr\xfahľovania, napr\xedklad 0,50 alebo 1,00.","info2":"Tieto nastavenia m\xf4žu viesť k tomu, že celkov\xe1 suma objedn\xe1vky sa bude l\xedšiť od s\xfačtu jednotliv\xfdch položiek. Keď spoločnosť Mollie pri kontrole zist\xed, že sa tieto sumy nezhoduj\xfa, sp\xf4sob\xed to chybu pri dokončen\xed objedn\xe1vky.","info3":"T\xfato funkciu m\xf4žete použiť na zabr\xe1nenie probl\xe9mom so zaokr\xfahľovan\xedm pri pokladni. Ak je aktivovan\xe1, prid\xe1 samostatn\xfd riadok do v\xe1šho Mollie Dashboard pre rozdiel v zaokr\xfahľovan\xed a vaši z\xe1kazn\xedci zaplatia celkov\xfa sumu vypoč\xedtan\xfa programom Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Nie je možn\xe9 použiť met\xf3dy Klarna Pay now, Klarna Slice it ani Klarna Pay later, ak je d\xe1tum exspir\xe1cie viac ako 28 dn\xed vopred, pokiaľ sa medzi obchodn\xedkom a spoločnosťou Klarna nedohodne in\xfd maxim\xe1lny limit.","bankTransferDueDateLimitReached":"Nie je možn\xe9 nastaviť dobu platnosti objedn\xe1vky na viac ako 100 dn\xed."},"support":{"modalTitle":"Požiadať o podporu od Mollie","btnCancel":"Zrušiť","btnConfirm":"Požiadať o podporu","btnSupport":"Viac o našej podpore","form":{"name":"Vaše meno","email":"V\xe1š email","recipient":"Odoslať žiadosť na","subject":"Predmet","message":"Spr\xe1va"},"data":{"header":"\xdadaje odoslan\xe9 do Mollie:","other":"In\xe9:","shopwareVersion":"Verzia Shopware","pluginLogs":"{plugin} s\xfabory protokolu","pluginConfiguration":"{plugin} konfigur\xe1cia","pluginConfigurationHelpText":"API kľ\xfače s\xfa vyl\xfačen\xe9.","paymentMethods":"\xdadaje o platobnej met\xf3de","paymentMethodsHelpText":"Obsahuje inform\xe1cie o tom, ktor\xe9 platobn\xe9 met\xf3dy s\xfa akt\xedvne, priraden\xe9 k jednotliv\xfdm predajn\xfdm kan\xe1lom, ako aj ich stav vo vašom \xfačte Mollie."},"success":"Žiadosť o podporu bola \xfaspešne odoslan\xe1. Urob\xedme všetko pre to, aby sme v\xe1m odpovedali čo najsk\xf4r","error":"Pri odosielan\xed e-mailu cez Shopware nastal probl\xe9m. Sk\xfaste to znova alebo n\xe1s kontaktujte priamo e-mailom."}},"rules":{"itemSubscriptionRule":"Položka je predplatn\xe9 (Mollie)","cartSubscriptionRule":"Koš\xedk s predplatn\xfdm (Mollie)"},"refunds":{"status":{"queued":"Čak\xe1 sa","pending":"Čakaj\xface","processing":"Spracov\xe1vanie","refunded":"Refundovan\xe9","failed":"Zlyhalo","description":{"queued":"Vr\xe1tenie platby je v porad\xed a čak\xe1 na dostatočn\xfd zostatok na \xfačte na jeho spracovanie. St\xe1le ho m\xf4žete zrušiť.","pending":"Vr\xe1tenie platby bude odoslan\xe9 do banky nasleduj\xfaci pracovn\xfd deň. Vr\xe1tenie m\xf4žete st\xe1le zrušiť.","processing":"Vr\xe1tenie platby bude odoslan\xe9 do banky nasleduj\xfaci pracovn\xfd deň. Vr\xe1tenie m\xf4žete st\xe1le zrušiť.","refunded":"Refundovan\xe1 suma bola preveden\xe1 spotrebiteľovi.","failed":"Vr\xe1tenie platby zlyhalo po spracovan\xed. Napr\xedklad z\xe1kazn\xedk mohol zrušiť svoj bankov\xfd \xfačet. Prostriedky bud\xfa vr\xe1ten\xe9 na v\xe1š \xfačet."}}},"refund-manager":{"general":{"unitQuantity":"ks."},"acl":{"warningCreate":"Nem\xe1te opr\xe1vnenie na vytv\xe1ranie vr\xe1ten\xed platieb","warningCancel":"Nem\xe1te opr\xe1vnenia na zrušenie refund\xe1ci\xed"},"cart":{"title":"Objedn\xe1vka ##orderNumber##","btnSelectAll":"Vybrať všetko","btnResetForm":"Obnoviť formul\xe1r","linkHowTo":"Ako použ\xedvať tento formul\xe1r?","grid":{"columns":{"item":"Položka","productNumber":"Č\xedslo produktu","unitPrice":"Cena za kus","quantity":"Množstvo","refunded":"Refundovan\xe9","refundQuantity":"Refund\xe1cia","totalPrice":"Celkov\xe1 cena","refundAmount":"Refund\xe1cia","resetStock":"Obnoviť z\xe1soby"},"btnResetLine":"Obnoviť riadok","checkDeductPromotion":"Odpoč\xedtať zľavu","checkRefundTax":"Vr\xe1tit DPH"},"roundDiffItemAdded":"Položka automatick\xe9ho zaokr\xfahľovania bola pridan\xe1"},"instructions":{"linkResetTutorials":"Obnoviť n\xe1vody","btnToggleTutorial":"Zobraziť/Skryť n\xe1vod","titleFullRefund":"\xdapln\xe9 vr\xe1tenie peňaz\xed","textFullRefund":"Jednoducho použite tlačidlo na \xfapln\xe9 vr\xe1tenie peňaz\xed. T\xfdm sa zabezpeč\xed, že všetky položky bud\xfa označen\xe9 ako vr\xe1ten\xe9 a z\xe1kazn\xedkovi bude vr\xe1ten\xe1 cel\xe1 suma.","titleStockReset":"Resetovanie z\xe1sob","textStockReset":"M\xf4žete automaticky zv\xfdšiť dostupn\xfd zostatok zadan\xedm množstva, ktor\xe9 chcete vr\xe1tiť do z\xe1soby. Zadajte ho pred t\xfdm, ako prejdete k \xfaplnej alebo čiastočnej refund\xe1cii. Resetovanie z\xe1sob m\xf4že byť flexibilne kombinovan\xe9 s procesom refund\xe1cie.","titleShipping":"Doprava","textShipping":"Položky dopravy je možn\xe9 vr\xe1tiť rovnako ako ak\xfdkoľvek in\xfd produkt. Zadajte buď cel\xe9 množstvo, alebo vlastn\xfa čiastočn\xfa sumu a pokračujte vo vr\xe1ten\xed. Vr\xe1tenie n\xe1kladov na dopravu je možn\xe9 flexibilne kombinovať s procesom vr\xe1tenia samotn\xfdch produktov.","titlePartialAmount":"Čiastočn\xe9 vr\xe1tenie peňaz\xed (iba suma)","textPartialAmount":"Stač\xed zadať čiastočn\xfa sumu do textov\xe9ho poľa a spustiť vr\xe1tenie peňaz\xed.","titlePartialItems":"Čiastočn\xe1 refund\xe1cia (s položkami)","textPartialItems":"Ak chcete v Mollie označiť množstv\xe1 a položky ako vr\xe1ten\xe9, použite formul\xe1r vyššie. Nastavte požadovan\xe9 množstv\xe1 a zadajte vlastn\xfa sumu pre každ\xfa položku, ktor\xe1 bude vr\xe1ten\xe1. Celkov\xe1 suma sa n\xe1sledne zobraz\xed v textovom poli s konečnou sumou na vr\xe1tenie. Nezabudnite, že t\xfato konečn\xfa sumu je st\xe1le možn\xe9 upraviť pred spusten\xedm refund\xe1cie.","titlePartialPromotions":"Čiastočn\xe1 refund\xe1cia (s promo akciami)","textPartialPromotions":"Ak m\xe1te v koš\xedku promo akciu, zobraz\xed sa ako samostatn\xe1 položka. Ak chcete vr\xe1tiť všetky zľavnen\xe9 produkty, pokračujte a vr\xe1ťte ich pln\xe9 sumy spolu s celou položkou promo akcie. Ak však chcete vr\xe1tiť len niektor\xe9 zľavnen\xe9 produkty, zľava sa m\xf4že automaticky odpoč\xedtať z každej položky zvl\xe1šť. Samozrejme, hodnoty m\xf4žete vždy upraviť, ak nie s\xfa spr\xe1vne.","titleRoundingDiff":"Rozdiel v zaokr\xfahlen\xed","textRoundingDiff":"Pln\xe9 vr\xe1tenie zahrnie rozdiely v zaokr\xfahlen\xed"},"summary":{"dataLoading":"Nač\xedtavaj\xfa sa \xfadaje...","headerExcludingVat":"Bez DPH","headerIncludingVat":"S DPH","captionTotal":"Celkom","captionTotalTaxFree":"Celkom","captionPendingRefunds":"Čak\xe1 sa na refund\xe1ciu","captionVouchers":"Suma poukazu","captionRefunded":"Vr\xe1ten\xe1 suma","captionRemaining":"Vratn\xe1 suma","btnFixDiff":"Opraviť rozdiel","placeholderDescription":"Zadajte popis pre v\xfdpis z banky/karty pre z\xe1kazn\xedka. Maxim\xe1lne 140 znakov","lblDescription":"Popis (voliteľn\xe9) ({characters}/140 znakov)","descriptionHelp":"Tento text sa zobraz\xed na bankovom alebo kartovom v\xfdpise z\xe1kazn\xedka, ak to bude možn\xe9. Spr\xe1va bude skr\xe1ten\xe1 po 140 znakoch.","placeholderInternalDescription":"Zadajte popis pre intern\xe9 použitie","lblInternalDescription":"Intern\xfd popis (voliteľn\xe9)","internalDescriptionHelp":"Toto sa zobraz\xed ako miestny popis v administr\xe1torskom rozhran\xed.","checkVerification":"Overil som celkov\xfa sumu refund\xe1cie a konfigurovan\xe9 množstv\xe1 na refund\xe1ciu a doplnenie skladu.","btnRefund":"Refund\xe1cia","btnFullRefund":"\xdapln\xe9 vr\xe1tenie peňaz\xed","roundDiffItemAdded":"Položka zaokr\xfahlenia"},"refunds":{"title":"Refund\xe1cie v Mollie Dashboard","linkMore":"Viac o vr\xe1ten\xed peňaz\xed","grid":{"columns":{"amount":"Suma","status":"Status","description":"Popis","internalDescription":"Intern\xfd popis","composition":"Zloženie","date":"D\xe1tum"},"lblNoComposition":"Zloženie nie je k dispoz\xedcii","btnCancelRefund":"Zrušiť t\xfato refund\xe1ciu"}},"notifications":{"success":{"refund-created":"V Mollie bolo vytvoren\xe9 vr\xe1tenie peňaz\xed. Dokončenie m\xf4že trvať až 2 hodiny. Do tohto času m\xf4žete vr\xe1tenie zrušiť.","refund-canceled":"Čakaj\xfaca refund\xe1cia bola \xfaspešne zrušen\xe1 a odstr\xe1nen\xe1."},"error":{"low-amount":"Pros\xedm, zadajte sumu ktor\xe1 m\xe1 byť vr\xe1ten\xe1.","refund-created":"Pri vytv\xe1ran\xed refund\xe1cie došlo k probl\xe9mu.","refund-canceled":"Pri zrušen\xed čakaj\xfaceho vr\xe1tenia peňaz\xed nastal probl\xe9m. Sk\xfaste to znova v Mollie Dashboarde."}}},"vouchers":{"CARD_TITLE":"Poukaz","VOUCHER_INFO_TITLE":"Platby poukazom","VOUCHER_INFO_DESCRIPTION":"Mollie v\xe1m umožňuje jednoducho prij\xedmať platby vo vašom online obchode pomocou ekologick\xfdch, darčekov\xfdch a stravn\xfdch poukazov – inteligentn\xe1 voľba na zv\xfdšenie predaja a spokojnosti z\xe1kazn\xedkov. Platobn\xe1 met\xf3da „poukaz“ je viditeľn\xe1 len vtedy, ak m\xe1te v koš\xedku aspoň 1 produkt s priraden\xfdm typom poukazu.","VOUCHER_INFO_DEFAULTLANGUAGE":"Upozornenie: T\xe1to konfigur\xe1cia sa d\xe1 upraviť iba v predvolenom jazyku. Ak chcete zmeniť typ poukazu pre tento produkt, zmeňte jazyk.","VOUCHER_BTN_READMORE":"Zistite viac","VOUCHER_TYPE_CAPTION":"Typ poukazu produktu","VOUCHER_TYPE_VALUE_NONE":"Žiadne","VOUCHER_TYPE_VALUE_ECO":"Eko","VOUCHER_TYPE_VALUE_MEAL":"Jedlo","VOUCHER_TYPE_VALUE_VOUCHER":"Darček"},"modals":{"shipping":{"title":"Odoslať cez Mollie","item":{"label":"Položka:","noQuantity":"Zadajte množstvo na odoslanie.","shipAll":"Odoslať všetky","summary":{"quantity":"Množstvo na odoslanie","shipped":"Odoslan\xe9 množstvo","shippable":"Množstvo, ktor\xe9 je možn\xe9 odoslať"},"success":"Objedn\xe1vka bola \xfaspešne odoslan\xe1."},"order":{"description":"Nasleduj\xface množstv\xe1 položiek bud\xfa odoslan\xe9.","itemHeader":"Položka","quantityHeader":"Množstvo","originalQuantityHeader":"Množstvo (na odoslanie)"},"availableTracking":{"label":"Dostupn\xe9 sledovacie k\xf3dy","hint":"Kliknite na jeden z t\xfdchto sledovac\xedch k\xf3dov, aby sa automaticky vyplnili všetky \xfadaje."},"showTracking":"Pridať inform\xe1cie o sledovan\xed k tejto z\xe1sielke","tracking":{"carrier":"Dopravca","code":"K\xf3d","url":"Url","invalid":"Pros\xedm, zadajte dopravcu a k\xf3d"},"confirmButton":"Zaslať objedn\xe1vku","cancelButton":"Zrušiť","selectAllButton":"Vybrať všetko","resetButton":"Obnoviť"},"cancel":{"title":"Zrušiť položku cez Mollie","confirmButton":"Zrušiť položku cez Mollie","cancelButton":"Zavrieť modal","resetStock":"Obnoviť z\xe1soby","item":{"success":"Produkt bol \xfaspešne zrušen\xfd","failed":{"quantityZero":"Množstvo je 0","invalidLine":"Produkt neexistuje v objedn\xe1vke","quantityTooHigh":"Množstvo je pr\xedliš vysok\xe9"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Zaslať objedn\xe1vku (Mollie)","description":"Zaslať objedn\xe1vku v Mollie."},"modal":{"title":"Zaslať objedn\xe1vku","description":"T\xe1to akcia automaticky odošle objedn\xe1vku cez Mollie. Postup bude zahŕňať č\xedslo objedn\xe1vky, ktor\xe9 sa odošle do Mollie API. \xdaspešn\xe9 aj ne\xfaspešn\xe9 z\xe1sielky bud\xfa viditeľn\xe9 v Mollie protokoloch.","warningConfig":"Uistite sa, že vypnete ak\xfakoľvek dodatočn\xfa automatiz\xe1ciu pre tento typ akcie, aby nedošlo k žiadnym konfliktom. Nasleduj\xface akt\xedvne funkcie tohto doplnku m\xf4žu s touto akciou kolidovať:","noWarnings":"Žiadne upozornenia"}},"refundOrder":{"editor":{"title":"Refund\xe1cia objedn\xe1vky (Mollie)","description":"Refundovať objedn\xe1vku cez Mollie."},"modal":{"title":"Refund\xe1cia objedn\xe1vky","description":"T\xe1to akcia automaticky spust\xed vr\xe1tenie platby cez Mollie. Postup zahŕňa prijatie č\xedsla objedn\xe1vky, ktor\xe9 sa odošle do Mollie API. \xdaspešn\xe9 aj ne\xfaspešn\xe9 vr\xe1tenia platby bud\xfa viditeľn\xe9 v Mollie protokoloch.","warning":"Majte na pam\xe4ti, že vr\xe1tenie platby m\xf4že trvať až 2 hodiny, k\xfdm sa dokonč\xed a zobraz\xed v obchode. Dovtedy m\xf4žete refund\xe1ciu, ktor\xe1 je v priebehu spracovania, kedykoľvek zrušiť – buď zo str\xe1nky objedn\xe1vky v Shopware, alebo cez Mollie Dashboard.","warningConfig":"Uistite sa, že ste deaktivovali všetky ďalšie automatiz\xe1cie pre tento typ akcie, aby ste predišli možn\xfdm probl\xe9mom. "}},"warnings":{"automaticShipping":"Automatick\xe9 odosielanie v konfigur\xe1cii doplnku"}}},"subscriptions":{"status":{"pending":"Čakaj\xface","active":"Akt\xedvne","canceled":"Zrušen\xe9","suspended":"Pozastaven\xe9","completed":"Dokončen\xe9","paused":"Pozastaven\xe9","resumed":"Obnoven\xe9","skipped":"Preskočen\xe9"},"navigation":{"title":"Mollie predplatn\xe9"},"TYPE_DAYS":"Deň/ dn\xed","TYPE_WEEKS":"T\xfdždeň/ t\xfdždne","TYPE_MONTHS":"Mesiac/ mesiace","confirm":{"cancelTitle":"Ukončiť predplatn\xe9?","cancel":"Zrušiť predplatn\xe9 v\xe1šho z\xe1kazn\xedka.","pauseTitle":"Pozastaviť predplatn\xe9?","pause":"Pozastavte predplatn\xe9, k\xfdm ho znovu neobnov\xedte.","resumeTitle":"Obnoviť predplatn\xe9?","resume":"Pokračovať v predplatnom.","skipTitle":"Preskočiť nasleduj\xfacu spl\xe1tku?","skip":"Preskočiť nasleduj\xfacu spl\xe1tku v predplatnom. N\xe1sledne bude predplatn\xe9 pokračovať automaticky."},"alerts":{"cancelSuccess":"Predplatn\xe9 bolo \xfaspešne zrušen\xe9","pauseSuccess":"Predplatn\xe9 bolo \xfaspešne pozastaven\xe9","resumeSuccess":"Predplatn\xe9 bolo \xfaspešne obnoven\xe9","skipSuccess":"Predplatn\xe9 bolo \xfaspešne preskočen\xe9. Nasleduj\xfaca platba bola aktualizovan\xe1."},"list":{"title":"Mollie Predplatn\xe9","columns":{"customer":"Z\xe1kazn\xedk","status":"Stav","description":"Popis","amount":"Suma","nextPaymentAt":"Nasleduj\xfaca platba","prePaymentReminder":"Pripomenut\xe9 o","canceledAt":"Zrušen\xe9 o","createdAt":"Vytvoren\xe9 o"},"action":{"edit":"Upraviť predplatn\xe9"},"deletedCustomer":"Zmazan\xfd z\xe1kazn\xedk"},"detail":{"title":"Mollie predplatn\xe9","buttonCancelSubscription":"Zrušiť predplatn\xe9","labelDescription":"Popis","labelAmount":"Suma","labelQuantity":"Množstvo","labelMollieSubscription":"Mollie predplatn\xe9","labelMollieCustomer":"Mollie z\xe1kazn\xedk","labelMandateId":"Mand\xe1t","labelShopwareCustomer":"Shopware z\xe1kazn\xedk","labelCreatedAt":"Vytvoren\xe9 o","buttonShowShopwareOrder":"Zobraziť Shopware objedn\xe1vku","buttonShowShopwareCustomer":"Zobraziť Shopware z\xe1kazn\xedka","cardTitleSubscription":"Predplatn\xe9","cardTitleStatus":"Stav","labelStatus":"Stav","labelNextPaymentAt":"Nasleduj\xfaca platba o","labelLastRemindedAt":"Posledn\xe1 pripomienka k","labelCanceledAt":"Zrušen\xe9 k","buttonPauseSubscription":"Pozastaviť predplatn\xe9","buttonResumeSubscription":"Obnoviť predplatn\xe9","buttonSkipSubscription":"Preskočiť predplatn\xe9","history":{"cardTitle":"Hist\xf3ria","colDate":"D\xe1tum","colComment":"Koment\xe1r","colStatusFrom":"Stav (od)","colStatusTo":"Stav (do)","colMollieSubscription":"Mollie predplatn\xe9"}},"product":{"card-title":"Predplatn\xe9","title":"Mollie Predplatn\xe9","description":"Spr\xe1va opakovan\xfdch platieb je jednoduchšia než kedykoľvek predt\xfdm vďaka našim užitočn\xfdm funkci\xe1m. Posuňte svoje podnikanie na vyššiu \xfaroveň s efekt\xedvnym sledovan\xedm, jednoduch\xfdmi integr\xe1ciami a ďalš\xedmi možnosťami. S predplatn\xfdm od Mollie m\xf4žete jednoducho vytv\xe1rať produkty na predplatn\xe9 a napl\xe1novať opakovan\xe9 platby podľa nastaven\xe9ho intervalu a obdobia.","mollieSubscriptionProduct":"Produkt predplatn\xe9ho","mollieSubscriptionIntervalAmount":"Opakovať platbu každ\xfdch","mollieSubscriptionIntervalType":"Jednotka intervalu","mollieSubscriptionRepetitionAmount":"Počet opakovan\xed","mollieSubscriptionRepetitionPlaceholder":"Zadajte č\xedslo alebo ponechajte pr\xe1zdne","infoDefaultLanguage":"Upozornenie: T\xe1to konfigur\xe1cia sa d\xe1 upraviť iba v predvolenom jazyku. Ak chcete zmeniť nastavenia predplatn\xe9ho pre tento produkt, zmeňte jazyk.","btnReadMore":"Zistite viac"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Predplatn\xe9"}},"sw-order":{"detailExtended":{"titleCreditCardData":"\xdadaje o kreditnej karte","buttonMolliePaymentLink":"Kop\xedrovať do schr\xe1nky","columnRefunded":"Vr\xe1ten\xe9","columnShipped":"Odoslan\xe9","columnCanceled":"Zrušen\xe9","labelMollieOrderId":"Mollie ID objedn\xe1vky","labelMollieThirdPartyPaymentId":"Referencia platby","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Suma vr\xe1tenia","totalRefundsPending":"Čak\xe1 sa na vr\xe1tenie","totalRemaining":"Vratn\xe1 suma","totalVouchers":"Suma poukazu","totalShipments":"Odoslan\xe1 suma ({quantity} položiek)","subscriptionBadge":"Objedn\xe1vka predplatn\xe9ho","refundManager":{"title":"Mollie Manager vr\xe1tenia","btnOpenRefundManager":"Otvoriť Manager vr\xe1tenia","btnCloseRefundManager":"Zavrieť Manager vr\xe1tenia"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Preferovan\xfd emitent iDeal"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Spr\xe1vca vr\xe1tenia peňaz\xed"},"mollie_subscription":{"label":"Predplatn\xe9"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Popis"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Vr\xe1tenie","subscription":"Predplatn\xe9","webhookReceived":"Webhooks","status":"Stav","started":"Začat\xe9","ended":"Ukončen\xe9","paused":"Pozastaven\xe9","renewalReminder":"Pripomienka o obnoven\xed","renewed":"Obnoven\xe9","resumed":"Predĺžen\xe9","skipped":"Preskočen\xe9","all":"Všetko","canceled":"Zrušen\xe9","expired":"Expirovan\xe9","partiallyRefunded":"Vr\xe1ten\xe9 (čiastočne)","orderSuccess":"Objedn\xe1vka \xfaspešn\xe1","orderFailed":"Objedn\xe1vka zlyhala","orderCanceled":"Objedn\xe1vka zrušen\xe1"}}}'),te=JSON.parse('{"global":{"entities":{"mollie_subscription":"Mollie Абонамент | Mollie Абонаменти"},"businessEvents":{"mollie_checkout_order_success":" Поръчката е успешна","mollie_checkout_order_failed":" Поръчката не е успешна","mollie_checkout_order_canceled":" Поръчката е отказана","mollie_webhook_received_All":" Получен е Mollie уебхук (Всички)","mollie_webhook_received_status_authorized":" Получен е уебхук на Mollie (Разрешен)","mollie_webhook_received_status_failed":" Получен е Mollie уебхук (Неуспешно)","mollie_webhook_received_status_canceled":" Получен е Mollie уебхук (Отказан)","mollie_webhook_received_status_expired":" Получен е Mollie уебхук (Изтекъл)","mollie_webhook_received_status_pending":" Получен е Mollie уебхук (В изчакване)","mollie_webhook_received_status_paid":" Получен е Mollie уебхук (Платено)","mollie_webhook_received_status_completed":" Получен е Mollie уебхук (Завършен)","mollie_webhook_received_status_refunded":" Получен е Mollie уебхук (Възстановена сума)","mollie_webhook_received_status_partially_refunded":" Получен е Mollie уебхук (Частично възстановена сума)","mollie_refund_started":" Започнато Mollie възстановяване на сума","mollie_subscription_started":" Mollie абонамент е започнат","mollie_subscription_ended":" Mollie абонамент е завършен","mollie_subscription_cancelled":" Mollie абонамент е прекратен","mollie_subscription_paused":" Mollie абонамент е паузиран","mollie_subscription_resumed":" Mollie абонамент е възобновен","mollie_subscription_skipped":" Mollie абонамент е пропуснат","mollie_subscription_renewed":" Mollie абонамент е подновен","mollie_subscription_renewal_reminder":" Mollie напомняне за подновяване на абонамент"}},"mollie-payments":{"pluginTitle":"Mollie","pluginDescription":"Mollie Модул","searchPlaceholder":"Търсене на абонаменти...","general":{"mainMenuItemGeneral":"Mollie Плащания","descriptionTextModule":"Mollie Плащания","btnMollieActions":"Mollie Действия","refundThroughMollie":"Възстановяване на сума чрез Mollie","shipThroughMollie":"Изпращане чрез Mollie","cancelMollieItem":"Отказ чрез Mollie"},"config":{"info":{"title":"Здравейте {userName}, Добре дошли в Mollie!","descriptionTop":"Onboarding е лесно с Mollie!","descriptionBottom":"Това е!","descriptionFooter":"Ако искате да научите повече за нашия плъгин, моля посетете страницата с официалната ни документация.","onboardingStep1":"Регистрация за Mollie акаунт.","onboardingStep2":"Въведете вашите API ключове в секцията по-долу.","onboardingStep2TestMode":"Включете \\"Тестов режим\\", ако искате да тествате само плащания.","onboardingStep3":"Присвоете методи на плащане на вашия продажбени канали.","onboardingStep3Link":"към вашите продажбени канали","btnDocumentation":"Документация","btnRequestSupport":"Подкрепа","btnTroubleshooting":"Ръководство за отстраняване на проблеми"},"api":{"apiLinkButton":"Вземете своите API ключове от Mollie табло","testButton":"Тестови API ключове","testApiKeys":{"title":"Mollie Плащания","apiKey":"API ключ","isValid":"е валиден","isInvalid":"е невалиден"}},"payments":{"format":{"placeholder":"Заместител","preview":"Предварителен преглед"},"updatePaymentMethods":{"title":"Mollie Плащания","button":"Актуализиране на методите на плащане","succeeded":"Методите за плащане са успешно актуализирани.","failed":"Методите за плащане не можаха да бъдат актуализирани."},"mollieLimits":{"link":"Покажи правила за наличност на mollie за методи на плащане"}},"rounding":{"info1":"Shopware може да използва настройките за валута, за да изчисли как да закръгли крайната сума на поръчка. Това включва броя на десетичните знаци в ценообразуването на вашите продукти и най-близкия интервал на закръгляне, като например 0.50 или 1.00.","info2":"Тези настройки могат да доведат до различна обща сума от сбора на отделните артикули. Когато Mollie проверява тези суми и установи, че не съвпадат, това причинява грешка при плащането.","info3":"Можете да използвате тази функция, за да избегнете проблеми със закръглянето при обработката. Когато е активирана, тя добавя отделен артикул за разликата в закръглянето във вашето Mollie табло, и вашите клиенти плащат общата сума, изчислена от Shopware."},"order":{"bankTransferDueDateKlarnaLimitReached":"Не е възможно да използвате Klarna Плати сега, Klarna Раздели го или Klarna Плати по-късно като метод, когато датата на изтичане е повече от 28 дни напред, освен ако не е договорено друг максимум между търговеца и Klarna.","bankTransferDueDateLimitReached":"Не е възможно срокът на поръчки да бъде зададен на повече от 100 дни."},"support":{"modalTitle":"Заявка за помощ от Mollie","btnCancel":"Откажи","btnConfirm":"Заявка за помощ","btnSupport":"Повече за нашата поддръжка","form":{"name":"Вашето име","email":"Вашият имейл","recipient":"Изпратете заявка до","subject":"Тема","message":"Съобщение"},"data":{"header":"Данни изпратени до Mollie:","other":"Други:","shopwareVersion":"Версия на Shopware","pluginLogs":"{plugin} лог файловете","pluginConfiguration":"Конфигурация на {plugin}","pluginConfigurationHelpText":"API ключовете са изключени.","paymentMethods":"Данни за метода на плащане","paymentMethodsHelpText":"Съдържа информация за това кои методи на плащане са активни, присвоени на всеки търговски канал, както и техния статус във вашия Mollie акаунт."},"success":"Заявката за помощ е успешна изпратена. Правим всичко възможно да отговорим възможно най-скоро","error":"Имаше проблем при изпращането на пощата чрез Shopware. Моля, опитайте отново или се свържете с нас директно по имейл."}},"rules":{"itemSubscriptionRule":"Артикулът е абонамент (Mollie)","cartSubscriptionRule":"Количка с абонаменти (Mollie)"},"refunds":{"status":{"queued":"В опашката","pending":"В изчакване","processing":"Обработване","refunded":"Възстановена сума","failed":"Неуспешно","description":{"queued":"Възстановяването на сума е в изчакване до момента, в който има достатъчно баланс за обработката му. Все още може да отмените възстановяването.","pending":"Възстановената сума ще бъде изпратена към банката на следващия работен ден. Все още можете да отмените възстановяването.","processing":"Възстановената сума е изпратена към банката. Сумата за възстановяване ще бъде прехвърлена по сметката на потребителя възможно най-скоро.","refunded":"Сумата за възстановяване е прехвърлена към потребителя.","failed":"Възстановяването на сума се провали след обработка. Например, клиентът е закрил своята банкова сметка. Средствата ще бъдат върнати във вашата сметка."}}},"refund-manager":{"general":{"unitQuantity":"бр."},"acl":{"warningCreate":"Нямате разрешение да създавате възстановявания на суми","warningCancel":"Нямате разрешение да отказвате възстановявания на суми"},"cart":{"title":"Поръчка ##orderNumber##","btnSelectAll":"Изберете Всички","btnResetForm":"Нулиране на формата","linkHowTo":"Как се използва този формуляр?","grid":{"columns":{"item":"Артикул","productNumber":"Номер на Продукта","unitPrice":"Единична цена","quantity":"Количество","refunded":"Възстановено","refundQuantity":"Възстановяване","totalPrice":"Общо","refundAmount":"Възстановяване","resetStock":"Нулиране на наличност"},"btnResetLine":"Нулиране на редът","checkDeductPromotion":"Удръжка на промоция","checkRefundTax":"Възстановяване на ДДС"},"roundDiffItemAdded":"Автоматичен елемент за закръгляне беше добавен"},"instructions":{"linkResetTutorials":"Нулиране на Обучения","btnToggleTutorial":"Показване/Скриване на урока","titleFullRefund":"Пълно Възстановяване на Сума","textFullRefund":"Просто използвайте бутона за пълно възстановяване на сумата. Това гарантира, че всички ваши артикули са маркирани като възстановено и пълната сума е върната на клиента.","titleStockReset":"Нулиране на наличност","textStockReset":"Можете автоматично да увеличите наличността, като въведете количеството, което искате да върнете в наличност. Просто го въведете преди да продължите с пълно или частично възстановяване на сума. Нулирането на наличността може да бъде комбинирано с процесът на възстановяване по флексибилен начин.","titleShipping":"Доставка","textShipping":"Сумите на артикулите за доставка могат да бъдат възстановени, както всеки друг продукт. Ако желаете, въведете пълното количество или частична сума и продължете с възстановяването. Процесът на възстановяване на сума на разходи за доставка може да се комбинира с действителния процес на възстановяване на суми на артикули по флексибилен начин.","titlePartialAmount":"Частично Възстановяване (само сума)","textPartialAmount":"Просто въведете частичната сума в текстовото поле и започнете възстановяването.","titlePartialItems":"Частично Възстановяване (с артикули)","textPartialItems":"Ако желаете да отбележите количества и артикули като възстановени суми в Mollie, използвайте формата по-горе. Задайте вашите количества и предоставете сума по избор за всеки артикул, който ще бъде възстановен. Общата сума ще бъде видима в текстовото поле за крайна сума на възстановяването. Запомнете, все още е възможно да коригирате тази крайна сума преди да започнете възстановяването.","titlePartialPromotions":"Частично Възстановяване (с промоции)","textPartialPromotions":"Ако имате промоция във вашата количка, тогава вашата промоция е отделен елемент в списъка. Ако искате да възстановите сумите на всички намалени артикули, просто възстановете техните общи стойности и целият ред на промоцията. Обаче, ако искате да възстановите сумите на само няколко артикула, които са били намалени, можете автоматично да извадите приложената отстъпка за всеки отделен елемент в списъка. Разбира се, винаги можете да промените стойностите, ако те не са правилни.","titleRoundingDiff":"Разликата в закръглянето","textRoundingDiff":"Пълното възстановяване на сума ще включва разлики в закръглянето"},"summary":{"dataLoading":"Данните се зареждат...","headerExcludingVat":"Без ДДС","headerIncludingVat":"С ДДС","captionTotal":"Общо","captionTotalTaxFree":"Общо","captionPendingRefunds":"Очаква се да бъде възстановена сумата","captionVouchers":"Сума на Ваучера","captionRefunded":"Възстановена сума","captionRemaining":"Възстановяема сума","btnFixDiff":"Поправяне на разликата","placeholderDescription":"Въведете описание на отчет от банка/карти за потребителя. Максимум 140 знака","lblDescription":"Описание (по избор) ({characters}/140 знака)","descriptionHelp":"Това ще бъде показано в банковия отчет или в отчета за карти на потребителя, когато е възможно. Съобщението ще бъде съкратено до 140 знака.","placeholderInternalDescription":"Въведете вашето вътрешно описание","lblInternalDescription":"Вътрешно описание (по избор)","internalDescriptionHelp":"Това ще бъде показано като локално описание в административния интерфейс.","checkVerification":"Проверил съм общата сума за възстановяване и конфигурираните количества за възстановяване и зареждане.","btnRefund":"Възстановяване на сума","btnFullRefund":"Пълно Възстановяване на Сума","roundDiffItemAdded":"Артикул за закръгляване"},"refunds":{"title":"Възстановявания на Суми в Mollie таблото","linkMore":"Още за възстановявания на суми","grid":{"columns":{"amount":"Сума","status":"Статус","description":"Описание","internalDescription":"Вътрешно описание","composition":"Състав","date":"Дата"},"lblNoComposition":"Няма наличен състав","btnCancelRefund":"Откажете това възстановяване на сума"}},"notifications":{"success":{"refund-created":"Възстановяване е създадено в Mollie. Може да отнеме 2 часа за да се завърши възстановяването на сума. До този момент можете да отмените възстановяването.","refund-canceled":"Очакваното възстановяване на сума е успешно отказано и премахнато."},"error":{"low-amount":"Моля, въведете сума за възстановяване на сума.","refund-created":"Нещо се обърка при създаването на възстановяване на сума.","refund-canceled":"Имаше проблем при отказа на възстановяването на сума в изчакване. Моля, опитайте отново в Mollie Таблото."}}},"vouchers":{"CARD_TITLE":"Ваучер","VOUCHER_INFO_TITLE":"Плащания с ваучер","VOUCHER_INFO_DESCRIPTION":"Mollie ви позволява лесно да приемате плащания във вашия онлайн магазин, използвайки еко, подаръчни и хранителни ваучери – умен избор за увеличаване на продажбите и удовлетворяване на вашите клиенти. Методът на плащане \\"ваучер\\" е видим само ако имате поне 1 продукт с присвоен тип ваучер в количката.","VOUCHER_INFO_DEFAULTLANGUAGE":"Моля, обърнете внимание, че тази конфигурация може да бъде редактирана само на вашия основен език. Моля, сменете езика си, за да модифицирате типа ваучер на този продукт.","VOUCHER_BTN_READMORE":"Прочетете още","VOUCHER_TYPE_CAPTION":"Вид ваучер на продукта","VOUCHER_TYPE_VALUE_NONE":"Няма","VOUCHER_TYPE_VALUE_ECO":"Еко","VOUCHER_TYPE_VALUE_MEAL":"Храна","VOUCHER_TYPE_VALUE_VOUCHER":"Подарък"},"modals":{"shipping":{"title":"Изпращане чрез Mollie","item":{"label":"Артикул:","noQuantity":"Моля, въведете количество за изпращане.","shipAll":"Изпратете всички","summary":{"quantity":"Количество за изпращане","shipped":"Изпратено количество","shippable":"Количество годно за изпращане"},"success":"Поръчката е успешно изпратена."},"order":{"description":"Следните количества на артикули ще бъдат изпратени.","itemHeader":"Артикул","quantityHeader":"Количество","originalQuantityHeader":"Количество (годно за изпращане)"},"availableTracking":{"label":"Налични кодове за проследяване","hint":"Кликнете върху един от тези проследяващи кодове, за да попълните автоматично всички данни."},"showTracking":"Добавете информация за проследяване за тази пратка","tracking":{"carrier":"Куриер","code":"Код","url":"Url","invalid":"Моля, въведете както куриер, така и код"},"confirmButton":"Изпращане на поръчката","cancelButton":"Отказ","selectAllButton":"Изберете всичко","resetButton":"Нулиране"},"cancel":{"title":"Откажи артикул чрез mollie","confirmButton":"Откажи артикула чрез mollie","cancelButton":"Затвори modal","resetStock":"Нулиране на наличностите","item":{"success":"Продуктът беше успешно отказан","failed":{"quantityZero":"Количество е 0","invalidLine":"Продуктът не съществува в поръчката","quantityTooHigh":"Количеството е твърде голямо"}}}},"sw-flow":{"actions":{"shipOrder":{"editor":{"title":"Изпратете поръчката (Mollie)","description":"Изпратете поръчка в Mollie."},"modal":{"title":"Изпратете поръчката","description":"Това действие ще изпрати поръчка автоматично чрез Mollie. Последователността на потока ще получи номера на поръчката и ще го предаде на Mollie API. Успешните и неуспешните изпращания ще бъдат видими във Mollie лог файловете.","warningConfig":"Моля, уверете се, че сте изключили всяка допълнителна автоматизация за този тип действие, за да избегнете прекъсвания. \\nСледните активирани функции на този плъгин може да попречат на това действие:","noWarnings":"Без предупреждения"}},"refundOrder":{"editor":{"title":"Възстановяване на сума на поръчка (Mollie)","description":"Възстановяване на сума на поръчка чрез Mollie."},"modal":{"title":"Възстановяване на сума на поръчка","description":"Това действие ще стартира автоматично възстановяване на сума чрез Mollie. Поръчковият номер ще бъде изпратен към Mollie API. Успешните и неуспешните възстановявания на суми ще бъдат видими в Mollie лог файловете.","warning":"Моля, имайте предвид, че възстановявания на суми могат да отнемат до 2 часа преди да бъдат финализирани и видими в магазина. До тогава винаги можете да отмените висящо възстановяване на сума от страницата за поръчки в Shopware или от Mollie Таблото.","warningConfig":"Уверете се, че изключвате всяка допълнителна автоматизация за този вид действие, за да избегнете прекъсвания."}},"warnings":{"automaticShipping":"Автоматично изпращане в конфигурацията на плъгина"}}},"subscriptions":{"status":{"pending":"В изчакване","active":"Активно","canceled":"Прекратено","suspended":"Спряно","completed":"Завършено","paused":"Паузирано","resumed":"Възобновено","skipped":"Пропуснато"},"navigation":{"title":"Абонаменти на Mollie"},"TYPE_DAYS":"Ден (дни)","TYPE_WEEKS":"Седмица/и","TYPE_MONTHS":"Месец(и)","confirm":{"cancelTitle":"Прекратяване на абонамента?","cancel":"Прекратете абонамента на вашия клиент.","pauseTitle":"Паузирайте абонамента?","pause":"Поставете абонамента на пауза, докато го възобновите отново.","resumeTitle":"Възобновете абонамента?","resume":"Продължете с абонамента отново.","skipTitle":"Пропускане на следващата вноска?","skip":"Пропуснете следващата вноска от абонамента. Тя ще продължи автоматично след това."},"alerts":{"cancelSuccess":"Абонаментът беше успешно прекратен","pauseSuccess":"Абонаментът беше успешно поставен на пауза","resumeSuccess":"Абонаментът беше успешно възобновен","skipSuccess":"Абонаментът беше успешно пропуснат. Следващото плащане е актуализирано."},"list":{"title":"Mollie Абонаменти","columns":{"customer":"Клиент","status":"Статус","description":"Описание","amount":"Сума","nextPaymentAt":"Следващо плащане","prePaymentReminder":"Напомнено на","canceledAt":"Прекратено на","createdAt":"Създадено на"},"action":{"edit":"Редактиране на абонамента"},"deletedCustomer":"Изтрит клиент"},"detail":{"title":"Mollie абонамент","buttonCancelSubscription":"Прекратяване на абонамент","labelDescription":"Описание","labelAmount":"Сума","labelQuantity":"Количество","labelMollieSubscription":"Mollie Абонамент","labelMollieCustomer":"Mollie клиент","labelMandateId":"Мандат","labelShopwareCustomer":"Shopware клиент","labelCreatedAt":"Създадено на","buttonShowShopwareOrder":"Покажи Shopware поръчка","buttonShowShopwareCustomer":"Покажи Shopware клиент","cardTitleSubscription":"Абонамент","cardTitleStatus":"Статус","labelStatus":"Статус","labelNextPaymentAt":"Следващо плащане на","labelLastRemindedAt":"Последно напомнено на","labelCanceledAt":"Прекратено на","buttonPauseSubscription":"Паузирайте абонамента","buttonResumeSubscription":"Възобновяване на абонамента","buttonSkipSubscription":"Пропускане на абонамента","history":{"cardTitle":"История","colDate":"Дата","colComment":"Коментар","colStatusFrom":"Статус (от)","colStatusTo":"Статус (до)","colMollieSubscription":"Mollie абонамент"}},"product":{"card-title":"Абонамент","title":"Mollie Абонаменти","description":"Управлението на вашите периодични плащания е по-лесно от всякога с нашите полезни функции. Издигнете бизнеса си на следващо ниво с ефективни възможности за проследяване, лесни интеграции и още. С абонаментите на Mollie, можете лесно да създавате абонаментни продукти и да планирате периодични плащания, които да се извършват в зададения интервал и период.","mollieSubscriptionProduct":"Абонаментен продукт","mollieSubscriptionIntervalAmount":"Повторение на плащането всеки","mollieSubscriptionIntervalType":"Интервална единица","mollieSubscriptionRepetitionAmount":"Броят на повторенията","mollieSubscriptionRepetitionPlaceholder":"Въведете число или оставете празно","infoDefaultLanguage":"Моля, обърнете внимание, че тази конфигурация може да бъде редактирана само на вашия основен език. Моля, сменете езика си, за да модифицирате настройките за абонамента на този продукт.","btnReadMore":"Прочетете още"}},"sw-order-list":{"columns":{"mollie":"Mollie"},"badgeSubscription":"Абонамент"}},"sw-order":{"detailExtended":{"titleCreditCardData":"Данни за кредитната карта","buttonMolliePaymentLink":"Копирайте в клипборда","columnRefunded":"Възстановена сума","columnShipped":"Изпратено","columnCanceled":"Отказан","labelMollieOrderId":"Mollie Поръчка ID","labelMollieThirdPartyPaymentId":"Референция на плащането","labelMolliePaymentLink":"Mollie Checkout URL","totalRefunds":"Възстановена сума","totalRefundsPending":"Очаква се да бъде възстановена сумата","totalRemaining":"Възстановяема сума","totalVouchers":"Сума на ваучера","totalShipments":"Изпратена сума ({quantity} артикули)","subscriptionBadge":"Абонаментна поръчка","refundManager":{"title":"Mollie Управление на възстановяване на суми","btnOpenRefundManager":"Отворете Управлението на възстановявания на суми","btnCloseRefundManager":"Затворете Управлението на възстановявания на суми"}}},"sw-customer":{"extendedInfo":{"labelPreferredIdealIssuer":"Предпочитан iDeal издател"}},"sw-privileges":{"permissions":{"parents":{"mollie":"Mollie"},"mollie_refund_manager":{"label":"Управление на възстановявания на суми"},"mollie_subscription":{"label":"Абонаменти"}}},"sw-profile":{"tabSearchPreferences":{"modules":{"mollie_subscription":{"description":"Описание"}}}},"sw-flow":{"triggers":{"mollie":"Mollie","refund":"Възстановяване","subscription":"Абонамент","webhookReceived":"Уебхукс","status":"Статус","started":"Започнало","ended":"Завършено","paused":"Паузирано","renewalReminder":"Напомняне за подновяване","renewed":"Подновено","resumed":"Възобновено","skipped":"Пропуснато","all":"Всичко","canceled":"Отказан","expired":"Изтекъл","partiallyRefunded":"Възстановена сума (частично)","orderSuccess":"Поръчка успешна","orderFailed":"Поръчка неуспешна","orderCanceled":"Поръчката е отказана"}}}');Shopware.Locale.extend("de-DE",eB),Shopware.Locale.extend("en-GB",eH),Shopware.Locale.extend("nl-NL",eK),Shopware.Locale.extend("it-IT",eq),Shopware.Locale.extend("pt-PT",e$),Shopware.Locale.extend("es-ES",eW),Shopware.Locale.extend("sv-SE",eG),Shopware.Locale.extend("nb-NO",eY),Shopware.Locale.extend("pl-PL",eQ),Shopware.Locale.extend("cs-CZ",eZ),Shopware.Locale.extend("sl-SL",eJ),Shopware.Locale.extend("hu-HU",eX),Shopware.Locale.extend("fi-FI",e0),Shopware.Locale.extend("da-DK",e1),Shopware.Locale.extend("el-GR",e2),Shopware.Locale.extend("hr-HR",e8),Shopware.Locale.extend("et-EE",e7),Shopware.Locale.extend("is-IS",e9),Shopware.Locale.extend("lt-LT",e5),Shopware.Locale.extend("lv-LV",e4),Shopware.Locale.extend("ro-RO",e3),Shopware.Locale.extend("sk-SK",e6),Shopware.Locale.extend("bg-BG",te)}()}(); \ No newline at end of file diff --git a/src/Resources/public/mollie-payments.js b/src/Resources/public/mollie-payments.js index 10586f297..c16ab4fc6 100644 --- a/src/Resources/public/mollie-payments.js +++ b/src/Resources/public/mollie-payments.js @@ -1 +1 @@ -(()=>{"use strict";var e={744(e){var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function o(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function i(e,t,n){return e.concat(t).map(function(e){return o(e,n)})}function s(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}(e))}function r(e,t){try{return t in e}catch(e){return!1}}function a(e,n,l){(l=l||{}).arrayMerge=l.arrayMerge||i,l.isMergeableObject=l.isMergeableObject||t,l.cloneUnlessOtherwiseSpecified=o;var c=Array.isArray(n);return c===Array.isArray(e)?c?l.arrayMerge(e,n,l):function(e,t,n){var i={};return n.isMergeableObject(e)&&s(e).forEach(function(t){i[t]=o(e[t],n)}),s(t).forEach(function(s){(function(e,t){return r(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,s)||(r(e,s)&&n.isMergeableObject(t[s])?i[s]=function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a}(s,n)(e[s],t[s],n):i[s]=o(t[s],n))}),i}(e,n,l):o(n,l)}a.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce(function(e,n){return a(e,n,t)},{})};var l=a;e.exports=l},988(e,t){Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e){this._el=e,e.$emitter=this,this._listeners=[]}return e.prototype.publish=function(e,t,n){void 0===t&&(t={}),void 0===n&&(n=!1);var o=new CustomEvent(e,{detail:t,cancelable:n});return this.el.dispatchEvent(o),o},e.prototype.subscribe=function(e,t,n){void 0===n&&(n={});var o=this,i=e.split("."),s=n.scope?t.bind(n.scope):t;if(n.once&&!0===n.once){var r=s;s=function(t){o.unsubscribe(e),r(t)}}return this.el.addEventListener(i[0],s),this.listeners.push({splitEventName:i,opts:n,cb:s}),!0},e.prototype.unsubscribe=function(e){var t=this,n=e.split(".");return this.listeners=this.listeners.reduce(function(e,o){return o.splitEventName.sort().toString()===n.sort().toString()?(t.el.removeEventListener(o.splitEventName[0],o.cb),e):(e.push(o),e)},[]),!0},e.prototype.reset=function(){var e=this;return this.listeners.forEach(function(t){e.el.removeEventListener(t.splitEventName[0],t.cb)}),this.listeners=[],!0},Object.defineProperty(e.prototype,"el",{get:function(){return this._el},set:function(e){this._el=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"listeners",{get:function(){return this._listeners},set:function(e){this._listeners=e},enumerable:!1,configurable:!0}),e}();t.default=n},512(e,t,n){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=o(n(988)),s=o(n(744)),r=function(){function e(e,t,n){void 0===t&&(t={}),void 0===n&&(n=!1),this.el=e,this.$emitter=new i.default(this.el),this._pluginName=this._getPluginName(n),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}return e.prototype._init=function(){this._initialized||(this.init(),this._initialized=!0)},e.prototype._update=function(){this._initialized&&this.update()},e.prototype.update=function(){},e.prototype._registerInstance=function(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)},e.prototype._getPluginName=function(e){return!1===e?this.constructor.name:e},e.prototype._mergeOptions=function(e){var t=this._pluginName.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase(),n=this.parseJsonOrFail(t);let o="";"function"==typeof this.el.getAttribute&&(o=this.el.getAttribute("data-".concat(t,"-options"))||"");var i=[this.constructor.options,this.options,e];n&&i.push(window.PluginConfigManager.get(this._pluginName,n));try{o&&i.push(JSON.parse(o))}catch(e){throw new Error("The data attribute 'data-".concat(t,"-options' could not be parsed to json: ").concat(e.message||""))}return s.default.all(i.filter(function(e){return e instanceof Object&&!(e instanceof Array)}).map(function(e){return e||{}}))},e.prototype.parseJsonOrFail=function(e){if("function"!=typeof this.el.getAttribute)return"";const t=this.el.getAttribute("data-".concat(e,"-config"))||"";try{return JSON.parse(t)}catch(e){return t}},e}();t.default=r}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var s=t[o]={exports:{}};return e[o].call(s.exports,s,s.exports,n),s.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var o=n(744),i=n.n(o);const s="application/json";class r{get(e,t=null,n=null,o=s){this.send("GET",e,null,t,n,o)}post(e,t=null,n=null,o=null,i=s){this.send("POST",e,t,n,o,i)}send(e,t,n=null,o=null,i=null,r=s){const a=new XMLHttpRequest;a.open(e,t),a.setRequestHeader("Content-Type",r),a.onload=function(){if(!o||"function"!=typeof o)return;const e=a.getResponseHeader("content-type"),t="response"in a?a.response:a.responseText;e.indexOf("application/json")>-1?o(JSON.parse(t)):o(t)},a.onerror=function(){i&&"function"==typeof o&&i()},a.send(n)}}var a=n(512),l=n.n(a);class c extends(l()){}const d="d-none";class u extends c{static options={newCardMandateOption:null,mollieCreditCardFormClass:".mollie-components-credit-card",mollieCreditCardMandateInput:'input[name="mollieCreditCardMandate"]',mollieShouldSaveCardDetailInput:'input[name="mollieShouldSaveCardDetail"]'};init(){this.client=new r,this._fixShopUrl()}registerMandateEvents(){const{newCardMandateOption:e}=this.options;e&&(this.mollieCreditCarfFormEl=document.querySelector(this.options.mollieCreditCardFormClass),this.mollieCreditCardMandateEls=document.querySelectorAll(this.options.mollieCreditCardMandateInput),this.mollieCreditCarfFormEl&&this.mollieCreditCardMandateEls&&this._registerRadioButtonsEvent())}_fixShopUrl(){null!=this.options.shopUrl&&"/"===this.options.shopUrl.substr(-1)&&(this.options.shopUrl=this.options.shopUrl.substr(0,this.options.shopUrl.length-1))}_registerRadioButtonsEvent(){this.onMandateInputChange(this.getMandateCheckedValue()),this.mollieCreditCardMandateEls.forEach(e=>{e.addEventListener("change",()=>{this.onMandateInputChange(this.getMandateCheckedValue())})})}getMandateCheckedValue(){const e=document.querySelector(`${this.options.mollieCreditCardMandateInput}:checked`);return e&&e.value?e.value:null}isValidSelectedMandate(e){return e&&e!==this.options.newCardMandateOption}shouldSaveCardDetail(){const e=document.querySelector(this.options.mollieShouldSaveCardDetailInput);return!!e&&e.checked}onMandateInputChange(e){e!==this.options.newCardMandateOption?null!==e&&this.mollieCreditCarfFormEl.classList.add(d):this.mollieCreditCarfFormEl.classList.remove(d)}}const p="error";class h extends u{static options=i()(u.options,{customerId:null,locale:null,profileId:null,shopUrl:null,testMode:!0});init(){super.init();const e=this;let t=null;const n=document.querySelector("div.mollie-components-controller");n&&n.remove(),this.getElements(),this._componentsContainer&&this._cardHolder&&(t=Mollie(this.options.profileId,{locale:this.options.locale,testmode:this.options.testMode})),this.createComponentsInputs(t,[this.getInputFields().cardHolder,this.getInputFields().cardNumber,this.getInputFields().expiryDate,this.getInputFields().verificationCode]),this._submitButton.addEventListener("click",n=>{n.preventDefault(),e.submitForm(n,t,this._paymentForm)}),this.registerMandateEvents()}getElements(){this._cardHolder=document.querySelector("#cardHolder"),this._componentsContainer=document.querySelector("div.mollie-components-credit-card"),this._paymentForm=document.querySelector("#confirmPaymentForm"),this._radioInputs=document.querySelectorAll('#confirmPaymentForm input[type="radio"]'),this._submitButton=document.querySelector('#confirmPaymentForm button[type="submit"]'),this._creditCardRadioInput=document.querySelector('#confirmPaymentForm input[type="radio"].creditcard')}getDefaultProperties(){return{styles:{base:{backgroundColor:"#fff",fontSize:"14px",padding:"10px 10px","::placeholder":{color:"rgba(68, 68, 68, 0.2)"}},valid:{color:"#090"},invalid:{backgroundColor:"#fff1f3"}}}}getInputFields(){return{cardHolder:{name:"cardHolder",id:"#cardHolder",errors:"cardHolderError"},cardNumber:{name:"cardNumber",id:"#cardNumber",errors:"cardNumberError"},expiryDate:{name:"expiryDate",id:"#expiryDate",errors:"expiryDateError"},verificationCode:{name:"verificationCode",id:"#verificationCode",errors:"verificationCodeError"}}}createComponentsInputs(e,t){const n=this;t.forEach((t,o,i)=>{const s=e.createComponent(t.name,n.getDefaultProperties());s.mount(t.id),i[o][t.name]=s,s.addEventListener("change",e=>{const n=document.getElementById(`${t.name}`),o=document.getElementById(`${t.errors}`);e.error&&e.touched?(n.classList.add(p),o.textContent=e.error):(n.classList.remove(p),o.textContent="")}),s.addEventListener("focus",()=>{n.setFocus(`${t.id}`,!0)}),s.addEventListener("blur",()=>{n.setFocus(`${t.id}`,!1)})})}setFocus(e,t){document.querySelector(e).classList.toggle("is-focused",t)}disableForm(){this._submitButton&&(this._submitButton.disabled=!0)}enableForm(){this._submitButton&&(this._submitButton.disabled=!1)}async submitForm(e,t,n){e.preventDefault();const o=this;if(this.disableForm(),void 0!==this._creditCardRadioInput&&null!==this._creditCardRadioInput&&!1!==this._creditCardRadioInput.checked||!n||n.submit(),this._creditCardRadioInput&&!0===this._creditCardRadioInput.checked){const e=this.getMandateCheckedValue();if(this.isValidSelectedMandate(e))return void this.client.post(o.options.shopUrl+"/mollie/components/store-mandate-id/"+o.options.customerId+"/"+e,()=>{n.submit()},()=>{n.submit()},"application/json; charset=utf-8");const i=document.getElementById(`${this.getInputFields().verificationCode.errors}`);i.textContent="";const{token:s,error:r}=await t.createToken();if(r)return this.enableForm(),void(i.textContent=r.message);r||this.client.post(o.options.shopUrl+"/mollie/components/store-card-token/"+s,JSON.stringify({shouldSaveCardDetail:this.shouldSaveCardDetail()}),()=>{document.getElementById("cardToken").setAttribute("value",s),n.submit()},()=>{n.submit()},"application/json; charset=utf-8")}}}class m{static isTouchDevice(){return"ontouchstart"in document.documentElement}static isIOSDevice(){return m.isIPhoneDevice()||m.isIPadDevice()}static isNativeWindowsBrowser(){return m.isIEBrowser()||m.isEdgeBrowser()}static isIPhoneDevice(){return!!navigator.userAgent.match(/iPhone/i)}static isIPadDevice(){return!!navigator.userAgent.match(/iPad/i)}static isIEBrowser(){return-1!==navigator.userAgent.toLowerCase().indexOf("msie")||!!navigator.userAgent.match(/Trident.*rv:\d+\./)}static isEdgeBrowser(){return!!navigator.userAgent.match(/Edge\/\d+/i)}static getList(){return{"is-touch":m.isTouchDevice(),"is-ios":m.isIOSDevice(),"is-native-windows":m.isNativeWindowsBrowser(),"is-iphone":m.isIPhoneDevice(),"is-ipad":m.isIPadDevice(),"is-ie":m.isIEBrowser(),"is-edge":m.isEdgeBrowser()}}}class y{constructor(e){this.csrf=e}isActive(){return void 0!==this.csrf&&!1!==this.csrf.enabled&&"ajax"===this.csrf.mode}}class f{constructor(e){this._document=e}getPaymentForm(){return this._document.querySelector("#changePaymentForm")}getConfirmForm(){return this._document.querySelector("#confirmOrderForm")}getSubmitButton(){let e=this._document.querySelector("#confirmFormSubmit");return null===e&&(e=this._document.querySelector('#confirmOrderForm > button[type="submit"]')),e}}const g="error";class v extends u{static options=i()(u.options,{paymentId:null,customerId:null,locale:null,profileId:null,shopUrl:null,testMode:!0});init(){super.init();try{const e=new f(document);this._paymentForm=e.getPaymentForm(),this._confirmForm=e.getConfirmForm(),this._confirmFormButton=e.getSubmitButton()}catch(e){return void console.error("Mollie Credit Card components: Required HTML elements not found on this page!")}this._initializeComponentInstance(),this._registerEvents(),this.registerMandateEvents()}_initializeComponentInstance(){const e=document.querySelector("#cardHolder");document.querySelector("div.mollie-components-credit-card")&&e&&!window.mollieComponentsObject&&(window.mollieComponentsObject=Mollie(this.options.profileId,{locale:this.options.locale,testmode:this.options.testMode}),window.mollieComponents={}),this.createComponentsInputs()}_registerEvents(){null!==this._confirmForm&&this._confirmForm.addEventListener("submit",this.submitForm.bind(this))}_reactivateFormSubmit(){this._confirmFormButton.disabled=!1;const e=this._confirmFormButton.querySelector(".loader");e&&e.remove()}getDefaultProperties(){return{styles:{base:{backgroundColor:"#fff",fontSize:"14px",padding:"10px 10px","::placeholder":{color:"rgba(68, 68, 68, 0.2)"}},valid:{color:"#090"},invalid:{backgroundColor:"#fff1f3"}}}}getInputFields(){return{cardHolder:{name:"cardHolder",id:"#cardHolder",errors:"cardHolderError"},cardNumber:{name:"cardNumber",id:"#cardNumber",errors:"cardNumberError"},expiryDate:{name:"expiryDate",id:"#expiryDate",errors:"expiryDateError"},verificationCode:{name:"verificationCode",id:"#verificationCode",errors:"verificationCodeError"}}}createComponentsInputs(){const e=this,t=[this.getInputFields().cardHolder,this.getInputFields().cardNumber,this.getInputFields().expiryDate,this.getInputFields().verificationCode];window.mollieComponentsObject&&t.forEach((t,n,o)=>{const i=this._mountMollieComponent(t.id,t.name);o[n][t.name]=i,i.addEventListener("change",e=>{const n=document.getElementById(`${t.name}`),o=document.getElementById(`${t.errors}`);e.error&&e.touched?(n.classList.add(g),o.textContent=e.error):(n.classList.remove(g),o.textContent="")}),i.addEventListener("focus",()=>{e.setFocus(`${t.id}`,!0)}),i.addEventListener("blur",()=>{e.setFocus(`${t.id}`,!1)})})}_mountMollieComponent(e,t){return window.mollieComponents[t]?window.mollieComponents[t].unmount():window.mollieComponents[t]=window.mollieComponentsObject.createComponent(t,this.getDefaultProperties()),window.mollieComponents[t].mount(e),window.mollieComponents[t]}setFocus(e,t){document.querySelector(e).classList.toggle("is-focused",t)}async submitForm(e){const t=this,n=this._confirmForm,o=document.querySelector(`#changePaymentForm input[type="radio"][value="${this.options.paymentId}"]`);if((null==o||!1===o.checked)&&this._confirmForm)return;if(o&&!1===o.checked)return;e.preventDefault();const i=this.getMandateCheckedValue();if(this.isValidSelectedMandate(i))return void this.client.post(t.options.shopUrl+"/mollie/components/store-mandate-id/"+t.options.customerId+"/"+i,()=>{t.continueShopwareCheckout(n)},()=>{t.continueShopwareCheckout(n)},"application/json; charset=utf-8");const s=document.getElementById(`${this.getInputFields().verificationCode.errors}`);s.textContent="";const{token:r,error:a}=await window.mollieComponentsObject.createToken();if(a)return s.textContent=a.message,this._reactivateFormSubmit(),void s.scrollIntoView();this.client.post(t.options.shopUrl+"/mollie/components/store-card-token/"+r,JSON.stringify({shouldSaveCardDetail:this.shouldSaveCardDetail()}),function(){t.continueShopwareCheckout(n)},function(){t.continueShopwareCheckout(n)},"application/json; charset=utf-8")}continueShopwareCheckout(e){if(m.isIEBrowser()){const t=function(e,t){const n=document.createElement("input");return n.type="checkbox",n.name=e,n.checked=t,n.style.display="none",n},n=document.getElementById("tos");null!=n&&e.insertAdjacentElement("beforeend",t("tos",n.checked))}new y(window.csrf).isActive()||e.submit()}}class C{constructor(e){this._document=e}findClosestShopwareBuyButton(e){const t=this.findClosestBuyBox(e);return null===t?null:t.querySelector(".btn-buy")}findClosestApplePayContainer(e){return e.closest(".mollie-apple-pay-direct")}findClosestBuyBox(e){let t=e.closest(".product-action");return null===t&&(t=e.closest(".product-detail-form-container")),null===t&&(t=e.closest(".offcanvas-cart-actions")),null===t&&(t=e.closest(".checkout-aside-container")),null===t&&(t=e.closest(".checkout-main")),t}findAllExpressButtons(e,t=null){let n=".mollie-express-button";return null!==t&&(n+=t),e.querySelectorAll(n)}findApplePayButtons(){return this._document.querySelectorAll(".mollie-express-button.js-apple-pay")}findApplePayContainers(){return this._document.querySelectorAll(".js-apple-pay-container")}findPayPalExpressButtons(){return this._document.querySelectorAll(".mollie-paypal-button")}findClosestPrivacyBox(e){const t=this.findClosestBuyBox(e);return null===t?null:t.querySelector(".mollie-privacy-note")}getPrivacyBoxCheckbox(e){return e.querySelector('input[name="acceptedDataProtection"]')}}const _="d-none",b="is-invalid";class S{constructor(e){this._repoBuyBox=new C,this._document=e}initCheckbox(){const e=this._document.querySelectorAll(".mollie-privacy-note:not(.observed)");for(let t=0;t{let t=i.length;n.classList.remove(_),e.forEach(e=>{e.target.classList.contains(_)&&t--}),t<=0&&n.classList.add(_)}).observe(t,{attributes:!0,attributeFilter:["class"]})}else n.classList.add(_)}}validateForExpressButton(e){const t=this._repoBuyBox.findClosestPrivacyBox(e);if(!(t instanceof HTMLDivElement))return!0;const n=this._repoBuyBox.getPrivacyBoxCheckbox(t),o=n.checked?1:0;return n.classList.remove(b),0!==o||(n.classList.add(b),!1)}}class E{addEventListenerOnce(e,t,n="click"){const o="__handler_"+n;e[o]||(e.addEventListener(n,t),e[o]=!0)}}class w{register(e,t){const n=window.PluginManager.getPluginList().OffCanvasCart.get("instances");if(n)for(let o=0;o{if(a.readyState===XMLHttpRequest.DONE&&(e.classList.remove(P),a.status>=400))throw new Error(`Request failed with status ${a.status}`)},a.send(i.join("&"))}}class M{APPLE_PAY_VERSION=3;constructor(){this.client=new r}create(e,t,n,o,i,s,r){const a=this;var l=["name","email","postalAddress"];1===o&&l.push("phone");let c=!1;null!==s&&(c=s.value);var d={countryCode:t,currencyCode:n,requiredShippingContactFields:l,supportedNetworks:["amex","maestro","masterCard","visa","vPay"],merchantCapabilities:["supports3DS"],total:{label:"",amount:0}};const u=new ApplePaySession(this.APPLE_PAY_VERSION,d);return u.onvalidatemerchant=function(e){a.client.post(i+"/mollie/apple-pay/validate",JSON.stringify({validationUrl:e.validationURL}),t=>{if(!1===t.success)throw new Error("Validation failed for URL: "+e.validationURL);const n=JSON.parse(t.session);u.completeMerchantValidation(n)},()=>{u.abort()})},u.onshippingcontactselected=function(e){var t="";void 0!==e.shippingContact.countryCode&&(t=e.shippingContact.countryCode),a.client.post(i+"/mollie/apple-pay/shipping-methods",JSON.stringify({countryCode:t}),e=>{e.success?u.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS,e.shippingmethods,e.cart.total,e.cart.items):u.completeShippingContactSelection(ApplePaySession.STATUS_FAILURE,[],{label:"",amount:0,pending:!0},[])},()=>{u.abort()})},u.onshippingmethodselected=function(e){a.client.post(i+"/mollie/apple-pay/set-shipping",JSON.stringify({identifier:e.shippingMethod.identifier}),e=>{e.success?u.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS,e.cart.total,e.cart.items):u.completeShippingMethodSelection(ApplePaySession.STATUS_FAILURE,{label:"",amount:0,pending:!0},[])},()=>{u.abort()})},u.onpaymentauthorized=function(e){var t=e.payment.token;t=JSON.stringify(t),u.completePayment(ApplePaySession.STATUS_SUCCESS),a.finishPayment(i+"/mollie/apple-pay/start-payment",t,e.payment,c),r.classList.remove("processed")},u.oncancel=function(){e&&a.client.post(i+"/mollie/apple-pay/restore-cart"),r.classList.remove("processed")},u}finishPayment(e,t,n,o){const i=function(e,t){const n=document.createElement("input");return n.type="hidden",n.name=e,n.value=t,n},s=document.createElement("form");s.action=e,s.method="POST";let r=n.shippingContact.addressLines[0];n.shippingContact.addressLines.length>1&&(r+=" "+n.shippingContact.addressLines[1]),s.insertAdjacentElement("beforeend",i("email",n.shippingContact.emailAddress)),s.insertAdjacentElement("beforeend",i("lastname",n.shippingContact.familyName)),s.insertAdjacentElement("beforeend",i("firstname",n.shippingContact.givenName)),s.insertAdjacentElement("beforeend",i("street",r)),s.insertAdjacentElement("beforeend",i("postalCode",n.shippingContact.postalCode)),s.insertAdjacentElement("beforeend",i("city",n.shippingContact.locality)),s.insertAdjacentElement("beforeend",i("acceptedDataProtection",o)),void 0!==n.shippingContact.phoneNumber&&n.shippingContact.phoneNumber.length>0&&s.insertAdjacentElement("beforeend",i("phone",n.shippingContact.phoneNumber)),s.insertAdjacentElement("beforeend",i("countryCode",n.shippingContact.countryCode)),s.insertAdjacentElement("beforeend",i("paymentToken",t)),document.body.insertAdjacentElement("beforeend",s),s.submit()}}class A{constructor(){this._repoBuyBox=new C}isCheckoutPossible(e){const t=this._repoBuyBox.findClosestShopwareBuyButton(e);return!(t instanceof HTMLButtonElement&&t.hasAttribute("disabled"))}}class I{constructor(e,t){this._countryCode=e.querySelector('input[name="countryCode"]').value,this._currency=e.querySelector('input[name="currency"]').value,this._mode=e.querySelector('input[name="mode"]').value,this._withPhone=parseInt(e.querySelector('input[name="withPhone"]').value),this._dataProtection=e.querySelector('input[name="acceptedDataProtection"]'),this._isProductMode="productMode"===this._mode;let n=t.getAttribute("data-shop-url");"/"===n.slice(-1)&&(n=n.slice(0,-1)),this._shopSlug=n}isProductMode(){return this._isProductMode}getCountryCode(){return this._countryCode}getCurrency(){return this._currency}getMode(){return this._mode}getWithPhone(){return this._withPhone}getDataProtection(){return this._dataProtection}getShopSlug(){return this._shopSlug}}const x="d-none";class L extends c{init(){this._privacySection=new S(document),this._eventUtils=new E,this._cartService=new B,this._productBoxValidator=new A,this._repoBuyBox=new C(document),(new w).register(this.initCurrentPage.bind(this),"mollie-apple-pay-direct"),this.initCurrentPage()}initCurrentPage(){if(this._applePayButtons=this._repoBuyBox.findApplePayButtons(),this._applePayContainers=this._repoBuyBox.findApplePayContainers(),!window.ApplePaySession||!window.ApplePaySession.canMakePayments()||this._applePayButtons.length<=0)this.hideApplePayFeature();else if(this._privacySection.initCheckbox(),this.showApplePayFeature(),this._applePayButtons)for(let e=0;e{this.updateButtonVisibility(t)})}}updateButtonVisibility(e){this._productBoxValidator.isCheckoutPossible(e)?(e.hidden=!1,e.classList.remove(x)):(e.hidden=!0,e.classList.add(x))}showApplePayFeature(){if(this._applePayContainers)for(let e=0;e=0&&t.item(n)!==this;);return n>-1});e&&e!==document;e=e.parentNode)if(e.matches(t))return e;return null}}const O="d-none";class k extends c{static options={shopUrl:null,customerId:null,mollieMandateContainerClass:".mollie-credit-card-mandate",mollieMandateDataId:"data-mollie-credit-card-mandate-id",mollieMandateRemoveButtonClass:".mollie-credit-card-mandate-remove",mollieMandateRemoveModalButtonClass:".mollie-credit-card-mandate-remove-modal-button",mollieMandateDeleteAlertSuccessId:"#mollieCreditCardMandateDeleteSuccess",mollieMandateDeleteAlertErrorId:"#mollieCreditCardMandateDeleteError"};init(){if(!this.options.shopUrl)throw new Error(`The "shopUrl" option for the plugin "${this._pluginName}" is not defined.`);if(!this.options.customerId)throw new Error(`The "customerId" option for the plugin "${this._pluginName}" is not defined.`);this.mollieMandateDeleteAlertEl=document.querySelector(this.options.mollieMandateDeleteAlertSuccessId),this.mollieMandateDeleteAlertEl&&(this.mollieMandateDeleteAlertErrorEl=document.querySelector(this.options.mollieMandateDeleteAlertErrorId),this.mollieMandateDeleteAlertErrorEl&&(this.client=new r,this.registerEvents()))}registerEvents(){const e=document.querySelectorAll(this.options.mollieMandateRemoveButtonClass);if(!e||0===e.length)return;const t=document.querySelectorAll(this.options.mollieMandateRemoveModalButtonClass);t&&0!==t.length&&(e.forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),this.onRemoveButtonClick(e)})}),t.forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),this.onConfirmRemoveButtonClick()})}))}onRemoveButtonClick(e){this.currentContainerEl=e.closest(this.options.mollieMandateContainerClass),this.currentContainerEl&&(this.currentMandateId=this.currentContainerEl.getAttribute(this.options.mollieMandateDataId))}onConfirmRemoveButtonClick(){const{currentContainerEl:e,currentMandateId:t}=this;e&&t&&this.deleteMandate(t).then(({success:t})=>{t?(this.mollieMandateDeleteAlertErrorEl.classList.add(O),this.mollieMandateDeleteAlertEl.classList.remove(O),e.remove()):(this.mollieMandateDeleteAlertEl.classList.add(O),this.mollieMandateDeleteAlertErrorEl.classList.remove(O))})}deleteMandate(e){return new Promise(t=>{this.client.post(this.options.shopUrl+"/mollie/components/revoke-mandate/"+e,"",e=>{t({success:e&&e.success})},()=>{t({success:!1})},"application/json; charset=utf-8")})}}const D="d-none";class q extends c{_shopUrl="";_customerId="";_dropdownTerminals=null;_container=null;_paymentForm=null;_radioInputs=null;_posRadioInput=null;init(){this._container=document.querySelector("div.mollie-pos-terminals"),void 0!==this._container&&null!==this._container&&(this.initControls(),null!==this._paymentForm&&null!==this._dropdownTerminals&&(this.registerEvents(),this.updateDropdownVisibility(this._posRadioInput,this._container,this._dropdownTerminals),this.updateTerminal(this._shopUrl,this._customerId,this._posRadioInput,this._dropdownTerminals,function(){})))}initControls(){this._shopUrl=this._container.getAttribute("data-shop-url"),"/"===this._shopUrl.substr(-1)&&(this._shopUrl=this._shopUrl.substr(0,this._shopUrl.length-1)),this._customerId=this._container.getAttribute("data-customer-id"),this._dropdownTerminals=document.querySelector("#posTerminals"),this._paymentForm=document.querySelector("#changePaymentForm"),void 0!==this._paymentForm&&null!==this._paymentForm&&(this._radioInputs=this._paymentForm.querySelectorAll('input[type="radio"]'),this._posRadioInput=this._paymentForm.querySelector('input[type="radio"].pointofsale'))}registerEvents(){if(null===this._paymentForm)return;const e=this._shopUrl,t=this._customerId,n=this._container,o=this._radioInputs,i=this._posRadioInput,s=this._dropdownTerminals;o.forEach(e=>{e.addEventListener("change",()=>{this.updateDropdownVisibility(i,n,s)})}),s.addEventListener("change",async()=>{this.updateTerminal(e,t,i,s,function(){})})}updateDropdownVisibility(e,t,n){let o=!1;void 0===e||!1===e.checked?t.classList.add(D):(t.classList.remove(D),o=!0),void 0!==n&&(n.required=o)}updateTerminal(e,t,n,o,i){void 0!==n?null!==n?!1!==n.checked?void 0!==o?null!==o?""!==o.value?(new r).post(e+"/mollie/pos/store-terminal/"+o.value,"",function(){i("terminal updated successfully")},function(){i("error when updating terminal")},"application/json; charset=utf-8"):i("no POS terminal selected"):i("POS terminals not found"):i("POS terminals not defined"):i("POS payment not active"):i("POS Radio Input not found"):i("POS Radio Input not defined")}}const j="d-none";class T extends c{init(){this._privacySection=new S(document),this._eventUtils=new E,this._cartService=new B,this._productBoxValidator=new A,this._repoBuyBox=new C(document),(new w).register(this.bindEvents.bind(this),"mollie-paypal-express"),this.bindEvents()}bindEvents(){const e=this._repoBuyBox.findPayPalExpressButtons();if(0!==e.length){this._privacySection.initCheckbox();for(let t=0;t{this.updateButtonVisibility(n)})}}}updateButtonVisibility(e){this._productBoxValidator.isCheckoutPossible(e)?(e.hidden=!1,e.classList.remove(j)):(e.hidden=!0,e.classList.add(j))}onExpressCheckout(e){const t=e.currentTarget;if(!this._productBoxValidator.isCheckoutPossible(t))return;if(!this._privacySection.validateForExpressButton(t))return;this._cartService.addItemToCart(t);const n=t.getAttribute("data-form-action"),o=document.createElement("form");o.setAttribute("action",n),o.setAttribute("method","POST"),document.body.insertAdjacentElement("beforeend",o),o.submit()}}const U="d-none",N="invalid";class R extends c{init(){const e=document.getElementById("molliePayPhone");if(null===e)return;const t=document.querySelector(".mollie-phone-field"),n=document.querySelector('.mollie-phone-field [data-form-validation-invalid-phone="true"]');e.addEventListener("focus",e=>{t.classList.add("was-validated"),e.target.removeAttribute(N),n.classList.add(U)}),e.addEventListener("blur",e=>{const t=e.target.form;return!1===t.reportValidity()&&(e.target.setAttribute(N,!0),n.classList.remove(U)),t.reportValidity()})}}class V{register(){const e=window.PluginManager;e.register("MollieApplePayDirect",L),e.register("PayPalExpressPlugin",T),e.register("MollieApplePayPaymentMethod",F,"[data-mollie-template-applepay-account]"),e.register("MollieApplePayPaymentMethod",F,"[data-mollie-template-applepay-checkout]"),e.register("MollieCreditCardComponents",h,"[data-mollie-template-creditcard-components]"),e.register("MollieCreditCardComponentsSw64",v,"[data-mollie-template-creditcard-components-sw64]"),e.register("MollieCreditCardMandateManage",k,"[data-mollie-credit-card-mandate-manage]"),e.register("MolliePosTerminal",q,"[data-mollie-template-pos-terminal]"),e.register("MolliePhonePlugin",R,"[data-mollie-phone-validation]")}}window.addEventListener("load",function(){void 0!==window.mollie_javascript_use_shopware&&"1"!==window.mollie_javascript_use_shopware&&((new V).register(),window.dispatchEvent(new Event("mollieLoaded")),window.PluginManager.initializePlugins())})})(); \ No newline at end of file +(()=>{"use strict";var e={744(e){var t=function(e){return function(e){return!!e&&"object"==typeof e}(e)&&!function(e){var t=Object.prototype.toString.call(e);return"[object RegExp]"===t||"[object Date]"===t||function(e){return e.$$typeof===n}(e)}(e)},n="function"==typeof Symbol&&Symbol.for?Symbol.for("react.element"):60103;function o(e,t){return!1!==t.clone&&t.isMergeableObject(e)?a((n=e,Array.isArray(n)?[]:{}),e,t):e;var n}function i(e,t,n){return e.concat(t).map(function(e){return o(e,n)})}function r(e){return Object.keys(e).concat(function(e){return Object.getOwnPropertySymbols?Object.getOwnPropertySymbols(e).filter(function(t){return Object.propertyIsEnumerable.call(e,t)}):[]}(e))}function s(e,t){try{return t in e}catch(e){return!1}}function a(e,n,l){(l=l||{}).arrayMerge=l.arrayMerge||i,l.isMergeableObject=l.isMergeableObject||t,l.cloneUnlessOtherwiseSpecified=o;var c=Array.isArray(n);return c===Array.isArray(e)?c?l.arrayMerge(e,n,l):function(e,t,n){var i={};return n.isMergeableObject(e)&&r(e).forEach(function(t){i[t]=o(e[t],n)}),r(t).forEach(function(r){(function(e,t){return s(e,t)&&!(Object.hasOwnProperty.call(e,t)&&Object.propertyIsEnumerable.call(e,t))})(e,r)||(s(e,r)&&n.isMergeableObject(t[r])?i[r]=function(e,t){if(!t.customMerge)return a;var n=t.customMerge(e);return"function"==typeof n?n:a}(r,n)(e[r],t[r],n):i[r]=o(t[r],n))}),i}(e,n,l):o(n,l)}a.all=function(e,t){if(!Array.isArray(e))throw new Error("first argument should be an array");return e.reduce(function(e,n){return a(e,n,t)},{})};var l=a;e.exports=l},988(e,t){Object.defineProperty(t,"__esModule",{value:!0});var n=function(){function e(e){this._el=e,e.$emitter=this,this._listeners=[]}return e.prototype.publish=function(e,t,n){void 0===t&&(t={}),void 0===n&&(n=!1);var o=new CustomEvent(e,{detail:t,cancelable:n});return this.el.dispatchEvent(o),o},e.prototype.subscribe=function(e,t,n){void 0===n&&(n={});var o=this,i=e.split("."),r=n.scope?t.bind(n.scope):t;if(n.once&&!0===n.once){var s=r;r=function(t){o.unsubscribe(e),s(t)}}return this.el.addEventListener(i[0],r),this.listeners.push({splitEventName:i,opts:n,cb:r}),!0},e.prototype.unsubscribe=function(e){var t=this,n=e.split(".");return this.listeners=this.listeners.reduce(function(e,o){return o.splitEventName.sort().toString()===n.sort().toString()?(t.el.removeEventListener(o.splitEventName[0],o.cb),e):(e.push(o),e)},[]),!0},e.prototype.reset=function(){var e=this;return this.listeners.forEach(function(t){e.el.removeEventListener(t.splitEventName[0],t.cb)}),this.listeners=[],!0},Object.defineProperty(e.prototype,"el",{get:function(){return this._el},set:function(e){this._el=e},enumerable:!1,configurable:!0}),Object.defineProperty(e.prototype,"listeners",{get:function(){return this._listeners},set:function(e){this._listeners=e},enumerable:!1,configurable:!0}),e}();t.default=n},512(e,t,n){var o=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0});var i=o(n(988)),r=o(n(744)),s=function(){function e(e,t,n){void 0===t&&(t={}),void 0===n&&(n=!1),this.el=e,this.$emitter=new i.default(this.el),this._pluginName=this._getPluginName(n),this.options=this._mergeOptions(t),this._initialized=!1,this._registerInstance(),this._init()}return e.prototype._init=function(){this._initialized||(this.init(),this._initialized=!0)},e.prototype._update=function(){this._initialized&&this.update()},e.prototype.update=function(){},e.prototype._registerInstance=function(){window.PluginManager.getPluginInstancesFromElement(this.el).set(this._pluginName,this),window.PluginManager.getPlugin(this._pluginName,!1).get("instances").push(this)},e.prototype._getPluginName=function(e){return!1===e?this.constructor.name:e},e.prototype._mergeOptions=function(e){var t=this._pluginName.replace(/([A-Z])/g,"-$1").replace(/^-/,"").toLowerCase(),n=this.parseJsonOrFail(t);let o="";"function"==typeof this.el.getAttribute&&(o=this.el.getAttribute("data-".concat(t,"-options"))||"");var i=[this.constructor.options,this.options,e];n&&i.push(window.PluginConfigManager.get(this._pluginName,n));try{o&&i.push(JSON.parse(o))}catch(e){throw new Error("The data attribute 'data-".concat(t,"-options' could not be parsed to json: ").concat(e.message||""))}return r.default.all(i.filter(function(e){return e instanceof Object&&!(e instanceof Array)}).map(function(e){return e||{}}))},e.prototype.parseJsonOrFail=function(e){if("function"!=typeof this.el.getAttribute)return"";const t=this.el.getAttribute("data-".concat(e,"-config"))||"";try{return JSON.parse(t)}catch(e){return t}},e}();t.default=s}},t={};function n(o){var i=t[o];if(void 0!==i)return i.exports;var r=t[o]={exports:{}};return e[o].call(r.exports,r,r.exports,n),r.exports}n.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return n.d(t,{a:t}),t},n.d=(e,t)=>{for(var o in t)n.o(t,o)&&!n.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var o=n(744),i=n.n(o);const r="application/json";class s{get(e,t=null,n=null,o=r){this.send("GET",e,null,t,n,o)}post(e,t=null,n=null,o=null,i=r){this.send("POST",e,t,n,o,i)}send(e,t,n=null,o=null,i=null,s=r){const a=new XMLHttpRequest;a.open(e,t),a.setRequestHeader("Content-Type",s),a.onload=function(){if(!o||"function"!=typeof o)return;const e=a.getResponseHeader("content-type"),t="response"in a?a.response:a.responseText;e.indexOf("application/json")>-1?o(JSON.parse(t)):o(t)},a.onerror=function(){i&&"function"==typeof o&&i()},a.send(n)}}var a=n(512),l=n.n(a);class c extends(l()){}const d="d-none";class u extends c{static options={newCardMandateOption:null,mollieCreditCardFormClass:".mollie-components-credit-card",mollieCreditCardMandateInput:'input[name="mandateId"]',mollieShouldSaveCardDetailInput:'input[name="mollieShouldSaveCardDetail"]'};init(){this.client=new s,this._fixShopUrl()}registerMandateEvents(){const{newCardMandateOption:e}=this.options;e&&(this.mollieCreditCarfFormEl=document.querySelector(this.options.mollieCreditCardFormClass),this.mollieCreditCardMandateEls=document.querySelectorAll(this.options.mollieCreditCardMandateInput),this.mollieCreditCarfFormEl&&this.mollieCreditCardMandateEls&&this._registerRadioButtonsEvent())}_fixShopUrl(){null!=this.options.shopUrl&&"/"===this.options.shopUrl.substr(-1)&&(this.options.shopUrl=this.options.shopUrl.substr(0,this.options.shopUrl.length-1))}_registerRadioButtonsEvent(){this.onMandateInputChange(this.getMandateCheckedValue()),this.mollieCreditCardMandateEls.forEach(e=>{e.addEventListener("change",()=>{this.onMandateInputChange(this.getMandateCheckedValue())})})}getMandateCheckedValue(){const e=document.querySelector(`${this.options.mollieCreditCardMandateInput}:checked`);return e&&e.value?e.value:null}isValidSelectedMandate(e){return e&&e!==this.options.newCardMandateOption}shouldSaveCardDetail(){const e=document.querySelector(this.options.mollieShouldSaveCardDetailInput);return!!e&&e.checked}onMandateInputChange(e){e!==this.options.newCardMandateOption?null!==e&&this.mollieCreditCarfFormEl.classList.add(d):this.mollieCreditCarfFormEl.classList.remove(d)}}const p="error";class h extends u{static options=i()(u.options,{customerId:null,locale:null,profileId:null,shopUrl:null,testMode:!0});init(){super.init();const e=this;let t=null;const n=document.querySelector("div.mollie-components-controller");n&&n.remove(),this.getElements(),this._componentsContainer&&this._cardHolder&&(t=Mollie(this.options.profileId,{locale:this.options.locale,testmode:this.options.testMode})),this.createComponentsInputs(t,[this.getInputFields().cardHolder,this.getInputFields().cardNumber,this.getInputFields().expiryDate,this.getInputFields().verificationCode]),this._submitButton.addEventListener("click",n=>{n.preventDefault(),e.submitForm(n,t,this._paymentForm)}),this.registerMandateEvents()}getElements(){this._cardHolder=document.querySelector("#cardHolder"),this._componentsContainer=document.querySelector("div.mollie-components-credit-card"),this._paymentForm=document.querySelector("#confirmPaymentForm"),this._radioInputs=document.querySelectorAll('#confirmPaymentForm input[type="radio"]'),this._submitButton=document.querySelector('#confirmPaymentForm button[type="submit"]'),this._creditCardRadioInput=document.querySelector('#confirmPaymentForm input[type="radio"].creditcard')}getDefaultProperties(){return{styles:{base:{backgroundColor:"#fff",fontSize:"14px",padding:"10px 10px","::placeholder":{color:"rgba(68, 68, 68, 0.2)"}},valid:{color:"#090"},invalid:{backgroundColor:"#fff1f3"}}}}getInputFields(){return{cardHolder:{name:"cardHolder",id:"#cardHolder",errors:"cardHolderError"},cardNumber:{name:"cardNumber",id:"#cardNumber",errors:"cardNumberError"},expiryDate:{name:"expiryDate",id:"#expiryDate",errors:"expiryDateError"},verificationCode:{name:"verificationCode",id:"#verificationCode",errors:"verificationCodeError"}}}createComponentsInputs(e,t){const n=this;t.forEach((t,o,i)=>{const r=e.createComponent(t.name,n.getDefaultProperties());r.mount(t.id),i[o][t.name]=r,r.addEventListener("change",e=>{const n=document.getElementById(`${t.name}`),o=document.getElementById(`${t.errors}`);e.error&&e.touched?(n.classList.add(p),o.textContent=e.error):(n.classList.remove(p),o.textContent="")}),r.addEventListener("focus",()=>{n.setFocus(`${t.id}`,!0)}),r.addEventListener("blur",()=>{n.setFocus(`${t.id}`,!1)})})}setFocus(e,t){document.querySelector(e).classList.toggle("is-focused",t)}disableForm(){this._submitButton&&(this._submitButton.disabled=!0)}enableForm(){this._submitButton&&(this._submitButton.disabled=!1)}async submitForm(e,t,n){e.preventDefault();const o=this;if(this.disableForm(),void 0!==this._creditCardRadioInput&&null!==this._creditCardRadioInput&&!1!==this._creditCardRadioInput.checked||!n||n.submit(),this._creditCardRadioInput&&!0===this._creditCardRadioInput.checked){const e=this.getMandateCheckedValue();if(this.isValidSelectedMandate(e))return void this.client.post(o.options.shopUrl+"/mollie/components/store-mandate-id/"+o.options.customerId+"/"+e,()=>{n.submit()},()=>{n.submit()},"application/json; charset=utf-8");const i=document.getElementById(`${this.getInputFields().verificationCode.errors}`);i.textContent="";const{token:r,error:s}=await t.createToken();if(s)return this.enableForm(),void(i.textContent=s.message);s||this.client.post(o.options.shopUrl+"/mollie/components/store-card-token/"+r,JSON.stringify({shouldSaveCardDetail:this.shouldSaveCardDetail()}),()=>{document.getElementById("cardToken").setAttribute("value",r),n.submit()},()=>{n.submit()},"application/json; charset=utf-8")}}}class m{static isTouchDevice(){return"ontouchstart"in document.documentElement}static isIOSDevice(){return m.isIPhoneDevice()||m.isIPadDevice()}static isNativeWindowsBrowser(){return m.isIEBrowser()||m.isEdgeBrowser()}static isIPhoneDevice(){return!!navigator.userAgent.match(/iPhone/i)}static isIPadDevice(){return!!navigator.userAgent.match(/iPad/i)}static isIEBrowser(){return-1!==navigator.userAgent.toLowerCase().indexOf("msie")||!!navigator.userAgent.match(/Trident.*rv:\d+\./)}static isEdgeBrowser(){return!!navigator.userAgent.match(/Edge\/\d+/i)}static getList(){return{"is-touch":m.isTouchDevice(),"is-ios":m.isIOSDevice(),"is-native-windows":m.isNativeWindowsBrowser(),"is-iphone":m.isIPhoneDevice(),"is-ipad":m.isIPadDevice(),"is-ie":m.isIEBrowser(),"is-edge":m.isEdgeBrowser()}}}class y{constructor(e){this.csrf=e}isActive(){return void 0!==this.csrf&&!1!==this.csrf.enabled&&"ajax"===this.csrf.mode}}class f{constructor(e){this._document=e}getPaymentForm(){return this._document.querySelector("#changePaymentForm")}getConfirmForm(){return this._document.querySelector("#confirmOrderForm")}getSubmitButton(){let e=this._document.querySelector("#confirmFormSubmit");return null===e&&(e=this._document.querySelector('#confirmOrderForm > button[type="submit"]')),e}}const g="error";class v extends u{static options=i()(u.options,{paymentId:null,customerId:null,locale:null,profileId:null,shopUrl:null,testMode:!0});init(){super.init();try{const e=new f(document);this._paymentForm=e.getPaymentForm(),this._confirmForm=e.getConfirmForm(),this._confirmFormButton=e.getSubmitButton()}catch(e){return void console.error("Mollie Credit Card components: Required HTML elements not found on this page!")}this._initializeComponentInstance(),this._registerEvents(),this.registerMandateEvents()}_initializeComponentInstance(){const e=document.querySelector("#cardHolder");document.querySelector("div.mollie-components-credit-card")&&e&&!window.mollieComponentsObject&&(window.mollieComponentsObject=Mollie(this.options.profileId,{locale:this.options.locale,testmode:this.options.testMode}),window.mollieComponents={}),this.createComponentsInputs()}_registerEvents(){null!==this._confirmForm&&this._confirmForm.addEventListener("submit",this.submitForm.bind(this))}_reactivateFormSubmit(){this._confirmFormButton.disabled=!1;const e=this._confirmFormButton.querySelector(".loader");e&&e.remove()}getDefaultProperties(){return{styles:{base:{backgroundColor:"#fff",fontSize:"14px",padding:"10px 10px","::placeholder":{color:"rgba(68, 68, 68, 0.2)"}},valid:{color:"#090"},invalid:{backgroundColor:"#fff1f3"}}}}getInputFields(){return{cardHolder:{name:"cardHolder",id:"#cardHolder",errors:"cardHolderError"},cardNumber:{name:"cardNumber",id:"#cardNumber",errors:"cardNumberError"},expiryDate:{name:"expiryDate",id:"#expiryDate",errors:"expiryDateError"},verificationCode:{name:"verificationCode",id:"#verificationCode",errors:"verificationCodeError"}}}createComponentsInputs(){const e=this,t=[this.getInputFields().cardHolder,this.getInputFields().cardNumber,this.getInputFields().expiryDate,this.getInputFields().verificationCode];window.mollieComponentsObject&&t.forEach((t,n,o)=>{const i=this._mountMollieComponent(t.id,t.name);o[n][t.name]=i,i.addEventListener("change",e=>{const n=document.getElementById(`${t.name}`),o=document.getElementById(`${t.errors}`);e.error&&e.touched?(n.classList.add(g),o.textContent=e.error):(n.classList.remove(g),o.textContent="")}),i.addEventListener("focus",()=>{e.setFocus(`${t.id}`,!0)}),i.addEventListener("blur",()=>{e.setFocus(`${t.id}`,!1)})})}_mountMollieComponent(e,t){return window.mollieComponents[t]?window.mollieComponents[t].unmount():window.mollieComponents[t]=window.mollieComponentsObject.createComponent(t,this.getDefaultProperties()),window.mollieComponents[t].mount(e),window.mollieComponents[t]}setFocus(e,t){document.querySelector(e).classList.toggle("is-focused",t)}async submitForm(e){const t=this._confirmForm,n=document.querySelector(`#changePaymentForm input[type="radio"][value="${this.options.paymentId}"]`);if((null==n||!1===n.checked)&&this._confirmForm)return;if(n&&!1===n.checked)return;e.preventDefault();const o=this.getMandateCheckedValue();if(this.isValidSelectedMandate(o))return void this.continueShopwareCheckout(t);const i=document.getElementById(`${this.getInputFields().verificationCode.errors}`);i.textContent="";const{token:r,error:s}=await window.mollieComponentsObject.createToken();if(s)return i.textContent=s.message,this._reactivateFormSubmit(),void i.scrollIntoView();document.getElementById("cardToken").value=r,this.continueShopwareCheckout(t)}continueShopwareCheckout(e){if(m.isIEBrowser()){const t=function(e,t){const n=document.createElement("input");return n.type="checkbox",n.name=e,n.checked=t,n.style.display="none",n},n=document.getElementById("tos");null!=n&&e.insertAdjacentElement("beforeend",t("tos",n.checked))}new y(window.csrf).isActive()||e.submit()}}class C{constructor(e){this._document=e}findClosestShopwareBuyButton(e){const t=this.findClosestBuyBox(e);return null===t?null:t.querySelector(".btn-buy")}findClosestApplePayContainer(e){return e.closest(".mollie-apple-pay-direct")}findClosestBuyBox(e){let t=e.closest(".product-action");return null===t&&(t=e.closest(".product-detail-form-container")),null===t&&(t=e.closest(".offcanvas-cart-actions")),null===t&&(t=e.closest(".checkout-aside-container")),null===t&&(t=e.closest(".checkout-main")),t}findAllExpressButtons(e,t=null){let n=".mollie-express-button";return null!==t&&(n+=t),e.querySelectorAll(n)}findApplePayButtons(){return this._document.querySelectorAll(".mollie-express-button.js-apple-pay")}findApplePayContainers(){return this._document.querySelectorAll(".js-apple-pay-container")}findPayPalExpressButtons(){return this._document.querySelectorAll(".mollie-paypal-button")}findClosestPrivacyBox(e){const t=this.findClosestBuyBox(e);return null===t?null:t.querySelector(".mollie-privacy-note")}getPrivacyBoxCheckbox(e){return e.querySelector('input[name="acceptedDataProtection"]')}}const _="d-none",b="is-invalid";class S{constructor(e){this._repoBuyBox=new C,this._document=e}initCheckbox(){const e=this._document.querySelectorAll(".mollie-privacy-note:not(.observed)");for(let t=0;t{let t=i.length;n.classList.remove(_),e.forEach(e=>{e.target.classList.contains(_)&&t--}),t<=0&&n.classList.add(_)}).observe(t,{attributes:!0,attributeFilter:["class"]})}else n.classList.add(_)}}validateForExpressButton(e){const t=this._repoBuyBox.findClosestPrivacyBox(e);if(!(t instanceof HTMLDivElement))return!0;const n=this._repoBuyBox.getPrivacyBoxCheckbox(t),o=n.checked?1:0;return n.classList.remove(b),0!==o||(n.classList.add(b),!1)}}class E{addEventListenerOnce(e,t,n="click"){const o="__handler_"+n;e[o]||(e.addEventListener(n,t),e[o]=!0)}}class P{register(e,t){const n=window.PluginManager.getPluginList().OffCanvasCart.get("instances");if(n)for(let o=0;o{if(a.readyState===XMLHttpRequest.DONE&&(e.classList.remove(w),a.status>=400))throw new Error(`Request failed with status ${a.status}`)},a.send(i.join("&"))}}class M{APPLE_PAY_VERSION=3;constructor(){this.client=new s}create(e,t,n,o,i,r,s){const a=this;var l=["name","email","postalAddress"];1===o&&l.push("phone");let c=!1;null!==r&&(c=r.value);var d={countryCode:t,currencyCode:n,requiredShippingContactFields:l,supportedNetworks:["amex","maestro","masterCard","visa","vPay"],merchantCapabilities:["supports3DS"],total:{label:"",amount:0}};const u=new ApplePaySession(this.APPLE_PAY_VERSION,d);return u.onvalidatemerchant=function(e){a.client.post(i+"/mollie/apple-pay/validate",JSON.stringify({validationUrl:e.validationURL}),t=>{if(!1===t.success)throw new Error("Validation failed for URL: "+e.validationURL);const n=JSON.parse(t.session);u.completeMerchantValidation(n)},()=>{u.abort()})},u.onshippingcontactselected=function(e){var t="";void 0!==e.shippingContact.countryCode&&(t=e.shippingContact.countryCode),a.client.post(i+"/mollie/apple-pay/shipping-methods",JSON.stringify({countryCode:t}),e=>{e.success?u.completeShippingContactSelection(ApplePaySession.STATUS_SUCCESS,e.shippingmethods,e.cart.total,e.cart.items):u.completeShippingContactSelection(ApplePaySession.STATUS_FAILURE,[],{label:"",amount:0,pending:!0},[])},()=>{u.abort()})},u.onshippingmethodselected=function(e){a.client.post(i+"/mollie/apple-pay/set-shipping",JSON.stringify({identifier:e.shippingMethod.identifier}),e=>{e.success?u.completeShippingMethodSelection(ApplePaySession.STATUS_SUCCESS,e.cart.total,e.cart.items):u.completeShippingMethodSelection(ApplePaySession.STATUS_FAILURE,{label:"",amount:0,pending:!0},[])},()=>{u.abort()})},u.onpaymentauthorized=function(e){var t=e.payment.token;t=JSON.stringify(t),u.completePayment(ApplePaySession.STATUS_SUCCESS),a.finishPayment(i+"/mollie/apple-pay/start-payment",t,e.payment,c),s.classList.remove("processed")},u.oncancel=function(){e&&a.client.post(i+"/mollie/apple-pay/restore-cart"),s.classList.remove("processed")},u}finishPayment(e,t,n,o){const i=function(e,t){const n=document.createElement("input");return n.type="hidden",n.name=e,n.value=t,n},r=document.createElement("form");r.action=e,r.method="POST";let s=n.shippingContact.addressLines[0];n.shippingContact.addressLines.length>1&&(s+=" "+n.shippingContact.addressLines[1]),r.insertAdjacentElement("beforeend",i("email",n.shippingContact.emailAddress)),r.insertAdjacentElement("beforeend",i("lastname",n.shippingContact.familyName)),r.insertAdjacentElement("beforeend",i("firstname",n.shippingContact.givenName)),r.insertAdjacentElement("beforeend",i("street",s)),r.insertAdjacentElement("beforeend",i("postalCode",n.shippingContact.postalCode)),r.insertAdjacentElement("beforeend",i("city",n.shippingContact.locality)),r.insertAdjacentElement("beforeend",i("acceptedDataProtection",o)),void 0!==n.shippingContact.phoneNumber&&n.shippingContact.phoneNumber.length>0&&r.insertAdjacentElement("beforeend",i("phone",n.shippingContact.phoneNumber)),r.insertAdjacentElement("beforeend",i("countryCode",n.shippingContact.countryCode)),r.insertAdjacentElement("beforeend",i("paymentToken",t)),document.body.insertAdjacentElement("beforeend",r),r.submit()}}class A{constructor(){this._repoBuyBox=new C}isCheckoutPossible(e){const t=this._repoBuyBox.findClosestShopwareBuyButton(e);return!(t instanceof HTMLButtonElement&&t.hasAttribute("disabled"))}}class I{constructor(e,t){this._countryCode=e.querySelector('input[name="countryCode"]').value,this._currency=e.querySelector('input[name="currency"]').value,this._mode=e.querySelector('input[name="mode"]').value,this._withPhone=parseInt(e.querySelector('input[name="withPhone"]').value),this._dataProtection=e.querySelector('input[name="acceptedDataProtection"]'),this._isProductMode="productMode"===this._mode;let n=t.getAttribute("data-shop-url");"/"===n.slice(-1)&&(n=n.slice(0,-1)),this._shopSlug=n}isProductMode(){return this._isProductMode}getCountryCode(){return this._countryCode}getCurrency(){return this._currency}getMode(){return this._mode}getWithPhone(){return this._withPhone}getDataProtection(){return this._dataProtection}getShopSlug(){return this._shopSlug}}const x="d-none";class L extends c{init(){this._privacySection=new S(document),this._eventUtils=new E,this._cartService=new B,this._productBoxValidator=new A,this._repoBuyBox=new C(document),(new P).register(this.initCurrentPage.bind(this),"mollie-apple-pay-direct"),this.initCurrentPage()}initCurrentPage(){if(this._applePayButtons=this._repoBuyBox.findApplePayButtons(),this._applePayContainers=this._repoBuyBox.findApplePayContainers(),!window.ApplePaySession||!window.ApplePaySession.canMakePayments()||this._applePayButtons.length<=0)this.hideApplePayFeature();else if(this._privacySection.initCheckbox(),this.showApplePayFeature(),this._applePayButtons)for(let e=0;e{this.updateButtonVisibility(t)})}}updateButtonVisibility(e){this._productBoxValidator.isCheckoutPossible(e)?(e.hidden=!1,e.classList.remove(x)):(e.hidden=!0,e.classList.add(x))}showApplePayFeature(){if(this._applePayContainers)for(let e=0;e=0&&t.item(n)!==this;);return n>-1});e&&e!==document;e=e.parentNode)if(e.matches(t))return e;return null}}const O="d-none";class k extends c{static options={shopUrl:null,customerId:null,mollieMandateContainerClass:".mollie-credit-card-mandate",mollieMandateDataId:"data-mollie-credit-card-mandate-id",mollieMandateRemoveButtonClass:".mollie-credit-card-mandate-remove",mollieMandateRemoveModalButtonClass:".mollie-credit-card-mandate-remove-modal-button",mollieMandateDeleteAlertSuccessId:"#mollieCreditCardMandateDeleteSuccess",mollieMandateDeleteAlertErrorId:"#mollieCreditCardMandateDeleteError"};init(){if(!this.options.shopUrl)throw new Error(`The "shopUrl" option for the plugin "${this._pluginName}" is not defined.`);if(!this.options.customerId)throw new Error(`The "customerId" option for the plugin "${this._pluginName}" is not defined.`);this.mollieMandateDeleteAlertEl=document.querySelector(this.options.mollieMandateDeleteAlertSuccessId),this.mollieMandateDeleteAlertEl&&(this.mollieMandateDeleteAlertErrorEl=document.querySelector(this.options.mollieMandateDeleteAlertErrorId),this.mollieMandateDeleteAlertErrorEl&&(this.client=new s,this.registerEvents()))}registerEvents(){const e=document.querySelectorAll(this.options.mollieMandateRemoveButtonClass);if(!e||0===e.length)return;const t=document.querySelectorAll(this.options.mollieMandateRemoveModalButtonClass);t&&0!==t.length&&(e.forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),this.onRemoveButtonClick(e)})}),t.forEach(e=>{e.addEventListener("click",e=>{e.preventDefault(),this.onConfirmRemoveButtonClick()})}))}onRemoveButtonClick(e){this.currentContainerEl=e.closest(this.options.mollieMandateContainerClass),this.currentContainerEl&&(this.currentMandateId=this.currentContainerEl.getAttribute(this.options.mollieMandateDataId))}onConfirmRemoveButtonClick(){const{currentContainerEl:e,currentMandateId:t}=this;e&&t&&this.deleteMandate(t).then(({success:t})=>{t?(this.mollieMandateDeleteAlertErrorEl.classList.add(O),this.mollieMandateDeleteAlertEl.classList.remove(O),e.remove()):(this.mollieMandateDeleteAlertEl.classList.add(O),this.mollieMandateDeleteAlertErrorEl.classList.remove(O))})}deleteMandate(e){return new Promise(t=>{this.client.post(this.options.shopUrl+"/mollie/components/revoke-mandate/"+e,"",e=>{t({success:e&&e.success})},()=>{t({success:!1})},"application/json; charset=utf-8")})}}const D="d-none";class q extends c{_shopUrl="";_customerId="";_dropdownTerminals=null;_container=null;_paymentForm=null;_radioInputs=null;_posRadioInput=null;init(){this._container=document.querySelector("div.mollie-pos-terminals"),void 0!==this._container&&null!==this._container&&(this.initControls(),null!==this._paymentForm&&null!==this._dropdownTerminals&&(this.registerEvents(),this.updateDropdownVisibility(this._posRadioInput,this._container,this._dropdownTerminals),this.updateTerminal(this._shopUrl,this._customerId,this._posRadioInput,this._dropdownTerminals,function(){})))}initControls(){this._shopUrl=this._container.getAttribute("data-shop-url"),"/"===this._shopUrl.substr(-1)&&(this._shopUrl=this._shopUrl.substr(0,this._shopUrl.length-1)),this._customerId=this._container.getAttribute("data-customer-id"),this._dropdownTerminals=document.querySelector("#posTerminals"),this._paymentForm=document.querySelector("#changePaymentForm"),void 0!==this._paymentForm&&null!==this._paymentForm&&(this._radioInputs=this._paymentForm.querySelectorAll('input[type="radio"]'),this._posRadioInput=this._paymentForm.querySelector('input[type="radio"].pointofsale'))}registerEvents(){if(null===this._paymentForm)return;const e=this._shopUrl,t=this._customerId,n=this._container,o=this._radioInputs,i=this._posRadioInput,r=this._dropdownTerminals;o.forEach(e=>{e.addEventListener("change",()=>{this.updateDropdownVisibility(i,n,r)})}),r.addEventListener("change",async()=>{this.updateTerminal(e,t,i,r,function(){})})}updateDropdownVisibility(e,t,n){let o=!1;void 0===e||!1===e.checked?t.classList.add(D):(t.classList.remove(D),o=!0),void 0!==n&&(n.required=o)}updateTerminal(e,t,n,o,i){void 0!==n?null!==n?!1!==n.checked?void 0!==o?null!==o?""!==o.value?(new s).post(e+"/mollie/pos/store-terminal/"+o.value,"",function(){i("terminal updated successfully")},function(){i("error when updating terminal")},"application/json; charset=utf-8"):i("no POS terminal selected"):i("POS terminals not found"):i("POS terminals not defined"):i("POS payment not active"):i("POS Radio Input not found"):i("POS Radio Input not defined")}}const j="d-none";class T extends c{init(){this._privacySection=new S(document),this._eventUtils=new E,this._cartService=new B,this._productBoxValidator=new A,this._repoBuyBox=new C(document),(new P).register(this.bindEvents.bind(this),"mollie-paypal-express"),this.bindEvents()}bindEvents(){const e=this._repoBuyBox.findPayPalExpressButtons();if(0!==e.length){this._privacySection.initCheckbox();for(let t=0;t{this.updateButtonVisibility(n)})}}}updateButtonVisibility(e){this._productBoxValidator.isCheckoutPossible(e)?(e.hidden=!1,e.classList.remove(j)):(e.hidden=!0,e.classList.add(j))}onExpressCheckout(e){const t=e.currentTarget;if(!this._productBoxValidator.isCheckoutPossible(t))return;if(!this._privacySection.validateForExpressButton(t))return;this._cartService.addItemToCart(t);const n=t.getAttribute("data-form-action"),o=document.createElement("form");o.setAttribute("action",n),o.setAttribute("method","POST"),document.body.insertAdjacentElement("beforeend",o),o.submit()}}const U="d-none",N="invalid";class R extends c{init(){const e=document.getElementById("molliePayPhone");if(null===e)return;const t=document.querySelector(".mollie-phone-field"),n=document.querySelector('.mollie-phone-field [data-form-validation-invalid-phone="true"]');e.addEventListener("focus",e=>{t.classList.add("was-validated"),e.target.removeAttribute(N),n.classList.add(U)}),e.addEventListener("blur",e=>{const t=e.target.form;return!1===t.reportValidity()&&(e.target.setAttribute(N,!0),n.classList.remove(U)),t.reportValidity()})}}class V{register(){const e=window.PluginManager;e.register("MollieApplePayDirect",L),e.register("PayPalExpressPlugin",T),e.register("MollieApplePayPaymentMethod",F,"[data-mollie-template-applepay-account]"),e.register("MollieApplePayPaymentMethod",F,"[data-mollie-template-applepay-checkout]"),e.register("MollieCreditCardComponents",h,"[data-mollie-template-creditcard-components]"),e.register("MollieCreditCardComponentsSw64",v,"[data-mollie-template-creditcard-components-sw64]"),e.register("MollieCreditCardMandateManage",k,"[data-mollie-credit-card-mandate-manage]"),e.register("MolliePosTerminal",q,"[data-mollie-template-pos-terminal]"),e.register("MolliePhonePlugin",R,"[data-mollie-phone-validation]")}}window.addEventListener("load",function(){void 0!==window.mollie_javascript_use_shopware&&"1"!==window.mollie_javascript_use_shopware&&((new V).register(),window.dispatchEvent(new Event("mollieLoaded")),window.PluginManager.initializePlugins())})})(); \ No newline at end of file diff --git a/src/Resources/snippet/bg_BG/SnippetFile_bg_BG.php b/src/Resources/snippet/bg_BG/SnippetFile_bg_BG.php index 720e26812..d3af58ea5 100644 --- a/src/Resources/snippet/bg_BG/SnippetFile_bg_BG.php +++ b/src/Resources/snippet/bg_BG/SnippetFile_bg_BG.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\bg_BG; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_bg_BG implements SnippetFileInterface +class SnippetFile_bg_BG extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/bg_BG/mollie-payments.bg-BG.json b/src/Resources/snippet/bg_BG/mollie-payments.bg-BG.json index 67435a245..84d8e3dfb 100644 --- a/src/Resources/snippet/bg_BG/mollie-payments.bg-BG.json +++ b/src/Resources/snippet/bg_BG/mollie-payments.bg-BG.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "редактиране на адрес за фактуриране", "btnEditShippingAddress": "редактиране на адрес за доставка", - "cancelSubscription": "Абонаментът е прекратен", - "errorCancelSubscription": "Абонаментът не може да бъде прекратен поради грешка. Моля, свържете се с нашата клиентска поддръжка.", + "successCancel": "Абонаментът е прекратен", + "errorCancel": "Абонаментът не може да бъде прекратен поради грешка. Моля, свържете се с нашата клиентска поддръжка.", "errorPause": "Възникна грешка при паузиране на вашия абонамент", "errorResume": "Възникна грешка при възобновяване на вашия абонамент", "errorSkip": "Възникна грешка при пропускане на вашия абонамент", diff --git a/src/Resources/snippet/cs_CZ/SnippetFile_cs_CZ.php b/src/Resources/snippet/cs_CZ/SnippetFile_cs_CZ.php index fb0abc991..4bb7deee4 100644 --- a/src/Resources/snippet/cs_CZ/SnippetFile_cs_CZ.php +++ b/src/Resources/snippet/cs_CZ/SnippetFile_cs_CZ.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\cs_CZ; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_cs_CZ implements SnippetFileInterface +class SnippetFile_cs_CZ extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/cs_CZ/mollie-payments.cs-CZ.json b/src/Resources/snippet/cs_CZ/mollie-payments.cs-CZ.json index 6cf4bf2d0..ef32a5a50 100644 --- a/src/Resources/snippet/cs_CZ/mollie-payments.cs-CZ.json +++ b/src/Resources/snippet/cs_CZ/mollie-payments.cs-CZ.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "upravit fakturační adresu", "btnEditShippingAddress": "upravit doručovací adresu", - "cancelSubscription": "Předplatné bylo zrušeno", - "errorCancelSubscription": "Předplatné se nepodařilo zrušit kvůli chybě. Prosim, kontaktujte naši podporu.", + "successCancel": "Předplatné bylo zrušeno", + "errorCancel": "Předplatné se nepodařilo zrušit kvůli chybě. Prosim, kontaktujte naši podporu.", "errorPause": "Došlo k chybě při pozastavení vašeho předplatného", "errorResume": "Došlo k chybě při obnovování vašeho předplatného", "errorSkip": "Došlo k chybě při přeskočení vašeho předplatného", diff --git a/src/Resources/snippet/da_DK/SnippetFile_da_DK.php b/src/Resources/snippet/da_DK/SnippetFile_da_DK.php index ac0160e4a..2e9ae57e7 100644 --- a/src/Resources/snippet/da_DK/SnippetFile_da_DK.php +++ b/src/Resources/snippet/da_DK/SnippetFile_da_DK.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\da_DK; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_da_DK implements SnippetFileInterface + +class SnippetFile_da_DK extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/da_DK/mollie-payments.da-DK.json b/src/Resources/snippet/da_DK/mollie-payments.da-DK.json index b574cff10..bdee5a819 100644 --- a/src/Resources/snippet/da_DK/mollie-payments.da-DK.json +++ b/src/Resources/snippet/da_DK/mollie-payments.da-DK.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "rediger faktureringsadresse", "btnEditShippingAddress": "rediger leveringsadresse", - "cancelSubscription": "Abonnementet er blevet annulleret", - "errorCancelSubscription": "Abonnementsaftalen kunne ikke annulleres på grund af en fejl. Kontakt venligst vores support.", + "successCancel": "Abonnementet er blevet annulleret", + "errorCancel": "Abonnementsaftalen kunne ikke annulleres på grund af en fejl. Kontakt venligst vores support.", "errorPause": "Der opstod en fejl, da dit abonnement blev sat på pause.", "errorResume": "Der opstod en fejl, da dit abonnement blev genoptaget.", "errorSkip": "Der opstod en fejl, da dit abonnement blev sprunget over.", diff --git a/src/Resources/snippet/de_DE/SnippetFile_de_DE.php b/src/Resources/snippet/de_DE/SnippetFile_de_DE.php index 32d366fe3..b483f4f2d 100644 --- a/src/Resources/snippet/de_DE/SnippetFile_de_DE.php +++ b/src/Resources/snippet/de_DE/SnippetFile_de_DE.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\de_DE; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_de_DE implements SnippetFileInterface +class SnippetFile_de_DE extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/de_DE/mollie-payments.de-DE.json b/src/Resources/snippet/de_DE/mollie-payments.de-DE.json index efacdbd13..c446d4403 100644 --- a/src/Resources/snippet/de_DE/mollie-payments.de-DE.json +++ b/src/Resources/snippet/de_DE/mollie-payments.de-DE.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "Rechnungsadresse bearbeiten", "btnEditShippingAddress": "Lieferadresse bearbeiten", - "cancelSubscription": "Das Abonnement wurde gekündigt", - "errorCancelSubscription": "Das Abonnement konnte aufgrund eines Fehlers nicht gekündigt werden. Bitte wenden Sie sich an unseren Support.", + "successCancel": "Das Abonnement wurde gekündigt", + "errorCancel": "Das Abonnement konnte aufgrund eines Fehlers nicht gekündigt werden. Bitte wenden Sie sich an unseren Support.", "errorPause": "Dein Abonnement konnte nicht pausiert werden", "errorResume": "Dein Abonnement konnte nicht fortgesetzt werden", "errorSkip": "Dein Abonnement konnte nicht ausgesetzt werden", diff --git a/src/Resources/snippet/el_GR/SnippetFile_el_GR.php b/src/Resources/snippet/el_GR/SnippetFile_el_GR.php index f91122947..d347ffc4f 100644 --- a/src/Resources/snippet/el_GR/SnippetFile_el_GR.php +++ b/src/Resources/snippet/el_GR/SnippetFile_el_GR.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\el_GR; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_el_GR implements SnippetFileInterface +class SnippetFile_el_GR extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/el_GR/mollie-payments.el-GR.json b/src/Resources/snippet/el_GR/mollie-payments.el-GR.json index a10bfb9f6..b02f1d573 100644 --- a/src/Resources/snippet/el_GR/mollie-payments.el-GR.json +++ b/src/Resources/snippet/el_GR/mollie-payments.el-GR.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "Επεξεργασία διεύθυνσης χρέωσης", "btnEditShippingAddress": "Επεξεργασία διεύθυνσης αποστολής", - "cancelSubscription": "Η συνδρομή έχει ακυρωθεί", - "errorCancelSubscription": "Η συνδρομή δεν μπόρεσε να ακυρωθεί λόγω σφάλματος. Παρακαλώ επικοινωνήστε με την υποστήριξή μας.", + "successCancel": "Η συνδρομή έχει ακυρωθεί", + "errorCancel": "Η συνδρομή δεν μπόρεσε να ακυρωθεί λόγω σφάλματος. Παρακαλώ επικοινωνήστε με την υποστήριξή μας.", "errorPause": "Προέκυψε σφάλμα κατά τη διακοπή της συνδρομής σας", "errorResume": "Προέκυψε σφάλμα κατά την επαναφορά της συνδρομής σας", "errorSkip": "Προέκυψε σφάλμα κατά την παράλειψη της συνδρομής σας", diff --git a/src/Resources/snippet/en_GB/SnippetFile_en_GB.php b/src/Resources/snippet/en_GB/SnippetFile_en_GB.php index 8442af31b..46c4c0b9e 100644 --- a/src/Resources/snippet/en_GB/SnippetFile_en_GB.php +++ b/src/Resources/snippet/en_GB/SnippetFile_en_GB.php @@ -3,9 +3,9 @@ namespace Kiener\MolliePayments\Resources\snippet\en_GB; use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; -class SnippetFile_en_GB extends AbstractSnippetFile implements SnippetFileInterface + +class SnippetFile_en_GB extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/en_GB/mollie-payments.en-GB.json b/src/Resources/snippet/en_GB/mollie-payments.en-GB.json index 68dc85ac7..f2b83e116 100644 --- a/src/Resources/snippet/en_GB/mollie-payments.en-GB.json +++ b/src/Resources/snippet/en_GB/mollie-payments.en-GB.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "edit billing address", "btnEditShippingAddress": "edit shipping address", - "cancelSubscription": "Subscription has been canceled", - "errorCancelSubscription": "The subscription could not be canceled due to an error. Please contact our support.", + "successCancel": "Subscription has been canceled", + "errorCancel": "The subscription could not be canceled due to an error. Please contact our support.", "errorPause": "There was an error when pausing your subscription", "errorResume": "There was an error when resuming your subscription", "errorSkip": "There was an error when skipping your subscription", diff --git a/src/Resources/snippet/es_ES/SnippetFile_es_ES.php b/src/Resources/snippet/es_ES/SnippetFile_es_ES.php index 8f09654ce..99dbe87f8 100644 --- a/src/Resources/snippet/es_ES/SnippetFile_es_ES.php +++ b/src/Resources/snippet/es_ES/SnippetFile_es_ES.php @@ -2,9 +2,10 @@ namespace Kiener\MolliePayments\Resources\snippet\es_ES; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_es_ES implements SnippetFileInterface + +class SnippetFile_es_ES extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/es_ES/mollie-payments.es-ES.json b/src/Resources/snippet/es_ES/mollie-payments.es-ES.json index 58987c5cd..d3e40f64c 100644 --- a/src/Resources/snippet/es_ES/mollie-payments.es-ES.json +++ b/src/Resources/snippet/es_ES/mollie-payments.es-ES.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "editar la dirección de facturación", "btnEditShippingAddress": "editar la dirección de envío", - "cancelSubscription": "La suscripción ha sido cancelada", - "errorCancelSubscription": "No ha sido posible cancelar la suscripción debido a un error. Por favor, contacta con nuestro soporte.", + "successCancel": "La suscripción ha sido cancelada", + "errorCancel": "No ha sido posible cancelar la suscripción debido a un error. Por favor, contacta con nuestro soporte.", "errorPause": "Se ha producido un error al pausar tu suscripción", "errorResume": "Se ha producido un error al reanudar tu suscripción", "errorSkip": "Se ha producido un error al posponer tu suscripción", diff --git a/src/Resources/snippet/et_EE/SnippetFile_et_EE.php b/src/Resources/snippet/et_EE/SnippetFile_et_EE.php index b12714bcc..cef1bc394 100644 --- a/src/Resources/snippet/et_EE/SnippetFile_et_EE.php +++ b/src/Resources/snippet/et_EE/SnippetFile_et_EE.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\et_EE; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_et_EE implements SnippetFileInterface +class SnippetFile_et_EE extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/et_EE/mollie-payments.et-EE.json b/src/Resources/snippet/et_EE/mollie-payments.et-EE.json index 0aee17bcd..ea7472fc1 100644 --- a/src/Resources/snippet/et_EE/mollie-payments.et-EE.json +++ b/src/Resources/snippet/et_EE/mollie-payments.et-EE.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "muuda arvete aadressi", "btnEditShippingAddress": "muuda kohaletoimetamise aadressi", - "cancelSubscription": "Tellimus on tühistatud", - "errorCancelSubscription": "Tellimust ei saa tühistada, kuna ilmnes viga. Palun võta meiega ühendust.", + "successCancel": "Tellimus on tühistatud", + "errorCancel": "Tellimust ei saa tühistada, kuna ilmnes viga. Palun võta meiega ühendust.", "errorPause": "Tellimuse peatamisel tekkis viga", "errorResume": "Tellimuse jätkamisel tekkis viga", "errorSkip": "Tellimuse vahelejätmisel tekkis viga", diff --git a/src/Resources/snippet/fi_FI/SnippetFile_fi_FI.php b/src/Resources/snippet/fi_FI/SnippetFile_fi_FI.php index 5645817f1..bb2ca23df 100644 --- a/src/Resources/snippet/fi_FI/SnippetFile_fi_FI.php +++ b/src/Resources/snippet/fi_FI/SnippetFile_fi_FI.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\fi_FI; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_fi_FI implements SnippetFileInterface + +class SnippetFile_fi_FI extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/fi_FI/mollie-payments.fi-FI.json b/src/Resources/snippet/fi_FI/mollie-payments.fi-FI.json index 28d39f63c..d4e925f73 100644 --- a/src/Resources/snippet/fi_FI/mollie-payments.fi-FI.json +++ b/src/Resources/snippet/fi_FI/mollie-payments.fi-FI.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "muokkaa laskutusosoitetta", "btnEditShippingAddress": "muokkaa toimitusosoitetta", - "cancelSubscription": "Tilaus on peruutettu", - "errorCancelSubscription": "Tilauksen peruuttaminen epäonnistui virheen vuoksi. Ota yhteyttä tukeemme.", + "successCancel": "Tilaus on peruutettu", + "errorCancel": "Tilauksen peruuttaminen epäonnistui virheen vuoksi. Ota yhteyttä tukeemme.", "errorPause": "Tilauksen keskeyttämisessä ilmeni virhe", "errorResume": "Tilauksen jatkamisessa ilmeni virhe", "errorSkip": "Tilauksen ohittamisessa ilmeni virhe", diff --git a/src/Resources/snippet/hr_HR/SnippetFile_hr_HR.php b/src/Resources/snippet/hr_HR/SnippetFile_hr_HR.php index 61c7151dd..c073aa58f 100644 --- a/src/Resources/snippet/hr_HR/SnippetFile_hr_HR.php +++ b/src/Resources/snippet/hr_HR/SnippetFile_hr_HR.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\hr_HR; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_hr_HR implements SnippetFileInterface +class SnippetFile_hr_HR extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/hr_HR/mollie-payments.hr-HR.json b/src/Resources/snippet/hr_HR/mollie-payments.hr-HR.json index b164bbc1d..ff5ad50ea 100644 --- a/src/Resources/snippet/hr_HR/mollie-payments.hr-HR.json +++ b/src/Resources/snippet/hr_HR/mollie-payments.hr-HR.json @@ -1,15 +1,15 @@ { "checkout": { "mollie-payments-cart-error-method-invalid": "Trenutno odabrana metoda plaćanja nije dostupna za pretplatničke proizvode.", - "mollie-payments-cart-error-mixedcart": "Vaša košarica sadrži više artikala u kombinaciji s pretplatničkim artiklima. Imajte na umu da možete kupiti samo 1 pretplatnički artikl odjednom.", - "mollie-payments-cart-error-paymentmethod-availability": "Nisu sve metode plaćanja dostupne prilikom naručivanja pretplatničkih proizvoda.", - "mollie-payments-cart-guest-account": "Gostujući računi ne mogu se koristiti za pretplatničke narudžbe." + "mollie-payments-cart-error-mixedcart": "Tvoj košarica sadrži više artikala u kombinaciji s pretplatničkim proizvodima. Napomena: moguće je kupiti samo jedan pretplatnički proizvod odjednom.", + "mollie-payments-cart-error-paymentmethod-availability": "Nisu sve metode plaćanja dostupne prilikom prilikom narudžbe pretplatničkih proizvoda.", + "mollie-payments-cart-guest-account": "Gostujući računi ne mogu se koristiti za narudžbe s pretplatom." }, "error": { - "mollie-payments-cart-error-method-invalid": "Trenutno odabrana metoda plaćanja nije dostupna za pretplatničke proizvode.", - "mollie-payments-cart-error-mixedcart": "Vaša košarica sadrži više artikala u kombinaciji s pretplatničkim artiklima. Imajte na umu da možete kupiti samo 1 pretplatnički artikl odjednom.", - "mollie-payments-cart-error-paymentmethod-availability": "Nisu sve metode plaćanja dostupne prilikom naručivanja pretplatničkih proizvoda.", - "mollie-payments-cart-guest-account": "Gostujući računi ne mogu se koristiti za pretplatničke narudžbe." + "mollie-payments-cart-error-method-invalid": "Trenutno odabrana metoda plaćanja nije dostupna za proizvode s pretplatom.", + "mollie-payments-cart-error-mixedcart": "Tvoja košarica sadrži više artikala u kombinaciji s preplatničkim proizvodima. Napomena: moguće je kupiti samo jedan preplatnički proizvod odjednom. ", + "mollie-payments-cart-error-paymentmethod-availability": "Sve metode plaćanja nisu dostupne prilikom naručivanja proizvoda s pretplatom.", + "mollie-payments-cart-guest-account": "Gosteći računi ne mogu se koristiti za narudžbe s pretplatom." }, "molliePayments": { "components": { @@ -18,9 +18,9 @@ "cardHolderLabel": "Ime na kartici", "cardNumberLabel": "Broj kartice", "cardVerificationCodeLabel": "CVC/CVV", - "creditCardTagLine": "Plaćanje osigurano i omogućeno od strane", + "creditCardTagLine": "Plaćanje osigurano i omogućeno putem", "headLine": "Unesite podatke s kartice", - "saveCardDetailLabel": "Spremi detalje kartice za buduće plaćanje" + "saveCardDetailLabel": "Spremi podatke kartice za buduća plaćanja" }, "ideal": { "selectBank": "Odaberi banku" @@ -32,95 +32,95 @@ "sectionTitle": "Spremljene kartice", "cardTitleLabel": "%name% •••• %number%", "deleteSuccessMessage": "Vaša kartica je uspješno izbrisana", - "deleteErrorMessage": "Došlo je do problema prilikom uklanjanja vaše kartice", + "deleteErrorMessage": "Došlo je do problema pri uklanjanju vaše kartice", "newCard": "Nova kartica", "remove": "Ukloni", "subscriptionBadge": "Pretplata" }, "mandateRemoveModal": { "cancelButton": "Otkaži", - "cardSubscription": "Ova se kartica koristi za pretplatu. Prije uklanjanja ove kartice prvo otkažite pretplatu.", + "cardSubscription": "Ova kartica se koristi za pretplatu. Molimo prvo otkaži pretplatu prije nego što uklonite ovu karticu.", "deleteButton": "Izbriši", "deleteConfirmation": "Jeste li sigurni da želite izbrisati?", "title": "Potvrda brisanja" }, "phoneField": { "headLine": "Broj telefona", - "phoneErrorMessage": "Broj telefona je obavezan. Na primjer +38512345678" + "phoneErrorMessage": "Broj telefona je obavezan. Na primjer +31208202070" } }, "messages": { "payment": { - "buttonPayThroughMollie": "Platite s drugom metodom plaćanja", + "buttonPayThroughMollie": "Platite drugom metodom plaćanja", "buttonReturnToShop": "Povratak u trgovinu", "error": "Plaćanje nije uspjelo", - "failed": "Plaćanje nije uspjelo ili je otkazano. Bit ćete preusmjereni na Mollie, gdje možete završiti plaćanje odabranom metodom. " + "failed": "Plaćanje nije uspjelo ili je otkazano. Biti ćete preusmjereni na Mollie, gdje možete dovršiti plaćanje metodom po izboru." }, - "redirecting": "Preusmjeravam vas na: " + "redirecting": "Preusmjeravamo vas na: " }, "payments": { "applePayDirect": { "captionSubtotal": "Međuzbroj", "captionTaxes": "Porezi", - "paymentError": "Plaćanje s Apple Pay nije uspjelo." + "paymentError": "Plaćanje putem Apple Pay-a nije uspjelo." }, "paypalExpress": { - "paymentError": "Plaćanje s Paypal Express nije uspjelo." + "paymentError": "Plaćanje putem PayPal Express-a nije uspjelo." } }, "subscriptions": { "account": { "btnEditBillingAddress": "uredi adresu za naplatu", "btnEditShippingAddress": "uredi adresu za dostavu", - "cancelSubscription": "Pretplata je otkazana", - "errorCancelSubscription": "Pretplatu nije moguće otkazati zbog pogreške. Molimo kontaktirajte našu podršku.", - "errorPause": "Došlo je do greške prilikom pauziranja vaše pretplate", - "errorResume": "Došlo je do greške prilikom nastavka vaše pretplate", - "errorSkip": "Došlo je do pogreške pri preskakanju vaše pretplate", - "errorUpdateAddress": "Došlo je do greške prilikom ažuriranja vaše adrese", - "errorUpdatePayment": "Došlo je do greške prilikom ažuriranja vaše metode plaćanja", + "successCancel": "Pretplata je otkazana", + "errorCancel": "Pretplatu nije bilo moguće otkazati zbog pogreške. Molimo kontaktirajte našu podršku.", + "errorPause": "Došlo je do greške prilikom pauziranja pretplate", + "errorResume": "Došlo je do greške prilikom nastavka pretplate", + "errorSkip": "Došlo je do greške prilikom preskakanja pretplate", + "errorUpdateAddress": "Došlo je do greške prilikom ažuriranja adrese", + "errorUpdatePayment": "Došlo je do greške prilikom ažuriranja metode plaćanja", "headlineBillingAddress": "Adresa za naplatu", "headlineShippingAddress": "Adresa za dostavu", "mollieSubscriptionAmount": "Iznos", "mollieSubscriptionCancel": "Otkaži pretplatu", "mollieSubscriptionCancelUntil": "Otkazivanje moguće do", - "mollieSubscriptionContextMenuReorder": "Ponovite pretplatu", - "mollieSubscriptionId": "Id", - "mollieSubscriptionNextPayment": "Sljedeće plaćanje na", + "mollieSubscriptionContextMenuReorder": "Ponovi pretplatu", + "mollieSubscriptionId": "ID", + "mollieSubscriptionNextPayment": "Sljedeće plaćanje", "mollieSubscriptionPause": "Pauziraj pretplatu", "mollieSubscriptionResume": "Nastavi pretplatu", "mollieSubscriptionSkip": "Preskoči pretplatu", "mollieSubscriptionUpdatePayment": "Ažuriraj plaćanje", "mollieSubscriptionsHeadline": "Pretplata:", - "mollieSubscriptionsInfoEmpty": "Još nemate pretplata.", + "mollieSubscriptionsInfoEmpty": "Još nemate aktivnih pretplata.", "mollieSubscriptionsLink": "Pretplate", "mollieSubscriptionsTitle": "Pretplate", "mollieSubscriptionsWelcome": "Vaše nedavne pretplate:", "orderActionHide": "Sakrij", - "orderActionView": "Pregledaj", - "shippingEqualToBilling": "Jednaka adresi za naplatu", - "successPause": "Vaša pretplata je pauzirana", - "successResume": "Vaša pretplata će sada biti nastavljena", - "successSkip": "Vaša pretplata je preskočena", - "successUpdateAddress": "Vaša adresa je uspješno ažurirana", - "successUpdatePayment": "Vaša metoda plaćanja je uspješno ažurirana" + "orderActionView": "Prikaži", + "shippingEqualToBilling": "Isto kao adresa za naplatu", + "successPause": "Vaša je pretplata pauzirana", + "successResume": "Vaša će se pretplata sada nastaviti", + "successSkip": "Vaša je pretplata preskočena", + "successUpdateAddress": "Adresa je uspješno ažurirana", + "successUpdatePayment": "Metoda plaćanja je uspješno ažurirana" }, "options": { - "everyDay": "Svaki dan", - "everyDays": "Svaki %value% dana", - "everyMonth": "Svakog mjeseca", + "everyDay": "Svakog dana", + "everyDays": "Svakih %value% dana", + "everyMonth": "Svaki mjesec", "everyMonths": "Svakih %value% mjeseci", - "everyWeek": "Svake sedmice", - "everyWeeks": "Svake %value% sedmice", + "everyWeek": "Svaki tjedan", + "everyWeeks": "Svakih %value% tjedana", "repetitionCount": "%value% puta" }, "product": { - "addToCartText": "Pretplatite se", + "addToCartText": "Pretplati se", "information": "Pretplatnički proizvod" } }, "testMode": { - "label": "Testni režim" + "label": "Testni način rada" } } } \ No newline at end of file diff --git a/src/Resources/snippet/hu_HU/SnippetFile_hu_HU.php b/src/Resources/snippet/hu_HU/SnippetFile_hu_HU.php index 85129fe1a..a99d24496 100644 --- a/src/Resources/snippet/hu_HU/SnippetFile_hu_HU.php +++ b/src/Resources/snippet/hu_HU/SnippetFile_hu_HU.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\hu_HU; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_hu_HU implements SnippetFileInterface +class SnippetFile_hu_HU extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/hu_HU/mollie-payments.hu-HU.json b/src/Resources/snippet/hu_HU/mollie-payments.hu-HU.json index f3527e08c..3a6b3d039 100644 --- a/src/Resources/snippet/hu_HU/mollie-payments.hu-HU.json +++ b/src/Resources/snippet/hu_HU/mollie-payments.hu-HU.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "címzett cím módosítása", "btnEditShippingAddress": "szállítási cím módosítása", - "cancelSubscription": "Az előfizetés törölve lett", - "errorCancelSubscription": "Hiba miatt nem lehetett lemondani az előfizetést. Kérjük, lépjen kapcsolatba ügyfélszolgálatunkkal.", + "successCancel": "Az előfizetés törölve lett", + "errorCancel": "Hiba miatt nem lehetett lemondani az előfizetést. Kérjük, lépjen kapcsolatba ügyfélszolgálatunkkal.", "errorPause": "Hiba történt az előfizetés szüneteltetésekor", "errorResume": "Hiba történt az előfizetés folytatásakor", "errorSkip": "Hiba történt az előfizetés kihagyásakor", diff --git a/src/Resources/snippet/is_IS/SnippetFile_is_IS.php b/src/Resources/snippet/is_IS/SnippetFile_is_IS.php index 4017b4578..9704db4d8 100644 --- a/src/Resources/snippet/is_IS/SnippetFile_is_IS.php +++ b/src/Resources/snippet/is_IS/SnippetFile_is_IS.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\is_IS; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_is_IS implements SnippetFileInterface + +class SnippetFile_is_IS extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/is_IS/mollie-payments.is-IS.json b/src/Resources/snippet/is_IS/mollie-payments.is-IS.json index 3dbdf2a30..a152d1223 100644 --- a/src/Resources/snippet/is_IS/mollie-payments.is-IS.json +++ b/src/Resources/snippet/is_IS/mollie-payments.is-IS.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "breyta reikningsfangi", "btnEditShippingAddress": "breyta heimilsfangi sendingar", - "cancelSubscription": "Hætt var við áskrift", - "errorCancelSubscription": "Ekki var hægt að hætta við áskrift vegna villu. Vinsamlegast hafðu samband við stuðningsíðuna okkar.", + "successCancel": "Hætt var við áskrift", + "errorCancel": "Ekki var hægt að hætta við áskrift vegna villu. Vinsamlegast hafðu samband við stuðningsíðuna okkar.", "errorPause": "Vandamál kom upp þegar áskriftin var stöðvuð", "errorResume": "Vandamál kom upp þegar áskriftin var hafin á ný", "errorSkip": "Vandamál kom upp þegar áskriftinni var sleppt", diff --git a/src/Resources/snippet/it_IT/SnippetFile_it_IT.php b/src/Resources/snippet/it_IT/SnippetFile_it_IT.php index 3fe260e05..10d595ceb 100644 --- a/src/Resources/snippet/it_IT/SnippetFile_it_IT.php +++ b/src/Resources/snippet/it_IT/SnippetFile_it_IT.php @@ -2,9 +2,9 @@ namespace Kiener\MolliePayments\Resources\snippet\it_IT; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_it_IT implements SnippetFileInterface +class SnippetFile_it_IT extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/it_IT/mollie-payments.it-IT.json b/src/Resources/snippet/it_IT/mollie-payments.it-IT.json index 1a1881469..6ad379dec 100644 --- a/src/Resources/snippet/it_IT/mollie-payments.it-IT.json +++ b/src/Resources/snippet/it_IT/mollie-payments.it-IT.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "modifica l'indirizzo di fatturazione", "btnEditShippingAddress": "modifica l'indirizzo di spedizione", - "cancelSubscription": "L'abbonamento è stato annullato", - "errorCancelSubscription": "Non è stato possibile annullare l'abbonamento a causa di un errore. Si prega di contattare il nostro supporto.", + "successCancel": "L'abbonamento è stato annullato", + "errorCancel": "Non è stato possibile annullare l'abbonamento a causa di un errore. Si prega di contattare il nostro supporto.", "errorPause": "Si è verificato un errore durante la pausa del suo abbonamento", "errorResume": "Si è verificato un errore durante la ripresa del suo abbonamento", "errorSkip": "Si è verificato un errore durante il salto del suo abbonamento", diff --git a/src/Resources/snippet/lt_LT/SnippetFile_lt_LT.php b/src/Resources/snippet/lt_LT/SnippetFile_lt_LT.php index 4ddf1b6a5..6ee4e6d0d 100644 --- a/src/Resources/snippet/lt_LT/SnippetFile_lt_LT.php +++ b/src/Resources/snippet/lt_LT/SnippetFile_lt_LT.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\lt_LT; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_lt_LT implements SnippetFileInterface + +class SnippetFile_lt_LT extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/lt_LT/mollie-payments.lt-LT.json b/src/Resources/snippet/lt_LT/mollie-payments.lt-LT.json index 71b849f94..061da0b80 100644 --- a/src/Resources/snippet/lt_LT/mollie-payments.lt-LT.json +++ b/src/Resources/snippet/lt_LT/mollie-payments.lt-LT.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "redaguoti faktūrų adresą", "btnEditShippingAddress": "redaguoti siuntimo adresą", - "cancelSubscription": "Prenumerata sėkmingai atšaukta", - "errorCancelSubscription": "Dėl klaidos nepavyko atšaukti prenumeratos. Prašome susisiekti su mūsų pagalbos komanda.", + "successCancel": "Prenumerata sėkmingai atšaukta", + "errorCancel": "Dėl klaidos nepavyko atšaukti prenumeratos. Prašome susisiekti su mūsų pagalbos komanda.", "errorPause": "Sustabdant jūsų prenumeratą įvyko klaida", "errorResume": "Atnaujinant jūsų prenumeratą įvyko klaida", "errorSkip": "Praleidžiant jūsų prenumeratą įvyko klaida", diff --git a/src/Resources/snippet/lv_LV/SnippetFile_lv_LV.php b/src/Resources/snippet/lv_LV/SnippetFile_lv_LV.php index 7881d029a..6dad4c1ce 100644 --- a/src/Resources/snippet/lv_LV/SnippetFile_lv_LV.php +++ b/src/Resources/snippet/lv_LV/SnippetFile_lv_LV.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\lv_LV; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_lv_LV implements SnippetFileInterface + +class SnippetFile_lv_LV extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/lv_LV/mollie-payments.lv-LV.json b/src/Resources/snippet/lv_LV/mollie-payments.lv-LV.json index 92f0bc4a1..6f3c08321 100644 --- a/src/Resources/snippet/lv_LV/mollie-payments.lv-LV.json +++ b/src/Resources/snippet/lv_LV/mollie-payments.lv-LV.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "rediģēt rēķina adresi", "btnEditShippingAddress": "rediģēt piegādes adresi", - "cancelSubscription": "Abonēšana ir atcelta", - "errorCancelSubscription": "Abonementu nevarēja atcelt kļūdas dēļ. Lūdzu, sazinieties ar mūsu atbalsta dienestu.", + "successCancel": "Abonēšana ir atcelta", + "errorCancel": "Abonementu nevarēja atcelt kļūdas dēļ. Lūdzu, sazinieties ar mūsu atbalsta dienestu.", "errorPause": "Radās kļūda, pauzējot jūsu abonēšanu", "errorResume": "Radās kļūda, atsākot jūsu abonēšanu", "errorSkip": "Radās kļūda, izlaižot jūsu abonēšanu", diff --git a/src/Resources/snippet/nb_NO/SnippetFile_nb_NO.php b/src/Resources/snippet/nb_NO/SnippetFile_nb_NO.php index 5ba8c50ca..5b00055c4 100644 --- a/src/Resources/snippet/nb_NO/SnippetFile_nb_NO.php +++ b/src/Resources/snippet/nb_NO/SnippetFile_nb_NO.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\nb_NO; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_nb_NO implements SnippetFileInterface +class SnippetFile_nb_NO extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/nb_NO/mollie-payments.nb-NO.json b/src/Resources/snippet/nb_NO/mollie-payments.nb-NO.json index 13134d9de..8579c9ca7 100644 --- a/src/Resources/snippet/nb_NO/mollie-payments.nb-NO.json +++ b/src/Resources/snippet/nb_NO/mollie-payments.nb-NO.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "rediger faktureringsadresse", "btnEditShippingAddress": "rediger fraktadresse", - "cancelSubscription": "Abonnementet be kansellert", - "errorCancelSubscription": "Abonnementet kunne ikke kanselleres på grunn av en feil. Vennligst kontakt vår support.", + "successCancel": "Abonnementet be kansellert", + "errorCancel": "Abonnementet kunne ikke kanselleres på grunn av en feil. Vennligst kontakt vår support.", "errorPause": "Det oppstod en feil ved pausing av abonnementet ditt", "errorResume": "Det oppstod en feil ved gjenopptakelse av abonnementet ditt", "errorSkip": "Det oppstod en feil ved overhopping av abonnementet ditt", diff --git a/src/Resources/snippet/nl_NL/SnippetFile_nl_NL.php b/src/Resources/snippet/nl_NL/SnippetFile_nl_NL.php index 0a1872a17..a5c8f592a 100644 --- a/src/Resources/snippet/nl_NL/SnippetFile_nl_NL.php +++ b/src/Resources/snippet/nl_NL/SnippetFile_nl_NL.php @@ -2,9 +2,10 @@ namespace Kiener\MolliePayments\Resources\snippet\nl_NL; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_nl_NL implements SnippetFileInterface + +class SnippetFile_nl_NL extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/nl_NL/mollie-payments.nl-NL.json b/src/Resources/snippet/nl_NL/mollie-payments.nl-NL.json index 489d83943..3136272fc 100644 --- a/src/Resources/snippet/nl_NL/mollie-payments.nl-NL.json +++ b/src/Resources/snippet/nl_NL/mollie-payments.nl-NL.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "factuuradres bewerken", "btnEditShippingAddress": "verzendadres bewerken", - "cancelSubscription": "Abonnement is geannuleerd", - "errorCancelSubscription": "Door een fout kon het abonnement niet worden opgezegd. Neem dan contact op met onze ondersteuning.", + "successCancel": "Abonnement is geannuleerd", + "errorCancel": "Door een fout kon het abonnement niet worden opgezegd. Neem dan contact op met onze ondersteuning.", "errorPause": "There was an error when pausing your subscription", "errorResume": "There was an error when resuming your subscription", "errorSkip": "There was an error when skipping your subscription", diff --git a/src/Resources/snippet/pl_PL/SnippetFile_pl_PL.php b/src/Resources/snippet/pl_PL/SnippetFile_pl_PL.php index a18ed546a..a1cad8017 100644 --- a/src/Resources/snippet/pl_PL/SnippetFile_pl_PL.php +++ b/src/Resources/snippet/pl_PL/SnippetFile_pl_PL.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\pl_PL; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_pl_PL implements SnippetFileInterface +class SnippetFile_pl_PL extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/pl_PL/mollie-payments.pl-PL.json b/src/Resources/snippet/pl_PL/mollie-payments.pl-PL.json index 51b56ee49..5be562dcb 100644 --- a/src/Resources/snippet/pl_PL/mollie-payments.pl-PL.json +++ b/src/Resources/snippet/pl_PL/mollie-payments.pl-PL.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "edytuj adres rozliczeniowy", "btnEditShippingAddress": "edytuj adres dostawy", - "cancelSubscription": "Subskrypcja została anulowana", - "errorCancelSubscription": "Subskrypcja nie mogła zostać anulowana z powodu błędu. Prosimy o kontakt z naszym działem wsparcia.", + "successCancel": "Subskrypcja została anulowana", + "errorCancel": "Subskrypcja nie mogła zostać anulowana z powodu błędu. Prosimy o kontakt z naszym działem wsparcia.", "errorPause": "Wystąpił błąd podczas wstrzymywania subskrypcji", "errorResume": "Wystąpił błąd podczas wznawiania subskrypcji", "errorSkip": "Wystąpił błąd podczas pomijania subskrypcji", diff --git a/src/Resources/snippet/pt_PT/SnippetFile_pt_PT.php b/src/Resources/snippet/pt_PT/SnippetFile_pt_PT.php index 63db4da57..1a6773b75 100644 --- a/src/Resources/snippet/pt_PT/SnippetFile_pt_PT.php +++ b/src/Resources/snippet/pt_PT/SnippetFile_pt_PT.php @@ -2,9 +2,10 @@ namespace Kiener\MolliePayments\Resources\snippet\pt_PT; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_pt_PT implements SnippetFileInterface + +class SnippetFile_pt_PT extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/pt_PT/mollie-payments.pt-PT.json b/src/Resources/snippet/pt_PT/mollie-payments.pt-PT.json index b187c57d1..6d3540841 100644 --- a/src/Resources/snippet/pt_PT/mollie-payments.pt-PT.json +++ b/src/Resources/snippet/pt_PT/mollie-payments.pt-PT.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "editar endereço de faturação", "btnEditShippingAddress": "editar endereço de envio", - "cancelSubscription": "A subscrição foi cancelada", - "errorCancelSubscription": "A subscrição não pôde ser cancelada devido a um erro. Por favor, contacte o nosso centro de apoio.", + "successCancel": "A subscrição foi cancelada", + "errorCancel": "A subscrição não pôde ser cancelada devido a um erro. Por favor, contacte o nosso centro de apoio.", "errorPause": "Ocorreu um erro ao colocar a sua subscrição em pausa", "errorResume": "Ocorreu um erro ao retomar a sua subscrição", "errorSkip": "Ocorreu um erro ao saltar a sua subscrição", diff --git a/src/Resources/snippet/ro_RO/SnippetFile_ro_RO.php b/src/Resources/snippet/ro_RO/SnippetFile_ro_RO.php index 882100771..1bd58a14f 100644 --- a/src/Resources/snippet/ro_RO/SnippetFile_ro_RO.php +++ b/src/Resources/snippet/ro_RO/SnippetFile_ro_RO.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\ro_RO; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_ro_RO implements SnippetFileInterface +class SnippetFile_ro_RO extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/ro_RO/mollie-payments.ro-RO.json b/src/Resources/snippet/ro_RO/mollie-payments.ro-RO.json index f570845f9..579e321c8 100644 --- a/src/Resources/snippet/ro_RO/mollie-payments.ro-RO.json +++ b/src/Resources/snippet/ro_RO/mollie-payments.ro-RO.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "editați adresa de facturare", "btnEditShippingAddress": "editați adresa de livrare", - "cancelSubscription": "Abonamentul a fost anulat", - "errorCancelSubscription": "Abonamentul nu a putut fi anulat din cauza unei erori. Vă rugăm să contactați echipa noastră de suport.", + "successCancel": "Abonamentul a fost anulat", + "errorCancel": "Abonamentul nu a putut fi anulat din cauza unei erori. Vă rugăm să contactați echipa noastră de suport.", "errorPause": "A apărut o eroare când ați încercat să suspendați abonamentul dvs.", "errorResume": "A apărut o eroare când ați încercat să reactivați abonamentul dvs.", "errorSkip": "A apărut o eroare când ați încercat să amânați abonamentul dvs.", diff --git a/src/Resources/snippet/sk_SK/SnippetFile_sk_SK.php b/src/Resources/snippet/sk_SK/SnippetFile_sk_SK.php index 37b3e70e3..ac91f06c0 100644 --- a/src/Resources/snippet/sk_SK/SnippetFile_sk_SK.php +++ b/src/Resources/snippet/sk_SK/SnippetFile_sk_SK.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\sk_SK; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_sk_SK implements SnippetFileInterface + +class SnippetFile_sk_SK extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/sk_SK/mollie-payments.sk-SK.json b/src/Resources/snippet/sk_SK/mollie-payments.sk-SK.json index 01b827f34..2af25a5a5 100644 --- a/src/Resources/snippet/sk_SK/mollie-payments.sk-SK.json +++ b/src/Resources/snippet/sk_SK/mollie-payments.sk-SK.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "Upraviť fakturačnú adresu", "btnEditShippingAddress": "Upraviť dodaciu adresu", - "cancelSubscription": "Predplatné bolo zrušené", - "errorCancelSubscription": "Predplatné sa nepodarilo zrušiť kvôli chybe. Prosím, kontaktujte našu podporu.", + "successCancel": "Predplatné bolo zrušené", + "errorCancel": "Predplatné sa nepodarilo zrušiť kvôli chybe. Prosím, kontaktujte našu podporu.", "errorPause": "Pri pozastavovaní vášho predplatného nastala chyba", "errorResume": "Pri obnove vášho predplatného nastala chyba", "errorSkip": "Pri preskočení predplatného došlo k chybe", diff --git a/src/Resources/snippet/sl_SL/SnippetFile_sl_SL.php b/src/Resources/snippet/sl_SL/SnippetFile_sl_SL.php index 6f1dba0db..64db8141c 100644 --- a/src/Resources/snippet/sl_SL/SnippetFile_sl_SL.php +++ b/src/Resources/snippet/sl_SL/SnippetFile_sl_SL.php @@ -4,9 +4,10 @@ namespace Kiener\MolliePayments\Resources\snippet\sl_SL; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_sl_SL implements SnippetFileInterface + +class SnippetFile_sl_SL extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/sl_SL/mollie-payments.sl-SL.json b/src/Resources/snippet/sl_SL/mollie-payments.sl-SL.json index 668517254..bcff91e5b 100644 --- a/src/Resources/snippet/sl_SL/mollie-payments.sl-SL.json +++ b/src/Resources/snippet/sl_SL/mollie-payments.sl-SL.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "uredi naslov za račun", "btnEditShippingAddress": "Uredi naslov za pošiljanje", - "cancelSubscription": "Naročnina je bila preklicana", - "errorCancelSubscription": "Naročnine ni bilo mogoče preklicati zaradi napake. Prosimo, kontaktirajte našo podporo.", + "successCancel": "Naročnina je bila preklicana", + "errorCancel": "Naročnine ni bilo mogoče preklicati zaradi napake. Prosimo, kontaktirajte našo podporo.", "errorPause": "Prišlo je do napake pri ustavljanju vaše naročnine", "errorResume": "Prišlo je do napake pri nadaljevanju vaše naročnine", "errorSkip": "Prišlo je do napake pri začasni zaustavitvi vaše naročnine", diff --git a/src/Resources/snippet/sv_SE/SnippetFile_sv_SE.php b/src/Resources/snippet/sv_SE/SnippetFile_sv_SE.php index 248956523..4227f8c55 100644 --- a/src/Resources/snippet/sv_SE/SnippetFile_sv_SE.php +++ b/src/Resources/snippet/sv_SE/SnippetFile_sv_SE.php @@ -4,9 +4,9 @@ namespace Kiener\MolliePayments\Resources\snippet\sv_SE; -use Shopware\Core\System\Snippet\Files\SnippetFileInterface; +use Shopware\Core\System\Snippet\Files\AbstractSnippetFile; -class SnippetFile_sv_SE implements SnippetFileInterface +class SnippetFile_sv_SE extends AbstractSnippetFile { public function getName(): string { diff --git a/src/Resources/snippet/sv_SE/mollie-payments.sv-SE.json b/src/Resources/snippet/sv_SE/mollie-payments.sv-SE.json index 74e2dba68..df0763849 100644 --- a/src/Resources/snippet/sv_SE/mollie-payments.sv-SE.json +++ b/src/Resources/snippet/sv_SE/mollie-payments.sv-SE.json @@ -72,8 +72,8 @@ "account": { "btnEditBillingAddress": "redigera faktureringsadress", "btnEditShippingAddress": "redigera fraktadress", - "cancelSubscription": "Prenumerationen har avbrutits", - "errorCancelSubscription": "Prenumerationen kunde inte avbrytas på grund av ett fel. Vänligen kontakta vår support.", + "successCancel": "Prenumerationen har avbrutits", + "errorCancel": "Prenumerationen kunde inte avbrytas på grund av ett fel. Vänligen kontakta vår support.", "errorPause": "Det uppstod ett fel när prenumerationen skulle pausas", "errorResume": "Det uppstod ett fel när prenumerationen skulle återupptas", "errorSkip": "Det uppstod ett fel när prenumerationen skulle hoppas över", diff --git a/src/Resources/views/mollie/component/credit-card-mandate.html.twig b/src/Resources/views/mollie/component/credit-card-mandate.html.twig index 0b3ee885b..a6e72764b 100644 --- a/src/Resources/views/mollie/component/credit-card-mandate.html.twig +++ b/src/Resources/views/mollie/component/credit-card-mandate.html.twig @@ -8,7 +8,8 @@ {% block mollie_credit_card_mandate_block_input %} {% if not modifiable %}
- {% if changeStatusUrl %} - + {% if changePaymentStateUrl %} + Change Status in Test Mode @@ -257,7 +257,7 @@ function requestStatus() { const xhr = new XMLHttpRequest(); - xhr.open('GET', '/mollie/pos/{{ swOrderId }}/{{ molliePaymentId }}/status'); + xhr.open('GET', '/mollie/pos/{{ transactionId }}/{{ paymentId }}/status'); xhr.setRequestHeader('Content-Type', 'application/json'); xhr.onload = handleResponse; diff --git a/src/Resources/views/storefront/component/payment/component/cc-fields.html.twig b/src/Resources/views/storefront/component/payment/component/cc-fields.html.twig index 39fc64160..7527c0946 100644 --- a/src/Resources/views/storefront/component/payment/component/cc-fields.html.twig +++ b/src/Resources/views/storefront/component/payment/component/cc-fields.html.twig @@ -35,7 +35,8 @@
{% block mollie_credit_card_mandate_form_radio_input %} {% if page.enable_credit_card_components == true %} - +
{{ "molliePayments.components.creditCard.headLine"|trans|striptags }} @@ -121,8 +122,9 @@ {% block mollie_creditcard_form_check_store_card_checkbox_input %} + name="savePaymentDetails"/> {% endblock %} {% block mollie_creditcard_form_check_store_card_checkbox_label %}
{{ payment.translated.name }} ({{ "molliePayments.testMode.label"|trans }}) {% if payment.translated.description %} diff --git a/src/Resources/views/storefront/component/payment/payment-method.html.twig b/src/Resources/views/storefront/component/payment/payment-method.html.twig index 8d3e4acd5..eb7c45bd5 100644 --- a/src/Resources/views/storefront/component/payment/payment-method.html.twig +++ b/src/Resources/views/storefront/component/payment/payment-method.html.twig @@ -14,7 +14,7 @@ {% block component_payment_method_description %} - {% if "MolliePayments" in payment.handlerIdentifier and page.extensions.MollieTestModePageExtension.testMode == true %} + {% if "Mollie" in payment.handlerIdentifier and page.extensions.MollieTestModePageExtension.testMode == true %}
{{ payment.translated.name }} ({{ "molliePayments.testMode.label"|trans }}) {% if payment.translated.description and payment.id is same as(selectedPaymentMethodId) %} @@ -38,5 +38,8 @@ {% sw_include '@MolliePayments/storefront/component/payment/component/pos-fields.html.twig' %} {% elseif payment.translated.customFields.mollie_payment_method_name in ['bancomatpay', 'bizum'] %} {% sw_include '@MolliePayments/storefront/component/payment/component/phone-fields.html.twig' %} + {% elseif payment.technicalName == 'payment_mollie_paypalexpress' %} + {% sw_include '@MolliePayments/storefront/component/payment/component/ppe-fields.html.twig' %} {% endif %} + {% endblock %} diff --git a/src/Resources/views/storefront/page/account/index.html.twig b/src/Resources/views/storefront/page/account/index.html.twig new file mode 100644 index 000000000..6a8199001 --- /dev/null +++ b/src/Resources/views/storefront/page/account/index.html.twig @@ -0,0 +1,10 @@ +{% sw_extends '@Storefront/storefront/page/account/index.html.twig' %} + +{% block page_account_overview_payment_content %} + {% if "Mollie" in context.customer.defaultPaymentMethod.handlerIdentifier and page.extensions.MollieTestModePageExtension.testMode == true %} + {{ context.customer.defaultPaymentMethod.translated.name }} ({{ "molliePayments.testMode.label"|trans }}) +

{{ context.customer.defaultPaymentMethod.description }}

+ {% else %} + {{ parent() }} + {% endif %} +{% endblock %} diff --git a/src/Resources/views/storefront/page/account/subscriptions/subscription-item.html.twig b/src/Resources/views/storefront/page/account/subscriptions/subscription-item.html.twig index d88aac29c..37cff1e73 100644 --- a/src/Resources/views/storefront/page/account/subscriptions/subscription-item.html.twig +++ b/src/Resources/views/storefront/page/account/subscriptions/subscription-item.html.twig @@ -1,6 +1,7 @@ {% block page_account_mollie_subscriptions_item_overview %}
+
{% block page_account_mollie_subscriptions_item_heading %}

@@ -129,7 +130,7 @@ {% if(subscription.isPauseAllowed) %} {% block page_account_subscriptions_item_context_menu_pause %} {% block page_account_subscriptions_item_context_menu_pause_form %} -
@@ -152,7 +153,7 @@ {% if(subscription.isResumeAllowed) %} {% block page_account_subscriptions_item_context_menu_resume %} {% block page_account_subscriptions_item_context_menu_resume_form %} - @@ -177,7 +178,7 @@ {% if page.allowSkip and subscription.isSkipAllowed %} {% block page_account_subscriptions_item_context_menu_skip %} {% block page_account_subscriptions_item_context_menu_skip_form %} - diff --git a/src/Resources/views/storefront/page/checkout/cart/index.html.twig b/src/Resources/views/storefront/page/checkout/cart/index.html.twig index a1bfbe752..cebfadbef 100644 --- a/src/Resources/views/storefront/page/checkout/cart/index.html.twig +++ b/src/Resources/views/storefront/page/checkout/cart/index.html.twig @@ -15,6 +15,7 @@ {% endblock %} {% block page_checkout_cart_shipping_costs_form_group_payment_method %} +
+ {% for paymentMethod in paymentMethods %} + + {% endfor %} +   {{ "molliePayments.messages.payment.buttonReturnToShop"|trans|striptags }} +

diff --git a/src/Service/Cart/Voucher/VoucherCartCollector.php b/src/Service/Cart/Voucher/VoucherCartCollector.php deleted file mode 100644 index 98032dae2..000000000 --- a/src/Service/Cart/Voucher/VoucherCartCollector.php +++ /dev/null @@ -1,104 +0,0 @@ -voucherService = $voucherService; - $this->repoPaymentMethods = $paymentMethodRepository; - } - - /** - * This function is used to verify if a voucher payment is permitted to be used. - * It will just calculate this once, and then offer that information - * in the DATA field of the cart object. - * - * @param CartDataCollection $data - */ - public function collect(CartDataCollection $data, Cart $original, SalesChannelContext $context, CartBehavior $behavior): void - { - $salesChannelHasVoucherMethod = true; - - // if we have a lot of products, the performance might not be good enough at the moment. - // we try to improve this as first step, by only verifying our products - // if we even have the voucher payment method assigned to our Sales Channel. - // if it's not assigned anyway, then we can simply skip that step - /** @var null|string[] $paymentMethodIDs */ - $paymentMethodIDs = $context->getSalesChannel()->getPaymentMethodIds(); - - if (is_array($paymentMethodIDs)) { - $voucherID = $this->getVoucherID($context->getContext()); - $salesChannelHasVoucherMethod = in_array($voucherID, $paymentMethodIDs, true); - } - - $cartHasVoucher = false; - - if ($salesChannelHasVoucherMethod) { - foreach ($original->getLineItems()->getFlat() as $item) { - // get the final inherited voucher type of the product - // this might even be from the parent - $voucherType = $this->voucherService->getFinalVoucherType($item, $context); - - // if we have a valid voucher product - // then we have to update the actual line item, - // because the current one might be empty, if only our PARENT would be configured. - if (VoucherType::isVoucherProduct($voucherType)) { - $cartHasVoucher = true; - - // load current custom fields data of mollie - // and overwrite the voucher type that we just searched - $attributes = new LineItemAttributes($item); - $attributes->setVoucherType($voucherType); - - $customFields = $item->getPayload()['customFields']; - $customFields[CustomFieldsInterface::MOLLIE_KEY] = $attributes->toArray(); - - $item->setPayloadValue('customFields', $customFields); - } - } - } - - $data->set(self::VOUCHER_PERMITTED, $cartHasVoucher); - } - - private function getVoucherID(Context $context): string - { - $criteria = new Criteria(); - $criteria->addFilter(new EqualsFilter('handlerIdentifier', VoucherPayment::class)); - - // Get payment methods - /** @var array $paymentMethods */ - $paymentMethods = $this->repoPaymentMethods->getRepository()->searchIds($criteria, $context)->getIds(); - - return (string) $paymentMethods[0]; - } -} diff --git a/src/Service/Cart/Voucher/VoucherService.php b/src/Service/Cart/Voucher/VoucherService.php deleted file mode 100644 index 5ef1be391..000000000 --- a/src/Service/Cart/Voucher/VoucherService.php +++ /dev/null @@ -1,130 +0,0 @@ -> - */ - private $repoProducts; - - /** - * @var LoggerInterface - */ - private $logger; - - /** - * @param EntityRepository> $repoProducts - */ - public function __construct($repoProducts, LoggerInterface $logger) - { - $this->repoProducts = $repoProducts; - $this->logger = $logger; - } - - public function getFinalVoucherType(LineItem $item, SalesChannelContext $context): string - { - $attributes = new LineItemAttributes($item); - - // verify if we even have a product number - if (empty($attributes->getProductNumber())) { - return VoucherType::TYPE_NOTSET; - } - - try { - // we might not always be able to find a product - // some plugins (custom products, easycoupon) use not-existing product numbers in the line items. - // in that case, we just ignore this, and return voucher type NOT_SET (in the exception) - $currentProduct = $this->getProductByNumber($attributes->getProductNumber(), $context); - } catch (ProductNumberNotFoundException $ex) { - $this->logger->notice( - 'VoucherService could not find product: ' . $attributes->getProductNumber() . '. This might be a custom product, or voucher. If so, you can just ignore this message! If not, something is going wrong in here!' - ); - - return VoucherType::TYPE_NOTSET; - } - - $currentAttributes = new ProductAttributes($currentProduct); - - $voucherType = $currentAttributes->getVoucherType(); - - // if we don't have a voucher type in our current product, - // but we do have a parent product, then check if that one is a voucher. - if ($voucherType === VoucherType::TYPE_NOTSET && ! empty($currentProduct->getParentId())) { - $parentProduct = $this->getProductById($currentProduct->getParentId(), $context); - $parentAttributes = new ProductAttributes($parentProduct); - - $voucherType = $parentAttributes->getVoucherType(); - } - - return $voucherType; - } - - public function isVoucherPaymentMethod(PaymentMethodEntity $pm): bool - { - $attributes = new PaymentMethodAttributes($pm); - - if ($attributes->isVoucherMethod()) { - return true; - } - - return false; - } - - private function getProductByNumber(string $productNumber, SalesChannelContext $context): ProductEntity - { - $criteria = new Criteria(); - $criteria->addFilter(new EqualsFilter('productNumber', $productNumber)); - - /** @var EntitySearchResult> $productsSearchResult */ - $productsSearchResult = $this->repoProducts->search($criteria, $context->getContext()); - - if ($productsSearchResult->count() === 0) { - throw new ProductNumberNotFoundException($productNumber); - } - /** @var ?ProductEntity $product */ - $product = $productsSearchResult->first(); - if ($product === null) { - throw new ProductNotFoundException($productNumber); - } - - return $product; - } - - private function getProductById(string $productId, SalesChannelContext $context): ProductEntity - { - $criteria = new Criteria([$productId]); - $productSearchResult = $this->repoProducts->search($criteria, $context->getContext()); - - if ($productSearchResult->count() === 0) { - throw new ProductNotFoundException($productId); - } - - /** @var ?ProductEntity $product */ - $product = $productSearchResult->first(); - if ($product === null) { - throw new ProductNotFoundException($productId); - } - - return $product; - } -} diff --git a/src/Service/CustomerService.php b/src/Service/CustomerService.php index f144bbc9d..bb5673cdf 100644 --- a/src/Service/CustomerService.php +++ b/src/Service/CustomerService.php @@ -336,7 +336,7 @@ public function getCustomerStruct(string $customerId, Context $context): Custome $customer = $this->getCustomer($customerId, $context); - if (! ($customer instanceof CustomerEntity)) { + if (! $customer instanceof CustomerEntity) { throw new CustomerCouldNotBeFoundException($customerId); } @@ -481,7 +481,7 @@ public function createMollieCustomer(string $customerId, string $salesChannelId, $customer = $this->getCustomer($customerId, $context); - if (! ($customer instanceof CustomerEntity)) { + if (! $customer instanceof CustomerEntity) { throw new CustomerCouldNotBeFoundException($customerId); } diff --git a/src/Service/Installer/CustomFieldsInstaller.php b/src/Service/Installer/CustomFieldsInstaller.php index 4ea4b732c..2b451c798 100644 --- a/src/Service/Installer/CustomFieldsInstaller.php +++ b/src/Service/Installer/CustomFieldsInstaller.php @@ -4,7 +4,7 @@ namespace Kiener\MolliePayments\Service\Installer; -use Kiener\MolliePayments\Struct\Voucher\VoucherType; +use Mollie\Shopware\Component\Mollie\VoucherCategory; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; @@ -67,10 +67,11 @@ private function installProductData(Context $context): void 'id' => self::ID_VOUCHER_TYPE, 'name' => 'mollie_payments_product_voucher_type', 'active' => true, + 'allowCartExpose' => true, 'type' => CustomFieldTypes::SELECT, 'config' => [ 'customFieldPosition' => 1, - 'componentName' => 'sw-single-select', + 'componentName' => 'sw-multi-select', 'customFieldType' => 'select', 'label' => [ 'en-GB' => 'Voucher Type', @@ -94,7 +95,7 @@ private function installProductData(Context $context): void 'de_DE' => 'Öko', 'nl-NL' => 'Eco', ], - 'value' => VoucherType::TYPE_ECO, + 'value' => VoucherCategory::ECO->value, ], [ 'label' => [ @@ -102,7 +103,7 @@ private function installProductData(Context $context): void 'de_DE' => 'Mahlzeit', 'nl-NL' => 'Meal', ], - 'value' => VoucherType::TYPE_MEAL, + 'value' => VoucherCategory::MEAL->value, ], [ 'label' => [ @@ -110,7 +111,7 @@ private function installProductData(Context $context): void 'de_DE' => 'Geschenk', 'nl-NL' => 'Geschenk', ], - 'value' => VoucherType::TYPE_GIFT, + 'value' => VoucherCategory::GIFT->value, ], ], ], @@ -119,6 +120,7 @@ private function installProductData(Context $context): void 'id' => self::ID_SUBSCRIPTION_ENABLED, 'name' => 'mollie_payments_product_subscription_enabled', 'active' => true, + 'allowCartExpose' => true, 'type' => CustomFieldTypes::SWITCH, 'config' => [ 'customFieldPosition' => 2, @@ -135,6 +137,7 @@ private function installProductData(Context $context): void 'id' => self::ID_SUBSCRIPTION_INTERVAL, 'name' => 'mollie_payments_product_subscription_interval', 'active' => true, + 'allowCartExpose' => true, 'type' => CustomFieldTypes::INT, 'config' => [ 'customFieldPosition' => 3, @@ -161,6 +164,7 @@ private function installProductData(Context $context): void 'id' => self::ID_SUBSCRIPTION_INTERVAL_UNIT, 'name' => 'mollie_payments_product_subscription_interval_unit', 'active' => true, + 'allowCartExpose' => true, 'type' => CustomFieldTypes::SELECT, 'config' => [ 'customFieldPosition' => 4, @@ -213,6 +217,7 @@ private function installProductData(Context $context): void 'id' => self::ID_SUBSCRIPTION_REPETITION, 'name' => 'mollie_payments_product_subscription_repetition', 'active' => true, + 'allowCartExpose' => true, 'type' => CustomFieldTypes::TEXT, 'config' => [ 'customFieldPosition' => 5, diff --git a/src/Service/Mail/MailService.php b/src/Service/Mail/MailService.php index e4cf3581e..636dce149 100644 --- a/src/Service/Mail/MailService.php +++ b/src/Service/Mail/MailService.php @@ -44,7 +44,7 @@ public function send(array $data, array $attachments = []): void $this->buildContents($data), [], [], // Additional data, but doesn't work properly. -/** @phpstan-ignore argument.type */ $attachments + /** @phpstan-ignore argument.type */ $attachments ); $mail->addReplyTo(...$this->formatMailAddresses([$data['replyToEmail'] => $data['replyToName']])); diff --git a/src/Service/Order/OrderExpireService.php b/src/Service/Order/OrderExpireService.php index bbf9fb194..fb334c05e 100644 --- a/src/Service/Order/OrderExpireService.php +++ b/src/Service/Order/OrderExpireService.php @@ -3,7 +3,6 @@ namespace Kiener\MolliePayments\Service\Order; -use Kiener\MolliePayments\Handler\Method\BankTransferPayment; use Kiener\MolliePayments\Service\Mollie\MolliePaymentStatus; use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Struct\Order\OrderAttributes; @@ -109,7 +108,7 @@ public function cancelExpiredOrders(OrderCollection $orders, Context $context): if ($this->orderUsesSepaPayment($lastTransaction)) { $bankTransferDueDays = $settings->getPaymentMethodBankTransferDueDateDays(); if ($bankTransferDueDays === null) { - $bankTransferDueDays = BankTransferPayment::DUE_DATE_MAX_DAYS; + $bankTransferDueDays = 100; } $finalizeTransactionTimeInMinutes = 60 * 60 * 24 * $bankTransferDueDays; } @@ -149,6 +148,6 @@ private function orderUsesSepaPayment(OrderTransactionEntity $transaction): bool return false; } - return $paymentMethod->getHandlerIdentifier() === BankTransferPayment::class; + return $paymentMethod->getHandlerIdentifier() === 'Kiener\MolliePayments\Handler\Method\BankTransferPayment'; } } diff --git a/src/Service/PayPalExpressConfig.php b/src/Service/PayPalExpressConfig.php deleted file mode 100644 index 54414d3db..000000000 --- a/src/Service/PayPalExpressConfig.php +++ /dev/null @@ -1,52 +0,0 @@ -enabled = $enabled ?? 0; - $this->buttonStyle = $buttonStyle ?? 1; - $this->buttonShape = $buttonShape ?? 1; - $restrictions = $restrictions ?? ''; - - if ($restrictions !== '') { - $this->restrictions = explode(' ', $restrictions); - } - } - - public function isEnabled(): bool - { - return $this->enabled === 1; - } - - /** - * @param array $structData - * - * @return array - */ - public function assign(array $structData): array - { - $structData['paypalExpressEnabled'] = $this->isEnabled(); - $structData['paypalExpressButtonStyle'] = $structData['paypalExpressButtonStyle'] ?? $this->buttonStyle; - $structData['paypalExpressButtonShape'] = $structData['paypalExpressButtonShape'] ?? $this->buttonShape; - $structData['paypalExpressRestrictions'] = array_unique(array_merge($structData['paypalExpressRestrictions'] ?? [], $this->restrictions)); - - return $structData; - } -} diff --git a/src/Service/Payment/Remover/PayPalExpressPaymentRemover.php b/src/Service/Payment/Remover/PayPalExpressPaymentRemover.php deleted file mode 100644 index a6745b6a6..000000000 --- a/src/Service/Payment/Remover/PayPalExpressPaymentRemover.php +++ /dev/null @@ -1,52 +0,0 @@ -isAllowedRoute()) { - return $originalData; - } - $showPPEOnly = false; - - if ($this->isOrderRoute()) { - $order = $this->getOrder($context->getContext()); - $showPPEOnly = (bool) ($order->getCustomFields()[CustomFieldsInterface::MOLLIE_KEY][CustomFieldsInterface::PAYPAL_EXPRESS_AUTHENTICATE_ID] ?? false); - } - if ($this->isCartRoute()) { - $cart = $this->getCart($context); - $mollieShopwareCart = new MollieShopwareCart($cart); - - $showPPEOnly = $mollieShopwareCart->isPayPalExpressComplete(); - } - - foreach ($originalData->getPaymentMethods() as $key => $paymentMethod) { - $attributes = new PaymentMethodAttributes($paymentMethod); - $isPayPalExpress = $attributes->getMollieIdentifier() === PayPalExpressPayment::PAYMENT_METHOD_NAME; - - if ($showPPEOnly === true && $isPayPalExpress === false) { - $originalData->getPaymentMethods()->remove($key); - continue; - } - - if ($showPPEOnly === false && $isPayPalExpress === true) { - $originalData->getPaymentMethods()->remove($key); - } - } - - return $originalData; - } -} diff --git a/src/Service/Payment/Remover/PaymentMethodRemover.php b/src/Service/Payment/Remover/PaymentMethodRemover.php index 597bbc89e..94181c16c 100644 --- a/src/Service/Payment/Remover/PaymentMethodRemover.php +++ b/src/Service/Payment/Remover/PaymentMethodRemover.php @@ -11,7 +11,6 @@ use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Struct\LineItem\LineItemAttributes; use Kiener\MolliePayments\Struct\OrderLineItemEntity\OrderLineItemEntityAttributes; -use Kiener\MolliePayments\Struct\Voucher\VoucherType; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Cart\Cart; @@ -184,22 +183,6 @@ protected function isSubscriptionOrder(OrderEntity $order, Context $context): bo return false; } - protected function isVoucherOrder(OrderEntity $order, Context $context): bool - { - $lineItems = $this->orderDataExtractor->extractLineItems($order); - - /** @var OrderLineItemEntity $lineItem */ - foreach ($lineItems as $lineItem) { - $attributes = new OrderLineItemEntityAttributes($lineItem); - - if (VoucherType::isVoucherProduct($attributes->getVoucherType())) { - return true; - } - } - - return false; - } - /** * @throws MissingRequestException */ diff --git a/src/Service/PaymentMethodService.php b/src/Service/PaymentMethodService.php index 93f49bba6..62c978261 100644 --- a/src/Service/PaymentMethodService.php +++ b/src/Service/PaymentMethodService.php @@ -3,110 +3,28 @@ namespace Kiener\MolliePayments\Service; -use Kiener\MolliePayments\Compatibility\VersionCompare; -use Kiener\MolliePayments\Handler\Method\AlmaPayment; use Kiener\MolliePayments\Handler\Method\ApplePayPayment; -use Kiener\MolliePayments\Handler\Method\BancomatPayment; -use Kiener\MolliePayments\Handler\Method\BanContactPayment; -use Kiener\MolliePayments\Handler\Method\BankTransferPayment; -use Kiener\MolliePayments\Handler\Method\BelfiusPayment; -use Kiener\MolliePayments\Handler\Method\BilliePayment; -use Kiener\MolliePayments\Handler\Method\BizumPayment; -use Kiener\MolliePayments\Handler\Method\BlikPayment; -use Kiener\MolliePayments\Handler\Method\CreditCardPayment; -use Kiener\MolliePayments\Handler\Method\EpsPayment; -use Kiener\MolliePayments\Handler\Method\GiftCardPayment; -use Kiener\MolliePayments\Handler\Method\GiroPayPayment; -use Kiener\MolliePayments\Handler\Method\iDealPayment; -use Kiener\MolliePayments\Handler\Method\In3Payment; use Kiener\MolliePayments\Handler\Method\IngHomePayPayment; -use Kiener\MolliePayments\Handler\Method\KbcPayment; -use Kiener\MolliePayments\Handler\Method\KlarnaOnePayment; use Kiener\MolliePayments\Handler\Method\KlarnaPayLaterPayment; use Kiener\MolliePayments\Handler\Method\KlarnaPayNowPayment; use Kiener\MolliePayments\Handler\Method\KlarnaSliceItPayment; -use Kiener\MolliePayments\Handler\Method\MbWayPayment; -use Kiener\MolliePayments\Handler\Method\MobilePayPayment; -use Kiener\MolliePayments\Handler\Method\MultibancoPayment; -use Kiener\MolliePayments\Handler\Method\MyBankPayment; -use Kiener\MolliePayments\Handler\Method\PayByBankPayment; -use Kiener\MolliePayments\Handler\Method\PayconiqPayment; -use Kiener\MolliePayments\Handler\Method\PayPalExpressPayment; -use Kiener\MolliePayments\Handler\Method\PayPalPayment; -use Kiener\MolliePayments\Handler\Method\PaySafeCardPayment; -use Kiener\MolliePayments\Handler\Method\PosPayment; -use Kiener\MolliePayments\Handler\Method\Przelewy24Payment; -use Kiener\MolliePayments\Handler\Method\RivertyPayment; -use Kiener\MolliePayments\Handler\Method\SatispayPayment; use Kiener\MolliePayments\Handler\Method\SofortPayment; -use Kiener\MolliePayments\Handler\Method\SwishPayment; -use Kiener\MolliePayments\Handler\Method\TrustlyPayment; -use Kiener\MolliePayments\Handler\Method\TwintPayment; -use Kiener\MolliePayments\Handler\Method\VippsPayment; -use Kiener\MolliePayments\Handler\Method\VoucherPayment; -use Kiener\MolliePayments\MolliePayments; -use Kiener\MolliePayments\Repository\MediaRepository; use Kiener\MolliePayments\Repository\PaymentMethodRepository; -use Kiener\MolliePayments\Service\HttpClient\HttpClientInterface; use Mollie\Api\Resources\Order; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity; use Shopware\Core\Checkout\Payment\PaymentMethodEntity; -use Shopware\Core\Content\Media\MediaCollection; -use Shopware\Core\Content\Media\MediaService; -use Shopware\Core\Defaults; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent; -use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; -use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\ContainsFilter; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; -use Shopware\Core\Framework\Plugin\Util\PluginIdProvider; class PaymentMethodService { public const TECHNICAL_NAME_PREFIX = 'payment_mollie_'; - /** - * @var MediaService - */ - private $mediaService; - - /** - * @var PaymentMethodRepository - */ - private $paymentRepository; - - /** - * @var PluginIdProvider - */ - private $pluginIdProvider; - - /** - * @var MediaRepository - */ - private $mediaRepository; - - /** - * @var HttpClientInterface - */ - private $httpClient; - - /** - * @var VersionCompare - */ - private $versionCompare; - private PayPalExpressConfig $payPalExpressConfig; - - public function __construct(VersionCompare $versionCompare, MediaService $mediaService, MediaRepository $mediaRepository, PaymentMethodRepository $paymentRepository, PluginIdProvider $pluginIdProvider, HttpClientInterface $httpClient, PayPalExpressConfig $payPalExpressConfig) - { - $this->mediaService = $mediaService; - $this->mediaRepository = $mediaRepository; - $this->paymentRepository = $paymentRepository; - $this->pluginIdProvider = $pluginIdProvider; - $this->httpClient = $httpClient; - - $this->versionCompare = $versionCompare; - $this->payPalExpressConfig = $payPalExpressConfig; + public function __construct( + private PaymentMethodRepository $paymentRepository, + ) { } public function installAndActivatePaymentMethods(Context $context): void @@ -119,189 +37,6 @@ public function installAndActivatePaymentMethods(Context $context): void $this->disablePaymentMethod(KlarnaPayNowPayment::class, $context); $this->disablePaymentMethod(KlarnaSliceItPayment::class, $context); $this->disablePaymentMethod(SofortPayment::class, $context); - $this->disablePaymentMethod(PayconiqPayment::class, $context); - $this->disablePaymentMethod(GiroPayPayment::class, $context); - - if (! $this->payPalExpressConfig->isEnabled()) { - $this->disablePaymentMethod(PayPalExpressPayment::class, $context); - } - - // Get installable payment methods - $installablePaymentMethods = $this->getInstallablePaymentMethods(); - - if (empty($installablePaymentMethods)) { - return; - } - - // Check which payment methods from Mollie are already installed in the shop - $installedPaymentMethodHandlers = $this->getInstalledPaymentMethodHandlers($this->getPaymentHandlers(), $context); - - // Add payment methods - $this->addPaymentMethods($installablePaymentMethods, $context); - - // Activate newly installed payment methods - $this->activatePaymentMethods( - $installablePaymentMethods, - $installedPaymentMethodHandlers, - $context - ); - } - - /** - * @param array $paymentMethods - */ - public function addPaymentMethods(array $paymentMethods, Context $context): void - { - // Get the plugin ID - $pluginId = $this->pluginIdProvider->getPluginIdByBaseClass(MolliePayments::class, $context); - - $upsertData = []; - - foreach ($paymentMethods as $paymentMethod) { - $identifier = $paymentMethod['handler']; - - // Upload icon to the media repository - $mediaId = $this->getMediaId($paymentMethod, $context); - - try { - $existingPaymentMethod = $this->getPaymentMethod($identifier, $context); - } catch (InconsistentCriteriaIdsException $e) { - $existingPaymentMethod = null; - } - - $technicalName = ''; - - if ($existingPaymentMethod instanceof PaymentMethodEntity) { - $paymentMethodData = [ - // ALWAYS ADD THE ID, otherwise upsert would create NEW entries! - 'id' => $existingPaymentMethod->getId(), - 'handlerIdentifier' => $paymentMethod['handler'], - // ------------------------------------------ - // make sure to repair some fields in here - // so that Mollie does always work for our wonderful customers :) - 'pluginId' => $pluginId, - 'mediaId' => $mediaId, - // ------------------------------------------ - // unfortunately some fields are required (*sigh) - // so we need to provide those with the value of - // the existing method!!! - 'name' => $existingPaymentMethod->getName(), - ]; - $translations = $existingPaymentMethod->getTranslations(); - - if ($translations !== null) { - $paymentMethodData['translations'][Defaults::LANGUAGE_SYSTEM] = [ - 'name' => $existingPaymentMethod->getName(), - ]; - - foreach ($translations as $translation) { - $paymentMethodData['translations'][$translation->getLanguageId()] = [ - 'name' => $translation->getName(), - ]; - } - } - - /** @phpstan-ignore-next-line */ - if ($this->versionCompare->gte('6.5.7.0') && method_exists($existingPaymentMethod, 'getTechnicalName')) { - // we do a string cast here, since getTechnicalName will be not nullable in the future - /** @phpstan-ignore-next-line */ - $technicalName = (string) $existingPaymentMethod->getTechnicalName(); - } - } else { - // let's create a full parameter list of everything - // that our new payment method needs to have - $paymentMethodData = [ - 'handlerIdentifier' => $paymentMethod['handler'], - 'pluginId' => $pluginId, - // ------------------------------------------ - 'name' => $paymentMethod['description'], - 'description' => '', - 'mediaId' => $mediaId, - 'afterOrderEnabled' => true, - 'translations' => [ - Defaults::LANGUAGE_SYSTEM => [ - 'name' => $paymentMethod['description'], - ], - ], - ]; - } - - if ($technicalName === '') { - $technicalName = self::TECHNICAL_NAME_PREFIX . $paymentMethod['name']; - } - - // custom field name is required to be specific, because we use it in the template to display components - $paymentMethodData['customFields'] = [ - 'mollie_payment_method_name' => $paymentMethod['name'], - ]; - - // starting with Shopware 6.5.7.0 this has to be filled out - // so that you can still save the payment method in the administration - if ($this->versionCompare->gte('6.5.7.0')) { - $paymentMethodData['technicalName'] = $technicalName; - } - - $upsertData[] = $paymentMethodData; - } - - if (count($upsertData) > 0) { - $this->paymentRepository->getRepository()->upsert($upsertData, $context); - } - } - - /** - * @param array $installableHandlers - * - * @return array - */ - public function getInstalledPaymentMethodHandlers(array $installableHandlers, Context $context): array - { - $installedHandlers = []; - $paymentCriteria = new Criteria(); - $paymentCriteria->addFilter(new ContainsFilter('handlerIdentifier', 'MolliePayments')); - - $paymentMethods = $this->paymentRepository->getRepository()->search($paymentCriteria, $context); - - if (! $paymentMethods->count()) { - return $installableHandlers; - } - - /** @var PaymentMethodEntity $paymentMethod */ - foreach ($paymentMethods->getEntities() as $paymentMethod) { - if (! in_array($paymentMethod->getHandlerIdentifier(), $installableHandlers, true)) { - continue; - } - - $installedHandlers[] = $paymentMethod->getHandlerIdentifier(); - } - - return $installedHandlers; - } - - /** - * Activate payment methods in Shopware. - * - * @param array $paymentMethods - * @param array $installedHandlers - */ - public function activatePaymentMethods(array $paymentMethods, array $installedHandlers, Context $context): void - { - if (! empty($paymentMethods)) { - foreach ($paymentMethods as $paymentMethod) { - if ( - ! isset($paymentMethod['handler']) - || in_array($paymentMethod['handler'], $installedHandlers, true) - ) { - continue; - } - - $existingPaymentMethod = $this->getPaymentMethod($paymentMethod['handler'], $context); - - if (isset($existingPaymentMethod)) { - $this->setPaymentMethodActivated($existingPaymentMethod->getId(), true, $context); - } - } - } } public function disablePaymentMethod(string $handlerName, Context $context): void @@ -333,117 +68,6 @@ public function setPaymentMethodActivated(string $paymentMethodId, bool $active, ); } - /** - * Get payment method by ID. - * - * @param string $id - * - * @throws InconsistentCriteriaIdsException - */ - public function getPaymentMethodById($id): ?PaymentMethodEntity - { - // Fetch ID for update - $paymentCriteria = new Criteria(); - $paymentCriteria->addFilter(new EqualsFilter('id', $id)); - - // Get payment methods - $paymentMethods = $this->paymentRepository->getRepository()->search($paymentCriteria, Context::createDefaultContext()); - - if ($paymentMethods->getTotal() === 0) { - return null; - } - /** @var ?PaymentMethodEntity $paymentMethod */ - $paymentMethod = $paymentMethods->first(); - if ($paymentMethod === null) { - return null; - } - - return $paymentMethod; - } - - /** - * Get an array of installable payment methods for Mollie. - * - * @return array - */ - public function getInstallablePaymentMethods(): array - { - $installablePaymentMethods = $this->getPaymentHandlers(); - - if (count($installablePaymentMethods) <= 0) { - return []; - } - - $paymentMethods = []; - - foreach ($installablePaymentMethods as $installablePaymentMethod) { - $paymentMethods[] = [ - 'name' => constant($installablePaymentMethod . '::PAYMENT_METHOD_NAME'), - 'description' => constant($installablePaymentMethod . '::PAYMENT_METHOD_DESCRIPTION'), - 'handler' => $installablePaymentMethod, - ]; - } - - return $paymentMethods; - } - - /** - * Returns an array of payment handlers. - * - * @return array - */ - public function getPaymentHandlers(): array - { - $paymentHandlers = [ - ApplePayPayment::class, - BanContactPayment::class, - BankTransferPayment::class, - BilliePayment::class, - BelfiusPayment::class, - CreditCardPayment::class, - EpsPayment::class, - GiftCardPayment::class, - iDealPayment::class, - KbcPayment::class, - // GiroPayPayment::class, // not existing anymore - // KlarnaPayLaterPayment::class, // not existing anymore - // KlarnaPayNowPayment::class, // not existing anymore - // KlarnaSliceItPayment::class, // not existing anymore - KlarnaOnePayment::class, - PayPalPayment::class, - PaySafeCardPayment::class, - Przelewy24Payment::class, - // SofortPayment::class, // not existing anymore - VoucherPayment::class, - In3Payment::class, - PosPayment::class, - TwintPayment::class, - BlikPayment::class, - BancomatPayment::class, - MyBankPayment::class, - AlmaPayment::class, - TrustlyPayment::class, - // PayconiqPayment::class, // not existing anymore - RivertyPayment::class, - SatispayPayment::class, - PayByBankPayment::class, - MbWayPayment::class, - MultibancoPayment::class, - SwishPayment::class, - BizumPayment::class, - MobilePayPayment::class, - VippsPayment::class, - // IngHomePayPayment::class, // not allowed anymore - // DirectDebitPayment::class, // only allowed when updating subsriptions, aka => not allowed anymore - ]; - - if ($this->payPalExpressConfig->isEnabled()) { - $paymentHandlers[] = PayPalExpressPayment::class; - } - - return $paymentHandlers; - } - public function isPaidApplePayTransaction(OrderTransactionEntity $transaction, Order $mollieOrder): bool { $paymentMethodId = $transaction->getPaymentMethodId(); @@ -484,67 +108,4 @@ private function getPaymentMethod($handlerIdentifier, Context $context): ?Paymen return $paymentMethod; } - - /** - * Retrieve the icon from the database, or add it. - * - * @param array $paymentMethod - */ - private function getMediaId(array $paymentMethod, Context $context): ?string - { - $name = $paymentMethod['name']; - - if ($name === PayPalExpressPayment::PAYMENT_METHOD_NAME) { - $name = PayPalPayment::PAYMENT_METHOD_NAME; - } - - $fileName = $name . '-icon'; - - $criteria = new Criteria(); - $criteria->addFilter(new EqualsFilter('fileName', $fileName)); - - /** @var MediaCollection $icons */ - $icons = $this->mediaRepository->getRepository()->search($criteria, $context); - - if ($icons->count() && $icons->first() !== null) { - return $icons->first()->getId(); - } - - // Add icon to the media library - $iconMime = 'image/svg+xml'; - $iconExt = 'svg'; - $iconBlob = $this->downloadFile('https://www.mollie.com/external/icons/payment-methods/' . $paymentMethod['name'] . '.svg'); - - if ($iconBlob === '') { - $iconBlob = $this->downloadFile('https://www.mollie.com/external/icons/payment-methods/' . $paymentMethod['name'] . '.png'); - $iconMime = 'image/png'; - $iconExt = 'png'; - } - - if ($iconBlob === '') { - return null; - } - - return $this->mediaService->saveFile( - $iconBlob, - $iconExt, - $iconMime, - $fileName, - $context, - 'Mollie Payments - Icons', - null, - false - ); - } - - private function downloadFile(string $url): string - { - $response = $this->httpClient->sendRequest('GET', $url); - - if ($response->getStatusCode() < 200 || $response->getStatusCode() >= 300) { - return ''; - } - - return $response->getBody(); - } } diff --git a/src/Service/ProductService.php b/src/Service/ProductService.php deleted file mode 100644 index 884eaa2ec..000000000 --- a/src/Service/ProductService.php +++ /dev/null @@ -1,44 +0,0 @@ -> - */ - private $productRepository; - - /** - * @param EntityRepository> $productRepository - */ - public function __construct($productRepository) - { - $this->productRepository = $productRepository; - } - - /** - * Finds a product by id. - * - * @param string $productId - * - * @throws InconsistentCriteriaIdsException - */ - public function getProductById($productId, ?Context $context = null): ?ProductEntity - { - $criteria = new Criteria([$productId]); - - $result = $this->productRepository->search($criteria, $context ?? Context::createDefaultContext()); - - /** @var null|ProductEntity */ - return $result->get($productId); - } -} diff --git a/src/Service/Refund/RefundService.php b/src/Service/Refund/RefundService.php index f0dda377f..b197c39a1 100644 --- a/src/Service/Refund/RefundService.php +++ b/src/Service/Refund/RefundService.php @@ -179,7 +179,7 @@ public function cancel(OrderEntity $order, string $refundId): bool } // This payment does not have a refund with $refundId, so we cannot cancel it. - if (! ($refund instanceof Refund)) { + if (! $refund instanceof Refund) { return false; } diff --git a/src/Service/Router/RoutingBuilder.php b/src/Service/Router/RoutingBuilder.php index 2e10c5729..da7ce1874 100644 --- a/src/Service/Router/RoutingBuilder.php +++ b/src/Service/Router/RoutingBuilder.php @@ -12,13 +12,13 @@ class RoutingBuilder * This has to match the parameter from the Return Route annotations. * Otherwise, an exception is being thrown. */ - private const ROUTE_PARAM_RETURN_ID = 'swTransactionId'; + private const ROUTE_PARAM_RETURN_ID = 'transactionId'; /** * This has to match the parameter from the Webhook Route annotations. * Otherwise, an exception is being thrown. */ - private const ROUTE_PARAM_WEBHOOK_ID = 'swTransactionId'; + private const ROUTE_PARAM_WEBHOOK_ID = 'transactionId'; /** * This has to match the parameter from the Subscription Renewal Route annotations. diff --git a/src/Service/SettingsService.php b/src/Service/SettingsService.php index 14aa369ec..e9754c1e0 100644 --- a/src/Service/SettingsService.php +++ b/src/Service/SettingsService.php @@ -53,7 +53,6 @@ class SettingsService implements PluginSettingsServiceInterface * @var string */ private $envCypressMode; - private PayPalExpressConfig $payPalExpressConfig; /** * @var array @@ -63,7 +62,7 @@ class SettingsService implements PluginSettingsServiceInterface /** * @param EntityRepository> $repoSalesChannels */ - public function __construct(SystemConfigService $systemConfigService, $repoSalesChannels, PayPalExpressConfig $payPalExpressConfig, ?string $envShopDomain, ?string $envDevMode, ?string $envCypressMode) + public function __construct(SystemConfigService $systemConfigService, $repoSalesChannels, ?string $envShopDomain, ?string $envDevMode, ?string $envCypressMode) { $this->systemConfigService = $systemConfigService; $this->repoSalesChannels = $repoSalesChannels; @@ -71,7 +70,6 @@ public function __construct(SystemConfigService $systemConfigService, $repoSales $this->envShopDomain = (string) $envShopDomain; $this->envDevMode = (string) $envDevMode; $this->envCypressMode = (string) $envCypressMode; - $this->payPalExpressConfig = $payPalExpressConfig; } /** @@ -112,11 +110,6 @@ public function getSettings(?string $salesChannelId = null): MollieSettingStruct $structData[self::PAYMENT_FINALIZE_TRANSACTION_TIME] = $cartSettings[self::PAYMENT_FINALIZE_TRANSACTION_TIME] ?? 1800; } - /** - * TODO: remove this when we move to config - */ - $structData = $this->payPalExpressConfig->assign($structData); - $this->cachedStructs[$cacheKey] = (new MollieSettingStruct())->assign($structData); return $this->cachedStructs[$cacheKey]; diff --git a/src/Service/Tags/OrderTagService.php b/src/Service/Tags/OrderTagService.php index b0ce4a45e..147fab64c 100644 --- a/src/Service/Tags/OrderTagService.php +++ b/src/Service/Tags/OrderTagService.php @@ -3,9 +3,9 @@ namespace Kiener\MolliePayments\Service\Tags; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\SubscriptionEntity; use Kiener\MolliePayments\Service\Tags\Exceptions\CouldNotTagOrderException; use Kiener\MolliePayments\Struct\Tags\SubscriptionTag; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\SubscriptionEntity; use Shopware\Core\Checkout\Order\OrderEntity; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; diff --git a/src/Service/TransactionService.php b/src/Service/TransactionService.php index a72552d16..0e2dfc0fa 100644 --- a/src/Service/TransactionService.php +++ b/src/Service/TransactionService.php @@ -3,13 +3,16 @@ namespace Kiener\MolliePayments\Service; +use Mollie\Shopware\Component\Transaction\TransactionDataException; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionCollection; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity; +use Shopware\Core\Framework\Api\Context\SystemSource; use Shopware\Core\Framework\Context; use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection; use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository; use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenContainerEvent; use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria; +use Shopware\Core\Framework\DataAbstractionLayer\Search\EntitySearchResult; use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter; class TransactionService @@ -17,23 +20,19 @@ class TransactionService /** * @var EntityRepository> */ - private $orderTransactionRepository; + private EntityRepository $orderTransactionRepository; /** * Creates a new instance of the transaction service. * * @param EntityRepository> $orderTransactionRepository */ - public function __construct($orderTransactionRepository) + public function __construct(EntityRepository $orderTransactionRepository) { $this->orderTransactionRepository = $orderTransactionRepository; } - /** - * @param string $transactionId - * @param null|string $versionId - */ - public function getTransactionById($transactionId, $versionId = null, ?Context $context = null): ?OrderTransactionEntity + public function getTransactionById(string $transactionId,?string $versionId = null, ?Context $context = null): OrderTransactionEntity { $transactionCriteria = new Criteria(); $transactionCriteria->addFilter(new EqualsFilter('id', $transactionId)); @@ -46,17 +45,22 @@ public function getTransactionById($transactionId, $versionId = null, ?Context $ $transactionCriteria->addAssociation('order.lineItems'); $transactionCriteria->addAssociation('order.stateMachineState'); - /** @var OrderTransactionCollection $transactions */ + /** @var EntitySearchResult> $transactions */ $transactions = $this->orderTransactionRepository->search( $transactionCriteria, - $context ?? Context::createDefaultContext() + $context ?? new Context(new SystemSource()), ); if ($transactions->count() === 0) { - return null; + throw TransactionDataException::transactionNotFound($transactionId); + } + + $transaction = $transactions->first(); + if ($transaction === null) { + throw TransactionDataException::transactionNotFound($transactionId); } - return $transactions->first(); + return $transaction; } /** diff --git a/src/Service/Transition/TransactionTransitionService.php b/src/Service/Transition/TransactionTransitionService.php index 04e6e9bcb..65467328c 100644 --- a/src/Service/Transition/TransactionTransitionService.php +++ b/src/Service/Transition/TransactionTransitionService.php @@ -7,7 +7,6 @@ use Psr\Log\LoggerInterface; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionDefinition; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity; -use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStateHandler; use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates; use Shopware\Core\Checkout\Payment\PaymentMethodEntity; use Shopware\Core\Framework\Context; @@ -25,22 +24,23 @@ class TransactionTransitionService implements TransactionTransitionServiceInterf * @var LoggerInterface */ private $logger; - private OrderTransactionStateHandler $orderTransactionStateHandler; public function __construct( TransitionServiceInterface $transitionService, - OrderTransactionStateHandler $orderTransactionStateHandler, LoggerInterface $loggerService ) { $this->transitionService = $transitionService; $this->logger = $loggerService; - $this->orderTransactionStateHandler = $orderTransactionStateHandler; } public function processTransaction(OrderTransactionEntity $transaction, Context $context): void { - $method = 'process'; - + $technicalName = ($transaction->getStateMachineState() instanceof StateMachineStateEntity) ? $transaction->getStateMachineState()->getTechnicalName() : ''; + $defaultState = OrderTransactionStates::STATE_IN_PROGRESS; + $action = StateMachineTransitionActions::ACTION_PROCESS; + if (defined(StateMachineTransitionActions::ACTION_DO_PAY)) { + $action = StateMachineTransitionActions::ACTION_DO_PAY; + } $paymentMethod = $transaction->getPaymentMethod(); $isBankTransfer = false; if ($paymentMethod === null) { @@ -50,14 +50,26 @@ public function processTransaction(OrderTransactionEntity $transaction, Context if ($paymentMethod instanceof PaymentMethodEntity) { /** @phpstan-ignore-next-line */ $reflectionClass = new \ReflectionClass($paymentMethod->getHandlerIdentifier()); + $isBankTransfer = $reflectionClass->implementsInterface(BankTransfer::class); } - if (defined('\Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates::STATE_UNCONFIRMED') && ! $isBankTransfer) { - $method = 'processUnconfirmed'; + $defaultState = OrderTransactionStates::STATE_UNCONFIRMED; + $action = StateMachineTransitionActions::ACTION_PROCESS_UNCONFIRMED; + } + + if ($this->isFinalOrTargetStatus($technicalName, [$defaultState])) { + return; + } + + $entityId = $transaction->getId(); + $availableTransitions = $this->getAvailableTransitions($entityId, $context); + + if (! $this->transitionIsAllowed($action, $availableTransitions)) { + $this->reOpenTransaction($transaction, $context); } - $this->orderTransactionStateHandler->{$method}($transaction->getId(), $context); + $this->performTransition($entityId, $action, $context); } public function reOpenTransaction(OrderTransactionEntity $transaction, Context $context): void diff --git a/src/Setting/MollieSettingStruct.php b/src/Setting/MollieSettingStruct.php index c8b6936b8..1c3c48a0e 100644 --- a/src/Setting/MollieSettingStruct.php +++ b/src/Setting/MollieSettingStruct.php @@ -3,7 +3,6 @@ namespace Kiener\MolliePayments\Setting; -use Kiener\MolliePayments\Handler\Method\BankTransferPayment; use Shopware\Core\Framework\Struct\Struct; class MollieSettingStruct extends Struct @@ -476,10 +475,10 @@ public function getPaymentMethodBankTransferDueDateDays(): ?int return min( max( - BankTransferPayment::DUE_DATE_MIN_DAYS, + 1, $this->paymentMethodBankTransferDueDateDays ), - BankTransferPayment::DUE_DATE_MAX_DAYS + 100 ); } diff --git a/src/Struct/LineItem/LineItemAttributes.php b/src/Struct/LineItem/LineItemAttributes.php index 7eee8a31f..8a5ff65bb 100644 --- a/src/Struct/LineItem/LineItemAttributes.php +++ b/src/Struct/LineItem/LineItemAttributes.php @@ -13,11 +13,6 @@ class LineItemAttributes */ private $productNumber; - /** - * @var string - */ - private $voucherType; - /** * @var bool */ @@ -51,7 +46,6 @@ class LineItemAttributes public function __construct(LineItem $lineItem) { $this->productNumber = ''; - $this->voucherType = ''; $payload = $lineItem->getPayload(); @@ -61,8 +55,6 @@ public function __construct(LineItem $lineItem) $this->isPromotionProduct = array_key_exists('promotionId', $payload); - $this->voucherType = $this->getCustomFieldValue($lineItem, 'voucher_type'); - $this->subscriptionProduct = (bool) $this->getCustomFieldValue($lineItem, 'subscription_enabled'); $this->subscriptionInterval = (int) $this->getCustomFieldValue($lineItem, 'subscription_interval'); $this->subscriptionIntervalUnit = $this->getCustomFieldValue($lineItem, 'subscription_interval_unit'); @@ -76,7 +68,6 @@ public function __construct(LineItem $lineItem) public static function getKeyList(): array { return [ - 'mollie_payments_product_voucher_type', 'mollie_payments_product_subscription_enabled', 'mollie_payments_product_subscription_interval', 'mollie_payments_product_subscription_interval_unit', @@ -95,16 +86,6 @@ public function isPromotionProduct(): bool return $this->isPromotionProduct; } - public function getVoucherType(): string - { - return $this->voucherType; - } - - public function setVoucherType(string $voucherType): void - { - $this->voucherType = $voucherType; - } - public function isSubscriptionProduct(): bool { return $this->subscriptionProduct; @@ -155,9 +136,6 @@ public function toArray(): array // lets save some space and only store // what is existing - if ($this->voucherType !== null) { - $mollieData[$prefix . 'voucher_type'] = $this->voucherType; - } // only save if it's a subscription product if ($this->subscriptionProduct) { @@ -183,9 +161,12 @@ public function toArray(): array return $mollieData; } - private function getCustomFieldValue(LineItem $lineItem, string $keyName): string + /** + * @return mixed|string + */ + private function getCustomFieldValue(LineItem $lineItem, string $keyName) { - $foundValue = ''; + $foundValue = null; if (count($lineItem->getPayload()) > 0) { // check if we have customFields in our payload diff --git a/src/Struct/OrderLineItemEntity/OrderLineItemEntityAttributes.php b/src/Struct/OrderLineItemEntity/OrderLineItemEntityAttributes.php index 041792f1d..c30abdfcf 100644 --- a/src/Struct/OrderLineItemEntity/OrderLineItemEntityAttributes.php +++ b/src/Struct/OrderLineItemEntity/OrderLineItemEntityAttributes.php @@ -4,7 +4,6 @@ namespace Kiener\MolliePayments\Struct\OrderLineItemEntity; use Kiener\MolliePayments\Service\CustomFieldsInterface; -use Kiener\MolliePayments\Struct\Voucher\VoucherType; use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity; class OrderLineItemEntityAttributes @@ -19,11 +18,6 @@ class OrderLineItemEntityAttributes */ private $productNumber; - /** - * @var string - */ - private $voucherType; - /** * @var bool */ @@ -66,7 +60,6 @@ public function __construct(OrderLineItemEntity $lineItem) $this->productNumber = (string) $payload['productNumber']; } - $this->voucherType = $this->getCustomFieldValue($lineItem, 'voucher_type'); $this->mollieOrderLineID = $this->getCustomFieldValue($lineItem, 'order_line_id'); $this->isPromotionProduct = $lineItem->getType() === 'promotion'; @@ -82,25 +75,6 @@ public function getProductNumber(): string return (string) $this->productNumber; } - /** - * @return string - */ - public function getVoucherType() - { - $availableTypes = [ - VoucherType::TYPE_NONE, - VoucherType::TYPE_ECO, - VoucherType::TYPE_MEAL, - VoucherType::TYPE_GIFT, - ]; - - if (! in_array($this->voucherType, $availableTypes)) { - return VoucherType::TYPE_NOTSET; - } - - return $this->voucherType; - } - public function getMollieOrderLineID(): string { return $this->mollieOrderLineID; diff --git a/src/Struct/PaymentMethod/PaymentMethodAttributes.php b/src/Struct/PaymentMethod/PaymentMethodAttributes.php index 3c04faeb7..bebb569dd 100644 --- a/src/Struct/PaymentMethod/PaymentMethodAttributes.php +++ b/src/Struct/PaymentMethod/PaymentMethodAttributes.php @@ -3,12 +3,11 @@ namespace Kiener\MolliePayments\Struct\PaymentMethod; -use Kiener\MolliePayments\Handler\Method\VoucherPayment; use Shopware\Core\Checkout\Payment\PaymentMethodEntity; class PaymentMethodAttributes { - public const MOLLIE_PAYMENT_HANDLER_NAMESPACE = 'Kiener\MolliePayments\Handler\Method'; + public const MOLLIE_PAYMENT_HANDLER_NAMESPACE = 'Mollie\Shopware\Component\Payment\Method'; /** * @var string @@ -20,11 +19,6 @@ public function __construct(PaymentMethodEntity $paymentMethod) $this->handlerIdentifier = (string) $paymentMethod->getHandlerIdentifier(); } - public function isVoucherMethod(): bool - { - return $this->handlerIdentifier === VoucherPayment::class; - } - public function isMolliePayment(): bool { $pattern = sprintf( diff --git a/src/Struct/Product/ProductAttributes.php b/src/Struct/Product/ProductAttributes.php index 6d69fd764..ffa54657b 100644 --- a/src/Struct/Product/ProductAttributes.php +++ b/src/Struct/Product/ProductAttributes.php @@ -3,7 +3,6 @@ namespace Kiener\MolliePayments\Struct\Product; -use Kiener\MolliePayments\Struct\Voucher\VoucherType; use Shopware\Core\Content\Product\ProductEntity; class ProductAttributes @@ -43,25 +42,6 @@ public function __construct(ProductEntity $product) $this->subscriptionRepetitionCount = $this->getCustomFieldValue($product, 'subscription_repetition'); } - /** - * @return string - */ - public function getVoucherType() - { - $availableTypes = [ - VoucherType::TYPE_NONE, - VoucherType::TYPE_ECO, - VoucherType::TYPE_MEAL, - VoucherType::TYPE_GIFT, - ]; - - if (! in_array($this->voucherType, $availableTypes)) { - return VoucherType::TYPE_NOTSET; - } - - return (string) $this->voucherType; - } - public function isSubscriptionProduct(): bool { return (bool) $this->subscriptionProduct; diff --git a/src/Struct/Voucher/VoucherType.php b/src/Struct/Voucher/VoucherType.php deleted file mode 100644 index 51efb120e..000000000 --- a/src/Struct/Voucher/VoucherType.php +++ /dev/null @@ -1,30 +0,0 @@ -applePay = $applePay; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ StorefrontRenderEvent::class => 'onStorefrontRender', diff --git a/src/Subscriber/ApplePaySubscriber.php b/src/Subscriber/ApplePaySubscriber.php index 49058a8ed..e06ea4e83 100644 --- a/src/Subscriber/ApplePaySubscriber.php +++ b/src/Subscriber/ApplePaySubscriber.php @@ -19,7 +19,7 @@ public function __construct(ApplePayDirect $applePay) $this->applePay = $applePay; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ StorefrontRenderEvent::class => 'onStorefrontRender', diff --git a/src/Subscriber/CartConvertedSubscriber.php b/src/Subscriber/CartConvertedSubscriber.php index 5eadd7fc7..1e8b0a36b 100644 --- a/src/Subscriber/CartConvertedSubscriber.php +++ b/src/Subscriber/CartConvertedSubscriber.php @@ -10,7 +10,7 @@ final class CartConvertedSubscriber implements EventSubscriberInterface { - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ CartConvertedEvent::class => 'savePayPalExpressData', @@ -21,7 +21,7 @@ public function savePayPalExpressData(CartConvertedEvent $event): void { $cart = $event->getCart(); $cartExtension = $cart->getExtension(CustomFieldsInterface::MOLLIE_KEY); - if (! ($cartExtension instanceof ArrayStruct)) { + if (! $cartExtension instanceof ArrayStruct) { return; } $paypalExpressAuthenticateId = $cartExtension[CustomFieldsInterface::PAYPAL_EXPRESS_AUTHENTICATE_ID] ?? null; diff --git a/src/Subscriber/CheckoutConfirmPageSubscriber.php b/src/Subscriber/CheckoutConfirmPageSubscriber.php index 135fe9d23..d9ee02ce6 100644 --- a/src/Subscriber/CheckoutConfirmPageSubscriber.php +++ b/src/Subscriber/CheckoutConfirmPageSubscriber.php @@ -94,6 +94,7 @@ public function addDataToPage($args): void $scId = $args->getSalesChannelContext()->getSalesChannel()->getId(); $currentSelectedPaymentMethod = $args->getSalesChannelContext()->getPaymentMethod(); + $mollieAttributes = new PaymentMethodAttributes($currentSelectedPaymentMethod); // load additional data only for mollie payment methods diff --git a/src/Subscriber/CsrfSubscriber.php b/src/Subscriber/CsrfSubscriber.php index 2c2371e5c..b5f834e31 100644 --- a/src/Subscriber/CsrfSubscriber.php +++ b/src/Subscriber/CsrfSubscriber.php @@ -19,7 +19,7 @@ public function __construct(string $shopwareVersion) $this->versionCompare = new VersionCompare($shopwareVersion); } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ StorefrontRenderEvent::class => 'onStorefrontRender', diff --git a/src/Subscriber/KernelSubscriber.php b/src/Subscriber/KernelSubscriber.php index 00142d09d..c9a066c25 100644 --- a/src/Subscriber/KernelSubscriber.php +++ b/src/Subscriber/KernelSubscriber.php @@ -5,6 +5,7 @@ use Kiener\MolliePayments\Compatibility\VersionCompare; use Shopware\Core\Framework\Routing\Annotation\RouteScope; +use Shopware\Core\Framework\Routing\KernelListenerPriorities; use Shopware\Core\PlatformRequest; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\ControllerEvent; @@ -25,7 +26,7 @@ public function __construct(VersionCompare $versionCompare) public static function getSubscribedEvents(): array { return [ - KernelEvents::CONTROLLER => 'onModifyRouteScope', + KernelEvents::CONTROLLER => ['onModifyRouteScope', KernelListenerPriorities::KERNEL_CONTROLLER_EVENT_SCOPE_VALIDATE_PRE], ]; } @@ -51,11 +52,13 @@ public function onModifyRouteScope(ControllerEvent $event): void if ($routeScope === null) { return; } + if ($routeScope instanceof RouteScope) { return; } $routeScope = new RouteScope(['scopes' => $routeScope]); + $attributes->set(PlatformRequest::ATTRIBUTE_ROUTE_SCOPE, $routeScope); } } diff --git a/src/Subscriber/MandatesSubscriber.php b/src/Subscriber/MandatesSubscriber.php index 8d6101add..47abb2034 100644 --- a/src/Subscriber/MandatesSubscriber.php +++ b/src/Subscriber/MandatesSubscriber.php @@ -41,7 +41,7 @@ public function __construct( public static function getSubscribedEvents(): array { return [ - StorefrontRenderEvent::class => ['addDataToPage', 10], + // StorefrontRenderEvent::class => ['addDataToPage', 10], ]; } diff --git a/src/Subscriber/OrderLinesUpdatedSubscriber.php b/src/Subscriber/OrderLinesUpdatedSubscriber.php index 5decb1010..7a4cba84d 100644 --- a/src/Subscriber/OrderLinesUpdatedSubscriber.php +++ b/src/Subscriber/OrderLinesUpdatedSubscriber.php @@ -18,7 +18,7 @@ public function __construct(LoggerInterface $logger) $this->logger = $logger; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ OrderLinesUpdatedEvent::class => 'onOrderLinesUpdated', diff --git a/src/Subscriber/OrderReturnSubscriber.php b/src/Subscriber/OrderReturnSubscriber.php index bbfc0f5ee..4666b2e9f 100644 --- a/src/Subscriber/OrderReturnSubscriber.php +++ b/src/Subscriber/OrderReturnSubscriber.php @@ -16,7 +16,7 @@ public function __construct(OrderReturnHandler $orderReturnHandler) $this->orderReturnHandler = $orderReturnHandler; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ 'state_enter.order_return.state.done' => ['onOrderReturnFinished', 10], diff --git a/src/Subscriber/PaypalExpressSubscriber.php b/src/Subscriber/PaypalExpressSubscriber.php index 6064a051e..517336a7c 100644 --- a/src/Subscriber/PaypalExpressSubscriber.php +++ b/src/Subscriber/PaypalExpressSubscriber.php @@ -5,10 +5,10 @@ use Kiener\MolliePayments\Components\PaypalExpress\PayPalExpress; use Kiener\MolliePayments\Handler\Method\PayPalExpressPayment; -use Kiener\MolliePayments\Service\Cart\CartBackupService; use Kiener\MolliePayments\Service\CartServiceInterface; use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Traits\StringTrait; +use Mollie\Shopware\Component\Payment\ExpressMethod\CartBackupService; use Mollie\Shopware\Entity\Cart\MollieShopwareCart; use Mollie\Shopware\Entity\Order\MollieShopwareOrder; use Shopware\Core\Checkout\Cart\SalesChannel\CartService; @@ -58,7 +58,7 @@ public function __construct(SettingsService $settingsService, PayPalExpress $pay $this->mollieCartService = $mollieCartService; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ StorefrontRenderEvent::class => 'onStorefrontRender', diff --git a/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php b/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php index e1c8b4f36..4358d41c7 100644 --- a/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php +++ b/src/Subscriber/SalesChannelContextTokenChangedSubscriber.php @@ -3,7 +3,7 @@ namespace Kiener\MolliePayments\Subscriber; -use Kiener\MolliePayments\Service\Cart\CartBackupService; +use Mollie\Shopware\Component\Payment\ExpressMethod\CartBackupService; use Shopware\Core\System\SalesChannel\Event\SalesChannelContextTokenChangeEvent; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -19,7 +19,7 @@ public function __construct(CartBackupService $cartBackupService) $this->cartBackupService = $cartBackupService; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ SalesChannelContextTokenChangeEvent::class => 'onTokenChange', diff --git a/src/Subscriber/StorefrontBuildSubscriber.php b/src/Subscriber/StorefrontBuildSubscriber.php index 4f14d0ea3..7ab20d6a8 100644 --- a/src/Subscriber/StorefrontBuildSubscriber.php +++ b/src/Subscriber/StorefrontBuildSubscriber.php @@ -38,7 +38,7 @@ public function __construct(SettingsService $settingsService, $pluginRegistry, V $this->versionCompare = $versionCompare; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ StorefrontRenderEvent::class => 'onStorefrontRender', diff --git a/src/Subscriber/SubscriptionSubscriber.php b/src/Subscriber/SubscriptionSubscriber.php index 1d4fd31be..a6725a13f 100644 --- a/src/Subscriber/SubscriptionSubscriber.php +++ b/src/Subscriber/SubscriptionSubscriber.php @@ -3,12 +3,12 @@ namespace Kiener\MolliePayments\Subscriber; -use Kiener\MolliePayments\Components\Subscription\DAL\Subscription\Struct\IntervalType; use Kiener\MolliePayments\Service\SettingsService; use Kiener\MolliePayments\Storefront\Struct\SubscriptionCartExtensionStruct; use Kiener\MolliePayments\Storefront\Struct\SubscriptionDataExtensionStruct; use Kiener\MolliePayments\Struct\LineItem\LineItemAttributes; use Kiener\MolliePayments\Struct\Product\ProductAttributes; +use Mollie\Shopware\Component\Subscription\DAL\Subscription\Struct\IntervalType; use Shopware\Core\Checkout\Cart\Event\CartBeforeSerializationEvent; use Shopware\Storefront\Event\StorefrontRenderEvent; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPage; @@ -40,7 +40,7 @@ public function __construct(SettingsService $settingsService, TranslatorInterfac /** * @return string[] */ - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ CartBeforeSerializationEvent::class => 'onBeforeSerializeCart', diff --git a/src/Subscriber/SystemConfigSubscriber.php b/src/Subscriber/SystemConfigSubscriber.php index 54b0438b9..253ac1ade 100644 --- a/src/Subscriber/SystemConfigSubscriber.php +++ b/src/Subscriber/SystemConfigSubscriber.php @@ -36,7 +36,7 @@ public function __construct(SettingsService $settingsService, LoggerInterface $l $this->apiClient = new MollieApiClient(); } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ 'system_config.written' => 'onSystemConfigWritten', diff --git a/src/Subscriber/TestModeNotificationSubscriber.php b/src/Subscriber/TestModeNotificationSubscriber.php index ee6591767..3a7e19bad 100644 --- a/src/Subscriber/TestModeNotificationSubscriber.php +++ b/src/Subscriber/TestModeNotificationSubscriber.php @@ -7,7 +7,6 @@ use Kiener\MolliePayments\Storefront\Struct\TestModePageExtensionStruct; use Shopware\Storefront\Page\Account\Order\AccountEditOrderPageLoadedEvent; use Shopware\Storefront\Page\Account\Overview\AccountOverviewPageLoadedEvent; -use Shopware\Storefront\Page\Account\PaymentMethod\AccountPaymentMethodPageLoadedEvent; use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent; use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent; use Shopware\Storefront\Page\PageLoadedEvent; @@ -27,12 +26,10 @@ public function __construct( $this->settingsService = $settingsService; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ AccountOverviewPageLoadedEvent::class => 'addTestModeInformationToPages', - /** @phpstan-ignore class.notFound */ - AccountPaymentMethodPageLoadedEvent::class => 'addTestModeInformationToPages', AccountEditOrderPageLoadedEvent::class => 'addTestModeInformationToPages', CheckoutConfirmPageLoadedEvent::class => 'addTestModeInformationToPages', CheckoutFinishPageLoadedEvent::class => 'addTestModeInformationToPages', diff --git a/src/Subscriber/WebhookTimezoneSubscriber.php b/src/Subscriber/WebhookTimezoneSubscriber.php index c8785a838..3585e9291 100644 --- a/src/Subscriber/WebhookTimezoneSubscriber.php +++ b/src/Subscriber/WebhookTimezoneSubscriber.php @@ -39,7 +39,7 @@ public function __construct(TransactionService $transactionService, RoutingDetec $this->logger = $logger; } - public static function getSubscribedEvents() + public static function getSubscribedEvents(): array { return [ // Route gets matched in a subscriber with priority 32, so we need to have a lower priority than that. diff --git a/tests/Behat/Context/BootstrapContext.php b/tests/Behat/Context/BootstrapContext.php index 9f8f353f5..9ccb814e9 100644 --- a/tests/Behat/Context/BootstrapContext.php +++ b/tests/Behat/Context/BootstrapContext.php @@ -1,12 +1,18 @@ getContainer()->get(SettingsService::class); + $settingsService->clearCache(); + + Storage::clear(); + } +} diff --git a/tests/Behat/Context/CheckoutContext.php b/tests/Behat/Context/CheckoutContext.php index f11ab8ff4..fa56d6bfe 100644 --- a/tests/Behat/Context/CheckoutContext.php +++ b/tests/Behat/Context/CheckoutContext.php @@ -1,30 +1,41 @@ addItemToCart($productNumber, $salesChannelContext, $quantity); } - #[When('i start checkout with payment method :arg1')] public function iStartCheckoutWithPaymentMethod(string $paymentMethodTechnicalName): void { + $paymentMethod = $this->getPaymentMethodByTechnicalName($paymentMethodTechnicalName, $this->getCurrentSalesChannelContext()->getContext()); - $salesChannelContext = $this->getCurrentSalesChannelContext(); - $paymentMethod = $this->getPaymentMethodByTechnicalName($paymentMethodTechnicalName, $salesChannelContext->getContext()); - $this->setOptions(SalesChannelContextService::PAYMENT_METHOD_ID, $paymentMethod->getId()); - - /** @var RedirectResponse $response */ - $response = $this->startCheckout($this->getCurrentSalesChannelContext()); + $this->setOptions(SalesChannelContextService::PAYMENT_METHOD_ID, $paymentMethod->getId()); - $this->mollieSandboxPage = $response->getTargetUrl(); - - Assert::assertStringContainsString('mollie.com', $this->mollieSandboxPage); + /** @var RedirectResponse $response */ + $response = $this->startCheckout($this->getCurrentSalesChannelContext()); + $mollieSandboxPage = $response->getTargetUrl(); + Storage::set(self::STORAGE_MOLLIE_URL, $mollieSandboxPage); + Assert::assertStringContainsString('mollie.com', $mollieSandboxPage); } - - #[When('select payment status :arg1')] public function selectPaymentStatus(string $selectedStatus): void { - $response = $this->selectMolliePaymentStatus($selectedStatus, $this->mollieSandboxPage); + $mollieUrl = Storage::get(self::STORAGE_MOLLIE_URL); + $molliePage = new MolliePage($mollieUrl); + $response = $molliePage->selectPaymentStatus($selectedStatus); + Assert::assertSame($response->getStatusCode(), 302); + $redirect = $response->getHeaderLine('location'); + + if (str_contains($redirect, 'mollie.com')) { + Storage::set(self::STORAGE_MOLLIE_URL, $redirect); + + return; + } + Storage::set(self::STORAGE_RETURN_URL, $redirect); + } + + #[When('i select issuer :arg1')] + public function iSelectIssuer(string $issuer): void + { + $mollieUrl = Storage::get(self::STORAGE_MOLLIE_URL); + $molliePage = new MolliePage($mollieUrl); + $response = $molliePage->selectIssuer($issuer); + Assert::assertSame($response->getStatusCode(), 302); - $this->shopwareReturnPage = $response->getHeaderLine('location'); - Assert::assertStringContainsString('mollie/payment', $this->shopwareReturnPage); + $mollieUrl = $response->getHeaderLine('location'); + Storage::set(self::STORAGE_MOLLIE_URL, $mollieUrl); + Assert::assertStringContainsString('mollie.com', $mollieUrl); } #[Given('i select :art1 as currency')] public function iSelectAsCurrency(string $currency): void { - $currency = $this->findCurrencyByIso($currency,$this->getCurrentSalesChannelContext()); + $currency = $this->findCurrencyByIso($currency, $this->getCurrentSalesChannelContext()); $this->setOptions(SalesChannelContextService::CURRENCY_ID, $currency->getId()); } #[Then('i see success page')] public function iSeeSuccessPage(): void { - $this->shopwareOderId = ''; + $returnPage = Storage::get(self::STORAGE_RETURN_URL, ''); + if (strlen($returnPage) === 0) { + $mollieUrl = Storage::get(self::STORAGE_MOLLIE_URL); + $molliePage = new MolliePage($mollieUrl); + $returnPage = $molliePage->getShopwareReturnPage(); + Storage::set(self::STORAGE_RETURN_URL, $returnPage); + } + Assert::assertStringContainsString('mollie/', $returnPage); /** @var RedirectResponse $response */ - $response = $this->finishCheckout($this->shopwareReturnPage, $this->getCurrentSalesChannelContext()); - $this->shopwareOderId = str_replace('/checkout/finish?orderId=','',$response->getTargetUrl()); + $response = $this->finishCheckout($returnPage, $this->getCurrentSalesChannelContext()); + $shopwareOderId = str_replace('/checkout/finish?orderId=', '', $response->getTargetUrl()); Assert::assertSame($response->getStatusCode(), 302); - Assert::assertStringContainsString('/checkout/finish', $response->getTargetUrl()); - Assert::assertNotEmpty($this->shopwareOderId); + Assert::assertNotEmpty($shopwareOderId); + Storage::set(self::STORAGE_ORDER_ID,$shopwareOderId); + } + + #[When('select mollie payment method :arg1')] + public function selectMolliePaymentMethod(string $molliePaymentMethod): void + { + $mollieUrl = Storage::get(self::STORAGE_MOLLIE_URL); + $molliePage = new MolliePage($mollieUrl); + $response = $molliePage->selectPaymentMethod($molliePaymentMethod); + + Assert::assertSame($response->getStatusCode(), 302); + $mollieUrl = $response->getHeaderLine('location'); + Assert::assertStringContainsString('mollie.com', $mollieUrl); + Storage::set(self::STORAGE_MOLLIE_URL, $mollieUrl); } #[Then('order payment status is :arg1')] public function orderPaymentStatusIs(string $expectedPaymentStatus): void { - $order = $this->getOrderById($this->shopwareOderId,$this->getCurrentSalesChannelContext()); + $orderId = Storage::get(self::STORAGE_ORDER_ID); + $order = $this->getOrderById($orderId, $this->getCurrentSalesChannelContext()); /** @var OrderTransactionEntity $oderTransaction */ $oderTransaction = $order->getTransactions()->first(); $actualOrderState = $oderTransaction->getStateMachineState()->getTechnicalName(); + Assert::assertSame($expectedPaymentStatus, $actualOrderState); } -} \ No newline at end of file + + #[When('i select delivery status action :arg1')] + public function iSelectDeliveryStatusAction(string $targetStatus): void + { + /** @var OrderActionController $orderActionController */ + $orderActionController = $this->getContainer()->get(OrderActionController::class); + /** @var CachedMollieGateway $mollieGateway */ + $mollieGateway = $this->getContainer()->get(MollieGateway::class); + $mollieGateway->clearCache(); + $orderId = Storage::get(self::STORAGE_ORDER_ID); + $order = $this->getOrderById($orderId, $this->getCurrentSalesChannelContext()); + $firstDelivery = $order->getDeliveries()->first(); + $orderDeliveryId = $firstDelivery->getId(); + $request = new Request(); + $request->request->set('sendMail', false); + + $response = $orderActionController->orderDeliveryStateTransition($orderDeliveryId, $targetStatus, $request, $this->getCurrentSalesChannelContext()->getContext()); + } + + #[When('i ship line item :arg1 with quantity :arg2')] + public function iShipLineItemWithQuantity(string $productNumber, int $quantity): void + { + /** @var ShipOrderRoute $shipOrderRoute */ + $shipOrderRoute = $this->getContainer()->get(ShipOrderRoute::class); + /** @var CachedMollieGateway $mollieGateway */ + $mollieGateway = $this->getContainer()->get(MollieGateway::class); + $mollieGateway->clearCache(); + + $items = [ + [ + 'id' => $productNumber, + 'quantity' => $quantity, + ], + ]; + $orderId = Storage::get(self::STORAGE_ORDER_ID); + $request = new Request(); + $request->request->set('orderId', $orderId); + $request->request->set('items', $items); + + $shipOrderRoute->ship($request, $this->getCurrentSalesChannelContext()->getContext()); + } + + #[Then('delivery status is :arg1')] + public function deliveryStatusIs(string $expectedDeliveryStatus): void + { + $orderId = Storage::get(self::STORAGE_ORDER_ID); + $order = $this->getOrderById($orderId, $this->getCurrentSalesChannelContext()); + /** @var OrderDeliveryEntity $orderDelivery */ + $orderDelivery = $order->getDeliveries()->first(); + $actualDeliveryStatus = $orderDelivery->getStateMachineState()->getTechnicalName(); + + Assert::assertSame($expectedDeliveryStatus, $actualDeliveryStatus); + } +} diff --git a/tests/Behat/Context/CustomerContext.php b/tests/Behat/Context/CustomerContext.php index 632b9f32e..a7b514cfe 100644 --- a/tests/Behat/Context/CustomerContext.php +++ b/tests/Behat/Context/CustomerContext.php @@ -1,35 +1,31 @@ loginOrCreateAccount($email, $this->getCurrentSalesChannelContext()); + $customerId = $this->getUserIdByEmail($email, $this->getCurrentSalesChannelContext()); $this->setOptions(SalesChannelContextService::CUSTOMER_ID,$customerId); } - #[Given('i select :arg1 as billing country')] public function iSelectAsBillingCountry(string $billingCountry): void { $salesChannelContext = $this->getCurrentSalesChannelContext(); $addressIdSearchResult = $this->getUserAddressByIso($billingCountry, $salesChannelContext); $addressId = $addressIdSearchResult->firstId(); + $this->setOptions(SalesChannelContextService::BILLING_ADDRESS_ID,$addressId); $this->setOptions(SalesChannelContextService::SHIPPING_ADDRESS_ID,$addressId); } -} \ No newline at end of file +} diff --git a/tests/Behat/Context/PaymentContext.php b/tests/Behat/Context/PaymentContext.php index 16162700e..feb00214a 100644 --- a/tests/Behat/Context/PaymentContext.php +++ b/tests/Behat/Context/PaymentContext.php @@ -1,15 +1,12 @@ assignPaymentMethodToSalesChannel($paymentMethod, $salesChannelContext->getSalesChannel(), $salesChannelContext->getContext()); } + #[Given('plugin configuration :arg1 is set to :arg2')] + public function pluginConfigurationIsSetTo(string $configKey, string $configValue): void + { + /** + * @var SystemConfigService $systemConfigService + */ + $systemConfigService = $this->getContainer()->get(SystemConfigService::class); + + if ($configValue === 'true') { + $configValue = true; + } + if ($configValue === 'false') { + $configValue = false; + } + if (is_numeric($configValue)) { + $configValue = (float) $configValue; + } + if (is_int($configValue)) { + $configValue = (int) $configValue; + } -} \ No newline at end of file + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . $configKey, $configValue); + } +} diff --git a/tests/Behat/Context/ShopwareContext.php b/tests/Behat/Context/ShopwareContext.php index 8d153f446..6cdf34b9b 100644 --- a/tests/Behat/Context/ShopwareContext.php +++ b/tests/Behat/Context/ShopwareContext.php @@ -1,9 +1,10 @@ getDefaultSalesChannelContext('',self::$options); } + return self::$salesChannelContext; } + public function setOptions(string $key, $value): void { self::$salesChannelContext = null; - if($value === null){ + if ($value === null) { unset(self::$options[$key]); + return; } self::$options[$key] = $value; } + public function getOptions(): array { return self::$options; } -} \ No newline at end of file +} diff --git a/tests/Behat/Context/SubscriptionContext.php b/tests/Behat/Context/SubscriptionContext.php new file mode 100644 index 000000000..58399473f --- /dev/null +++ b/tests/Behat/Context/SubscriptionContext.php @@ -0,0 +1,42 @@ +getCurrentSalesChannelContext()->getContext(); + /** @var SubscriptionActionHandler $actionHandler */ + $actionHandler = $this->getContainer()->get(SubscriptionActionHandler::class); + $actionHandler->handle($action,$subscription->getId(),$context); + } + + #[Then('the subscription status is :arg1')] + public function theSubscriptionStatusIs(string $status): void + { + $orderId = Storage::get('orderId'); + $context = $this->getCurrentSalesChannelContext()->getContext(); + + $subscription = $this->getSubscriptionByOrderId($orderId, $context); + + Storage::set(self::STORAGE_SUBSCRIPTION, $subscription); + + Assert::assertSame($status, $subscription->getStatus()); + } +} diff --git a/tests/Behat/Features/payment.feature b/tests/Behat/Features/payment.feature index 70dfbe015..2b00c95f6 100644 --- a/tests/Behat/Features/payment.feature +++ b/tests/Behat/Features/payment.feature @@ -1,9 +1,10 @@ +@core @payment Feature: Basic payment checkout In order to use payment methods As a customer Background: - Given iam logged in as user "test@mollie.com" + Given iam logged in as user "cypress@mollie.com" Scenario Outline: payment success Given payment method "" exists and active @@ -17,23 +18,91 @@ Feature: Basic payment checkout Examples: | paymentMethod | productNumber | quantity | paymentStatus | billingCountry | currency | - | paypal | SWDEMO10007.1 | 1 | paid | NL | EUR | - | klarna | SWDEMO10007.1 | 1 | authorized | DE | EUR | - | billie | SWDEMO10007.1 | 1 | authorized | DE | EUR | - | riverty | SWDEMO10007.1 | 1 | authorized | NL | EUR | - | eps | SWDEMO10007.1 | 1 | paid | DE | EUR | - | przelewy24 | SWDEMO10007.1 | 1 | paid | PL | PLN | - | twint | SWDEMO10007.1 | 1 | paid | DE | CHF | - | blik | SWDEMO10007.1 | 1 | paid | DE | PLN | - | mbway | SWDEMO10007.1 | 1 | paid | DE | EUR | - | swish | SWDEMO10007.1 | 1 | paid | SE | SEK | - | multibanco | SWDEMO10007.1 | 1 | paid | DE | EUR | - | trustly | SWDEMO10007.1 | 1 | paid | DE | EUR | - | alma | SWDEMO10007.1 | 5 | paid | FR | EUR | - | eps | SWDEMO10007.1 | 1 | paid | DE | EUR | - | banktransfer | SWDEMO10007.1 | 1 | paid | DE | EUR | - | bancontact | SWDEMO10007.1 | 1 | paid | DE | EUR | - | paybybank | SWDEMO10007.1 | 1 | paid | DE | EUR | - | satispay | SWDEMO10007.1 | 1 | paid | DE | EUR | - | mobilepay | SWDEMO10007.1 | 1 | paid | DK | DKK | - | vipps | SWDEMO10007.1 | 1 | paid | NO | NOK | \ No newline at end of file + | alma | MOL_REGULAR | 2 | paid | FR | EUR | + | bancomatpay | MOL_REGULAR | 1 | paid | IT | EUR | + | bancontact | MOL_REGULAR | 1 | paid | DE | EUR | + | banktransfer | MOL_REGULAR | 1 | paid | DE | EUR | + | belfius | MOL_REGULAR | 1 | paid | BE | EUR | + | billie | MOL_REGULAR | 1 | authorized | DE | EUR | + | bizum | MOL_REGULAR | 1 | paid | ES | EUR | + | blik | MOL_REGULAR | 1 | paid | DE | PLN | + | eps | MOL_REGULAR | 1 | paid | DE | EUR | + | in3 | MOL_REGULAR | 2 | paid | NL | EUR | + | klarna | MOL_REGULAR | 1 | authorized | DE | EUR | + | mbway | MOL_REGULAR | 1 | paid | DE | EUR | + | multibanco | MOL_REGULAR | 1 | paid | DE | EUR | + | mybank | MOL_REGULAR | 1 | paid | IT | EUR | + | paybybank | MOL_REGULAR | 1 | paid | DE | EUR | + | paypal | MOL_REGULAR | 1 | paid | DE | EUR | + | przelewy24 | MOL_REGULAR | 1 | paid | PL | PLN | + | riverty | MOL_REGULAR | 1 | authorized | NL | EUR | + | satispay | MOL_REGULAR | 1 | paid | DE | EUR | + | swish | MOL_REGULAR | 1 | paid | SE | SEK | + | trustly | MOL_REGULAR | 1 | paid | DE | EUR | + | twint | MOL_REGULAR | 1 | paid | DE | CHF | + | vipps | MOL_REGULAR | 1 | paid | NO | NOK | + | mobilepay | MOL_REGULAR | 1 | paid | DK | DKK | + + Scenario Outline: payment success with issuer + Given payment method "" exists and active + And i select "" as billing country + And i select "" as currency + And product "" with quantity "" is in cart + When i start checkout with payment method "" + And i select issuer "" + And select payment status "" + Then i see success page + And order payment status is "" + + Examples: + | paymentMethod | productNumber | quantity | paymentStatus | billingCountry | currency | issuer | + | ideal | MOL_REGULAR | 5 | paid | NL | EUR | ideal_INGBNL2A | + | kbc | MOL_REGULAR | 1 | paid | BE | EUR | kbc | + | kbc | MOL_REGULAR | 1 | paid | BE | EUR | cbc | + | giftcard | MOL_CHEAP | 1 | paid | NL | EUR | beautycadeaukaart | + | giftcard | MOL_CHEAP | 1 | paid | NL | EUR | biercheque | + | giftcard | MOL_CHEAP | 1 | paid | NL | EUR | bloemencadeaukaart | + + Scenario Outline: payment success with giftcard and rest amount + Given payment method "" exists and active + And i select "" as billing country + And i select "" as currency + And product "" with quantity "" is in cart + When i start checkout with payment method "" + And i select issuer "" + And select payment status "" + And select mollie payment method "" + And select payment status "" + Then i see success page + And order payment status is "" + + Examples: + | paymentMethod | molliePaymentMethod | productNumber | quantity | paymentStatus | billingCountry | currency | issuer | + | giftcard | paypal | MOL_REGULAR | 1 | paid | NL | EUR | beautycadeaukaart | + | giftcard | paypal | MOL_REGULAR | 1 | paid | NL | EUR | biercheque | + | giftcard | paypal | MOL_REGULAR | 1 | paid | NL | EUR | bloemencadeaukaart | + + Scenario: payment success with mixed tax + Given payment method "paypal" exists and active + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_REGULAR" with quantity "1" is in cart + And product "MOL_REDUCED_TAX" with quantity "1" is in cart + And product "MOL_TAX_FREE" with quantity "1" is in cart + When i start checkout with payment method "paypal" + And select payment status "paid" + Then i see success page + And order payment status is "paid" + + Scenario: payment success with mixed tax and net customer + Given payment method "paypal" exists and active + And iam logged in as user "cypress-net@mollie.com" + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_REGULAR" with quantity "1" is in cart + And product "MOL_REDUCED_TAX" with quantity "1" is in cart + And product "MOL_TAX_FREE" with quantity "1" is in cart + When i start checkout with payment method "paypal" + And select payment status "paid" + Then i see success page + And order payment status is "paid" \ No newline at end of file diff --git a/tests/Behat/Features/shipment.feature b/tests/Behat/Features/shipment.feature new file mode 100644 index 000000000..40d635c76 --- /dev/null +++ b/tests/Behat/Features/shipment.feature @@ -0,0 +1,57 @@ +@core @shipping +Feature: Basic Shipment Feature + In order to ship authorized order + As an Admin + + Background: + Given iam logged in as user "cypress@mollie.com" + + Scenario: shipping line item is working + Given payment method "klarna" exists and active + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_REGULAR" with quantity "2" is in cart + And product "MOL_REDUCED_TAX" with quantity "1" is in cart + When i start checkout with payment method "klarna" + And select payment status "authorized" + Then i see success page + And order payment status is "authorized" + When i ship line item "MOL_REGULAR" with quantity "1" + Then order payment status is "authorized" + And delivery status is "shipped_partially" + When i ship line item "MOL_REGULAR" with quantity "1" + Then order payment status is "authorized" + And delivery status is "shipped_partially" + When i ship line item "MOL_REDUCED_TAX" with quantity "1" + Then order payment status is "paid" + And delivery status is "shipped" + + + Scenario: automatic shipment is working + Given payment method "klarna" exists and active + And plugin configuration "automaticShipping" is set to "true" + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_REGULAR" with quantity "2" is in cart + And product "MOL_REDUCED_TAX" with quantity "1" is in cart + When i start checkout with payment method "klarna" + And select payment status "authorized" + Then i see success page + And order payment status is "authorized" + When i select delivery status action "ship" + Then order payment status is "paid" + + Scenario: automatic shipment is disabled + Given payment method "klarna" exists and active + And plugin configuration "automaticShipping" is set to "false" + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_REGULAR" with quantity "2" is in cart + And product "MOL_REDUCED_TAX" with quantity "1" is in cart + When i start checkout with payment method "klarna" + And select payment status "authorized" + Then i see success page + And order payment status is "authorized" + When i select delivery status action "ship" + Then order payment status is "authorized" + diff --git a/tests/Behat/Features/subscription.feature b/tests/Behat/Features/subscription.feature new file mode 100644 index 000000000..453712125 --- /dev/null +++ b/tests/Behat/Features/subscription.feature @@ -0,0 +1,25 @@ +@core @subscription +Feature: Subscription checkout + In order to use subscription payment methods + As a customer + + Background: + Given iam logged in as user "cypress@mollie.com" + + Scenario: subscription can be bought, paused, resumed and cancelled + Given payment method "trustly" exists and active + And i select "DE" as billing country + And i select "EUR" as currency + And product "MOL_SUB_1" with quantity "1" is in cart + When i start checkout with payment method "trustly" + And select payment status "paid" + Then i see success page + And order payment status is "paid" + And the subscription status is "active" + Then i "pause" the subscription + And the subscription status is "paused" + Then i "resume" the subscription + And the subscription status is "resumed" + Then i "cancel" the subscription + And the subscription status is "canceled" + diff --git a/tests/Behat/Storage.php b/tests/Behat/Storage.php new file mode 100644 index 000000000..203924097 --- /dev/null +++ b/tests/Behat/Storage.php @@ -0,0 +1,32 @@ + { // status code needs to be 422 unprocessable entity expect(response.status).to.eq(422); // also verify the content - expect(response.body.success).to.eq(false); - expect(response.body.error).to.eq('Transaction 0d8eefdd6d12456335280e2ff42431b9 not found in Shopware'); + expect(response.body.errors[0].detail).to.eq('Transaction 0d8eefdd6d12456335280e2ff42431b9 not found in Shopware'); }) }) it('C266660: API Legacy Webhook is reachable @core', () => { cy.request({url: '/api/v2/mollie/webhook/abc', failOnStatusCode: false,}).then((response) => { - // status code needs to be 422 unprocessable entity - expect(response.status).to.eq(422); - // also verify the content - expect(response.body.success).to.eq(false); - expect(response.body.error).to.eq('Value is not a valid UUID: abc'); + + expect(response.status).to.eq(404); + }) }) diff --git a/tests/Cypress/cypress/e2e/store-api/applepay-direct.cy.js b/tests/Cypress/cypress/e2e/store-api/applepay-direct.cy.js index 110253b25..1ed8bc4e7 100644 --- a/tests/Cypress/cypress/e2e/store-api/applepay-direct.cy.js +++ b/tests/Cypress/cypress/e2e/store-api/applepay-direct.cy.js @@ -119,7 +119,7 @@ describe('Apple Pay Direct - Store API Routes', () => { cy.wrap(request).its('data').then(response => { cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('Please provide a validation url!'); + expect(response.data.errors[0].detail).to.contain('Please provide a validation url'); }); }) @@ -137,7 +137,7 @@ describe('Apple Pay Direct - Store API Routes', () => { cy.wrap(request).its('data').then(response => { cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('No Country Code provided!'); + expect(response.data.errors[0].detail).to.contain('No Country Code provided'); }); }) @@ -170,7 +170,7 @@ describe('Apple Pay Direct - Store API Routes', () => { cy.wrap(request).its('data').then(response => { cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('Please provide a Shipping Method identifier!'); + expect(response.data.errors[0].detail).to.contain('Missing shipping method identifier'); }); }) @@ -203,7 +203,7 @@ describe('Apple Pay Direct - Store API Routes', () => { cy.wrap(request).its('data').then(response => { cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('PaymentToken not found!') + expect(response.data.errors[0].detail).to.contain('"paymentToken" not set in request body') }); }) diff --git a/tests/Cypress/cypress/e2e/store-api/creditcard.cy.js b/tests/Cypress/cypress/e2e/store-api/creditcard.cy.js index b8d933794..183159256 100644 --- a/tests/Cypress/cypress/e2e/store-api/creditcard.cy.js +++ b/tests/Cypress/cypress/e2e/store-api/creditcard.cy.js @@ -14,14 +14,14 @@ context(storeApiPrefix + "/mollie/creditcard/store-token", () => { it('C266682: Store Credit Card Token with invalid customer ID (Store API) @core', () => { const request = new Promise((resolve) => { - client.post('/mollie/creditcard/store-token/tk_123').then(response => { + client.post('/mollie/creditcard/store-token/cust-123/tk_123').then(response => { resolve({'data': response.data}); }); }) cy.wrap(request).its('data').then(response => { - cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('Customer with ID not found in Shopware'); + + expect(response.message).to.contain('Using deprecated route, please provide "creditCardToken" in request body for payment'); }); }) diff --git a/tests/Cypress/cypress/e2e/store-api/pos.cy.js b/tests/Cypress/cypress/e2e/store-api/pos.cy.js index 839be4226..115a1fd74 100644 --- a/tests/Cypress/cypress/e2e/store-api/pos.cy.js +++ b/tests/Cypress/cypress/e2e/store-api/pos.cy.js @@ -33,14 +33,14 @@ context(storeApiPrefix +"/mollie/ideal/store-issuer", () => { it('C1341123: POS store terminal with invalid customer id (Store API) @core', () => { const request = new Promise((resolve) => { - client.post('/mollie/pos/store-terminal/ideal_ABNANL2A').then(response => { + client.post('/mollie/pos/store-terminal/cust-123/ideal_ABNANL2A').then(response => { resolve({'data': response.data}); }); }) cy.wrap(request).its('data').then(response => { - cy.wrap(response).its('status').should('eq', 500) - expect(response.data.errors[0].detail).to.contain('Customer with ID not found in Shopware'); + + expect(response.message).to.contain('Using deprecated route, please provide "terminalId" in request body for payment'); }); }) diff --git a/tests/Cypress/cypress/e2e/storefront/checkout/checkout-failed.cy.js b/tests/Cypress/cypress/e2e/storefront/checkout/checkout-failed.cy.js index 132489bdc..eec03a4ed 100644 --- a/tests/Cypress/cypress/e2e/storefront/checkout/checkout-failed.cy.js +++ b/tests/Cypress/cypress/e2e/storefront/checkout/checkout-failed.cy.js @@ -94,7 +94,7 @@ context("Checkout Failure Tests", () => { // verify that we are back in our shop // if the payment fails, the order is finished but // we still have the option to change the payment method - cy.url().should('include', '/mollie/payment/'); + cy.url().should('include', '/account/order/edit'); cy.contains('The payment is failed or was canceled.'); // click on the mollie plugin retry button @@ -109,7 +109,8 @@ context("Checkout Failure Tests", () => { molliePaymentStatus.selectPaid(); cy.url().should('include', '/checkout/finish'); - cy.contains('Thank you for your order'); + cy.contains('Thank you'); + cy.contains('Your order number'); }) it('C1278577: Retry canceled payment with Mollie Failure Mode', () => { @@ -128,21 +129,10 @@ context("Checkout Failure Tests", () => { // verify that we are back in our shop // if the payment fails, the order is finished, but // we still have the option to change the payment method - cy.url().should('include', '/mollie/payment/'); - - // click on the mollie plugin retry button - // which brings us to the mollie payment selection page - checkout.mollieFailureModeRetryPayment(); - - cy.url().should('include', '/checkout/select-method/'); - - // select giro pay and mark it as "paid" - mollieSandbox.initSandboxCookie(); - molliePaymentList.selectBankTransfer(); - molliePaymentStatus.selectPaid(); - - cy.url().should('include', '/checkout/finish'); - cy.contains('Thank you for your order'); + cy.url().should('include', '/account/order'); + //in newer shopware version, if a customer cancelled a payment and order was changed to cancelled + //that means the order reached final state and cannot be edited afterwards + cy.contains('canceled and cannot be edited afterwards'); }) it('C4010: Continue Shopping after failed payment in Mollie Failure Mode', () => { @@ -161,7 +151,7 @@ context("Checkout Failure Tests", () => { // verify that we are back in our shop // if the payment fails, the order is finished but // we still have the option to change the payment method - cy.url().should('include', '/mollie/payment/'); + cy.url().should('include', '/account/order/edit'); cy.contains('The payment is failed or was canceled.'); diff --git a/tests/Cypress/cypress/e2e/storefront/checkout/checkout-states.cy.js b/tests/Cypress/cypress/e2e/storefront/checkout/checkout-states.cy.js index f50bf1d88..11d24acc1 100644 --- a/tests/Cypress/cypress/e2e/storefront/checkout/checkout-states.cy.js +++ b/tests/Cypress/cypress/e2e/storefront/checkout/checkout-states.cy.js @@ -58,7 +58,7 @@ context("Order Status Mapping Tests", () => { context(devices.getDescription(device), () => { - it('C4028: Test Status Open stays In progress', () => { + it('C4028: Test Status Open stays Unconfirmed/In progress', () => { beforeEach(device); @@ -79,7 +79,15 @@ context("Order Status Mapping Tests", () => { adminLogin.login(); adminOrders.assertLatestOrderStatus('Open'); - adminOrders.assertLatestPaymentStatus('In Progress'); + let paymentStatus = 'In Progress' + /** + * In Shopware 6.7 the action DO_PAY was removed, so we use ACTION_PROCESS for bank payments. this action sets status to open in lower than 6.7 + */ + if(shopware.isVersionLower('6.6.0.0')){ + paymentStatus = 'Open' + } + + adminOrders.assertLatestPaymentStatus(paymentStatus); }) diff --git a/tests/Cypress/cypress/e2e/storefront/payment-methods/applepay-direct.cy.js b/tests/Cypress/cypress/e2e/storefront/payment-methods/applepay-direct.cy.js index 2a3342dec..69558ea91 100644 --- a/tests/Cypress/cypress/e2e/storefront/payment-methods/applepay-direct.cy.js +++ b/tests/Cypress/cypress/e2e/storefront/payment-methods/applepay-direct.cy.js @@ -170,7 +170,7 @@ describe('Apple Pay Direct - Storefront Routes', () => { cy.wrap(request).its('data').then(data => { cy.wrap(data).its('success').should('eq', false) - cy.wrap(data).its('error').should('contain', 'Please provide a Shipping Method identifier'); + cy.wrap(data).its('error').should('contain', 'Missing shipping method identifier'); }); }) @@ -187,18 +187,6 @@ describe('Apple Pay Direct - Storefront Routes', () => { }); }) - it('C266707: /mollie/apple-pay/finish-payment redirects to cart with invalid data @core', () => { - - const request = new Promise((resolve) => { - storefrontClient.get('/mollie/apple-pay/finish-payment').then(response => { - resolve({'data': response}); - }); - }) - - cy.wrap(request).its('data').then(data => { - cy.wrap(data).its('request.responseURL').should('contain', '/checkout/cart'); - }); - }) it('C266708: /mollie/apple-pay/restore-cart @core', () => { diff --git a/tests/Cypress/cypress/e2e/storefront/subscriptions/subscription.cy.js b/tests/Cypress/cypress/e2e/storefront/subscriptions/subscription.cy.js index 0b21c03dc..fd879764d 100644 --- a/tests/Cypress/cypress/e2e/storefront/subscriptions/subscription.cy.js +++ b/tests/Cypress/cypress/e2e/storefront/subscriptions/subscription.cy.js @@ -480,7 +480,7 @@ function assertAvailablePaymentMethods() { cy.contains('iDEAL').should('exist'); cy.contains('Card').should('exist'); - cy.contains('eps').should('exist'); + cy.contains('EPS').should('exist'); cy.contains('Bancontact').should('exist'); cy.contains('Belfius').should('exist'); cy.contains('PayPal').should('exist'); diff --git a/tests/Cypress/cypress/support/actions/storefront/checkout/CheckoutAction.js b/tests/Cypress/cypress/support/actions/storefront/checkout/CheckoutAction.js index 0757fa77a..5964c33bc 100644 --- a/tests/Cypress/cypress/support/actions/storefront/checkout/CheckoutAction.js +++ b/tests/Cypress/cypress/support/actions/storefront/checkout/CheckoutAction.js @@ -98,14 +98,14 @@ export default class CheckoutAction { * */ mollieFailureModeRetryPayment() { - cy.get('.cy-retry-payment').click(); + cy.get('form[name="update-order"] .btn-primary').click(); } /** * */ mollieFailureModeContinueShopping() { - cy.get(':nth-child(3) > .btn-secondary').click(); + cy.get('form[name="update-order"] .btn-secondary').click(); } /** @@ -123,18 +123,19 @@ export default class CheckoutAction { if (shopware.isVersionGreaterEqual('6.7.0.0')) { cy.get('.confirm-address .card-actions:eq(0) > a').click(); + cy.wait(1000); cy.get('.modal-dialog-address #shipping-address-tab-pane .address-manager-select-address button').first().click(); cy.get('.dropdown-menu .address-manager-modal-address-form[data-address-type="shipping"]').first().click(); } - if (shopware.isVersionLower('6.7.0.0')) { - cy.get('.js-confirm-overview-addresses .card:eq(0) .card-actions a[data-address-editor]', { timeout: 15000 }).click(); + cy.get('.js-confirm-overview-addresses .card:eq(0) .card-actions a[data-address-editor]').click(); cy.wait(2000); cy.get('.address-editor-edit').click(); cy.wait(1000); } + cy.get('select.country-select:eq(0)').select(billingCountry); if (shopware.isVersionGreaterEqual('6.7.0.0')) { diff --git a/tests/Fixtures/Category/CategoryFixture.php b/tests/Fixtures/Category/CategoryFixture.php new file mode 100644 index 000000000..733258c2a --- /dev/null +++ b/tests/Fixtures/Category/CategoryFixture.php @@ -0,0 +1,107 @@ +helper = $helper; + $this->categoryRepository = $categoryRepository; + } + + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $context = new Context(new SystemSource()); + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('name', 'Free time & electronics')); + $categorySearchResult = $this->categoryRepository->search($criteria, $context); + + /** @var CategoryEntity $category */ + $category = $categorySearchResult->first(); + + $afterCatId = $category->getId(); + $parentId = $category->getParentId(); + $cmsPageId = $category->getCmsPageId(); + + + $this->createCategory(Uuid::fromStringToHex('Voucher'), "Voucher", $context, $afterCatId, $parentId, $cmsPageId); + $this->createCategory(Uuid::fromStringToHex('Subscriptions'), "Subscriptions", $context, $afterCatId, $parentId, $cmsPageId); + $this->createCategory(Uuid::fromStringToHex('Failures'), "Failures", $context, $afterCatId, $parentId, $cmsPageId); + $this->createCategory(Uuid::fromStringToHex('Rounding'), "Rounding", $context, $afterCatId, $parentId, $cmsPageId); + $this->createCategory(Uuid::fromStringToHex('Cheap'), "Cheap", $context, $afterCatId, $parentId, $cmsPageId); + } + + /** + * @param string $id + * @param string $name + * @param null|string $afterCategoryId + */ + private function createCategory(string $id, string $name, Context $context, ?string $afterCategoryId, ?string $parentId, ?string $cmsPageId): void + { + + $this->categoryRepository->upsert([ + [ + 'id' => $id, + 'translations' => [ + 'de-DE' => [ + 'name' => $name, + ], + 'en-GB' => [ + 'name' => $name, + ], + ], + 'productAssignmentType' => 'product', + 'level' => 2, + 'active' => true, + 'displayNestedProducts' => true, + 'visible' => true, + 'type' => 'page', + 'cmsPageId' => $cmsPageId, + 'parentId' => $parentId, + 'afterCategoryId' => $afterCategoryId, + ], + ], $context); + } +} diff --git a/tests/Fixtures/Customer/CustomerFixture.php b/tests/Fixtures/Customer/CustomerFixture.php new file mode 100644 index 000000000..e3023aec3 --- /dev/null +++ b/tests/Fixtures/Customer/CustomerFixture.php @@ -0,0 +1,84 @@ +helper = $helper; + $this->customerRepository = $customerRepository; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $salesChannel = $this->helper->SalesChannel()->getStorefrontSalesChannel(); + + $dataNL = [[ + 'id' => self::CUSTOMER_ID_NL, + 'salesChannelId' => $salesChannel->getId(), + 'groupId' => $salesChannel->getCustomerGroupId(), + 'defaultPaymentMethodId' => $this->helper->PaymentMethod()->getInvoicePaymentMethod()->getId(), + 'defaultBillingAddress' => [ + 'id' => self::ADDRESS_ID_NL, + 'salutationId' => $this->helper->Salutation()->getNotSpecifiedSalutation()->getId(), + 'firstName' => 'Mollie NL', + 'lastName' => 'Test', + 'zipcode' => '1015 CW', + 'street' => 'Keizersgracht 126', + 'city' => 'Amsterdam', + 'countryId' => $this->helper->LanguageAndLocale()->getCountry('NL')->getId(), + ], + 'defaultShippingAddressId' => self::ADDRESS_ID_NL, + 'salutationId' => $this->helper->Salutation()->getNotSpecifiedSalutation()->getId(), + 'customerNumber' => '1122', + 'firstName' => 'Mollie NL', + 'lastName' => 'Test', + 'email' => 'test@mollie.nl', + 'password' => 'molliemollie' + ]]; + + $this->customerRepository->upsert($dataNL, Context::createDefaultContext()); + } +} diff --git a/tests/Fixtures/Product/CheapProducts.php b/tests/Fixtures/Product/CheapProducts.php new file mode 100644 index 000000000..362796d16 --- /dev/null +++ b/tests/Fixtures/Product/CheapProducts.php @@ -0,0 +1,67 @@ +helper = $helper; + $this->repoProducts = $repoProducts; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @return string[] + */ + public function dependsOn(): array + { + return [ + CategoryFixture::class + ]; + } + + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $category = 'Cheap'; + $image = 'tshirt-black.png'; + $description = 'Mollie Product for testing purpose in development environment. You can use this cheap products for LIVE tests or other scenarios'; + + $this->createProduct('1d3eefdd2d22436385580e2fb43431b9', 'Cheap Mollie Shirt', 'MOL_CHEAP_1', $category, $description, 1, $image, true, [], $this->repoProducts, $this->helper); + } +} diff --git a/tests/Fixtures/Product/FailureProducts.php b/tests/Fixtures/Product/FailureProducts.php new file mode 100644 index 000000000..eaa3084e4 --- /dev/null +++ b/tests/Fixtures/Product/FailureProducts.php @@ -0,0 +1,79 @@ +helper = $helper; + $this->repoProducts = $repoProducts; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @return string[] + */ + public function dependsOn(): array + { + return [ + CategoryFixture::class + ]; + } + + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $category = 'Failures'; + $image = 'tshirt-black-fail.png'; + $description = 'Mollie Product for testing purpose in development environment. Use "failed" on the Mollie Payment Sandbox page to force the special error reason of this product.'; + + + $this->createProduct('0d1eeedd6d22436385580e2ff42431b9', 'Invalid Card Number', 'MOL_ERROR_1', $category, $description, 1001, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d2eeedd6d22436385580e2ff42431b9', 'Invalid CVV', 'MOL_ERROR_2', $category, $description, 1002, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d3eeedd6d22436385580e2ff42431b9', 'Invalid Card Holder Name', 'MOL_ERROR_3', $category, $description, 1003, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d4eeedd6d22436385580e2ff42431b9', 'Card Expired', 'MOL_ERROR_4', $category, $description, 1004, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d5eeedd6d22436385580e2ff42431b9', 'Invalid Card Type', 'MOL_ERROR_5', $category, $description, 1005, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d6eeedd6d22436385580e2ff42431b9', 'Refused by Issuer', 'MOL_ERROR_6', $category, $description, 1006, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d7eeedd6d22436385580e2ff42431b9', 'Insufficient Funds', 'MOL_ERROR_7', $category, $description, 1007, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d8eeedd6d22436385580e2ff42431b9', 'Inactive Card', 'MOL_ERROR_8', $category, $description, 1008, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d9eeedd6d22436385580e2ff42431b9', 'Possible Fraud', 'MOL_ERROR_9', $category, $description, 1009, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d3eeedd6d10436385580e2ff42431b9', 'Authentication Failed', 'MOL_ERROR_10', $category, $description, 1010, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('0d3eeedd6d11436385580e2ff42431b9', 'Card Declined', 'MOL_ERROR_11', $category, $description, 1011, $image, false, [], $this->repoProducts, $this->helper); + } +} diff --git a/tests/Fixtures/Product/RoundingProducts.php b/tests/Fixtures/Product/RoundingProducts.php new file mode 100644 index 000000000..a935cdee4 --- /dev/null +++ b/tests/Fixtures/Product/RoundingProducts.php @@ -0,0 +1,58 @@ +helper = $helper; + $this->repoProducts = $repoProducts; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $category = 'Rounding'; + $image = 'tshirt-white.png'; + $description = 'Product to test rounding issues.'; + + $this->createProduct('7d1abedd2d22436385580e2ff42431b9', 'Product A 4 Decimals', 'MOL_ROUNDING_1', $category, $description, 2.7336, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('6d1abedd2d22436485580f3ff42431b9', 'Product B 4 Decimals', 'MOL_ROUNDING_2', $category, $description, 2.9334, $image, false, [], $this->repoProducts, $this->helper); + $this->createProduct('1a2abeed2d22436485580f3ff42431b9', 'Product C 4 Decimals', 'MOL_ROUNDING_3', $category, $description, 1.6494, $image, false, [], $this->repoProducts, $this->helper); + } +} diff --git a/tests/Fixtures/Product/SubscriptionFixture.php b/tests/Fixtures/Product/SubscriptionFixture.php new file mode 100644 index 000000000..9739ecdb7 --- /dev/null +++ b/tests/Fixtures/Product/SubscriptionFixture.php @@ -0,0 +1,69 @@ +helper = $helper; + $this->repoProducts = $repoProducts; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $category = 'Subscriptions'; + $image = 'champagne.png'; + $description = 'Mollie Subscription Product for testing purpose in development environment.'; + + $customFieldsDaily = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => "days" + ]; + + $customFieldsWeekly = [ + 'mollie_payments_product_subscription_enabled' => true, + 'mollie_payments_product_subscription_interval' => 1, + 'mollie_payments_product_subscription_interval_unit' => "week" + ]; + + $this->createProduct('1d1eeedd6d22436385580e2ff42431b9', 'Subscription (1x Daily)', 'MOL_SUB_1', $category, $description, 19, $image, false, $customFieldsDaily, $this->repoProducts, $this->helper); + $this->createProduct('1d2eeedd6d22436385580e2ff42431b9', 'Subscription (1x Weekly)', 'MOL_SUB_2', $category, $description, 29, $image, false, $customFieldsWeekly, $this->repoProducts, $this->helper); + } +} diff --git a/tests/Fixtures/Product/VoucherFixture.php b/tests/Fixtures/Product/VoucherFixture.php new file mode 100644 index 000000000..43d0a17e9 --- /dev/null +++ b/tests/Fixtures/Product/VoucherFixture.php @@ -0,0 +1,70 @@ +helper = $helper; + $this->repoProducts = $repoProducts; + } + + /** + * @return string[] + */ + public function groups(): array + { + return [ + 'mollie', + 'mollie-demodata', + ]; + } + + /** + * @param FixtureBag $bag + * @return void + */ + public function load(): void + { + $category = 'Voucher'; + $image = 'tshirt-white.png'; + $description = 'Mollie Voucher Product for testing purpose in development environment.'; + + $customFieldsEco = [ + 'mollie_payments_product_voucher_type' => 1, + ]; + + $customFieldsMeal = [ + 'mollie_payments_product_voucher_type' => 2, + ]; + + $customFieldsGift = [ + 'mollie_payments_product_voucher_type' => 3, + ]; + + $this->createProduct('4d1eeedd6d22436385580e2ff42431b9', 'Voucher ECO', 'MOL_VOUCHER_1', $category, $description, 19, $image, false, $customFieldsEco, $this->repoProducts, $this->helper); + $this->createProduct('5d1eeedd6d22436385580e2ff42431b9', 'Voucher MEAL', 'MOL_VOUCHER_2', $category, $description, 19, 'champagne.png', false, $customFieldsMeal, $this->repoProducts, $this->helper); + $this->createProduct('6d1eeedd6d22436385580e2ff42431b9', 'Voucher GIFT', 'MOL_VOUCHER_3', $category, $description, 19, $image, false, $customFieldsGift, $this->repoProducts, $this->helper); + } +} diff --git a/tests/Integration/Data/CheckoutTestBehaviour.php b/tests/Integration/Data/CheckoutTestBehaviour.php index 9e558a906..556c7fb13 100644 --- a/tests/Integration/Data/CheckoutTestBehaviour.php +++ b/tests/Integration/Data/CheckoutTestBehaviour.php @@ -1,14 +1,13 @@ set('tos', true); $response = $checkoutController->order($requestDataBag, $salesChannelContext, $request); + /** @var FlashBag $flashBag */ $flashBag = $request->getSession()->getBag('flashes'); $flashBagData = $flashBag->peekAll(); @@ -103,24 +102,16 @@ public function finishCheckout(string $paymentUrl, SalesChannelContext $salesCha { $matches = []; preg_match('/mollie\/payment\/(?.*)/m', $paymentUrl, $matches); - $paymentId = $matches['paymentId']; - - $returnController = $this->getContainer()->get(ReturnControllerBase::class); - /** @var RedirectResponse $response */ - $response = $returnController->payment($salesChannelContext, $paymentId); - $redirectLocation = $response->getTargetUrl(); - Assert::assertSame(302, $response->getStatusCode()); - Assert::assertStringContainsString('payment/finalize-transaction', $redirectLocation); + $paymentId = $matches['paymentId'] ?? null; - $queryString = parse_url($redirectLocation, PHP_URL_QUERY); - $urlParameters = []; - parse_str($queryString, $urlParameters); + if ($paymentId === null) { + throw new \Exception('Failed to find Payment ID in ' . $paymentUrl); + } - $request = $this->createStoreFrontRequest($salesChannelContext); - $request->request->set('_sw_payment_token', $urlParameters['_sw_payment_token']); - $paymentController = $this->getContainer()->get(PaymentController::class); + /** @var PaymentController $returnController */ + $returnController = $this->getContainer()->get(PaymentController::class); - return $paymentController->finalizeTransaction($request); + return $returnController->return($paymentId, $salesChannelContext); } public function getOrderById(string $orderId, SalesChannelContext $salesChannelContext): OrderEntity @@ -129,9 +120,16 @@ public function getOrderById(string $orderId, SalesChannelContext $salesChannelC $repository = $this->getContainer()->get('order.repository'); $criteria = (new Criteria([$orderId])); $criteria->addAssociation('transactions.stateMachineState'); - + $criteria->addAssociation('deliveries'); + $criteria->addAssociation('deliveries.stateMachineState'); $criteria->getAssociation('transactions')->addSorting(new FieldSorting('createdAt')); + $criteria->addAssociation('lineItems.product'); + $criteria->addAssociation('currency'); + $criteria->addAssociation('deliveries.positions'); + $criteria->addAssociation('deliveries.shippingCosts'); + + $searchResult = $repository->search($criteria, $salesChannelContext->getContext()); - return $repository->search($criteria, $salesChannelContext->getContext())->first(); + return $searchResult->first(); } } diff --git a/tests/Integration/Data/CustomerTestBehaviour.php b/tests/Integration/Data/CustomerTestBehaviour.php index d2015d929..ad129be38 100644 --- a/tests/Integration/Data/CustomerTestBehaviour.php +++ b/tests/Integration/Data/CustomerTestBehaviour.php @@ -1,20 +1,14 @@ createDefaultData($salesChannelContext); - $data['email'] = $email; - } - - $registerController = $this->getContainer()->get(RegisterController::class); - - $requestDat = new RequestDataBag($data); - $request = $this->createStoreFrontRequest($salesChannelContext); - $request->request->set('errorRoute', 'frontend.account.login.page'); - - return $registerController->register($request, $requestDat, $salesChannelContext); - } - - public function findUserIdByEmail(string $email, Context $context): ?string + public function getUserIdByEmail(string $email, SalesChannelContext $salesChannelContext): string { /** @var EntityRepository $repository */ $repository = $this->getContainer()->get('customer.repository'); @@ -46,37 +24,7 @@ public function findUserIdByEmail(string $email, Context $context): ?string $criteria->addFilter(new EqualsFilter('email', $email)); - return $repository->searchIds($criteria, $context)->firstId(); - } - - public function loginOrCreateAccount(string $email, SalesChannelContext $salesChannelContext, ?array $accountData = null): string - { - $customerId = $this->findUserIdByEmail($email, $salesChannelContext->getContext()); - if ($customerId === null) { - $this->createAccount($email, $salesChannelContext, $accountData); - $customerId = $this->findUserIdByEmail($email, $salesChannelContext->getContext()); - $this->addAdditionalAddresses($customerId, $salesChannelContext); - } - - return $customerId; - } - - public function getCountryByIso(array $isoCodes, SalesChannelContext $salesChannelContext): IdSearchResult - { - /** @var EntityRepository $repository */ - $repository = $this->getContainer()->get('country.repository'); - - $criteria = (new Criteria()) - ->addFilter(new EqualsFilter('active', true)) - ->addFilter(new EqualsFilter('shippingAvailable', true)) - ->addFilter(new EqualsAnyFilter('iso', $isoCodes)) - ; - - if ($salesChannelContext->getSalesChannelId() !== null) { - $criteria->addFilter(new EqualsFilter('salesChannels.id', $salesChannelContext->getSalesChannelId())); - } - - return $repository->searchIds($criteria, $salesChannelContext->getContext()); + return (string) $repository->searchIds($criteria, $salesChannelContext->getContext())->firstId(); } public function getUserAddressByIso(string $isoCode, SalesChannelContext $salesChannelContext): IdSearchResult @@ -90,58 +38,4 @@ public function getUserAddressByIso(string $isoCode, SalesChannelContext $salesC return $repository->searchIds($criteria, $salesChannelContext->getContext()); } - - private function addAdditionalAddresses(string $customerId, SalesChannelContext $salesChannelContext): void - { - $countrySearchResult = $this->getCountryByIso(['NL', 'FR', 'BE', 'PL', 'ES', 'SE'], $salesChannelContext); - $salutationId = $this->getValidSalutationId(); - $addresses = []; - foreach ($countrySearchResult->getIds() as $countryId) { - $addresses[] = [ - 'salutationId' => $salutationId, - 'company' => 'Mollie Company', - 'firstName' => 'Max', - 'lastName' => 'Mollie', - 'countryId' => $countryId, - 'street' => 'Mollie Street 123', - 'city' => 'Mollie City', - 'zipcode' => '12345', - 'phoneNumber' => '0123456789', - ]; - } - $customerData = [ - 'id' => $customerId, - 'addresses' => $addresses, - ]; - /** @var EntityRepository $repository */ - $repository = $this->getContainer()->get('customer.repository'); - $repository->upsert([ - $customerData - ], $salesChannelContext->getContext()); - } - - private function createDefaultData(SalesChannelContext $salesChannelContext): array - { - $countryId = $this->getCountryByIso(['DE'], $salesChannelContext)->firstId(); - $salutationId = $this->getValidSalutationId(); - - return [ - 'salutationId' => $salutationId, - 'firstName' => 'Max', - 'lastName' => 'Mollie', - 'createCustomerAccount' => true, - 'password' => 'molliemollie', - 'groupId' => TestDefaults::FALLBACK_CUSTOMER_GROUP, - 'billingAddress' => [ - 'company' => 'Mollie Company', - 'firstName' => 'Max', - 'lastName' => 'Mollie', - 'countryId' => $countryId, - 'street' => 'Mollie Street 123', - 'city' => 'Mollie City', - 'zipcode' => '12345', - 'phoneNumber' => '0123456789', - ] - ]; - } } diff --git a/tests/Integration/Data/MolliePageTestBehaviour.php b/tests/Integration/Data/MolliePageTestBehaviour.php deleted file mode 100644 index f534c783c..000000000 --- a/tests/Integration/Data/MolliePageTestBehaviour.php +++ /dev/null @@ -1,95 +0,0 @@ -get($url, [RequestOptions::ALLOW_REDIRECTS => false]); - $formLocation = $response->getHeader('location')[0]; - - $htmlContent = file_get_contents($formLocation); - - $dom = new \DOMDocument(); - try { - $dom = $dom->loadHTML($htmlContent); - } catch (\Throwable $exception) { - } - $form = $dom->getElementById('body'); - $inputs = $form->getElementsByTagName('input'); - - $formData = [ - 'submit-button' => '' - ]; - foreach ($inputs as $input) { - $inputName = $input->getAttribute('name'); - $inputValue = $input->getAttribute('value'); - $inputType = $input->getAttribute('type'); - - dump($inputName, $inputType); - if (isset($formData[$inputName])) { - continue; - } - $formData[$inputName] = $inputValue; - } - dump($formData); - - return $client->post($formLocation, [ - RequestOptions::FORM_PARAMS => $formData, - RequestOptions::ALLOW_REDIRECTS => false, - ]); - } - - public function selectMolliePaymentStatus(string $paymentStatus, string $url): ResponseInterface - { - $client = new Client(); - $response = $client->get($url, [RequestOptions::ALLOW_REDIRECTS => false]); - $formLocation = $response->getHeader('location')[0]; - - $htmlContent = file_get_contents($formLocation); - - $dom = new \DOMDocument(); - try { - $dom = $dom->loadHTML($htmlContent); - } catch (\Throwable $exception) { - } - - $form = $dom->getElementById('body'); - $inputs = $form->getElementsByTagName('input'); - - $formData = [ - 'submit' => '' - ]; - - foreach ($inputs as $input) { - $inputName = $input->getAttribute('name'); - $inputValue = $input->getAttribute('value'); - $inputType = $input->getAttribute('type'); - - if ($inputType === 'radio' && $inputValue === $paymentStatus) { - $formData[$inputName] = $inputValue; - continue; - } - if (isset($formData[$inputName])) { - continue; - } - $formData[$inputName] = $inputValue; - } - - Assert::assertTrue(isset($formData['final_state'])); - Assert::assertEquals($paymentStatus, $formData['final_state']); - - return $client->post($formLocation, [ - RequestOptions::FORM_PARAMS => $formData, - RequestOptions::ALLOW_REDIRECTS => false, - ]); - } -} diff --git a/tests/Integration/Data/OrderTestBehaviour.php b/tests/Integration/Data/OrderTestBehaviour.php index 7e69a8ebd..fca896d36 100644 --- a/tests/Integration/Data/OrderTestBehaviour.php +++ b/tests/Integration/Data/OrderTestBehaviour.php @@ -1,8 +1,9 @@ getContainer()->get('order.repository'); - $criteria = new Criteria(); - - $searchResult = $orderRepository->searchIds($criteria, $context); - - if ($searchResult->getTotal() === 0) { - return null; - } $ids = array_map(function (string $orderId) { return ['id' => $orderId]; - }, $searchResult->getIds()); + }, $ids); return $orderRepository->delete($ids, $context); } @@ -51,6 +45,21 @@ public function getLatestOrderId(Context $context): ?string return $searchResult->getIds()[0]; } + public function getOrder(string $orderId, Context $context): ?OrderEntity + { + /** @var EntityRepository $orderRepository */ + $orderRepository = $this->getContainer()->get('order.repository'); + $criteria = new Criteria([$orderId]); + $criteria->addAssociation('transactions'); + $searchResult = $orderRepository->search($criteria, $context); + + if ($searchResult->getTotal() === 0) { + return null; + } + + return $searchResult->first(); + } + public function updateOrder(string $orderId, array $data, Context $context): void { /** @var EntityRepository $orderRepository */ diff --git a/tests/Integration/Data/PaymentMethodTestBehaviour.php b/tests/Integration/Data/PaymentMethodTestBehaviour.php index fa24c4098..c5c802b19 100644 --- a/tests/Integration/Data/PaymentMethodTestBehaviour.php +++ b/tests/Integration/Data/PaymentMethodTestBehaviour.php @@ -1,40 +1,8 @@ AlmaPayment::class, - ApplePayPayment::PAYMENT_METHOD_NAME => ApplePayPayment::class, - BancomatPayment::PAYMENT_METHOD_NAME => BancomatPayment::class, - BanContactPayment::PAYMENT_METHOD_NAME => BanContactPayment::class, - BankTransferPayment::PAYMENT_METHOD_NAME => BankTransferPayment::class, - BelfiusPayment::PAYMENT_METHOD_NAME => BelfiusPayment::class, - BilliePayment::PAYMENT_METHOD_NAME => BilliePayment::class, - BizumPayment::PAYMENT_METHOD_NAME => BizumPayment::class, - BlikPayment::PAYMENT_METHOD_NAME => BlikPayment::class, - CreditCardPayment::PAYMENT_METHOD_NAME => CreditCardPayment::class, - DirectDebitPayment::PAYMENT_METHOD_NAME => DirectDebitPayment::class, - EpsPayment::PAYMENT_METHOD_NAME => EpsPayment::class, - GiftCardPayment::PAYMENT_METHOD_NAME => GiftCardPayment::class, - GiroPayPayment::PAYMENT_METHOD_NAME => GiroPayPayment::class, - iDealPayment::PAYMENT_METHOD_NAME => iDealPayment::class, - KbcPayment::PAYMENT_METHOD_NAME => KbcPayment::class, - KlarnaOnePayment::PAYMENT_METHOD_NAME => KlarnaOnePayment::class, - MbWayPayment::PAYMENT_METHOD_NAME => MbWayPayment::class, - MultibancoPayment::PAYMENT_METHOD_NAME => MultibancoPayment::class, - MyBankPayment::PAYMENT_METHOD_NAME => MyBankPayment::class, - PayByBankPayment::PAYMENT_METHOD_NAME => PayByBankPayment::class, - PayconiqPayment::PAYMENT_METHOD_NAME => PayconiqPayment::class, - PayPalPayment::PAYMENT_METHOD_NAME => PayPalPayment::class, - Przelewy24Payment::PAYMENT_METHOD_NAME => Przelewy24Payment::class, - RivertyPayment::PAYMENT_METHOD_NAME => RivertyPayment::class, - SatispayPayment::PAYMENT_METHOD_NAME => SatispayPayment::class, - SwishPayment::PAYMENT_METHOD_NAME => SwishPayment::class, - TrustlyPayment::PAYMENT_METHOD_NAME => TrustlyPayment::class, - TwintPayment::PAYMENT_METHOD_NAME => TwintPayment::class, - VoucherPayment::PAYMENT_METHOD_NAME => VoucherPayment::class, - MobilePayPayment::PAYMENT_METHOD_NAME => MobilePayPayment::class, - VippsPayment::PAYMENT_METHOD_NAME => VippsPayment::class, - ]; - public function getPaymentMethodByTechnicalName(string $technicalName, Context $context): PaymentMethodEntity { /** @var EntityRepository $repository */ $repository = $this->getContainer()->get('payment_method.repository'); $criteria = new Criteria(); - $handlerIdentifier = $this->paymentMethodMapping[$technicalName] ?? null; - if ($handlerIdentifier === null) { - throw new \RuntimeException('Handler identifier not found'); + $criteria->addFilter(new EqualsFilter('technicalName', 'payment_mollie_' . $technicalName)); + $searchResult = $repository->search($criteria, $context); + /** @var ?PaymentMethodEntity $firstPaymentMethod */ + $firstPaymentMethod = $searchResult->first(); + if ($firstPaymentMethod === null) { + throw new \RuntimeException(sprintf('Payment method not found for technical name "payment_mollie_%s"', $technicalName)); } - $criteria->addFilter(new EqualsFilter('handlerIdentifier', $handlerIdentifier)); - return $repository->search($criteria, $context)->first(); + return $firstPaymentMethod; } public function getPaymentMethodByIdentifier(string $handlerIdentifier, Context $context): PaymentMethodEntity @@ -109,8 +39,13 @@ public function getPaymentMethodByIdentifier(string $handlerIdentifier, Context $criteria = new Criteria(); $criteria->addFilter(new EqualsFilter('handlerIdentifier', $handlerIdentifier)); + $searchResult = $repository->search($criteria, $context); + $firstPaymentMethod = $searchResult->first(); + if ($firstPaymentMethod === null) { + throw new \RuntimeException(sprintf('Payment method not found for handler "%s"', $handlerIdentifier)); + } - return $repository->search($criteria, $context)->first(); + return $firstPaymentMethod; } public function activatePaymentMethod(PaymentMethodEntity $paymentMethod, Context $context): void diff --git a/tests/Integration/Data/ProductTestBehaviour.php b/tests/Integration/Data/ProductTestBehaviour.php index 39bb0d2c5..2edb681fe 100644 --- a/tests/Integration/Data/ProductTestBehaviour.php +++ b/tests/Integration/Data/ProductTestBehaviour.php @@ -1,7 +1,7 @@ > $repository */ + $repository = $this->getContainer()->get('mollie_subscription.repository'); + + $criteria = new Criteria(); + + $criteria->addFilter(new EqualsFilter('orderId', $orderId)); + + return $repository->search($criteria, $context)->first(); + } +} diff --git a/tests/Integration/MolliePage/MolliePage.php b/tests/Integration/MolliePage/MolliePage.php new file mode 100644 index 000000000..39371da79 --- /dev/null +++ b/tests/Integration/MolliePage/MolliePage.php @@ -0,0 +1,139 @@ +client = new Client(); + } + + public function selectIssuer(string $issuer): ResponseInterface + { + $page = $this->loadPage($this->url); + $dom = $page->getDom(); + + $form = $dom->getElementById('body'); + $inputs = $form->getElementsByTagName('input'); + + $formData = [ + 'issuer' => $issuer, + ]; + + foreach ($inputs as $input) { + $inputName = $input->getAttribute('name'); + $inputValue = $input->getAttribute('value'); + if (isset($formData[$inputName])) { + continue; + } + $formData[$inputName] = $inputValue; + } + + return $this->submit($page->getUrl(), $formData); + } + + public function selectPaymentStatus(string $paymentStatus): ResponseInterface + { + $page = $this->loadPage($this->url); + $dom = $page->getDom(); + $form = $dom->getElementById('body'); + + $inputs = $form->getElementsByTagName('input'); + + $formData = [ + 'submit' => '' + ]; + + foreach ($inputs as $input) { + $inputName = $input->getAttribute('name'); + $inputValue = $input->getAttribute('value'); + $inputType = $input->getAttribute('type'); + + if ($inputType === 'radio' && $inputValue === $paymentStatus) { + $formData[$inputName] = $inputValue; + continue; + } + if (isset($formData[$inputName])) { + continue; + } + $formData[$inputName] = $inputValue; + } + + Assert::assertTrue(isset($formData['final_state'])); + Assert::assertEquals($paymentStatus, $formData['final_state']); + + return $this->submit($page->getUrl(), $formData); + } + + public function selectPaymentMethod(string $molliePaymentMethod): ResponseInterface + { + $page = $this->loadPage($this->url); + $dom = $page->getDom(); + + $form = $dom->getElementById('body'); + $url = $form->getAttribute('action'); + $inputs = $form->getElementsByTagName('input'); + + $formData = [ + 'method' => $molliePaymentMethod, + ]; + + foreach ($inputs as $input) { + $inputName = $input->getAttribute('name'); + $inputValue = $input->getAttribute('value'); + if (isset($formData[$inputName])) { + continue; + } + $formData[$inputName] = $inputValue; + } + + return $this->submit($url, $formData); + } + + public function getShopwareReturnPage(): string + { + $response = $this->client->get($this->url, [ + RequestOptions::ALLOW_REDIRECTS => false, + ]); + + return $response->getHeaderLine('location'); + } + + private function loadPage(string $url): PageResponse + { + $response = $this->client->get($url, [RequestOptions::ALLOW_REDIRECTS => false]); + + $formLocation = $response->getHeader('location')[0] ?? null; + if ($formLocation === null) { + $htmlContent = $response->getBody()->getContents(); + $formLocation = $url; + } else { + $htmlContent = file_get_contents($formLocation); + } + + $dom = new \DOMDocument(); + try { + $dom = $dom->loadHTML($htmlContent); + } catch (\Throwable $exception) { + } + + return new PageResponse($formLocation, $dom); + } + + private function submit(string $url, array $formData): ResponseInterface + { + return $this->client->post($url, [ + RequestOptions::FORM_PARAMS => $formData, + RequestOptions::ALLOW_REDIRECTS => false, + ]); + } +} diff --git a/tests/Integration/MolliePage/PageResponse.php b/tests/Integration/MolliePage/PageResponse.php new file mode 100644 index 000000000..961f654cf --- /dev/null +++ b/tests/Integration/MolliePage/PageResponse.php @@ -0,0 +1,23 @@ +url; + } + + public function getDom(): \DOMDocument + { + return $this->dom; + } +} diff --git a/tests/Integration/Repository/OrderTransactionRepositoryTest.php b/tests/Integration/Repository/OrderTransactionRepositoryTest.php index d3295b7dd..db9cd0fb3 100644 --- a/tests/Integration/Repository/OrderTransactionRepositoryTest.php +++ b/tests/Integration/Repository/OrderTransactionRepositoryTest.php @@ -1,26 +1,28 @@ getContainer()->get(VersionCompare::class); - if ($versionCompare->lt('6.5')) { - $this->markTestSkipped( - 'We have issues with shopware version below 6.5, we skip the tests for now' - ); - } - if (method_exists($this, 'disableNestTransactionsWithSavepointsForNextTest')) { - $this->disableNestTransactionsWithSavepointsForNextTest(); - } + $this->createdOrders = []; + $this->createTestOrders(); + $salesChannelContext = $this->getDefaultSalesChannelContext(); + $orderTransactionRepository = $this->getContainer()->get(OrderTransactionRepository::class); + $searchResult = $orderTransactionRepository->findOpenTransactions($salesChannelContext->getContext()); + + $this->assertGreaterThanOrEqual(1, $searchResult->getTotal()); + $this->deleteAllOrders($this->createdOrders, new Context(new SystemSource())); + } + + /** + * create a non mollie order, a normal mollie order and order which is older than 10 minutes. + * when we search for open orders, we will find this one which is older than 10 minutes + */ + private function createTestOrders(): void + { $salesChannelContext = $this->getDefaultSalesChannelContext(); $paypalPaymentMethod = $this->getPaymentMethodByIdentifier(PayPalPayment::class, $salesChannelContext->getContext()); @@ -50,50 +60,37 @@ protected function setUp(): void $this->activatePaymentMethod($paypalPaymentMethod, $salesChannelContext->getContext()); $this->assignPaymentMethodToSalesChannel($paypalPaymentMethod, $salesChannelContext->getSalesChannel(), $salesChannelContext->getContext()); - $salesChannelContext = $this->loginOrCreateAccount('test@mollie.com', $salesChannelContext); + $salesChannelContext = $this->getSalesChannelContestWithCustomer($salesChannelContext); $salesChannelContext = $this->createOrderWithCashPayment($salesChannelContext); $this->assertNotNull($salesChannelContext->getCustomer()); - $salesChannelContext = $this->createMollieOrderWithPaymentMethod('paid', $paypalPaymentMethod, $salesChannelContext); - - $salesChannelContext = $this->createMollieOrderWithPaymentMethod('paid', $paypalPaymentMethod, $salesChannelContext); + $salesChannelContext = $this->createMollieOrderWithPaymentMethod($paypalPaymentMethod, $salesChannelContext); + $latestOrderId = $this->getLatestOrderId($salesChannelContext->getContext()); + $this->createdOrders[] = $latestOrderId; + $salesChannelContext = $this->createMollieOrderWithPaymentMethod($paypalPaymentMethod, $salesChannelContext); $latestOrderId = $this->getLatestOrderId($salesChannelContext->getContext()); + $this->createdOrders[] = $latestOrderId; $this->updateOrder($latestOrderId, [ 'orderDateTime' => (new \DateTime())->modify('-10 minutes')->format(Defaults::STORAGE_DATE_TIME_FORMAT), ], $salesChannelContext->getContext()); } - protected function tearDown(): void - { - $versionCompare = $this->getContainer()->get(VersionCompare::class); - if ($versionCompare->lt('6.5')) { - $this->markTestSkipped( - 'We have issues with shopware version below 6.5, we skip the tests for now' - ); - } - $result = $this->deleteAllOrders(Context::createDefaultContext()); - $this->assertNotNull($result); - } - - public function testMollieTransactionsAreLoaded(): void + private function getSalesChannelContestWithCustomer(?SalesChannelContext $salesChannelContext = null): SalesChannelContext { - $versionCompare = $this->getContainer()->get(VersionCompare::class); - if ($versionCompare->lt('6.5')) { - $this->markTestSkipped( - 'We have issues with shopware version below 6.5, we skip the tests for now' - ); + if ($salesChannelContext === null) { + $salesChannelContext = $this->getDefaultSalesChannelContext(); } - $salesChannelContext = $this->getDefaultSalesChannelContext(); - $orderTransactionRepository = $this->getContainer()->get(OrderTransactionRepository::class); - $searchResult = $orderTransactionRepository->findOpenTransactions($salesChannelContext->getContext()); + $customerId = $this->getUserIdByEmail('cypress@mollie.com', $salesChannelContext); - $this->assertSame(1, $searchResult->getTotal()); + return $this->getDefaultSalesChannelContext(options: [ + SalesChannelContextService::CUSTOMER_ID => $customerId + ]); } - private function createMollieOrderWithPaymentMethod(string $status, PaymentMethodEntity $paymentMethod, SalesChannelContext $salesChannelContext): SalesChannelContext + private function createMollieOrderWithPaymentMethod(PaymentMethodEntity $paymentMethod, SalesChannelContext $salesChannelContext): SalesChannelContext { $salesChannelContext = $this->setPaymentMethod($paymentMethod, $salesChannelContext); $this->assertNotNull($salesChannelContext->getCustomer()); @@ -104,8 +101,6 @@ private function createMollieOrderWithPaymentMethod(string $status, PaymentMetho $this->assertStringContainsString('mollie.com', $response->getTargetUrl()); - $this->selectMolliePaymentStatus($status, $response->getTargetUrl()); - return $salesChannelContext; } @@ -120,6 +115,10 @@ private function createOrderWithCashPayment(SalesChannelContext $salesChannelCon $this->addItemToCart('SWDEMO10007.1', $salesChannelContext); /** @var RedirectResponse $response */ $response = $this->startCheckout($salesChannelContext); + $urlParts = []; + $queryString = parse_url($response->getTargetUrl(), PHP_URL_QUERY); + parse_str($queryString, $urlParts); + $this->createdOrders[] = $urlParts['orderId']; return $salesChannelContext; } diff --git a/tests/Integration/Settings/ApiSettingsTest.php b/tests/Integration/Settings/ApiSettingsTest.php new file mode 100644 index 000000000..5b5fa6e38 --- /dev/null +++ b/tests/Integration/Settings/ApiSettingsTest.php @@ -0,0 +1,59 @@ +getContainer()->get(SystemConfigService::class); + $oldTestKey = $systemConfigService->get(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_API_KEY); + $oldLiveKey = $systemConfigService->get(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_LIVE_API_KEY); + + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_MODE, true); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_LIVE_API_KEY, 'live_key'); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_API_KEY, 'test_key'); + + $devMode = (int) EnvironmentHelper::getVariable('MOLLIE_DEV_MODE', 0); + $cypressMode = (int) EnvironmentHelper::getVariable('MOLLIE_CYPRESS_MODE', 0); + $settingsService = new SettingsService($systemConfigService, $devMode, $cypressMode); + $apiSettings = $settingsService->getApiSettings(); + + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_LIVE_API_KEY, $oldLiveKey); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . ApiSettings::KEY_TEST_API_KEY, $oldTestKey); + + $this->assertSame('test_key', $apiSettings->getTestApiKey()); + $this->assertSame('live_key', $apiSettings->getLiveApiKey()); + $this->assertTrue($apiSettings->isTestMode()); + $this->assertSame('test_key', $apiSettings->getApiKey()); + $this->assertNotSame('live_key', $apiSettings->getApiKey()); + } + + public function testSettingsAreCachedPerSalesChannel(): void + { + $settingsService = $this->getContainer()->get(SettingsService::class); + + $expectedSettings = $settingsService->getApiSettings(); + $actualSettings = $settingsService->getApiSettings(); + $differentSalesChannelSettings = $settingsService->getApiSettings(Uuid::randomHex()); + + $this->assertSame($expectedSettings, $actualSettings); + $this->assertNotSame($actualSettings, $differentSalesChannelSettings); + } +} diff --git a/tests/Integration/Settings/EnvironmentSettingsTest.php b/tests/Integration/Settings/EnvironmentSettingsTest.php new file mode 100644 index 000000000..5a2ce65ca --- /dev/null +++ b/tests/Integration/Settings/EnvironmentSettingsTest.php @@ -0,0 +1,36 @@ +getContainer()->get(SystemConfigService::class); + + $devMode = (int) EnvironmentHelper::getVariable('MOLLIE_DEV_MODE', 0); + $cypressMode = (int) EnvironmentHelper::getVariable('MOLLIE_CYPRESS_MODE', 0); + $settingsService = new SettingsService($systemConfigService, $devMode, $cypressMode); + + $environmentSettings = $settingsService->getEnvironmentSettings(); + + $this->assertFalse($environmentSettings->isDevMode()); + $this->assertTrue($environmentSettings->isCypressMode()); + } +} diff --git a/tests/Integration/Settings/LoggerSettingsTest.php b/tests/Integration/Settings/LoggerSettingsTest.php index f34f4df42..70427adbd 100644 --- a/tests/Integration/Settings/LoggerSettingsTest.php +++ b/tests/Integration/Settings/LoggerSettingsTest.php @@ -1,49 +1,50 @@ disableNestTransactionsWithSavepointsForNextTest(); - } - } - public function testSettingsCanBeReadFromDatabase(): void { /** * @var SystemConfigService $systemConfigService */ $systemConfigService = $this->getContainer()->get(SystemConfigService::class); + $oldLogFileDays = $systemConfigService->get(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_LOG_FILE_DAYS); + $oldDebugMode = $systemConfigService->get(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_DEBUG_MODE); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_LOG_FILE_DAYS, 10); $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_DEBUG_MODE, false); - $settingsService = new SettingsService($this->getContainer()); + $devMode = (int) EnvironmentHelper::getVariable('MOLLIE_DEV_MODE', 0); + $cypressMode = (int) EnvironmentHelper::getVariable('MOLLIE_CYPRESS_MODE', 0); + $settingsService = new SettingsService($systemConfigService, $devMode, $cypressMode); $actualSettings = $settingsService->getLoggerSettings(); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_LOG_FILE_DAYS, $oldLogFileDays); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . LoggerSettings::KEY_DEBUG_MODE, $oldDebugMode); + $this->assertSame(10, $actualSettings->getLogFileDays()); $this->assertFalse($actualSettings->isDebugMode()); } public function testSettingsAreCachedPerSalesChannel(): void { - $settingsService = new SettingsService($this->getContainer()); + $settingsService = $this->getContainer()->get(SettingsService::class); $expectedSettings = $settingsService->getLoggerSettings(); $actualSettings = $settingsService->getLoggerSettings(); diff --git a/tests/Integration/Settings/PaymentSettingsTest.php b/tests/Integration/Settings/PaymentSettingsTest.php new file mode 100644 index 000000000..b4dff69de --- /dev/null +++ b/tests/Integration/Settings/PaymentSettingsTest.php @@ -0,0 +1,47 @@ +getContainer()->get(SystemConfigService::class); + $oldNumberFormat = $systemConfigService->get(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . PaymentSettings::KEY_ORDER_NUMBER_FORMAT); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . PaymentSettings::KEY_ORDER_NUMBER_FORMAT, 'test_{ordernumber}_{customernumber}'); + $devMode = (int) EnvironmentHelper::getVariable('MOLLIE_DEV_MODE', 0); + $cypressMode = (int) EnvironmentHelper::getVariable('MOLLIE_CYPRESS_MODE', 0); + $settingsService = new SettingsService($systemConfigService, $devMode, $cypressMode); + $paymentSettings = $settingsService->getPaymentSettings(); + $systemConfigService->set(SettingsService::SYSTEM_CONFIG_DOMAIN . '.' . PaymentSettings::KEY_ORDER_NUMBER_FORMAT, $oldNumberFormat); + $this->assertSame('test_{ordernumber}_{customernumber}', $paymentSettings->getOrderNumberFormat()); + } + + public function testSettingsAreCachedPerSalesChannel(): void + { + $settingsService = $this->getContainer()->get(SettingsService::class); + + $expectedSettings = $settingsService->getPaymentSettings(); + $actualSettings = $settingsService->getPaymentSettings(); + $differentSalesChannelSettings = $settingsService->getPaymentSettings(Uuid::randomHex()); + + $this->assertSame($expectedSettings, $actualSettings); + $this->assertNotSame($actualSettings, $differentSalesChannelSettings); + } +} diff --git a/tests/Integration/Settings/ShippingMethodsTest.php b/tests/Integration/Settings/ShippingMethodsTest.php index 8afea32b0..ff6783ab8 100644 --- a/tests/Integration/Settings/ShippingMethodsTest.php +++ b/tests/Integration/Settings/ShippingMethodsTest.php @@ -1,10 +1,10 @@ handle($flowEvent); + if (class_exists(FlowEvent::class) && $flowEvent instanceof FlowEvent) { + $action->handle($flowEvent); + } else { + $action->handleFlow($flowEvent); + } // verify the passed request object $this->assertEquals('ord-123', $fakeRefundManager->getRefundRequest()->getOrderNumber()); diff --git a/tests/PHPUnit/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderActionTest.php b/tests/PHPUnit/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderActionTest.php index f38cfbef1..9c40b8555 100644 --- a/tests/PHPUnit/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderActionTest.php +++ b/tests/PHPUnit/Compatibility/Bundles/FlowBuilder/Actions/ShipOrderActionTest.php @@ -1,15 +1,16 @@ handle($flowEvent); + if (class_exists(FlowEvent::class) && $flowEvent instanceof FlowEvent) { + $action->handle($flowEvent); + } else { + $action->handleFlow($flowEvent); + } // let's see if our shipment service did receive // the correct calls and data diff --git a/tests/PHPUnit/Components/ApplePayDirect/Gateways/ApplePayDirectDomainAllowListGatewayTest.php b/tests/PHPUnit/Components/ApplePayDirect/Gateways/ApplePayDirectDomainAllowListGatewayTest.php index 332a6eba0..f6706b4fc 100644 --- a/tests/PHPUnit/Components/ApplePayDirect/Gateways/ApplePayDirectDomainAllowListGatewayTest.php +++ b/tests/PHPUnit/Components/ApplePayDirect/Gateways/ApplePayDirectDomainAllowListGatewayTest.php @@ -1,7 +1,7 @@ sanitizer = new ApplePayDirectDomainSanitizer(); } - /** - * @dataProvider sanitationTestDataProvider - */ + #[DataProvider('sanitationTestDataProvider')] public function testProvidesSanitizedDomain(string $url, string $expected): void { $sanitizedUrl = $this->sanitizer->sanitizeDomain($url); @@ -25,7 +24,7 @@ public function testProvidesSanitizedDomain(string $url, string $expected): void $this->assertEquals($expected, $sanitizedUrl); } - public function sanitationTestDataProvider(): array + public static function sanitationTestDataProvider(): array { return [ 'removes http value if provided' => ['http://example.com', 'example.com'], diff --git a/tests/PHPUnit/Components/CancelManager/CancelItemFacadeTest.php b/tests/PHPUnit/Components/CancelManager/CancelItemFacadeTest.php index 6e340ab26..384e861da 100644 --- a/tests/PHPUnit/Components/CancelManager/CancelItemFacadeTest.php +++ b/tests/PHPUnit/Components/CancelManager/CancelItemFacadeTest.php @@ -1,15 +1,15 @@ setupConnection($enLangId, $deLangId); - + $matcher = $this->exactly(4); $this->connection - ->expects($this->exactly(4)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template_type'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($deLangId)], - [ - $this->equalTo('mail_template_type_translation'), - $this->containsEqual(Uuid::fromHexToBytes(Defaults::LANGUAGE_SYSTEM)), - ], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId,$defaultLanguageId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals('mail_template_type',$tableName); + $this->assertIsArray($data); + + return 1; + } + $this->assertEquals('mail_template_type_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContainsEquals($deLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertContainsEquals($defaultLanguageId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -148,15 +166,30 @@ public function testCreateMailTypeWhereDefaultLangIsEnglish() $deLangId = 'bar'; $this->setupConnection($enLangId, $deLangId); + $matcher = $this->exactly(3); $this->connection - ->expects($this->exactly(3)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template_type'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($deLangId)], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals('mail_template_type',$tableName); + $this->assertIsArray($data); + + return 1; + } + $this->assertEquals('mail_template_type_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContainsEquals($deLangId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -184,15 +217,29 @@ public function testCreateMailTypeWhereDefaultLangIsGerman() $deLangId = Uuid::fromHexToBytes(Defaults::LANGUAGE_SYSTEM); $this->setupConnection($enLangId, $deLangId); + $matcher = $this->exactly(3); $this->connection - ->expects($this->exactly(3)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template_type'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_type_translation'), $this->containsEqual($deLangId)], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('mail_template_type',$tableName); + + return 1; + } + $this->assertSame('mail_template_type_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContainsEquals($deLangId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -220,21 +267,38 @@ public function testCreateMailTemplateWhereDefaultLangIsNotEnglishOrGerman() $enLangId = 'foo'; $deLangId = 'bar'; + $defaultLanguageId = Uuid::fromHexToBytes(Defaults::LANGUAGE_SYSTEM); $this->setupConnection($enLangId, $deLangId); - + $matcher = $this->exactly(4); $this->connection - ->expects($this->exactly(4)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($deLangId)], - [ - $this->equalTo('mail_template_translation'), - $this->containsEqual(Uuid::fromHexToBytes(Defaults::LANGUAGE_SYSTEM)), - ], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId,$defaultLanguageId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('mail_template',$tableName); + $this->assertIsArray($data); + + return 1; + } + + $this->assertSame('mail_template_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContainsEquals($deLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 4) { + $this->assertContainsEquals($defaultLanguageId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -262,15 +326,29 @@ public function testCreateMailTemplateWhereDefaultLangIsEnglish() $deLangId = 'bar'; $this->setupConnection($enLangId, $deLangId); - + $matcher = $this->exactly(3); $this->connection - ->expects($this->exactly(3)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($deLangId)], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame('mail_template',$tableName); + $this->assertIsArray($data); + + return 1; + } + $this->assertSame('mail_template_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContainsEquals($deLangId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -298,15 +376,29 @@ public function testCreateMailTemplateWhereDefaultLangIsGerman() $deLangId = Uuid::fromHexToBytes(Defaults::LANGUAGE_SYSTEM); $this->setupConnection($enLangId, $deLangId); - + $matcher = $this->exactly(3); $this->connection - ->expects($this->exactly(3)) + ->expects($matcher) ->method('insert') - ->withConsecutive( - [$this->equalTo('mail_template'), $this->isType(IsType::TYPE_ARRAY)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($enLangId)], - [$this->equalTo('mail_template_translation'), $this->containsEqual($deLangId)], - ) + ->willReturnCallback(function (string $tableName,array $data) use ($matcher,$enLangId,$deLangId) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertSame($tableName,'mail_template'); + $this->assertIsArray($data); + + return 1; + } + $this->assertEquals('mail_template_translation',$tableName); + if ($matcher->numberOfInvocations() === 2) { + $this->assertContainsEquals($enLangId,$data); + + return 1; + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertContains($deLangId,$data); + + return 1; + } + }) ; $this->repoMailTypes @@ -321,32 +413,30 @@ public function testCreateMailTemplateWhereDefaultLangIsGerman() // ----Connection---------------------------------------- private function setupConnection($enLangId, $deLangId) { - $enResult = $this->createConfiguredMock(Result::class, [ - 'fetchColumn' => $enLangId, - 'fetchOne' => $enLangId, - ]); - $deResult = $this->createConfiguredMock(Result::class, [ - 'fetchColumn' => $deLangId, - 'fetchOne' => $deLangId, - ]); + $enResult = new Result(new ArrayResult([],[[$enLangId]]),$this->createMock(Connection::class)); + $deResult = new Result(new ArrayResult([],[[$deLangId]]),$this->createMock(Connection::class)); + $matcher = $this->atLeast(2); $this->connection - ->expects($this->atLeast(2)) + ->expects($matcher) ->method('executeQuery') - ->withConsecutive( - [$this->isType(IsType::TYPE_STRING), $this->containsEqual('en-GB')], - [$this->isType(IsType::TYPE_STRING), $this->containsEqual('de-DE')], - ) - ->willReturnOnConsecutiveCalls($enResult, $deResult) + ->willReturnCallback(function (string $sql,array $parameters) use ($enResult, $deResult) { + $code = $parameters['code']; + + if ($code === 'en-GB') { + return $enResult; + } + if ($code === 'de-DE') { + return $deResult; + } + }) ; } // ----MailType---------------------------------------- private function setupMailTypeRepoWithoutData() { - $result = $this->createConfiguredMock(IdSearchResult::class, [ - 'getIds' => [], - ]); + $result = new IdSearchResult(0,[],new Criteria(),Context::createDefaultContext()); $this->repoMailTypes->method('searchIds')->willReturn($result); $this->repoMailTypes->expects($this->once())->method('searchIds'); @@ -354,10 +444,13 @@ private function setupMailTypeRepoWithoutData() private function setupMailTypeRepoWithExistingData($id) { - $result = $this->createConfiguredMock(IdSearchResult::class, [ - 'getIds' => [$id], - 'firstId' => $id, - ]); + $data = [ + 'primaryKey' => $id, + 'data' => [ + 'id' => $id, + ] + ]; + $result = new IdSearchResult(1,[$data],new Criteria(),Context::createDefaultContext()); $this->repoMailTypes->method('searchIds')->willReturn($result); $this->repoMailTypes->expects($this->once())->method('searchIds'); @@ -366,9 +459,7 @@ private function setupMailTypeRepoWithExistingData($id) // ----MailTemplate---------------------------------------- private function setupMailTemplateRepoWithoutData() { - $result = $this->createConfiguredMock(IdSearchResult::class, [ - 'getIds' => [], - ]); + $result = new IdSearchResult(0,[],new Criteria(),Context::createDefaultContext()); $this->repoMailTemplates->method('searchIds')->willReturn($result); $this->repoMailTemplates->expects($this->once())->method('searchIds'); @@ -376,11 +467,13 @@ private function setupMailTemplateRepoWithoutData() private function setupMailTemplateRepoWithExistingData($id) { - $result = $this->createConfiguredMock(IdSearchResult::class, [ - 'getIds' => [$id], - 'firstId' => $id, - ]); - + $data = [ + 'primaryKey' => $id, + 'data' => [ + 'id' => $id, + ] + ]; + $result = new IdSearchResult(1,[$data],new Criteria(),Context::createDefaultContext()); $this->repoMailTemplates->method('searchIds')->willReturn($result); $this->repoMailTemplates->expects($this->once())->method('searchIds'); } diff --git a/tests/PHPUnit/Components/PaypalExpress/CancelCheckoutRouteTest.php b/tests/PHPUnit/Components/PaypalExpress/CancelCheckoutRouteTest.php deleted file mode 100644 index 9356713dd..000000000 --- a/tests/PHPUnit/Components/PaypalExpress/CancelCheckoutRouteTest.php +++ /dev/null @@ -1,69 +0,0 @@ -getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new CancelCheckoutRoute($settingsService, $cartService, $paypalExpress); - - $this->expectException(DecorationPatternException::class); - $route->getDecorated(); - } - - public function testPaymentIsNotEnabledExceptionIsThrown(): void - { - $settingsService = $this->getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new CancelCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->cancelCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::PAYMENT_METHOD_DISABLED); - } - } - - public function testCartSessionIdIsMissing(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new CancelCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->cancelCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_CART_SESSION_ID); - } - } - - public function testCancelCheckoutSuccess(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - $paypalExpress = $this->getPaypalExpress(); - - $route = new CancelCheckoutRoute($settingsService, $cartService, $paypalExpress); - - $response = $route->cancelCheckout($this->getContext()); - $this->assertNotNull($response->getSessionId()); - } -} diff --git a/tests/PHPUnit/Components/PaypalExpress/FinishCheckoutRouteTest.php b/tests/PHPUnit/Components/PaypalExpress/FinishCheckoutRouteTest.php deleted file mode 100644 index c1245cecf..000000000 --- a/tests/PHPUnit/Components/PaypalExpress/FinishCheckoutRouteTest.php +++ /dev/null @@ -1,185 +0,0 @@ -getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - $this->expectException(DecorationPatternException::class); - $route->getDecorated(); - } - - public function testPaymentIsNotEnabledExceptionIsThrown(): void - { - $settingsService = $this->getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::PAYMENT_METHOD_DISABLED); - } - } - - public function testCartSessionIdIsMissing(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_CART_SESSION_ID); - } - } - - public function testSessionShippingAddressIsMissing(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - $paypalExpress = $this->getPaypalExpress(true, false, true); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_SHIPPING_ADDRESS); - } - } - - public function testSessionBillingAddressIsMissing(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - $methodDetails = new \stdClass(); - $methodDetails->shippingAddress = new \stdClass(); - - $paypalExpress = $this->getPaypalExpress(true, false, true, false, false, $methodDetails); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_BILLING_ADDRESS); - } - } - - public function testBillingAddressParsingError(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - $methodDetails = new \stdClass(); - $methodDetails->shippingAddress = new \stdClass(); - $billingAddress = new \stdClass(); - $billingAddress->streetAndNumber = 'fake 10'; - $billingAddress->streetAdditional = 'B'; - $billingAddress->phone = '01235'; - $billingAddress->email = 'fake@fake'; - $methodDetails->billingAddress = $billingAddress; - - $paypalExpress = $this->getPaypalExpress(true, false, true, false, true, $methodDetails); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::BILLING_ADDRESS_PARSING_ERROR); - } - } - - public function testShippingAddressParsingError(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - $methodDetails = new \stdClass(); - $methodDetails->shippingAddress = new \stdClass(); - $billingAddress = new \stdClass(); - $billingAddress->streetAndNumber = 'fake 10'; - - $billingAddress->streetAdditional = 'B'; - $billingAddress->phone = '01235'; - $billingAddress->email = 'fake@fake'; - $billingAddress->givenName = 'test'; - $billingAddress->familyName = 'test'; - $billingAddress->postalCode = '01234'; - $billingAddress->city = 'test'; - $billingAddress->country = 'test'; - $methodDetails->billingAddress = $billingAddress; - - $paypalExpress = $this->getPaypalExpress(true, false, true, false, false, $methodDetails); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - - try { - $route->finishCheckout($this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::SHIPPING_ADDRESS_PARSING_ERROR); - } - } - - public function testAuthenticateIdSetInCartExtension(): void - { - $settingsService = $this->getSettings(true, true); - $cartService = $this->getCartService(true, true, true); - $methodDetails = new \stdClass(); - $shippingAddress = new \stdClass(); - $shippingAddress->givenName = 'test'; - $shippingAddress->familyName = 'test'; - $shippingAddress->streetAndNumber = 'Fakestreet 10'; - $shippingAddress->postalCode = '12356'; - $shippingAddress->city = 'test'; - $shippingAddress->country = 'test'; - $methodDetails->shippingAddress = $shippingAddress; - $billingAddress = new \stdClass(); - $billingAddress->streetAndNumber = 'fake 10'; - - $billingAddress->streetAdditional = 'B'; - $billingAddress->phone = '01235'; - $billingAddress->email = 'fake@fake'; - $billingAddress->givenName = 'test'; - $billingAddress->familyName = 'test'; - $billingAddress->postalCode = '01234'; - $billingAddress->city = 'test'; - $billingAddress->country = 'test'; - $methodDetails->billingAddress = $billingAddress; - - $paypalExpress = $this->getPaypalExpress(true, false, true, false, true, $methodDetails); - - $route = new FinishCheckoutRoute($settingsService, $cartService, $paypalExpress); - $response = $route->finishCheckout($this->getContext()); - $cartExtension = $this->cart->getExtension(CustomFieldsInterface::MOLLIE_KEY); - - $this->assertNotNull($response->getSessionId()); - $this->assertNotNull($response->getAuthenticateId()); - - $this->assertInstanceOf(ArrayStruct::class, $cartExtension); - $this->assertSame('fakeAuthenticationId', $cartExtension[CustomFieldsInterface::PAYPAL_EXPRESS_AUTHENTICATE_ID]); - } -} diff --git a/tests/PHPUnit/Components/PaypalExpress/PayPalExpressMockTrait.php b/tests/PHPUnit/Components/PaypalExpress/PayPalExpressMockTrait.php deleted file mode 100644 index 36db17096..000000000 --- a/tests/PHPUnit/Components/PaypalExpress/PayPalExpressMockTrait.php +++ /dev/null @@ -1,113 +0,0 @@ -cart = null; - } - - private function getSettings(bool $paymentEnabled = false, bool $requiredDataProtection = false): SettingsService - { - /** @var SettingsService $settingsService */ - $settingsService = $this->createMock(SettingsService::class); - $settings = new MollieSettingStruct(); - if ($paymentEnabled) { - $settings->setPaypalExpressEnabled(true); - } - if ($requiredDataProtection) { - $settings->setRequireDataProtectionCheckbox(true); - } - $settingsService->method('getSettings')->willReturn($settings); - - return $settingsService; - } - - private function getCartService(bool $withCart = false, bool $withLineItems = false, bool $withFakeSessionId = false): CartServiceInterface - { - /** @var CartServiceInterface $cartService */ - $cartService = $this->createMock(CartServiceInterface::class); - - if ($withCart) { - $fakeCart = new Cart('fake', 'fake'); - - if ($withLineItems) { - $fakeLineItem = $this->createMock(LineItem::class); - $lineItemsCollection = new LineItemCollection([$fakeLineItem]); - - $fakeCart->setLineItems($lineItemsCollection); - } - - if ($withFakeSessionId) { - $fakeCart->addExtensions([ - CustomFieldsInterface::MOLLIE_KEY => new ArrayStruct([ - CustomFieldsInterface::PAYPAL_EXPRESS_SESSION_ID_KEY => 'fakeLoadedSessionId', - ]), - ]); - } - - $this->cart = $fakeCart; - $cartService->expects($this->once())->method('getCalculatedMainCart')->willReturn($fakeCart); - } - - return $cartService; - } - - private function getPaypalExpress(bool $withSessionId = false, bool $withStartSession = false, bool $withLoadSession = false, bool $withRedirectUrl = false, bool $withAuthenticateId = false, ?\stdClass $methodDetails = null): PayPalExpress - { - if ($methodDetails === null) { - $methodDetails = new \stdClass(); - } - /** @var PayPalExpress $paypalExpress */ - $paypalExpress = $this->createMock(PayPalExpress::class); - $fakeSession = $this->createMock(Session::class); - - if ($withSessionId) { - $fakeSession->id = 'fakeSessionId'; - if ($withRedirectUrl) { - $fakeSession->redirectUrl = 'fakeRedirectUrl'; - } - if ($withAuthenticateId) { - $fakeSession->authenticationId = 'fakeAuthenticationId'; - } - $fakeSession->methodDetails = $methodDetails; - } - - if ($withStartSession) { - $paypalExpress->expects($this->once())->method('startSession')->willReturn($fakeSession); - } - if ($withLoadSession) { - $paypalExpress->expects($this->once())->method('loadSession')->willReturn($fakeSession); - } - - return $paypalExpress; - } - - private function getContext(): SalesChannelContext - { - /** - * @var SalesChannelContext $context - */ - $context = $this->createMock(SalesChannelContext::class); - $context->method('getSalesChannelId')->willReturn('fakeSalesChannelId'); - - return $context; - } -} diff --git a/tests/PHPUnit/Components/PaypalExpress/StartCheckoutRouteTest.php b/tests/PHPUnit/Components/PaypalExpress/StartCheckoutRouteTest.php deleted file mode 100644 index ca3638bd6..000000000 --- a/tests/PHPUnit/Components/PaypalExpress/StartCheckoutRouteTest.php +++ /dev/null @@ -1,152 +0,0 @@ -getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - - $this->expectException(DecorationPatternException::class); - $route->getDecorated(); - } - - public function testPaymentIsNotEnabledExceptionIsThrown(): void - { - $settingsService = $this->getSettings(); - $cartService = $this->getCartService(); - $paypalExpress = $this->getPaypalExpress(); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - try { - $route->startCheckout($request, $this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::PAYMENT_METHOD_DISABLED); - } - } - - public function testCartIsEmptyExceptionIsThrown(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true); - - $paypalExpress = $this->getPaypalExpress(); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - try { - $route->startCheckout($request, $this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::EMPTY_CART); - } - } - - public function testStartSessionReturnsEmptyId(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true); - - $paypalExpress = $this->getPaypalExpress(false, true); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - try { - $route->startCheckout($request, $this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_SESSION_ID); - } - } - - public function testLoadSessionReturnsEmptyId(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - - $paypalExpress = $this->getPaypalExpress(false, false, true); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - try { - $route->startCheckout($request, $this->getContext()); - } catch (HttpException $e) { - $this->assertSame($e->getErrorCode(), PaypalExpressException::MISSING_SESSION_ID); - } - } - - public function testStartSessionIdStoresCartExtension(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true); - - $paypalExpress = $this->getPaypalExpress(true, true); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - $response = $route->startCheckout($request, $this->getContext()); - - $this->assertNotNull($response->getSessionId()); - $this->assertSame('fakeSessionId', $this->cart->getExtension(CustomFieldsInterface::MOLLIE_KEY)[CustomFieldsInterface::PAYPAL_EXPRESS_SESSION_ID_KEY]); - } - - public function testLoadSessionIdStoresCartExtension(): void - { - $settingsService = $this->getSettings(true); - $cartService = $this->getCartService(true, true, true); - - $paypalExpress = $this->getPaypalExpress(true, false, true); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - - $response = $route->startCheckout($request, $this->getContext()); - - $this->assertNotNull($response->getSessionId()); - $this->assertSame('fakeSessionId', $this->cart->getExtension(CustomFieldsInterface::MOLLIE_KEY)[CustomFieldsInterface::PAYPAL_EXPRESS_SESSION_ID_KEY]); - } - - public function testDataProtectionFlagIsSet(): void - { - $settingsService = $this->getSettings(true, true); - $cartService = $this->getCartService(true, true, true); - - $paypalExpress = $this->getPaypalExpress(true, false, true); - - $route = new StartCheckoutRoute($settingsService, $cartService, $paypalExpress); - $request = new Request(); - $request->request->set(CustomFieldsInterface::ACCEPTED_DATA_PROTECTION, true); - - $response = $route->startCheckout($request, $this->getContext()); - - $cartExtension = $this->cart->getExtension(CustomFieldsInterface::MOLLIE_KEY); - $this->assertInstanceOf(ArrayStruct::class, $cartExtension); - $this->assertNotNull($response->getSessionId()); - $this->assertSame('fakeSessionId', $cartExtension[CustomFieldsInterface::PAYPAL_EXPRESS_SESSION_ID_KEY]); - $this->assertSame(1, $cartExtension[CustomFieldsInterface::ACCEPTED_DATA_PROTECTION]); - } -} diff --git a/tests/PHPUnit/Components/RefundManager/DAL/RefundItem/RefundItemTest.php b/tests/PHPUnit/Components/RefundManager/DAL/RefundItem/RefundItemTest.php index 95dae84b5..42aa2dc3e 100644 --- a/tests/PHPUnit/Components/RefundManager/DAL/RefundItem/RefundItemTest.php +++ b/tests/PHPUnit/Components/RefundManager/DAL/RefundItem/RefundItemTest.php @@ -1,7 +1,7 @@ buildValidOrder(); @@ -222,13 +222,12 @@ public function testValidItemsAreAdded(int $qty, float $itemPrice): void * We have a strict definition on what is valid or invalid. * So we build invalid items and make sure no refundItems are saved into the database. * - * @testWith [ 0, 0 ] - * [ -1, 20 ] - * * @throws \Mollie\Api\Exceptions\ApiException * @throws \Mollie\Api\Exceptions\ApiException * / */ + #[TestWith([0, 0])] + #[TestWith([-1, 20])] public function testInvalidItemsAreNotAdded(int $qty, float $itemPrice): void { $order = $this->buildValidOrder(); diff --git a/tests/PHPUnit/Components/RefundManager/Request/RefundRequestTest.php b/tests/PHPUnit/Components/RefundManager/Request/RefundRequestTest.php index eab545dd3..23892c1b9 100644 --- a/tests/PHPUnit/Components/RefundManager/Request/RefundRequestTest.php +++ b/tests/PHPUnit/Components/RefundManager/Request/RefundRequestTest.php @@ -1,7 +1,7 @@ setHistoryEntries($subscriptionHistoryEntries); - $subscriptionMetadata = new SubscriptionMetadata('2025-08-13', 2, 'months', null, ''); + $subscriptionMetadata = new SubscriptionMetadata('2025-08-13', 2, IntervalUnit::MONTHS, 0, ''); $fakeSubscription->setMetadata($subscriptionMetadata); $repoSubscriptions = $this->createMock(SubscriptionRepository::class); diff --git a/tests/PHPUnit/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricherTest.php b/tests/PHPUnit/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricherTest.php index b6d83573e..d3ce63f5d 100644 --- a/tests/PHPUnit/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricherTest.php +++ b/tests/PHPUnit/Components/Subscription/DAL/Subscription/Enricher/LiveDataEnricherTest.php @@ -1,10 +1,10 @@ getStartDate()); - static::assertSame(1, $meta->getInterval()); - static::assertSame(IntervalType::MONTHS, $meta->getIntervalUnit()); + static::assertSame(1, $meta->getIntervalValue()); + static::assertSame(IntervalType::MONTHS, $meta->getIntervalUnit()->value); static::assertSame(5, $meta->getTimes()); static::assertSame('tr_123', $meta->getTmpTransaction()); } @@ -30,13 +31,14 @@ public function testProperties(): void */ public function testArrayStructure(): void { - $meta = new SubscriptionMetadata('2022-05-01', 1, IntervalType::MONTHS, 5, 'tr_123'); + $meta = new SubscriptionMetadata('2022-05-01', 1, IntervalUnit::MONTHS, 5, 'tr_123'); $expected = [ 'start_date' => '2022-05-01', 'interval_value' => 1, 'interval_unit' => IntervalType::MONTHS, 'times' => 5, + 'nextPossiblePaymentDate' => '', 'tmp_transaction' => 'tr_123', ]; static::assertSame($expected, $meta->toArray()); @@ -49,29 +51,17 @@ public function testArrayStructure(): void */ public function testSkipTmpTransactionInArrayStructure(): void { - $meta = new SubscriptionMetadata('', 1, IntervalType::MONTHS, null, ''); + $meta = new SubscriptionMetadata('', 1, IntervalUnit::MONTHS, 0, ''); static::assertArrayNotHasKey('tmp_transaction', $meta->toArray()); } - /** - * This test verifies that our times key is created even - * if the value is NULL. - */ - public function testTimesWithNullInArrayStructure(): void - { - $meta = new SubscriptionMetadata('2022-05-01', 1, IntervalType::MONTHS, null, 'tr_123'); - - static::assertArrayHasKey('times', $meta->toArray()); - static::assertSame(null, $meta->toArray()['times']); - } - /** * This test verifies that our property can be used correclty. */ public function testTmpTransactionId(): void { - $meta = new SubscriptionMetadata('2022-05-01', 1, IntervalType::MONTHS, null, 'tr_123'); + $meta = new SubscriptionMetadata('2022-05-01', 1, IntervalUnit::MONTHS, 0, 'tr_123'); $meta->setTmpTransaction('tr_xyz'); diff --git a/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionCollectionTest.php b/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionCollectionTest.php index 2cb853046..3ddcd2a22 100644 --- a/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionCollectionTest.php +++ b/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionCollectionTest.php @@ -1,10 +1,10 @@ '2022-05-01', 'interval_value' => 1, 'interval_unit' => IntervalType::MONTHS, - 'times' => null, + 'times' => 0, + 'nextPossiblePaymentDate' => '', ]; static::assertSame($expected, $returnedMeta->toArray()); diff --git a/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionEventsTest.php b/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionEventsTest.php index 28340b2f0..d9b302f61 100644 --- a/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionEventsTest.php +++ b/tests/PHPUnit/Components/Subscription/DAL/Subscription/SubscriptionEventsTest.php @@ -1,9 +1,9 @@ assertEquals($expected, SubscriptionRemover::ALLOWED_METHODS); - } -} diff --git a/tests/PHPUnit/Components/Subscription/Services/SubscriptionCancellation/CancellationValidatorTest.php b/tests/PHPUnit/Components/Subscription/Services/SubscriptionCancellation/CancellationValidatorTest.php index 7a2e60301..5d0944f89 100644 --- a/tests/PHPUnit/Components/Subscription/Services/SubscriptionCancellation/CancellationValidatorTest.php +++ b/tests/PHPUnit/Components/Subscription/Services/SubscriptionCancellation/CancellationValidatorTest.php @@ -1,9 +1,10 @@ validator->isCancellationAllowed( new \DateTime('2022-07-08'), @@ -43,13 +41,10 @@ public function testNoCancellationRestrictions() * This test verifies that a cancellation on the last possible * day is indeed valid and working for the customer. * - * @group subscriptions - * * @throws \Exception - * - * @return void */ - public function testNoCancellationWithDaysInRange() + #[Group('subscriptions')] + public function testNoCancellationWithDaysInRange(): void { $isAllowed = $this->validator->isCancellationAllowed( new \DateTime('2022-07-08'), @@ -65,13 +60,10 @@ public function testNoCancellationWithDaysInRange() * subscription as soon as the latest possible date * has been exceeded. * - * @group subscriptions - * * @throws \Exception - * - * @return void */ - public function testNoCancellationWithDaysOutsideRange() + #[Group('subscriptions')] + public function testNoCancellationWithDaysOutsideRange(): void { $isAllowed = $this->validator->isCancellationAllowed( new \DateTime('2022-07-08'), @@ -87,13 +79,10 @@ public function testNoCancellationWithDaysOutsideRange() * a subscription if there is no renewal date known. * This should not happen, but still we need to support it in case it does. * - * @group subscriptions - * * @throws \Exception - * - * @return void */ - public function testNoRenewalDateExisting() + #[Group('subscriptions')] + public function testNoRenewalDateExisting(): void { $isAllowed = $this->validator->isCancellationAllowed( null, diff --git a/tests/PHPUnit/Components/Subscription/Services/SubscriptionReminder/ReminderValidatorTest.php b/tests/PHPUnit/Components/Subscription/Services/SubscriptionReminder/ReminderValidatorTest.php index 838b05ac6..72fb831f3 100644 --- a/tests/PHPUnit/Components/Subscription/Services/SubscriptionReminder/ReminderValidatorTest.php +++ b/tests/PHPUnit/Components/Subscription/Services/SubscriptionReminder/ReminderValidatorTest.php @@ -1,9 +1,11 @@ validator->shouldRemind( new \DateTime('2022-02-01'), @@ -100,15 +91,11 @@ public function testNoReminderIfAlreadyReminded() * We have not yet sent the reminder, but we have already * reached the actual renewal date. A reminder would be * embarassing and frustrating now. - * - * @group subscriptions - * - * @testWith ["2021-12-27"] - * [""] - * - * @return void */ - public function testNoReminderOnRenewalDay(string $lastReminded) + #[TestWith(['2021-12-27'])] + #[TestWith([''])] + #[Group('subscriptions')] + public function testNoReminderOnRenewalDay(string $lastReminded): void { if ($lastReminded !== '') { $lastReminded = new \DateTime($lastReminded); diff --git a/tests/PHPUnit/Controller/Api/PluginConfig/Services/MollieRefundConfigServiceTest.php b/tests/PHPUnit/Controller/Api/PluginConfig/Services/MollieRefundConfigServiceTest.php index 3d88e00cc..5856fac65 100644 --- a/tests/PHPUnit/Controller/Api/PluginConfig/Services/MollieRefundConfigServiceTest.php +++ b/tests/PHPUnit/Controller/Api/PluginConfig/Services/MollieRefundConfigServiceTest.php @@ -1,7 +1,7 @@ createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeCardToken($salesChannelContext, 'test', new Request()); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'result' => null, - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseNotSuccessWithErrors(): void - { - $customerService = new FakeCustomerService(); - - $customerService = $customerService->withFakeCustomer(); - $customerService = $customerService->withCardTokenErrors(['test error']); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeCardToken($salesChannelContext, 'test', new Request()); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'result' => ['test error'], - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseSuccess(): void - { - $customerService = new FakeCustomerService(); - $customerService = $customerService->withFakeCustomer(); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeCardToken($salesChannelContext, 'test', new Request()); - $expected = new JsonResponse([ - 'success' => true, - 'customerId' => 'test', - 'result' => [], - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseNotSuccessWithoutCustomerStoreMandateId(): void - { - $customerService = new FakeCustomerService(); - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeMandateId('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'result' => null, - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseNotSuccessWithErrorsStoreMandateId(): void - { - $customerService = new FakeCustomerService(); - $customerService = $customerService->withFakeCustomer(); - $customerService = $customerService->withSaveMandateIdErrors(['test error']); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeMandateId('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'result' => ['test error'], - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseSuccessStoreMandateId(): void - { - $customerService = new FakeCustomerService(); - $customerService = $customerService->withFakeCustomer(); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->storeMandateId('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => true, - 'customerId' => 'test', - 'result' => [], - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseNotSuccessWithoutCustomerRevokeMandate(): void - { - $customerService = new FakeCustomerService(); - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->revokeMandate('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'mandateId' => 'test', - 'result' => null, - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseNotSuccessWithErrorsRevokeMandate(): void - { - $customerService = new FakeCustomerService(true); - $customerService = $customerService->withFakeCustomer(); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(true); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->revokeMandate('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => false, - 'customerId' => 'test', - 'mandateId' => 'test', - 'result' => 'Error when removing mandate', - ]); - - $this->assertEquals($expected, $actualResponse); - } - - public function testResponseSuccessRevokeMandate(): void - { - $customerService = new FakeCustomerService(); - $customerService = $customerService->withFakeCustomer(); - - $salesChannelContext = $this->createMock(SalesChannelContext::class); - $salesChannelContext->method('getCustomerId')->willReturn('test'); - $mandateService = new FakeMandateService(); - $controller = new CreditCardControllerBase($customerService, $mandateService, new NullLogger()); - - $actualResponse = $controller->revokeMandate('test', $salesChannelContext); - $expected = new JsonResponse([ - 'success' => true, - 'customerId' => 'test', - 'mandateId' => 'test', - 'result' => null, - ]); - - $this->assertEquals($expected, $actualResponse); - } -} diff --git a/tests/PHPUnit/Event/MollieOrderBuildEventTest.php b/tests/PHPUnit/Event/MollieOrderBuildEventTest.php index beeda61d2..15b9706ee 100644 --- a/tests/PHPUnit/Event/MollieOrderBuildEventTest.php +++ b/tests/PHPUnit/Event/MollieOrderBuildEventTest.php @@ -1,7 +1,7 @@ payFacade->createCustomerAtMollie($this->order, $this->salesChannelContext); } - public function createMollieCustomerIsCalledTestData() + public static function createMollieCustomerIsCalledTestData() { return [ 'customer is not a guest, create customers on => create customer' => [ diff --git a/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php b/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php index 19ae84aa2..512af5aa8 100644 --- a/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php +++ b/tests/PHPUnit/Fakes/CancelItemFacadeBuilder.php @@ -1,7 +1,7 @@ testCase = $testCase; - $this->mollieClient = $testCase->getMockBuilder(MollieApiClient::class)->disableOriginalConstructor()->getMock(); + $this->mollieClient = $this->getMockBuilder(MollieApiClient::class)->disableOriginalConstructor()->getMock(); $this->itemCollection = new OrderLineItemCollection(); $this->stockManager = new FakeStockManager(); } public function withInvalidOrder(): self { - $mockOrderEndpoint = $this->testCase->getMockBuilder(OrderEndpoint::class)->disableOriginalConstructor()->getMock(); + $mockOrderEndpoint = $this->getMockBuilder(OrderEndpoint::class)->disableOriginalConstructor()->getMock(); $mockOrderEndpoint->method('get')->willThrowException(new ApiException('Invalid order')); $this->mollieClient->orders = $mockOrderEndpoint; @@ -57,17 +58,17 @@ public function withInvalidOrder(): self public function withDefaultOrder(): self { - $mockOrderLine = $this->testCase->getMockBuilder(OrderLine::class)->disableOriginalConstructor()->getMock(); + $mockOrderLine = $this->getMockBuilder(OrderLine::class)->disableOriginalConstructor()->getMock(); $mockOrderLine->cancelableQuantity = 2; $mockOrderLine->id = 'valid'; $oderLineCollection = new OrderLineCollection(1, null); $oderLineCollection[0] = $mockOrderLine; - $mockOrder = $this->testCase->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); + $mockOrder = $this->getMockBuilder(Order::class)->disableOriginalConstructor()->getMock(); $mockOrder->method('lines')->willReturn($oderLineCollection); - $mockOrderEndpoint = $this->testCase->getMockBuilder(OrderEndpoint::class)->disableOriginalConstructor()->getMock(); + $mockOrderEndpoint = $this->getMockBuilder(OrderEndpoint::class)->disableOriginalConstructor()->getMock(); $mockOrderEndpoint->method('get')->willReturn($mockOrder); $this->mollieClient->orders = $mockOrderEndpoint; @@ -98,11 +99,16 @@ public function getStockManager(): FakeStockManager public function bild(): CancelItemFacade { /** @var MollieApiFactory $mollieFactory */ - $mollieFactory = $this->testCase->getMockBuilder(MollieApiFactory::class)->disableOriginalConstructor()->getMock(); + $mollieFactory = $this->getMockBuilder(MollieApiFactory::class)->disableOriginalConstructor()->getMock(); $mollieFactory->method('getClient')->willReturn($this->mollieClient); - $dispatcher = $this->testCase->getMockBuilder(EventDispatcherInterface::class)->getMock(); + $dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); $orderLineRepository = new FakeOrderLineItemRepository($this->itemCollection); return new CancelItemFacade($mollieFactory, $orderLineRepository, $this->stockManager, $dispatcher, new NullLogger()); } + + private function getMockBuilder(string $className): MockBuilder + { + return new MockBuilder($this->testCase, $className); + } } diff --git a/tests/PHPUnit/Fakes/FakeCartService.php b/tests/PHPUnit/Fakes/FakeCartService.php index eeffbfce8..a3cc73023 100644 --- a/tests/PHPUnit/Fakes/FakeCartService.php +++ b/tests/PHPUnit/Fakes/FakeCartService.php @@ -1,7 +1,7 @@ */ public $criteria = []; diff --git a/tests/PHPUnit/Fakes/FakeHttpClient.php b/tests/PHPUnit/Fakes/FakeHttpClient.php index 6a43dd4e4..7bb9db8d3 100644 --- a/tests/PHPUnit/Fakes/FakeHttpClient.php +++ b/tests/PHPUnit/Fakes/FakeHttpClient.php @@ -1,7 +1,7 @@ status = $status; + } +} diff --git a/tests/PHPUnit/Fakes/FakeOrderService.php b/tests/PHPUnit/Fakes/FakeOrderService.php index b7cd9adb1..af41bafbc 100644 --- a/tests/PHPUnit/Fakes/FakeOrderService.php +++ b/tests/PHPUnit/Fakes/FakeOrderService.php @@ -1,7 +1,7 @@ refundHydrator = new RefundHydrator(); } - /** - * @dataProvider getHydratorTestData - */ + #[DataProvider('getHydratorTestData')] public function testRefundHydrator(array $expected, Refund $refund) { $orderMock = $this->createMock(OrderEntity::class); @@ -36,45 +36,45 @@ public function testRefundHydrator(array $expected, Refund $refund) /** * @return array[] */ - public function getHydratorTestData() + public static function getHydratorTestData() { return [ 'Refund with amount 12.99, settlementAmount -12.99' => [ - $this->getExpectedData(12.99, -12.99), - $this->getRefund(12.99, -12.99), + self::getExpectedData(12.99, -12.99), + self::getRefund(12.99, -12.99), ], 'Refund with amount 12.99, settlementAmount null' => [ - $this->getExpectedData(12.99, null), - $this->getRefund(12.99, null), + self::getExpectedData(12.99, null), + self::getRefund(12.99, null), ], 'Refund with amount null, settlementAmount -12.99' => [ - $this->getExpectedData(null, -12.99), - $this->getRefund(null, -12.99), + self::getExpectedData(null, -12.99), + self::getRefund(null, -12.99), ], 'Refund with amount null, settlementAmount null' => [ - $this->getExpectedData(null, null), - $this->getRefund(null, null), + self::getExpectedData(null, null), + self::getRefund(null, null), ], 'Refund with status processing' => [ - $this->getExpectedData(12.99, -12.99, RefundStatus::STATUS_PROCESSING), - $this->getRefund(12.99, -12.99, RefundStatus::STATUS_PROCESSING), + self::getExpectedData(12.99, -12.99, RefundStatus::STATUS_PROCESSING), + self::getRefund(12.99, -12.99, RefundStatus::STATUS_PROCESSING), ], 'Refund with status pending' => [ - $this->getExpectedData(12.99, -12.99, RefundStatus::STATUS_PENDING), - $this->getRefund(12.99, -12.99, RefundStatus::STATUS_PENDING), + self::getExpectedData(12.99, -12.99, RefundStatus::STATUS_PENDING), + self::getRefund(12.99, -12.99, RefundStatus::STATUS_PENDING), ], 'Refund with status failed' => [ - $this->getExpectedData(12.99, -12.99, RefundStatus::STATUS_FAILED), - $this->getRefund(12.99, -12.99, RefundStatus::STATUS_FAILED), + self::getExpectedData(12.99, -12.99, RefundStatus::STATUS_FAILED), + self::getRefund(12.99, -12.99, RefundStatus::STATUS_FAILED), ], 'Refund with status refunded' => [ - $this->getExpectedData(12.99, -12.99, RefundStatus::STATUS_REFUNDED), - $this->getRefund(12.99, -12.99, RefundStatus::STATUS_REFUNDED), + self::getExpectedData(12.99, -12.99, RefundStatus::STATUS_REFUNDED), + self::getRefund(12.99, -12.99, RefundStatus::STATUS_REFUNDED), ], ]; } - private function getExpectedData(?float $amount, ?float $settlementAmount, string $status = RefundStatus::STATUS_QUEUED): array + private static function getExpectedData(?float $amount, ?float $settlementAmount, string $status = RefundStatus::STATUS_QUEUED): array { if (! is_null($amount)) { $amount = [ @@ -109,7 +109,7 @@ private function getExpectedData(?float $amount, ?float $settlementAmount, strin ]; } - private function getRefund(?float $amount, ?float $settlementAmount, string $status = RefundStatus::STATUS_QUEUED): Refund + private static function getRefund(?float $amount, ?float $settlementAmount, string $status = RefundStatus::STATUS_QUEUED): Refund { if (! is_null($amount)) { $amount = [ @@ -125,17 +125,7 @@ private function getRefund(?float $amount, ?float $settlementAmount, string $sta ]; } - $refundMock = $this->createConfiguredMock( - Refund::class, - [ - 'isQueued' => $status == RefundStatus::STATUS_QUEUED, - 'isPending' => $status == RefundStatus::STATUS_PENDING, - 'isProcessing' => $status == RefundStatus::STATUS_PROCESSING, - 'isTransferred' => $status == RefundStatus::STATUS_REFUNDED, - 'isFailed' => $status == RefundStatus::STATUS_FAILED, - 'cancel' => null, - ] - ); + $refundMock = new FakeMollieRefund($status); $refundMock->id = 'foo'; $refundMock->orderId = 'bar'; diff --git a/tests/PHPUnit/Service/ApplePayDirect/ApplePayDirectTest.php b/tests/PHPUnit/Service/ApplePayDirect/ApplePayDirectTest.php index 14c9d7639..9ac47a512 100644 --- a/tests/PHPUnit/Service/ApplePayDirect/ApplePayDirectTest.php +++ b/tests/PHPUnit/Service/ApplePayDirect/ApplePayDirectTest.php @@ -1,7 +1,7 @@ createDummyMock(EntityRepository::class, $this)); /** @var CartBackupService $cartBackupService */ - $cartBackupService = $this->createDummyMock(CartBackupService::class, $this); + $cartBackupService = $this->createDummyMock(AbstractCartBackupService::class, $this); /* @var MollieApiFactory $apiFactory */ $this->apiFactory = $this->createDummyMock(MollieApiFactory::class, $this); diff --git a/tests/PHPUnit/Service/ApplePayDirect/ApplePayDomainVerificationServiceTest.php b/tests/PHPUnit/Service/ApplePayDirect/ApplePayDomainVerificationServiceTest.php index b748d3e6b..91c75cf05 100644 --- a/tests/PHPUnit/Service/ApplePayDirect/ApplePayDomainVerificationServiceTest.php +++ b/tests/PHPUnit/Service/ApplePayDirect/ApplePayDomainVerificationServiceTest.php @@ -1,7 +1,7 @@ addSnippet('molliePayments.payments.applePayDirect.captionSubtotal', 'Subtotal'); $fakeSnippets->addSnippet('molliePayments.payments.applePayDirect.captionTaxes', 'Taxes'); - $routingDetector = new RoutingDetector(new RequestStack(new Request())); + $routingDetector = new RoutingDetector(new RequestStack([])); $this->formatter = new ApplePayFormatter($fakeSnippets, $routingDetector); } diff --git a/tests/PHPUnit/Service/Cart/Subscription/SubscriptionCartCollectorTest.php b/tests/PHPUnit/Service/Cart/Subscription/SubscriptionCartCollectorTest.php index de60289d6..382e5606b 100644 --- a/tests/PHPUnit/Service/Cart/Subscription/SubscriptionCartCollectorTest.php +++ b/tests/PHPUnit/Service/Cart/Subscription/SubscriptionCartCollectorTest.php @@ -1,7 +1,7 @@ setPayload(['customFields' => $value]); } diff --git a/tests/PHPUnit/Service/Cart/Voucher/VoucherServiceTest.php b/tests/PHPUnit/Service/Cart/Voucher/VoucherServiceTest.php deleted file mode 100644 index fb1edd941..000000000 --- a/tests/PHPUnit/Service/Cart/Voucher/VoucherServiceTest.php +++ /dev/null @@ -1,170 +0,0 @@ -salesChannelContext = $this->createMock(SalesChannelContext::class); - } - - /** - * This test verifies that line items with invalid product numbers - * just return NO voucher type at all. - */ - public function testInvalidProductNumber() - { - // build a repo that would return nothing...just in case ;) - $fakeRepoProducts = new FakeProductRepository(null, null); - - // build a product line item that - // has no valid product number... - $item = $this->buildProductLineItem(''); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $voucherType = $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - - $this->assertEquals(VoucherType::TYPE_NOTSET, $voucherType); - } - - /** - * This test verifies that we do NOT get an exception if the - * product numbers would be valid, but no product has been found. - */ - public function testUnknownProductThrowsNoException() - { - // build a repo that would return nothing...just in case ;) - $fakeRepoProducts = new FakeProductRepository(null, null); - - $item = $this->buildProductLineItem('10001'); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $voucherType = $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - - $this->assertEquals(VoucherType::TYPE_NOTSET, $voucherType); - } - - /** - * This test verifies that we get the MEAL voucher value - * if our product entity has that one stored in its custom fields. - */ - public function testProductHasMealVoucher() - { - $foundProduct = new ProductEntity(); - $foundProduct->setId('ID-123'); - $foundProduct->setCustomFields([ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_MEAL, - ]); - $foundProduct->setTranslated(['customFields' => $foundProduct->getCustomFields()]); - // build a repo that would return nothing...just in case ;) - $fakeRepoProducts = new FakeProductRepository(null, $foundProduct); - - $item = $this->buildProductLineItem('10001'); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $voucherType = $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - - $this->assertEquals(VoucherType::TYPE_MEAL, $voucherType); - } - - /** - * This test verifies that we get a correct exception, if our - * product has no voucher data, a parentID has been set, but that - * parent product is not found. - */ - public function testUnknownParentThrowsException() - { - $this->expectException(ProductNotFoundException::class); - - $foundProduct = new ProductEntity(); - - $foundProduct->setId('ID-123'); - $foundProduct->setParentId('PARENT-123'); - $foundProduct->setTranslated(['customFields' => $foundProduct->getCustomFields()]); - - $fakeRepoProducts = new FakeProductRepository(null, $foundProduct); - $fakeRepoProducts->throwExceptions = true; - $item = $this->buildProductLineItem('10001'); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - } - - /** - * This test verifies that we get the voucher type of the parent. - * Our product has no voucher, but a valid parent ID. - * The returned parent product, has then a valid voucher, which must be returned - * from our voucher services. - */ - public function testVoucherOfParent() - { - $foundProduct = new ProductEntity(); - $foundProduct->setId('ID-123'); - $foundProduct->setParentId('PARENT-123'); - $foundProduct->setTranslated(['customFields' => $foundProduct->getCustomFields()]); - - $foundParentProduct = new ProductEntity(); - $foundParentProduct->setId('ID-456'); - $foundParentProduct->setCustomFields([ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_GIFT, - ]); - $foundParentProduct->setTranslated(['customFields' => $foundParentProduct->getCustomFields()]); - - $fakeRepoProducts = new FakeProductRepository($foundParentProduct, null); - - $item = $this->buildProductLineItem('10001'); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $voucherType = $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - - $this->assertEquals(VoucherType::TYPE_GIFT, $voucherType); - } - - /** - * This test verifies that products with a number "*" do not - * return a voucher type. This is indeed happening when using the plugin CustomProducts in SW6. - */ - public function testCustomProductPluginIsSkipped() - { - // build a repo that would return nothing...just in case ;) - $fakeRepoProducts = new FakeProductRepository(null, null); - - // build a product line item with * as number. - // this is what custom products does. - // and just to be safe, let's try it with a space ;) - $item = $this->buildProductLineItem('* '); - - $vouchers = new VoucherService($fakeRepoProducts, new NullLogger()); - $voucherType = $vouchers->getFinalVoucherType($item, $this->salesChannelContext); - - $this->assertEquals('', $voucherType); - } - - private function buildProductLineItem(string $productNumber): LineItem - { - $item = new LineItem('id-123', 'product'); - $item->setPayloadValue('productNumber', $productNumber); - - return $item; - } -} diff --git a/tests/PHPUnit/Service/CustomerServiceTest.php b/tests/PHPUnit/Service/CustomerServiceTest.php index fe3c76873..f4d8f71ca 100644 --- a/tests/PHPUnit/Service/CustomerServiceTest.php +++ b/tests/PHPUnit/Service/CustomerServiceTest.php @@ -1,14 +1,15 @@ assertEquals($actual, $expected); } - /** - * @dataProvider setMollieCustomerIdTestData - */ + #[DataProvider('setMollieCustomerIdTestData')] public function testSetMollieCustomerId( string $customerId, string $mollieCustomerId, @@ -126,7 +125,7 @@ public function testSetMollieCustomerId( * customerRepository::update, and this does mean it is consolidated with the existing customFields. * Normally, this is something the EntityRepository takes care of. */ - public function setMollieCustomerIdTestData() + public static function setMollieCustomerIdTestData() { return [ 'New Mollie customer, live' => [ diff --git a/tests/PHPUnit/Service/DomainExtractorTest.php b/tests/PHPUnit/Service/DomainExtractorTest.php index 7ba3cc1b8..89e76092b 100644 --- a/tests/PHPUnit/Service/DomainExtractorTest.php +++ b/tests/PHPUnit/Service/DomainExtractorTest.php @@ -1,7 +1,7 @@ createConfiguredMock(ValidatorInterface::class, [ 'validate' => (new ConstraintViolationList()), ]); + if (! interface_exists(FilesystemInterface::class)) { + $this->mailFactory = new MailFactory($validator); + return; + } $fileSystem = $this->createConfiguredMock(FilesystemInterface::class, [ 'getMimetype' => 'application/fake', ]); @@ -52,14 +57,13 @@ public function setUp(): void * This test verifies that we send the correct mail data * to the mail server. * - * @dataProvider getMailData - * * @param mixed $expectedData * @param mixed $mailData * @param mixed $attachments * * @return void */ + #[DataProvider('getMailData')] public function testMailSenderGetsCorrectData($expectedData, $mailData, $attachments) { $expectedMail = $this->buildExpectedMailObject( @@ -100,14 +104,14 @@ public function testMailSenderGetsCorrectData($expectedData, $mailData, $attachm $mailService->send($mailData, $attachments); } - public function getMailData(): array + public static function getMailData(): array { return [ '1. German support, no attachments' => [ [ 'expectedTo' => self::RECIPIENT_DE, ], - $this->buildMailArrayData( + self::buildMailArrayData( 'Help needed', 'localhost', 'de-DE', @@ -121,7 +125,7 @@ public function getMailData(): array [ 'expectedTo' => self::RECIPIENT_DE, ], - $this->buildMailArrayData( + self::buildMailArrayData( 'Help needed', 'localhost', 'de-DE', @@ -141,7 +145,7 @@ public function getMailData(): array [ 'expectedTo' => self::RECIPIENT_INTL, ], - $this->buildMailArrayData( + self::buildMailArrayData( 'Help needed', 'localhost', 'en-GB', @@ -155,7 +159,7 @@ public function getMailData(): array [ 'expectedTo' => self::RECIPIENT_INTL, ], - $this->buildMailArrayData( + self::buildMailArrayData( 'Help needed', 'localhost', '', @@ -171,7 +175,7 @@ public function getMailData(): array /** * @return string[] */ - private function buildMailArrayData(string $subject, string $host, string $locale, string $html, string $replyName, string $replyMail) + private static function buildMailArrayData(string $subject, string $host, string $locale, string $html, string $replyName, string $replyMail) { return [ 'subject' => $subject, diff --git a/tests/PHPUnit/Service/Mollie/MolliePaymentDetailsTest.php b/tests/PHPUnit/Service/Mollie/MolliePaymentDetailsTest.php index 4f74dc8a7..f3a4af42d 100644 --- a/tests/PHPUnit/Service/Mollie/MolliePaymentDetailsTest.php +++ b/tests/PHPUnit/Service/Mollie/MolliePaymentDetailsTest.php @@ -1,7 +1,7 @@ createMock(Payment::class); $fakePayment->createdAt = date(DATE_ISO8601, strtotime('-1 hour')); - $paymentCollection = new PaymentCollection($this->createMock(MollieApiClient::class), 2, null); + $paymentCollection = new PaymentCollection($this->createMock(MollieApiClient::class), [], null); $paymentCollection->append($this->payment); $paymentCollection->append($fakePayment); diff --git a/tests/PHPUnit/Service/MollieApi/Builder/AbstractMollieOrderBuilder.php b/tests/PHPUnit/Service/MollieApi/Builder/AbstractMollieOrderBuilder.php index 68a9cea5e..1c865239c 100644 --- a/tests/PHPUnit/Service/MollieApi/Builder/AbstractMollieOrderBuilder.php +++ b/tests/PHPUnit/Service/MollieApi/Builder/AbstractMollieOrderBuilder.php @@ -1,7 +1,7 @@ createMock(TransactionConverterInterface::class); - $routingDetector = new RoutingDetector(new RequestStack(new Request())); + $routingDetector = new RoutingDetector(new RequestStack([])); $routingBuilder = new RoutingBuilder( $this->router, $routingDetector, diff --git a/tests/PHPUnit/Service/MollieApi/Builder/MollieLineItemBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/MollieLineItemBuilderTest.php index ab68e85de..a10b2387d 100644 --- a/tests/PHPUnit/Service/MollieApi/Builder/MollieLineItemBuilderTest.php +++ b/tests/PHPUnit/Service/MollieApi/Builder/MollieLineItemBuilderTest.php @@ -1,7 +1,7 @@ getOrderLineItem( @@ -137,13 +137,13 @@ public function testLineItemStructure(string $itemType, string $mollieLineType): /** * @return array[] */ - public function getStructureData(): array + public static function getStructureData(): array { return [ 'PRODUCT Line Item is PHYSICAL' => [LineItem::PRODUCT_LINE_ITEM_TYPE, OrderLineType::TYPE_PHYSICAL], 'CREDIT Line Item is PHYSICAL' => [LineItem::CREDIT_LINE_ITEM_TYPE, OrderLineType::TYPE_STORE_CREDIT], 'PROMOTION Line Item is PHYSICAL' => [LineItem::PROMOTION_LINE_ITEM_TYPE, OrderLineType::TYPE_DISCOUNT], - 'CUSTOM_PRODUCT Line Item is PHYSICAL' => [MollieLineItemBuilder::LINE_ITEM_TYPE_CUSTOM_PRODUCTS_OPTIONS, OrderLineType::TYPE_DIGITAL], + 'CUSTOM_PRODUCT Line Item is PHYSICAL' => [MollieLineItemBuilder::LINE_ITEM_TYPE_CUSTOM_PRODUCTS, OrderLineType::TYPE_PHYSICAL], 'Fallback Line Item is DIGITAL' => ['test', OrderLineType::TYPE_DIGITAL], ]; } @@ -196,10 +196,9 @@ public function testLineItemsWithHigherPrecision(): void * and depending on our fixing configuration, a new (diff) line item is then added or not. * In the end the sum of the line items has to match our expected orderTotal amount. * - * @dataProvider getRoundingFixerData - * * @return void */ + #[DataProvider('getRoundingFixerData')] public function testRoundingFixerIsUsedCorrectly(bool $fixRoundingIssues, float $swItemUnitPrice, float $swOrderTotal, int $lineItemCount, float $expectedOrderSum) { $settings = new MollieSettingStruct(); @@ -246,7 +245,7 @@ public function testRoundingFixerIsUsedCorrectly(bool $fixRoundingIssues, float /** * @return array[] */ - public function getRoundingFixerData(): array + public static function getRoundingFixerData(): array { return [ 'Enable Fixing, but not difference, items remain the same' => [true, 2.73, 2.73, 1, 2.73], diff --git a/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderAddressBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderAddressBuilderTest.php index c859fbeb2..bfcbdbd9a 100644 --- a/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderAddressBuilderTest.php +++ b/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderAddressBuilderTest.php @@ -1,10 +1,10 @@ settingStruct->setFormatOrderNumber($format); - - $order = new OrderEntity(); - $order->setId(Uuid::randomHex()); - $order->setAmountTotal(14); - $order->setSalesChannelId(Uuid::randomHex()); - $order->setTaxStatus('ok'); - $order->setOrderNumber('10000'); - - $customer = new OrderCustomerEntity(); - $customer->setCustomerNumber('5000'); - $customer->setEmail(''); - $order->setOrderCustomer($customer); - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode('EUR'); - $order->setCurrency($currency); - - $language = new LanguageEntity(); - $language->setId(Uuid::randomHex()); - $locale = new LocaleEntity(); - $locale->setCode('en-GB'); - $language->setLocale($locale); - $order->setLanguage($language); - - $data = $this->builder->buildOrderPayload( - $order, - '123', - 'paypal', - $this->salesChannelContext, - new PayPalPayment($this->payAction, $this->finalizeAction), - [] - ); - - self::assertSame($expected, $data['orderNumber']); - } - - /** - * @return string[][] - */ - public function getFormatValues() - { - return - [ - 'no_custom_format' => ['10000', ''], - 'white_space_is_no_custom_format' => ['10000', ' '], - 'more_whitespaces_are_also_no_custom_format' => ['10000', ' '], - 'just_ordernumber' => ['10000', '{ordernumber}'], - 'custom_prefix' => ['R10000', 'R{ordernumber}'], - 'custom_suffix' => ['10000-stage', '{ordernumber}-stage'], - 'full_format' => ['R10000-stage', 'R{ordernumber}-stage'], - 'with_customer_number' => ['R10000-5000', 'R{ordernumber}-{customernumber}'], - ]; - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderPriceBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderPriceBuilderTest.php index a6861324a..95b0f937e 100644 --- a/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderPriceBuilderTest.php +++ b/tests/PHPUnit/Service/MollieApi/Builder/MollieOrderPriceBuilderTest.php @@ -1,7 +1,7 @@ router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::ALMA; - - $this->paymentHandler = new KlarnaOnePayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/ApplePayOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/ApplePayOrderBuilderTest.php index ce2b713ac..2ba9a38e2 100644 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/ApplePayOrderBuilderTest.php +++ b/tests/PHPUnit/Service/MollieApi/Builder/Payments/ApplePayOrderBuilderTest.php @@ -1,12 +1,12 @@ router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::BANCONTACT; - - $this->paymentHandler = new BanContactPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BancomatOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/BancomatOrderBuilderTest.php deleted file mode 100644 index a75c58d6d..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BancomatOrderBuilderTest.php +++ /dev/null @@ -1,71 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new BancomatPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $phoneNumber = '+1234567'; - $orderAttributes = new OrderAttributes($order); - $orderAttributes->setPayPhoneNumber($phoneNumber); - $order->setCustomFields($orderAttributes->toArray()); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expectedBillingAddress = $this->getExpectedTestAddress($this->address, $this->email); - $expectedBillingAddress['phone'] = $phoneNumber; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $expectedBillingAddress, - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BankTransferOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/BankTransferOrderBuilderTest.php deleted file mode 100644 index 973625d68..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BankTransferOrderBuilderTest.php +++ /dev/null @@ -1,81 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $paymentMethod = PaymentMethod::BANKTRANSFER; - - $this->paymentHandler = new BankTransferPayment( - $this->payAction, - $this->finalizeAction, - $this->settingsService - ); - - $bankDueDays = 2; - $expiresDays = 10; - - $this->settingStruct->assign([ - 'orderLifetimeDays' => $expiresDays, - 'paymentMethodBankTransferDueDateDays' => $bankDueDays, - ]); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $bankDueDatetime = (new \DateTime()) - ->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $bankDueDays)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $bankDueDatetime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BelfiusOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/BelfiusOrderBuilderTest.php deleted file mode 100644 index 09ab9777c..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BelfiusOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::BELFIUS; - - $this->paymentHandler = new BelfiusPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BizumOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/BizumOrderBuilderTest.php deleted file mode 100644 index d968468c3..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BizumOrderBuilderTest.php +++ /dev/null @@ -1,68 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new BizumPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $phoneNumber = '+1234567'; - $orderAttributes = new OrderAttributes($order); - $orderAttributes->setPayPhoneNumber($phoneNumber); - $order->setCustomFields($orderAttributes->toArray()); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - $expected['billingAddress']['phone'] = $phoneNumber; - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BlikOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/BlikOrderBuilderTest.php deleted file mode 100644 index 92d1a4a7a..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/BlikOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new BlikPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/CreditCardOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/CreditCardOrderBuilderTest.php deleted file mode 100644 index 1ede7acda..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/CreditCardOrderBuilderTest.php +++ /dev/null @@ -1,128 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::CREDITCARD; - /** @var CustomerService $customerService */ - $customerService = $this->getMockBuilder(CustomerService::class)->disableOriginalConstructor()->getMock(); - $customerService->expects($this->never())->method('setCardToken'); - - $this->paymentHandler = new CreditCardPayment( - $this->payAction, - $this->finalizeAction, - $customerService - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } - - public function testOrderBuildWithToken(): void - { - $token = 'secrettoken'; - $redirectWebhookUrl = 'https://foo'; - $this->router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::CREDITCARD; - /** @var CustomerService $customerService */ - $customerService = $this->getMockBuilder(CustomerService::class)->disableOriginalConstructor()->getMock(); - $customerService->expects($this->once())->method('setCardToken'); - - $this->paymentHandler = new CreditCardPayment( - $this->payAction, - $this->finalizeAction, - $customerService - ); - - $this->customer->setCustomFields(['mollie_payments' => ['credit_card_token' => $token]]); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - 'cardToken' => $token, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/DirectDebitOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/DirectDebitOrderBuilderTest.php deleted file mode 100644 index 361accec3..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/DirectDebitOrderBuilderTest.php +++ /dev/null @@ -1,70 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::DIRECTDEBIT; - - $this->paymentHandler = new DirectDebitPayment( - $this->payAction, - $this->finalizeAction - ); - - $firstName = 'First'; - $lastName = 'Last'; - $this->customer->setFirstName($firstName); - $this->customer->setLastName($lastName); - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/EpsOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/EpsOrderBuilderTest.php deleted file mode 100644 index 732f6266f..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/EpsOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::EPS; - - $this->paymentHandler = new EpsPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiftCardOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiftCardOrderBuilderTest.php deleted file mode 100644 index e3e6ce1c6..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiftCardOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::GIFTCARD; - - $this->paymentHandler = new GiftCardPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiroPayOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiroPayOrderBuilderTest.php deleted file mode 100644 index ac05d0df9..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/GiroPayOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::GIROPAY; - - $this->paymentHandler = new GiroPayPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/IDealOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/IDealOrderBuilderTest.php deleted file mode 100644 index 013c5af91..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/IDealOrderBuilderTest.php +++ /dev/null @@ -1,66 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::IDEAL; - - $this->paymentHandler = new iDealPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/In3OrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/In3OrderBuilderTest.php deleted file mode 100644 index 7272155bc..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/In3OrderBuilderTest.php +++ /dev/null @@ -1,70 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = 'in3'; // TODO constant not yet availablePaymentMethod::EPS; - - $this->paymentHandler = new In3Payment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload( - $order, - $transactionId, - $paymentMethod, - $this->salesChannelContext, - $this->paymentHandler, - [] - ); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/KbcOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/KbcOrderBuilderTest.php deleted file mode 100644 index 20189f6e1..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/KbcOrderBuilderTest.php +++ /dev/null @@ -1,66 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::KBC; - - $this->paymentHandler = new KbcPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number very long'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/KlarnaOneOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/KlarnaOneOrderBuilderTest.php deleted file mode 100644 index d56657280..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/KlarnaOneOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::KLARNA_PAY_LATER; - - $this->paymentHandler = new KlarnaOnePayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MbWayOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/MbWayOrderBuilderTest.php deleted file mode 100644 index 42a724b3a..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MbWayOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new MbWayPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MobilePayOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/MobilePayOrderBuilderTest.php deleted file mode 100644 index bae282771..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MobilePayOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new MobilePayPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'DKK'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MultibancoOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/MultibancoOrderBuilderTest.php deleted file mode 100644 index 768f8bd66..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MultibancoOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new MultibancoPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MyBankOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/MyBankOrderBuilderTest.php deleted file mode 100644 index e8297fe08..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/MyBankOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::MYBANK; - - $this->paymentHandler = new KlarnaOnePayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayByBankOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayByBankOrderBuilderTest.php deleted file mode 100644 index 1ca796377..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayByBankOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::PAYBYBANK; - - $this->paymentHandler = new PayByBankPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayLaterOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayLaterOrderBuilderTest.php deleted file mode 100644 index 96641ef62..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayLaterOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::KLARNA_PAY_LATER; - - $this->paymentHandler = new KlarnaPayLaterPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayPalOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayPalOrderBuilderTest.php deleted file mode 100644 index 3a387f443..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayPalOrderBuilderTest.php +++ /dev/null @@ -1,128 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::PAYPAL; - - $this->paymentHandler = new PayPalPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } - - public function testOrderBuildWithDelivery(): void - { - $redirectWebhookUrl = 'https://foo'; - $this->router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::PAYPAL; - - $this->paymentHandler = new PayPalPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 42.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $taxAmount = 15.0; - $taxRate = 50.0; - $totalPrice = 15.0; - $deliveryId = Uuid::randomHex(); - - $delivery = $this->getOrderDelivery($deliveryId, $taxAmount, $taxRate, $totalPrice); - $delivery->setShippingOrderAddress($this->getDummyAddress()); - $deliveries = new OrderDeliveryCollection([$delivery]); - - $order->setDeliveries($deliveries); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => array_merge( - $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - $this->getExpectedDeliveries($taxStatus, $deliveries, $currency) - ), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PaySafeOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PaySafeOrderBuilderTest.php deleted file mode 100644 index 54bff3da4..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PaySafeOrderBuilderTest.php +++ /dev/null @@ -1,70 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::PAYSAFECARD; - - $this->paymentHandler = new PaySafeCardPayment( - $this->payAction, - $this->finalizeAction - ); - - $customerNumber = 'fooBar'; - $this->customer->setCustomerNumber($customerNumber); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - 'customerReference' => $customerNumber, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayconiqOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayconiqOrderBuilderTest.php deleted file mode 100644 index 76060bd77..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PayconiqOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new PayconiqPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PosOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/PosOrderBuilderTest.php deleted file mode 100644 index 98fa65458..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/PosOrderBuilderTest.php +++ /dev/null @@ -1,63 +0,0 @@ -assertEquals('pointofsale', PosPayment::PAYMENT_METHOD_NAME); - } - - /** - * This test verifies that the default name of our payment is correct. - * This is also used in Cypress tests. - */ - public function testDefaultName(): void - { - $this->assertEquals('POS Terminal', PosPayment::PAYMENT_METHOD_DESCRIPTION); - } - - /** - * This test verifies that the terminal ID is extracted from the customers - * custom fields, if it is set. - */ - public function testTerminalIsExtractedFromCustomer(): void - { - $pos = new PosPayment( - $this->payAction, - $this->finalizeAction - ); - - $customer = new CustomerEntity(); - - $customer->setCustomFields( - [ - 'mollie_payments' => [ - 'preferred_pos_terminal' => 'term_123', - ], - ] - ); - - $pos->processPaymentMethodSpecificParameters( - [], - new OrderEntity(), - $this->salesChannelContext, - $customer - ); - - $terminalID = $pos->getTerminalId(); - - $this->assertEquals('term_123', $terminalID); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/Przelewy24OrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/Przelewy24OrderBuilderTest.php deleted file mode 100644 index 55a55d624..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/Przelewy24OrderBuilderTest.php +++ /dev/null @@ -1,66 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::PRZELEWY24; - - $this->paymentHandler = new Przelewy24Payment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => [ - 'webhookUrl' => $redirectWebhookUrl, - ], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/RivertyOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/RivertyOrderBuilderTest.php deleted file mode 100644 index fb9a45e1d..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/RivertyOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new RivertyPayment( - $this->payAction, - $this->finalizeAction, - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SatispayOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/SatispayOrderBuilderTest.php deleted file mode 100644 index 7dbd3886a..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SatispayOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new SatispayPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SliceItOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/SliceItOrderBuilderTest.php deleted file mode 100644 index 0912a57f4..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SliceItOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::KLARNA_SLICE_IT; - - $this->paymentHandler = new KlarnaSliceItPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SofortOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/SofortOrderBuilderTest.php deleted file mode 100644 index b99eb556d..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SofortOrderBuilderTest.php +++ /dev/null @@ -1,64 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - $paymentMethod = PaymentMethod::SOFORT; - - $this->paymentHandler = new SofortPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $paymentMethod, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $paymentMethod, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SwishOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/SwishOrderBuilderTest.php deleted file mode 100644 index 572d1cce7..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/SwishOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new SwishPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/TrustlyOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/TrustlyOrderBuilderTest.php deleted file mode 100644 index 66755be19..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/TrustlyOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new TrustlyPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/TwintOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/TwintOrderBuilderTest.php deleted file mode 100644 index 27c333a64..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/TwintOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new TwintPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'EUR'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/Builder/Payments/VippsOrderBuilderTest.php b/tests/PHPUnit/Service/MollieApi/Builder/Payments/VippsOrderBuilderTest.php deleted file mode 100644 index d99aecad1..000000000 --- a/tests/PHPUnit/Service/MollieApi/Builder/Payments/VippsOrderBuilderTest.php +++ /dev/null @@ -1,62 +0,0 @@ -router->method('generate')->willReturn($redirectWebhookUrl); - - $this->paymentHandler = new VippsPayment( - $this->payAction, - $this->finalizeAction - ); - - $transactionId = Uuid::randomHex(); - $amountTotal = 27.0; - $taxStatus = CartPrice::TAX_STATE_GROSS; - $currencyISO = 'NOK'; - - $currency = new CurrencyEntity(); - $currency->setId(Uuid::randomHex()); - $currency->setIsoCode($currencyISO); - - $orderNumber = 'foo number'; - $lineItems = $this->getDummyLineItems(); - - $order = $this->getOrderEntity($amountTotal, $taxStatus, $currencyISO, $lineItems, $orderNumber); - - $actual = $this->builder->buildOrderPayload($order, $transactionId, $this->paymentHandler::PAYMENT_METHOD_NAME, $this->salesChannelContext, $this->paymentHandler, []); - - $expectedOrderLifeTime = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')) - ->modify(sprintf('+%d day', $this->expiresAt)) - ->format('Y-m-d') - ; - - $expected = [ - 'amount' => (new MollieOrderPriceBuilder())->build($amountTotal, $currencyISO), - 'locale' => $this->localeCode, - 'method' => $this->paymentHandler::PAYMENT_METHOD_NAME, - 'orderNumber' => $orderNumber, - 'payment' => ['webhookUrl' => $redirectWebhookUrl], - 'redirectUrl' => $redirectWebhookUrl, - 'webhookUrl' => $redirectWebhookUrl, - 'lines' => $this->getExpectedLineItems($taxStatus, $lineItems, $currency), - 'billingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'shippingAddress' => $this->getExpectedTestAddress($this->address, $this->email), - 'expiresAt' => $expectedOrderLifeTime, - ]; - - self::assertSame($expected, $actual); - } -} diff --git a/tests/PHPUnit/Service/MollieApi/CustomerTest.php b/tests/PHPUnit/Service/MollieApi/CustomerTest.php index 41ccf34eb..88fab967b 100644 --- a/tests/PHPUnit/Service/MollieApi/CustomerTest.php +++ b/tests/PHPUnit/Service/MollieApi/CustomerTest.php @@ -1,7 +1,7 @@ customerApiService->createCustomerAtMollie($customerMock, 'buzz'); } - /** - * @dataProvider isLegacyCustomerValidTestData - */ + #[DataProvider('isLegacyCustomerValidTestData')] public function testIsLegacyCustomerValid( ?string $mollieCustomerId, bool $expectedValue @@ -108,7 +107,7 @@ public function testIsLegacyCustomerValid( $this->assertSame($expectedValue, $actualValue); } - public function isLegacyCustomerValidTestData(): array + public static function isLegacyCustomerValidTestData(): array { return [ 'Customer exists in Mollie' => ['foo', true], diff --git a/tests/PHPUnit/Service/MollieApi/Fixer/RoundingDifferenceFixerTest.php b/tests/PHPUnit/Service/MollieApi/Fixer/RoundingDifferenceFixerTest.php index f98fbe122..15305b9b5 100644 --- a/tests/PHPUnit/Service/MollieApi/Fixer/RoundingDifferenceFixerTest.php +++ b/tests/PHPUnit/Service/MollieApi/Fixer/RoundingDifferenceFixerTest.php @@ -1,13 +1,14 @@ fixer->fixAmountDiff($this->orderTotal + $diff, $this->cartItems, '', ''); diff --git a/tests/PHPUnit/Service/MollieApi/LineItemDataExtractorTest.php b/tests/PHPUnit/Service/MollieApi/LineItemDataExtractorTest.php index 712d13c8d..9a34cefc5 100644 --- a/tests/PHPUnit/Service/MollieApi/LineItemDataExtractorTest.php +++ b/tests/PHPUnit/Service/MollieApi/LineItemDataExtractorTest.php @@ -1,7 +1,7 @@ orderApiService->getMollieOrder('foo', 'bar'); } - /** - * @dataProvider getIsCompletelyShippedData - */ + #[DataProvider('getIsCompletelyShippedData')] public function testIsCompletelyShipped(string $type, int $shippableQuantity, bool $expectedValue) { $mollieOrderLine = $this->createMock(OrderLine::class); @@ -138,7 +137,7 @@ public function testIsCompletelyShipped(string $type, int $shippableQuantity, bo $this->assertEquals($expectedValue, $actualValue); } - public function getIsCompletelyShippedData() + public static function getIsCompletelyShippedData() { return [ // These types are available as line items in Shopware, so test whether they need to be shipped. diff --git a/tests/PHPUnit/Service/MollieApi/PriceCalculatorTest.php b/tests/PHPUnit/Service/MollieApi/PriceCalculatorTest.php index f6a1e6177..4430a4acb 100644 --- a/tests/PHPUnit/Service/MollieApi/PriceCalculatorTest.php +++ b/tests/PHPUnit/Service/MollieApi/PriceCalculatorTest.php @@ -1,7 +1,7 @@ disableOriginalConstructor() ->getMock() ; + $fakeSalesChannel = new SalesChannelEntity(); + $fakeSalesChannel->setId(TestDefaults::SALES_CHANNEL); + $fakeSalesChannel->setLanguageId('test'); + $this->fakeSalesChannelContext->method('getSalesChannel')->willReturn($fakeSalesChannel); } /** @@ -47,9 +54,8 @@ public function testAvailableLocales(): void * This test verifies that a locale is correctly returned from a sales channel if available. * We fake the repository that returns us a given locale for our sales channel. * That locale is in the list of available locales and should therefore be correctly returned in our function. - * - * @dataProvider getAvailableLocales */ + #[DataProvider('getAvailableLocales')] public function testAvailableLocalesAreFound(string $locale): void { $scLanguage = $this->buildSalesChannelLanguage($locale); @@ -66,7 +72,7 @@ public function testAvailableLocalesAreFound(string $locale): void /** * @return string[] */ - public function getAvailableLocales(): array + public static function getAvailableLocales(): array { return [ ['en_US'], @@ -124,9 +130,7 @@ public function testSalesChannelWithoutLocale(): void $this->assertEquals('en_GB', $detectedLocale); } - /** - * @dataProvider mollieLocaleDataProvider - */ + #[DataProvider('mollieLocaleDataProvider')] public function testProvidesMollieLocale(string $input, string $expected): void { $service = new MollieLocaleService(new FakeLanguageRepository(null)); @@ -134,7 +138,7 @@ public function testProvidesMollieLocale(string $input, string $expected): void $this->assertEquals($expected, $service->getMollieLocale($input)); } - public function mollieLocaleDataProvider(): array + public static function mollieLocaleDataProvider(): array { return [ 'en_US' => ['en-US', 'en_US'], diff --git a/tests/PHPUnit/Service/MolliePaymentExtractorTest.php b/tests/PHPUnit/Service/MolliePaymentExtractorTest.php index 31629a1b8..e5b6a99b8 100644 --- a/tests/PHPUnit/Service/MolliePaymentExtractorTest.php +++ b/tests/PHPUnit/Service/MolliePaymentExtractorTest.php @@ -1,7 +1,7 @@ assertEquals([$orderState], $this->orderTransitionService->states); } - public function provideOrderState(): array + public static function provideOrderState(): array { return [ [OrderStates::STATE_OPEN], diff --git a/tests/PHPUnit/Service/Order/OrderTimeServiceTest.php b/tests/PHPUnit/Service/Order/OrderTimeServiceTest.php index b49cd0161..ed0d43384 100644 --- a/tests/PHPUnit/Service/Order/OrderTimeServiceTest.php +++ b/tests/PHPUnit/Service/Order/OrderTimeServiceTest.php @@ -1,9 +1,10 @@ orderMockWithLastTransactionTimestamp($orderDate); @@ -24,7 +23,7 @@ public function testDateComparisonLogic(\DateTime $now, \DateTime $orderDate, bo $this->assertSame($expected, $result); } - public function dateComparisonLogicProvider() + public static function dateComparisonLogicProvider() { return [ 'order is older than 1 hour' => [ diff --git a/tests/PHPUnit/Service/OrderServiceTest.php b/tests/PHPUnit/Service/OrderServiceTest.php index b08b6aee4..8d5794473 100644 --- a/tests/PHPUnit/Service/OrderServiceTest.php +++ b/tests/PHPUnit/Service/OrderServiceTest.php @@ -1,7 +1,7 @@ paymentMethodRepository = new FakePaymentMethodRepository($paymentMethod); $this->paymentMethodService = new PaymentMethodService( - new VersionCompare('6.5.6.0'), - $this->createMock(MediaService::class), - $this->mediaRepository, $this->paymentMethodRepository, - $this->createMock(PluginIdProvider::class), - new FakeHttpClient(), - new PayPalExpressConfig(1), ); } @@ -104,51 +60,4 @@ public function testTechnicalPaymentMethodPrefix(): void { $this->assertEquals('payment_mollie_', PaymentMethodService::TECHNICAL_NAME_PREFIX); } - - /** - * This test verifies that our list of officially supported payment - * methods is not touched without recognizing it. - */ - public function testSupportedMethods(): void - { - $expected = [ - ApplePayPayment::class, - BanContactPayment::class, - BankTransferPayment::class, - BilliePayment::class, - BelfiusPayment::class, - CreditCardPayment::class, - EpsPayment::class, - GiftCardPayment::class, - iDealPayment::class, - KbcPayment::class, - KlarnaOnePayment::class, - PayPalPayment::class, - PaySafeCardPayment::class, - Przelewy24Payment::class, - VoucherPayment::class, - In3Payment::class, - PosPayment::class, - TwintPayment::class, - BlikPayment::class, - BancomatPayment::class, - MyBankPayment::class, - AlmaPayment::class, - TrustlyPayment::class, - RivertyPayment::class, - SatispayPayment::class, - PayByBankPayment::class, - MbWayPayment::class, - MultibancoPayment::class, - SwishPayment::class, - BizumPayment::class, - MobilePayPayment::class, - VippsPayment::class, - PayPalExpressPayment::class, - ]; - - $handlers = $this->paymentMethodService->getPaymentHandlers(); - - $this->assertEquals($expected, $handlers); - } } diff --git a/tests/PHPUnit/Service/Refund/Fakes/RefundSummarizationServiceFake.php b/tests/PHPUnit/Service/Refund/Fakes/RefundSummarizationServiceFake.php index 550ea6392..801a0cba3 100644 --- a/tests/PHPUnit/Service/Refund/Fakes/RefundSummarizationServiceFake.php +++ b/tests/PHPUnit/Service/Refund/Fakes/RefundSummarizationServiceFake.php @@ -1,7 +1,7 @@ anonymize($token)); } - public function getTestData(): array + public static function getTestData(): array { return [ 'test that empty string returns empty string' => ['', ' '], diff --git a/tests/PHPUnit/Service/TrackingInfoStructFactoryTest.php b/tests/PHPUnit/Service/TrackingInfoStructFactoryTest.php index ecf4ce40e..bf0508351 100644 --- a/tests/PHPUnit/Service/TrackingInfoStructFactoryTest.php +++ b/tests/PHPUnit/Service/TrackingInfoStructFactoryTest.php @@ -1,11 +1,13 @@ assertSame($expectedCarrier, $trackingInfoStruct->getCarrier()); } - /** - * @dataProvider invalidShippingUrlPatterns - */ + #[DataProvider('invalidShippingUrlPatterns')] public function testUrlEmptyOnInvalidShippingURLs(string $invalidPattern): void { $trackingInfoStruct = $this->factory->create('test', 'valid-code', 'https://foo.bar/' . $invalidPattern); @@ -164,7 +162,7 @@ public function testUrlEmptyOnInvalidShippingURLs(string $invalidPattern): void $this->assertSame('', $trackingInfoStruct->getUrl()); } - public function invalidShippingUrlPatterns(): array + public static function invalidShippingUrlPatterns(): array { return [ ['%s%'], diff --git a/tests/PHPUnit/Service/Transition/DeliveryTransitionServiceTest.php b/tests/PHPUnit/Service/Transition/DeliveryTransitionServiceTest.php index 2e5a49848..61ec68300 100644 --- a/tests/PHPUnit/Service/Transition/DeliveryTransitionServiceTest.php +++ b/tests/PHPUnit/Service/Transition/DeliveryTransitionServiceTest.php @@ -1,7 +1,7 @@ createTransitionForAction(StateMachineTransitionActions::ACTION_REOPEN); $expectedTransition2 = $this->createTransitionForAction(StateMachineTransitionActions::ACTION_SHIP); - + $matcher = $this->exactly(2); $this->stateMachineRegistry->expects($this->once())->method('getAvailableTransitions'); - $this->stateMachineRegistry->expects($this->exactly(2))->method('transition') - ->withConsecutive( - [$expectedTransition1, $this->context], - [$expectedTransition2, $this->context] - ) + $this->stateMachineRegistry->expects($matcher)->method('transition') + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1, $expectedTransition2) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + }) ; $this->deliveryTransitionService->shipDelivery($delivery, $this->context); @@ -251,12 +255,19 @@ public function testPartialReturnDeliveryOnNotAllowedState() $expectedTransition3 = $this->createTransitionForAction(StateMachineTransitionActions::ACTION_RETOUR_PARTIALLY); $this->stateMachineRegistry->expects($this->once())->method('getAvailableTransitions'); + $matcher = $this->exactly(3); $this->stateMachineRegistry->expects($this->exactly(3))->method('transition') - ->withConsecutive( - [$expectedTransition1, $this->context], - [$expectedTransition2, $this->context], - [$expectedTransition3, $this->context] - ) + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1, $expectedTransition2, $expectedTransition3) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertEquals($expectedTransition3, $transition); + } + }) ; $this->deliveryTransitionService->partialReturnDelivery($delivery, $this->context); @@ -309,12 +320,19 @@ public function testReturnDeliveryOnNotAllowedState() $expectedTransition3 = $this->createTransitionForAction(StateMachineTransitionActions::ACTION_RETOUR); $this->stateMachineRegistry->expects($this->once())->method('getAvailableTransitions'); - $this->stateMachineRegistry->expects($this->exactly(3))->method('transition') - ->withConsecutive( - [$expectedTransition1, $this->context], - [$expectedTransition2, $this->context], - [$expectedTransition3, $this->context] - ) + $matcher = $this->exactly(3); + $this->stateMachineRegistry->expects($matcher)->method('transition') + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1, $expectedTransition2, $expectedTransition3) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertEquals($expectedTransition3, $transition); + } + }) ; $this->deliveryTransitionService->returnDelivery($delivery, $this->context); diff --git a/tests/PHPUnit/Service/Transition/OrderTransitionServiceTest.php b/tests/PHPUnit/Service/Transition/OrderTransitionServiceTest.php index 2bba2f34b..12b0041ec 100644 --- a/tests/PHPUnit/Service/Transition/OrderTransitionServiceTest.php +++ b/tests/PHPUnit/Service/Transition/OrderTransitionServiceTest.php @@ -1,7 +1,7 @@ setId('orderId'); $context = $this->createMock(Context::class); - $this->stateMachineRegistry->expects($this->once()) ->method('getAvailableTransitions') ->with(OrderDefinition::ENTITY_NAME, 'orderId', 'stateId', $context) @@ -146,10 +146,19 @@ public function testOpenOrderFromNotDirectlyAllowedState(): void StateMachineTransitionActions::ACTION_REOPEN, 'stateId' ); - - $this->stateMachineRegistry->expects($this->exactly(2)) + $matcher = $this->exactly(2); + $this->stateMachineRegistry->expects($matcher) ->method('transition') - ->withConsecutive([$expectedTransition1, $context], [$expectedTransition2, $context]) + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1, $expectedTransition2) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + + return new StateMachineStateCollection(); + }) ; $this->orderTransitionService->openOrder($order, $context); @@ -267,10 +276,20 @@ public function testProcessOrderFromNotDirectlyAllowedState(): void StateMachineTransitionActions::ACTION_PROCESS, 'stateId' ); + $matcher = $this->exactly(2); $this->stateMachineRegistry->expects($this->exactly(2)) ->method('transition') - ->withConsecutive([$expectedTransition1, $context], [$expectedTransition2, $context]) + ->willReturnCallback(function (Transition $transition) use ($matcher, $expectedTransition1, $expectedTransition2) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + + return new StateMachineStateCollection(); + }) ; $this->orderTransitionService->processOrder($order, $context); @@ -368,11 +387,12 @@ public function testCompleteOrderFromOpen(): void $order->setStateMachineState($stateMachineState); $context = $this->createMock(Context::class); - - $this->stateMachineRegistry->expects($this->exactly(2)) + $matcher = $this->exactly(2); + $this->stateMachineRegistry->expects($matcher) ->method('getAvailableTransitions') ->with(OrderDefinition::ENTITY_NAME, 'orderId', 'stateId', $context) - ->willReturnOnConsecutiveCalls([$transition1], [$transition1]) + + ->willReturn([$transition1]) ; $expectedTransition1 = new Transition( @@ -388,10 +408,19 @@ public function testCompleteOrderFromOpen(): void StateMachineTransitionActions::ACTION_COMPLETE, 'stateId' ); - - $this->stateMachineRegistry->expects($this->exactly(2)) + $matcher = $this->exactly(2); + $this->stateMachineRegistry->expects($matcher) ->method('transition') - ->withConsecutive([$expectedTransition1, $context], [$expectedTransition2, $context]) + ->willReturnCallback(function (Transition $transition) use ($matcher, $expectedTransition1, $expectedTransition2) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + + return new StateMachineStateCollection(); + }) ; $this->orderTransitionService->completeOrder($order, $context); @@ -444,10 +473,22 @@ public function testCompleteOrderFromCancelled(): void StateMachineTransitionActions::ACTION_COMPLETE, 'stateId' ); - + $matcher = $this->exactly(3); $this->stateMachineRegistry->expects($this->exactly(3)) ->method('transition') - ->withConsecutive([$expectedTransition1, $context], [$expectedTransition2, $context], [$expectedTransition3, $context]) + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1,$expectedTransition2,$expectedTransition3) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + if ($matcher->numberOfInvocations() === 3) { + $this->assertEquals($expectedTransition3, $transition); + } + + return new StateMachineStateCollection(); + }) ; $this->orderTransitionService->completeOrder($order, $context); @@ -565,10 +606,19 @@ public function testCancelOrderFromNotDirectlyAllowedState(): void StateMachineTransitionActions::ACTION_CANCEL, 'stateId' ); - - $this->stateMachineRegistry->expects($this->exactly(2)) + $matcher = $this->exactly(2); + $this->stateMachineRegistry->expects($matcher) ->method('transition') - ->withConsecutive([$expectedTransition1, $context], [$expectedTransition2, $context]) + ->willReturnCallback(function (Transition $transition) use ($matcher,$expectedTransition1, $expectedTransition2) { + if ($matcher->numberOfInvocations() === 1) { + $this->assertEquals($expectedTransition1, $transition); + } + if ($matcher->numberOfInvocations() === 2) { + $this->assertEquals($expectedTransition2, $transition); + } + + return new StateMachineStateCollection(); + }) ; $this->orderTransitionService->cancelOrder($order, $context); diff --git a/tests/PHPUnit/Service/Transition/TransitionServiceTest.php b/tests/PHPUnit/Service/Transition/TransitionServiceTest.php index 36752c074..4d18f615e 100644 --- a/tests/PHPUnit/Service/Transition/TransitionServiceTest.php +++ b/tests/PHPUnit/Service/Transition/TransitionServiceTest.php @@ -1,7 +1,7 @@ service = new UrlParsingService(); } - /** - * @dataProvider urlProvider - */ + #[DataProvider('urlProvider')] public function testIsUrl(string $url, bool $expected) { $this->assertEquals($expected, $this->service->isUrl($url)); } - public function urlProvider(): array + public static function urlProvider(): array { return [ ['https://www.example.com', true], @@ -33,15 +32,13 @@ public function urlProvider(): array ]; } - /** - * @dataProvider queryParameterProvider - */ + #[DataProvider('queryParameterProvider')] public function testParseTrackingCodeQueryParameter(string $input, array $expected) { $this->assertEquals($expected, $this->service->parseTrackingCodeFromUrl($input)); } - public function queryParameterProvider(): array + public static function queryParameterProvider(): array { return [ ['https://www.example.com/product?code=12345&postal_code=123', ['code=12345&postal_code=123', 'https://www.example.com/product?%s']], @@ -52,15 +49,13 @@ public function queryParameterProvider(): array ]; } - /** - * @dataProvider hashProvider - */ + #[DataProvider('hashProvider')] public function testParseTrackingCodeHash(string $input, array $expected) { $this->assertEquals($expected, $this->service->parseTrackingCodeFromUrl($input)); } - public function hashProvider(): array + public static function hashProvider(): array { return [ ['https://www.example.com/product#code=12345', ['code=12345', 'https://www.example.com/product#%s']], @@ -70,15 +65,13 @@ public function hashProvider(): array ]; } - /** - * @dataProvider notFoundProvider - */ + #[DataProvider('notFoundProvider')] public function testParseTrackingCodeNotFound(string $input, array $expected) { $this->assertEquals($expected, $this->service->parseTrackingCodeFromUrl($input)); } - public function notFoundProvider(): array + public static function notFoundProvider(): array { return [ ['https://www.example.com/product', ['https://www.example.com/product', '']], @@ -86,15 +79,13 @@ public function notFoundProvider(): array ]; } - /** - * @dataProvider encodePathAndQueryProvider - */ + #[DataProvider('encodePathAndQueryProvider')] public function testEncodePathAndQuery(string $input, string $expected) { $this->assertEquals($expected, $this->service->encodePathAndQuery($input)); } - public function encodePathAndQueryProvider(): array + public static function encodePathAndQueryProvider(): array { return [ ['https://www.example.com/path/to/resource', 'https://www.example.com/path/to/resource'], @@ -104,15 +95,13 @@ public function encodePathAndQueryProvider(): array ]; } - /** - * @dataProvider sanitizeQueryProvider - */ + #[DataProvider('sanitizeQueryProvider')] public function testSanitizeQuery(array $input, array $expected) { $this->assertEquals($expected, $this->service->sanitizeQuery($input)); } - public function sanitizeQueryProvider(): array + public static function sanitizeQueryProvider(): array { return [ [['key=value'], ['key=value']], @@ -122,15 +111,13 @@ public function sanitizeQueryProvider(): array ]; } - /** - * @dataProvider sanitizeQueryPartProvider - */ + #[DataProvider('sanitizeQueryPartProvider')] public function testSanitizeQueryPart(string $input, string $expected) { $this->assertEquals($expected, $this->service->sanitizeQueryPart($input)); } - public function sanitizeQueryPartProvider(): array + public static function sanitizeQueryPartProvider(): array { return [ ['key=value', 'key=value'], diff --git a/tests/PHPUnit/Setting/MollieSettingsStructTest.php b/tests/PHPUnit/Setting/MollieSettingsStructTest.php index dcfcef079..a4fc56305 100644 --- a/tests/PHPUnit/Setting/MollieSettingsStructTest.php +++ b/tests/PHPUnit/Setting/MollieSettingsStructTest.php @@ -1,10 +1,10 @@ assertSame($expectedDateString, $actualValue); } - public function orderLifeTimeDaysData() + public static function orderLifeTimeDaysData() { $today = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')); @@ -64,10 +62,9 @@ public function orderLifeTimeDaysData() /** * test get the correct calculation based on paymentMethodBankTransferDueDateDays config * - * @dataProvider orderBankTransferDueDays - * * @param mixed $lifeTimeDays */ + #[DataProvider('orderBankTransferDueDays')] public function testBankTransferDueDays($lifeTimeDays, ?int $realLifeTimeDays, ?string $expectedDateString) { $settingsStruct = new MollieSettingStruct(); @@ -82,12 +79,11 @@ public function testBankTransferDueDays($lifeTimeDays, ?int $realLifeTimeDays, ? /** * test to get correct value range based on paymentMethodBankTransferDueDateDays config * - * @dataProvider orderBankTransferDueDays - * * @param mixed $lifeTimeDays * * @throws \Exception */ + #[DataProvider('orderBankTransferDueDays')] public function testBankTransferDueDate($lifeTimeDays, ?int $realLifeTimeDays, ?string $expectedDateString) { $settingsStruct = new MollieSettingStruct(); @@ -100,13 +96,13 @@ public function testBankTransferDueDate($lifeTimeDays, ?int $realLifeTimeDays, ? $this->assertSame($expectedDateString, $actualValue); } - public function orderBankTransferDueDays() + public static function orderBankTransferDueDays() { $today = (new \DateTime())->setTimezone(new \DateTimeZone('UTC')); return [ - 'dueDateDays cannot be smaller than minimum' => [-1, BankTransferPayment::DUE_DATE_MIN_DAYS, (clone $today)->modify('+1 day')->format('Y-m-d')], - 'dueDateDays cannot be bigger than maximum' => [1000, BankTransferPayment::DUE_DATE_MAX_DAYS, (clone $today)->modify('+100 day')->format('Y-m-d')], + 'dueDateDays cannot be smaller than minimum' => [-1, 1, (clone $today)->modify('+1 day')->format('Y-m-d')], + 'dueDateDays cannot be bigger than maximum' => [1000, 100, (clone $today)->modify('+100 day')->format('Y-m-d')], 'dueDateDays can be set' => [10, 10, (clone $today)->modify('+10 day')->format('Y-m-d')], 'dueDateDays can be null' => [null, null, null], 'dueDateDays can be empty' => ['', null, null], diff --git a/tests/PHPUnit/Struct/CustomerStructTest.php b/tests/PHPUnit/Struct/CustomerStructTest.php index da42fa773..0c000abd1 100644 --- a/tests/PHPUnit/Struct/CustomerStructTest.php +++ b/tests/PHPUnit/Struct/CustomerStructTest.php @@ -1,9 +1,10 @@ assertSame($expectedCustomerId, $actualValue); } - public function mollieCustomerIdsTestData() + public static function mollieCustomerIdsTestData() { return [ 'profileId foo, live' => [ - $this->customerIds(), + self::customerIds(), 'foo', false, 'cst_123', ], 'profileId foo, test' => [ - $this->customerIds(), + self::customerIds(), 'foo', true, 'cst_321', ], 'profileId bar, live' => [ - $this->customerIds(), + self::customerIds(), 'bar', false, 'cst_789', ], 'profileId bar, test' => [ - $this->customerIds(), + self::customerIds(), 'bar', true, 'cst_987', ], 'profileId baz, live' => [ - $this->customerIds(), + self::customerIds(), 'baz', false, 'cst_456', ], 'profileId baz, test' => [ - $this->customerIds(), + self::customerIds(), 'baz', true, 'cst_654', ], 'profileId doesn\'t exist, live' => [ - $this->customerIds(), + self::customerIds(), 'fizz', false, '', ], 'profileId doesn\'t exist, test' => [ - $this->customerIds(), + self::customerIds(), 'fizz', true, '', @@ -194,7 +194,7 @@ public function testCustomFieldsArrayKeepLegacyCustomerId() $this->assertEquals($expected, $customFields); } - private function customerIds() + private static function customerIds() { return [ 'customer_ids' => [ diff --git a/tests/PHPUnit/Struct/LineItem/LineItemAttributesTest.php b/tests/PHPUnit/Struct/LineItem/LineItemAttributesTest.php index 416dde6ce..c6d56dce9 100644 --- a/tests/PHPUnit/Struct/LineItem/LineItemAttributesTest.php +++ b/tests/PHPUnit/Struct/LineItem/LineItemAttributesTest.php @@ -1,10 +1,9 @@ assertEquals('', $attributes->getProductNumber()); } - - /** - * This test verifies that nothing breaks if we - * have NULL instead of a payload array. - */ - public function testNullPayload() - { - $item = new LineItem('', ''); - $attributes = new LineItemAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that nothing breaks - * if we only have an empty list as custom fields. - */ - public function testEmptyCustomFields() - { - $item = new LineItem('', ''); - $item->setPayload([ - 'customFields' => [], - ]); - - $attributes = new LineItemAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that nothing breaks - * if we have NULL for the customFields - */ - public function testNullCustomFields() - { - $item = new LineItem('', ''); - $item->setPayload([ - 'customFields' => null, - ]); - - $attributes = new LineItemAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that an existing voucher type entry - * is correctly loaded from our attributes class. - */ - public function testVoucherType() - { - $item = new LineItem('', ''); - $item->setPayload([ - 'customFields' => [ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_MEAL, - ], - ]); - - $attributes = new LineItemAttributes($item); - - $this->assertEquals(VoucherType::TYPE_MEAL, $attributes->getVoucherType()); - } - - /** - * This test verifies that our array is correctly built - * from our data. - */ - public function testToArray() - { - $item = new LineItem('', ''); - $item->setPayload([ - 'customFields' => [ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_MEAL, - ], - ]); - - $attributes = new LineItemAttributes($item); - - $expected = [ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_MEAL, - ]; - - $this->assertEquals($expected, $attributes->toArray()); - } } diff --git a/tests/PHPUnit/Struct/MollieApi/ShipmentTrackingInfoStructTest.php b/tests/PHPUnit/Struct/MollieApi/ShipmentTrackingInfoStructTest.php index e7008ded2..9ce2bc4f7 100644 --- a/tests/PHPUnit/Struct/MollieApi/ShipmentTrackingInfoStructTest.php +++ b/tests/PHPUnit/Struct/MollieApi/ShipmentTrackingInfoStructTest.php @@ -1,7 +1,7 @@ assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that nothing breaks - * if we only have an empty list as custom fields. - */ - public function testEmptyCustomFields() - { - $item = new OrderLineItemEntity(); - $item->setPayload([ - 'customFields' => [], - ]); - - $attributes = new OrderLineItemEntityAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that nothing breaks - * if we have NULL for the customFields - */ - public function testNullCustomFields() - { - $item = new OrderLineItemEntity(); - $item->setPayload([ - 'customFields' => null, - ]); - - $attributes = new OrderLineItemEntityAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that we have default values - * if our mollie data struct is empty. - */ - public function testEmptyMolliePayments() - { - $item = new OrderLineItemEntity(); - $item->setPayload([ - 'customFields' => [ - 'mollie_payments' => [ - ], - ], - ]); - - $attributes = new OrderLineItemEntityAttributes($item); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that an existing voucher type entry - * is correctly loaded from our attributes class. - */ - public function testVoucherType() - { - $item = new OrderLineItemEntity(); - $item->setPayload([ - 'customFields' => [ - 'mollie_payments' => [ - 'voucher_type' => VoucherType::TYPE_MEAL, - ], - ], - ]); - - $attributes = new OrderLineItemEntityAttributes($item); - - $this->assertEquals(VoucherType::TYPE_MEAL, $attributes->getVoucherType()); - } - /** * This test verifies that regular items are not recognized as promotion items.@ */ diff --git a/tests/PHPUnit/Struct/OrderTransaction/OrderTransactionAttributesTest.php b/tests/PHPUnit/Struct/OrderTransaction/OrderTransactionAttributesTest.php index 711c58920..1e7ba5b93 100644 --- a/tests/PHPUnit/Struct/OrderTransaction/OrderTransactionAttributesTest.php +++ b/tests/PHPUnit/Struct/OrderTransaction/OrderTransactionAttributesTest.php @@ -1,7 +1,7 @@ setHandlerIdentifier(VoucherPayment::class); - - $attributes = new PaymentMethodAttributes($method); - - $this->assertEquals(true, $attributes->isVoucherMethod()); - } - - /** - * This test verifies that a non-voucher payment, such as - * PayPal is not accidentally recognized as "voucher" payment. - */ - public function testPaypalIsNoVoucher() - { - $method = new PaymentMethodEntity(); - $method->setHandlerIdentifier(PayPalPayment::class); - - $attributes = new PaymentMethodAttributes($method); - - $this->assertEquals(false, $attributes->isVoucherMethod()); - } -} diff --git a/tests/PHPUnit/Struct/Product/ProductAttributesTest.php b/tests/PHPUnit/Struct/Product/ProductAttributesTest.php deleted file mode 100644 index de80329cc..000000000 --- a/tests/PHPUnit/Struct/Product/ProductAttributesTest.php +++ /dev/null @@ -1,71 +0,0 @@ -setCustomFields([]); - $product->setTranslated([ - 'customFields' => $product->getCustomFields(), - ]); - - $attributes = new ProductAttributes($product); - - $this->assertEquals('', $attributes->getVoucherType()); - } - - /** - * This test verifies that a valid voucher type - * is correctly assigned and returned later on. - * If we have a new type of data, then we read that data and skip the legacy one. - */ - public function testVoucherType() - { - $product = new ProductEntity(); - $product->setCustomFields([ - 'mollie_payments_product_voucher_type' => VoucherType::TYPE_ECO, - 'mollie_payments' => [ - 'voucher_type' => VoucherType::TYPE_MEAL, - ], - ]); - $product->setTranslated([ - 'customFields' => $product->getCustomFields(), - ]); - - $attributes = new ProductAttributes($product); - - $this->assertEquals(VoucherType::TYPE_ECO, $attributes->getVoucherType()); - } - - /** - * This test verifies that we get a NOT SET value - * for every type that is not officially known. - */ - public function testUnknownVoucherType() - { - $product = new ProductEntity(); - $product->setCustomFields([ - 'mollie_payments_product_voucher_type' => '5', - ]); - $product->setTranslated([ - 'customFields' => $product->getCustomFields(), - ]); - - $attributes = new ProductAttributes($product); - - $this->assertEquals(VoucherType::TYPE_NOTSET, $attributes->getVoucherType()); - } -} diff --git a/tests/PHPUnit/Subscriber/CancelMollieOrderSubscriberTest.php b/tests/PHPUnit/Subscriber/CancelMollieOrderSubscriberTest.php index 2d95717de..4c4f6be0a 100644 --- a/tests/PHPUnit/Subscriber/CancelMollieOrderSubscriberTest.php +++ b/tests/PHPUnit/Subscriber/CancelMollieOrderSubscriberTest.php @@ -1,7 +1,7 @@ subscriber = new TestModeNotificationSubscriber($this->settingsServiceMock); } - public function testAccountOverviewPageDoesContainTestModeInformation(): void - { - $event = new AccountOverviewPageLoadedEvent( - new AccountOverviewPage(), - $this->createMock(SalesChannelContext::class), - $this->createMock(Request::class) - ); - - $settings = new MollieSettingStruct(); - $settings->setTestMode(true); - - $this->settingsServiceMock->method('getSettings')->willReturn($settings); - $this->subscriber->addTestModeInformationToPages($event); - - self::assertTrue($event->getPage()->hasExtension('MollieTestModePageExtension')); - self::assertTrue($event->getPage()->getExtension('MollieTestModePageExtension')->isTestMode()); - } - - public function testAccountPaymentMethodPageDoesContainTestModeInformation(): void - { - $event = new AccountPaymentMethodPageLoadedEvent( - new AccountPaymentMethodPage(), - $this->createMock(SalesChannelContext::class), - $this->createMock(Request::class) - ); - - $settings = new MollieSettingStruct(); - $settings->setTestMode(true); - - $this->settingsServiceMock->method('getSettings')->willReturn($settings); - $this->subscriber->addTestModeInformationToPages($event); - - self::assertTrue($event->getPage()->hasExtension('MollieTestModePageExtension')); - self::assertTrue($event->getPage()->getExtension('MollieTestModePageExtension')->isTestMode()); - } - public function testAccountEditOrderPageDoesContainTestModeInformation(): void { $event = new AccountEditOrderPageLoadedEvent( diff --git a/tests/PHPUnit/Subscriber/WebhookTimezoneSubscriberTest.php b/tests/PHPUnit/Subscriber/WebhookTimezoneSubscriberTest.php index 98effb7b2..29817347b 100644 --- a/tests/PHPUnit/Subscriber/WebhookTimezoneSubscriberTest.php +++ b/tests/PHPUnit/Subscriber/WebhookTimezoneSubscriberTest.php @@ -1,7 +1,7 @@ setUpTransactionService(null); $event = $this->initSubscriberRequests(self::STOREFRONT_WEBHOOK_ROUTE, self::TRANSACTION_ID); $this->transactionService->expects($this->once())->method('getTransactionById'); diff --git a/tests/PHPUnit/Traits/BuilderTestTrait.php b/tests/PHPUnit/Traits/BuilderTestTrait.php index f8ee2e0bb..29cec429d 100644 --- a/tests/PHPUnit/Traits/BuilderTestTrait.php +++ b/tests/PHPUnit/Traits/BuilderTestTrait.php @@ -1,14 +1,13 @@ 'not-empty'] + ); + } - return new FlowEvent( - $actionName, - new FlowState($event), - ['data' => 'not-empty'] - ); + return new StorableFlow($actionName,$context,['orderId' => $order->getId()],['data' => 'not-empty']); } } diff --git a/tests/PHPUnit/Traits/MockTrait.php b/tests/PHPUnit/Traits/MockTrait.php index a567eb6f3..f81bc4d84 100644 --- a/tests/PHPUnit/Traits/MockTrait.php +++ b/tests/PHPUnit/Traits/MockTrait.php @@ -1,7 +1,7 @@ getMockBuilder($originalClassName) ->disableOriginalConstructor() ->disableOriginalClone() - ->disableArgumentCloning() - ->disallowMockingUnknownTypes() ->getMock() ; } diff --git a/tests/PHPUnit/Traits/OrderTrait.php b/tests/PHPUnit/Traits/OrderTrait.php index 3c71f9b42..4fd7a2080 100644 --- a/tests/PHPUnit/Traits/OrderTrait.php +++ b/tests/PHPUnit/Traits/OrderTrait.php @@ -1,7 +1,7 @@ event = $event; + } + + public function getEvent(): object + { + return $this->event; + } +} diff --git a/tests/Unit/Fake/FakeCustomerRepository.php b/tests/Unit/Fake/FakeCustomerRepository.php new file mode 100644 index 000000000..3de0ecc4d --- /dev/null +++ b/tests/Unit/Fake/FakeCustomerRepository.php @@ -0,0 +1,33 @@ +setDisplayName('Not specified'); + $orderCustomer = $this->getDefaultCustomerWithoutSalutation(); + $orderCustomer->setSalutation($salutation); + + return $orderCustomer; + } + + public function getDefaultCustomerWithoutSalutation(): CustomerEntity + { + $orderCustomer = new CustomerEntity(); + $orderCustomer->setCustomerNumber('100'); + $orderCustomer->setEmail('fake@unit.test'); + $orderCustomer->setFirstName('Tester'); + $orderCustomer->setLastName('Test'); + $orderCustomer->setGuest(false); + $orderCustomer->setId('test-customer-id'); + + return $orderCustomer; + } +} diff --git a/tests/PHPUnit/Fakes/FakeEventDispatcher.php b/tests/Unit/Fake/FakeEventDispatcher.php similarity index 93% rename from tests/PHPUnit/Fakes/FakeEventDispatcher.php rename to tests/Unit/Fake/FakeEventDispatcher.php index eb64049bc..2ac576810 100644 --- a/tests/PHPUnit/Fakes/FakeEventDispatcher.php +++ b/tests/Unit/Fake/FakeEventDispatcher.php @@ -1,7 +1,7 @@ setId('fakeShopwareOrderId'); + $order->setOrderNumber('10000'); + $order->setSalesChannelId(TestDefaults::SALES_CHANNEL); + $order->setBillingAddress($this->getOrderAddress($customer)); + + $order->setDeliveries($this->getOrderDeliveries($customer)); + $order->setAmountTotal(100.00); + $order->setTaxStatus(CartPrice::TAX_STATE_GROSS); + $order->setLineItems($this->getLineItems()); + if (method_exists($order, 'setPrimaryOrderDeliveryId')) { + $order->setPrimaryOrderDeliveryId('fake-delivery-id'); + } + + $stateMachineState = new StateMachineStateEntity(); + $stateMachineState->setTechnicalName('open'); + $stateMachineState->setId('openFakeStateId'); + + $order->setStateId($stateMachineState->getId()); + $order->setStateMachineState($stateMachineState); + + return $order; + } + + public function getOrderAddress(CustomerEntity $customerEntity): OrderAddressEntity + { + $orderAddress = $this->getOrderAddressWithoutCountry($customerEntity); + $country = new CountryEntity(); + $country->setIso('DE'); + $orderAddress->setCountry($country); + + return $orderAddress; + } + + public function getOrderAddressWithoutCountry(CustomerEntity $customerEntity): OrderAddressEntity + { + $orderAddress = new OrderAddressEntity(); + if ($customerEntity->getSalutation() instanceof SalutationEntity) { + $orderAddress->setSalutation($customerEntity->getSalutation()); + } + $orderAddress->setFirstName($customerEntity->getFirstName()); + $orderAddress->setLastName($customerEntity->getLastName()); + $orderAddress->setStreet('Test Street'); + $orderAddress->setZipCode('12345'); + $orderAddress->setCity('Test City'); + + return $orderAddress; + } + + public function getOrderDeliveries(CustomerEntity $customer): OrderDeliveryCollection + { + $collection = new OrderDeliveryCollection(); + + $shippingMethod = new ShippingMethodEntity(); + $shippingMethod->setId('fake-shipping-method-id'); + $shippingMethod->setName('DHL'); + + $delivery = new OrderDeliveryEntity(); + $delivery->setId('fake-delivery-id'); + $delivery->setShippingOrderAddress($this->getOrderAddress($customer)); + $delivery->setShippingCosts($this->getPrice(4.99, 19.0)); + $delivery->setShippingMethod($shippingMethod); + + $collection->add($delivery); + + $delivery = new OrderDeliveryEntity(); + $delivery->setId('fake-free-delivery-id'); + $delivery->setShippingOrderAddress($this->getOrderAddress($customer)); + $delivery->setShippingCosts($this->getPrice(0.0, 19.0)); + $delivery->setShippingMethod($shippingMethod); + $collection->add($delivery); + + return $collection; + } + + public function getOrderDeliveryWithoutShippingCosts(): OrderDeliveryEntity + { + $shippingMethod = new ShippingMethodEntity(); + $shippingMethod->setId('fake-shipping-method-id'); + $shippingMethod->setName('DHL'); + + $delivery = new OrderDeliveryEntity(); + $delivery->setId('fake-delivery-without-costs'); + $delivery->setShippingMethod($shippingMethod); + $shippingCosts = new CalculatedPrice(4.99, 4.99, new CalculatedTaxCollection(), new TaxRuleCollection(), 1); + $delivery->setShippingCosts($shippingCosts); + + return $delivery; + } + + public function getOrderLineItemWithoutPrice(): OrderLineItemEntity + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setId('fake-line-item-id'); + $orderLineItem->setLabel('Fake product'); + + return $orderLineItem; + } + + public function getLineItems(): OrderLineItemCollection + { + $collection = new OrderLineItemCollection(); + $orderLineItem = $this->createOrderLineItem('fake-line-item-id', 'SW1000', 'Fake product', 10.99); + $collection->add($orderLineItem); + + return $collection; + } + + public function getLineItemWithVoucherCategory(): OrderLineItemEntity + { + return $this->createOrderLineItem('fake-line-item-voucher-id', 'SW1001', 'Voucher product', 25.00, [1, 2]); + } + + public function getLineItemWithSingleVoucherCategory(): OrderLineItemEntity + { + return $this->createOrderLineItem( + 'fake-line-item-single-voucher-id', 'SW1002', 'Single voucher product', 30.00, [1]); + } + + public function getLineItemWithMixedVoucherCategories(): OrderLineItemEntity + { + return $this->createOrderLineItem('fake-line-item-mixed-voucher-id', 'SW1003', 'Mixed voucher product', 35.00, [1, 99, 2]); + } + + private function createOrderLineItem(string $id, string $productNumber, string $label, float $price, $voucherCategories = null): OrderLineItemEntity + { + $product = new ProductEntity(); + $product->setProductNumber($productNumber); + $extension = new Product(); + if ($voucherCategories !== null) { + $voucherCategoriesCollection = new VoucherCategoryCollection(); + foreach ($voucherCategories as $voucherCategory) { + $voucherCategory = VoucherCategory::tryFromNumber($voucherCategory); + if ($voucherCategory === null) { + continue; + } + $voucherCategoriesCollection->add($voucherCategory); + } + $extension->setVoucherCategories($voucherCategoriesCollection); + $product->addExtension(Mollie::EXTENSION,$extension); + } + + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setId($id); + $orderLineItem->setPrice($this->getPrice($price, 19)); + $orderLineItem->setLabel($label); + $orderLineItem->setProduct($product); + + return $orderLineItem; + } + + private function getPrice(float $unitPrice, float $taxRate, int $quantity = 1): CalculatedPrice + { + $totalPrice = $unitPrice * $quantity; + + $taxAmount = $totalPrice * ($taxRate / 100); + + $calculatedTax = new CalculatedTax($taxAmount, $taxRate, $totalPrice); + + return new CalculatedPrice($totalPrice, $unitPrice, new CalculatedTaxCollection([$calculatedTax]), new TaxRuleCollection(), $quantity); + } +} diff --git a/tests/Unit/Fake/FakeOrderService.php b/tests/Unit/Fake/FakeOrderService.php new file mode 100644 index 000000000..4d0f68752 --- /dev/null +++ b/tests/Unit/Fake/FakeOrderService.php @@ -0,0 +1,39 @@ +loggerSettings === null) { + $this->loggerSettings = new LoggerSettings(true, 0); + } + if ($this->paymentSettings === null) { + $this->paymentSettings = new PaymentSettings('',0); + } + if ($this->apiSettings === null) { + $profileId = $this->profileId ?? ''; + $this->apiSettings = new ApiSettings('test_key', 'live_key', Mode::TEST, $profileId); + } + if ($this->orderStateSettings === null) { + $this->orderStateSettings = new OrderStateSettings(); + } + } - public function __construct(LoggerSettings $settings = null) + public function getPaypalExpressSettings(?string $salesChannelId = null): PayPalExpressSettings { - if($settings === null) { - $settings = new LoggerSettings(true,0); - } - $this->settings = $settings; + // TODO: Implement getPaypalExpressSettings() method. + } + + public function getEnvironmentSettings(): EnvironmentSettings + { + // TODO: Implement getEnvironmentSettings() method. } + public function getDecorated(): AbstractSettingsService { // TODO: Implement getDecorated() method. } + public function getCreditCardSettings(?string $salesChannelId = null): CreditCardSettings + { + // TODO: Implement getCreditCardSettings() method. + } + + public function getApiSettings(?string $salesChannelId = null): ApiSettings + { + return $this->apiSettings; + } + + public function getPaymentSettings(?string $salesChannelId = null): PaymentSettings + { + return $this->paymentSettings; + } + public function getLoggerSettings(?string $salesChannelId = null): LoggerSettings { - return $this->settings; + return $this->loggerSettings; + } + + public function getAccountSettings(?string $salesChannelId = null): AccountSettings + { + // TODO: Implement getAccountSettings() method. + } + + public function getSubscriptionSettings(?string $salesChannelId = null): SubscriptionSettings + { + // TODO: Implement getSubscriptionSettings() method. + } + + public function getApplePaySettings(?string $salesChannelId = null): ApplePaySettings + { + // TODO: Implement getApplePaySettings() method. + } + + public function getOrderStateSettings(?string $salesChannelId = null): OrderStateSettings + { + return $this->orderStateSettings; } -} \ No newline at end of file +} diff --git a/tests/Unit/Logger/PluginSettingsHandlerTest.php b/tests/Unit/Logger/PluginSettingsHandlerTest.php index 80929c87b..902a48382 100644 --- a/tests/Unit/Logger/PluginSettingsHandlerTest.php +++ b/tests/Unit/Logger/PluginSettingsHandlerTest.php @@ -1,20 +1,17 @@ createMock(Connection::class); $connection->expects($this->once())->method('isConnected')->willReturn(false); - $handler = new PluginSettingsHandler($fakeSettingsService,$connection,''); - $record = [ - 'message' => 'test' - ]; + $handler = new PluginSettingsHandler($fakeSettingsService, $connection, ''); + + $record = new LogRecord(new \DateTimeImmutable(),'test',Level::Info,'test'); $result = $handler->handle($record); $this->assertFalse($result); } + public function testHandleIsFalseForDifferentChannel(): void { $fakeSettingsService = new FakeSettingsService(); @@ -39,57 +36,43 @@ public function testHandleIsFalseForDifferentChannel(): void $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('isConnected')->willReturn(true); - $handler = new PluginSettingsHandler($fakeSettingsService,$connection,''); - $record = [ - 'message' => 'test', - 'channel' => 'test' - ]; + $handler = new PluginSettingsHandler($fakeSettingsService, $connection, ''); + + $record = new LogRecord(new \DateTimeImmutable(),'test',Level::Info,'test'); $result = $handler->handle($record); $this->assertFalse($result); } + public function testHandleIsFalseFowLowerLogLevel(): void { - $loggerSettings = new LoggerSettings(false,0); + $loggerSettings = new LoggerSettings(false, 0); $fakeSettingsService = new FakeSettingsService($loggerSettings); $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('isConnected')->willReturn(true); - $handler = new PluginSettingsHandler($fakeSettingsService,$connection,''); - $record = [ - 'message' => 'test', - 'channel' => 'mollie', - 'level' => LogLevel::DEBUG, + $handler = new PluginSettingsHandler($fakeSettingsService, $connection, ''); - 'extra'=>[], - 'context'=>[], - 'datetime'=>new \DateTime() - ]; + $record = new LogRecord(new \DateTimeImmutable(),'mollie',Level::Debug,'test'); $result = $handler->handle($record); $this->assertFalse($result); } - public function testHandleIsWorking():void + + public function testHandleIsWorking(): void { - $loggerSettings = new LoggerSettings(true,0); + $loggerSettings = new LoggerSettings(true, 0); $fakeSettingsService = new FakeSettingsService($loggerSettings); $connection = $this->createMock(Connection::class); $connection->expects($this->once())->method('isConnected')->willReturn(true); - $handler = new PluginSettingsHandler($fakeSettingsService,$connection,'',false); - $record = [ - 'message' => 'test', - 'channel' => 'mollie', - 'level' => LogLevel::DEBUG, + $handler = new PluginSettingsHandler($fakeSettingsService, $connection, '', false); - 'extra'=>[], - 'context'=>[], - 'datetime'=>new \DateTime() - ]; + $record = new LogRecord(new \DateTimeImmutable(),'mollie',Level::Debug,'test'); $result = $handler->handle($record); $this->assertTrue($result); } -} \ No newline at end of file +} diff --git a/tests/Unit/Logger/RecordAnonymizerTest.php b/tests/Unit/Logger/RecordAnonymizerTest.php index 55b90bc24..b6da1c122 100644 --- a/tests/Unit/Logger/RecordAnonymizerTest.php +++ b/tests/Unit/Logger/RecordAnonymizerTest.php @@ -1,16 +1,14 @@ 'nothing has changed' - ]; - + $record = new LogRecord(new \DateTimeImmutable(), 'test', Level::Info, 'nothing has changed'); $result = $anonymizer($record); - $this->assertSame($record,$result); + $this->assertEquals($record, $result); } public function testIpIsAnonymized(): void { $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); - $record = [ - 'message'=>'nothing has changed', - 'extra'=>[ - 'ip'=>'127.0.0.1' - ] - ]; - + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '127.0.0.1', + ]); $result = $anonymizer($record); - $expected = [ - 'message'=>'nothing has changed', - 'extra' =>[ - 'ip'=>'127.0.0.0' - ] - ]; - $this->assertSame($expected,$result); + $expected = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '127.0.0.0' + ]); + + $this->assertEquals($expected, $result); } + public function testIpV6IsAnonymized(): void { $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); - $record = [ - 'message'=>'nothing has changed', - 'extra'=>[ - 'ip'=>'3c3d:d7f6:25ef:29fd:f5b7:1fb1:4241:5208' - ] - ]; - + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '3c3d:d7f6:25ef:29fd:f5b7:1fb1:4241:5208' + ]); $result = $anonymizer($record); - $expected = [ - 'message'=>'nothing has changed', - 'extra' =>[ - 'ip'=>'3c3d:d7f6:25ef:29fd::' - ] - ]; - $this->assertSame($expected,$result); + + $expected = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '3c3d:d7f6:25ef:29fd::' + ]); + $this->assertEquals($expected, $result); } + public function testUrlParametersAreAnonymized(): void { $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '3c3d:d7f6:25ef:29fd:f5b7:1fb1:4241:5208', + 'url' => 'https://shop.phpunit.mollie/payment/finalize-transaction?token=abc' + ]); + + $result = $anonymizer($record); + $expected = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [], [ + 'ip' => '3c3d:d7f6:25ef:29fd::', + 'url' => 'https://shop.phpunit.mollie/payment/finalize-transaction' + ]); - $record = [ - 'message'=>'nothing has changed', - 'extra'=>[ - 'ip'=>'3c3d:d7f6:25ef:29fd:f5b7:1fb1:4241:5208', - 'url'=>'https://shop.phpunit.mollie/payment/finalize-transaction?token=abc' + $this->assertEquals($expected, $result); + } + + public function testPersonalDataInContextIsAnonymized(): void + { + $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [ + 'payload' => [ + 'billingAddress' => [ + 'givenName' => 'Maximilian', + 'familyName' => 'Mollie', + 'organizationName' => 'Mollie Company', + 'email' => 'test@mollie.com', + 'phone' => '+490123456789', + 'streetAndNumber' => 'Mollie Street 123', + 'postalCode' => '12345', + ] ] - ]; + ]); $result = $anonymizer($record); - $expected = [ - 'message'=>'nothing has changed', - 'extra' =>[ - 'ip'=>'3c3d:d7f6:25ef:29fd::', - 'url' => 'https://shop.phpunit.mollie/payment/finalize-transaction' + + $this->assertEquals('**', $result['context']['payload']['billingAddress']['givenName']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['familyName']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['organizationName']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['email']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['phone']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['streetAndNumber']); + $this->assertEquals('**', $result['context']['payload']['billingAddress']['postalCode']); + } + + public function testTokenParametersInUrlsAreAnonymized(): void + { + $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [ + 'checkoutUrl' => 'https://www.mollie.com/checkout/test-mode?method=alma&token=6.balale', + 'finalizeUrl' => 'https://mollie-local.diwc.de/payment/finalize-transaction?_sw_payment_token=eyeo555n4777nclr771n5zcidj6ym96m3456' + ]); + + $result = $anonymizer($record); + + $this->assertStringContainsString('token=6.**', $result['context']['checkoutUrl']); + $this->assertStringNotContainsString('balale', $result['context']['checkoutUrl']); + $this->assertStringContainsString('_sw_payment_token=ey**', $result['context']['finalizeUrl']); + $this->assertStringNotContainsString('eyeo555n4777nclr771n5zcidj6ym96m3456', $result['context']['finalizeUrl']); + } + + public function testApplePayPaymentTokenIsAnonymized(): void + { + $anonymizer = new RecordAnonymizer(); + $now = new \DateTimeImmutable(); + $applePayToken = '{"paymentData":{"data":"zazq6d9tsJzah148grEdwNBWosUlEdnmu9c/tpEidah","signature":"MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQECAQUAMIAGCSqGSIb3DQEH"}}'; + + $record = new LogRecord($now, 'test', Level::Info, 'nothing has changed', [ + 'payment' => [ + 'applePayPaymentToken' => $applePayToken ] - ]; - $this->assertSame($expected,$result); + ]); + + $result = $anonymizer($record); + $maskedToken = $result['context']['payment']['applePayPaymentToken']; + + $this->assertEquals('**', $maskedToken); } -} \ No newline at end of file +} diff --git a/tests/Unit/Mollie/AddressTest.php b/tests/Unit/Mollie/AddressTest.php new file mode 100644 index 000000000..9b8d13ae6 --- /dev/null +++ b/tests/Unit/Mollie/AddressTest.php @@ -0,0 +1,78 @@ +customerRepository = new FakeCustomerRepository(); + $this->orderRepository = new FakeOrderRepository(); + } + + public function testCanCreateFromEntity(): void + { + $customer = $this->customerRepository->getDefaultCustomer(); + $orderAddress = $this->orderRepository->getOrderAddress($customer); + $orderAddress->setPhoneNumber('+1234567890'); + $orderAddress->setAdditionalAddressLine1('Appartment 2'); + $orderAddress->setAdditionalAddressLine2('Block C'); + $orderAddress->setCompany('Test Company'); + $actual = Address::fromAddress($customer, $orderAddress); + $expected = [ + 'title' => 'Not specified', + 'givenName' => 'Tester', + 'familyName' => 'Test', + 'organizationName' => 'Test Company', + 'streetAndNumber' => 'Test Street', + 'streetAdditional' => 'Appartment 2 Block C', + 'postalCode' => '12345', + 'email' => 'fake@unit.test', + 'phone' => '+1234567890', + 'city' => 'Test City', + 'country' => 'DE', + ]; + $this->assertInstanceOf(Address::class, $actual); + + $this->assertSame($expected['givenName'], $actual->getGivenName()); + $this->assertSame($expected['familyName'], $actual->getFamilyName()); + $this->assertSame($expected['organizationName'], $actual->getOrganizationName()); + $this->assertSame($expected['streetAndNumber'], $actual->getStreetAndNumber()); + $this->assertSame($expected['streetAdditional'], $actual->getStreetAdditional()); + $this->assertSame($expected['phone'], $actual->getPhone()); + $this->assertSame($expected['postalCode'], $actual->getPostalCode()); + $this->assertSame($expected['email'], $actual->getEmail()); + $this->assertSame($expected['city'], $actual->getCity()); + $this->assertSame($expected['country'], $actual->getCountry()); + $this->assertSame($expected['title'], $actual->getTitle()); + } + + public function testExpectExceptionOnEmptySalutation() + { + $customer = $this->customerRepository->getDefaultCustomerWithoutSalutation(); + $orderAddress = $this->orderRepository->getOrderAddress($customer); + $this->expectException(MissingSalutationException::class); + Address::fromAddress($customer, $orderAddress); + } + + public function testExpectExceptionOnEmptyCountry() + { + $customer = $this->customerRepository->getDefaultCustomer(); + $orderAddress = $this->orderRepository->getOrderAddressWithoutCountry($customer); + $this->expectException(MissingCountryException::class); + Address::fromAddress($customer, $orderAddress); + } +} diff --git a/tests/Unit/Mollie/CreatePaymentTest.php b/tests/Unit/Mollie/CreatePaymentTest.php new file mode 100644 index 000000000..dbcfaa508 --- /dev/null +++ b/tests/Unit/Mollie/CreatePaymentTest.php @@ -0,0 +1,152 @@ +assertSame($description, $payment->getDescription()); + $this->assertSame($redirectUrl, $payment->getRedirectUrl()); + $this->assertSame($amount, $payment->getAmount()); + $this->assertSame(SequenceType::ONEOFF, $payment->getSequenceType()); + } + + public function testSettersAndGetters(): void + { + $billingAddress = new Address( + 'billing@example.com', + 'Mr.', + 'John', + 'Doe', + 'Main Street 1', + '12345', + 'Berlin', + 'DE' + ); + $shippingAddress = new Address( + 'shipping@example.com', + 'Mrs.', + 'Jane', + 'Smith', + 'Secondary Street 2', + '54321', + 'Munich', + 'DE' + ); + $lineItems = new LineItemCollection(); + $dueDate = new \DateTime('2025-12-31'); + + $payment = new CreatePayment('Test', 'https://example.com', new Money(50.00, 'EUR')); + $payment->setBillingAddress($billingAddress); + $payment->setShippingAddress($shippingAddress); + $payment->setMethod(PaymentMethod::PAYPAL); + $payment->setLocale(Locale::deDE); + $payment->setSequenceType(SequenceType::RECURRING); + $payment->setCaptureMode(CaptureMode::MANUAL); + $payment->setWebhookUrl('https://example.com/webhook'); + $payment->setCardToken('test_card_token_123'); + $payment->setApplePayPaymentToken('test_apple_pay_token_456'); + $payment->setDueDate($dueDate); + $payment->setDescription('Test'); + $payment->setLines($lineItems); + $payment->setShopwareOrderNumber('SW-ORDER-123456'); + $payment->setCustomerReference('SW-CUSTOMER-123456'); + $payment->setCustomerId('SW-CUSTOMER-123'); + $payment->setMandateId('SW-MANDATOR-123456'); + $payment->setProfileId('SW-PROFILE-123456'); + $payment->setTerminalId('SW-TERMINAL-123456'); + + $this->assertSame('Test', $payment->getDescription()); + $this->assertSame('https://example.com', $payment->getRedirectUrl()); + $this->assertInstanceOf(Money::class, $payment->getAmount()); + $this->assertSame($billingAddress, $payment->getBillingAddress()); + $this->assertSame($shippingAddress, $payment->getShippingAddress()); + $this->assertSame(PaymentMethod::PAYPAL, $payment->getMethod()); + $this->assertSame(Locale::deDE, $payment->getLocale()); + $this->assertSame(SequenceType::RECURRING, $payment->getSequenceType()); + $this->assertSame(CaptureMode::MANUAL, $payment->getCaptureMode()); + $this->assertSame('https://example.com/webhook', $payment->getWebhookUrl()); + $this->assertSame('', $payment->getCancelUrl()); + $this->assertSame('test_card_token_123', $payment->getCardToken()); + $this->assertSame('test_apple_pay_token_456', $payment->getApplePayPaymentToken()); + $this->assertSame($dueDate, $payment->getDueDate()); + $this->assertSame($lineItems, $payment->getLines()); + $this->assertSame('SW-ORDER-123456', $payment->getShopwareOrderNumber()); + $this->assertSame('SW-CUSTOMER-123456', $payment->getCustomerReference()); + $this->assertSame('SW-CUSTOMER-123', $payment->getCustomerId()); + $this->assertSame('SW-MANDATOR-123456', $payment->getMandateId()); + $this->assertSame('SW-PROFILE-123456', $payment->getProfileId()); + $this->assertSame('SW-TERMINAL-123456', $payment->getTerminalId()); + } + + public function testApplePayPaymentTokenCanBeSetToNull(): void + { + $payment = new CreatePayment('Test', 'https://example.com', new Money(50.00, 'EUR')); + + $payment->setApplePayPaymentToken('token'); + $this->assertSame('token', $payment->getApplePayPaymentToken()); + + $payment->setApplePayPaymentToken(null); + $this->assertNull($payment->getApplePayPaymentToken()); + } + + public function testDueDateCanBeSetToNull(): void + { + $payment = new CreatePayment('Test', 'https://example.com', new Money(50.00, 'EUR')); + + $dueDate = new \DateTime('2025-12-31'); + $payment->setDueDate($dueDate); + $this->assertSame($dueDate, $payment->getDueDate()); + + $payment->setDueDate(null); + $this->assertNull($payment->getDueDate()); + } + + public function testToArray(): void + { + $payment = new CreatePayment('Test Payment', 'https://example.com/redirect', new Money(99.99, 'EUR')); + $payment->setMethod(PaymentMethod::IDEAL); + $payment->setWebhookUrl('https://example.com/webhook'); + + $array = $payment->toArray(); + + $this->assertIsArray($array); + $this->assertArrayHasKey('description', $array); + $this->assertArrayHasKey('amount', $array); + $this->assertArrayHasKey('redirectUrl', $array); + $this->assertArrayHasKey('method', $array); + $this->assertArrayHasKey('webhookUrl', $array); + $this->assertSame('Test Payment', $array['description']); + $this->assertSame('https://example.com/redirect', $array['redirectUrl']); + } + + public function testToArrayFiltersNullValues(): void + { + $payment = new CreatePayment('Test', 'https://example.com', new Money(50.00, 'EUR')); + + $array = $payment->toArray(); + + $this->assertArrayNotHasKey('cardToken', $array); + $this->assertArrayNotHasKey('applePayPaymentToken', $array); + $this->assertArrayNotHasKey('dueDate', $array); + } +} diff --git a/tests/Unit/Mollie/CustomerTest.php b/tests/Unit/Mollie/CustomerTest.php new file mode 100644 index 000000000..11667ebbe --- /dev/null +++ b/tests/Unit/Mollie/CustomerTest.php @@ -0,0 +1,59 @@ +getClientResponseBody('de_DE'); + $customer = Customer::fromClientResponse($body); + + $this->assertSame('123', $customer->getId()); + $this->assertSame('Max', $customer->getName()); + $this->assertSame('Max.Mollie@test.com', $customer->getEmail()); + $this->assertSame(['key' => 'value'], $customer->getMetaData()); + $this->assertSame(Locale::deDE, $customer->getLocale()); + } + + public function testSetAndGetLocale(): void + { + $customer = new Customer('123', 'Max', 'Max.Mollie@test.com', []); + $customer->setLocale(Locale::deDE); + + $this->assertSame(Locale::deDE, $customer->getLocale()); + } + + public function testJsonSerialize(): void + { + $customer = new Customer('123', 'Max', 'Max.Mollie@test.de', ['ref' => 'abc']); + + $json = $customer->jsonSerialize(); + + $this->assertIsArray($json); + $this->assertSame('123', $json['id']); + $this->assertSame('Max', $json['name']); + $this->assertSame('Max.Mollie@test.de', $json['email']); + $this->assertSame(['ref' => 'abc'], $json['metaData']); + } + + /** + * @return array + */ + private function getClientResponseBody(?string $locale): array + { + return [ + 'id' => '123', + 'name' => 'Max', + 'email' => 'Max.Mollie@test.com', + 'metadata' => ['key' => 'value'], + 'locale' => $locale, + ]; + } +} diff --git a/tests/Unit/Mollie/Fake/FakeClient.php b/tests/Unit/Mollie/Fake/FakeClient.php new file mode 100644 index 000000000..bbb2472bb --- /dev/null +++ b/tests/Unit/Mollie/Fake/FakeClient.php @@ -0,0 +1,61 @@ +response = new Response(status: 500, body: json_encode([ + 'title' => 'Failed Response', + 'detail' => 'This response failed and simulate an exception', + 'field' => 'payment.id', + ])); + + return; + } + $body = ['id' => $id, 'status' => $status, 'method' => $method->value]; + if ($this->checkoutUrl !== null) { + $body['_links']['checkout']['href'] = $this->checkoutUrl; + } + if ($embed) { + $body['_embedded']['payments'][0] = $body; + } + $this->response = new Response(body: json_encode($body)); + } + + public function get($uri, array $options = []): ResponseInterface + { + if ($this->response->getStatusCode() === 500) { + $request = new Request('GET', $uri); + throw new ClientException('Exception was triggered', $request, $this->response); + } + + return $this->response; + } + + public function post($uri, array $options = []): ResponseInterface + { + if ($this->response->getStatusCode() === 500) { + $request = new Request('POST', $uri); + throw new ClientException('Exception was triggered', $request, $this->response); + } + + return $this->response; + } +} diff --git a/tests/Unit/Mollie/Fake/FakeClientFactory.php b/tests/Unit/Mollie/Fake/FakeClientFactory.php new file mode 100644 index 000000000..eeb6e4d97 --- /dev/null +++ b/tests/Unit/Mollie/Fake/FakeClientFactory.php @@ -0,0 +1,19 @@ +client; + } +} diff --git a/tests/Unit/Mollie/Fake/FakeRouteBuilder.php b/tests/Unit/Mollie/Fake/FakeRouteBuilder.php new file mode 100644 index 000000000..fcf677e3a --- /dev/null +++ b/tests/Unit/Mollie/Fake/FakeRouteBuilder.php @@ -0,0 +1,44 @@ +returnUrl; + } + + public function getWebhookUrl(string $transactionId): string + { + return $this->webhookUrl; + } + + public function getPosCheckoutUrl(Payment $payment, string $transactionId, string $orderNumber): string + { + return $this->posCheckoutUrl; + } + + public function getPaypalExpressRedirectUrl(): string + { + // TODO: Implement getPaypalExpressRedirectUrl() method. + } + + public function getPaypalExpressCancelUrl(): string + { + // TODO: Implement getPaypalExpressCancelUrl() method. + } + + public function getSubscriptionWebhookUrl(string $subscriptionId): string + { + // TODO: Implement getSubscriptionWebhookUrl() method. + } +} diff --git a/tests/Unit/Mollie/Gateway/ClientFactoryTest.php b/tests/Unit/Mollie/Gateway/ClientFactoryTest.php new file mode 100644 index 000000000..50bfc19d1 --- /dev/null +++ b/tests/Unit/Mollie/Gateway/ClientFactoryTest.php @@ -0,0 +1,73 @@ +create(TestDefaults::SALES_CHANNEL); + $headers = $client->getConfig('headers'); + /** @var Uri $baseUri */ + $baseUri = $client->getConfig('base_uri'); + + $expectedUserAgent = sprintf('Shopware/%s MollieShopware6/%s', $shopwareVersion, MolliePayments::PLUGIN_VERSION); + $expectedAuthorization = 'Bearer ' . $key; + $expectedUrl = 'https://api.mollie.com/v2/'; + $this->assertSame($expectedAuthorization, $headers['Authorization']); + $this->assertSame($expectedUserAgent, $headers['User-Agent']); + $this->assertSame($expectedUrl, (string) $baseUri); + } + + public function testLiveKeyIsUsedInLiveMode(): void + { + $shopwareVersion = '6.7.4.0'; + $key = 'live_key'; + $apiSettings = new ApiSettings('test_key', $key, Mode::LIVE,''); + $fakeSettings = new FakeSettingsService(apiSettings: $apiSettings); + $factory = new ClientFactory($fakeSettings, $shopwareVersion); + + $client = $factory->create(TestDefaults::SALES_CHANNEL); + $headers = $client->getConfig('headers'); + /** @var Uri $baseUri */ + $baseUri = $client->getConfig('base_uri'); + + $expectedUserAgent = sprintf('Shopware/%s MollieShopware6/%s', $shopwareVersion, MolliePayments::PLUGIN_VERSION); + $expectedAuthorization = 'Bearer ' . $key; + $expectedUrl = 'https://api.mollie.com/v2/'; + $this->assertSame($expectedAuthorization, $headers['Authorization']); + $this->assertSame($expectedUserAgent, $headers['User-Agent']); + $this->assertSame($expectedUrl, (string) $baseUri); + } + + public function testExceptionIsThrownIfApiKeyIsEmpty(): void + { + $this->expectException(ApiKeyException::class); + $shopwareVersion = '6.7.4.0'; + + $apiSettings = new ApiSettings('test_key', '', Mode::LIVE,''); + $fakeSettings = new FakeSettingsService(apiSettings: $apiSettings); + $factory = new ClientFactory($fakeSettings, $shopwareVersion); + + $client = $factory->create(TestDefaults::SALES_CHANNEL); + } +} diff --git a/tests/Unit/Mollie/Gateway/MollieGatewayTest.php b/tests/Unit/Mollie/Gateway/MollieGatewayTest.php new file mode 100644 index 000000000..f76122060 --- /dev/null +++ b/tests/Unit/Mollie/Gateway/MollieGatewayTest.php @@ -0,0 +1,170 @@ +createValidStruct(); + + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + + $actual = $gateway->getPaymentByTransactionId('test', $context); + + $this->assertInstanceOf(Payment::class, $actual); + $this->assertSame('mollieTestId',$actual->getId()); + $this->assertSame('paid', $actual->getStatus()->value); + } + + public function testPaymentIsLoadedByOrderEntity(): void + { + $fakeClient = new FakeClient('mollieTestId', 'paid', embed: true); + $fakeClientFactory = new FakeClientFactory($fakeClient); + + $transactionService = new FakeTransactionService(); + $transactionService->withOrderCustomFields([ + 'order_id' => 'mollieTestId', + 'transactionReturnUrl' => 'payment/finalize', + ]); + + $gateway = new MollieGateway($fakeClientFactory, $transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + + $actual = $gateway->getPaymentByTransactionId('test', $context); + + $this->assertInstanceOf(Payment::class, $actual); + $this->assertSame('mollieTestId',$actual->getId()); + $this->assertSame('paid',$actual->getStatus()->value); + } + + public function testLoadingPaymentByOrderThrowsException(): void + { + $this->expectException(ApiException::class); + $fakeClient = new FakeClient(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + $transactionService = new FakeTransactionService(); + $transactionService->withOrderCustomFields([ + 'order_id' => 'mollieTestId', + 'transactionReturnUrl' => 'payment/finalize', + ]); + + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + + $gateway->getPaymentByTransactionId('test', $context); + } + + public function testTransactionWithoutMollieDataThrowsException(): void + { + $this->expectException(TransactionWithoutMollieDataException::class); + $fakeClient = new FakeClient(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + $transactionService = new FakeTransactionService(); + + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + $gateway->getPaymentByTransactionId('test', $context); + } + + public function testEmptyMollieOrderIdThrowsException(): void + { + $this->expectException(TransactionWithoutMollieDataException::class); + $fakeClient = new FakeClient(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + $transactionService = new FakeTransactionService(); + $transactionService->withOrderCustomFields([ + 'transactionReturnUrl' => 'payment/finalize', + ]); + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + $gateway->getPaymentByTransactionId('test', $context); + } + + public function testEmptyTransactionUrlThrowsException(): void + { + $this->expectException(TransactionWithoutMollieDataException::class); + $fakeClient = new FakeClient(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + $transactionService = new FakeTransactionService(); + + $transactionService->withOrderCustomFields([ + 'order_id' => 'test', + ]); + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $context = new Context(new SystemSource()); + $gateway->getPaymentByTransactionId('test', $context); + } + + public function testLoadPaymentThrowsException(): void + { + $this->expectException(ApiException::class); + + $fakeClient = new FakeClient(); + $transactionService = new FakeTransactionService(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + + $transactionService->createValidStruct(); + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + $context = new Context(new SystemSource()); + $gateway->getPaymentByTransactionId('test', $context); + } + + public function testCreatePaymentIsSuccessful(): void + { + $fakeClient = new FakeClient('mollieTestId', 'paid'); + $fakeClientFactory = new FakeClientFactory($fakeClient); + $transactionService = new FakeTransactionService(); + + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $createPayment = new CreatePayment('test','test',new Money(10.00,'EUR')); + $createPayment->setShopwareOrderNumber('10000'); + $payment = $gateway->createPayment($createPayment,Defaults::SALES_CHANNEL_TYPE_STOREFRONT); + $this->assertInstanceOf(Payment::class, $payment); + $this->assertSame('mollieTestId',$payment->getId()); + $this->assertSame('paid',$payment->getStatus()->value); + } + + public function testCreatePaymentHandledApiException(): void + { + $this->expectException(ApiException::class); + $fakeClient = new FakeClient(); + $fakeClientFactory = new FakeClientFactory($fakeClient); + + $transactionService = new FakeTransactionService(); + $gateway = new MollieGateway($fakeClientFactory,$transactionService, new NullLogger()); + + $createPayment = new CreatePayment('test','test',new Money(10.00,'EUR')); + $createPayment->setShopwareOrderNumber('10000'); + $gateway->createPayment($createPayment,Defaults::SALES_CHANNEL_TYPE_STOREFRONT); + } +} diff --git a/tests/Unit/Mollie/LineItemTest.php b/tests/Unit/Mollie/LineItemTest.php new file mode 100644 index 000000000..4b3410137 --- /dev/null +++ b/tests/Unit/Mollie/LineItemTest.php @@ -0,0 +1,171 @@ +orderRepository = new FakeOrderRepository(); + } + + public function testSettersAndGetters(): void + { + $price = new Money(10.99, 'EUR'); + $discountAmount = new Money(1.99, 'EUR'); + $vatAmount = new Money(1.99, 'EUR'); + $lineItem = new LineItem('test', 1, $price, $price); + $lineItem->setQuantityUnit('pc'); + $lineItem->setSku('test'); + $lineItem->setDiscountAmount($discountAmount); + $lineItem->setVatAmount($vatAmount); + $lineItem->setVatRate('7'); + $lineItem->setImageUrl('test.jpg'); + $lineItem->setProductUrl('test.com/1234'); + + $this->assertSame('test', $lineItem->getDescription()); + $this->assertSame(1, $lineItem->getQuantity()); + $this->assertEquals($price, $lineItem->getUnitPrice()); + $this->assertEquals($price, $lineItem->getTotalAmount()); + $this->assertSame('physical', $lineItem->getType()->value); + $this->assertSame('pc', $lineItem->getQuantityUnit()); + $this->assertEquals($discountAmount, $lineItem->getDiscountAmount()); + $this->assertEquals($vatAmount, $lineItem->getVatAmount()); + $this->assertSame('7', $lineItem->getVatRate()); + $this->assertSame('test.jpg', $lineItem->getImageUrl()); + $this->assertSame('test.com/1234', $lineItem->getProductUrl()); + $this->assertSame('test', $lineItem->getSku()); + } + + public function testExpectExceptionOnEmptyShippingMethod(): void + { + $delivery = new OrderDeliveryEntity(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + $this->expectException(MissingShippingMethodException::class); + LineItem::fromDelivery($delivery, $currency); + } + + public function testCanCreateFromDelivery(): void + { + $customerRepository = new FakeCustomerRepository(); + $customer = $customerRepository->getDefaultCustomer(); + $delivery = $this->orderRepository->getOrderDeliveries($customer)->first(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + $actual = LineItem::fromDelivery($delivery, $currency); + + $expected = [ + 'description' => 'DHL', + 'quantity' => 1, + 'type' => 'shipping_fee', + 'sku' => 'mol-delivery-fake-shipping-method-id', + 'unitPrice' => new Money(4.99, 'EUR'), + 'totalAmount' => new Money(4.99, 'EUR'), + ]; + + $this->assertInstanceOf(LineItem::class, $actual); + + $this->assertSame($expected['description'], $actual->getDescription()); + $this->assertSame($expected['quantity'], $actual->getQuantity()); + $this->assertSame($expected['type'], $actual->getType()->value); + $this->assertSame($expected['sku'], $actual->getSku()); + $this->assertEquals($expected['unitPrice'], $actual->getUnitPrice()); + $this->assertEquals($expected['totalAmount'], $actual->getTotalAmount()); + } + + public function testExpectExceptionOnEmptyLineItemPrice(): void + { + $this->expectException(MissingLineItemPriceException::class); + $orderLineItem = $this->orderRepository->getOrderLineItemWithoutPrice(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + LineItem::fromOrderLine($orderLineItem, $currency); + } + + public function testCanCreateFromOrderLine(): void + { + $lineItems = $this->orderRepository->getLineItems(); + $orderLineItem = $lineItems->first(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + $actual = LineItem::fromOrderLine($orderLineItem, $currency); + + $expected = [ + 'description' => 'Fake product', + 'quantity' => 1, + 'type' => 'digital', + 'sku' => 'SW1000', + 'unitPrice' => new Money(10.99, 'EUR'), + 'totalAmount' => new Money(10.99, 'EUR'), + ]; + + $this->assertInstanceOf(LineItem::class, $actual); + $this->assertSame($expected['description'], $actual->getDescription()); + $this->assertSame($expected['quantity'], $actual->getQuantity()); + $this->assertSame($expected['type'], $actual->getType()->value); + $this->assertSame($expected['sku'], $actual->getSku()); + $this->assertEquals($expected['unitPrice'], $actual->getUnitPrice()); + $this->assertEquals($expected['totalAmount'], $actual->getTotalAmount()); + } + + public function testCanCreateFromOrderLineWithVoucherCategoriesArray(): void + { + $orderLineItem = $this->orderRepository->getLineItemWithVoucherCategory(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + $actual = LineItem::fromOrderLine($orderLineItem, $currency); + + $this->assertInstanceOf(LineItem::class, $actual); + $this->assertSame('Voucher product', $actual->getDescription()); + $this->assertSame('SW1001', $actual->getSku()); + $this->assertCount(2, $actual->getCategories()); + } + + public function testCanCreateFromOrderLineWithSingleVoucherCategory(): void + { + $orderLineItem = $this->orderRepository->getLineItemWithSingleVoucherCategory(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + $actual = LineItem::fromOrderLine($orderLineItem, $currency); + + $this->assertInstanceOf(LineItem::class, $actual); + $this->assertSame('Single voucher product', $actual->getDescription()); + $this->assertSame('SW1002', $actual->getSku()); + $this->assertCount(1, $actual->getCategories()); + } + + public function testCanCreateFromOrderLineWithMixedVoucherCategories(): void + { + $orderLineItem = $this->orderRepository->getLineItemWithMixedVoucherCategories(); + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + $actual = LineItem::fromOrderLine($orderLineItem, $currency); + + $this->assertInstanceOf(LineItem::class, $actual); + $this->assertSame('Mixed voucher product', $actual->getDescription()); + $this->assertSame('SW1003', $actual->getSku()); + + $this->assertCount(2, $actual->getCategories()); + } +} diff --git a/tests/Unit/Mollie/LineItemTypeTest.php b/tests/Unit/Mollie/LineItemTypeTest.php new file mode 100644 index 000000000..511cc1cef --- /dev/null +++ b/tests/Unit/Mollie/LineItemTypeTest.php @@ -0,0 +1,86 @@ +assertSame('physical', LineItemType::PHYSICAL->value); + $this->assertSame('digital', LineItemType::DIGITAL->value); + $this->assertSame('shipping_fee', LineItemType::SHIPPING->value); + $this->assertSame('discount', LineItemType::DISCOUNT->value); + $this->assertSame('store_credit', LineItemType::CREDIT->value); + $this->assertSame('gift_card', LineItemType::GIFT_CARD->value); + $this->assertSame('surcharge', LineItemType::SURCHARGE->value); + $this->assertSame('customized-products', LineItemType::LINE_ITEM_TYPE_CUSTOM_PRODUCTS->value); + } + + public function testFromOrderLineItemWithProductType(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType(LineItem::PRODUCT_LINE_ITEM_TYPE); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::PHYSICAL, $result); + } + + public function testFromOrderLineItemWithCustomProductsType(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType(LineItemType::LINE_ITEM_TYPE_CUSTOM_PRODUCTS->value); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::PHYSICAL, $result); + } + + public function testFromOrderLineItemWithCreditType(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType(LineItem::CREDIT_LINE_ITEM_TYPE); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::CREDIT, $result); + } + + public function testFromOrderLineItemWithPromotionType(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType(LineItem::PROMOTION_LINE_ITEM_TYPE); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::DISCOUNT, $result); + } + + public function testFromOrderLineItemWithUnknownTypeDefaultsToDigital(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType('unknown_type'); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::DIGITAL, $result); + } + + public function testFromOrderLineItemWithShippingType(): void + { + $orderLineItem = new OrderLineItemEntity(); + $orderLineItem->setType('shipping'); + + $result = LineItemType::fromOderLineItem($orderLineItem); + + $this->assertSame(LineItemType::DIGITAL, $result); + } +} diff --git a/tests/Unit/Mollie/LocaleTest.php b/tests/Unit/Mollie/LocaleTest.php new file mode 100644 index 000000000..2eff9a795 --- /dev/null +++ b/tests/Unit/Mollie/LocaleTest.php @@ -0,0 +1,74 @@ +setCode('de-DE'); + + $language = new LanguageEntity(); + $language->setLocale($locale); + + $actual = Locale::fromLanguage($language); + + $this->assertSame(Locale::deDE, $actual); + } + + public function testCanCreateFromLanguageWithoutLocale(): void + { + $language = new LanguageEntity(); + + $actual = Locale::fromLanguage($language); + + $this->assertSame(Locale::enGB, $actual); + } + + public function testCanCreateFromLanguageWithDifferentLocales(): void + { + $testCases = [ + 'en-GB' => Locale::enGB, + 'en-US' => Locale::enUS, + 'nl-NL' => Locale::nlNL, + 'fr-FR' => Locale::frFR, + 'it-IT' => Locale::itIT, + 'de-DE' => Locale::deDE, + 'de-AT' => Locale::deAT, + 'de-CH' => Locale::deCH, + 'es-ES' => Locale::esES, + 'ca-ES' => Locale::caES, + 'nb-NO' => Locale::nbNO, + 'pt-PT' => Locale::ptPT, + 'sv-SE' => Locale::svSE, + 'fi-FI' => Locale::fiFI, + 'da-DK' => Locale::daDK, + 'is-IS' => Locale::isIS, + 'hu-HU' => Locale::huHU, + 'pl-PL' => Locale::plPL, + 'lv-LV' => Locale::lvLV, + 'lt-LT' => Locale::ltLT, + ]; + + foreach ($testCases as $code => $expectedLocale) { + $locale = new LocaleEntity(); + $locale->setCode($code); + + $language = new LanguageEntity(); + $language->setLocale($locale); + + $actual = Locale::fromLanguage($language); + + $this->assertSame($expectedLocale, $actual); + } + } +} diff --git a/tests/Unit/Mollie/MandateCollectionTest.php b/tests/Unit/Mollie/MandateCollectionTest.php new file mode 100644 index 000000000..27cabdeda --- /dev/null +++ b/tests/Unit/Mollie/MandateCollectionTest.php @@ -0,0 +1,39 @@ +filterByPaymentMethod(PaymentMethod::APPLEPAY); + + $this->assertCount(3, $filtered); + } + + public function testFilterByPaymentMethodReturnsEmptyCollection(): void + { + $collection = new MandateCollection([ + new Mandate('123', PaymentMethod::APPLEPAY, []), + new Mandate('1234', PaymentMethod::CREDIT_CARD, []), + ]); + + $filtered = $collection->filterByPaymentMethod(PaymentMethod::ALMA); + + $this->assertCount(0, $filtered); + } +} diff --git a/tests/Unit/Mollie/MandateTest.php b/tests/Unit/Mollie/MandateTest.php new file mode 100644 index 000000000..b63294284 --- /dev/null +++ b/tests/Unit/Mollie/MandateTest.php @@ -0,0 +1,38 @@ + '123', + 'method' => 'applepay', + 'details' => ['cardNumber' => '12341234'], + ]; + + $mandate = Mandate::fromClientResponse($body); + + $this->assertEquals('123', $mandate->getId()); + $this->assertEquals(PaymentMethod::APPLEPAY, $mandate->getMethod()); + $this->assertEquals(['cardNumber' => '12341234'], $mandate->getDetails()); + } + + public function testJsonSerialize(): void + { + $mandate = new Mandate('123', PaymentMethod::APPLEPAY, ['token' => 'abc123']); + + $json = $mandate->jsonSerialize(); + + $this->assertEquals('123', $json['id']); + $this->assertEquals(PaymentMethod::APPLEPAY, $json['method']); + $this->assertEquals(['token' => 'abc123'], $json['details']); + } +} diff --git a/tests/Unit/Mollie/MoneyTest.php b/tests/Unit/Mollie/MoneyTest.php new file mode 100644 index 000000000..d37f915ae --- /dev/null +++ b/tests/Unit/Mollie/MoneyTest.php @@ -0,0 +1,30 @@ +setIsoCode('EUR'); + $orderEntity = new OrderEntity(); + $orderEntity->setCurrency($currency); + $orderEntity->setTaxStatus(CartPrice::TAX_STATE_FREE); + $orderEntity->setAmountNet(19.99); + $orderEntity->setAmountTotal(25.00); + $money = Money::fromOrder($orderEntity,$currency); + + $this->assertSame('19.99', $money->getValue()); + $this->assertSame('EUR', $money->getCurrency()); + } +} diff --git a/tests/Unit/Mollie/PaymentStatusTest.php b/tests/Unit/Mollie/PaymentStatusTest.php new file mode 100644 index 000000000..4da5ac355 --- /dev/null +++ b/tests/Unit/Mollie/PaymentStatusTest.php @@ -0,0 +1,97 @@ +assertFalse($paidStatus->isFailed()); + $this->assertTrue($failedStatus->isFailed()); + $this->assertTrue($canceledStatus->isFailed()); + $this->assertTrue($expiredStatus->isFailed()); + } + + public function testCanceledStatus(): void + { + $paidStatus = PaymentStatus::PAID; + $failedStatus = PaymentStatus::FAILED; + $canceledStatus = PaymentStatus::CANCELED; + $expiredStatus = PaymentStatus::EXPIRED; + + $this->assertFalse($paidStatus->isCanceled()); + $this->assertFalse($failedStatus->isCanceled()); + $this->assertTrue($canceledStatus->isCanceled()); + $this->assertFalse($expiredStatus->isCanceled()); + } + + public function testInvalidStatus(): void + { + $this->expectExceptionMessageMatches('/"invalid" is not a valid/'); + + $invalid = PaymentStatus::from('invalid'); + } + + public function testShopwareHandlerMethods(): void + { + $paidStatus = PaymentStatus::PAID; + $authorizedStatus = PaymentStatus::AUTHORIZED; + $canceledStatus = PaymentStatus::CANCELED; + $failedStatus = PaymentStatus::FAILED; + $expiredStatus = PaymentStatus::EXPIRED; + + $this->assertSame('paid', $paidStatus->getShopwareHandlerMethod()); + $this->assertSame('authorize', $authorizedStatus->getShopwareHandlerMethod()); + $this->assertSame('cancel', $canceledStatus->getShopwareHandlerMethod()); + $this->assertSame('fail', $failedStatus->getShopwareHandlerMethod()); + $this->assertSame('', $expiredStatus->getShopwareHandlerMethod()); + } + + public function testGetAllWebhookEvents(): void + { + $events = PaymentStatus::getAllWebhookEvents(); + + $expected = [ + WebhookStatusOpenEvent::class, + WebhookStatusPendingEvent::class, + WebhookStatusAuthorizedEvent::class, + WebhookStatusPaidEvent::class, + WebhookStatusCancelledEvent::class, + WebhookStatusExpiredEvent::class, + WebhookStatusFailedEvent::class, + ]; + + $this->assertIsArray($events); + $this->assertCount(7, $events); + $this->assertSame($expected, $events); + } + + public function testGetWebhookEventClass(): void + { + $this->assertSame(WebhookStatusOpenEvent::class, PaymentStatus::OPEN->getWebhookEventClass()); + $this->assertSame(WebhookStatusPendingEvent::class, PaymentStatus::PENDING->getWebhookEventClass()); + $this->assertSame(WebhookStatusAuthorizedEvent::class, PaymentStatus::AUTHORIZED->getWebhookEventClass()); + $this->assertSame(WebhookStatusPaidEvent::class, PaymentStatus::PAID->getWebhookEventClass()); + $this->assertSame(WebhookStatusCancelledEvent::class, PaymentStatus::CANCELED->getWebhookEventClass()); + $this->assertSame(WebhookStatusExpiredEvent::class, PaymentStatus::EXPIRED->getWebhookEventClass()); + $this->assertSame(WebhookStatusFailedEvent::class, PaymentStatus::FAILED->getWebhookEventClass()); + } +} diff --git a/tests/Unit/Mollie/PaymentTest.php b/tests/Unit/Mollie/PaymentTest.php new file mode 100644 index 000000000..24e924a47 --- /dev/null +++ b/tests/Unit/Mollie/PaymentTest.php @@ -0,0 +1,84 @@ +setMethod(PaymentMethod::PAYPAL); + $payment->setStatus(PaymentStatus::PENDING); + $payment->setFinalizeUrl('http://test.finalize'); + $payment->setCheckoutUrl('http://test.checkout'); + $payment->setCountPayments(2); + $payment->setThirdPartyPaymentId('test_thirdPartyPaymentId'); + $payment->setShopwareTransaction(new OrderTransactionEntity()); + $payment->setChangePaymentStateUrl('http://test.payment'); + + $this->assertSame('tr_test', $payment->getId()); + $this->assertSame(PaymentMethod::PAYPAL, $payment->getMethod()); + $this->assertSame(PaymentStatus::PENDING, $payment->getStatus()); + $this->assertSame('http://test.finalize', $payment->getFinalizeUrl()); + $this->assertSame('http://test.checkout', $payment->getCheckoutUrl()); + $this->assertSame(2, $payment->getCountPayments()); + $this->assertSame('test_thirdPartyPaymentId', $payment->getThirdPartyPaymentId()); + $this->assertInstanceOf(OrderTransactionEntity::class, $payment->getShopwareTransaction()); + $this->assertSame('http://test.payment', $payment->getChangePaymentStateUrl()); + } + + public function testShopwareTransactionIsRemovedInData(): void + { + $payment = new Payment('tr_test'); + $payment->setMethod(PaymentMethod::PAYPAL); + $payment->setStatus(PaymentStatus::PENDING); + $payment->setShopwareTransaction(new OrderTransactionEntity()); + + $expectedArray = [ + 'status' => 'pending', + 'countPayments' => 1, + 'id' => 'tr_test', + 'method' => PaymentMethod::PAYPAL->value + ]; + + $this->assertEquals($expectedArray, $payment->toArray()); + } + + public function testCreatePaymentFromArray(): void + { + $body = [ + 'id' => 'tr_test', + 'method' => PaymentMethod::PAYPAL->value, + 'status' => PaymentStatus::PAID->value, + 'details' => [ + 'paypalReference' => 'thirdPartyPaymentId', + ], + '_links' => [ + 'checkout' => [ + 'href' => 'http://test.checkout', + ], + 'changePaymentState' => [ + 'href' => 'http://test.payment' + ] + ] + ]; + + $payment = Payment::createFromClientResponse($body); + + $this->assertSame('tr_test', $payment->getId()); + $this->assertSame('paid', $payment->getStatus()->value); + $this->assertSame('thirdPartyPaymentId', $payment->getThirdPartyPaymentId()); + $this->assertSame('http://test.checkout', $payment->getCheckoutUrl()); + $this->assertSame('http://test.payment', $payment->getChangePaymentStateUrl()); + } +} diff --git a/tests/Unit/Mollie/ProfileTest.php b/tests/Unit/Mollie/ProfileTest.php new file mode 100644 index 000000000..2452701ff --- /dev/null +++ b/tests/Unit/Mollie/ProfileTest.php @@ -0,0 +1,26 @@ + '123', + 'name' => 'Max', + 'email' => 'Max.Mollie@test.de' + ]; + + $profile = Profile::fromClientResponse($body); + + $this->assertEquals('123', $profile->getId()); + $this->assertEquals('Max', $profile->getName()); + $this->assertEquals('Max.Mollie@test.de', $profile->getEmail()); + } +} diff --git a/tests/Unit/Mollie/TerminalTest.php b/tests/Unit/Mollie/TerminalTest.php new file mode 100644 index 000000000..aaa8a4a40 --- /dev/null +++ b/tests/Unit/Mollie/TerminalTest.php @@ -0,0 +1,37 @@ + '123', + 'description' => 'test', + 'currency' => 'eur', + 'status' => 'active', + 'brand' => 'PAX', + 'model' => 'A35', + 'serialNumber' => '123123123' + ]; + + $terminal = Terminal::fromClientResponse($body); + + $this->assertEquals('123', $terminal->getId()); + $this->assertEquals('test', $terminal->getDescription()); + $this->assertEquals('eur', $terminal->getCurrency()); + $this->assertEquals(TerminalStatus::ACTIVE, $terminal->getStatus()); + $this->assertEquals(TerminalBrand::PAX, $terminal->getBrand()); + $this->assertEquals(TerminalModel::A35, $terminal->getModel()); + $this->assertEquals('123123123', $terminal->getSerialNumber()); + } +} diff --git a/tests/Unit/Mollie/VoucherCategoryTest.php b/tests/Unit/Mollie/VoucherCategoryTest.php new file mode 100644 index 000000000..fbffacbc1 --- /dev/null +++ b/tests/Unit/Mollie/VoucherCategoryTest.php @@ -0,0 +1,27 @@ +assertSame(VoucherCategory::ECO, VoucherCategory::tryFromNumber(1)); + $this->assertSame(VoucherCategory::GIFT, VoucherCategory::tryFromNumber(2)); + $this->assertSame(VoucherCategory::MEAL, VoucherCategory::tryFromNumber(3)); + } + + public function testTryFromNumberReturnsNullForInvalidNumber(): void + { + $this->assertNull(VoucherCategory::tryFromNumber(0)); + $this->assertNull(VoucherCategory::tryFromNumber(4)); + $this->assertNull(VoucherCategory::tryFromNumber(99)); + $this->assertNull(VoucherCategory::tryFromNumber(-1)); + } +} diff --git a/tests/Unit/Payment/Action/FinalizeTest.php b/tests/Unit/Payment/Action/FinalizeTest.php new file mode 100644 index 000000000..a274cf734 --- /dev/null +++ b/tests/Unit/Payment/Action/FinalizeTest.php @@ -0,0 +1,93 @@ +context = new Context(new SystemSource()); + $this->eventSpy = new EventSpy(); + } + + public function testSuccessEventIsFired(): void + { + $fakePayment = $this->getPayment(); + $fakePayment->setStatus(PaymentStatus::PAID); + + $paymentFinalize = $this->getFinalizeAction($fakePayment); + $paymentFinalize->execute(new PaymentTransactionStruct('test'), $this->context); + + $this->assertInstanceOf(SuccessEvent::class, $this->eventSpy->getEvent()); + } + + public function testCancelEventIsFired(): void + { + $fakePayment = $this->getPayment(); + $fakePayment->setStatus(PaymentStatus::CANCELED); + + $this->expectException(PaymentException::class); + $this->expectExceptionMessageMatches('/customer canceled the external payment process/'); + + $paymentFinalize = $this->getFinalizeAction($fakePayment); + $paymentFinalize->execute(new PaymentTransactionStruct('test'), $this->context); + $this->assertInstanceOf(CancelledEvent::class, $this->eventSpy->getEvent()); + } + + public function testFailedEventIsFired(): void + { + $fakePayment = $this->getPayment(); + $fakePayment->setStatus(PaymentStatus::FAILED); + + $this->expectException(PaymentException::class); + $this->expectExceptionMessageMatches('/payment finalize was interrupted/'); + + $paymentFinalize = $this->getFinalizeAction($fakePayment); + $paymentFinalize->execute(new PaymentTransactionStruct('test'), $this->context); + $this->assertInstanceOf(FailedEvent::class, $this->eventSpy->getEvent()); + } + + private function getFinalizeAction(Payment $fakePayment): Finalize + { + $transactionService = new FakeTransactionService(); + $transactionService->createValidStruct(); + + return new Finalize( + $transactionService, + new FakeGateway(payment: $fakePayment), + $this->eventSpy, + new NullLogger() + ); + } + + private function getPayment(): Payment + { + $fakePayment = new Payment('test'); + $fakePayment->setMethod(PaymentMethod::CREDIT_CARD); + + return $fakePayment; + } +} diff --git a/tests/Unit/Payment/Action/PayTest.php b/tests/Unit/Payment/Action/PayTest.php new file mode 100644 index 000000000..8eaa8f265 --- /dev/null +++ b/tests/Unit/Payment/Action/PayTest.php @@ -0,0 +1,74 @@ +createTransaction(); + $expectedUrl = 'https://mollie.com/checkout=token=123'; + + $payAction = $this->getPayAction($transactionService, $expectedUrl); + + $response = $payAction->execute(new FakePaymentMethodHandler(), new PaymentTransactionStruct('test', 'returnUrl'), new RequestDataBag(), new Context(new SystemSource())); + + $this->assertInstanceOf(RedirectResponse::class, $response); + $this->assertSame($expectedUrl, $response->getTargetUrl()); + } + + public function testPayActionRedirectToShopwareReturnUrl(): void + { + $transactionService = new FakeTransactionService(); + $transactionService->createTransaction(); + $expectedUrl = 'returnUrl'; + + $payAction = $this->getPayAction($transactionService, $expectedUrl); + + $response = $payAction->execute(new FakePaymentMethodHandler(), new PaymentTransactionStruct('test', 'returnUrl'), new RequestDataBag(), new Context(new SystemSource())); + + $this->assertInstanceOf(RedirectResponse::class, $response); + $this->assertSame($expectedUrl, $response->getTargetUrl()); + } + + private function getPayAction(FakeTransactionService $transactionService, string $checkoutUrl): Pay + { + $eventDispatcher = new FakeEventDispatcher(); + $fakeRouteBuilder = new FakeRouteBuilder(); + $paymentSettings = new PaymentSettings('test_{ordernumber}-{customernumber}', 0); + $settingsService = new FakeSettingsService(paymentSettings: $paymentSettings); + + $fakeOrderTransactionStateHandler = new FakeOrderTransactionStateHandler(); + $fakeCustomerRepository = new FakeCustomerRepository(); + $logger = new NullLogger(); + $gateway = new FakeGateway($checkoutUrl); + $lineItemAnalyzer = new LineItemAnalyzer(); + $builder = new CreatePaymentBuilder($fakeRouteBuilder, $settingsService,$gateway,$lineItemAnalyzer,$fakeCustomerRepository,$logger); + + return new Pay($transactionService, $builder, $gateway, $fakeOrderTransactionStateHandler, $fakeRouteBuilder,$eventDispatcher, $logger); + } +} diff --git a/tests/Unit/Payment/CreatePaymentBuilderTest.php b/tests/Unit/Payment/CreatePaymentBuilderTest.php new file mode 100644 index 000000000..7302ddcd1 --- /dev/null +++ b/tests/Unit/Payment/CreatePaymentBuilderTest.php @@ -0,0 +1,467 @@ +context = new Context(new SystemSource()); + } + + public function testBuild(): void + { + $builder = $this->createBuilder(); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + $actual->setCardToken('testCard'); + $actual->setMethod(PaymentMethod::PAYPAL); + + $this->assertInstanceOf(CreatePayment::class, $actual); + + $expected = [ + 'description' => 'test_10000-100', + 'amount' => [ + 'currency' => 'EUR', + 'value' => '100.00', + ], + 'redirectUrl' => '', + 'cancelUrl' => '', + 'webhookUrl' => '', + 'method' => 'paypal', + 'billingAddress' => [ + 'title' => 'Not specified', + 'givenName' => 'Tester', + 'familyName' => 'Test', + 'streetAndNumber' => 'Test Street', + 'postalCode' => '12345', + 'email' => 'fake@unit.test', + 'city' => 'Test City', + 'country' => 'DE', + ], + 'shippingAddress' => [ + 'title' => 'Not specified', + 'givenName' => 'Tester', + 'familyName' => 'Test', + 'streetAndNumber' => 'Test Street', + 'postalCode' => '12345', + 'email' => 'fake@unit.test', + 'city' => 'Test City', + 'country' => 'DE', + ], + 'locale' => 'en_GB', + 'lines' => [ + [ + 'type' => 'digital', + 'vatRate' => '19', + 'vatAmount' => [ + 'currency' => 'EUR', + 'value' => '2.09', + ], + 'sku' => 'SW1000', + 'description' => 'Fake product', + 'quantity' => 1, + 'unitPrice' => [ + 'currency' => 'EUR', + 'value' => '10.99', + ], + 'totalAmount' => [ + 'currency' => 'EUR', + 'value' => '10.99', + ] + ], + [ + 'type' => 'shipping_fee', + 'vatRate' => '19', + 'vatAmount' => [ + 'currency' => 'EUR', + 'value' => '0.95', + ], + 'sku' => 'mol-delivery-fake-shipping-method-id', + 'description' => 'DHL', + 'quantity' => 1, + 'unitPrice' => [ + 'currency' => 'EUR', + 'value' => '4.99', + ], + 'totalAmount' => [ + 'currency' => 'EUR', + 'value' => '4.99', + ], + ], + ], + 'sequenceType' => 'oneoff', + 'cardToken' => 'testCard', + 'metadata' => [ + 'shopwareOrderNumber' => '10000' + ] + ]; + $this->assertEquals($expected, $actual->toArray()); + + $this->assertSame($expected['cardToken'], $actual->getCardToken()); + $this->assertSame($expected['description'], $actual->getDescription()); + $this->assertInstanceOf(Address::class, $actual->getShippingAddress()); + $this->assertInstanceOf(Address::class, $actual->getBillingAddress()); + $this->assertInstanceOf(LineItemCollection::class, $actual->getLines()); + $this->assertEquals(new Money(100.00, 'EUR'), $actual->getAmount()); + $this->assertSame($expected['method'], $actual->getMethod()->value); + $this->assertEquals($expected['locale'], $actual->getLocale()->value); + $this->assertSame($expected['webhookUrl'], $actual->getWebhookUrl()); + $this->assertSame($expected['redirectUrl'], $actual->getRedirectUrl()); + $this->assertSame($expected['sequenceType'], $actual->getSequenceType()->value); + + $this->assertSame($expected['metadata']['shopwareOrderNumber'], $actual->getShopwareOrderNumber()); + } + + public function testSetters(): void + { + $createPayment = new CreatePayment('test', '', new Money(10.00, 'EUR')); + $createPayment->setDescription('test2'); + + $this->assertSame('test2', $createPayment->getDescription()); + } + + public function testBuildWithManualCaptureModeAwareHandler(): void + { + $builder = $this->createBuilder(); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakeManualCaptureModeAwarePaymentHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame(CaptureMode::MANUAL->value, $actual->getCaptureMode()->value); + } + + public function testBuildWithBankTransferAwareHandler(): void + { + $dueDateDays = 14; + $expectedDueDate = new \DateTime('now', new \DateTimeZone('UTC')); + $expectedDueDate->modify('+' . $dueDateDays . ' days'); + + $paymentSettings = new PaymentSettings('test_{ordernumber}-{customernumber}', $dueDateDays); + $builder = $this->createBuilder($paymentSettings); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakeBankTransferAwarePaymentHandler(), new RequestDataBag(), $this->context); + + $actualArray = $actual->toArray(); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertNotNull($actual->getDueDate()); + $this->assertInstanceOf(\DateTime::class, $actual->getDueDate()); + $this->assertSame($expectedDueDate->format('Y-m-d'),$actualArray['dueDate']); + + $this->assertSame($expectedDueDate->format('Y-m-d'), $actual->getDueDate()->format('Y-m-d')); + } + + public function testBuildWithBankTransferAwareHandlerButNoDueDateDays(): void + { + $builder = $this->createBuilder(); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakeBankTransferAwarePaymentHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertNull($actual->getDueDate()); + } + + public function testBuildWithMollieCustomerId(): void + { + $mollieCustomerId = 'cust_test_mollie_id'; + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + $transactionData = $transactionService->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame($mollieCustomerId, $actual->getCustomerId()); + } + + public function testBuildWithoutMollieCustomerId(): void + { + $builder = $this->createBuilder(); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertNull($actual->getCustomerId()); + } + + public function testBuildSetsSequenceTypeFirstWhenNotGuestAndSavePaymentDetails(): void + { + $mollieCustomerId = 'cust_test_mollie_id'; + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + + $transactionData = $transactionService->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('first', $actual->getSequenceType()->value); + } + + public function testBuildKeepsSequenceTypeOneoffWhenGuestEvenIfSavePaymentDetails(): void + { + $builder = $this->createBuilder(); + + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $transactionData->getCustomer()->setGuest(true); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('oneoff', $actual->getSequenceType()->value); + } + + public function testBuildSetsSequenceTypeRecurringWhenAllConditionsMet(): void + { + $mollieCustomerId = 'cust_test_mollie_id'; + $profileId = 'pfl_test_profile'; + $mandateId = 'tr_test_mandate_id'; + + $builder = $this->createBuilder(profileId: $profileId); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('mandateId', $mandateId); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + + $transactionData = $transactionService->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakeRecurringAwarePaymentHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('recurring', $actual->getSequenceType()->value); + $this->assertSame($mandateId, $actual->getMandateId()); + } + + public function testBuildKeepsSequenceTypeFirstWhenMandateIdMissingEvenIfRecurringHandler(): void + { + $mollieCustomerId = 'cust_test_mollie_id'; + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + + $transactionData = $transactionService->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakeRecurringAwarePaymentHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('first', $actual->getSequenceType()->value); + $this->assertNull($actual->getMandateId()); + } + + public function testBuildKeepsSequenceTypeOneoffWhenNotRecurringAwareHandler(): void + { + $mollieCustomerId = 'cust_test_mollie_id'; + $profileId = 'pfl_test_profile'; + $mandateId = 'tr_test_mandate_id'; + + $builder = $this->createBuilder(profileId: $profileId); + + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('mandateId', $mandateId); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + $transactionData = $transactionService->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('oneoff', $actual->getSequenceType()->value); + $this->assertNull($actual->getMandateId()); + } + + public function testBuildCreatesCustomerWhenSequenceTypeIsFirstAndNoCustomerId(): void + { + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('first', $actual->getSequenceType()->value); + $this->assertNotNull($actual->getCustomerId()); + $this->assertStringStartsWith('cust_fake_', $actual->getCustomerId()); + } + + public function testBuildDoesNotCreateCustomerWhenSequenceTypeIsOneoff(): void + { + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('oneoff', $actual->getSequenceType()->value); + $this->assertNull($actual->getCustomerId()); + } + + public function testBuildDoesNotCreateCustomerWhenCustomerIdAlreadyExists(): void + { + $mollieCustomerId = 'cust_existing_mollie_id'; + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, $mollieCustomerId); + + $transactionData = $transactionService->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('first', $actual->getSequenceType()->value); + $this->assertSame($mollieCustomerId, $actual->getCustomerId()); + } + + public function testBuildDoesNotCreateCustomerWhenGuest(): void + { + $profileId = 'pfl_test_profile'; + + $builder = $this->createBuilder(profileId: $profileId); + $requestDataBag = new RequestDataBag(); + $requestDataBag->set('savePaymentDetails', true); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $transactionData->getCustomer()->setGuest(true); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), $requestDataBag, $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('oneoff', $actual->getSequenceType()->value); + $this->assertNull($actual->getCustomerId()); + } + + public function testBuildWithEmptyOrderNumberFormat(): void + { + $paymentSettings = new PaymentSettings('', 0); + $builder = $this->createBuilder($paymentSettings); + + $transactionData = (new FakeTransactionService())->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('10000', $actual->getDescription()); + } + + public function testBuildWithEmptyProfileId(): void + { + $profileId = 'fake_profile'; + + $builder = $this->createBuilder(profileId: ''); + + $transactionService = new FakeTransactionService(); + $transactionService->withMollieCustomerId($profileId, 'cust_from_fallback_profile'); + + $transactionData = $transactionService->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertSame('cust_from_fallback_profile', $actual->getCustomerId()); + } + + public function testBuildWithNullLineItems(): void + { + $builder = $this->createBuilder(); + + $transactionService = new FakeTransactionService(); + $transactionService->withNullLineItems(); + + $transactionData = $transactionService->findById('test', $this->context); + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + $this->assertInstanceOf(LineItemCollection::class, $actual->getLines()); + } + + public function testBuildWithZeroShippingCosts(): void + { + $builder = $this->createBuilder(); + + $transactionService = new FakeTransactionService(); + $transactionService->withZeroShippingCosts(); + + $transactionData = $transactionService->findById('test', $this->context); + + $actual = $builder->build($transactionData, new FakePaymentMethodHandler(), new RequestDataBag(), $this->context); + + $this->assertInstanceOf(CreatePayment::class, $actual); + + $lines = $actual->getLines(); + foreach ($lines as $line) { + $this->assertNotSame('shipping_fee', $line->getType()->value); + } + } + + private function createBuilder(?PaymentSettings $paymentSettings = null, ?string $profileId = null): CreatePaymentBuilder + { + if ($paymentSettings === null) { + $paymentSettings = new PaymentSettings('test_{ordernumber}-{customernumber}', 0); + } + $settingsService = new FakeSettingsService(paymentSettings: $paymentSettings,profileId: $profileId); + + return new CreatePaymentBuilder(new FakeRouteBuilder(), $settingsService, new FakeGateway('test'), new LineItemAnalyzer(), new FakeCustomerRepository(), new NullLogger()); + } +} diff --git a/tests/Unit/Payment/Fake/FakeBankTransferAwarePaymentHandler.php b/tests/Unit/Payment/Fake/FakeBankTransferAwarePaymentHandler.php new file mode 100644 index 000000000..270d93b0e --- /dev/null +++ b/tests/Unit/Payment/Fake/FakeBankTransferAwarePaymentHandler.php @@ -0,0 +1,25 @@ + $data + */ + public function upsert(array $data, Context $context): EntityWrittenContainerEvent + { + return new EntityWrittenContainerEvent($context, new NestedEventCollection(), []); + } +} diff --git a/tests/Unit/Payment/Fake/FakeGateway.php b/tests/Unit/Payment/Fake/FakeGateway.php new file mode 100644 index 000000000..3ce398561 --- /dev/null +++ b/tests/Unit/Payment/Fake/FakeGateway.php @@ -0,0 +1,80 @@ +setMethod(PaymentMethod::CREDIT_CARD); + $payment->setCheckoutUrl($this->checkoutUrl); + $this->payment = $payment; + } + } + + public function createPayment(CreatePayment $molliePayment, string $salesChannelId): Payment + { + return $this->payment; + } + + public function getPaymentByTransactionId(string $transactionId, Context $context): Payment + { + return $this->payment; + } + + public function getCurrentProfile(?string $salesChannelId = null): Profile + { + return new Profile('fake_profile', 'fake', 'fake'); + } + + public function createCustomer(CustomerEntity $customer, string $salesChannelId): Customer + { + return new Customer('cust_fake_' . uniqid(), 'Fake Customer', 'fake@mollie.test', []); + } + + public function listMandates(string $mollieCustomerId, string $salesChannelId): MandateCollection + { + $collection = new MandateCollection(); + $mandate = new Mandate('tr_test_mandate_id', PaymentMethod::CREDIT_CARD, []); + $collection->set('tr_test_mandate_id', $mandate); + + return $collection; + } + + public function revokeMandate(string $mollieCustomerId, string $mandateId, string $salesChannelId): bool + { + // TODO: Implement revokeMandate() method. + } + + public function listTerminals(string $salesChannelId): TerminalCollection + { + // TODO: Implement listTerminals() method. + } + + public function getPayment(string $molliePaymentId, string $orderNumber, string $salesChannelId): Payment + { + // TODO: Implement getPayment() method. + } + + public function createCapture(CreateCapture $createCapture, string $paymentId, string $orderNumber, string $salesChannelId): Capture + { + // TODO: Implement createCapture() method. + } +} diff --git a/tests/Unit/Payment/Fake/FakeManualCaptureModeAwarePaymentHandler.php b/tests/Unit/Payment/Fake/FakeManualCaptureModeAwarePaymentHandler.php new file mode 100644 index 000000000..967e44eed --- /dev/null +++ b/tests/Unit/Payment/Fake/FakeManualCaptureModeAwarePaymentHandler.php @@ -0,0 +1,25 @@ +fakeId; + } + + public function getIdByPaymentMethod(PaymentMethod $paymentMethod, string $salesChannelId, Context $context): ?string + { + return $this->fakeId; + } +} diff --git a/tests/Unit/Payment/Fake/FakePaymentMethodUpdater.php b/tests/Unit/Payment/Fake/FakePaymentMethodUpdater.php new file mode 100644 index 000000000..e09c5859f --- /dev/null +++ b/tests/Unit/Payment/Fake/FakePaymentMethodUpdater.php @@ -0,0 +1,17 @@ +updatePaymentMethod($paymentMethodExtension, PaymentMethod::CREDIT_CARD, 'test', 'test', 'test', $context); + + $this->assertSame('shopwareId', $newPaymentMethodId); + } + + public function testApplePayAndCreditCardDoesNotChange(): void + { + $context = new Context(new SystemSource()); + + $paymentMethodUpdater = new PaymentMethodUpdater( + new FakeOrderTransactionRepository(), + new FakePaymentMethodRepository(), + new NullLogger() + ); + $paymentMethodExtension = new PaymentMethodExtension('shopwareId', PaymentMethod::APPLEPAY); + $newPaymentMethodId = $paymentMethodUpdater->updatePaymentMethod($paymentMethodExtension, PaymentMethod::CREDIT_CARD, 'test', 'test', 'test', $context); + + $this->assertSame('shopwareId', $newPaymentMethodId); + } + + public function testExceptionIsThrownOnDisabledPaymentMethod(): void + { + $this->expectException(\RuntimeException::class); + $context = new Context(new SystemSource()); + + $paymentMethodUpdater = new PaymentMethodUpdater( + new FakeOrderTransactionRepository(), + new FakePaymentMethodRepository(), + new NullLogger() + ); + $paymentMethodExtension = new PaymentMethodExtension('shopwareId', PaymentMethod::CREDIT_CARD); + $newPaymentMethodId = $paymentMethodUpdater->updatePaymentMethod($paymentMethodExtension, PaymentMethod::PAYCONIQ, 'test', 'test', 'test', $context); + } + + public function testNewPaymentMethodIsSet(): void + { + $context = new Context(new SystemSource()); + + $paymentMethodUpdater = new PaymentMethodUpdater( + new FakeOrderTransactionRepository(), + new FakePaymentMethodRepository('newPaymentMethodId'), + new NullLogger() + ); + $paymentMethodExtension = new PaymentMethodExtension('shopwareId', PaymentMethod::PAYPAL); + $newPaymentMethodId = $paymentMethodUpdater->updatePaymentMethod($paymentMethodExtension, PaymentMethod::CREDIT_CARD, 'test', 'test', 'test', $context); + + $this->assertSame('newPaymentMethodId', $newPaymentMethodId); + } +} diff --git a/tests/Unit/Payment/Route/WebhookRouteTest.php b/tests/Unit/Payment/Route/WebhookRouteTest.php new file mode 100644 index 000000000..937511e3a --- /dev/null +++ b/tests/Unit/Payment/Route/WebhookRouteTest.php @@ -0,0 +1,81 @@ +context = new Context(new SystemSource()); + } + + public function testWebhookIsSuccessful(): void + { + $webhookRoute = $this->getRoute(); + $response = $webhookRoute->notify('test', $this->context); + $this->assertInstanceOf(WebhookResponse::class, $response); + $this->assertInstanceOf(Payment::class, $response->getPayment()); + } + + public function testTransactionWithoutOrderExceptionIsThrown(): void + { + $transactionService = new FakeTransactionService(); + $transactionService->createValidStruct(); + $transactionService->withoutOrder(); + + $webhookRoute = $this->getRoute($transactionService); + try { + $response = $webhookRoute->notify('test', $this->context); + } catch (WebhookException $exception) { + $this->assertSame(WebhookException::TRANSACTION_WITHOUT_ORDER,$exception->getErrorCode()); + } + } + + private function getRoute(?TransactionServiceInterface $transactionService = null): WebhookRoute + { + if ($transactionService === null) { + $transactionService = new FakeTransactionService(); + $transactionService->createValidStruct(); + } + + $logger = new NullLogger(); + $fakeClient = new FakeClient('mollieTestId', 'paid'); + $fakeClientFactory = new FakeClientFactory($fakeClient); + + $gateway = new MollieGateway($fakeClientFactory, $transactionService, $logger); + + return new WebhookRoute( + $gateway, + new FakeOrderTransactionStateHandler(), + new FakeEventDispatcher(), + new FakePaymentMethodUpdater(), + new FakeOrderStateHandler(), + new FakeOrderService(), + $logger + ); + } +} diff --git a/tests/Unit/Settings/ApiSettingsTest.php b/tests/Unit/Settings/ApiSettingsTest.php new file mode 100644 index 000000000..b841b0353 --- /dev/null +++ b/tests/Unit/Settings/ApiSettingsTest.php @@ -0,0 +1,27 @@ + 'test_key', + ApiSettings::KEY_LIVE_API_KEY => 'live_key', + ApiSettings::KEY_TEST_MODE => true, + ]; + $settings = ApiSettings::createFromShopwareArray($data); + + $this->assertSame('test_key', $settings->getTestApiKey()); + $this->assertSame('live_key', $settings->getLiveApiKey()); + $this->assertTrue($settings->isTestMode()); + $this->assertSame('test_key', $settings->getApiKey()); + } +} diff --git a/tests/Unit/Settings/EnvironmentSettingsTest.php b/tests/Unit/Settings/EnvironmentSettingsTest.php new file mode 100644 index 000000000..4bbcefe2c --- /dev/null +++ b/tests/Unit/Settings/EnvironmentSettingsTest.php @@ -0,0 +1,19 @@ +assertTrue($settings->isDevMode()); + $this->assertFalse($settings->isCypressMode()); + } +} diff --git a/tests/Unit/Settings/LoggerSettingsTest.php b/tests/Unit/Settings/LoggerSettingsTest.php new file mode 100644 index 000000000..9cadd20b7 --- /dev/null +++ b/tests/Unit/Settings/LoggerSettingsTest.php @@ -0,0 +1,24 @@ + false, + LoggerSettings::KEY_LOG_FILE_DAYS => 5, + ]; + $settings = LoggerSettings::createFromShopwareArray($data); + + $this->assertFalse($settings->isDebugMode()); + $this->assertSame(5, $settings->getLogFileDays()); + } +} diff --git a/tests/Unit/Settings/PaymentSettingsTest.php b/tests/Unit/Settings/PaymentSettingsTest.php new file mode 100644 index 000000000..efa729fc4 --- /dev/null +++ b/tests/Unit/Settings/PaymentSettingsTest.php @@ -0,0 +1,22 @@ + 'test-{orderNumber}' + ]; + $settings = PaymentSettings::createFromShopwareArray($data); + + $this->assertSame('test-{orderNumber}', $settings->getOrderNumberFormat()); + } +} diff --git a/tests/Unit/StateHandler/Fake/FakeStateMachineRegistry.php b/tests/Unit/StateHandler/Fake/FakeStateMachineRegistry.php new file mode 100644 index 000000000..91fe000b4 --- /dev/null +++ b/tests/Unit/StateHandler/Fake/FakeStateMachineRegistry.php @@ -0,0 +1,37 @@ +actions[] = $transition->getTransitionName(); + $transition = $this->repository->findByActionName($transition->getTransitionName()); + $result = new StateMachineStateCollection(); + if ($transition instanceof StateMachineTransitionEntity) { + $result->set('fromPlace',$transition->getFromStateMachineState()); + $result->set('toPlace',$transition->getToStateMachineState()); + } + + return $result; + } + + public function getActions(): array + { + return $this->actions; + } +} diff --git a/tests/Unit/StateHandler/Fake/FakeStateMachineRepository.php b/tests/Unit/StateHandler/Fake/FakeStateMachineRepository.php new file mode 100644 index 000000000..dd05060af --- /dev/null +++ b/tests/Unit/StateHandler/Fake/FakeStateMachineRepository.php @@ -0,0 +1,131 @@ +collection = new StateMachineTransitionCollection(); + } + } + + public function search(Criteria $criteria, Context $context): EntitySearchResult + { + return new EntitySearchResult(StateMachineTransitionEntity::class, $this->collection->count(), $this->collection, null, $criteria, $context); + } + + public function findByActionName(string $actioName): ?StateMachineTransitionEntity + { + foreach ($this->collection as $stateMachineTransition) { + if ($stateMachineTransition->getActionName() === $actioName) { + return $stateMachineTransition; + } + } + + return null; + } + + public function createDefaultCollection(): void + { + $collection = new StateMachineTransitionCollection(); + + $stateMachine = new StateMachineEntity(); + $stateMachine->setId('oder.state.id'); + $stateMachine->setTechnicalName(OrderStates::STATE_MACHINE); + + $openState = new StateMachineStateEntity(); + $openState->setTechnicalName(OrderStates::STATE_OPEN); + $openState->setName('Open'); + $openState->setId('openId'); + + $inProgressState = new StateMachineStateEntity(); + $inProgressState->setTechnicalName(OrderStates::STATE_IN_PROGRESS); + $inProgressState->setName('In Progress'); + $inProgressState->setId('inProgressId'); + + $cancelledState = new StateMachineStateEntity(); + $cancelledState->setTechnicalName(OrderStates::STATE_CANCELLED); + $cancelledState->setName('Cancelled'); + $cancelledState->setId('cancelledId'); + + $completedState = new StateMachineStateEntity(); + $completedState->setTechnicalName(OrderStates::STATE_COMPLETED); + $completedState->setName('Done'); + $completedState->setId('completedId'); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('processId'); + $transition->setActionName('process'); + $transition->setFromStateMachineState($openState); + $transition->setFromStateId($openState->getId()); + $transition->setToStateMachineState($inProgressState); + $transition->setToStateId($inProgressState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('cancelFromOpenId'); + $transition->setActionName('cancel'); + $transition->setFromStateMachineState($openState); + $transition->setFromStateId($openState->getId()); + $transition->setToStateMachineState($cancelledState); + $transition->setToStateId($cancelledState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('cancelFromInProgressId'); + $transition->setActionName('cancel'); + $transition->setFromStateMachineState($inProgressState); + $transition->setFromStateId($inProgressState->getId()); + $transition->setToStateMachineState($cancelledState); + $transition->setToStateId($cancelledState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('doneId'); + $transition->setActionName('complete'); + $transition->setFromStateMachineState($inProgressState); + $transition->setFromStateId($inProgressState->getId()); + $transition->setToStateMachineState($completedState); + $transition->setToStateId($completedState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('reopenFromCancelledId'); + $transition->setActionName('reopen'); + $transition->setFromStateMachineState($cancelledState); + $transition->setFromStateId($cancelledState->getId()); + $transition->setToStateMachineState($openState); + $transition->setToStateId($openState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $transition = new StateMachineTransitionEntity(); + $transition->setId('reopenFromCompletedId'); + $transition->setActionName('reopen'); + $transition->setFromStateMachineState($completedState); + $transition->setFromStateId($completedState->getId()); + $transition->setToStateMachineState($openState); + $transition->setToStateId($openState->getId()); + $transition->setStateMachine($stateMachine); + $collection->add($transition); + + $this->collection = $collection; + } +} diff --git a/tests/Unit/StateHandler/OrderStateHandlerTest.php b/tests/Unit/StateHandler/OrderStateHandlerTest.php new file mode 100644 index 000000000..9fa279d49 --- /dev/null +++ b/tests/Unit/StateHandler/OrderStateHandlerTest.php @@ -0,0 +1,166 @@ +context = new Context(new SystemSource()); + } + + public function testOrderStateIsFinal(): void + { + $fakeOrder = $this->getOrder(); + $fakeOrder->setStateId('finalId'); + + $settings = new OrderStateSettings([], 'finalId'); + + $stateHandler = $this->getOrderStateHandler($settings); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_COMPLETED, 'test', $this->context); + $this->assertSame('finalId', $actual); + } + + public function testMappingForPaymentStateIsNotSet(): void + { + $fakeOrder = $this->getOrder(); + + $stateHandler = $this->getOrderStateHandler(); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_OPEN, 'test', $this->context); + $this->assertSame('openFakeStateId', $actual); + } + + public function testOrderIsAlreadyInCurrentSettings(): void + { + $fakeOrder = $this->getOrder(); + + $settings = new OrderStateSettings([ + OrderTransactionStates::STATE_PAID => 'open' + ]); + + $stateHandler = $this->getOrderStateHandler($settings); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_OPEN, 'test', $this->context); + $this->assertSame('openFakeStateId', $actual); + } + + public function testTransactionActionsAreNotSet(): void + { + $fakeOrder = $this->getOrder(); + + $settings = new OrderStateSettings([ + OrderTransactionStates::STATE_PAID => OrderStates::STATE_COMPLETED + ]); + + $stateHandler = $this->getOrderStateHandler($settings); + $this->expectException(\RuntimeException::class); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_OPEN, 'test', $this->context); + } + + public function testTransactionIsMovedOnce(): void + { + $fakeOrder = $this->getOrder(); + + $settings = new OrderStateSettings([ + OrderTransactionStates::STATE_PAID => OrderStates::STATE_IN_PROGRESS + ]); + $stateMachineRepository = new FakeStateMachineRepository(); + $stateMachineRepository->createDefaultCollection(); + + $stateHandler = $this->getOrderStateHandler($settings, $stateMachineRepository); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_OPEN, 'test', $this->context); + + $expectedTransition = ['process']; + $this->assertSame('inProgressId', $actual); + $this->assertSame($expectedTransition, $this->registry->getActions()); + } + + public function testTransactionIsMovedFromCancelledToComplete(): void + { + $fakeOrder = $this->getOrder(); + + $settings = new OrderStateSettings([ + OrderTransactionStates::STATE_PAID => OrderStates::STATE_COMPLETED + ]); + $stateMachineRepository = new FakeStateMachineRepository(); + $stateMachineRepository->createDefaultCollection(); + + $stateHandler = $this->getOrderStateHandler($settings, $stateMachineRepository); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_PAID, OrderStates::STATE_CANCELLED, 'test', $this->context); + + $expectedTransition = ['reopen', 'process', 'complete']; + $this->assertSame('completedId', $actual); + $this->assertSame($expectedTransition, $this->registry->getActions()); + } + + public function testTransactionIsMovedFromCompleteToCancelled(): void + { + $fakeOrder = $this->getOrder(); + + $settings = new OrderStateSettings([ + OrderTransactionStates::STATE_FAILED => OrderStates::STATE_CANCELLED + ]); + $stateMachineRepository = new FakeStateMachineRepository(); + $stateMachineRepository->createDefaultCollection(); + + $stateHandler = $this->getOrderStateHandler($settings, $stateMachineRepository); + + $actual = $stateHandler->performTransition($fakeOrder, OrderTransactionStates::STATE_FAILED, OrderStates::STATE_COMPLETED, 'test', $this->context); + + $expectedTransition = ['reopen', 'cancel']; + $this->assertSame('cancelledId', $actual); + $this->assertSame($expectedTransition, $this->registry->getActions()); + } + + private function getOrder(): OrderEntity + { + $customerRepository = new FakeCustomerRepository(); + $orderRepository = new FakeOrderRepository(); + + return $orderRepository->getDefaultOrder($customerRepository->getDefaultCustomer()); + } + + private function getOrderStateHandler(?OrderStateSettings $settings = null, ?FakeStateMachineRepository $stateMachineRepository = null): OrderStateHandler + { + if ($settings === null) { + $settings = new OrderStateSettings([]); + } + if ($stateMachineRepository === null) { + $stateMachineRepository = new FakeStateMachineRepository(); + } + $this->registry = new FakeStateMachineRegistry($stateMachineRepository); + + return new OrderStateHandler( + $stateMachineRepository, + $this->registry, + new FakeSettingsService(orderStateSettings: $settings), + new NullLogger() + ); + } +} diff --git a/tests/Unit/StatsUpdate/UpdateStatusActionTest.php b/tests/Unit/StatsUpdate/UpdateStatusActionTest.php index 61b0058b1..c8e916257 100644 --- a/tests/Unit/StatsUpdate/UpdateStatusActionTest.php +++ b/tests/Unit/StatsUpdate/UpdateStatusActionTest.php @@ -1,17 +1,19 @@ assertEquals(1, $result->getUpdated()); } -} \ No newline at end of file +} diff --git a/tests/Unit/Transaction/Fake/FakeTransactionService.php b/tests/Unit/Transaction/Fake/FakeTransactionService.php new file mode 100644 index 000000000..352b22427 --- /dev/null +++ b/tests/Unit/Transaction/Fake/FakeTransactionService.php @@ -0,0 +1,212 @@ +customerRepository = new FakeCustomerRepository(); + $this->orderRepository = new FakeOrderRepository(); + } + + public function findById(string $transactionId, Context $context): TransactionDataStruct + { + if ($this->transaction === null) { + $this->createTransaction(); + } + $this->transaction->getTransaction()->setId($transactionId); + + return $this->transaction; + } + + public function savePaymentExtension(string $transactionId, OrderEntity $order, Payment $payment, Context $context): EntityWrittenContainerEvent + { + $context = new Context(new SystemSource()); + $nestedEventCollection = new NestedEventCollection(); + + return new EntityWrittenContainerEvent($context, $nestedEventCollection, []); + } + + public function createValidStruct(): void + { + $this->withPayment = true; + } + + public function withoutOrder(): void + { + $this->withoutOrder = true; + } + + public function withOrderCustomFields(array $customFields): void + { + $this->orderCustomFields = $customFields; + } + + public function withMollieCustomerId(string $profileId, string $mollieCustomerId): void + { + $this->mollieCustomerIds[$profileId] = $mollieCustomerId; + } + + public function withNullLineItems(): void + { + $this->withNullLineItems = true; + } + + public function withZeroShippingCosts(): void + { + $this->withZeroShippingCosts = true; + } + + public function getDefaultSalesChannelEntity(): SalesChannelEntity + { + $salesChannel = new SalesChannelEntity(); + $salesChannel->setId(Defaults::SALES_CHANNEL_TYPE_STOREFRONT); + + return $salesChannel; + } + + public function createTransaction(): void + { + $transaction = new OrderTransactionEntity(); + $currency = $this->getDefaultCurrency(); + $language = $this->getDefaultLanguage(); + $customer = $this->customerRepository->getDefaultCustomer(); + + if (count($this->mollieCustomerIds) > 0) { + $customerExtension = new Customer(); + foreach ($this->mollieCustomerIds as $profileId => $mollieCustomerId) { + $customerExtension->setCustomerId($profileId, Mode::TEST, $mollieCustomerId); + } + $customer->addExtension(Mollie::EXTENSION, $customerExtension); + } + + if ($this->withPayment) { + $payment = new Payment('testMollieId'); + $payment->setMethod(PaymentMethod::CREDIT_CARD); + $payment->setFinalizeUrl('payment/finalize'); + $payment->setShopwareTransaction($transaction); + $transaction->addExtension(Mollie::EXTENSION, $payment); + + $paymentMethod = new PaymentMethodEntity(); + $paymentMethod->setId('testShopwareId'); + $paymentMethod->addExtension(Mollie::EXTENSION, new PaymentMethodExtension('testShopwareId', PaymentMethod::CREDIT_CARD)); + + $transaction->setPaymentMethodId($paymentMethod->getId()); + $transaction->setPaymentMethod($paymentMethod); + } + $order = $this->orderRepository->getDefaultOrder($customer); + $order->setCurrency($currency); + $order->setLanguage($language); + if (count($this->orderCustomFields) > 0) { + $order->setCustomFields([ + Mollie::EXTENSION => $this->orderCustomFields + ]); + } + + if ($this->withNullLineItems === true) { + $order->setLineItems(new OrderLineItemCollection()); + } + + if ($this->withoutOrder === false) { + $transaction->setOrder($order); + } + + $shippingAddress = $this->orderRepository->getOrderAddress($customer); + $billingAddress = $this->orderRepository->getOrderAddress($customer); + + $deliveries = $this->orderRepository->getOrderDeliveries($customer); + + if ($this->withZeroShippingCosts === true && $deliveries !== null) { + foreach ($deliveries as $delivery) { + $zeroPrice = new CalculatedPrice(0, 0, new CalculatedTaxCollection(), new TaxRuleCollection(), 1); + $delivery->setShippingCosts($zeroPrice); + } + } + + $this->transaction = new TransactionDataStruct( + $transaction, + $order, + $this->getDefaultSalesChannelEntity(), + $customer, + $shippingAddress, + $billingAddress, + $currency, + $language, + $deliveries + ); + } + + private function getDefaultCurrency(): CurrencyEntity + { + $currency = new CurrencyEntity(); + $currency->setIsoCode('EUR'); + + return $currency; + } + + private function getDefaultLocale(): LocaleEntity + { + $locale = new LocaleEntity(); + $locale->setCode('en-GB'); + + return $locale; + } + + private function getDefaultLanguage(): LanguageEntity + { + $language = new LanguageEntity(); + $language->setLocale($this->getDefaultLocale()); + + return $language; + } + + private function getDefaultCountry(): CountryEntity + { + $country = new CountryEntity(); + $country->setIso('DE'); + + return $country; + } +} diff --git a/tests/Unit/TranslationImporter/TranslationAppenderTest.php b/tests/Unit/TranslationImporter/TranslationAppenderTest.php index 556b1f900..4662a97ee 100644 --- a/tests/Unit/TranslationImporter/TranslationAppenderTest.php +++ b/tests/Unit/TranslationImporter/TranslationAppenderTest.php @@ -1,16 +1,18 @@ @@ -19,8 +21,7 @@ public function testAppendOnRoot(): void XML; - - $exampleXML = << @@ -30,11 +31,9 @@ public function testAppendOnRoot(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.title', 'Test', 'de-DE'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -42,7 +41,7 @@ public function testAppendOnRoot(): void public function testReplaceOldValue(): void { - $expectedXML = << @@ -51,8 +50,7 @@ public function testReplaceOldValue(): void XML; - - $exampleXML = << @@ -63,11 +61,9 @@ public function testReplaceOldValue(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.title', 'Test', 'de-DE'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -75,7 +71,7 @@ public function testReplaceOldValue(): void public function testAppendTitle(): void { - $expectedXML = << @@ -88,8 +84,7 @@ public function testAppendTitle(): void XML; - - $exampleXML = << @@ -103,11 +98,9 @@ public function testAppendTitle(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.title', 'API', 'pt-PT'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -115,7 +108,7 @@ public function testAppendTitle(): void public function testReplaceMultipleOldValues(): void { - $exampleXML = << @@ -164,7 +157,6 @@ public function testReplaceMultipleOldValues(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.title', 'API', 'pt-PT'); $result = $appender->append($dom, 'card.api.liveApiKey.label', 'Chave ativa', 'pt-PT'); @@ -172,16 +164,14 @@ public function testReplaceMultipleOldValues(): void $result = $appender->append($dom, 'card.api.testMode.label', 'Modo de Teste', 'pt-PT'); $result = $appender->append($dom, 'card.api.testMode.helpText', 'Ativa o modo de teste com a página de pagamento do Mollie Sandbox. A loja também será mostrada (Modo de teste) ao lado dos nomes dos métodos de pagamento.', 'pt-PT'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); - } public function testReplaceOldValuesInOptions(): void { - $exampleXML = << @@ -244,12 +234,11 @@ public function testReplaceOldValuesInOptions(): void XML; -$expectedXML = $exampleXML; + $expectedXML = $exampleXML; $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.orderStateAutomation.orderStateWithPartialRefundTransaction.label', 'Estado da encomenda com uma transação de reembolso parcial', 'pt-PT'); $result = $appender->append($dom, 'card.orderStateAutomation.orderStateWithPartialRefundTransaction.options.1.name', 'Ignorar este estado', 'pt-PT'); @@ -265,7 +254,7 @@ public function testReplaceOldValuesInOptions(): void public function testReplaceOldValueByNameOrTitle(): void { - $expectedXML = << @@ -278,8 +267,7 @@ public function testReplaceOldValueByNameOrTitle(): void XML; - - $exampleXML = << @@ -294,11 +282,9 @@ public function testReplaceOldValueByNameOrTitle(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.liveApiKey.label', 'New Key', 'de-DE'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -306,7 +292,7 @@ public function testReplaceOldValueByNameOrTitle(): void public function testFindByNameAndAppendNewTitle(): void { - $expectedXML = << @@ -317,8 +303,7 @@ public function testFindByNameAndAppendNewTitle(): void XML; - - $exampleXML = << @@ -330,11 +315,9 @@ public function testFindByNameAndAppendNewTitle(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.title', 'Test', 'de-DE'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -342,8 +325,7 @@ public function testFindByNameAndAppendNewTitle(): void public function testFindByChildNameAndAppendNewLabel(): void { - - $expectedXML = << @@ -366,8 +348,7 @@ public function testFindByChildNameAndAppendNewLabel(): void XML; - - $exampleXML = << @@ -391,11 +372,9 @@ public function testFindByChildNameAndAppendNewLabel(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.liveApiKey.label', 'Live Key', 'de-DE'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -403,7 +382,7 @@ public function testFindByChildNameAndAppendNewLabel(): void public function testAppendOptionsInArray(): void { - $expectedXML = << @@ -479,8 +458,7 @@ public function testAppendOptionsInArray(): void XML; - - $exampleXML = << @@ -556,20 +534,17 @@ public function testAppendOptionsInArray(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.applePay.applePayDirectRestrictions.options.2.name', 'Produktseiten', 'de-DE'); $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); - } public function testAppendElementToTheLastElementOfTheSameType(): void { - - $expectedXML = << @@ -593,8 +568,7 @@ public function testAppendElementToTheLastElementOfTheSameType(): void XML; - - $exampleXML = << @@ -619,7 +593,6 @@ public function testAppendElementToTheLastElementOfTheSameType(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.api.liveApiKey.label', 'Live Key', 'de-DE'); @@ -630,7 +603,7 @@ public function testAppendElementToTheLastElementOfTheSameType(): void public function testAppendMultipleTexts(): void { - $expectedXML = << @@ -698,8 +671,7 @@ public function testAppendMultipleTexts(): void XML; - - $exampleXML = << @@ -766,13 +738,11 @@ public function testAppendMultipleTexts(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.payments.title', 'Pagamentos', 'pt-PT'); $result = $appender->append($dom, 'card.payments.shopwareFailedPayment.label', 'Utilizar o comportamento padrão do Shopware para pagamentos falhados', 'pt-PT'); $result = $appender->append($dom, 'card.payments.shopwareFailedPayment.helpText', 'Utilizar o comportamento padrão do Shopware em pagamentos falhados. Se este estiver desativado, a Mollie fornecerá automaticamente uma maneira de tentar novamente o pagamento redirecionando o utilizador para a página de pagamentos da Mollie.', 'pt-PT'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); @@ -780,7 +750,7 @@ public function testAppendMultipleTexts(): void public function testFindOptionInComplexXML(): void { - $expectedXML = << @@ -1115,7 +1085,7 @@ public function testFindOptionInComplexXML(): void XML; - $exampleXML = << @@ -1452,14 +1422,11 @@ public function testFindOptionInComplexXML(): void $dom = new \DOMDocument(); $dom->loadXML($exampleXML); - $appender = new TranslationAppender(); $result = $appender->append($dom, 'card.orderStateAutomation.orderStateWithAPaidTransaction.options.1.name', 'Ignorar este estado', 'pt-PT'); - $expectedXML = preg_replace('/\s+/', '', $expectedXML); $actualXML = preg_replace('/\s+/', '', $dom->saveXML()); $this->assertEquals($expectedXML, $actualXML); - } -} \ No newline at end of file +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index aa4b66a99..c95a0c258 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -10,17 +10,25 @@ $projectDir = realpath(__DIR__ . '/../../../../'); -$envFilePath = $projectDir . '/.env'; - -if (\is_file($envFilePath) || \is_file($envFilePath . '.dist') || \is_file($envFilePath . '.local.php')) { - (new Dotenv())->usePutenv()->bootEnv($envFilePath); +$envFilePath = [ + $projectDir . '/.env', + $projectDir . '/.env.local', +]; + +foreach ($envFilePath as $file) { + if(!file_exists($file)) { + continue; + } + (new Dotenv())->usePutenv()->bootEnv($file); } + $dataBaseUrl = getenv('DATABASE_URL'); $testBootstrapper = new TestBootstrapper(); $testBootstrapper->setProjectDir($projectDir); $testBootstrapper->setDatabaseUrl($dataBaseUrl); -$testBootstrapper->addActivePlugins('MolliePayments'); +$testBootstrapper->addCallingPlugin(realpath(__DIR__.'/../composer.json')); +$testBootstrapper->setLoadEnvFile(false); $testBootstrapper->bootstrap(); diff --git a/vendor_manual/mollie-api-php/src/Endpoints/PaymentEndpoint.php b/vendor_manual/mollie-api-php/src/Endpoints/PaymentEndpoint.php index 93f2395e3..35c5a9ef2 100644 --- a/vendor_manual/mollie-api-php/src/Endpoints/PaymentEndpoint.php +++ b/vendor_manual/mollie-api-php/src/Endpoints/PaymentEndpoint.php @@ -187,15 +187,15 @@ public function refund(Payment $payment, $data = []) * * @param Payment|string $paymentId * - * @return \stdClass + * @return void * @throws ApiException */ - public function releaseAuthorization($paymentId) + public function releaseAuthorization($paymentId): void { $paymentId = $paymentId instanceof Payment ? $paymentId->id : $paymentId; $resource = "{$this->getResourcePath()}/" . urlencode($paymentId) . "/release-authorization"; - return $this->client->performHttpCall(self::REST_CREATE, $resource); + $this->client->performHttpCall(self::REST_CREATE, $resource); } } diff --git a/vendor_manual/mollie-api-php/src/HttpAdapter/CurlMollieHttpAdapter.php b/vendor_manual/mollie-api-php/src/HttpAdapter/CurlMollieHttpAdapter.php index dad4a2832..2b9d28ff8 100644 --- a/vendor_manual/mollie-api-php/src/HttpAdapter/CurlMollieHttpAdapter.php +++ b/vendor_manual/mollie-api-php/src/HttpAdapter/CurlMollieHttpAdapter.php @@ -19,11 +19,6 @@ final class CurlMollieHttpAdapter implements MollieHttpAdapterInterface */ public const DEFAULT_CONNECT_TIMEOUT = 2; - /** - * HTTP status code for an empty ok response. - */ - public const HTTP_NO_CONTENT = 204; - /** * The maximum number of retries */ @@ -184,12 +179,8 @@ protected function isConnectTimeoutError($curlErrorNumber, $executionTime) */ protected function parseResponseBody($response, $statusCode, $httpBody) { - if (empty($response)) { - if ($statusCode === self::HTTP_NO_CONTENT) { - return null; - } - - throw new ApiException("No response body found."); + if (empty($response) && $statusCode >= 200 && $statusCode < 300) { + return null; } $body = @json_decode($response); diff --git a/vendor_manual/mollie-api-php/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php b/vendor_manual/mollie-api-php/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php index a9e27cdb3..76df5f609 100644 --- a/vendor_manual/mollie-api-php/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php +++ b/vendor_manual/mollie-api-php/src/HttpAdapter/Guzzle6And7MollieHttpAdapter.php @@ -24,11 +24,6 @@ final class Guzzle6And7MollieHttpAdapter implements MollieHttpAdapterInterface */ public const DEFAULT_CONNECT_TIMEOUT = 2; - /** - * HTTP status code for an empty ok response. - */ - public const HTTP_NO_CONTENT = 204; - /** * @var \GuzzleHttp\ClientInterface */ @@ -157,12 +152,9 @@ public function disableDebugging() private function parseResponseBody(ResponseInterface $response) { $body = (string) $response->getBody(); - if (empty($body)) { - if ($response->getStatusCode() === self::HTTP_NO_CONTENT) { - return null; - } - throw new ApiException("No response body found."); + if (empty($body) && $response->getStatusCode() >= 200 && $response->getStatusCode() < 300) { + return null; } $object = @json_decode($body); diff --git a/vendor_manual/mollie-api-php/src/MollieApiClient.php b/vendor_manual/mollie-api-php/src/MollieApiClient.php index 59036655f..2e9bf0915 100644 --- a/vendor_manual/mollie-api-php/src/MollieApiClient.php +++ b/vendor_manual/mollie-api-php/src/MollieApiClient.php @@ -56,7 +56,7 @@ class MollieApiClient /** * Version of our client. */ - public const CLIENT_VERSION = "2.79.0"; + public const CLIENT_VERSION = "2.79.1"; /** * Endpoint of the remote API. diff --git a/vendor_manual/mollie-api-php/src/Types/PaymentMethod.php b/vendor_manual/mollie-api-php/src/Types/PaymentMethod.php index f04fe7125..0eb1bef3f 100644 --- a/vendor_manual/mollie-api-php/src/Types/PaymentMethod.php +++ b/vendor_manual/mollie-api-php/src/Types/PaymentMethod.php @@ -49,11 +49,6 @@ class PaymentMethod */ public const BITCOIN = "bitcoin"; - /** - * @link https://www.mollie.com/en/payments/bizum - */ - public const BIZUM = "bizum"; - /** * @link https://www.mollie.com/en/payments/blik */ @@ -202,5 +197,4 @@ class PaymentMethod * @link https://www.mollie.com/en/payments/twint */ public const TWINT = "twint"; - }