HEX
Server: Apache/2.4.6 (CentOS) mpm-itk/2.4.7-04 mod_fcgid/2.3.9 PHP/5.4.16
System: Linux dvm.vladweb.ru 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
User: region-gk.ru (1016)
PHP: 7.3.33
Disabled: NONE
Upload Files
File: //home/temp/yarusvl.ru/api/Orders.php
<?php

require_once('Mgc.php');

class Orders extends Mgc {

    /*Выборка конкретного заказа*/
    public function get_order($id) {
        if (empty($id)) {
            return false;
        }
        if(is_int($id)) {
            $where = $this->db->placehold('AND o.id=? ', intval($id));
        } else {
            $where = $this->db->placehold('AND  o.url=? ', $id);
        }

        $query = $this->db->placehold("SELECT  
                o.*
            FROM __orders o 
            WHERE 
                1 
                $where 
            LIMIT 1
        ");

        if($this->db->query($query)) {
            return $this->db->result();
        } else {
            return false;
        }
    }

    /*Выборка всех заказов*/
    public function get_orders($filter = array()) {
        // По умолчанию
        $limit = 100;
        $page = 1;
        $keyword_filter = '';
        $label_filter = '';
        $status_filter = '';
        $user_filter = '';
        $modified_since_filter = '';
        $id_filter = '';
        $date_filter = '';

        if(isset($filter['limit'])) {
            $limit = max(1, intval($filter['limit']));
        }

        if(isset($filter['page'])) {
            $page = max(1, intval($filter['page']));
        }

        $sql_limit = $this->db->placehold(' LIMIT ?, ? ', ($page-1)*$limit, $limit);

        if(!empty($filter['status'])) {
            $status_filter = $this->db->placehold('AND o.status_id = ?', intval($filter['status']));
        }

        if(isset($filter['id'])) {
            $id_filter = $this->db->placehold('AND o.id in(?@)', (array)$filter['id']);
        }

        if(isset($filter['user_id'])) {
            $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id']));
        }

        if(isset($filter['modified_since'])) {
            $modified_since_filter = $this->db->placehold('AND o.modified > ?', $filter['modified_since']);
        }

        if(isset($filter['label'])) {
            $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']);
        }

        if(!empty($filter['keyword'])) {
            $keywords = explode(' ', $filter['keyword']);
            foreach($keywords as $keyword) {
                $keyword_filter .= $this->db->placehold('AND (
                    o.id = "'.$this->db->escape(trim($keyword)).'" 
                    OR o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" 
                    OR REPLACE(o.phone, "-", "")  LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" 
                    OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" 
                    OR o.email LIKE "%'.$this->db->escape(trim($keyword)).'%"
                    OR o.id in (SELECT order_id FROM __purchases WHERE product_name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR variant_name LIKE "%'.$this->db->escape(trim($keyword)).'%")
                ) ');
            }
        }

        if(!empty($filter['from_date']) || !empty($filter['to_date'])){
                if(!empty($filter['from_date'])){
                    $from = date('Y-m-d',strtotime($filter['from_date']));
                }else{
                    $from = '1970-01-01'; /*если стартовой даты нет, берем время с эпохи UNIX*/
                }
                if(!empty($filter['to_date'])){
                    $to = date('Y-m-d',strtotime($filter['to_date']));
                }else{
                    $to = date('Y-m-d'); /*если конечной даты нет, берем за дату "сегодня"*/
                }
                $date_filter = $this->db->placehold("AND (o.date BETWEEN ? AND ?)",$from,$to);
        }

        // Выбираем заказы
        $query = $this->db->placehold("SELECT 
                o.id, 
                o.delivery_id, 
                o.delivery_price, 
                o.separate_delivery, 
                o.payment_method_id, 
                o.paid, 
                o.payment_date, 
                o.closed, 
                o.discount, 
                o.coupon_code, 
                o.coupon_discount, 
                o.date, 
                o.user_id, 
                o.name, 
                o.address, 
                o.phone, 
                o.email, 
                o.comment, 
                o.status_id, 
                o.url, 
                o.total_price, 
                o.note, 
                o.lang_id,
                os.color as status_color,
u.card,
   
      IF(o.org IS NULL OR o.org = '', u.org, o.org) as org ,
       IF(o.inn IS NULL OR o.inn = '', u.inn, o.inn) as inn ,
      IF(o.file IS NULL OR o.file = '', u.file, o.file) as file 
            FROM __orders AS o
            LEFT JOIN __orders_labels AS ol ON o.id=ol.order_id
            LEFT JOIN __orders_status AS os ON o.status_id=os.id
            LEFT JOIN __users AS u ON u.id=o.user_id
            WHERE 
                1
                $id_filter 
                $status_filter 
                $user_filter 
                $keyword_filter 
                $label_filter 
                $modified_since_filter
                $date_filter
            GROUP BY o.id 
            ORDER BY o.id DESC
            $sql_limit
        ", "%Y-%m-%d");
        $this->db->query($query);
        $orders = array();
        foreach($this->db->results() as $order) {
            $orders[$order->id] = $order;
        }
        return $orders;
    }

    /*Подсчет количества заказов*/
    public function count_orders($filter = array()) {
        $keyword_filter = '';
        $label_filter = '';
        $status_filter = '';
        $user_filter = '';
        $date_filter = '';

        if(!empty($filter['status'])) {
            $status_filter = $this->db->placehold('AND o.status_id = ?', intval($filter['status']));
        }

        if(isset($filter['user_id'])) {
            $user_filter = $this->db->placehold('AND o.user_id = ?', intval($filter['user_id']));
        }

        if(isset($filter['label'])) {
            $label_filter = $this->db->placehold('AND ol.label_id = ?', $filter['label']);
        }

        if(!empty($filter['keyword'])) {
            $keywords = explode(' ', $filter['keyword']);
            foreach($keywords as $keyword) {
                $keyword_filter .= $this->db->placehold('AND (
                    o.id = "'.$this->db->escape(trim($keyword)).'" 
                    OR o.name LIKE "%'.$this->db->escape(trim($keyword)).'%" 
                    OR REPLACE(o.phone, "-", "")  LIKE "%'.$this->db->escape(str_replace('-', '', trim($keyword))).'%" 
                    OR o.address LIKE "%'.$this->db->escape(trim($keyword)).'%" 
                    OR o.email LIKE "%'.$this->db->escape(trim($keyword)).'%"
                    OR o.id in (SELECT order_id FROM __purchases WHERE product_name LIKE "%'.$this->db->escape(trim($keyword)).'%" OR variant_name LIKE "%'.$this->db->escape(trim($keyword)).'%")
                ) ');
            }
        }

        if (!empty($filter['from_date']) || !empty($filter['to_date'])) {
            if (!empty($filter['from_date'])) {
                $from = date('Y-m-d', strtotime($filter['from_date']));
            } else {
                $from = '1970-01-01'; /*если стартовой даты нет, берем время с эпохи UNIX*/
            }
            if (!empty($filter['to_date'])) {
                $to = date('Y-m-d', strtotime($filter['to_date']));
            } else {
                $to = date('Y-m-d'); /*если конечной даты нет, берем за дату "сегодня"*/
            }
            $date_filter = $this->db->placehold("AND (o.date BETWEEN ? AND ?)", $from, $to);
        }

        // Выбираем заказы
        $query = $this->db->placehold("SELECT COUNT(DISTINCT id) as count
            FROM __orders AS o
            LEFT JOIN __orders_labels AS ol ON o.id=ol.order_id
            WHERE 
                1
                $status_filter 
                $user_filter 
                $label_filter 
                $keyword_filter
                $date_filter
        ");
        $this->db->query($query);
        return $this->db->result('count');
    }

    /*Обновление заказа*/
    public function update_order($id, $order) {
        $order = (object)$order;

        $query = $this->db->placehold("UPDATE __orders SET ?% WHERE id=? LIMIT 1", $order, intval($id));
        $this->db->query($query);
        $this->update_total_price(intval($id));
        return $id;
    }

    /*Удаление заказа*/
    public function delete_order($id) {
        if(!empty($id)) {
            $query = $this->db->placehold("DELETE FROM __purchases WHERE order_id=?", $id);
            $this->db->query($query);

            $query = $this->db->placehold("DELETE FROM __orders_labels WHERE order_id=?", $id);
            $this->db->query($query);

            $query = $this->db->placehold("DELETE FROM __orders WHERE id=? LIMIT 1", $id);
            $this->db->query($query);
        }
    }

    /*Добавления заказа*/
    public function add_order($order) {
        $order = (object)$order;
        $order->url = md5(uniqid($this->config->salt, true));
        $set_curr_date = '';
        if(empty($order->date)) {
            $set_curr_date = ', date=now()';
        }
        $all_status = $this->orderstatus->get_status();
        $order->status_id = reset($all_status)->id;
        $query = $this->db->placehold("INSERT INTO __orders SET ?%$set_curr_date", $order);
        $this->db->query($query);
        $id = $this->db->insert_id();
        if(reset($all_status)->is_close == 1){
            $this->orders->close(intval($id));
        } else {
            $this->orders->open(intval($id));
        }

        return $id;
    }

    /*Выборка покупки по его ID*/
    public function get_purchase($id) {
        $query = $this->db->placehold("SELECT * FROM __purchases WHERE id=? LIMIT 1", intval($id));
        $this->db->query($query);
        return $this->db->result();
    }

    /*Выборка списка покупок с заказов*/
    public function get_purchases($filter = array()) {
        $order_id_filter = '';
        if(!empty($filter['order_id'])) {
            $order_id_filter = $this->db->placehold('AND order_id in(?@)', (array)$filter['order_id']);
        }

        $query = $this->db->placehold("SELECT * FROM __purchases WHERE 1 $order_id_filter ORDER BY id");
        $this->db->query($query);
        return $this->db->results();
    }

    /*Обновление покупки(товара)*/
    public function update_purchase($id, $purchase) {
        $purchase = (object)$purchase;
        $old_purchase = $this->get_purchase($id);
        if(!$old_purchase) {
            return false;
        }

        $order = $this->get_order(intval($old_purchase->order_id));
        if(!$order) {
            return false;
        }

        // Не допустить нехватки на складе
        $variant = $this->variants->get_variant($purchase->variant_id);
        if($order->closed && !empty($purchase->amount) && !empty($variant) && !$variant->infinity && $variant->stock<($purchase->amount-$old_purchase->amount)) {
            return false;
        }

        // Если заказ закрыт, нужно обновить склад при изменении покупки
        if($order->closed && !empty($purchase->amount)) {
            if($old_purchase->variant_id != $purchase->variant_id) {
                if(!empty($old_purchase->variant_id)) {
                    $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount, $old_purchase->variant_id);
                    $this->db->query($query);
                }
                if(!empty($purchase->variant_id)) {
                    $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $purchase->amount, $purchase->variant_id);
                    $this->db->query($query);
                }
            } elseif(!empty($purchase->variant_id)) {
                $query = $this->db->placehold("UPDATE __variants SET stock=stock+(?) WHERE id=? AND stock IS NOT NULL LIMIT 1", $old_purchase->amount - $purchase->amount, $purchase->variant_id);
                $this->db->query($query);
            }
        }

        $query = $this->db->placehold("UPDATE __purchases SET ?% WHERE id=? LIMIT 1", $purchase, intval($id));
        $this->db->query($query);
        $this->update_total_price($order->id);
        return $id;
    }

    /*Добавление покупки(товара в заказе)*/
    public function add_purchase($purchase) {
        $purchase = (object)$purchase;

        if(!empty($purchase->variant_id)) {
            $variant = $this->variants->get_variant($purchase->variant_id);

            if(empty($variant)) {
                return false;
            }
            $product = $this->products->get_product(intval($variant->product_id));
            if(empty($product)) {
                return false;
            }
        }

        $order = $this->get_order(intval($purchase->order_id));


        if(empty($order)) {
            return false;
        }


        // Не допустить нехватки на складе
        if($order->closed && !empty($purchase->amount) && !$variant->infinity && $variant->stock<$purchase->amount) {
            return false;
        }

        if(!isset($purchase->product_id) && isset($variant)) {
            $purchase->product_id = $variant->product_id;
        }

        if(!isset($purchase->product_name)  && !empty($product)) {
            $purchase->product_name = $product->name;
        }

        if(!isset($purchase->sku) && !empty($variant)) {
            $purchase->sku = $variant->sku;
        }

        if(!isset($purchase->variant_name) && !empty($variant)) {
            $purchase->variant_name = $variant->name;
        }

        /**
         * SET OPT PRICE ((((
         */
        if(!isset($purchase->price) && !empty($variant)) {
            $purchase->price = $variant->price;
            $num_opt = $this->features->get_option($variant->product_id,25);
            $num_opt = $num_opt->value;
            if(!empty($num_opt) && $purchase->amount>=$num_opt && !empty($variant->opt_price)){
                $purchase->price = $variant->opt_price;
            }
            if(!empty($variant->is_opt) && !empty($variant->opt_price)){
                $purchase->price = $variant->opt_price;
            }


        }

        if(!isset($purchase->amount)) {
            $purchase->amount = 1;
        }

        if(!isset($purchase->units) && !empty($variant)) {
            $purchase->units = $variant->units;
        }


        // Если заказ закрыт, нужно обновить склад при добавлении покупки
        if($order->closed && !empty($purchase->amount) && !empty($variant->id)) {
            $stock_diff = $purchase->amount;
            $query = $this->db->placehold("UPDATE __variants SET stock=stock-? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $variant->id);
            $this->db->query($query);
        }


        $query = $this->db->placehold("INSERT INTO __purchases SET ?%", $purchase);

        $this->db->query($query);
        $purchase_id = $this->db->insert_id();

        $this->update_total_price($order->id);
        return $purchase_id;
    }

    /*Удаление покупки*/
    public function delete_purchase($id) {
        $purchase = $this->get_purchase($id);
        if(!$purchase) {
            return false;
        }

        $order = $this->get_order(intval($purchase->order_id));
        if(!$order) {
            return false;
        }

        // Если заказ закрыт, нужно обновить склад при изменении покупки
        if($order->closed && !empty($purchase->amount)) {
            $stock_diff = $purchase->amount;
            $query = $this->db->placehold("UPDATE __variants SET stock=stock+? WHERE id=? AND stock IS NOT NULL LIMIT 1", $stock_diff, $purchase->variant_id);
            $this->db->query($query);
        }

        $query = $this->db->placehold("DELETE FROM __purchases WHERE id=? LIMIT 1", intval($id));
        $this->db->query($query);
        $this->update_total_price($order->id);
        return true;
    }

    /*Закрытие заказа(списание количества)*/
    public function close($order_id) {
        $order = $this->get_order(intval($order_id));
        if(empty($order)) {
            return false;
        }

        if(!$order->closed) {
            $variants_amounts = array();
            $purchases = $this->get_purchases(array('order_id'=>$order->id));
            foreach($purchases as $purchase) {
                if(isset($variants_amounts[$purchase->variant_id])) {
                    $variants_amounts[$purchase->variant_id] += $purchase->amount;
                } else {
                    $variants_amounts[$purchase->variant_id] = $purchase->amount;
                }
            }

            foreach($variants_amounts as $id=>$amount) {
                $variant = $this->variants->get_variant($id);
                if(empty($variant) || ($variant->stock<$amount)) {
                    return false;
                }
            }
            foreach($purchases as $purchase) {
                $variant = $this->variants->get_variant($purchase->variant_id);
                if(!$variant->infinity) {
                    $new_stock = $variant->stock-$purchase->amount;
                    $this->variants->update_variant($variant->id, array('stock'=>$new_stock));
                }
            }
            $query = $this->db->placehold("UPDATE __orders SET closed=1 WHERE id=? LIMIT 1", $order->id);
            $this->db->query($query);
        }
        return $order->id;
    }

    /*Открытие заказа (возвращение количества)*/
    public function open($order_id) {
        $order = $this->get_order(intval($order_id));
        if(empty($order)) {
            return false;
        }

        if($order->closed) {
            $purchases = $this->get_purchases(array('order_id'=>$order->id));
            foreach($purchases as $purchase) {
                $variant = $this->variants->get_variant($purchase->variant_id);
                if($variant && !$variant->infinity) {
                    $new_stock = $variant->stock+$purchase->amount;
                    $this->variants->update_variant($variant->id, array('stock'=>$new_stock));
                }
            }
            $query = $this->db->placehold("UPDATE __orders SET closed=0 WHERE id=? LIMIT 1", $order->id);
            $this->db->query($query);
        }
        return $order->id;
    }

    /*Обновление итого заказа*/
    private function update_total_price($order_id) {
        $order = $this->get_order(intval($order_id));
        if(empty($order)) {
            return false;
        }

        $query = $this->db->placehold("UPDATE __orders o SET o.total_price=IFNULL((SELECT SUM(p.price*p.amount)*(100-o.discount)/100 FROM __purchases p WHERE p.order_id=o.id), 0)+o.delivery_price*(1-IFNULL(o.separate_delivery, 0))-o.coupon_discount WHERE o.id=? LIMIT 1", $order->id);
        $this->db->query($query);
        return $order->id;
    }

    public function get_neighbors_orders($filter)
    {
        if (empty($filter['id'])) {
            return false;
        }
        $status_filter = '';
        $label_filter = '';

        if(!empty($filter['status'])) {
            $status_filter = $this->db->placehold('AND status_id=?', (int)$filter['status']);
        }

        if(!empty($filter['label'])) {
            $label_filter = $this->db->placehold('INNER JOIN __orders_labels AS ol ON o.id=ol.order_id AND label_id=?', (int)$filter['label']);
        }

        $oids = array();
        $this->db->query("SELECT MIN(o.id) as id
                  FROM __orders o
                  $label_filter
                  WHERE o.id>?
                  $status_filter
                  LIMIT 1", (int)$filter['id']);
        $id = $this->db->result('id');
        $oids[$id] = 'next';

        $this->db->query("SELECT MAX(o.id) as id
                  FROM __orders o
                  $label_filter
                  WHERE o.id<?
                  $status_filter
                  LIMIT 1", (int)$filter['id']);
        $id = $this->db->result('id');
        $oids[$id] = 'prev';

        $result = array('next'=>null, 'prev'=>null);
        if (!empty($oids)) {
            foreach ($this->get_orders(array('id'=>array_keys($oids))) as $o) {
                $result[$oids[$o->id]] = $o;
            }
        }
        return $result;
    }

    public function get_prev_order($id, $status = null)
    {
        $f = '';
        if($status !== null)
            $f = $this->db->placehold('AND status=?', $status);
        $this->db->query("SELECT MAX(id) as id FROM __orders WHERE id<? $f LIMIT 1", $id);
        $prev_id = $this->db->result('id');
        if($prev_id)
            return $this->get_order(intval($prev_id));
        else
            return false;
    }

}