From 57246e23cee16bc93767f500628f17dd9e578d44 Mon Sep 17 00:00:00 2001 From: andrewrowanwallee Date: Thu, 15 Jan 2026 09:20:03 +0100 Subject: [PATCH] Release 6.2.0 --- CHANGELOG.md | 4 + CHANGELOG_de-DE.md | 4 + LICENSE.txt | 2 +- README.md | 25 +- composer.json | 2 +- docs/de/documentation.html | 158 ++++++--- docs/en/documentation.html | 158 ++++++--- docs/fr/documentation.html | 158 ++++++--- docs/it/documentation.html | 158 ++++++--- src/.DS_Store | Bin 0 -> 6148 bytes .../Refund/Controller/RefundController.php | 68 +++- src/Core/Api/Refund/Service/RefundService.php | 93 ++++- .../Entity/TransactionEntityDefinition.php | 2 +- .../Subscriber/CheckoutSubscriber.php | 2 + src/Core/Util/Analytics/Analytics.php | 2 +- .../Exception/RefundNotSupportedException.php | 8 + .../Migration1590156974TransactionEntity.php | 2 +- .../Migration1590646356RefundEntity.php | 2 +- .../Migration1590646356TransactionEntity.php | 2 +- .../Migration1605701048TransactionEntity.php | 8 +- .../Migration1684240994TransactionEntity.php | 2 +- .../Migration1766067106TransactionEntity.php | 324 ++++++++++++++++++ src/Resources/.DS_Store | Bin 0 -> 6148 bytes .../index.js | 19 +- .../index.js | 13 +- .../index.js | 13 +- .../index.html.twig | 1 + .../vrpayment-order-action-refund/index.js | 19 +- .../vrpayment-order-detail/index.html.twig | 2 +- .../page/vrpayment-order-detail/index.js | 40 ++- .../module/vrpayment-order/snippet/de-DE.json | 10 +- .../module/vrpayment-order/snippet/en-GB.json | 11 +- .../module/vrpayment-order/snippet/fr-FR.json | 10 +- .../module/vrpayment-order/snippet/it-IT.json | 10 +- .../config/services/core/api/refund.xml | 1 + src/Resources/public/.DS_Store | Bin 0 -> 6148 bytes src/Resources/public/administration/.DS_Store | Bin 0 -> 6148 bytes .../administration/js/v-r-payment-payment.js | 2 +- 38 files changed, 1098 insertions(+), 237 deletions(-) create mode 100644 src/.DS_Store create mode 100644 src/Core/Util/Exception/RefundNotSupportedException.php create mode 100644 src/Migration/Migration1766067106TransactionEntity.php create mode 100644 src/Resources/.DS_Store create mode 100644 src/Resources/public/.DS_Store create mode 100644 src/Resources/public/administration/.DS_Store diff --git a/CHANGELOG.md b/CHANGELOG.md index 754b4c3..b164e4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +# 6.2.0 +- Renamed database table to avoid a naming conflict with legacy plugins +- Fixed issue with refunds failing for payments using Invoice + # 6.1.17 - Sales channels now support different spaces - Upgraded SDK to include latest fallback CA Bundle diff --git a/CHANGELOG_de-DE.md b/CHANGELOG_de-DE.md index bcb2cf5..d4079e7 100644 --- a/CHANGELOG_de-DE.md +++ b/CHANGELOG_de-DE.md @@ -1,3 +1,7 @@ +# 6.2.0 +- Datenbanktabelle umbenannt, um Namenskonflikte mit älteren Plugins zu vermeiden. +- Problem mit fehlgeschlagenen Rückerstattungen bei Zahlungen mit Rechnungen behoben. + # 6.1.17 - Vertriebskanäle unterstützen jetzt verschiedene Bereiche - SDK aktualisiert und enthält nun das neueste CA-Fallback-Bundle diff --git a/LICENSE.txt b/LICENSE.txt index cb82feb..a7f6000 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -186,7 +186,7 @@ same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2025 VR Payment GmbH + Copyright 2026 VR Payment GmbH Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index 5d45669..e0bac0b 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,10 @@ The VR Payment Payment Plugin integrates modern payment processing into Shopware - **VR Payment Account:** Obtain `Space ID`, `User ID`, and `API Key` from the [VR Payment Dashboard](https://gateway.vr-payment.de/). ## Documentation - -- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/en/documentation.html) -- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/de/documentation.html) -- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/fr/documentation.html) -- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.1.17/docs/it/documentation.html) +- For English documentation click [here](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.0/docs/en/documentation.html) +- Für die deutsche Dokumentation klicken Sie [hier](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.0/docs/de/documentation.html) +- Pour la documentation Française, cliquez [ici](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.0/docs/fr/documentation.html) +- Per la documentazione in tedesco, clicca [qui](https://docs.plugin-documentation.vr-payment.de/vr-payment/shopware-6/6.2.0/docs/it/documentation.html) ## Installation @@ -43,6 +42,22 @@ bin/console plugin:refresh bin/console plugin:install --activate --clearCache VRPaymentPayment ``` +## Update + +### Via Administration +1. Go to Shopware Admin > Extensions > My extensions. +2. Find VRPaymentPayment. +3. Click Update. + +### Via CLI +1. Deploy the new plugin files (replace the folder in custom/plugins/VRPaymentPayment or upload/install a new ZIP). +2. Run: +```bash +bin/console plugin:refresh +bin/console plugin:update --clearCache VRPaymentPayment +bin/console cache:clear +``` + ## Configuration ### API Credentials diff --git a/composer.json b/composer.json index b02a130..197cbf1 100644 --- a/composer.json +++ b/composer.json @@ -59,5 +59,5 @@ "vrpayment/sdk": "^4.0.0" }, "type": "shopware-platform-plugin", - "version": "6.1.17" + "version": "6.2.0" } diff --git a/docs/de/documentation.html b/docs/de/documentation.html index ed6b1ea..e54c5b1 100644 --- a/docs/de/documentation.html +++ b/docs/de/documentation.html @@ -178,10 +178,59 @@ php bin/console plugin:install --activate --clearCache VRPaymentPayment +
+
+

+ 5Update

+
+
+
+
+

+ 5.1Via Administration

+
+
+
+
    +
  1. +

    Gehe zu Shopware Admin > Erweiterungen > Meine Erweiterungen.

    +
  2. +
  3. +

    Suche nach VRPaymentPayment.

    +
  4. +
  5. +

    Klicke auf Aktualisieren.

    +
  6. +
+
+
+
+

+ 5.2Via CLI

+
+
+
+
    +
  1. +

    Stelle die neuen Plugin-Dateien bereit (ersetze den Ordner custom/plugins/VRPaymentPayment oder lade ein neues ZIP hoch/installiere es).

    +
  2. +
  3. +

    Führe aus:

    +
    +
    +
    bin/console plugin:refresh
    +bin/console plugin:update --clearCache VRPaymentPayment
    +bin/console cache:clear
    +
    +
    +
  4. +
