Artikel Preis anhand eines Codes festlegen

Guten Tag liebe Community,

nachdem ich nun durch einige Plugins und Themes durcharbeitet habe und ich aus dem Java-Bereich komme und quasi keine Ahnung habe wo ich beginnen soll, habe ich eine wahrscheinlich super einfache Frage.

Ich möchte bei einigen Produkten keinen Preis öffentlich zeigen und diesen ausschließlich mit der Eingabe eines Codes bestimmen. 

Das bedeutet, dass der Kunde bei dem entsprechenden Produkt einen Code eingeben muss und dieser dann - sofern gültig - mit einem Preis gebunden anhand des Codes in den Warenkorb gelegt wird.

Was habe ich bereits versucht?

Zuerst habe ich ein CheckBox Feld angelegt unter Attribute 4. Sofern das Attribute 4 angeklickt ist, überprüfe ich im Template folgendermaßen:

{block name='frontend_detail_buy_button'}
    {if $sArticle.attr4} 
        
        
            {s name="DetailBuyActionAdd"}{/s} 
        
    {else} {$smarty.block.parent} {/if}
{/block}

Somit habe ich zumindest schonmal einen Anfang, dass das Code Feld angezeigt wird, sofern das Attribute für das Item gesetzt wurde.

Nun müsste ich jedoch auch noch irgendwo einen Preis bestimmen. Das heißt, irgendwo müsste ich irgendwie auch noch Felder bestimmen, dass zu dem jeweiligen Code einen Preis angibt. 

Daraufhin habe ich die Gutscheine angeguckt. Hierbei ist es aber nicht möglich zu bestimmen, dass ein Gutschein den Preis festsetzt, sondern ausschließlich, dass hierbei der Wert vom Produktpreis abgezogen wird.  

Umgekehrt wäre es zwar möglich dem Produkt einen super teuren Preis anzugeben, diesen unkenntlich zu machen und ausschlißelich mit der Eingabe des Codes abzuziehen, jedoch ist das sicher nicht der richtige Weg.

Daraufhin habe ich nun ein Plugin erstellt, welches bei dem Event Enlight_Controller_Action_PostDispatchSecure_Frontend folgende Funktion auruft:

 public function onFrontendPostDispatch(Enlight_Event_EventArgs $args)
    {
        /** @var \Enlight_Controller_Action $controller */
        $controller = $args->get('subject');
        $view = $controller->View();

        $view->addTemplateDir( __DIR__. '/Views');
     
        $sArticle = $view->getAssign('sArticle');
        $sArticle['price'] = 200; // dummy testing

        $view->assign('sArticle', $sArticle);


    }

 

Der Preis wird zwar nun im Template geändert, jedoch ist das nur für das Template und wird nicht übernommen beim reinlegen in den Warenkorb.

Nachdem ich nun mit diversen Listenern gespielt habe, mit notifyUntil uvm. jedoch auf keinen geraden Pfad komme dies zu realisieren, würde ich gerne anfragen was denn die richtige Lösung wäre.

Das Ziel ist es einige Produkte ausschließlich anhand eines Codes zu erwerben, wobei der Code sozusagen eine Produkt-Variante darstellt gebunden auf einen Preis.

 

Vielen Dank für eure Mühe schonmal und das lesen des langen Textes. Und verzeiht mir dass ich gerade keinerlei Durchblick habe, jedoch ist mir die komplette Materie neu.  Foot-in-Mouth

 

Edit:

Angenommen ich baue in der Artikel Detailübersicht eine Input-Feld wie oben, daneben einen Button welcher ein Ajax-Call an einen Knotenpunkt sendet, welcher den Code beinhaltet und anhand einer aufbereiteten Datenquelle den Preis zurück sendet, dann ist dies ja Client-Seitig, bzw. müsste dann im Ajax-Skript im selben Session-Pool liegen damit auf $sArtikel zugegriffen werden kann (globale variable?). Sonst gäbe es ja die Möglich auf XSS was ungünstig wäre. Außerdem wäre die Verwaltung viel schöner direkt im Artikel selbst im Backend. 

