assets/s2diorder.php /// Art: Shop Business Logic /// Inhalt: Klasse order /// Beschreibung: Business Logic rund um die Bestellung /// Benötigt: config.php, db.php /// CCML-Parsing: nein /// ////////////////////////////////////////////////////////////////////////////////////////// /// /// Letzte Änderungen: /// 02.03.2009 br Tag in Lizenzemails ergänzt /// 20.03.2009 Gutschein bis einen Tag verlängert /// 24.03.2009 Erweiterung Bestandsverwaltung /// 24.03.2009 Rundung Gesamtpreis /// 26.03.2009 Tracking URL absolut /// 27.03.2009 Sript Tags für Textmail /// shop to date 7 /// 02.09.2009 Moneybookers hinzugefügt /// 07.12.2009 Warenkorbsperre bei Minderbestand hinzugefügt /// 11.12.2009 Rabattsperre hinzugefügt /// 14.12.2009 Rabattcoupons /// 23.01.2010 Rechnungsnummern hinzugefügt /// 22.02.2010 PDF Erstellungvariablen hinzugefügt /// 10.03.2010 Bestelloptionen /// 27.03.2010 PDF Versand und Erstellung /// 14.07.2010 Verbesserung unserialize wegen Warning /// 31.07.2010 Rabattierbare Bestelloptionen /// 31.07.2010 Bug mit Summenrabatten behoben /// 31.07.2010 Status auch in Bestellbestätigung /// 01.08.2010 Status-Email nicht für Bestellung eingegangen /// 05.08.2010 CRLF für Text Mails /// 13.08.2010 expected_date formatieren /// 13.09.2010 pdf email auch bei status neu /// 28.09.2010 Kauf bei Minderbestand verhindern nur nich bei kein Bestand /// 04.10.2010 Kauf bei Minderbestand verbessert /// 11.10.2010 Kauf bei Minderbestand nochmals verändert /// 25.10.2010 Gutscheincode mehr Zeichen /// 25.10.2010 Kauf bei Minderbestand nochmals verändert /// 23.11.2010 Deprecated array_push /// ////////////////////////////////////////////////////////////////////////////////////////// ///<23.11.2010/7.0.2.7> if (!defined('SHOP_TO_DATE')) die('Forbidden'); // Klasse Bestellung class order extends db { // Eigenschaften (in der DB) var $order_id = '0'; // Bestellnummer bzw. vor Abschluss der Bestellung session_id var $order_id_prefix = null; // Präfix Bestellnummer var $order_date = ''; // Bestelldatum (wichtig nur nach der Bestellung) var $order_time = ''; // Bestellzeit (wichtig nur nach der Bestellung) var $bill_id = null; // Eindeutige, fortlaufende Rechnungsnummer (wichtig nur nach der Bestellung) var $bill_id_prefix = null; // Präfix Rechnungsnummer var $bill_date = null; var $b2b = 0; var $pdf_creation = 0; // PDF Generierung: 0 = aus/manuell, 1 = Bei Bestelleingang, 2 = Bei Versand der Ware var $currency = ''; // Achtung muss null sein für Ersterkennung, nicht ändern! var $sumrebate_amount = null; // Summenrabatte var $sumrebate_absolute = 0; var $couponrebate_amount = 0; // Gutscheinrabatte var $couponrebate_absolute = 0; var $coupon_id = null; // Gutschein var $coupon_caption = null; // Bezeichnung Gutscheinart var $shipping_cost = 0; var $shipping_vat = 0; var $shipping_caption = ''; var $shipping_trackingurl = null; var $payment_amount = 0; var $payment_absolute = 0; var $payment_vat = 0 ; var $payment_caption = ''; var $payment_param = null; var $paymentrebate_amount = 0; // Zahlweisenrabatte var $paymentrebate_absolute = 0; var $status = CC_RESSOURCE_ORDERSTATUSSHORT_NEW; // Status der Bestellung var $shipping_date = null; var $payment_date = null; var $expected_date = null; var $message = null; var $tracking_id = null; var $affiliate_id = null; var $affiliate_subid = null; var $search_email; var $search_name; // Variablen var $client = null; var $items = array(); var $vatarray; // Alle Steuergruppen mit gerundeten Werten zum weiterrechnen var $sm = null; // Versandmethode var $pm = null; // Bezahlmethode var $coupon = null; var $coupondef = null; var $change_id; // Konstruktor Initialisierung zugehörige Datenbank function order($order_id = null, $client = null, $is_session = false) { global $shipping, $payment; $this->db(TABLE_ORDERS); if (!$order_id) return; $this->order_id = $order_id; // Bestellung laden nur bei tatsächlicher Bestellung, nicht für Sessions! if (!$is_session) { $this->db_selectobject(array('order_id' => $order_id)); } // Vor Abschluss der Bestellung if (!$this->order_date && $client) { $this->b2b = CC_SITE_B2B; $this->currency = CC_SITE_CURRENCY; // Kunde einfügen $this->client = $client; // Coupons in Eigenschaft übertragen $this->coupon = new coupon($this->client->coupon_id); if ($this->coupon->coupon_id) { $this->coupondef = new coupondef($this->coupon->coupondef_id); if (!$this->coupondef->item_uid) { $this->couponrebate_absolute = $this->coupondef->rebate_absolute; $this->couponrebate_amount = $this->coupondef->rebate_amount; } else { $this->couponrebate_absolute = 0; $this->couponrebate_amount = 0; } $this->coupon_id = $this->coupon->coupon_id; $this->coupon_caption = $this->coupondef->caption; } else $this->coupon = null; // Nach Abschluss der Bestellung } else if ($this->order_date) { // Versand und Bezahlung $this->sm = new shipping_method(); $this->sm->caption = $this->shipping_caption; $this->sm->trackingurl = $this->shipping_trackingurl; $this->sm->vat = $this->shipping_vat; $this->sm->total = $this->shipping_cost; $this->pm = new payment_method(); $this->pm->actualprice = null; $this->pm->caption = $this->payment_caption; $this->pm->amount = $this->payment_amount; $this->pm->absolute = $this->payment_absolute; $this->pm->rebate_amount = $this->paymentrebate_amount; $this->pm->rebate_absolute = $this->paymentrebate_absolute; $this->pm->parameter[0] = $this->payment_param; $this->pm->vat = $this->payment_vat; // Kunde einfügen $this->client = new client(null, $this->order_id); if (!$this->client->client_id) die('Data corrupt #2'); } else { // Nur Warenkorb $this->b2b = CC_SITE_B2B; $this->currency = CC_SITE_CURRENCY; } $this->vatarray = new vatarray($this->b2b, isset($this->client->novat) ? $this->client->novat : 0); format::to_abs($this, array('sumrebate_absolute', 'couponrebate_absolute', 'paymentrebate_absolute')); format::to_float($this, array('sumrebate_amount', 'couponrebate_amount', 'shipping_vat', 'payment_vat', 'shipping_cost', 'payment_amount', 'paymentrebate_amount'), 2); // Artikel laden $item = new item(); $item->db_select(array('uid', 'position', 'memo'), array('order_id' => $this->order_id), array('position asc')); while ($row = $item->db_fetch()) $this->items[] = new item($row->uid, $this->order_id, $row->position, null, $row->memo); $item->db_free(); // Vorgefüllter Artikel in den Warenkorb if (CC_SITE_PREFILL && !count($this->items)) { $position = $this->add_item(new item(null, null, null, MODE_PREFILL)); // Eco-Tax Anpassung Frankreich, falls Ecotax vorhanden Artikel anlegen if (CC_SITE_LOCALE_FR && CC_SITE_PREFILL_ECOTAX_PROVIDER) $this->add_item(new item(null, null, $position, MODE_ECOTAXPREFILL)); } if (!$this->order_date && $client) { if ($this->client->payment_uid) { $payment->calc_prices($this); $this->pm = $payment->get($this->client->payment_uid); } } else if ($this->order_date) $this->calc_vat(); } //////////////////////////////////////////////////////////////////////////// Gutscheine // Gutschein einbuchen function add_coupon($coupon_id) { if (!preg_match(CHECK_ALPHANUMCOUPON, $coupon_id)) return CC_RESSOURCE_COUPONINVALID; $coupon = new coupon($coupon_id); if (!$coupon->coupondef_id) return CC_RESSOURCE_COUPONINVALID; if ($coupon->order_id) return CC_RESSOURCE_COUPONREDEEMED; $coupondef = new coupondef($coupon->coupondef_id); // Bestimmter Kunde if ($coupon->client_email && $coupon->client_email != $this->client->email) return CC_RESSOURCE_COUPONCLIENTNOTMET; // Bestimmter Artikel if ($coupondef->item_uid && !$this->contains_item($coupondef->item_uid)) return CC_RESSOURCE_COUPONITEMNOTMET; // Bestimmter Zeitraum if ($coupondef->date_from && strtotime($coupondef->date_from) > time()) return CC_RESSOURCE_COUPONDATENOTMET; if ($coupondef->date_until && strtotime($coupondef->date_until) + 86400 < time()) return CC_RESSOURCE_COUPONDATENOTMET; // Mindestbestellwert if ($coupondef->subtotal && $this->get_subtotal() < $coupondef->subtotal) return CC_RESSOURCE_COUPONVALUENOTMET; // Gutschein im Kundenkonto speichern $this->client->coupon_id = $coupon_id; $this->client->store(); $this->coupon_id = $coupon_id; $this->couponrebate_absolute = $coupondef->rebate_absolute; $this->couponrebate_amount = $coupondef->rebate_amount; return false; } // Gutschein entfernen function remove_coupon() { if ($this->coupon_id) { $coupon = new coupon($this->coupon_id); $coupon->store(); $this->client->coupon_id = null; $this->client->store(); $this->coupon_id = null; $this->couponrebate_amount = 0; $this->couponrebate_absolute = 0; } } //////////////////////////////////////////////////////////////////////////// Berechnung // Tatsächliche Preise von Artikeln und Versand/Bezahlung aktuelisieren function calc_prices() { global $filename; // Artikelpreise aktualisieren foreach (array_keys($this->items) as $k) { $item = &$this->items[$k]; // Mengenrabatte $item->calc_quantrebate(); // Gutscheine mit Artikelrabatten (nicht für Artikel auf Merkzettel) if (!$item->memo) if ($this->coupon && $this->coupondef->item_uid == $item->uid) { $price = floatval($this->coupondef->item_price); $item->price = max(0, $price); } } // Umsatzsteueranpassung Spanien // Falls Kunde eingeloggt und für Provins Ersetzungen vorhanden $adapt = array(); if (CC_SITE_LOCALE_ES && $this->client && $adapt = get_vat_adaption($this->client)) { foreach (array_keys($this->items) as $k) { $item = &$this->items[$k]; if (array_key_exists($old = (int) $item->vat, $adapt)) { $new = $adapt[$old]; $item->vat = $new; if (!$this->b2b) $item->price = floor($item->price / (1 + $old / 100) * (1 + $new / 100) * 100) / 100; } } } // Umsatzsteueranpassung Spanien if (CC_SITE_LOCALE_ES && count($adapt)) { $this->get_shipping_cost(); if ($this->sm && array_key_exists($old = (int) $this->sm->vat, $adapt)) { $new = $adapt[$old]; $this->sm->vat = $new; if (!$this->b2b) $this->sm->actualprice = floor($this->sm->actualprice / (1 + $old / 100) * (1 + $new / 100) * 100) / 100; } $this->get_payment_cost(); if ($this->pm && array_key_exists($old = (int) $this->pm->vat, $adapt)) { $new = $adapt[$old]; $this->pm->vat = $new; if (!$this->b2b) $this->pm->actualprice = floor($this->pm->actualprice / (1 + $old / 100) * (1 + $new / 100) * 100) / 100; } } // Bestelloptionen zur Artikelliste hinzufügen global $checkout_sites; if ($this->client && in_array(FILENAME, $checkout_sites)) { // Position ermittlen $db_item = new item(); $obj = $db_item->db_selectone(array('max(position) as pos'), array('order_id' => $this->order_id)); if ($obj) $position = $obj->pos + 1; else $position = 1; if ($this->client->custom_options) $custom_values = (array) unserialize($this->client->custom_options); else $custom_values = array(); global $customoptions; foreach ((array) $customoptions as $custom) { $is_selectedprice = 0; $custom_item = new item(); $custom_item->vat = $custom->vat; $custom_item->uid = 'custom'; $custom_item->position = $position++; $custom_item->unit = 'x'; $custom_item->rebatable = CC_SITE_ORDERSPECIALSREBATABLE; if ($custom->is_checkbox && isset($custom_values[$custom->caption])) { $custom_item->price = $custom->price; $custom_item->caption = $custom->caption; $custom_item->quantity = 1; } if ($custom->is_combo && isset($custom_values[$custom->caption])) foreach ($custom->combo_options as $option) if (isset($custom_values[$custom->caption]) && $custom_values[$custom->caption] == $option->caption) { $custom_item->price = $option->price; $custom_item->caption = $custom->caption . ': ' . $option->caption; $custom_item->quantity = 1; } if ($custom->is_text && isset($custom_values[$custom->caption])) { $custom_item->price = 0; $custom_item->caption = $custom->caption . ': ' . $custom_values[$custom->caption]; $custom_item->quantity = 1; } if ($custom_item->quantity) { array_push($this->items, $custom_item); } } } } // Steuern berechnen function calc_vat($filename = null) { if ($this->get_subtotal()) { if ($this->get_subtotal_rebatable() > 0) $rebate_percent = ($this->get_subtotal_rebatable() - $this->get_rebate()) / $this->get_subtotal_rebatable(); else $rebate_percent = 0; // Steuern für Artikel (nicht die auf Merkzettel) foreach ($this->items as $item) { if (!$item->memo) { if ($item->rebatable) $sum = $item->price * $item->quantity * $rebate_percent; else $sum = $item->price * $item->quantity; $this->vatarray->add($item->vat, $sum, $this->b2b); } } } if ($filename != CC_FILENAME_BASKET) { // Steuern für Versandmethode $cost = $this->get_shipping_cost(); $this->vatarray->add($this->sm->vat, $cost, $this->b2b); // Steuern für Bezahlmethode $cost = $this->get_payment_cost(); $this->vatarray->add($this->pm->vat, $cost, $this->b2b); } $this->vatarray->sort(); } // Anzahl der Artikel im Korb aktualisieren function update_quantity() { if (!CC_SITE_LOCKOUTOFSTOCK) return array(); return $this->check_quantity(true); } // Anzahl der Artikel im Korb prüfen function check_quantity($update = false) { if (!CC_SITE_LOCKOUTOFSTOCK) return true; $messages = array(); foreach (array_keys($this->items) as $k) { $item = &$this->items[$k]; // Nicht für Artikel auf dem Merkzettel if ($item->memo) continue; // gültig if ($message = $item->check_minmax()) $messages[] = $message; // Aktuelle Bestands- und Statusdaten des Artikels einlesen if ($item->stockserver) { $stock_product = new stock_product($item->uid, $item->variationa ? $item->variationa : 1, $item->variationb ? $item->variationb : 1); $stock = $stock_product->get(); } // Falls nicht lieferbar auf Merkzettel setzen. if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock <= 0) { $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKNOTADDED); if ($update) { $toggle_item = new item( $item->uid, $this->order_id, $item->position, MODE_SWITCH, 0 ); $this->drop_item( $item->position, 0 ); $this->add_item($toggle_item); } } // Nur noch weniger Menge als im Bestand if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock < $item->quantity) { $item->quantity = $stock; $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKQUANTITYMODIFIED); } if ($update) $item->store(); } if ($update) return $messages; else if (count($messages)) return false; else return true; } // Artikel und Anzahl im Korb anhand Formular aktualisieren function calc_quantity() { $updated = false; $messages = array(); foreach (array_keys($this->items) as $k) { $item = &$this->items[$k]; // Nicht für Artikel auf dem Merkzettel if ($item->memo) continue; if (isset($_POST['quantity'.$item->position])) { $item->new_quantity = post('quantity'.$item->position, CHECK_NUMVALUE); $prev_quantity = $item->quantity; $item->quantity = null; $check = $item->check_quantity(); if ($item->quantity != $prev_quantity) { if ($check) { // gültige Menge if ($message = $item->check_minmax()) $messages[] = $message; // Aktuelle Bestands- und Statusdaten des Artikels einlesen if ($item->stockserver) { $stock_product = new stock_product($item->uid, $item->variationa ? $item->variationa : 1, $item->variationb ? $item->variationb : 1); $stock = $stock_product->get(); } // Falls nicht lieferbar auf Merkzettel setzen. if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock <= 0) { $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKNOTADDED); $toggle_item = new item( $item->uid, $this->order_id, $item->position, MODE_SWITCH, 0 ); $this->drop_item( $item->position, 0 ); $this->add_item($toggle_item); } // Nur noch weniger Menge als im Bestand if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock < $item->quantity) { $item->quantity = $stock; $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKQUANTITYMODIFIED); } // Eco-Tax Anpassung Frankreich / Abhängige Artikel if (CC_SITE_LOCALE_FR) // Menge des abhängigen Artikels mit ändern $this->update_belonging_items($item); $item->store(); $updated = true; } else if ($check === false) { // Ungültige Menge $messages[] = CC_RESSOURCE_BASKETNOQUANTITY; } else { // Menge 0 = aus Korb entfernen $drop_position[] = $item->position; $drop_memo[] = $item->memo; } } else $item->new_quantity = null; } } if (isset($drop_position)) for ($i = 0; $i < count($drop_position); $i++) $this->drop_item($drop_position[$i], $drop_memo[$i]); if (count($messages)) return $messages; else if ($updated) return array(CC_RESSOURCE_BASKETUPDATED); return array(); } //////////////////////////////////////////////////////////////////////////// Artikel // Eco-Tax Anpassung Frankreich / Abhängige Artikel // Menge des abhängigen Artikels mit ändern function update_belonging_items($main_item) { foreach (array_keys($this->items) as $k) { $item = &$this->items[$k]; if ($item->position_main == $main_item->position && $item->memo == $main_item->memo) { $item->quantity = $main_item->quantity; $item->store(); break; } } } // Überprüft ob Artikel im Warenkorb liegt (nicht auf dem Merkzettel) function contains_item($uid) { foreach ($this->items as $item) if ($item->uid == $uid && !$item->memo) return true; return false; } // Gibt Artikel zurück function get_item($uid) { foreach ($this->items as $item) if ($item->uid == $uid) return $item; return false; } // Element aus Korb oder von Merkzettel entfernen function drop_item($position, $memo) { $new_items = array(); foreach ($this->items as $item) { if ($item->position == $position && $item->memo == $memo || $item->position_main == $position && $item->memo == $memo) { $item->delete(); } else array_push($new_items, $item); } $this->items = $new_items; } // Ins Körbchen oder auf den Merkzettel legen function add_item($item) { global $myquantity; $messages = array(); // Verfügbar? if ($item->status == 0) return ITEMSTATUS_NOTAVAILABLE; else { // Durschsuchen ob bereits im Warenkorb vorhanden if ($item->check_quantity()) { // Aktuelle Bestands- und Statusinformationen if ($item->stockserver) { $stock_product = new stock_product($item->uid, $item->variationa ? $item->variationa : 1, $item->variationb ? $item->variationb : 1); $stock = $stock_product->get(); } // Falls nicht lieferbar auf Merkzettel setzen. if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock <= 0 && !$item->memo) { $item->memo = 1; $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKNOTADDED); } $found = -1; for ($i = 0; $i < count($this->items); $i++) { if ($this->items[$i]->uid == $item->uid && $this->items[$i]->variationa == $item->variationa && $this->items[$i]->variationb == $item->variationb && $this->items[$i]->memo == $item->memo && $this->items[$i]->specialinfo == $item->specialinfo) { $found = $i; } } // Falls nicht, neuen Artikel speichern if ($found == -1) { $found = count($this->items); $this->items[] = &$item; if ($message = $item->check_minmax()) $messages[] = $message; if (CC_SITE_LOCKOUTOFSTOCK && $item->stockserver && $stock < $item->quantity && !$item->memo) { // Nur noch weniger Menge als im Bestand $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKQUANTITYMODIFIED); $item->quantity = $stock; } $item->store($this->order_id); $myquantity = $item->quantity; return $messages; // ansonsten bereits im Korb, aktualisieren } else { $this->items[$found]->quantity += $item->quantity; // Nur noch weniger Menge als im Bestand if (CC_SITE_LOCKOUTOFSTOCK && !$item->memo && $this->items[$found]->stockserver && $stock < $this->items[$found]->quantity) { $this->items[$found]->quantity = $stock; $messages[] = str_replace('[c]', $item->caption, CC_RESSOURCE_BASKET_OUTOFSTOCKQUANTITYMODIFIED); } if ($message = $this->items[$found]->check_minmax()) $messages[] = $message; // Eco-Tax Anpassung Frankreich / Abhängige Artikel if (CC_SITE_LOCALE_FR) // Menge des abhängigen Artikels mit ändern $this->update_belonging_items($this->items[$found]); $this->items[$found]->store(); return $messages; } } else { // Ungültige Menge return ITEMSTATUS_INVALIDNUMBER; } } } //////////////////////////////////////////////////////////////////////////// Menge, Gewicht, Preis // Anzahl Artikel im Warenkorb (nicht auf dem Merkzettel) function get_quantity() { $quantity = 0; foreach ($this->items as $item) // Eco-Tax Anpassung Frankreich / Abhängige Artikel // Abhängige Artikel nicht mitzählen if (!$item->position_main && !$item->memo) $quantity += ($item->qprecision ? 1 : $item->quantity); return $quantity; } // Anzahl Artikel auf dem Merkzettel function get_memoquantity() { $quantity = 0; foreach ($this->items as $item) // Eco-Tax Anpassung Frankreich / Abhängige Artikel // Abhängige Artikel nicht mitzählen if (!$item->position_main && $item->memo) $quantity += ($item->qprecision ? 1 : $item->quantity); return $quantity; } // Gewicht im Warenkorb (nicht auf dem Merkzettel) function get_weight() { $weight = 0; foreach ($this->items as $item) if (!$item->memo) $weight += $item->weight * $item->quantity; return $weight; } // Summe Artikel im Warenkorb (nicht auf dem Merkzettel) function get_price() { $price = 0; foreach ($this->items as $item) if (!$item->memo) $price += round($item->price * $item->quantity, 2); return max($price, 0); } // Summe rabattierbarer Artikel im Warenkorb (nicht auf dem Merkzettel) function get_price_rebatable() { $price = 0; foreach ($this->items as $item) if (!$item->memo && $item->rebatable) $price += round($item->price * $item->quantity, 2); return max(0, $price); } // Zwischensumme function get_subtotal() { return round($this->get_price(), 2); } // Tabattierbare Zwischensumme function get_subtotal_rebatable() { return round($this->get_price_rebatable(), 2); } // Rabatte berechnen (nicht Artikel auf dem Merkzettel) function get_rebate() { global $payment; $subtotal = $this->get_subtotal(); $subtotal_rebatable = $this->get_subtotal_rebatable(); $rebate = 0; // Summenrabatte if ($this->sumrebate_amount === null) $this->set_sumrebate(); if ($this->sumrebate_amount && $this->sumrebate_absolute) $rebate += min($this->sumrebate_amount, $subtotal_rebatable); else if ($this->sumrebate_amount) $rebate += $subtotal_rebatable * $this->sumrebate_amount / 100; // Kundenrabatte if ($this->client) { if ($this->client->rebate_amount && $this->client->rebate_absolute) $rebate += min($this->client->rebate_amount, $subtotal_rebatable - $rebate); else if ($this->client->rebate_amount) $rebate += ($subtotal_rebatable - $rebate) * ($this->client->rebate_amount / 100); } // Gutscheinrabatte if ($this->couponrebate_amount && $this->couponrebate_absolute) $rebate += min($this->couponrebate_amount, $subtotal_rebatable - $rebate); else if ($this->couponrebate_amount) $rebate += ($subtotal_rebatable - $rebate) * ($this->couponrebate_amount / 100); // Zahlweisenrabatt if ($this->pm) { if ($this->pm->rebate_amount && $this->pm->rebate_absolute) $rebate += min($this->pm->rebate_amount, $subtotal_rebatable - $rebate); else if ($this->pm->rebate_amount) $rebate += ($subtotal_rebatable - $rebate) * ($this->pm->rebate_amount / 100); } return round($rebate, 2); } // Steuern im Warenkorb (nicht auf dem Merkzettel) function get_totalvat() { return $this->vatarray->get_total(); } // Endsumme ohne Versand- oder Bezahlkosten function get_subtotalprice() { return $this->get_subtotal() - $this->get_rebate(); } // Endsumme im Warenkorb (nicht auf dem Merkzettel) function get_totalprice() { $totalprice = $this->get_subtotal() - $this->get_rebate() + $this->get_shipping_cost() + $this->get_payment_cost(); if ($this->b2b) $totalprice += $this->get_totalvat(); return round($totalprice, 2); } // Versandkosten berechnen function get_shipping_cost() { global $shipping; if ($this->sm === null) { $shipping->calc_prices($this); $this->sm = $shipping->get($this->client->shipping_uid); $shipping_cost = 0; if ($this->sm->actualprice > 0) { if ($this->sm->perpiece) $shipping_cost = $this->sm->actualprice * $this->get_quantity(); else $shipping_cost = $this->sm->actualprice; } $this->sm->total = $shipping_cost; return $shipping_cost; } else return $this->sm->total; } // Bezahlkosten berechnen function get_payment_cost() { global $payment; if ($this->pm->total === null) { $payment_cost = 0; if ($this->pm->actualprice !== null) $payment_cost = $this->pm->actualprice; else { if ($this->pm->amount && $this->pm->absolute) $payment_cost += $this->pm->amount; else if ($this->pm->amount) $payment_cost += $this->get_subtotal() * $this->pm->amount / 100; } $this->pm->total = $payment_cost; return $payment_cost; } else return $this->pm->total; } // Summenrabatte errechnen function set_sumrebate() { // Summenrabattstaffel auslesen function get_sumrebateinfo($subtotal) { global $sumrebate_from, $sumrebate_amount, $sumrebate_absolute; for ($i = 5; $i >= 1; $i--) { if (isset($sumrebate_from[$i])) { if ($subtotal >= $sumrebate_from[$i]) return array($sumrebate_amount[$i], $sumrebate_absolute[$i]); } } return array(0, 0); } $info = get_sumrebateinfo($this->get_subtotal_rebatable()); $this->sumrebate_amount = $info[0]; $this->sumrebate_absolute = $info[1]; } //////////////////////////////////////////////////////////////////////////// Datenbankl // Key zum Drucken der Bestellung (wegen Zugang ohne Konto) function generate_key() { return md5($this->order_time.$this->order_date.$this->client->password.$this->order_id); } // Rechnungsnummer generieren und Datum setzen function set_bill_data() { $bill_id = new abstractdb(TABLE_BILLIDS); if (!$bill_id->db_numrows()) { $bill_id->bill_id = max(1, CC_SITE_STARTBILLID); $bill_id->store(true); } else $bill_id->bill_id = $bill_id->generate_id(); $this->bill_id = $bill_id->bill_id; $this->bill_id_prefix = CC_SITE_PREFIXBILLID; $this->bill_date = date("Y-m-d"); } // Auftragsnummer generieren und Datum setzen function set_order_data() { if (CC_SITE_STARTORDERID) { $order_id = new abstractdb(TABLE_ORDERIDS); if (!$order_id->db_numrows()) { $order_id->order_id = max(1, CC_SITE_STARTORDERID); $order_id->store(true); } else $order_id->order_id = $order_id->generate_id(); $this->order_id = $order_id->order_id; } else { list($usec, $sec) = explode(" ", microtime()); $usec = floor((float) $usec * 1000); $this->order_id = substr($usec.strrev($sec), 0, 9); } $this->order_id_prefix = CC_SITE_PREFIXORDERID; $this->order_date = date("Y-m-d"); $this->order_time = date("H:i:s"); } // Bestellung zum Speichern kreieren function create($session) { $this->set_order_data(); $this->shipping_cost = $this->get_shipping_cost(); if ($this->get_payment_cost()) { $this->payment_amount = $this->pm->amount; } else { $this->payment_amount = 0; } $this->payment_absolute = $this->pm->absolute; $this->paymentrebate_amount = $this->pm->rebate_amount; $this->paymentrebate_absolute = $this->pm->rebate_absolute; // PDF Erstellung $has_esd = false; foreach ($this->items as $item) if ($item->download_uid && !$item->memo) $has_esd = true; $this->pdf_creation = $has_esd ? $this->pm->pdf_creation_esd : $this->pm->pdf_creation; $this->shipping_vat = $this->sm->vat; $this->payment_vat = $this->pm->vat; $this->shipping_caption = $this->sm->caption; if ($this->sm->parameter) $this->shipping_param = $this->sm->parameter; if ($this->sm->trackingurl) $this->shipping_trackingurl = $this->sm->trackingurl; $this->payment_caption = $this->pm->caption; if ($this->pm->parameter[0]) $this->payment_param = $this->pm->parameter[0]; $this->search_email = $this->client->email; $this->search_name = $this->client->firstname.' '.$this->client->lastname; $this->affiliate_id = $session->affiliate_id or null; $this->affiliate_subid = $session->affiliate_subid or null; $session->unset_affiliate(); // Gutschein einlösen if ($this->coupon) { if ($this->coupon->mode == COUPONMODE_COUPON) { $this->coupon->order_id = $this->order_id; $this->coupon->client_id = $this->client->client_id; $this->coupon->store(); } $this->client->coupon_id = null; $this->client->store(); } // Bestandskontrolle und Artikel mit Bestellnummer versehen, nicht mehr benötigte Felder nullen foreach ($this->items as $item) { if ($item->memo) continue; if ($item->stockserver) { $product = new stock_product($item->uid, $item->variationa ? $item->variationa : 1, $item->variationb ? $item->variationb : 1); $product->dec($item->quantity); } $item->change_order_id($this->order_id); $item->order_status = CC_RESSOURCE_ORDERSTATUSSHORT_NEW; $item->position_main = null; $item->noship = null; $item->rebate = null; $item->minimum = null; $item->maximum = null; $item->stockserver = null; $item->variationa = 0; $item->variationb = 0; if ($item->download_uid) $item->download_count = 0; if ($item->uid == 'custom') $item->store(true); $item->store(); } } // Setz den Status und ggf. Datum Geldeingang oder Versand function set_status($status, $set_items) { $old_status = $this->status; if ($status < CC_RESSOURCE_ORDERSTATUSSHORT_NEW || $status > CC_RESSOURCE_ORDERSTATUSSHORT_SHIPPED) return false; // Artikel setzen if ($set_items) { $downloads = 0; foreach ($this->items as $item) { $item->order_status = $status; // Bei digitalen Gütern Status direkt auf abgeschlossen setzen if ($status == CC_RESSOURCE_ORDERSTATUSSHORT_WAITINGITEMS && $item->download_uid) { $item->order_status = CC_RESSOURCE_ORDERSTATUSSHORT_SHIPPED; $downloads++; } $item->store(); } // Falls ausschliesslich digitale Güter, auch Bestellstatus auf abgeschlossen setzen if ($downloads == count($this->items)) $status = CC_RESSOURCE_ORDERSTATUSSHORT_SHIPPED; } if ($this->status <= CC_RESSOURCE_ORDERSTATUSSHORT_WAITINGPAYMENT && $status >= CC_RESSOURCE_ORDERSTATUSSHORT_WAITINGITEMS) $this->payment_date = date("Y-m-d"); else if ($status <= CC_RESSOURCE_ORDERSTATUSSHORT_WAITINGPAYMENT) $this->payment_date = null; if ($this->status <= CC_RESSOURCE_ORDERSTATUSSHORT_MANUFACTURING && $status >= CC_RESSOURCE_ORDERSTATUSSHORT_SHIPPED) $this->shipping_date = date("Y-m-d"); else if ($status <= CC_RESSOURCE_ORDERSTATUSSHORT_MANUFACTURING) $this->shipping_date = null; $this->status = $status; $this->store(); if ($old_status != $this->status) return true; else return false; } function send_status_email($pdf_email = false) { if (!CC_SITE_STATUSEMAILS && !$pdf_email) return; // Nicht bei Bestellung eingegangen if (!$this->status || ($this->status == CC_RESSOURCE_ORDERSTATUSSHORT_NEW && !$pdf_email)) return; // Template Variablen einlesen $active = false; foreach(file(CC_INCLUDE_OSTEMPLATES) as $line) { $line = trim($line); if (strlen($line)) { if ($active) { if (preg_match("/^\[.*\]$/", $line)) { if (!preg_match("/^\[Template-Variables-.*\]$/", $line)) $active = false; } else if (preg_match("/^([a-z_]+)=(.*)$/", $line, $found)) $mailtemplate_vars[$found[1]] = $found[2]; else if (!preg_match("/^;/", $line, $found)) die('Error in file '.CC_INCLUDE_OSTEMPLATES.', unknown command "'.$line.'".'); } else if (preg_match("/^\[Template-Variables-.*\]$/", $line)) $active = true; } } $mailtemplate = new abstractdb(TABLE_TEMPLATES); $mailtemplate = $mailtemplate->get(array('*'), array('status' => $pdf_email ? $pdf_email : $this->status), null); // Vorlagenvariablen foreach ($mailtemplate_vars as $key => $var) { $orig[] = '/{'.$var.'}/'; if ($key == 'country') $repl[] = substr($this->client->$key, 11); else if ($key == 'signature') $repl[] = str_replace('
', "\n", CC_SITE_SHOPADDRESS); else if (strstr($key, '_date')) $repl[] = $this->$key ? date(CC_SITE_DATEFORMAT, strtotime($this->$key)) : ''; else if (in_array($key, array('order_id', 'order_id_prefix', 'tracking_id', 'message', 'expected_date'))) $repl[] = $this->$key ? $this->$key : ''; else if ($key == 'shipping_trackingurl') $repl[] = CC_SITE_HTTPURL . clean_url($this->$key); else $repl[] = $this->client->$key; } // Email füllen $email = new email(); $email->order_id = $this->order_id; $email->client_id = $this->client->client_id; $email->to_plain = $this->client->firstname.' '.$this->client->lastname; $email->from_email = CC_SITE_MAILFROM; $email->from_plain = CC_SITE_MAILNAME; $email->to_email = $this->client->email; $email->subject = $mailtemplate->subject; $email->content_plain = preg_replace($orig, $repl, $mailtemplate->body); $orig[] = "/\n/"; $repl[] = "
"; $email->content_html = preg_replace($orig, $repl, $mailtemplate->body); // Ggf. Rechnung anhängen if (($pdf_email || $this->status == CC_RESSOURCE_ORDERSTATUSSHORT_SHIPPED && $this->pdf_creation == PDF_CREATION_ONSHIPP) && !CC_SITE_BILLHASLEFTTHEBUILDING) { include_once(CC_BLOGIC_PDFDOC); $pdfdoc = new pdfdoc(CC_SITE_FILEKEY, DOCS, $this); $pdfdoc->verify($pdfdoc->MODE_BILL); $pdf['filename'] = $pdfdoc->filename($pdfdoc->MODE_BILL); $pdf['name'] = $pdfdoc->name($pdfdoc->MODE_BILL); $email->pdf = $pdf; } $email->store(); if ($this->message) { $this->message = null; $this->store(); } } function send_confirmation_emails() { // HTML-Mail vorbereiten $html_template = new template(CC_TPL_SUMMARY); $html_template->show('email'); $html_template->assign(array( '_shopaddress' => CC_SITE_SHOPADDRESS, '_pm_email' => $this->pm->email, )); require(CC_SHOPSCRIPT_OUTPUTFUNCTIONS); generate_summary($html_template, $this, true); // Text-Mail vorbereiten $text_template = new template(CC_TPL_SUMMARYPLAIN); generate_summary($text_template, $this, true); $text_template->assign(array( '_shopaddress' => str_replace('
', "\r\n", CC_SITE_SHOPADDRESS), '_pm_email' => $this->pm->email, )); // Email Bestätigung an Betreiber $email = new email(); $email->order_id = $this->order_id; $email->client_id = $this->client->client_id; $email->to_email = CC_SITE_MAILCOPY; $email->from_email = CC_SITE_MAILFROM; $email->from_plain = CC_SITE_MAILNAME; $email->subject = 'FWD: '.CC_SITE_MAILSUBJECT; $email->content_html = $html_template->getparsed(); $email->content_plain = strip_tags($text_template->getparsed()); // PDF Auftragsbestätigung oder Rechnung // Direkt Rechnung $pdf = array(); if ($this->pdf_creation == PDF_CREATION_ONORDER) { include_once(CC_BLOGIC_PDFDOC); $pdfdoc = new pdfdoc(CC_SITE_FILEKEY, DOCS, $this); $pdfdoc->verify($pdfdoc->MODE_BILL); $pdf['filename'] = $pdfdoc->filename($pdfdoc->MODE_BILL); $pdf['name'] = $pdfdoc->name($pdfdoc->MODE_BILL); // Erstmal Auftragsbestätigung } else if ($this->pdf_creation == PDF_CREATION_ONSHIPP) { include_once(CC_BLOGIC_PDFDOC); $pdfdoc = new pdfdoc(CC_SITE_FILEKEY, DOCS, $this); $pdfdoc->verify($pdfdoc->MODE_CONFIRMATION); $pdf['filename'] = $pdfdoc->filename($pdfdoc->MODE_CONFIRMATION); $pdf['name'] = $pdfdoc->name($pdfdoc->MODE_CONFIRMATION); } $email->pdf = CC_SITE_BILLHASLEFTTHEBUILDING ? null : $pdf; if (CC_SITE_MAILCOPY) $email->store(); // Email an Kunden $email->to_email = $this->client->email; $email->to_plain = $this->client->firstname." ".$this->client->lastname; $email->subject = CC_SITE_MAILSUBJECT; $email->store(); } // Kunde über Lizenzvergabe informieren function send_license_mail($hk, $comment, $caption, $date, $ressource) { $email = new email(); $email->order_id = $this->order_id; $email->client_id = $this->client->client_id; $email->to_plain = $this->client->firstname." ".$this->client->lastname; $email->to_email = $this->client->email; $email->from_email = CC_SITE_MAILFROM; $email->from_plain = CC_SITE_MAILNAME; $email->subject = CC_RESSOURCE_LICENSEMAILSUBJECT; $email->content_plain = $ressource; $email->content_plain = str_replace('[br]', "\n", $email->content_plain); $email->content_plain = str_replace('[s]', $this->client->salutation, $email->content_plain); $email->content_plain = str_replace('[fn]', $this->client->firstname, $email->content_plain); $email->content_plain = str_replace('[ln]', $this->client->lastname, $email->content_plain); $email->content_plain = str_replace('[i]', $caption, $email->content_plain); $email->content_plain = str_replace('[od]', date(CC_SITE_DATEFORMAT, strtotime($this->order_date)), $email->content_plain); $email->content_plain = str_replace('[ld]', date(CC_SITE_DATEFORMAT, strtotime($date)), $email->content_plain); $email->content_plain = str_replace('[h]', $hk, $email->content_plain); $email->content_plain = str_replace('[c]', $comment, $email->content_plain); $email->content_plain = str_replace('[sa]', str_replace('
', "\n", CC_SITE_SHOPADDRESS), $email->content_plain); $email->store(); } //////////////////////////////////////////////////////////////////////////// Datenbank // Bestellungen holen function get($fields, $where, $order = null, $page = null, $perpage = null) { return $this->db_get($fields, $where, $order, $page, $perpage); } // Bestellungen holen mit join function getjoin($fields, $where = null, $order = null, $page, $perpage) { if (!$this->is_result()) { $from = $perpage * ($page - 1); $this->db_selectjoin($fields, 'clients', 'order_id', $where, $order, $from, $perpage); } $object = $this->db_fetch(); if (!$object) { $this->db_free(); return $object; } else { foreach(get_object_vars($object) as $k => $v) { $new_k = substr($k, (strpos($k, '.') ? strpos($k, '.') + 1 : 0)); $new_object->$new_k = $v; } return $new_object; } } // Bestellung speichern function store($mode = false) { $this->generate_change_id(); if ($mode) $this->db_insertobject(); else $this->db_updateobject(); } // Bestellung löschen function delete() { $this->db_delete(array('order_id' => $this->order_id)); $this->client->delete(); foreach ($this->items as $item) $item->delete(); $deleted_ids = new abstractdb(TABLE_DELETED); $deleted_ids->order_id = $this->order_id; $this->generate_change_id(); $deleted_ids->change_id = $this->change_id; $deleted_ids->store(true); return $this->change_id; } } //////////////////////////////////////////////////////////////////////////// // Klasse Steuern class vat { var $percent; // Prozentsatz var $amount; // Betrag function vat() { } } // Klasse Steuerfeld class vatarray { var $vatarray = array(); var $index = null; var $b2b; function vatarray($b2b, $novat) { $this->b2b = $b2b; $this->novat = $novat; } // Zufügen zum Feld function add($rate, $price) { if ($price) { $found = -1; for ($i = 0; $i < count($this->vatarray); $i++) { if ($this->vatarray[$i]->percent == $rate) $found = $i; } if ($found == -1) { $found = count($this->vatarray); $vat = new vat(); $vat->percent = $rate; $vat->amount = 0; $this->vatarray[] = $vat; } if ($this->b2b) $this->vatarray[$found]->amount += $price * $rate / 100; else $this->vatarray[$found]->amount += $price / (100 + $rate) * $rate; } } // Feld sortieren function sort() { uasort($this->vatarray, 'sort_vat'); } // Gesamtsteurn berechnen function get_total() { if ($this->novat) return 0; $totalvat = 0; foreach (array_keys($this->vatarray) as $k) $totalvat += round($this->vatarray[$k]->amount, 2); return round($totalvat, 2); } } // Callback Funktion zum Sortieren des Steuerfeldes function sort_vat($a, $b) { return $a->percent - $b->percent; } ?>