+
+

- 5Portal-Startanleitung

+ 6Portal-Startanleitung
@@ -200,7 +249,7 @@ Wählen Sie das passende Abo aus – es sollte E-Commerce-Transaktionen unterst

- 5.1Erstellen Sie den API-Schlüssel:

+ 6.1Erstellen Sie den API-Schlüssel:
@@ -286,7 +335,7 @@ Bitte beachten Sie, dass das Laden der Rollen einige Sekunden dauern kann.

- 5.2Zahlungsmethoden einrichten

+ 6.2Zahlungsmethoden einrichten
@@ -348,7 +397,7 @@ Bitte beachten Sie, dass die Konnektoren doppelt erscheinen, da einer für Zahlu

- 6Shop-Startanleitung

+ 7Shop-Startanleitung
@@ -487,7 +536,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7Transaktionszustandsdiagramm

+ 8Transaktionszustandsdiagramm
@@ -497,7 +546,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7.1Zustandsabbildung von Shopware-Bestellungen

+ 8.1Zustandsabbildung von Shopware-Bestellungen
@@ -505,7 +554,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7.1.1Allgemeine Anmerkungen zu Bestellstatus

+ 8.1.1Allgemeine Anmerkungen zu Bestellstatus
@@ -515,7 +564,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7.2Zustandsabbildung des Shopware-Zahlungsstatus

+ 8.2Zustandsabbildung des Shopware-Zahlungsstatus
@@ -542,7 +591,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7.2.1Allgemeine Anmerkungen zu Zahlungsstatus

+ 8.2.1Allgemeine Anmerkungen zu Zahlungsstatus
@@ -552,7 +601,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 7.3Zustandsabbildung des Shopware-Lieferstatus

+ 8.3Zustandsabbildung des Shopware-Lieferstatus
@@ -578,7 +627,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 8Transaktionsverwaltung

+ 9Transaktionsverwaltung
@@ -586,7 +635,7 @@ Bitte beachten Sie, dass diese Option leer bleiben sollte, wenn Sie die Space Vi

- 8.1Bestellung abschließen (erfassen)

+ 9.1Bestellung abschließen (erfassen)
@@ -614,7 +663,7 @@ Wenn der Abschluss in VR Payment ausstehend ist, bleibt die Bestellung im Status

- 8.2Transaktion stornieren

+ 9.2Transaktion stornieren
@@ -638,7 +687,7 @@ Sie können nur Transaktionen stornieren, die noch nicht abgeschlossen sind.

- 8.3Rückerstattung einer Transaktion

+ 9.3Rückerstattung einer Transaktion
@@ -664,7 +713,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück

- 8.4Bestellungen auf On Hold

+ 9.4Bestellungen auf On Hold
@@ -686,7 +735,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück

- 8.5Einschränkungen der Synchronisierung zwischen VR Payment und Shopware

+ 9.5Einschränkungen der Synchronisierung zwischen VR Payment und Shopware
@@ -697,7 +746,7 @@ Es kann einige Zeit dauern, bis Sie die Rückerstattung in Shopware sehen. Rück

- 8.6Tokenisierung

+ 9.6Tokenisierung
@@ -717,7 +766,7 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar

- 8.7Hauptfunktionen

+ 9.7Hauptfunktionen
@@ -739,7 +788,7 @@ Die Tokenisierung ist für Gast-Checkouts nicht verfügbar

- 8.8Fehlerbehebung

+ 9.8Fehlerbehebung
@@ -771,7 +820,7 @@ tail -f var/log/whitelabelname_payment*.log

- 8.9FAQs

+ 9.9FAQs
@@ -800,7 +849,7 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.

- 9Änderungsprotokoll

+ 10Änderungsprotokoll
@@ -809,7 +858,7 @@ A: Ja, das Plugin unterstützt Wallets wie Apple Pay.

+
+

+ 5Update

+
+
+
+
+

+ 5.1Via Administration

+
+
+
+
    +
  1. +

    Go to Shopware Admin > Extensions > My extensions.

    +
  2. +
  3. +

    Find VRPaymentPayment.

    +
  4. +
  5. +

    Click Update.

    +
  6. +
+
+
+
+

+ 5.2Via CLI

+
+
+
+
    +
  1. +

    Deploy the new plugin files (replace the folder in custom/plugins/VRPaymentPayment or upload/install a new ZIP).

    +
  2. +
  3. +

    Run:

    +
    +
    +
    bin/console plugin:refresh
    +bin/console plugin:update --clearCache VRPaymentPayment
    +bin/console cache:clear
    +
    +
    +
  4. +
+
+

- 5Portal Startup Guide

+ 6Portal Startup Guide
@@ -194,7 +243,7 @@ Please select the proper subscription plan - it should support ecommerce transac

- 5.1Create the API key:

+ 6.1Create the API key:
@@ -280,7 +329,7 @@ Please note that Roles might be loading for few seconds

- 5.2Setup Payment Methods

+ 6.2Setup Payment Methods
@@ -342,7 +391,7 @@ Please note that the connectors seems duplicated but it because one is for Physi

- 6Shop Startup Guide

+ 7Shop Startup Guide
@@ -481,7 +530,7 @@ Please note that if you do not use the Space View Id; this option should stay em

- 7Transaction State graph

+ 8Transaction State graph
@@ -493,7 +542,7 @@ can be found in the

- 7.1State mapping of Shopware orders

+ 8.1State mapping of Shopware orders
@@ -501,7 +550,7 @@ can be found in the

- 7.1.1General remarks regarding order statuses

+ 8.1.1General remarks regarding order statuses
@@ -511,7 +560,7 @@ can be found in the

- 7.2State mapping of Shopware payment status

+ 8.2State mapping of Shopware payment status
@@ -538,7 +587,7 @@ can be found in the

- 7.2.1General remarks regarding payment statuses

+ 8.2.1General remarks regarding payment statuses
@@ -548,7 +597,7 @@ can be found in the

- 7.3State mapping of Shopware delivery status

+ 8.3State mapping of Shopware delivery status
@@ -574,7 +623,7 @@ can be found in the

- 8Transaction management

+ 9Transaction management
@@ -584,7 +633,7 @@ Shopware. However, there are some limitations (see below).

- 8.1Complete (capture) an order

+ 9.1Complete (capture) an order
@@ -618,7 +667,7 @@ the fulfill state is reached. Initially the transaction will be in the Aut

- 8.2Void a transaction

+ 9.2Void a transaction
@@ -642,7 +691,7 @@ You can only void transactions that are not yet completed.

- 8.3Refund of a transaction

+ 9.3Refund of a transaction
@@ -669,7 +718,7 @@ It can take some time until you see the refund in Shopware. Refunds will only be

