SO RICHTEN SIE DIE KUNDENBASIERTE PREISBERECHNUNG IN SHOPWARE EIN

SO RICHTEN SIE DIE KUNDENBASIERTE PREISBERECHNUNG IN SHOPWARE EIN

Einführung

Derzeit ist es in Shopware nicht möglich, kundenbasierte Preise oder Rabatte für Produkte über Tags/Kategorien bereitzustellen. In diesem Artikel besprechen wir, wie man einen kundenorientierten Preis angibt.

Um kundenbasierte Preisberechnungen durchzuführen, die mit den Standardoptionen von Shopware nicht erfüllt werden können, müssen wir den Service ProductPriceCalculator dekorieren . Es verfügt über eine „Berechnungs“-Methode, die Sie dekorieren und anpassen können. Sie sollten also über ein grundlegendes Verständnis der Servicedekoration in Shopware verfügen.

Wir werden einen Admin-Bereich erstellen, um Produkte und Kunden mit Preisen oder Rabatten zuzuordnen. Basierend auf dieser Zuordnung erfolgt die Preisberechnung im Frontend.

Aber bevor wir fortfahren, geht es in unserem Leitfaden um die Verwendung von Shopware 6.5. Wir gehen daher davon aus, dass Sie über mittlere Shopware-Kenntnisse verfügen. Wenn nicht, ist es keine so gute Idee, als ersten Schritt direkt in ein Framework einzusteigen. Wenn Sie also ein Neuling sind, empfehlen wir Ihnen, sich einige Grundkenntnisse anzueignen, bevor Sie hier fortfahren.

Schritt 1: Erstellen Sie einen Admin-Bereich für die Preiszuordnung

Erstellen Sie eine benutzerdefinierte Entität und einen Administrator-CRUD-Abschnitt, um die folgenden Details einzufügen.

  • Menge Bereich

Für unendliche Mengen können wir das Feld „Bis Menge“ auf Null setzen.

  • Textfeld zur Eingabe von Preis oder Rabatt (%)

Es muss entweder Preis oder Rabatt ausgewählt werden.

  • Produkt/Tag

Wählen Sie entweder ein Produkt oder ein Produkt-Tag aus . Sie können die Funktionalität auch erweitern, um eine Kategorieauswahl hinzuzufügen , um die Regel auf alle Produkte in dieser Kategorie anzuwenden.

  • Kunde

Wählen Sie einen Kunden aus , auf den die Regeln angewendet werden sollen. Sie können auch eine Kundengruppe hinzufügen , sodass alle Kunden innerhalb dieser Gruppe angewendet werden. Diese Felder können je nach Ihren Anforderungen geändert oder aktualisiert werden.

Schritt 2: Den Preisrechner dekorieren

In diesem Abschnitt haben wir die Methode „Service anpassen“ verwendet, um die Preisrechnerfunktion zu dekorieren. Wenn Sie sich dessen nicht bewusst sind, empfehlen wir Ihnen, sich einige Grundkenntnisse anzueignen, bevor Sie hier fortfahren.

Wir müssen den ProductPriceCalculator- Dekorator in der Datei „services.xml“ hinzufügen, wobei das Attribut „ decorates“ auf den Dienst verweist, den wir dekorieren möchten. Wir können auch unser benutzerdefiniertes Entitäts-Repository als Argument hinzufügen.

<service id="CustomerSpecificPrices\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator"                decorates="Shopware\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator">
           <argument type="service" id="CustomerSpecificPrices\Core\Content\Product\SalesChannel\Price\ProductPriceCalculator.inner"/>
           <argument type="service" id="Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator" />
           <argument id="custom_customer_price.repository" type="service"/>
</service><span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

In der ProductPriceCalculator- Klasse könnten wir Argumente im Konstrukt akzeptieren.

class ProductPriceCalculator extends AbstractProductPriceCalculator implements ResetInterface
{
   protected EventDispatcherInterface $eventDispatcher;
   private AbstractProductPriceCalculator $coreService;
   private QuantityPriceCalculator $quantityPriceCalculator;
   private EntityRepository $customerPricesRepository;


