Dynamische Preisanpassung bei Auswahllisten

Hallo liebe User,

als kleines Ostergeschenk (etwas verspätet, aber lieber spät als nie ), wollen wir euch einen kleinen Hack vorstellen. Dieser ermöglicht es, auf der Detail-Seite eines Produkts, den Preis dynamisch anzupassen, wenn der Kunde in einer Auswahlliste (mit Aufpreis)auswählt.

Folgender Code-Snipe müsst ihr in die details.tpl einfügen:

<script type="text/javascript">
  /*Array zum speichern des Preises sowie der Auf-/Abschläge*/
  var prices=new Array();
  /*Index 0 ist immer der Basispreis*/
  prices[0] = [{$product->oxarticles__oxprice}];

  /*Hilfsfunktion um das Ergebnis zu trimmen*/
  function trim(str){
     if (str){
str=str.replace(/^s*|s*$/g,"");
     }
     return str;
  }
  
  /*Funktion zum Runden und formatieren des Ergebnisses
    je nach Einstellung von OXID*/
  function formatCurrency(num){
     var thousand="[{$currency->thousand}]";
     var dezimals="[{$currency->dec}]";
     var sign="[{$currency->sign}]";
     var decimal=Math.pow(10,[{$currency->decimal}]);
     num = num.toString();
     if (isNaN(num)){
num="0";
     }
     numsign=(num==(num=Math.abs(num)));
     num = Math.floor(num*decimal+0.5000000000);
     cents = num%decimal;
     num = Math.floor(num/decimal).toString();
     if (cents<10){
cents = "0" + cents;
     }
     for (i=0;i<Math.round((num.length-(1+i))/3);i++){
j=num.length-(4*i+3);
        num=num.substring(0,j)+thousand+num.substring(j);
     }
     if (cents=="00"){
cents="-";
     }
     return trim((((numsign)?"":"-") + num + dezimals + cents))+" "+sign;
   }

   /* Berechnet den Preis und aktualisiert das Anzeigefeld*/
   function CalculateAndUpdate(){
        var price_field = document.getElementById("test_product_price");
var m = prices.length;
var cur_price=0;
for (i=0;i <= m;i++){
      if (prices[i]){
cur_price += prices[i];
   }
 }
 price_field.innerHTML=formatCurrency(cur_price);
   }

   /*Event-Handler für onChange bei der betreffenden Auswahlliste*/
   function change_price(selectobj){
   var opti_field=selectobj.selectedIndex;
var idx=selectobj.options[opti_field].getAttribute("rev");
var opti=selectobj.options[opti_field].getAttribute("rel");
if (idx >=0){
   idx++; 
   if (opti){
         prices[idx] = parseFloat(opti.replace(/,/g,"."));
   }else{
      prices[idx] = 0.0;
   }
 }
CalculateAndUpdate();
    }
</script>

Dieser Teil macht im Prinzip die ganze Arbeit. Er berechnet den neuen Preis, aktuallisiert das Feld usw.

Folgend der Teil, der abgeändert wurde, um das ganze zum laufen zu bekommen.



   [{foreach key=iSel from=$oView->getSelectLists() item=oList}]
   <div class="variants">
      <label>[{ $oList.name }]:</label>
      <select id="test_select_[{$product->oxarticles__oxid->value}]_[{$iSel}]"  
      name="sel[[{$iSel}]]" onchange="change_price(this);">
      [{foreach key=iSelIdx from=$oList item=oSelItem}]
  [{ if $oSelItem->name }]<option value="[{$iSelIdx}]"
         rel="[{$oSelItem->fprice}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>  
         [{/if}]
      [{/foreach}]
      </select>
    </div>
   [{/foreach}]


Wie ihr seht, wird für jeden Listeneintrag der Auf-/Abpreis in das Attribut rel geschrieben, sowie der Index der Liste (nicht der Index des Elements !!!), in das rev-Attribut geschrieben. Dazu noch das onChange im Select, und schon funktioniert
das ganze.