- 8.4On hold orders

+ 9.4On hold orders
@@ -693,7 +742,7 @@ within the defined time frame, VR Payment will generate a manual task which you

- 8.5Limitations of the synchronization between VR Payment and Shopware

+ 9.5Limitations of the synchronization between VR Payment and Shopware
@@ -709,7 +758,7 @@ your Shopware backend.

- 8.6Tokenization

+ 9.6Tokenization
@@ -730,7 +779,7 @@ Tokenization is not available for guest checkouts.

- 8.7Key Features

+ 9.7Key Features
@@ -752,7 +801,7 @@ Tokenization is not available for guest checkouts.

- 8.8Troubleshooting

+ 9.8Troubleshooting
@@ -783,7 +832,7 @@ Tokenization is not available for guest checkouts.

- 8.9FAQs

+ 9.9FAQs
@@ -815,7 +864,7 @@ Tokenization is not available for guest checkouts.

- 9Changelog

+ 10Changelog
@@ -824,7 +873,7 @@ Tokenization is not available for guest checkouts.
+
+

+ 5Mise à jour

+
+
+
+
+

+ 5.1Via l’administration

+
+
+
+
    +
  1. +

    Allez dans Shopware Admin > Extensions > Mes extensions.

    +
  2. +
  3. +

    Recherchez VRPaymentPayment.

    +
  4. +
  5. +

    Cliquez sur Mettre à jour.

    +
  6. +
+
+
+
+

+ 5.2Via la CLI

+
+
+
+
    +
  1. +

    Déployez les nouveaux fichiers du plugin (remplacez le dossier custom/plugins/VRPaymentPayment ou téléversez/installez un nouveau ZIP).

    +
  2. +
  3. +

    Exécutez :

    +
    +
    +
    bin/console plugin:refresh
    +bin/console plugin:update --clearCache VRPaymentPayment
    +bin/console cache:clear
    +
    +
    +
  4. +
+
+

- 5Guide de démarrage pour le Portail

+ 6Guide de démarrage pour le Portail
@@ -187,7 +236,7 @@ Veuillez sélectionner le plan d’abonnement approprié - il doit prendre e

- 5.1Créez la clé API:

+ 6.1Créez la clé API:
@@ -273,7 +322,7 @@ Veuillez noter que le chargement des rôles peut durer quelques secondes.

- 5.2Configurer les modes de paiement

+ 6.2Configurer les modes de paiement
@@ -335,7 +384,7 @@ Veuillez noter que les connecteurs semblent faire double emploi, mais c’es

- 6Guide de démarrage pour Shopware

+ 7Guide de démarrage pour Shopware
@@ -474,7 +523,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7Différents Etats pour une Transaction

+ 8Différents Etats pour une Transaction
@@ -484,7 +533,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7.1Cartographie des différents états d’une commande de Shopware

+ 8.1Cartographie des différents états d’une commande de Shopware
@@ -492,7 +541,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7.1.1Remarque générales concernant les status des commandes

+ 8.1.1Remarque générales concernant les status des commandes
@@ -502,7 +551,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7.2Cartographie des différents états du paiement de Shopware

+ 8.2Cartographie des différents états du paiement de Shopware
@@ -529,7 +578,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7.2.1Remarques générales concernant les différents status pour les paiements

+ 8.2.1Remarques générales concernant les différents status pour les paiements
@@ -539,7 +588,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 7.3Carthographie des différents états de livraison chez Shopware

+ 8.3Carthographie des différents états de livraison chez Shopware
@@ -565,7 +614,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 8Gestion des Transactions

+ 9Gestion des Transactions
@@ -573,7 +622,7 @@ Veuillez noter que si vous n’utilisez pas Space View Id, cette option doit

- 8.1Complete (capture) an order

+ 9.1Complete (capture) an order
@@ -605,7 +654,7 @@ Lorsque le paiement est en attente dans wallee, la commande reste en attente.

- 8.2Annuler une transaction

+ 9.2Annuler une transaction
@@ -629,7 +678,7 @@ Vous ne pouvez annuler que les transactions qui ne sont pas encore complétée..

- 8.3Remboursement d’une transaction

+ 9.3Remboursement d’une transaction
@@ -655,7 +704,7 @@ Il peut s’écouler un certain temps avant que vous ne voyiez le remboursem

- 8.4Commandes en attente

+ 9.4Commandes en attente
@@ -677,7 +726,7 @@ Il peut s’écouler un certain temps avant que vous ne voyiez le remboursem

- 8.5Limites de la synchronisation entre wallee et Shopware

+ 9.5Limites de la synchronisation entre wallee et Shopware
@@ -688,7 +737,7 @@ Il peut s’écouler un certain temps avant que vous ne voyiez le remboursem

- 8.6Tokenisation

+ 9.6Tokenisation
@@ -708,7 +757,7 @@ La tokenisation n’est pas disponible pour les paiements par les invités.

- 8.7Caractéristiques Pricinpales

+ 9.7Caractéristiques Pricinpales
@@ -730,7 +779,7 @@ La tokenisation n’est pas disponible pour les paiements par les invités.

- 8.8Troubleshooting

+ 9.8Troubleshooting
@@ -761,7 +810,7 @@ La tokenisation n’est pas disponible pour les paiements par les invités.

- 8.9FAQs

+ 9.9FAQs
@@ -789,7 +838,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.

- 9Changelog

+ 10Changelog
@@ -798,7 +847,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.

- 10Contribuer

+ 11Contribuer
@@ -809,7 +858,7 @@ A: Oui, le plugin prend en charge les portefeuilles comme Apple Pay.

+
+
+

+ 5Aggiornamento

+
+
+
+
+

+ 5.1Tramite Amministrazione

+
+
+
+
    +
  1. +

    Vai su Shopware Admin > Estensioni > Le mie estensioni.

    +
  2. +
  3. +

    Trova VRPaymentPayment.

    +
  4. +
  5. +

    Clicca su Aggiorna.

    +
  6. +
+
+
+
+

+ 5.2Tramite CLI

+
+
+
+
    +
  1. +

    Distribuisci i nuovi file del plugin (sostituisci la cartella custom/plugins/VRPaymentPayment oppure carica/installa un nuovo ZIP).

    +
  2. +
  3. +

    Esegui:

    +
    +
    +
    bin/console plugin:refresh
    +bin/console plugin:update --clearCache VRPaymentPayment
    +bin/console cache:clear
    +
    +
    +
  4. +
+
+

- 5Guida Rapida al Portale

+ 6Guida Rapida al Portale
@@ -194,7 +243,7 @@ Selezionate il piano di abbonamento appropriato: dovrebbe supportare le transazi

- 5.1Create la chiave API:

+ 6.1Create la chiave API:
@@ -280,7 +329,7 @@ Si prega di notare che il caricamento dei ruoli potrebbe richiedere alcuni secon