Problem sehe ich jedoch wenn ich einen Hook anlege, welche beim drücken des “Artikel in Warenkorb” legen Knopfes ausgeführt wird mit den Daten des Input-Text Feldes, dann müsste die Überprüfung im hook geschehen und bei einem falschen Code die vorherige Seite wieder aufgerufen werden, anhand eines weiterne Hooks der dann im Template eine Variable setzt, dass ein Fehler unterlaufen ist.

Ist es überhaupt möglich Ajax Hooks zu erstellen? Gibt es diese Lösung vielleicht schon implementiert und ich habe sie nur nicht gefunden? 

Eine weitere Möglichkeit wäre die Preise für eine Kundengruppe bereit zu stellen. Anhand eines Vouchers oder Codes, welches der User irgendwo eingibt diesen dann in die Gruppe zu schieben, welche dann einen festgelegten Preis für den Artikel hat. Leider wäre das dann die alternative schlechteste Lösung, da dies dann nicht mehr Artikel spezifisch, sondern Gruppenspezifisch ist.

Zusatz 2:

Eine weitere Möglichkeit die mir eingefallen ist, ist das nutzen der REST-Api. Hierbei kann eine Überprüfung des Code-Feldes stattfinden, welche dann mit einer Ajax-Anfrage an einen Knotenpunkt den Code sendet. Dieser Knotenpunkt hat Zugriff auf $sArtikel und erstellt mithilfe der REST-Api ->ORDER den Artikel im Warenkorb mit dem bestimmten Preis welcher irgendwo hinterlegt sein muss

Nachteil: Der Benutzer benötigt eine feste UserID, da sonst kein Order per REST-Api erstellt werden kann.

 

Anbei mein erster Versuch diesen Prozess zu automatisieren. Leider finde ich dies mehr schlecht als recht.

Ich habe hierfür im Theme frontend/detail/buy.tpl überschrieben mit

 

{extends file="parent:frontend/detail/buy.tpl"}
{block name='frontend_detail_buy'}
    {if $sArticle.attr4} 
        
            

            
                

                
                    Code einlösen
                    
                
            
        
    {else}
        {$smarty.block.parent}
    {/if}
{/block}

 

Nun überprüfe ich ob der Artikel das Attribute attr4 (checkbox) aktiviert hat. Wenn ja, wird dann eben das Input-Feld angezeigt, welches zu meinem Controller leitet.

Ich habe zudem zu jedem Artikel Varianten angelegt mit diversen Preisen, welche ich im Template ausblende, sofern attr4 gesetzt ist. 

 

Der Controller selbst:

 

class Shopware_Controllers_Frontend_ComdevController extends Enlight_Controller_Action {

    protected $resource = null;

    public function init() {
        $this->resource = \Shopware\Components\Api\Manager::getResource('article');
    }

    public function codeAction() {
        Shopware()->Plugins()->Controller()->ViewRenderer()->setNoRender();

        $articleId = $this->Request()->getPost('articleId');
        $articleCode = $this->Request()->get("pCode");

        $sArticle = Shopware()->Modules()->Articles()->sGetArticleById($articleId);

        $articleData = $this->resource->getOne($articleId, [
            'language' => $this->Request()->getParam('language'),
            'considerTaxInput' => $this->Request()->getParam('considerTaxInput'),
        ]);

        $dataNumbers = array();

        $dataNumbers[] = $articleData["mainDetail"]["number"];

        foreach ($articleData["details"] as $data) {
            $dataNumbers[] = $data["number"];
        }


        if (in_array($articleCode, $dataNumbers)) {
            Shopware()->Session()->cGroup = "custom_1";
            Shopware()->Modules()->Basket()->sAddArticle($articleCode);
            Shopware()->Modules()->Basket()->sRefreshBasket();
        } else {
            Shopware()->Session()->cGroup = null;
        }

        $this->redirect(strtok($sArticle["linkDetailsRewrited"], "?"), array('code' => 301));

        return true;
    }

  
}

Hierbei überprüfe ich den code, welcher die Artikel ID ist, hole mir dann die Ids aller Varianten und sofern korrekt, lege ich es im Basket an und leite zurück auf die vorherrige Seite.

Es funktioniert, jedoch ist diese Lösung mehr schlecht als recht. Außerdem habe ich keine Überprüfung ob der Artikel nun tatsächlich angelegt wurde oder nicht. 

Gibt es bessere Möglichkeiten das zu realisieren, oder bin ich bereits auf dem richtigen Weg?

Vielen Dank!