Je développe une méthode d'expédition pour une entreprise logistique. Cette entreprise possède de nombreux bureaux où le client peut obtenir sa commande. Je peux obtenir la liste des bureaux par ville dans l' API, mais je ne sais pas comment mieux représenter cette étape?
Pour l'instant je viens de mettre de nouveaux \Magento\Quote\Model\Quote\Address\RateResult\Method
bureaux dans chaque bureau de la ville, dans les grandes villes, c'est un compte> 100 et je pense que ce n'est pas très bien de mettre 100 lignes en caisse.
Ce sera un module public pour différentes conceptions de paiement, alors comment puis-je afficher près de ma méthode d'expédition une liste déroulante avec une liste de bureaux et définir le prix et la méthode après que l'utilisateur en a sélectionné une.
la source
Réponses:
Le paiement Magento ne prend en charge aucun type de formulaire pour les données supplémentaires sur la méthode d'expédition. Mais il fournit un
shippingAdditional
blocage dans la caisse qui peut être utilisé pour cela. La solution suivante fonctionnera pour le paiement standard de magento.Préparons d'abord notre conteneur où nous pouvons mettre une forme. Pour ce faire, créez un fichier dans
view/frontend/layout/checkout_index_index.xml
Créez maintenant un fichier dans
Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.js
lequel sera rendu un modèle de knockout. Son contenu ressemble à ceciCe fichier utilise un modèle knockout qui doit être placé dans
Vendor/Module/view/frontend/web/template/checkout/shipping/form.html
Nous avons maintenant un champ de sélection qui sera visible lorsque notre méthode (définie par son code) sera sélectionnée dans le tableau des méthodes d'expédition. Il est temps de le remplir avec quelques options. Comme les valeurs dépendent de l'adresse, le meilleur moyen est de créer un point de terminaison de repos qui fournira les options disponibles. Dans
Vendor/Module/etc/webapi.xml
Définissez maintenant l'interface en
Vendor/Module/Api/OfficeManagementInterface.php
tant queDéfinissez l'interface pour les données de bureau dans
Vendor\Module\Api\Data\OfficeInterface.php
. Cette interface sera utilisée par le module webapi pour filtrer les données pour la sortie, vous devez donc définir tout ce que vous devez ajouter à la réponse.Temps pour les cours réels. Commencez par créer des préférences pour toutes les interfaces dans
Vendor/Module/etc/di.xml
Créez maintenant une
Vendor\Module\Model\OfficeManagement.php
classe qui fera la logique de la récupération des données.Et enfin la classe pour
OfficeInterface
enVendor/Module/Model/Office.php
Cela devrait afficher le champ de sélection et le mettre à jour lorsque l'adresse est modifiée. Mais il nous manque un élément de plus pour la manipulation frontale. Nous devons créer une fonction qui appellera le point de terminaison. L'appeler est déjà inclus dans
Vendor/Module/view/frontend/web/js/view/checkout/shipping/form.js
et c'est laVendor_Module/js/view/checkout/shipping/office-service
classe qui devrait allerVendor/Module/view/frontend/web/js/view/checkout/shipping/office-service.js
avec le code suivant:Il utilise 2 fichiers js supplémentaires.
Vendor_Module/js/view/checkout/shipping/model/resource-url-manager
crée une URL vers le point de terminaison et est assez simpleVendor_Module/js/view/checkout/shipping/model/office-registry
est un moyen de conserver le résultat dans le stockage local. Son code est:Ok, donc nous devrions tous travailler sur le frontend. Mais maintenant, il y a un autre problème à résoudre. Comme la caisse ne sait rien de ce formulaire, elle n'enverra pas le résultat de la sélection au backend. Pour y arriver, nous devons utiliser
extension_attributes
fonctionnalité. C'est un moyen dans magento2 d'informer le système que certaines données supplémentaires devraient se trouver dans les autres appels. Sans cela, magento filtrerait ces données et n'atteindrait jamais le code.Donc,
Vendor/Module/etc/extension_attributes.xml
définissez d'abord:Cette valeur est déjà insérée dans la demande
form.js
parthis.selectedOffice.subscribe()
définition. Ainsi, la configuration ci-dessus ne la transmettra qu'à l'entrée. Pour le récupérer dans le code, créez un pluginVendor/Module/etc/di.xml
À l'intérieur de cette classe
Bien sûr, où vous économiserez la valeur dépend entièrement de vos besoins. Le code ci - dessus , il faudrait créer colonne supplémentaire
carrier_office
dansquote_address
etsales_address
tables et un événement (enVendor/Module/etc/events.xml
)Cela copierait les données enregistrées dans l'adresse de devis vers l'adresse de vente.
J'ai écrit ceci pour mon module pour l'opérateur polonais InPost, j'ai donc changé quelques noms qui pourraient casser le code mais j'espère que cela vous donnera ce dont vous avez besoin.
[ÉDITER]
Modèle de transporteur demandé par @sangan
la source
J'ajoute une nouvelle réponse pour développer ce qui était déjà fourni précédemment mais sans le déformer.
C'est la route qui
QuoteAddressPlugin
se connectait:La dernière méthode appelait
Magento\Quote\Model\Quote\Address::setShippingMethod()
ce qui était en fait un appel pourMagento\Quote\Model\Quote\Address::__call()
lequel j'ai utilisé. En ce moment, j'ai trouvé un meilleur endroit pour le plugin, c'est laMagento\Quote\Model\ShippingAssignment::setShipping()
méthode. La partie plugin peut donc être réécrite pour:et le plugin lui-même:
la source
@Zefiryn, je suis tombé sur le problème avec:
quote.shippingAddress().extensionAttributes.carrier_office = office;
Lorsque j'entre dans la caisse pour la première fois (nouvelle fenêtre privée) en tant qu'invité (mais la même chose se produit avec le client enregistré), l'attribut office n'est pas enregistré dans la base de données après le premier "Suivant". Bien que dans la console, je vois une sortie correcte pour:
console.log(quote.shippingAddress().extensionAttributes.carrier_office);
Lorsque je reviens à la première page de paiement et que je sélectionne à nouveau le bureau, il est enregistré. Quelle pourrait être la raison de ce comportement?
J'ai essayé d'utiliser:
address.trigger_reload = new Date().getTime(); rateRegistry.set(address.getKey(), null); rateRegistry.set(address.getCacheKey(), null); quote.shippingAddress(address);
mais sans succès ...
la source
@Zefiryn, pouvez-vous expliquer en quelques mots comment fonctionne votre plugin ci-dessus? Im peu confus parce que, comme je sais, la méthode __call est exécutée si nous essayons d'exécuter une méthode qui n'existe pas pour un objet particulier. Cela semble être vrai parce que dans app / code / Magento / Quote / Model / Quote / Address.php, je ne vois pas une telle méthode - seulement un commentaire:
/** * Sales Quote address model ... * @method Address setShippingMethod(string $value)
$subject->setInpostMachine
et$subject->getCarrierOffice(null);
cela signifie-t-il que la méthode du plugin ci-dessus sera exécutée à nouveau car il n'y a pas de méthode setInpostMachine () et getCarrierOffice () dans Adress Class? Cela ressemble à une boucle pour moi.setShippingMethod()
? Comment cette méthode est-elle utilisée normalement? Je ne trouve aucune interception simillar dans le code Magento.la source
setShippingMethod
appel sur l'AddressInterface
objet et comme il n'y a pas une telle méthode, j'ai dû utiliser around__call pour voir sisetShippingMethod
a été appelé ou un autre champ magique. En ce moment, j'ai trouvé un meilleur endroit et je le publierai dans une nouvelle réponse.