   public function __construct(
       AbstractProductPriceCalculator $coreService,
       QuantityPriceCalculator $quantityPriceCalculator,
       EntityRepository $customerPricesRepository
   ) {
       $this->coreService = $coreService;
       $this->quantityPriceCalculator = $quantityPriceCalculator;
       $this->customerPricesRepository = $customerPricesRepository;
   }<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Erstellen Sie die Berechnungsfunktion innerhalb der Decorator-Klasse neu und lösen Sie die Kernberechnungsfunktion aus Rufen Sie dann Kundeninformationen aus dem Vertriebskanalkontext ab.

Gehen Sie dann die Produkte durch und rufen Sie den berechneten Preis und den Listenpreis ab.

Rufen Sie außerdem kundenspezifische Preise von der benutzerdefinierten Entität ab.

public function calculate(iterable $products, SalesChannelContext $context): void
   {
       $this->coreService->calculate($products, $context);
       $customer = $context->getCustomer();
	foreach ($products as $product) {
		$originalCalculatedPrices =  $product->getCalculatedPrices();
		$originalListPrice = $originalCalculatedPrice->getListPrice();
		 /* Fetch custom price form entity */
		$customerPricesCollection = $this->fetchCustomerPrices($product, $customer);<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Von unserer benutzerdefinierten Entität können wir den Preis oder Rabatt basierend auf Produkt/Tag und Kunde abrufen. Hier können Sie es entsprechend Ihren Anforderungen anpassen.

   public function fetchCustomerPrices($productId, $customerId)
   {
       $customerPrice = $this->customerPricesRepository->search(
           (new Criteria())
               ->addFilter(
                   new EqualsFilter('productId', $productId),
                   new EqualsFilter('customerId', $customerId),
                   new EqualsFilter('active', true)
               )
               ->addSorting(new FieldSorting('fromQuantity', 'ASC')),
           Context::createDefaultContext()
       )->getEntities();


       return $customerPrice;
   }<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Wenn eine benutzerdefinierte Entität nur einen Preis für alle Mengen eines Produkts hat. Legen Sie den berechneten Preis und den günstigsten Preis fest und überspringen Sie den Rest des Teils.

if($customerPricesCollection->count() === 1 && $customerPricesCollection->first()->getFromQuantity() === 1 && $customerPricesCollection->first()->getToQuantity() === null)            
{
    $discountPrice = $customerPricesCollection->first();
    /* Apply custom price on all calculated prices */
    foreach ($originalCalculatedPrices as $price) {
         $this->setPriceOnCalculatedPrice($price, $discountPrice);
     }
      /* Apply custom price on cheapest price */
if($product->getCalculatedCheapestPrice()) {                  
          $this->setPriceOnCalculatedPrice($product->getCalculatedCheapestPrice(),  $discountPrice);
      }
      continue;
}<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Sie können benutzerdefinierte Preise entsprechend den Bedingungen in der benutzerdefinierten Entität festlegen und diese entsprechend der Funktionalität im Backend ändern.

 /* Set price */
protected function setPriceOnCalculatedPrice(CalculatedPrice $price, CustomerPriceEntity $discountPrice): void
   {
       $reducedUnitPrice = $this->calcCustomerPrice($discountPrice, $price->getUnitPrice());
       $totalPrice = $this->calcCustomerPrice($discountPrice, $price->getTotalPrice());
       $price->assign([
           'unitPrice' => $reducedUnitPrice,
           'totalPrice' => $totalPrice
       ]);
   }


  /*Find price according with backend conditions */	
   private function calcCustomerPrice(CustomerPriceEntity $customerPrice, float $originalPrice): float
   {
       if($customerPrice->getPrice() > 0) {
           return $customerPrice->getPrice();
       }
       if($customerPrice->getDiscount() !== null) {
           return $originalPrice * (1 - ($customerPrice->getDiscount() / 100));
       }
      
       return $originalPrice;
   }<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Wenn mehr als unterschiedliche Preise für unterschiedliche Mengen vorliegen, müssen wir jeden Mengenpreis durchlaufen und den Preis entsprechend festlegen.

$quantityCustomerPrice = $customerPricesCollection->first();
$cheapestPrice = null;
$taxRules = $context->buildTaxRules($product->getTaxId());
$prices = new PriceCollection();


/* Loop through price for different quantities and set price for each quantity */
foreach ($customerPricesCollection as $customerPrice) {
$curQuantity = $customerPrice['toQuantity'];
       $price = new QuantityPriceDefinition(   $this->calcCustomerPrice($customerPrice,  $originalCalculatedPrice->getUnitPrice()),$taxRules,$curQuantity);
   	$price->setIsCalculated(true);
$price->setReferencePriceDefinition($this->buildReferencePriceDefinition($product));


   	$prices->add($this->quantityPriceCalculator->calculate($price, $context));
   	/* To find cheapest price */
   	if($cheapestPrice === null || 
($price->getPrice() < $cheapestPrice->getPrice())) {
       	$cheapestPrice = $price;
   	}
}
/* Set product calculatedPrices with quantity */
$product->setCalculatedPrices($prices);


/* Set product calculatedPrice */
$quantityPrice = new QuantityPriceDefinition(   $this->calcCustomerPrice($quantityCustomerPrice,$originalCalculatedPrice->getUnitPrice()),$taxRules);


$quantityPrice->setIsCalculated(true);
$quantityPrice->setReferencePriceDefinition($this->buildReferencePriceDefinition($product));
if($originalListPrice !== null) {
   $quantityPrice->setListPrice($originalListPrice);
}
$product->setCalculatedPrice(
   $this->quantityPriceCalculator->calculate($quantityPrice, $context)
);
/* Set product calculatedPrice end */


/** Set product $calculatedCheapestPrice */
$calculatedCheapestPrice = CalculatedCheapestPrice::createFrom(
   $this->quantityPriceCalculator->calculate($cheapestPrice, $context)
);
$product->setCalculatedCheapestPrice($calculatedCheapestPrice);
/** Set product $calculatedCheapestPrice end*/<span id="mce_marker" data-mce-type="bookmark" data-mce-fragment="1">​</span>

Da wir hier individuelle Preise basierend auf dem Kunden erstellen, muss sich der Kunde immer im Shop anmelden, um diese Preisaktualisierung anzuzeigen.

Abschluss

Mit Shopware 6.5 können Sie jetzt kundenbasierte Preiskalkulationen umsetzen. Es ist super einfach! Befolgen Sie einfach diese Schritte und stellen Sie sicher, dass Sie den Code an Ihre Geschäftsanforderungen anpassen. Viel Spaß beim Codieren!

Leave a Reply

Your email address will not be published. Required fields are marked *