first commit
This commit is contained in:
407
class/class.PosCart.php
Normal file
407
class/class.PosCart.php
Normal file
@@ -0,0 +1,407 @@
|
||||
<?php
|
||||
|
||||
use KupShop\KupShopBundle\Util\Compat\ServiceContainer;
|
||||
use KupShop\OrderingBundle\Entity\Purchase\PurchaseState;
|
||||
use KupShop\OrderingBundle\Event\OrderItemEvent;
|
||||
use KupShop\OrderingBundle\Util\Order\OrderInfo;
|
||||
|
||||
/**
|
||||
* Class PosCart.
|
||||
*/
|
||||
class PosCartBase extends Cart
|
||||
{
|
||||
/** @var \Symfony\Component\HttpFoundation\Session\Session */
|
||||
private $session;
|
||||
|
||||
/**
|
||||
* Fetching functions.
|
||||
*/
|
||||
protected function fetchProducts()
|
||||
{
|
||||
global $dbcfg, $cfg;
|
||||
|
||||
$this->session = ServiceContainer::getService('session');
|
||||
|
||||
$this->totalPriceNoVat = DecimalConstants::zero();
|
||||
$this->totalPriceWithVat = DecimalConstants::zero();
|
||||
|
||||
$where = queryCreate($this->getSelectParams(), true);
|
||||
|
||||
$fields = 'c.id, c.pieces, c.id_variation, c.note, p.id as id_product, p.title, p.price, p.producer as id_producer, pr.name as producer, p.discount, COALESCE(pv.in_store, p.in_store) as in_store, p.vat,
|
||||
FIND_IN_SET("Z", p.campaign)>0 free_shipping, COALESCE(pv.delivery_time, p.delivery_time) as delivery_time, COALESCE(pv.ean, p.ean) as ean ';
|
||||
$from = 'cart AS c
|
||||
LEFT JOIN products AS p ON c.id_product=p.id
|
||||
LEFT JOIN producers AS pr ON pr.id=p.producer
|
||||
LEFT JOIN products_variations AS pv ON c.id_variation=pv.id
|
||||
LEFT JOIN photos_products_relation ppr ON p.id=ppr.id_product AND ppr.show_in_lead="Y"';
|
||||
|
||||
if (findModule('products_variations', 'variationCode')) {
|
||||
$fields .= ', pv.code as variation_code';
|
||||
}
|
||||
|
||||
$SQL = sqlQuery("SELECT {$fields}
|
||||
FROM {$from}
|
||||
WHERE {$where}
|
||||
GROUP BY c.id
|
||||
ORDER BY c.id");
|
||||
|
||||
foreach ($SQL as $row) {
|
||||
$product = new Product($row['id_product']);
|
||||
|
||||
$product->createFromDB($product->id);
|
||||
|
||||
$product->cart_item_id = $row['id'];
|
||||
|
||||
$dec_Pieces = Decimal::fromString("{$row['pieces']}");
|
||||
$product->pieces = $row['pieces'];
|
||||
|
||||
$product->note = $product->parseNote($row['note']);
|
||||
$product->inStore = $row['in_store'];
|
||||
|
||||
$IDvariation = $product->id_variation = $row['id_variation'];
|
||||
|
||||
if (!is_null($IDvariation)) {
|
||||
$product->title = Variations::fillInProductTitle(intval($IDvariation), $product->title);
|
||||
}
|
||||
|
||||
if ($IDvariation) {
|
||||
$product->ean = returnSQLResult('SELECT ean FROM products_variations WHERE id=:id', ['id' => $IDvariation]);
|
||||
if (findModule(Modules::PRODUCTS_VARIATIONS, Modules::SUB_CODE)) {
|
||||
$product->code = returnSQLResult('SELECT code FROM products_variations WHERE id=:id', ['id' => $IDvariation]);
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($row['id_product'])) {
|
||||
if (!empty($product->note['title'])) {
|
||||
$product['title'] = $product->note['title'];
|
||||
}
|
||||
|
||||
if (!empty($product->note['vat'])) {
|
||||
$product['vat'] = getVal('vat', $product->note, 0);
|
||||
}
|
||||
|
||||
if (!empty($product->note['piece_price'])) {
|
||||
$product->priceRaw = toDecimal($product->note['piece_price']);
|
||||
}
|
||||
}
|
||||
$price = $product->getPrice($IDvariation, $product->note, $dec_Pieces);
|
||||
|
||||
$product->discount = getVal('discount', $product->note, $row['discount']);
|
||||
|
||||
// nove promenne s cenou
|
||||
$priceArray = formatCustomerPrice($price, (float) $product->discount, getVat($row['vat']), $product->id);
|
||||
|
||||
$price_with_vat_rounded = roundPrice($priceArray['value_with_vat']);
|
||||
$price_without_vat_rounded = calcPrice($price_with_vat_rounded, -getVat($row['vat']));
|
||||
$item_price_with_vat = $price_with_vat_rounded->mul($dec_Pieces);
|
||||
$item_price_without_vat = calcPrice($item_price_with_vat, -getVat($row['vat']));
|
||||
$totalPriceArray = formatPrice($item_price_without_vat, getVat($row['vat']));
|
||||
|
||||
/* TODO rozbije to automotovelo - zaokrouhlovani na cely cisla, 122 * 3pcs -10% sleva */
|
||||
$priceArray['value_without_vat'] = $price_without_vat_rounded;
|
||||
|
||||
$product->price = $priceArray;
|
||||
$product->totalPrice = $totalPriceArray;
|
||||
// celkova cena bez DPH
|
||||
$this->totalPriceNoVat = $this->totalPriceNoVat->add($price_without_vat_rounded->mul($dec_Pieces));
|
||||
|
||||
// celkova cena s DPH
|
||||
$this->totalPriceWithVat = $this->totalPriceWithVat->add($price_with_vat_rounded->mul($dec_Pieces));
|
||||
|
||||
$vat = $row['vat'];
|
||||
|
||||
// ceny podle DPH, vlozit cenu s DPH
|
||||
if (!isset($this->priceByVat[$vat])) {
|
||||
$this->priceByVat[$vat] = DecimalConstants::zero();
|
||||
}
|
||||
|
||||
$this->priceByVat[$vat] = $this->priceByVat[$vat]->add($price_without_vat_rounded->mul($dec_Pieces));
|
||||
|
||||
// zapocitat celkovy pocet kusu
|
||||
$this->totalPieces += $row['pieces'];
|
||||
|
||||
$this->products[$product->cart_item_id] = $product;
|
||||
}
|
||||
sqlFreeResult($SQL);
|
||||
}
|
||||
|
||||
public static function findDeliveryTypeByPayMethod($id_method)
|
||||
{
|
||||
switch ($id_method) {
|
||||
case Payment::METHOD_CASH:
|
||||
$payment_class = 'Hotovost';
|
||||
break;
|
||||
case Payment::METHOD_CARD:
|
||||
$payment_class = 'PlatebniKarta';
|
||||
break;
|
||||
case Payment::METHOD_INVOICE:
|
||||
$payment_class = 'Prevodem';
|
||||
break;
|
||||
default:
|
||||
throw new Exception('POS: undefined pay method !!');
|
||||
}
|
||||
|
||||
$delivery_type = sqlQueryBuilder()
|
||||
->select("dt.id as id, CONCAT_WS(' - ', dtp.name, dtd.name) as name")
|
||||
->from('delivery_type', 'dt')
|
||||
->join('dt', 'delivery_type_delivery', 'dtd', 'dt.id_delivery = dtd.id AND dtd.class = :delivery_class')
|
||||
->join('dt', 'delivery_type_payment', 'dtp', 'dt.id_payment = dtp.id AND dtp.class = :payment_class')
|
||||
->setParameters([
|
||||
'payment_class' => $payment_class,
|
||||
'delivery_class' => 'OsobniOdber',
|
||||
])
|
||||
->execute()
|
||||
->fetchAll();
|
||||
|
||||
if (!$delivery_type) {
|
||||
throw new Exception('POS: id_delivery_type not found!!');
|
||||
}
|
||||
|
||||
return $delivery_type[0];
|
||||
}
|
||||
|
||||
// Order Submission
|
||||
public function submitOrder($languageID = null)
|
||||
{
|
||||
global $cfg, $ctrl, $dbcfg, $adminID;
|
||||
|
||||
$error = $this->checkCart();
|
||||
|
||||
if (empty($error)) {
|
||||
$order = new Order();
|
||||
|
||||
sqlStartTransaction();
|
||||
|
||||
$fields = [
|
||||
'id_user' => null,
|
||||
'order_no' => '_'.rand(0, 999999),
|
||||
'status' => 0,
|
||||
'note_user' => $this->note,
|
||||
'invoice_name' => 'Zákazník',
|
||||
'delivery_type' => 'Kamenný obchod',
|
||||
'date_created' => date('Y-m-d H:i'),
|
||||
'date_updated' => date('Y-m-d H:i'),
|
||||
'source' => OrderInfo::ORDER_SOURCE_POS,
|
||||
'id_delivery' => $this->transport,
|
||||
];
|
||||
|
||||
$SQL = $this->insertSQL('orders', $fields);
|
||||
// TODO: non null - ["invoice_firm", "invoice_ico", "invoice_dic", "delivery_firm", "note_user", "invoice_country", "delivery_country"]
|
||||
|
||||
if ($SQL) {
|
||||
// ID nove ulozene objednavky
|
||||
$IDorder = sqlInsertId();
|
||||
|
||||
// Generate order ID
|
||||
$orderNo = Orders::createOrderNumber($IDorder);
|
||||
|
||||
if (empty($orderNo)) {
|
||||
logError(__FILE__, __LINE__, 'Empty orderNo!');
|
||||
}
|
||||
|
||||
// Store generated order ID
|
||||
$this->updateSQL('orders', [
|
||||
'order_no' => $orderNo,
|
||||
'admin' => $adminID ? $adminID : null,
|
||||
], ['id' => $IDorder]);
|
||||
|
||||
// Create Order object
|
||||
$order->createFromDB($IDorder, true, true, true);
|
||||
|
||||
// Set status indicating order creation
|
||||
$order->status = -1;
|
||||
|
||||
// ulozit vybrane zbozi do objednavky
|
||||
$products = [];
|
||||
|
||||
$cfg['Order']['hideCode'] = true;
|
||||
foreach ($this->products as $product) {
|
||||
$products[] = $product;
|
||||
|
||||
$discount = getVal('discount', $product->note, 0);
|
||||
|
||||
$fields = [
|
||||
'discount' => $discount,
|
||||
];
|
||||
|
||||
if (empty($product->id)) {
|
||||
$res = $order->insertNonItem(
|
||||
$order->id,
|
||||
$product->price['value_without_vat']->mul(toDecimal($product->pieces)),
|
||||
$product->price['value_without_vat'],
|
||||
$product->pieces,
|
||||
$product->price['vat'],
|
||||
$product['title']
|
||||
);
|
||||
} else {
|
||||
$res = $order->insertItem($product->id, $product->id_variation, $product->pieces, '', false);
|
||||
$fields['piece_price'] = $product->price['value_without_vat'];
|
||||
$fields['total_price'] = $product->price['value_without_vat']->mul(toDecimal($product->pieces));
|
||||
$dispatcher = ServiceContainer::getService('event_dispatcher');
|
||||
$event = $dispatcher->dispatch(
|
||||
new OrderItemEvent($product, $product->id_variation, null, $product->pieces, null, $order),
|
||||
OrderItemEvent::ITEM_UPDATED
|
||||
);
|
||||
}
|
||||
|
||||
$this->updateSQL('order_items',
|
||||
$fields, ['id' => $res]);
|
||||
|
||||
if (false === $res) {
|
||||
logError(__FILE__, __LINE__, "Order->insertItem failed: insertItem({$product->id}, {$product->id_variation}, {$product->pieces}, {$product->note}) cart item: {$product->cart_item_id}");
|
||||
|
||||
$_REQUEST['IDp'] = $product->id;
|
||||
|
||||
return 31;
|
||||
}
|
||||
|
||||
// vymazat zbozi z kosiku
|
||||
$this->deleteSQL('cart', ['id' => $product->cart_item_id]);
|
||||
}
|
||||
|
||||
$this->clear();
|
||||
|
||||
$order->recalculate(true);
|
||||
|
||||
sqlFinishTransaction();
|
||||
|
||||
$order->logHistory('Vytvořeno v pokladně '.date(Settings::getDateFormat().' '.Settings::getTimeFormat(), time()));
|
||||
|
||||
return $order;
|
||||
} else {
|
||||
$error = 2;
|
||||
}
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
|
||||
public function addNonItem($params)
|
||||
{
|
||||
return $this->insertSQL('cart', $params);
|
||||
}
|
||||
|
||||
public function updateNonItem($params)
|
||||
{
|
||||
return $this->updateSQL('cart', ['pieces' => $params['pieces'], 'note' => $params['note']], ['id' => $params['id']]);
|
||||
}
|
||||
|
||||
public static function getVats()
|
||||
{
|
||||
if (!empty($vats)) {
|
||||
return $vats;
|
||||
}
|
||||
|
||||
$SQL = sqlQuery('SELECT id, descr, vat, is_default
|
||||
FROM '.getTableName('vats').'
|
||||
ORDER BY vat DESC ');
|
||||
static $vats = [];
|
||||
|
||||
foreach ($SQL as $key => $row) {
|
||||
$vats[$row['id']] = $row;
|
||||
}
|
||||
|
||||
return $vats;
|
||||
}
|
||||
|
||||
public static function getVatByID($id_vat)
|
||||
{
|
||||
$vats = self::getVats();
|
||||
|
||||
if (!empty($vats[$id_vat]['vat'])) {
|
||||
return $vats[$id_vat]['vat'];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public function getSelectParams($alias = '')
|
||||
{
|
||||
$userKey = self::getCartID();
|
||||
|
||||
return ['user_key' => $userKey];
|
||||
}
|
||||
|
||||
protected function checkCart()
|
||||
{
|
||||
// Check cart is not empty
|
||||
$where = queryCreate($this->getSelectParams(), true);
|
||||
$products = returnSQLResult('SELECT COUNT(c.id)
|
||||
FROM '.getTableName('cart').' AS c
|
||||
LEFT JOIN '.getTableName('products')." AS p ON c.id_product=p.id
|
||||
WHERE {$where}");
|
||||
|
||||
if (0 == intval($products)) {
|
||||
return 12;
|
||||
}
|
||||
|
||||
// Check all items are in store if required
|
||||
return $this->checkCartItems();
|
||||
}
|
||||
|
||||
public function checkCartItems(&$errors = null)
|
||||
{
|
||||
global $dbcfg, $cfg;
|
||||
|
||||
$where = queryCreate($this->getSelectParams(), true);
|
||||
|
||||
$SQL = sqlQuery("SELECT p.id as id_product
|
||||
FROM cart AS c
|
||||
LEFT JOIN products AS p ON c.id_product=p.id
|
||||
LEFT JOIN products_variations pv ON pv.id_product = p.id
|
||||
WHERE {$where} AND c.id_variation IS NULL AND pv.id IS NOT NULL
|
||||
GROUP BY c.id");
|
||||
if (sqlNumRows($SQL) > 0) {
|
||||
logError(__FILE__, __LINE__, 'WARN: Není vybrana varianta');
|
||||
$this->errors[self::$ERR_NOT_SELECTED_VARIATION] = $errors = sqlFetchAll($SQL, ['id_product' => 'id_product']);
|
||||
|
||||
return 31;
|
||||
}
|
||||
|
||||
// Check for products not on stock
|
||||
if (\Settings::ORDER_AVAILABILITY_ALL !== $dbcfg->order_availability) {
|
||||
$where = queryCreate($this->getSelectParams(), true);
|
||||
|
||||
if (findModule('products', 'showMax')) {
|
||||
$where .= ' AND (COALESCE(pv.in_store, p.in_store) < c.pieces OR c.pieces > COALESCE(pv.in_store_show_max, p.in_store_show_max, '.$cfg['Modules']['products']['showMax'].'))';
|
||||
} else {
|
||||
$where .= ' AND COALESCE(pv.in_store, p.in_store) < c.pieces';
|
||||
}
|
||||
|
||||
$failedProducts = sqlFetchAll(sqlQuery("SELECT p.id, pv.id as id_variation
|
||||
FROM cart AS c
|
||||
LEFT JOIN products AS p ON c.id_product=p.id
|
||||
LEFT JOIN products_variations AS pv ON c.id_variation=pv.id
|
||||
WHERE {$where} AND p.id IS NOT NULL"),
|
||||
['id' => 'id_variation']);
|
||||
|
||||
if (count($failedProducts) > 0) {
|
||||
$this->errors[self::$ERR_OUT_OF_STOCK] = $errors = $failedProducts;
|
||||
|
||||
return 30;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getPurchaseState(): PurchaseState
|
||||
{
|
||||
$cart = clone $this;
|
||||
$cart->products = array_filter($cart->products, function ($product) {
|
||||
return !empty($product['product']);
|
||||
});
|
||||
|
||||
return $this->purchaseUtil->createStateFromCart($cart)->setSource(OrderInfo::ORDER_SOURCE_POS);
|
||||
}
|
||||
}
|
||||
|
||||
class POSInternalException extends Exception
|
||||
{
|
||||
}
|
||||
|
||||
if (empty($subclass)) {
|
||||
class PosCart extends PosCartBase
|
||||
{
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user