meraproject/module/shop/cart/model.php

604 lines
22 KiB
PHP
Raw Normal View History

<?
namespace shop;
use common\Image;
use core\db\structure\Column as C;
use core\db\structure\eColumnType;
use Mpdf\Tag\P;
use shop\core\structure\shopModuleTable;
use shop\coupon\structure\eShopCouponType;
use shop\item\Growth;
use shop\item\structure\eShopItemPriceType;
use shop\property\Value;
use ui\form\structure\eInputType;
use ui\Form;
use ui\input\Input;
use core\lang\structure\LangVariable as V;
use shop\cart\structure\shopCartLang as Vars;
use shop\cart\Item as ShopItem;
use shop\item\value as ItemValue;
use shop\item\price\Component as PriceComponent;
use shop\Component;
use shop\item\price\variant as PriceVariant;
class Cart extends shopModuleTable {
static $self;
static $table_name = 'shopCart';
static $controller = 'shop.cart';
static $ID = 'id';
static $PORTAL = 'portal';
static $PROFILE = 'profile';
static $KEY = 'key';
static $HASH = 'hash';
static $ORDER = 'order';
static $COUPON_NAME = 'coupon_name';
static $COUPON_VALUE = 'coupon_value';
static $COUPON_TYPE = 'coupon_type';
static $ACCOUNT = 'account';
static $CREATED = 'created';
static $UPDATED = 'updated';
static function getTitle(){return V::get(Vars::$MODULE_NAME);}
static function getSystemLangValues():array{ return Vars::getArray(); }
public function _update(\Where $w, array $values) {
$values[self::$UPDATED] = time();
return parent::_update($w, $values);
}
public static function installUniques() {
//parent::installUniques(); // TODO: Change the autogenerated stub
\DB::addIndex(self::$table_name,self::$PORTAL);
\DB::addIndex(self::$table_name,self::$KEY);
\DB::addIndex(self::$table_name,self::$HASH);
\DB::addIndex(self::$table_name,self::$ORDER);
}
static function setShopItemCount($cid,$count){
$count = floatval($count);
$r = ShopItem::updateById($cid,[ShopItem::$COUNT=>$count]);
$citem = ShopItem::getByID(intval($cid));
$cart = Cart::getByID($citem[ShopItem::$CART]);
if($order_id = intval($cart[Cart::$ORDER])){
Order::remath($order_id);
}
}
static function setShopItemPrice($cid,$price){
$price = floatval($price);
$r = ShopItem::updateById($cid,[ShopItem::$PRICE=>$price]);
$citem = ShopItem::getByID(intval($cid));
$cart = Cart::getByID($citem[ShopItem::$CART]);
if($order_id = intval($cart[Cart::$ORDER])){
Order::remath($order_id);
}
}
static function removeShopItem($cid){
$citem = ShopItem::getByID(intval($cid));
$cart = Cart::getByID($citem[ShopItem::$CART]);
ShopItem::deleteByID($cid);
if($order_id = intval($cart[Cart::$ORDER])){
Order::remath($order_id);
}
}
static function changeComponentCount($cid,$count){
$count = floatval($count);
$res = self::changeCartItem($cid,['component_count'=>$count]);
return $res;
}
static function changePriceComponent($cid,$id){
$res = [];
$id = intval($id);
$C = ShopItem::getByID($cid);
$price = PriceComponent::getByID($id);
if($price[PriceComponent::$ITEM] == $C[ShopItem::$ITEM]) {
$res = self::changeCartItem($cid, ['component_price_id' => $id]);
}
return $res;
}
static function changePropertyValue($cid,$property_id,$value_id){
$property_id = intval($property_id);
$value_id = intval($value_id);
$C = ShopItem::getByID($cid);
$props = json_decode($C[ShopItem::$PROPS],true);
if(!is_array($props)) $props = [];
if($value_id) {
$props[$property_id] = $value_id;
} else {
unset($props[$property_id]);
}
$res = self::changeCartItem($cid, ['props' => $props]);
return $res;
}
static function changeCartItem($cid,$options){
$C = ShopItem::getByID($cid);
$cart = Cart::getByID($C[ShopItem::$CART]);
$order = Order::getByID($cart[Cart::$ORDER]);
$order_id = $order[Order::$ID];
$component_count = isset($options['component_count']) ? cfloatval($options['component_count']) : $C[ShopItem::$COMPONENT_COUNT];
$component_price_id = isset($options['component_price_id']) ? intval($options['component_price_id']) : $C[ShopItem::$COMPONENT_PRICE_ID];
$props = isset($options['props']) ? $options['props'] : json_decode($C[ShopItem::$PROPS],true);
$res = Cart::addToCart(
$C[ShopItem::$CART],
$order[Order::$OID],
$C[ShopItem::$ITEM],
$C[ShopItem::$COUNT],
[
'props' => $props,
'component_count' => $component_count,
'component_price_id' => $component_price_id,
'data' => json_decode($C[ShopItem::$DATA],true),
'getData' => true,
],
$C[ShopItem::$GROWTH]
);
ShopItem::updateById($cid,$res);
Order::remath($order_id);
return $res;
}
static function addToCart($cart_id,$shop_id,$item_id,$count,$options,$growth_id=0){
$item_id = intval($item_id);
$cart_id = intval($cart_id);
$count = floatval($count);
$shop_id = intval($shop_id);
$growth_id = intval($growth_id);
$variant_id = intval($options['variant']);
$component_count = 0;
$component_total = 0;
$component_price = 0;
$cp_id = 0;
$shop = new Shop();
$shop->id_for_theme = $shop_id;
$item = Item::getByID($item_id);
$shop->_getItemPrice($item);
$price = $item[Item::$PRICE];
$initial_price = $item[Item::$PRICE];
$SALE_PERCENT = 1;
$SALE = null;
if($item['sale']){
$SALE_PERCENT = (100-$item['sale']['percent'])/100;
}
if($item['personal_sale']){
$SALE_PERCENT = (100-$item['personal_sale']['percent'])/100;
}
if($item['sale']['sale_id']){
$SALE = Sale::getByID(intval($item['sale']['sale_id']));
}
if($growth_id){
$growth = Growth::getByID($growth_id);
if($growth){
$initial_price = $growth[Growth::$PRICE];
$price = $growth[Growth::$PRICE];
}
}
if($variant_id){
$variant = PriceVariant::getByID($variant_id);
if($variant){
$initial_price = $variant[PriceVariant::$PRICE];
$price = $variant[PriceVariant::$PRICE];
}
}
switch ($item_price = $item[Item::$PRICE_TYPE]) {
case eShopItemPriceType::COMPONENT:
$component = Component::getByID(intval($item[Item::$COMPONENT]));
$component_count = floatval($options['component_count']);
$component_price = floatval($component[Component::$PRICE]);
$component_total = floatval($component[Component::$PRICE]) * $component_count;
$price = $initial_price + $component_total;
break;
case eShopItemPriceType::COMPONENT_LIST:
$cp_id = intval($options['component_price_id']);
$cp = PriceComponent::getByID($cp_id);
$component_count = $cp[PriceComponent::$COUNT];
$price = $cp[PriceComponent::$PRICE];
$initial_price = $cp[PriceComponent::$PRICE];
$component_total = $price;
$component_price = $component_total/$component_count;
break;
case eShopItemPriceType::COMPONENT_MULTI:
$initial_price = $item['price'];
$price = $item['price'];
break;
}
if($options['props']) {
$_keys = array_keys($options['props']);
$keys = [];
foreach ($_keys as $v){
if($v = intval($v)) $keys[] = $v;
}
if($keys){
$r = Property::getByIDS($keys,true);
$values = [];
foreach ($r as $v){
$prop_id = $v[Property::$ID];
$value = intval($options['props'][$prop_id]);
if($v[Property::$IS_PRICE] and $value) {
$values[] = $value;
}
}
if($values) {
$r = ItemValue::getByIDS($values,true);
$total_props_price = [
'item_value'=>0,
'item_percent'=>0,
'component_value'=>0,
'component_percent'=>0,
];
foreach ($r as $v){
$props_price = json_decode($v[ItemValue::$PRICE],true);
switch (intval($props_price['item_type'])){
case 1: $total_props_price['item_value'] += cfloatval($props_price['item_price']); break;
case 2: $total_props_price['item_percent'] += cfloatval($props_price['item_price']); break;
}
switch (intval($props_price['component_type'])){
case 1: $total_props_price['component_value'] += cfloatval($props_price['component_price']); break;
case 2: $total_props_price['component_percent'] += cfloatval($props_price['component_price']); break;
}
}
switch (intval($item[Item::$PRICE_TYPE])){
case eShopItemPriceType::COMPONENT:
//$price -= $component_total;
$component_price = $component_price + $total_props_price['component_value'] + $component_price * $total_props_price['component_percent']/100;
$price = $initial_price + $total_props_price['item_value'] + $initial_price*$total_props_price['item_percent']/100;
$component_total = $component_price*$component_count;
$price += $component_total;
break;
default:
$total_add = $total_props_price['item_value'] + $initial_price*$total_props_price['item_percent']/100;
$price = $initial_price + $total_add;
}
/**/
}
}
}
$price *= $SALE_PERCENT;
$arr = [
ShopItem::$ITEM => $item_id,
ShopItem::$COUNT => $count,
ShopItem::$CART => $cart_id,
ShopItem::$PRICE => $price,
ShopItem::$GROWTH => $growth_id,
ShopItem::$PROPS => je($options['props']),
ShopItem::$DATA => je($options['data']),
ShopItem::$PRICE_TYPE => $item_price,
ShopItem::$BASE_PRICE => $price,
ShopItem::$COMPONENT => $item[Item::$COMPONENT],
ShopItem::$COMPONENT_COUNT => $component_count,
ShopItem::$COMPONENT_TOTAL => $component_total,
ShopItem::$COMPONENT_PRICE_ID => $cp_id,
ShopItem::$SALE_ID => intval($SALE[Sale::$ID]),
ShopItem::$SALE_TYPE => intval($SALE[Sale::$TYPE]),
ShopItem::$SALE_VALUE => intval($SALE[Sale::$VALUE]),
];
if($options['getData']) return $arr;
$r = ShopItem::insert($arr);
return $r;
}
static function clearMy(){
$CART = self::getMyCartData();
if($ids = array_keys($CART['citems'])){
ShopItem::deleteByIDS($ids);
}
}
static function getMyCartData(){ return self::getData(Cart::getMyCartID()); }
static $carts = [];
static function getData($cart_id,$options=[]){
$isCached = boolval($options['cached']);
if($isCached and self::$carts[$cart_id]) return self::$carts[$cart_id];
$cart_id = intval($cart_id);
$total_sale = 0;
$total_base = 0;
$count = 0;
$citems = [];
$items = [];
$cart = Cart::getByID($cart_id);
$isGetProps = boolval($options['props']);
$needProps = [];
$needValues = [];
$r = ShopItem::select([
\Query::LEFT_JOINS => [
[Item::$table_name, ShopItem::$ITEM,Item::$ID ],
[Image::$table_name,Item::$IMAGE, Image::$ID],
[Growth::$table_name,ShopItem::$GROWTH, Growth::$ID],
],
\Query::WHERE => new \Where(
\Where::_operator(ShopItem::$CART,'=',$cart_id)
)
],false);
while($l = \DB::fetch($r)) {
$citems[$l[ShopItem::$ID]] = $l;
$items[$l[Item::$ID]] = $l;
$price = $l[ShopItem::$PRICE] * $l[ShopItem::$COUNT];
if($l[ShopItem::$SALE_ID]){
$total_sale += $price;
} else {
$total_base += $price;
}
$count += $l[ShopItem::$COUNT];
}
$old = $total_sale + $total_base;
// Проверяем, был ли применён купон
if($cart[Cart::$COUPON_NAME]) {
switch ($cart[Cart::$COUPON_TYPE]) {
case eShopCouponType::VALUE:
$total_base -= $cart[Cart::$COUPON_VALUE];
break;
case eShopCouponType::PERCENT:
default:
$total_base *= (100-cfloatval($cart[Cart::$COUPON_VALUE]))/100;
break;
}
}
$total = $total_base + $total_sale;
$res = [
'cart' => $cart,
'citems' => $citems,
'items' => $items,
'total' => $total,
'old' => $old,
'count' => $count,
];
if($isGetProps){
$ids = array_keys($items);
$res['props'] = Shop::getPropsForItems($ids);
}
self::$carts[$cart_id] = $res;
return $res;
}
static function getCookieKeyCart(){ return 'cart_'.\Site::$portal_id; }
static function isProfileInitedCart(){
return (IF_PROFILE || isset( $_COOKIE[self::getCookieKeyCart()] ));
}
static function getCookieKey(){
return 'cart_'.\Site::$portal_id;
}
static function newCartForProfile($PID){
}
static $cookie_id;
static function insertNewCart() {
$key = intval(microtime(true)*10);
$hash = self::getHash($key,\Site::$portal_id);
$r = self::insert([
self::$PORTAL => \Site::$portal_id,
self::$HASH => $hash,
self::$KEY => $key,
self::$PROFILE => PID,
]);
$r->hash = $hash;
$r->key = $key;
return $r;
}
static function getMyCartID(){
if(self::$cookie_id) return self::$cookie_id;
$res = 0;
$cart = null;
$cookie = self::getCookieKey();
if(IF_PROFILE){
$res = intval(\Profile::$data[\Profile::$CART]);
$cart = Cart::getByID($res);
} else {
// Сначала находим корзину по куке
if($hash = $_COOKIE[$cookie]) {
$_cart = self::getOneEqualByColumn(self::$HASH,$hash);
if($_cart){
if($_cart[Cart::$PROFILE]==PID) {
$cart = $_cart;
$res = $cart[self::$ID];
}
}
}
// Для приложений мы можем поискать id в запросе.
if(\Core::$IS_APP){
$hash = $_POST['_cart_hash'];
$_cart = self::getOneEqualByColumn(self::$HASH,$hash);
if($_cart){
if($_cart[Cart::$PROFILE]==PID) {
$cart = $_cart;
$res = $cart[self::$ID];
}
}
}
}
// Если корзина не найдена, то создаём новую
if(!$cart) {
//$key = time();
/*
$key = intval(microtime(true)*10);
$hash = self::getHash($key,\Site::$portal_id);
$r = self::insert([
self::$PORTAL => \Site::$portal_id,
self::$HASH => $hash,
self::$KEY => $key,
self::$PROFILE => PID,
]);
/**/
$r = self::insertNewCart();
$hash = $r->hash;
$key = $r->key;
if(IF_PROFILE){
\Profile::updateById(PID,[
\Profile::$CART => $r->id,
]);
}
\Core::setCookie($cookie,$hash);
$res = $r->id;
}
self::$cookie_id = $res;
return $res;
}
static function getHash($key,$portal_id){
return md5(SALT.SALT.$key.$portal_id.SALT);
}
static function getForm($values = [], $options = []) :array {
return [
self::getCommonFormInputs(),
[
Form::VIEW=>Form::ROW,
Form::COLS => [
[
Form::VIEW =>Form::INPUT,
Form::COL_CLASSES =>'col-12',
Form::KEY_VALUE =>self::$NAME,
Form::TYPE =>eInputType::TEXT,
Form::INPUT_OPT => [
Input::PLACEHOLDER => $c = V::get(Vars::$NAME),
Input::LABEL => $c,
],
],
]
],
self::getCommonFormSubmits($values),
];
}
static function columnInfo() : array {
return [
new C([
C::VAR_NAME =>&self::$ID,
C::TYPE =>eColumnType::INT,
C::AUTO_INCREMENT =>true,
C::PRIMARY =>true,
C::DEFAULT =>0,
C::HIDDEN =>true,
C::TH =>V::get(Vars::$ID),
]),
new C([
C::VAR_NAME => &self::$PORTAL,
C::TYPE => eColumnType::INT,
C::LENGTH => 11,
C::TH => V::get(Vars::$SHOP),
]),
new C([
C::VAR_NAME => &self::$PROFILE,
C::TYPE => eColumnType::INT,
C::LENGTH => 11,
C::TH => V::get(Vars::$PROFILE),
]),
new C([
C::VAR_NAME => &self::$ORDER,
C::TYPE => eColumnType::INT,
C::HIDDEN => true,
C::DEFAULT => 0,
]),
new C([
C::VAR_NAME => &self::$COUPON_NAME,
C::TYPE => eColumnType::TEXT,
C::DEFAULT => '',
C::HIDDEN => true,
]),
new C([
C::VAR_NAME => &self::$COUPON_VALUE,
C::TYPE => eColumnType::DOUBLE,
C::HIDDEN => true,
C::DEFAULT => 0,
]),
new C([
C::VAR_NAME => &self::$COUPON_TYPE,
C::TYPE => eColumnType::TINYINT,
C::HIDDEN => true,
C::DEFAULT => 0,
]),
new C([
C::VAR_NAME => &self::$KEY,
C::TYPE => eColumnType::BIGINT,
C::LENGTH => 11,
C::TH => V::get(Vars::$KEY),
]),
new C([
C::VAR_NAME => &self::$HASH,
C::TYPE => eColumnType::VARCHAR,
C::LENGTH => 32,
C::TH => V::get(Vars::$HASH),
]),
new C([
C::VAR_NAME => &self::$ACCOUNT,
C::TYPE => eColumnType::INT,
C::LENGTH => 11,
C::TH => V::get(Vars::$ACCOUNT),
C::DEFAULT => intval(UID),
c::HIDDEN=>true,
c::FUNC_VALUE => function($v){
if($id = $v[self::$ACCOUNT]) {
return \Account::getName( \Account::getByID($id) );
} else return '-';
},
]),
new C([
C::VAR_NAME => &self::$CREATED,
C::TYPE => eColumnType::INT,
C::LENGTH => 11,
C::TH => V::get(Vars::$CREATED),
C::DEFAULT => time(),
c::FUNC_VALUE => function($v){return self::formatDate($v[self::$CREATED]);},
c::HIDDEN=>true,
]),
new C([
C::VAR_NAME => &self::$UPDATED,
C::TYPE => eColumnType::INT,
C::DEFAULT => time(),
C::TH => V::get(Vars::$UPDATED),
c::FUNC_VALUE => function($v){return self::formatDate($v[self::$UPDATED]);},
c::HIDDEN=>true,
]),
];
}
}
new Cart();
///