- 5.2Configurate i Metodi di Pagamento

+ 6.2Configurate i Metodi di Pagamento
@@ -342,7 +391,7 @@ Si prega di notare che i connettori sembrano duplicati, ma è perché uno è per

- 6Guida Rapida al Shop

+ 7Guida Rapida al Shop
@@ -481,7 +530,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7Grafico dello Stato della Transazione

+ 8Grafico dello Stato della Transazione
@@ -491,7 +540,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7.1Mappatura degli Stati degli Ordini di Shopware

+ 8.1Mappatura degli Stati degli Ordini di Shopware
@@ -499,7 +548,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7.1.1Osservazioni Generali Riguardo agli Stati degli Ordini

+ 8.1.1Osservazioni Generali Riguardo agli Stati degli Ordini
@@ -509,7 +558,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7.2Mappatura dello Stato di Pagamento di Shopware

+ 8.2Mappatura dello Stato di Pagamento di Shopware
@@ -536,7 +585,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7.2.1Osservazioni Generali Riguardo agli Stati di Pagamento

+ 8.2.1Osservazioni Generali Riguardo agli Stati di Pagamento
@@ -546,7 +595,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 7.3Mappatura dello Stato di Spedizione di Shopware

+ 8.3Mappatura dello Stato di Spedizione di Shopware
@@ -572,7 +621,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 8Gestione delle Transazioni

+ 9Gestione delle Transazioni
@@ -580,7 +629,7 @@ Si prega di notare che se non utilizzate lo Space View Id, questa opzione dovreb

- 8.1Completare (Acquisire) un Ordine

+ 9.1Completare (Acquisire) un Ordine
@@ -612,7 +661,7 @@ Quando il completamento è in sospeso in Wallee, l’ordine rimarrà nello s

- 8.2Annullare una transazione

+ 9.2Annullare una transazione
@@ -636,7 +685,7 @@ Puoi annullare solo le transazioni che non sono ancora state completate

- 8.3Rimborso di una Transazione

+ 9.3Rimborso di una Transazione
@@ -662,7 +711,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri

- 8.4Ordini in Attesa

+ 9.4Ordini in Attesa
@@ -684,7 +733,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri

- 8.5Limitazioni della Sincronizzazione tra Wallee e Shopware

+ 9.5Limitazioni della Sincronizzazione tra Wallee e Shopware
@@ -695,7 +744,7 @@ Potrebbe volerci un po' di tempo prima che vediate il rimborso in Shopware. I ri

- 8.6Tokenization

+ 9.6Tokenization
@@ -715,7 +764,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 8.7Key Features

+ 9.7Key Features
@@ -737,7 +786,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 8.8Risoluzione dei Problemi

+ 9.8Risoluzione dei Problemi
@@ -768,7 +817,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 8.9FAQs

+ 9.9FAQs
@@ -800,7 +849,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 9Changelog

+ 10Changelog
@@ -809,7 +858,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 10Contribuzione

+ 11Contribuzione
@@ -820,7 +869,7 @@ La tokenizzazione non è disponibile per i checkout degli ospiti.

- 11Support