HINWEIS:

Das ganze wurde für Absolute Beträge entwickelt. Eine Anpassung für prozentuale Auf-/Abschläge sollte nicht schwierig sein.

Viel Spaß damit

euer Aggrosoft-Team

ich habe grade dieses script mit 4.3 versucht und es funktioniert nicht richtig … der preis springt zwar um, die Kalkulation funktioniert aber nicht da immer der betrag 1.500 ausgegeben wird. Die details seite lädt mit dem korrekten preis aber sobald man eine selection list auswählt springt der betrag auf 1500.

gibt es da einen update oder andere möglichkeit ?

Kannst du mal genauer sagen welchen Preis du wie beaufschlagen willst ?

ich habe folgende Produktlinie

Produkt -> 3 varianten -> 4 Optionen

Ich habe also Produkt A angelegt welches drei Varianten hat: billig, normal und teuer.

Dann habe ich mehrere Auswahllisten angelegt:

Domain Names, Websites, Email adresses, ip adresses

Bei den Auswahllisten (Domain names zB) soll dann ein .com der ‘default’ sein und im Variantenpreis eingeschlossen sein. Alle anderen domains sind dann teurer zB so angelegt:

1 - .com
2 - .ch, 30
3 - .tv, 50
4 - .dj, 150

habe also insgesamt bei einer Produktvariante 4 Auswahllisten mit jeweils 4 optionen. Wenn bei allen Auswahllisten die erste option (ohne Aufschlag) ausgewählt ist sollte der Grundpreis der Variante erscheinen … ich bekomme aber immer falsche Beträge.

ich habe das Gefühl das hängt irgendwie mit der Währungsumrechnung zusammen … bin aber noch am suchen …

ok, also das problem ist das die Währung immer automatisch auf den betrag in der STandardwährung springt.

Ich habe also in einem Produkt 3 Varianten angelegt, Preis 500, 1000 und 1500, Meine standardwährung ist CHF:

USD@ 0.92@ .@ @ $@ 0
EUR@ 0.69@ ,@ .@ €@ 0
GBP@ 0.61@ .@ @ £@ 0
CHF@ 1.00@ ,@ .@ CHF@ 0

Die Preise in den anderen Währungen sind Korrekt umgerechnet bis ich eine Auswahlliste benutze, dann springt es immer auf die 500, 1000, 1500 um und rechnet von da.

Ein weiteres problem ist das wohl nur 3stellige beträge angenommen werden, bei vierstelligen beträgen in der Auswahlliste werden nur die ersten drei stellen angerechnet.

Und in der Detailseite werden die preise jetzt netto angezeigt, überall anderswo sind si incl MWST

[QUOTE=aggrosoft;28999]Hallo liebe User,

als kleines Ostergeschenk (etwas verspätet, aber lieber spät als nie ), wollen wir euch einen kleinen Hack vorstellen. Dieser ermöglicht es, auf der Detail-Seite eines Produkts, den Preis dynamisch anzupassen, wenn der Kunde in einer Auswahlliste (mit Aufpreis)auswählt.

Folgender Code-Snipe müsst ihr in die details.tpl einfügen:

<script type="text/javascript">
  /*Array zum speichern des Preises sowie der Auf-/Abschläge*/
  var prices=new Array();
  /*Index 0 ist immer der Basispreis*/
  prices[0] = [{$product->oxarticles__oxprice}];

  /*Hilfsfunktion um das Ergebnis zu trimmen*/
  function trim(str){
     if (str){
str=str.replace(/^s*|s*$/g,"");
     }
     return str;
  }
  
  /*Funktion zum Runden und formatieren des Ergebnisses
    je nach Einstellung von OXID*/
  function formatCurrency(num){
     var thousand="[{$currency->thousand}]";
     var dezimals="[{$currency->dec}]";
     var sign="[{$currency->sign}]";
     var decimal=Math.pow(10,[{$currency->decimal}]);
     num = num.toString();
     if (isNaN(num)){
num="0";
     }
     numsign=(num==(num=Math.abs(num)));
     num = Math.floor(num*decimal+0.5000000000);
     cents = num%decimal;
     num = Math.floor(num/decimal).toString();
     if (cents<10){
cents = "0" + cents;
     }
     for (i=0;i<Math.round((num.length-(1+i))/3);i++){
j=num.length-(4*i+3);
        num=num.substring(0,j)+thousand+num.substring(j);
     }
     if (cents=="00"){
cents="-";
     }
     return trim((((numsign)?"":"-") + num + dezimals + cents))+" "+sign;
   }

   /* Berechnet den Preis und aktualisiert das Anzeigefeld*/
   function CalculateAndUpdate(){
        var price_field = document.getElementById("test_product_price");
var m = prices.length;
var cur_price=0;
for (i=0;i <= m;i++){
      if (prices[i]){
cur_price += prices[i];
   }
 }
 price_field.innerHTML=formatCurrency(cur_price);
   }

   /*Event-Handler für onChange bei der betreffenden Auswahlliste*/
   function change_price(selectobj){
   var opti_field=selectobj.selectedIndex;
var idx=selectobj.options[opti_field].getAttribute("rev");
var opti=selectobj.options[opti_field].getAttribute("rel");
if (idx >=0){
   idx++; 
   if (opti){
         prices[idx] = parseFloat(opti.replace(/,/g,"."));
   }else{
      prices[idx] = 0.0;
   }
 }
CalculateAndUpdate();
    }
</script>

Dieser Teil macht im Prinzip die ganze Arbeit. Er berechnet den neuen Preis, aktuallisiert das Feld usw.

Folgend der Teil, der abgeändert wurde, um das ganze zum laufen zu bekommen.



   [{foreach key=iSel from=$oView->getSelectLists() item=oList}]
   <div class="variants">
      <label>[{ $oList.name }]:</label>
      <select id="test_select_[{$product->oxarticles__oxid->value}]_[{$iSel}]"  
      name="sel[[{$iSel}]]" onchange="change_price(this);">
      [{foreach key=iSelIdx from=$oList item=oSelItem}]
  [{ if $oSelItem->name }]<option value="[{$iSelIdx}]"
         rel="[{$oSelItem->fprice}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>  
         [{/if}]
      [{/foreach}]
      </select>
    </div>
   [{/foreach}]


Wie ihr seht, wird für jeden Listeneintrag der Auf-/Abpreis in das Attribut rel geschrieben, sowie der Index der Liste (nicht der Index des Elements !!!), in das rev-Attribut geschrieben. Dazu noch das onChange im Select, und schon funktioniert
das ganze.

HINWEIS:

Das ganze wurde für Absolute Beträge entwickelt. Eine Anpassung für prozentuale Auf-/Abschläge sollte nicht schwierig sein.

Viel Spaß damit

euer Aggrosoft-Team[/QUOTE]
Wenn Du Dich schon an meinem Code bedienst (formatCurrency und trim) solltest Du das, der guten Ordnung halber, wenigstens vermerken.

Hi,

@avenger

Dein Code ??? Glaub ich nicht !!!

mfg
Stefan

Fix für Produktpreis (Mwst) und richtigen Auf/Abschlag:

Insert:

Über dem bisherigen Script-Code folgendes einbauen:

	&lt;script type="text/javascript"&gt;
		function toFloat(aString){
			var dezimals="[{$currency-&gt;dec}]";
			aString=aString.replace(/\[{$currency-&gt;thousand}]/g,"");
			if (dezimals != '.'){
				aString=aString.replace(/\[{$currency-&gt;dec}]/g,".");
			}
			return parseFloat(aString);
		}		
	&lt;/script&gt;

Im alten Script-Code folgendes Ändern:

aus: prices[0] = [{$product->oxarticles__oxprice}];
wird: prices[0]=toFloat("[{$product->getFPrice()}]");

