OXID eShop: Benutzerdefinierte Versandkostenregeln erstellen

Die Versandkostenregeln von OXID sind bekanntermaßen sehr komplex. Man braucht sich dafür nur die zahlreichen Beiträge im Forum anschauen. Trotzdem kann es unter Umständen erforderlich werden, seine eigenen Versandkostenregeln zu erstellen.

Standardmäßig bietet OXID die Parameter Menge, Größe, Gewicht und Preis, mit denen man die Berechnung der Versandkosten konfigurieren kann. Reichen diese jedoch nicht aus oder hat man mit seinem Paketdienstanbieter etwas anderes ausgehandelt, dann muss hier eine Ergänzung erfolgen.

Zunächst muss ein Modul erstellt werden

Hier empfehle ich, zunächst immer einen Vendor Ordner zu erstellen, in dem man alle seine Module pflegt. Das hilft den Überblick zu behalten und eigene von fremden Modulen unterscheiden zu können.
Im Ordner modules erstellen wir also einen Ordner ks. Dort erstellen wir einen weitere Ordner für unser Modul mit dem Namen ksdelivery. Wie ein OXID Modul erstellt wird, werde ich hier nicht im Detail erläutern. Ich empfehle Euch dafür, die zahlreichen Tutorials im Web durchzugehen.

Als erstes muss die neue Bedingung für die Versandkostenregeln m Backend verfügbar gemacht werden. Dazu müssen wir die Klasse delivery_main erweitern. Diese Klasse ist für die Darstellung des Tabs Stamm bei der Konfiguration der Versandkostenregeln verantwortlich, abrufbar unter Shopeinstellungen->Versandkostenregeln. Die Originaldatei befindet sich im Ordner application/controllers/admin/delivery_main.php. Für die Erweiterung erstellen wir einen Eintrag in der Datei metadata.php in unserem Modulordner.

'extend'    =>    array( 
                          'delivery_main'    =>    'ks/ksdelivery/controllers/admin/ks_delivery_main'
                      )

Im Ordner ks/ksdelivery/controllers/admin/ erstellen wir die entsprechende Datei ks_delivery_main.php.

<?php
class ks_delivery_main extends ks_delivery_main_parent {

}

Neue Bedingung ergänzen

Wir überschreiben die Methode render(), die jegliche Informationen sammelt und das Template rendert. Hier muss das Array $aDelTypes um die neue Bedingung ergänzt werden.
Als Bedingung verwenden wir das Volumengewicht, einen sehr häufig auftretenden Parameter. Hier findet Ihr wie z.B. UPS das Volumengewicht berechnet. Den gleichen Algorithmus werden wir hier auch benutzen.

public function render()
    
    {
    	
        $myConfig = $this->getConfig();
        parent::render();
        $oLang = oxRegistry::getLang();
        $iLang = $oLang->getTplLanguage();
        // remove itm from list
        unset( $this->_aViewData["sumtype"][2]);
        // Deliverytypes
        $aDelTypes = array();
        $oType = new stdClass();
        $oType->sType     = "a";      // amount
        $oType->sDesc    = $oLang->translateString( "amount", $iLang );
        $aDelTypes['a'] = $oType;
        $oType = new stdClass();
        $oType->sType     = "s";      // Size
        $oType->sDesc    = $oLang->translateString( "size", $iLang );
        $aDelTypes['s'] = $oType;
        $oType = new stdClass();
        $oType->sType     = "w";      // Weight
        $oType->sDesc    = $oLang->translateString( "weight", $iLang );
        $aDelTypes['w'] = $oType;
        $oType = new stdClass();
        $oType->sType     = "p";      // Price
        $oType->sDesc    = $oLang->translateString( "price", $iLang );
        $aDelTypes['p'] = $oType;
        $oType = new stdClass();
        $oType->sType     = "v";      // Volumengewicht
        $oType->sDesc    = $oLang->translateString( "dimweight", $iLang );
        $aDelTypes['v'] = $oType;
...
}

Die neue Bedingung sollte nun bereits im Backend zu sehen und wählbar sein. Damit sie aber auch abgespeichert werden kann, muss die Datenbanktabelle oxdelivery erweitert werden.

ALTER TABLE `oxdelivery` CHANGE `OXDELTYPE` `OXDELTYPE` ENUM( 'a', 's', 'w', 'p', 'v' )
CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT 'a' 
COMMENT 'Condition type: a - Amount, s - Size, w - Weight, p - Price, 
v - Volumengewicht'

Wir ermöglichen hier faktisch die Speicherung der Option v und fügen im Kommentarfeld die Erklärung für diese Option hinzu. Wichtig an der Stelle ist die Neugenerierung der Views.