+ 12Support
@@ -871,128 +920,145 @@ La tokenizzazione non è disponibile per i checkout degli ospiti. diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..c07ac1b967871b7aae207f9d855b03e515e84b37 GIT binary patch literal 6148 zcmeHKJ8nWT5S&dYh-fHN`U<&$g~$cq0#Set=}AHKugbY{w9I}A&`UaK(5$o`d%a`J zQ@ni(z*gt|8?Xd0r#s@?hpG9#`^26qVnjO6IO7XD9B|s7CfR=nocn@}b1+=;cgN3R zIQq6s3P=GdAO)m=6u6-RRb1zb8=k47q<|E73I(2Zv|@h%<)6IFDX} z*gQb&g<~QkG)pQmsa7q9C7tnBdA)EA4pEMYQI5Ira{L-e bnb&;I{a!dG2A%Ps6ZJFTy2zx!y%qQcBVZMt literal 0 HcmV?d00001 diff --git a/src/Core/Api/Refund/Controller/RefundController.php b/src/Core/Api/Refund/Controller/RefundController.php index 0133c85..8788a64 100644 --- a/src/Core/Api/Refund/Controller/RefundController.php +++ b/src/Core/Api/Refund/Controller/RefundController.php @@ -13,7 +13,9 @@ use Symfony\Component\{ }; use VRPaymentPayment\Core\{ Api\Refund\Service\RefundService, - Settings\Service\SettingsService + Api\Transaction\Service\TransactionService, + Settings\Service\SettingsService, + Util\Exception\RefundNotSupportedException }; /** @@ -40,17 +42,24 @@ class RefundController extends AbstractController * @var \Psr\Log\LoggerInterface */ protected $logger; - + + /** + * @var \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService + */ + protected $transactionService; + /** * RefundController constructor. * * @param \VRPaymentPayment\Core\Api\Refund\Service\RefundService $refundService * @param \VRPaymentPayment\Core\Settings\Service\SettingsService $settingsService + * @param \VRPaymentPayment\Core\Api\Transaction\Service\TransactionService $transactionService */ - public function __construct(RefundService $refundService, SettingsService $settingsService) + public function __construct(RefundService $refundService, SettingsService $settingsService, TransactionService $transactionService) { $this->settingsService = $settingsService; $this->refundService = $refundService; + $this->transactionService = $transactionService; } /** @@ -81,12 +90,29 @@ class RefundController extends AbstractController $transactionId = $request->request->get('transactionId'); $quantity = (int)$request->request->get('quantity'); $lineItemId = $request->request->get('lineItemId'); - + + if ($quantity === null || $quantity <= 0) { + return new Response('refundQuantityZero', Response::HTTP_BAD_REQUEST); + } + $settings = $this->settingsService->getSettings($salesChannelId); $apiClient = $settings->getApiClient(); $transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId); - $refund = $this->refundService->create($transaction, $context, $lineItemId, $quantity); + + $maxQuantity = $this->refundService->getMaxRefundableQuantity($transaction, $context, $lineItemId); + + if ($quantity > $maxQuantity) { + return new Response('refundExceedsQuantity', Response::HTTP_BAD_REQUEST); + } + + try { + $refund = $this->refundService->create($transaction, $context, $lineItemId, $quantity); + } catch (RefundNotSupportedException $exception) { + $this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId); + return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST); + } + if ($refund === null) { return new Response('Refund was not created. Please check the refund amound or if the item was not refunded before', Response::HTTP_BAD_REQUEST); } @@ -111,11 +137,33 @@ class RefundController extends AbstractController $transactionId = $request->request->get('transactionId'); $refundableAmount = $request->request->get('refundableAmount'); + if ($refundableAmount === null || $refundableAmount <= 0.0) { + return new Response('refundAmountZero', Response::HTTP_BAD_REQUEST); + } + $settings = $this->settingsService->getSettings($salesChannelId); $apiClient = $settings->getApiClient(); $transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId); - $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context); + + $completed = (float) $transaction->getCompletedAmount(); + $refunded = (float) $transaction->getRefundedAmount(); + $maxRefund = round($completed - $refunded, 2); + + if ($refundableAmount > $maxRefund) { + return new Response('refundExceedsAmount', Response::HTTP_BAD_REQUEST); + } + + try { + $refund = $this->refundService->createRefundByAmount($transaction, $refundableAmount, $context); + } catch (RefundNotSupportedException $exception) { + $this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId); + return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST); + } + + if ($refund === null) { + return new Response(null, Response::HTTP_BAD_REQUEST); + } return new Response(null, Response::HTTP_NO_CONTENT); } @@ -142,7 +190,13 @@ class RefundController extends AbstractController $apiClient = $settings->getApiClient(); $transaction = $apiClient->getTransactionService()->read($settings->getSpaceId(), $transactionId); - $this->refundService->createPartialRefund($transaction, $context, $lineItemId, $refundableAmount); + + try { + $refund = $this->refundService->createPartialRefund($transaction, $context, $lineItemId, $refundableAmount); + } catch (RefundNotSupportedException $exception) { + $this->logger->info('Payment method does not support online refunds for transaction: ' . $transactionId); + return new Response('methodDoesNotSupportRefund', Response::HTTP_BAD_REQUEST); + } return new Response(null, Response::HTTP_NO_CONTENT); } diff --git a/src/Core/Api/Refund/Service/RefundService.php b/src/Core/Api/Refund/Service/RefundService.php index defb2f8..970a534 100644 --- a/src/Core/Api/Refund/Service/RefundService.php +++ b/src/Core/Api/Refund/Service/RefundService.php @@ -12,14 +12,20 @@ use Shopware\Core\{ }; use VRPayment\Sdk\{ Model\Refund, - Model\Transaction + Model\Transaction, + Model\CriteriaOperator, + Model\EntityQueryFilter, + Model\EntityQueryFilterType, + Model\EntityQuery, + ApiException }; use VRPaymentPayment\Core\{ Api\Refund\Entity\RefundEntity, Api\Transaction\Entity\TransactionEntity, Api\Transaction\Entity\TransactionEntityDefinition, Settings\Service\SettingsService, - Util\Payload\RefundPayload + Util\Payload\RefundPayload, + Util\Exception\RefundNotSupportedException }; /** @@ -99,6 +105,12 @@ class RefundService $this->upsert($refund, $context); return $refund; } + } catch (ApiException $exception) { + $message = $exception->getMessage(); + $this->logger->critical($message); + if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) { + throw new RefundNotSupportedException($message, 0, $exception); + } } catch (\Exception $exception) { $this->logger->critical($exception->getMessage()); } @@ -134,6 +146,12 @@ class RefundService $this->upsert($refund, $context); return $refund; } + } catch (ApiException $exception) { + $message = $exception->getMessage(); + $this->logger->critical($message); + if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) { + throw new RefundNotSupportedException($message, 0, $exception); + } } catch (\Exception $exception) { $this->logger->critical($exception->getMessage()); } @@ -170,6 +188,12 @@ class RefundService $this->upsert($refund, $context); return $refund; } + } catch (ApiException $exception) { + $message = $exception->getMessage(); + $this->logger->critical($message); + if ($exception->getCode() === 442 && str_contains($message, 'does not support online refunds')) { + throw new RefundNotSupportedException($message, 0, $exception); + } } catch (\Exception $exception) { $this->logger->critical($exception->getMessage()); } @@ -240,5 +264,68 @@ class RefundService ) ->first(); } - + + /** + * Get total refunded quantity for transaction's line item by lineItemId. + * + * @param \VRPayment\Sdk\Model\Transaction $transaction + * @param \Shopware\Core\Framework\Context $context + * @param string $lineItemId + * + * @return int + */ + public function getRefundedQuantity(Transaction $transaction, Context $context, string $lineItemId): int { + $transactionEntity = $this->getTransactionEntityByTransactionId($transaction->getId(), $context); + $settings = $this->settingsService->getSettings($transactionEntity->getSalesChannel()->getId()); + $apiClient = $settings->getApiClient(); + + $entityQueryFilter = (new EntityQueryFilter()) + ->setType(EntityQueryFilterType::LEAF) + ->setOperator(CriteriaOperator::EQUALS) + ->setFieldName('transaction.id') + ->setValue($transaction->getId()); + + $query = (new EntityQuery())->setFilter($entityQueryFilter); + + $refunds = $apiClient->getRefundService()->search($settings->getSpaceId(), $query); + + $refundedQuantity = 0; + + foreach ($refunds as $refund) { + foreach ($refund->getReductions() as $reduction) { + if ($reduction->getLineItemUniqueId() === $lineItemId) { + $refundedQuantity += (int) $reduction->getQuantityReduction(); + } + } + } + + return $refundedQuantity; + } + + /** + * Get maximum quantity of available items to refund for line item. + * + * @param \VRPayment\Sdk\Model\Transaction $transaction + * @param \Shopware\Core\Framework\Context $context + * @param string $lineItemId + * + * @return int + */ + public function getMaxRefundableQuantity(Transaction $transaction, Context $context, string $lineItemId): int { + + $originalQuantity = 0; + + foreach ($transaction->getLineItems() as $lineItem) { + if ($lineItem->getUniqueId() === $lineItemId) { + $originalQuantity = (int) $lineItem->getQuantity(); + break; + } + } + + $refundedQuantity = $this->getRefundedQuantity($transaction, $context, $lineItemId); + + $maxQuantity = $originalQuantity - $refundedQuantity; + + return $maxQuantity; + } } diff --git a/src/Core/Api/Transaction/Entity/TransactionEntityDefinition.php b/src/Core/Api/Transaction/Entity/TransactionEntityDefinition.php index 3dcb045..391ffaa 100644 --- a/src/Core/Api/Transaction/Entity/TransactionEntityDefinition.php +++ b/src/Core/Api/Transaction/Entity/TransactionEntityDefinition.php @@ -32,7 +32,7 @@ use VRPaymentPayment\Core\Api\Refund\Entity\RefundEntityDefinition; */ class TransactionEntityDefinition extends EntityDefinition { - public const ENTITY_NAME = 'vrpayment_transaction'; + public const ENTITY_NAME = 'vrpayment_transaction_data'; /** * @return string diff --git a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php index 1c7ea24..036ed1e 100644 --- a/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php +++ b/src/Core/Storefront/Checkout/Subscriber/CheckoutSubscriber.php @@ -39,6 +39,7 @@ use VRPaymentPayment\Sdk\{Model\AddressCreate, Model\TransactionCreate, Model\TransactionPending}; use Shopware\Core\Framework\Struct\ArrayEntity; +use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting; /** * Class CheckoutSubscriber @@ -335,6 +336,7 @@ class CheckoutSubscriber implements EventSubscriberInterface $criteria->addFilter( new EqualsFilter('salesChannels.id', $event->getSalesChannelContext()->getSalesChannelId()) ); + $criteria->addSorting(new FieldSorting('position', FieldSorting::ASCENDING)); $result = $this->paymentMethodRepository->search($criteria, $event->getContext()); foreach ($result->getEntities() as $method) { diff --git a/src/Core/Util/Analytics/Analytics.php b/src/Core/Util/Analytics/Analytics.php index dcde480..0a74180 100644 --- a/src/Core/Util/Analytics/Analytics.php +++ b/src/Core/Util/Analytics/Analytics.php @@ -28,7 +28,7 @@ class Analytics { self::SHOP_SYSTEM => 'shopware', self::SHOP_SYSTEM_VERSION => $shopwareVersion, self::SHOP_SYSTEM_AND_VERSION => 'shopware-' . $shopwareVersion, - self::PLUGIN_SYSTEM_VERSION => '6.1.17', + self::PLUGIN_SYSTEM_VERSION => '6.2.0', ]; } diff --git a/src/Core/Util/Exception/RefundNotSupportedException.php b/src/Core/Util/Exception/RefundNotSupportedException.php new file mode 100644 index 0000000..ccfd5ef --- /dev/null +++ b/src/Core/Util/Exception/RefundNotSupportedException.php @@ -0,0 +1,8 @@ +executeStatement(' - CREATE TABLE IF NOT EXISTS `vrpayment_transaction` ( + CREATE TABLE IF NOT EXISTS `vrpayment_transaction_tmp` ( `id` BINARY(16) NOT NULL, `data` JSON NOT NULL, `payment_method_id` BINARY(16) NOT NULL, diff --git a/src/Migration/Migration1590646356RefundEntity.php b/src/Migration/Migration1590646356RefundEntity.php index 272d2ec..0f7cade 100644 --- a/src/Migration/Migration1590646356RefundEntity.php +++ b/src/Migration/Migration1590646356RefundEntity.php @@ -42,7 +42,7 @@ class Migration1590646356RefundEntity extends MigrationStep { PRIMARY KEY (`id`), UNIQUE KEY `refund_id_UNIQUE` (`refund_id`), KEY `fk.vrp_refund.transaction_id` (`transaction_id`), - CONSTRAINT `fk.vrp_refund.transaction_id` FOREIGN KEY (`transaction_id`) REFERENCES `vrpayment_transaction` (`transaction_id`) ON DELETE CASCADE + CONSTRAINT `fk.vrp_refund.transaction_id` FOREIGN KEY (`transaction_id`) REFERENCES `vrpayment_transaction_tmp` (`transaction_id`) ON DELETE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; '); } diff --git a/src/Migration/Migration1590646356TransactionEntity.php b/src/Migration/Migration1590646356TransactionEntity.php index 1e36e65..0173632 100644 --- a/src/Migration/Migration1590646356TransactionEntity.php +++ b/src/Migration/Migration1590646356TransactionEntity.php @@ -30,7 +30,7 @@ class Migration1590646356TransactionEntity extends MigrationStep { public function update(Connection $connection): void { try { - $connection->executeStatement('ALTER TABLE `vrpayment_transaction` ADD COLUMN `confirmation_email_sent` TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`;'); + $connection->executeStatement('ALTER TABLE `vrpayment_transaction_tmp` ADD COLUMN `confirmation_email_sent` TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`;'); }catch (\Exception $exception){ // column probably exists } diff --git a/src/Migration/Migration1605701048TransactionEntity.php b/src/Migration/Migration1605701048TransactionEntity.php index 5368d14..5d994e1 100644 --- a/src/Migration/Migration1605701048TransactionEntity.php +++ b/src/Migration/Migration1605701048TransactionEntity.php @@ -33,19 +33,19 @@ class Migration1605701048TransactionEntity extends MigrationStep try { $connection->executeStatement(' - ALTER TABLE `vrpayment_transaction` + ALTER TABLE `vrpayment_transaction_tmp` ADD `order_version_id` binary(16) NOT NULL AFTER `transaction_id`; '); $connection->executeStatement(' - UPDATE `vrpayment_transaction` t1 + UPDATE `vrpayment_transaction_tmp` t1 INNER JOIN `order` t2 ON t1.order_id = t2.id SET t1.order_version_id = t2.version_id; '); $connection->executeStatement(' - ALTER TABLE `vrpayment_transaction` + ALTER TABLE `vrpayment_transaction_tmp` DROP FOREIGN KEY `fk.vrp_transaction.order_id`, DROP FOREIGN KEY `fk.vrp_transaction.order_transaction_id`, DROP FOREIGN KEY `fk.vrp_transaction.payment_method_id`, @@ -53,7 +53,7 @@ class Migration1605701048TransactionEntity extends MigrationStep '); $connection->executeStatement(' - ALTER TABLE `vrpayment_transaction` + ALTER TABLE `vrpayment_transaction_tmp` ADD CONSTRAINT `fk.vrp_transaction_order_id` FOREIGN KEY (`order_id`, `order_version_id`) REFERENCES `order` (`id`, `version_id`) ON DELETE CASCADE ON UPDATE CASCADE, ADD CONSTRAINT `fk.vrp_transaction_payment_method_id` FOREIGN KEY (`payment_method_id`) diff --git a/src/Migration/Migration1684240994TransactionEntity.php b/src/Migration/Migration1684240994TransactionEntity.php index 2fc4bf9..0b9a5a0 100644 --- a/src/Migration/Migration1684240994TransactionEntity.php +++ b/src/Migration/Migration1684240994TransactionEntity.php @@ -30,7 +30,7 @@ class Migration1684240994TransactionEntity extends MigrationStep { public function update(Connection $connection): void { try { - $connection->executeStatement('ALTER TABLE `vrpayment_transaction` ADD COLUMN `erp_merchant_id` VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`;'); + $connection->executeStatement('ALTER TABLE `vrpayment_transaction_tmp` ADD COLUMN `erp_merchant_id` VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`;'); }catch (\Exception $exception){ // column probably exists } diff --git a/src/Migration/Migration1766067106TransactionEntity.php b/src/Migration/Migration1766067106TransactionEntity.php new file mode 100644 index 0000000..1cde2d6 --- /dev/null +++ b/src/Migration/Migration1766067106TransactionEntity.php @@ -0,0 +1,324 @@ +pushHandler(new StreamHandler(dirname(__DIR__, 5) . '/var/log/vrpayment-migration.log')); + $logger->info( + 'Migration start', [ + 'old_table_exists' => $this->tableExists($connection, $oldTableName), + 'temp_table_exists' => $this->tableExists($connection, $tempTableName), + 'real_table_exists' => $this->tableExists($connection, $realTableName), + ] + ); + + if ($this->tableExists($connection, $tempTableName)) { + // If _temp table exists, it means that this is a fresh installation. + $logger->info('Fresh installation detected.'); + $connection->executeStatement( + sprintf('RENAME TABLE `%s` TO `%s`', $tempTableName, $realTableName) + ); + $logger->info('Fresh installation finished.'); + } else { + // If _temp does not exist, it means that this could be a version upgrade. + $logger->info('Possible plugin upgrade detected.'); + if ($this->tableExists($connection, $oldTableName) && !$this->isOldPluginTable($connection, $oldTableName)) { + $logger->info('Old vrpayment_transaction table detected.'); + // If vrpayment_transaction already exists and does not belong to old plugin, + // it means that this is indeed a version update. + $this->syncTransactionTable($connection, $oldTableName); + $logger->info('Old vrpayment_transaction table sync finished.'); + $this->syncRefundTable($connection, $oldTableName); + $logger->info('Old vrpayment_refund table sync finished.'); + $connection->executeStatement( + sprintf('RENAME TABLE `%s` TO `%s`', $oldTableName, $realTableName) + ); + $logger->info('Old vrpayment_transaction table renaming completed.'); + } + $logger->info('Possible plugin upgrade finished.'); + // If vrpayment_transaction exists and it does belong to old plugin, + // it means we must run it in parallel. + } + $logger->info('Migration finished.'); + return; + } + + /** + * Check if table exists. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * + * @return bool + */ + public function tableExists(Connection $connection, string $table): bool { + $result = $connection->fetchOne('SHOW TABLES LIKE :table', ['table' => $table]); + return $result !== false && $result !== null; + } + + /** + * Check if table belongs to old plugin. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * + * @return bool + */ + public function isOldPluginTable(Connection $connection, string $table): bool { + $oldTableExclusiveColumns = [ + 'finalized_at' => 'datetime', + 'refunded_at' => 'datetime', + 'initial_transaction_mode' => 'varchar', + 'manual_capture' => 'tinyint', + 'partial_refunded_at' => 'datetime', + 'refunded_amount' => 'double', + 'amount_to_refund' => 'double', + ]; + $resultColumns = $connection->fetchAllAssociative( + 'SELECT LOWER(COLUMN_NAME) AS column_name, LOWER(DATA_TYPE) AS data_type + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = :table', + ['table' => $table] + ); + $dbColumns = []; + foreach($resultColumns as $column) { + $dbColumns[$column['column_name']] = $column['data_type']; + } + + $oldPluginTable = true; + foreach($oldTableExclusiveColumns as $columnName => $columnType) { + if(!isset($dbColumns[$columnName])) { + $oldPluginTable = false; + break; + } + if ($dbColumns[$columnName] !== $columnType) { + $oldPluginTable = false; + break; + } + } + return $oldPluginTable; + } + + /** + * Synchronizes the transaction table with the current/latest version. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + */ + private function syncTransactionTable(Connection $connection, string $table): void { + $this->addColumnIfMissing($connection, $table, 'confirmation_email_sent', "TINYINT(1) NOT NULL DEFAULT 0 AFTER `id`"); + $this->addColumnIfMissing($connection, $table, 'erp_merchant_id', "VARCHAR(255) DEFAULT NULL AFTER `confirmation_email_sent`"); + $this->addColumnIfMissing($connection, $table, 'data', "LONGTEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL CHECK (json_valid(`data`)) AFTER `erp_merchant_id`"); + $this->addColumnIfMissing($connection, $table, 'payment_method_id', "BINARY(16) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'order_id', "BINARY(16) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'order_transaction_id', "BINARY(16) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'space_id', "INT(10) UNSIGNED NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'state', "VARCHAR(255) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'sales_channel_id', "BINARY(16) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'transaction_id', "INT(10) UNSIGNED NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'order_version_id', "BINARY(16) NOT NULL AFTER `transaction_id`"); + + $this->addColumnIfMissing($connection, $table, 'created_at', "DATETIME(3) NOT NULL"); + $this->addColumnIfMissing($connection, $table, 'updated_at', "DATETIME(3) DEFAULT NULL"); + + $this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.order_id', "KEY `fk.vrp_transaction.order_id` (`order_id`)"); + $this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.order_transaction_id', "KEY `fk.vrp_transaction.order_transaction_id` (`order_transaction_id`)"); + $this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.payment_method_id', "KEY `fk.vrp_transaction.payment_method_id` (`payment_method_id`)"); + $this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction.sales_channel_id', "KEY `fk.vrp_transaction.sales_channel_id` (`sales_channel_id`)"); + $this->ensureIndexBySql($connection, $table, 'fk.vrp_transaction', "KEY `fk.vrp_transaction` (`order_id`,`order_version_id`)"); + + $this->ensureForeignKey( + $connection, + $table, + 'fk.vrp_transaction_order_id', + ['order_id', 'order_version_id'], + 'order', + ['id', 'version_id'], + 'CASCADE', + 'CASCADE' + ); + $this->ensureForeignKey( + $connection, + $table, + 'fk.vrp_transaction_payment_method_id', + ['payment_method_id'], + 'payment_method', + ['id'], + 'RESTRICT', + 'CASCADE' + ); + $this->ensureForeignKey( + $connection, + $table, + 'fk.vrp_transaction_sales_channel_id', + ['sales_channel_id'], + 'sales_channel', + ['id'], + 'RESTRICT', + 'CASCADE' + ); + } + + /** + * Synchronizes the parts of the refund table related to transactions with the current/latest version. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + */ + private function syncRefundTable(Connection $connection, string $table): void { + $refundTable = 'vrpayment_refund'; + $this->ensureIndexBySql($connection, $refundTable, 'fk.vrp_refund.transaction_id', "KEY `fk.vrp_refund.transaction_id` (`transaction_id`)"); + $this->ensureForeignKey( + $connection, + $refundTable, + 'fk.vrp_refund.transaction_id', + ['transaction_id'], + $table, + ['transaction_id'], + 'CASCADE', + null + ); + } + + /** + * Adds column to the table if it's missing. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * @param string $column + * @param string $sqlFragment + */ + private function addColumnIfMissing(Connection $connection, string $table, string $column, string $sqlFragment): void { + if ($this->columnExists($connection, $table, $column)) { + return; + } + $connection->executeStatement( + sprintf("ALTER TABLE `%s` ADD COLUMN `%s` %s", $table, $column, $sqlFragment) + ); + } + + /** + * Adds index to the table if it's missing. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * @param string $indexName + * @param string $sqlFragment + */ + private function ensureIndexBySql(Connection $connection, string $table, string $indexName, string $sqlFragment): void { + if ($this->indexExists($connection, $table, $indexName)) { + return; + } + $connection->executeStatement( + sprintf("ALTER TABLE `%s` ADD %s", $table, $sqlFragment) + ); + } + + /** + * Adds foreign key constraint to the table if it's missing. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * @param string $constraintName + * @param string $columns + * @param string $refTable + * @param string $refColumns + * @param string|null $onDelete + * @param string|null $onUpdate + */ + private function ensureForeignKey( + Connection $connection, + string $table, + string $constraintName, + array $columns, + string $refTable, + array $refColumns, + ?string $onDelete, + ?string $onUpdate + ): void { + if ($this->foreignKeyExists($connection, $table, $constraintName)) { + return; + } + $columnsList = '`' . implode('`,`', $columns) . '`'; + $refColumnsList = '`' . implode('`,`', $refColumns) . '`'; + $connection->executeStatement( + sprintf( + "ALTER TABLE `%s` + ADD CONSTRAINT `%s` FOREIGN KEY (%s) + REFERENCES `%s` (%s)%s%s", + $table, + $constraintName, + $columnsList, + $refTable, + $refColumnsList, + $onDelete ? " ON DELETE {$onDelete}" : "", + $onUpdate ? " ON UPDATE {$onUpdate}" : "" + ) + ); + } + + /** + * Check if foreign key constraint exists. + * + * @param \Doctrine\DBAL\Connection $connection + * @param string $table + * @param string $constraintName + * + * @return bool + */ + private function foreignKeyExists(Connection $connection, string $table, $constraintName): bool { + $result = $connection->fetchOne( + "SELECT 1 FROM information_schema.referential_constraints + WHERE constraint_schema = DATABASE() + AND table_name = ? + AND constraint_name = ? + LIMIT 1", + [$table,$constraintName] + ); + return $result !== false && $result !== null; + } + + /** + * update destructive changes + * + * @param \Doctrine\DBAL\Connection $connection + */ + public function updateDestructive(Connection $connection): void + { + // implement update destructive + } +} \ No newline at end of file diff --git a/src/Resources/.DS_Store b/src/Resources/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..b58b51eb1bcce3b292f0b283b09be84d2d433f4f GIT binary patch literal 6148 zcmeHKI|>3Z5S>vG!DdU#T)`Uz(Gz$9Q5#`FLF~8kTprCgpF&yfv{2r_^uvY(4IA~Jy+%GHLx*}i$t1{qNx9A_M4w?FUN?eW<5vR?;`JC>7NWGn3>-!^De zfC^9nDnJFOz{eHH5<8iG{A3;e&iX;6Vd)od{|=!lohtBGA;&_%QP(7ai*Ls7pS=NC^Gt$`e=02O#vU>M8B>i-J< zrvHB?aYY5Fz+Wk#qvd+Jz>~7J_8w=ow!k-V%eleLFn0c7o_SK_6`Nzf VCU${NN8IT^{tTEdG%E0I1@0mY6@&l) literal 0 HcmV?d00001 diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js index 2a0e0ad..55a297d 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-by-amount/index.js @@ -70,9 +70,24 @@ Component.register('vrpayment-order-action-refund-by-amount', { }); }).catch((errorResponse) => { try { + var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle') + var errorMessage; + switch(errorResponse.response.data) { + case 'refundAmountZero': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundAmountIsZero'); + break; + case 'refundExceedsAmount': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundAmountExceedsAvailableBalance'); + break; + case 'methodDoesNotSupportRefund': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund'); + break; + default: + errorMessage = errorResponse.response.data.errors[0].detail; + } this.createNotificationError({ - title: errorResponse.response.data.errors[0].title, - message: errorResponse.response.data.errors[0].detail, + title: errorTitle, + message: errorMessage, autoClose: false }); } catch (e) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js index b9274e8..1a4d668 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-partial/index.js @@ -69,9 +69,18 @@ Component.register('vrpayment-order-action-refund-partial', { }); }).catch((errorResponse) => { try { + var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle') + var errorMessage; + switch(errorResponse.response.data) { + case 'methodDoesNotSupportRefund': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund'); + break; + default: + errorMessage = errorResponse.response.data.errors[0].detail; + } this.createNotificationError({ - title: errorResponse.response.data.errors[0].title, - message: errorResponse.response.data.errors[0].detail, + title: errorTitle, + message: errorMessage, autoClose: false }); } catch (e) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.js index e2862b7..abbdb6c 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund-selected/index.js @@ -70,9 +70,18 @@ Component.register('vrpayment-order-action-refund-selected', { }); }).catch((errorResponse) => { try { + var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle') + var errorMessage; + switch(errorResponse.response.data) { + case 'methodDoesNotSupportRefund': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund'); + break; + default: + errorMessage = errorResponse.response.data.errors[0].detail; + } this.createNotificationError({ - title: errorResponse.response.data.errors[0].title, - message: errorResponse.response.data.errors[0].detail, + title: errorTitle, + message: errorMessage, autoClose: false }); } catch (e) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig index d25ef15..daef31d 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.html.twig @@ -9,6 +9,7 @@ :max="this.$parent.$parent.itemRefundableQuantity" :min="0" v-model:value="refundQuantity" + number-type="int" :label="$tc('vrpayment-order.refund.refundQuantity.label')"> diff --git a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.js b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.js index 243dc97..f389fe6 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.js +++ b/src/Resources/app/administration/src/module/vrpayment-order/component/vrpayment-order-action-refund/index.js @@ -68,9 +68,24 @@ Component.register('vrpayment-order-action-refund', { }); }).catch((errorResponse) => { try { + var errorTitle = errorResponse?.response?.data?.errors?.[0]?.title ?? this.$tc('vrpayment-order.refundAction.refundCreateError.errorTitle') + var errorMessage; + switch(errorResponse.response.data) { + case 'refundQuantityZero': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundQuantityIsZero'); + break; + case 'refundExceedsQuantity': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messageRefundQuantityExceedsAvailableBalance'); + break; + case 'methodDoesNotSupportRefund': + errorMessage = this.$tc('vrpayment-order.refundAction.refundCreateError.messagePaymentMethodDoesNotSupportRefund'); + break; + default: + errorMessage = errorResponse.response.data.errors[0].detail; + } this.createNotificationError({ - title: errorResponse.response.data.errors[0].title, - message: errorResponse.response.data.errors[0].detail, + title: errorTitle, + message: errorMessage, autoClose: false }); } catch (e) { diff --git a/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig b/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig index 5d68090..6691a6b 100644 --- a/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig +++ b/src/Resources/app/administration/src/module/vrpayment-order/page/vrpayment-order-detail/index.html.twig @@ -98,7 +98,7 @@