Files
ZangShiQi/app/model/cart/CartCalculate.php
2026-04-04 17:27:12 +08:00

437 lines
19 KiB
PHP
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\cart;
use addon\coupon\model\Coupon;
use addon\manjian\model\Manjian;
use app\model\goods\Goods;
use app\model\BaseModel;
/**
* 购物车计算
* Class CartCalculate
* @package app\model\cart
*/
class CartCalculate extends BaseModel
{
private $error = 0; //是否有错误
private $error_msg = ''; //错误描述
/**
* 订单计算
* @param $data
* @return mixed
*/
public function calculate($data)
{
$data = $this->getGoodsList($data);
$data = $this->manjianPromotion($data);
$promotion_money = $data[ 'promotion_money' ] ?? 0;
$order_money = $data[ 'goods_money' ] - $promotion_money;
$data[ 'order_money' ] = $order_money;
$data = $this->couponCalculate($data);
return $data;
}
/**
* 获取购物车商品列表信息
* @param $data
* @return mixed
*/
public function getGoodsList($data)
{
$site_id = $data[ 'site_id' ];
$sku_ids = $data[ 'sku_ids' ] ?? [];
$sku_id_list = array_column($sku_ids, 'sku_id');
$member_id = $data[ 'member_id' ];
$sku_num_list = array_column($sku_ids, 'num', 'sku_id');
$goods_model = new Goods();
//组装商品列表
$field = 'ngs.sku_id, ngs.sku_name, ngs.sku_no, ngs.price, ngs.discount_price, ngs.discount_config, ngs.cost_price, ngs.stock, ngs.sku_image,ngs.goods_id,ngs.goods_name,
ngs.site_id, ns.site_name,ngc.cart_id,ngc.num,ngs.is_consume_discount, ngs.member_price, ngs.discount_method';
$alias = 'ngs';
$join = [
[
'site ns',
'ngs.site_id = ns.site_id',
'inner'
],
[ 'goods_cart ngc', 'ngc.sku_id = ngs.sku_id and ngc.member_id = ' . $member_id, 'inner' ]
];
$condition = [
[ 'ngs.sku_id', 'in', $sku_id_list ],
[ 'ngs.site_id', '=', $site_id ]
];
$store_data = $data[ 'store_data' ] ?? [];
$store_id = $data[ 'store_id' ] ?? 0;
// 如果是连锁运营模式
if (!empty($store_data) && $store_data[ 'config' ][ 'store_business' ] == 'store') {
$join[] = [ 'store_goods_sku sgs', 'ngs.sku_id = sgs.sku_id and sgs.store_id=' . $store_id, 'left' ];
$field .= ',IFNULL(sgs.status, 0) as store_goods_status';
$field = str_replace('ngs.price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.price,sgs.price), ngs.price) as price', $field);
$field = str_replace('ngs.discount_price', 'IFNULL(IF(ngs.is_unify_price = 1,ngs.discount_price,sgs.price), ngs.discount_price) as discount_price', $field);
if ($store_data[ 'store_info' ][ 'stock_type' ] == 'store') {
$field = str_replace('ngs.stock', 'IFNULL(sgs.stock, 0) as stock', $field);
}
}
$goods_list = model('goods_sku')->getList($condition, $field, '', $alias, $join);
if (!empty($goods_list)) {
$goods_list = $goods_model->getGoodsListMemberPrice($goods_list, $member_id) ?? [];
foreach ($goods_list as $k => $v) {
$item_num = $sku_num_list[ $v[ 'sku_id' ] ];
$price = $v[ 'price' ];
if (isset($v[ 'member_price' ]) && !empty($v[ 'member_price' ]) && $v[ 'member_price' ] < $v[ 'price' ]) {
$price = $v[ 'member_price' ];
}
$v[ 'price' ] = $price;
$v[ 'goods_money' ] = $price * $item_num;
$v[ 'real_goods_money' ] = $v[ 'goods_money' ];
$v[ 'coupon_money' ] = 0; //优惠券金额
$v[ 'promotion_money' ] = 0; //优惠金额
$v[ 'stock' ] = numberFormat($v[ 'stock' ]);
if (!empty($data[ 'goods_list' ])) {
$data[ 'goods_list' ][] = $v;
$data[ 'goods_num' ] += $item_num;
$data[ 'goods_money' ] += $v[ 'goods_money' ];
} else {
$data[ 'site_id' ] = $site_id;
$data[ 'site_name' ] = $v[ 'site_name' ];
$data[ 'goods_money' ] = $v[ 'goods_money' ];
$data[ 'goods_num' ] = $item_num;
$data[ 'goods_list' ][] = $v;
}
}
}
return $data;
}
/****************************************************************************** 满减 start *****************************************************************************/
/**
* 满减优惠
* @param $data
* @return mixed
*/
public function manjianPromotion($data)
{
$site_id = $data[ 'site_id' ];
$promotion_money = $data[ 'promotion_money' ] ?? 0;
//先查询全部商品的满减套餐 进行中
$manjian_model = new Manjian();
$all_info = $manjian_model->getManjianInfo([ [ 'manjian_type', '=', 1 ], [ 'site_id', '=', $site_id ], [ 'status', '=', 1 ] ], 'manjian_name,type,goods_ids,rule_json,manjian_id')[ 'data' ] ?? [];
$goods_list = $data[ 'goods_list' ];
//存在全场满减(不考虑部分满减情况)
if (!empty($all_info)) {
$discount_array = $this->getManjianDiscountMoney($all_info, $data);
$all_info[ 'discount_array' ] = $discount_array;
$discount_money = $discount_array[ 'real_discount_money' ];
$promotion_money += $discount_money;
if (!empty($discount_array[ 'rule' ])) {
$goods_list = array_map(function($item) use ($all_info) {
$item[ 'promotion' ][ 'manjian' ] = $all_info;
return $item;
}, $goods_list);
}
} else {
$goods_ids = array_unique(array_column($data[ 'goods_list' ], 'goods_id'));
$manjian_condition = array (
[ 'goods_id', 'in', $goods_ids ],
[ 'status', '=', 1 ]
);
$manjian_goods_list = $manjian_model->getManjianGoodsList($manjian_condition, 'manjian_id')[ 'data' ];
if (!empty($manjian_goods_list)) {
$discount_money = 0;
$manjian_goods_list = array_column($manjian_goods_list, 'manjian_id');
$manjian_goods_list = array_unique($manjian_goods_list); //去重
sort($manjian_goods_list);
$manjian_list_result = $manjian_model->getManjianList([ [ 'manjian_id', 'in', $manjian_goods_list ], [ 'status', '=', 1 ] ]);
$manjian_list = $manjian_list_result[ 'data' ];
foreach ($manjian_list as $k => $v) {
$manjian_goods_ids = explode(',', $v[ 'goods_ids' ]);
$item_goods_data = [
'goods_money' => 0,
'goods_num' => 0
];
$item_goods_list = [];
$sku_ids = [];
foreach ($goods_list as $goods_k => $goods_item) {
if (in_array($goods_item[ 'goods_id' ], $manjian_goods_ids)) {
$item_goods_data[ 'goods_money' ] += $goods_item[ 'goods_money' ];
$item_goods_data[ 'goods_num' ] += $goods_item[ 'num' ];
$item_goods_list[] = $goods_item;
array_push($sku_ids, $goods_item[ 'sku_id' ]);
$goods_list[ $goods_k ] = $goods_item;
}
}
$discount_array = $this->getManjianDiscountMoney($v, $item_goods_data);
$manjian_list[ $k ][ 'discount_array' ] = $discount_array;
$discount_money += $discount_array[ 'real_discount_money' ];
if (!empty($discount_array[ 'rule' ])) {
$goods_list = array_map(function($item) use ($sku_ids, $v) {
if (in_array($item[ 'sku_id' ], $sku_ids)) {
$item[ 'promotion' ][ 'manjian' ] = $v;
}
return $item;
}, $goods_list);
}
}
$promotion_money += $discount_money;
}
}
$data[ 'goods_list' ] = $goods_list;
$data[ 'promotion_money' ] = $promotion_money;
return $data;
}
/**
* 满减优惠金额
* @param $manjian_info
* @param $data
* @return array
*/
public function getManjianDiscountMoney($manjian_info, $data)
{
$goods_money = $data[ 'goods_money' ];
$value = $manjian_info[ 'type' ] == 0 ? $data[ 'goods_money' ] : $data[ 'goods_num' ];
//阶梯计算优惠
$rule_item = json_decode($manjian_info[ 'rule_json' ], true);
$discount_money = 0;
$money = 0;
$rule = []; // 符合条件的优惠规则
array_multisort(array_column($rule_item, 'limit'), SORT_ASC, $rule_item); //排序根据num 排序
foreach ($rule_item as $k => $v) {
if ($value >= $v[ 'limit' ]) {
$rule = $v;
if (isset($v[ 'discount_money' ])) {
$discount_money = $v[ 'discount_money' ];
$money = $v[ 'limit' ];
}
}
}
$real_discount_money = min($discount_money, $goods_money);
return [ 'discount_money' => $discount_money, 'money' => $money, 'real_discount_money' => $real_discount_money, 'rule' => $rule ];
}
/**
* 处理商品满减
* @param $goods_list
* @param $goods_money
* @param $discount_money
* @param bool $is_free_shipping
* @param array $sku_ids
* @return mixed
*/
public function distributionGoodsDemiscount($goods_list, $goods_money, $discount_money, $is_free_shipping = false, $sku_ids = [])
{
$temp_discount_money = $discount_money;
$last_key = count($goods_list) - 1;
foreach ($goods_list as $k => $v) {
if ($last_key != $k) {
$item_discount_money = round(floor($v[ 'goods_money' ] / $goods_money * $discount_money * 100) / 100, 2);
} else {
$item_discount_money = $temp_discount_money;
}
$temp_discount_money -= $item_discount_money;
$goods_list[ $k ][ 'promotion_money' ] = $item_discount_money;
$real_goods_money = $v[ 'real_goods_money' ] - $item_discount_money;
$real_goods_money = max($real_goods_money, 0);
$goods_list[ $k ][ 'real_goods_money' ] = $real_goods_money; //真实订单项金额
// 满减送包邮
if ($is_free_shipping) {
if (empty($sku_ids) || in_array($v[ 'sku_id' ], $sku_ids)) {
$goods_list[ $k ][ 'is_free_shipping' ] = 1;
}
}
}
return $goods_list;
}
/****************************************************************************** 满减 end *****************************************************************************/
/****************************************************************************** 订单优惠券 start *****************************************************************************/
/**
* 查询可用优惠券
* @param $data
* @return mixed
*/
public function couponCalculate($data)
{
$site_id = $data[ 'site_id' ];
$member_id = $data[ 'member_id' ];
$goods_money = $data[ 'goods_money' ];//商品总额
$coupon_list = [];
$goods_list = $data[ 'goods_list' ];
// 先查询全场通用的优惠券
$member_coupon_model = new Coupon();
$condition = array (
[ 'member_id', '=', $member_id ],
[ 'state', '=', 1 ],
[ 'site_id', '=', $site_id ]
);
$member_coupon_model = new Coupon();
$member_coupon_list = $member_coupon_model->getCouponList($condition)[ 'data' ];
$coupon_array = [];
foreach ($member_coupon_list as $k => $v) {
//全场优惠券
if ($v[ 'goods_type' ] == 1) {
//检测门槛
if ($v[ 'at_least' ] <= $goods_money) {
$coupon_array[] = $v;
}
continue;
}
//指定商品可用优惠券
if ($v[ 'goods_type' ] == 2) {
$coupon_goods_array = explode(",", $v[ 'goods_ids' ]);
$least_money = 0;
foreach ($goods_list as $k_goods => $v_goods) {
if (in_array($v_goods[ 'goods_id' ], $coupon_goods_array)) {
$least_money += $v_goods[ 'goods_money' ];
}
}
if ($v[ 'at_least' ] <= $least_money) {
$coupon_array[] = $v;
}
continue;
}
if ($v[ 'goods_type' ] == 3) {
$coupon_goods_array = explode(",", $v[ 'goods_ids' ]);
$least_money = 0;
foreach ($goods_list as $k_goods => $v_goods) {
if (!in_array($v_goods[ 'goods_id' ], $coupon_goods_array)) {
$least_money += $v_goods[ 'goods_money' ];
}
}
if ($v[ 'at_least' ] <= $least_money) {
$coupon_array[] = $v;
}
// continue;
}
}
//已领取的优惠券id
$ed_coupon_ids = array_column($coupon_array, 'coupon_type_id');
$ing_coupon_condition = array (
[ 'site_id', '=', $site_id ],
[ 'status', '=', 1 ],
[ 'is_show', '=', 1 ]
);
if (!empty($ed_coupon_ids)) {
$ing_coupon_condition[] = [ 'coupon_type_id', 'not in', $ed_coupon_ids ];
}
$ing_coupon_list = $member_coupon_model->getCouponTypeList($ing_coupon_condition)[ 'data' ] ?? [];
if (!empty($ing_coupon_list)) {
foreach ($ing_coupon_list as $item_k => $item_v) {
$goods_type = $item_v[ 'goods_type' ];
$item_goods_money = 0;
if ($goods_type == 1) {
//全局支持优惠券
$item_goods_money = $goods_money;
} elseif ($goods_type == 2) {
// 指定参与商品
$item_goods_ids = explode(',', $item_v[ 'goods_ids' ]);
$item_goods_money = 0;
foreach ($goods_list as $goods_k => $goods_v) {
if (in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
$item_goods_money += $goods_v[ 'goods_money' ];
}
}
} elseif ($goods_type == 3) {
// continue;
// 指定不参与商品的优惠券
$item_goods_ids = explode(',', $item_v[ 'goods_ids' ]);
// $item_goods_ids = array_diff($goods_ids, $item_goods_ids);
$item_goods_money = 0;
foreach ($goods_list as $goods_k => $goods_v) {
if (!in_array($goods_v[ 'goods_id' ], $item_goods_ids)) {
$item_goods_money += $goods_v[ 'goods_money' ];
}
}
}
if ($item_goods_money >= $item_v[ 'at_least' ]) {
$check_result = $member_coupon_model->checkMemberReceiveCoupon([ 'site_id' => $site_id, 'member_id' => $member_id, 'coupon_type_info' => $item_v ]);
if ($check_result[ 'code' ] >= 0) {//只有还可领取的优惠券才可以
//核验会员是否还可以领取某张优惠券
$item_v[ 'receive_type' ] = 'wait';
$item_v[ 'coupon_goods_money' ] = $item_goods_money;
$coupon_list[] = $this->getCouponPromotionMoney($item_v);
}
}
}
}
//增加查询可以领取的优惠券
$max_coupon_money = 0;
foreach ($coupon_list as $k => $v) {
$item_coupon_money = $v[ 'coupon_money' ] ?? 0;//需修改
if ($item_coupon_money > $max_coupon_money) {
$max_coupon_money = $v[ 'coupon_money' ];
$coupon_info = $v;
}
}
$coupon_money = $coupon_info[ 'coupon_money' ] ?? 0;
if ($coupon_money > 0) {
$data[ 'coupon_info' ] = $coupon_info;
if ($coupon_money > $data[ 'order_money' ]) {
$coupon_money = $data[ 'order_money' ];
}
$data[ 'order_money' ] -= $coupon_money;
$data[ 'coupon_money' ] = $coupon_money;
}
return $data;
}
/**
* 优惠券优惠金额
* @param $coupon_info
* @return mixed
*/
public function getCouponPromotionMoney($coupon_info)
{
$coupon_goods_money = $coupon_info[ 'coupon_goods_money' ];//优惠券支持当前商品的总金额
$coupon_money = 0;
if ($coupon_info[ 'type' ] == 'reward') { //满减优惠券
$coupon_money = min($coupon_info['money'], $coupon_goods_money);
} else if ($coupon_info[ 'type' ] == 'divideticket') { //瓜分优惠券
$coupon_money = min($coupon_info['money'], $coupon_goods_money);
} else if ($coupon_info[ 'type' ] == 'discount') { //折扣优惠券
//计算折扣优惠金额
$coupon_money = $coupon_goods_money * ( 10 - $coupon_info[ 'discount' ] ) / 10;
$coupon_money = $coupon_money > $coupon_info[ 'discount_limit' ] && $coupon_info[ 'discount_limit' ] != 0 ? $coupon_info[ 'discount_limit' ] : $coupon_money;
$coupon_money = min($coupon_money, $coupon_goods_money);
$coupon_money = round(floor($coupon_money * 100) / 100, 2);
}
$coupon_info[ 'coupon_money' ] = $coupon_money;
return $coupon_info;
}
/****************************************************************************** 订单优惠券 end *****************************************************************************/
}