schlussendlich noch aus:

[{ if $oSelItem->name }]<option value="[{$iSelIdx}]“
rel=”[{$oSelItem->fprice}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>
[{/if}]

das machen:
[{ if $oSelItem->name }]<option value="[{$iSelIdx}]“
rel=”[{$oSelItem->price}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>
[{/if}]

Nun sollte das ganze funktionieren

Gruß

Aggrosoft-Team

[QUOTE=Uwe rupprecht;29112]Fix für Produktpreis (Mwst) und richtigen Auf/Abschlag:

schlussendlich noch aus:

[{ if $oSelItem->name }]<option value="[{$iSelIdx}]“
rel=”[{$oSelItem->fprice}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>
[{/if}]

das machen:
[{ if $oSelItem->name }]<option value="[{$iSelIdx}]“
rel=”[{$oSelItem->price}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>
[{/if}]
[/QUOTE]

Hey, vielen Dank für die Hilfe :slight_smile:

also es funktioniert nur nur in der Ursprungswährung aber die Preise werden immer noch netto angezeigt,

in den anderen Währungen gibt es diverse probleme:

http://melodybar.ch/currencybug.mp4

lol spaßig

uwe fixt das am montag :wink:

mfg
stefan

cool, danke … ist das nur noch niemandem aufgefallen oder bin ich der einzige der dieses skript benutzt :confused:

das script is 2 tage alt bist halt ne art beta tester dafür isses umsonst :wink:

mfg
stefan

ah ok :smiley: hatte mich verlesen … dachte es wär von letztem jahr ostern …

So…zwei Probleme hab ich gefunden und behoben.

Zum einen wird bei den Auswahllisten nur der formatierte Preis auf die neue Währung
umgerechnet. Zum anderen hatte ich nicht berücksichtigt, das es auch Währungen ohne Tausender-Trennung gibt (z.B. Pfund oder US-Dollar).

Beide Probleme sind nun behoben. Hier der Code dazu:



		<script type="text/javascript">
					function toFloat(aString){
						var dezimals="[{$currency->dec}]";
						[{if $currency->thousand != ""}]
							aString=aString.replace(/\[{$currency->thousand}]/g,"");
						[{/if}]
						if ((dezimals != '.') && (dezimals !="")){
								aString=aString.replace(/\[{$currency->dec}]/g,".");
						}
						return parseFloat(aString);
					}
		</script>		
		<script type="text/javascript">
				/*Array zum speichern des Preises sowie der Auf-/Abschläge*/
				var prices=new Array();
				/*Index 0 ist immer der Basispreis*/
				prices[0]=toFloat("[{$product->getFPrice()}]");

				/*Hilfsfunktion um das Ergebnis zu trimmen*/
				function trim(str){
					if (str){
						str=str.replace(/^s*|s*$/g,"");
				}
				return str;
				}
  
				/*Funktion zum Runden und formatieren des Ergebnisses	je nach Einstellung von OXID*/
			function formatCurrency(num){
				var thousand="[{$currency->thousand}]";
				var dezimals="[{$currency->dec}]";
				var sign="[{$currency->sign}]";
				var decimal=Math.pow(10,[{$currency->decimal}]);
				num = num.toString();
				if (isNaN(num)){
					num="0";
				}
				numsign=(num==(num=Math.abs(num)));
				num = Math.floor(num*decimal+0.5000000000);
				cents = num%decimal;
				num = Math.floor(num/decimal).toString();
				if (cents<10){
					cents = "0" + cents;
				}
				if (num.length > 3){
					count=num.length%3;
					for (i=0;i<count;i++){
						p = num.length-((i*3)+3);
						num=num.substr(0,p)+thousand+num.substring(p);
					}
				}
				if (cents=="00"){
					cents="-";
				}
				return trim((((numsign)?"":"-") + num + dezimals + cents))+" "+sign;
			}

			/* Berechnet den Preis und aktualisiert das Anzeigefeld*/
			function CalculateAndUpdate(){
				var price_field = document.getElementById("test_product_price");
				var m = prices.length;
				var cur_price=0;
				for (i=0;i <= m;i++){
					if (prices[i]){
						cur_price += prices[i];
					}
				}
				price_field.innerHTML=formatCurrency(cur_price);
			}

			/*Event-Handler für onChange bei der betreffenden Auswahlliste*/
			function change_price(selectobj){
				var opti_field=selectobj.selectedIndex;
				var idx=selectobj.options[opti_field].getAttribute("rev");
				var opti=selectobj.options[opti_field].getAttribute("rel");
				if (idx >=0){
					idx++; 
					if (opti){
						prices[idx] = toFloat(opti);
					}else{
						prices[idx] = 0.0;
					}
				}
				CalculateAndUpdate();
			}
		</script>  

sowie der HTML-Teil:


		[{foreach key=iSel from=$oView->getSelectLists() item=oList}]
		<div class="variants">
      <label>[{ $oList.name }]:</label>
      <select id="test_select_[{$product->oxarticles__oxid->value}]_[{$iSel}]" name="sel[[{$iSel}]]" onchange="change_price(this);">
      [{foreach key=iSelIdx from=$oList item=oSelItem}]
			[{ if $oSelItem->name }]
					<option value="[{$iSelIdx}]" rel="[{$oSelItem->fprice}]" rev="[{"$iSel"}]">[{ $oSelItem->name }]</option>
			[{/if}]
      [{/foreach}]
      </select>
    </div>
   [{/foreach}]  

Ein Problem mit der Mwst konnte ich so jetzt nicht feststellen, da die Preise auf der Detail-Seite entweder Brutto oder Netto sind (nicht aber gemischt). Vielleicht hab ich aber auch nur andere Mwst-Einstellungen. Bitte einfach mal ausprobieren.

Hey Uwe, vielen Dank ! Es funktioniert jetzt, die rechnungen sind korrekt. Ich habe immer noch das Problem das die Produkte auf der detail seite in netto angezeigt werden, ich bin am suchen habe aber noch keine Einstellung gefunden.

Aber wenigstens funktioniert die Preiskalkulation schon mal :slight_smile:

Wäre auch cool wenn dieses skript im checkout laufen würde, den ‘Update’ button finde ich ‘so last millenium’ :smiley: … Versuch mich mal selber dran

du must einfach das formular der combobox dazu bewegen eien refresh zu machen im warenkorb.

mfg
stefan

[QUOTE=chris1249;29468]Hey Uwe, vielen Dank ! Es funktioniert jetzt, die rechnungen sind korrekt. Ich habe immer noch das Problem das die Produkte auf der detail seite in netto angezeigt werden, ich bin am suchen habe aber noch keine Einstellung gefunden.

Aber wenigstens funktioniert die Preiskalkulation schon mal :slight_smile:

Wäre auch cool wenn dieses skript im checkout laufen würde, den ‘Update’ button finde ich ‘so last millenium’ :smiley: … Versuch mich mal selber dran[/QUOTE]

Hi ich hab ne Zeit lang nicht mehr an meinem Oxid Shop gearbeitet und muss mich erst wieder reinfinden. Also ich habe das Script in die Details TPL kopiert und den anderen Teil ersetzt. Nun zeigt er einen Syntaxfehler an:

und zwar in der Zeile:

[{if $currency->thousand != “”}]

Damit wird die ganze Details Seite nicht mehr geladen.

Wo liegt mein Fehler?

Dank euch.

mfg

Hast du evtl. vorher am ende der Zeile das Semikolon vegessen ? :slight_smile:

Hallo Uwe,

wohl eher nicht, da ich das Script hier heraus direkt in den Editor kopiert habe.

Es ist ja schon richtig, dass ich sowohl script als auch html Bereich in die Details.tpl kopiert habe oder?