Wie übergibt Magento die Gruppenpreise im Backend?
Das war die Frage, die ich mir dazu initial gestellt habe. Was brauche ich also alles, um Gruppenpreise zu speichern? Ich wurde fündig in app/code/core/Mage/Adminhtml/controllers/Catalog/ProductController.php. Eine Debug-Ausgabe von $this->getRequest()->getPost() in der saveAction zeigt, dass die Gruppenpreise wie folgt übergeben werden:
["group_price"]=> array(2) {
[0]=> array(4) {
["website_id"]=> string(1) "0"
["cust_group"]=> string(1) "1"
["price"]=> string(5) "12.00"
["delete"]=> string(0) ""
}
[1]=> array(4) {
["website_id"]=> string(1) "0"
["cust_group"]=> string(1) "0"
["price"]=> string(5) "11.00"
["delete"]=> string(0) "" }
}
Notwendig sind also die Attribute website_id (Website), cust_group (Kundengruppe), price (Preis) und delete (Leerstring bzw. 1 im Falle des Löschens). Mein Aufruf über die SOAP API soll diesem Schema folgen.
Das Modul
Was ist zu tun? Ein eigenes Modul muss her. Meines heißt hier beispielsweise Avoe_Catalog.
Wir brauchen darin:
- etc/config.xml
- Model/Product/Api/V2.php
- Model/Product/Attribute/Groupprice/Api/V2.php
Avoe/Catalog/etc/config.xml
Wir überschreiben die Product API mit folgenden Zeilen:<global>
<models>
<avoecatalog>
<class>Avoe_Catalog_Model</class>
</avoecatalog>
<catalog>
<rewrite>
<product_api_v2>Avoe_Catalog_Model_Product_Api_V2</product_api_v2>
</rewrite>
</catalog>
</models>
</global>
Avoe/Catalog/Model/Product/Api/V2.php
Klassendefinitionclass Avoe_Catalog_Model_Product_Api_V2 extends Mage_Catalog_Model_Product_Api_V2 { ... }
In der Methode _prepareDataForSave habe ich, nach der Abfrage für die Staffelpreise (tier_price) folgende Abfrage ergänzt:
if (property_exists($productData, 'group_price')) {
$groupPrices = Mage::getModel('avoecatalog/product_attribute_groupprice_api_V2')
->prepareGroupPrices($product, $productData->group_price);
$product->setData("group_price", $groupPrices);
}
Avoe/Catalog/Model/Product/Attribute/Groupprice/Api/V2.php
Die Datei ist eine Kopie von Mage/Catalog/Model/Product/Attribute/Tierprice/Api/V2.phpclass Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2 extends Mage_Catalog_Model_Product_Attribute_Tierprice_Api
Den Umweg über die SOAPv2 API lasse ich hier weg, deshalb lautet meine Klassendefinition:
class Avoe_Catalog_Model_Product_Attribute_Groupprice_Api_V2 extends Mage_Catalog_Model_Api_Resource { ... }
Der Inhalt der Klasse ist, wie oberhalb erwähnt, eine Kopie von Mage_Catalog_Model_Product_Attribute_Tierprice_Api_V2 mit jenen Änderungen, dass ich $tierPrices gegen $groupPrices ersetzt habe sowie die Abfragen der if's entsprechend jenen der Gruppenpreis-Attribute (cust_group, pricem website_id) angepasst.
Aufruf an die SOAP-API
Der Demo-Aufruf lautet nun:$newProductData = new stdClass();
$additionalAttrs = array();
$gp = array(
"0" => array (
"website_id" => "0",
"cust_group" => "1",
"price" => "11.11",
"delete" => "1"
),
"1" => array (
"website_id" => "0",
"cust_group" => "0",
"price" => "12.12"
)
);
$gp = array("key" => "group_price", "value" => array(serialize($gp[0]),serialize($gp[1])));
$additionalAttrs['multi_data'][] = $gp;
$newProductData->additional_attributes = $additionalAttrs;
$result = $client->catalogProductUpdate($sessionId,$prodSku,$newProductData,"","sku");
Zugegeben, der Teil mit dem Aufruf von array(serialize($gp[0]),serialize($gp[1]))); als Value ist nicht besonders schön. Allerdings funktioniert das Auslesen der Werte auf dem Server sonst nicht mehr.
Warum?
Sehen wir uns dazu Teile der WSDL genauer an:<complexType name="associativeMultiArray">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="typens:associativeMultiEntity[]"/>
</restriction>
</complexContent>
</complexType>
<complexType name="associativeMultiEntity">
<all>
<element name="key" type="xsd:string"/>
<element name="value" type="typens:ArrayOfString"/>
</all>
</complexType>
<complexType name="ArrayOfString">
<complexContent>
<restriction base="soapenc:Array">
<attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</restriction>
</complexContent>
</complexType>
Der Aufruf erfolgt über multi_data (typ: associativeMultiArray lt. WSDL), also über ein Array von Attributen, welches wiederum mehrere Werte enthalten kann. Nicht zuletzt ergibt sich (wenn man den Typdefinitionen in der WSDL folgt) aufgrund der Definition von