Damit haben wir nun alles getan, um die Pflege im Backend zu ermöglichen. Der User kann nun Versandkostenregeln mit der Bedingung Volumengewicht erstellen und Start- und Endwerte setzen.

Versandkostenregel anwenden

Damit die neue Bedingung bei der Versandkostenberechnung während des Bestellprozesses auch berücksichtigt wird, muss sie noch an dieser Stelle ergänzt werden. Dazu wird die Datei oxdelivery.php aus dem Ordner application/modelsper Modul erweitert und zwar wieder mithilfe der metadata.php.

'extend'    =>    array( 
                          'delivery_main'    =>    'ks/ksdelivery/controllers/admin/ks_delivery_main',
                          'oxdelivery'       =>    'ks/ksdelivery/models/ksdelivery'
                      )

In der Datei ksdelivery.php wird die Methode getDeliveryAmount() überschrieben. Die switch-Anweisung wird um einen neuen Eintrag mit der Bedingung v für unser Volumengewicht ergänzt. Im Block wird nun der Algorithmus angewandt, den der Lieferdienst UPS für die Berechnung des Volumengewichtes vorgibt.

<?php

class ksDelivery extends ksDelivery_parent{
	
    public function getDeliveryAmount( $oBasketItem )
    {
        $dAmount  = 0;
        $oProduct = $oBasketItem->getArticle( false );
        $blExclNonMaterial = $this->getConfig()->getConfigParam( 'blExclNonMaterialFromDelivery' );
        // mark free shipping products
        if ( $oProduct->oxarticles__oxfreeshipping->value || ($oProduct->oxarticles__oxnonmaterial->value && $blExclNonMaterial) ) {
            if ($this->_blFreeShipping !== false) {
                $this->_blFreeShipping = true;
            }
        } else {
            $this->_blFreeShipping = false;
            switch ( $this->oxdelivery__oxdeltype->value ) {
                case 'p': // price
                    if ( $this->oxdelivery__oxfixed->value == 2 ) {
                        $dAmount += $oProduct->getPrice()->getPrice();
                    } else {
                        $dAmount += $oBasketItem->getPrice()->getPrice(); // price// currency conversion must allready be done in price class / $oCur->rate; // $oBasketItem->oPrice->getPrice() / $oCur->rate;
                    }
                    break;
                case 'w': // weight
                    if ( $this->oxdelivery__oxfixed->value == 2 ) {
                        $dAmount += $oProduct->oxarticles__oxweight->value;
                    } else {
                        $dAmount += $oBasketItem->getWeight();
                    }
                    break;
                case 's': // size
                    $dAmount += $oProduct->oxarticles__oxlength->value *
                                $oProduct->oxarticles__oxwidth->value *
                                $oProduct->oxarticles__oxheight->value;
                    if ( $this->oxdelivery__oxfixed->value < 2 ) {
                        $dAmount *= $oBasketItem->getAmount();
                    }
                    break;
                case 'a': // amount
                    $dAmount += $oBasketItem->getAmount();
                    break;
				case 'v': //Volumengewicht
					$dAmount += $oProduct->oxarticles__oxlength->value *
                                $oProduct->oxarticles__oxwidth->value *
                                $oProduct->oxarticles__oxheight->value / 5000;
                    if ( $this->oxdelivery__oxfixed->value < 2 ) {
                        $dAmount *= $oBasketItem->getAmount();
                    }
                    break;				
            }
...
	}
	
}

Das war’s. Die neue Bedingung wird nun berücksichtigt und bei der Berechnung der Versandkosten miteinbezogen anhand der Grenzwerte, die Ihr im Backend für das Volumengewicht eingetragen hat.

Während der Umsetzung dieses Moduls bin ich auf einen Software Bug gestoßen. Befindet sich ein Artikel unter mehreren Kategorien und sind diese Kategorien einer Versandkostenregel zugewiesen, dann wird der errechnete Wert pro Kategorie nochmal zusätzlich drauf addiert. Hat ein Artikel also ein Volumengewicht von 4 und befindet sich unter zwei Kategorien, dann liefert OXID 8 als Ergebnis.

Hinweis 1: Um aufzuzeigen, wie die Methoden erweitert wurden, habe ich hier nochmal die kompletten Methoden aufgeführt. In der Praxis würde man mithilfe des parent Aufrufs nur den Teil der Methode überladen, der notwendig ist. Der Rest würde wie gewohnt über die Original Methode laufen. Somit bleibt die Updatefähigkeit gewährleistet.

Hinweis 2: Über den Bug gibt es bereits ein Forum Thread, sowie einen Eintrag im Bugtracking Tool von OXID.

Benutzte Software:
OXID eShop Community Edition v4.8.7

Kostas Strigkos

Lassen Sie uns mal sprechen.

Sie schicken die Anfrage.
Ich kümmere mich um den Rest.