初始上传

This commit is contained in:
2026-04-04 17:27:12 +08:00
parent 4d80d28eb4
commit b7e11774ee
11191 changed files with 1588469 additions and 0 deletions

View File

@@ -0,0 +1,336 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\ordercreate;
use app\model\member\Member;
use app\model\member\MemberAddress;
use app\model\store\Store;
use app\model\system\Site;
/**
* 订单创建 可调用的工具类
*/
trait CommonTool
{
/****************************************************************************** 站点 start *****************************************************************************/
/**
* 初始化站点信息
* @return true
*/
public function initSiteData()
{
$site_model = new Site();
$site_condition = array(
['site_id', '=', $this->site_id]
);
$site_info = $site_model->getSiteInfo($site_condition)['data'] ?? [];
$this->site_info = $site_info;
$this->site_name = $site_info['site_name'] ?? '';
return true;
}
/****************************************************************************** 站点 end *****************************************************************************/
/****************************************************************************** 门店 start *****************************************************************************/
/**
* 初始化门店
* @return true
*/
public function initStore()
{
$store_id = $this->param['store_id'] ?? 0;
$store_model = new Store();
if ($store_id == 0) {
// $is_allow_store = false;
// //是否安装门店插件
// //todo 只有存在门店插件,并且开启门店连锁模式,才可以所以传递store_id, 否则就只有门店配送和本地配送就可以接收store_id
// if (addon_is_exit('store')) {
// //查询门店运营插件
// $store_config_model = new \addon\store\model\Config();
// $store_config = $store_config_model->getStoreBusinessConfig($site_id)[ 'data' ][ 'value' ] ?? [];
// if ($store_config[ 'store_business' ] == 'store') {
// $is_allow_store = true;
// }
// }
// if($is_allow_store){
// $store_info = $store_model->getDefaultStore($site_id)[ 'data' ] ?? [];
// $data[ 'store_info' ] = $store_info;
// $data[ 'store_id' ] = $store_info[ 'store_id' ];
// }
} else {
$cashier_type = $this->param['cashier_type'] ?? '';
if ($cashier_type == 'cashier') {
} else {
$is_allow_store = false;
//是否安装门店插件
//todo 只有存在门店插件,并且开启门店连锁模式,才可以所以传递store_id, 否则就只有门店配送和本地配送就可以接收store_id
if (addon_is_exit('store')) {
//查询门店运营插件
$store_config = $this->config('store_business');
if ($store_config['store_business'] == 'store') {
$is_allow_store = true;
}
}
if (!$is_allow_store) {
$delivery_array = $this->param['delivery'] ?? [];
$delivery_type = $delivery_array['delivery_type'] ?? 'express';
if (!in_array($delivery_type, ['local', 'store'])) {
$store_id = 0;
} else {
$store_id = $this->param['delivery']['store_id'] ?? 0;
}
}
}
$this->store_info = $store_model->getStoreInfo([['site_id', '=', $this->site_id], ['store_id', '=', $store_id]])['data'] ?? [];
if (empty($this->store_info)) {
$store_id = 0;
}else{
if($this->store_info['status'] == 0){
if($cashier_type != 'cashier'){
$this->setError(1, '当前门店休息中!');
}
}else{
$delivery_array = $this->param['delivery'] ?? [];
$delivery_type = $delivery_array['delivery_type'] ?? 'express';
if($delivery_type == 'local'){
if(addon_is_exit('store') && $this->store_info['is_o2o'] == 0){
$this->setError(1, '同城配送未开启');
}
if($this->store_info['out_open_date_o2o_pay'] == 0){
$curr_time = time() - strtotime(date('Y-m-d'));
$open_date_config = json_decode($this->store_info['open_date_config'], true);
$o2o_pay = false;
if(!empty($open_date_config)){
foreach($open_date_config as $item){
if($item['start_time'] <= $curr_time && $item['end_time'] >= $curr_time){
$o2o_pay = true;
break;
}
}
}else{
$o2o_pay = true;
}
if(!$o2o_pay){
$this->setError(1, '请在营业时间内下单');
}
}
}
if($delivery_type == 'pickup'){
if(addon_is_exit('store') && $this->store_info['is_pickup'] == 0){
$this->setError(1, '门店自提未开启');
}
}
}
}
$this->delivery['store_info'] = $this->store_info;
$this->store_id = $store_id;
}
return true;
}
/**
* 补齐门店数据
* @return true
*/
public function storeOrderData()
{
$temp_data = [];
$delivery_store_id = $this->delivery['store_id'] ?? 0; //门店id
if ($delivery_store_id > 0) {
$store_model = new Store();
$condition = array(
['store_id', '=', $delivery_store_id],
['site_id', '=', $this->site_id],
);
$store_info = $store_model->getStoreInfo($condition)['data'] ?? [];
if (empty($store_info)) {
$this->setError(1, '当前门店不存在!');
}else if($store_info['status'] == 0){
$this->setError(1, '当前门店休息中');
}else if($store_info['is_pickup'] == 0){
$this->setError(1, '当前门店未开启自提');
} else {
$this->delivery['delivery_store_id'] = $delivery_store_id;
$delivery_store_name = $store_info['store_name'];
$this->delivery['delivery_store_name'] = $delivery_store_name;
$delivery_store_info = array(
'open_date' => $store_info['open_date'],
'full_address' => $store_info['full_address'] . $store_info['address'],
'longitude' => $store_info['longitude'],
'latitude' => $store_info['latitude'],
'telphone' => $store_info['telphone'],
'store_image' => $store_info['store_image'],
'time_type' => $store_info['time_type'],
'time_week' => $store_info['time_week'],
'start_time' => $store_info['start_time'],
'end_time' => $store_info['end_time'],
);
$this->delivery['delivery_store_info'] = json_encode($delivery_store_info, JSON_UNESCAPED_UNICODE);
}
} else {
$this->setError(1, '配送门店不可为空!');
}
return true;
}
/****************************************************************************** 门店 end *****************************************************************************/
/****************************************************************************** 发票 start *****************************************************************************/
/**
* 获取发票信息
* @return true
*/
public function getInovice()
{
$order_config = $this->config('order');
$invoice_status = $order_config['invoice_status'] ?? 0;
$this->invoice['invoice_status'] = $invoice_status;
if ($invoice_status == 1) {
$invoice_content = $order_config['invoice_content'] ?? '';
$invoice_content_array = explode(',', $invoice_content);
$this->invoice['invoice_content_array'] = $invoice_content_array;
$this->invoice['invoice_delivery_money'] = $order_config['invoice_money'] ?? 0;
$this->invoice['invoice_rate'] = $order_config['invoice_rate'] ?? 0;
$this->invoice['invoice_type'] = $order_config['invoice_type'] ?? '1,2';
}
return true;
}
/**
* 计算发票信息
* @return true
*/
public function calculateInvoice()
{
$order_config = $this->config('order');
$invoice_status = $order_config['invoice_status'] ?? 0;
$this->invoice['invoice_status'] = $invoice_status;
$invoice_money = 0;
$invoice_delivery_money = 0;
if ($invoice_status == 1) {
$is_invoice = $this->param['is_invoice'] ?? 0;
//是否需要发票
if ($is_invoice) {
$real_goods_money = $this->goods_money - $this->promotion_money - $this->coupon_money - $this->point_money;
$invoice_money = round($real_goods_money * $this->invoice['invoice_rate'] / 100, 2);
$invoice_type = $this->param['invoice_type'] ?? 1;
$this->invoice = [
'invoice_title_type' => $this->param['invoice_title_type'],
'is_tax_invoice' => $this->param['is_tax_invoice'],
'taxpayer_number' => $this->param['taxpayer_number'],
'invoice_title' => $this->param['invoice_title'],
'invoice_type' => $this->param['invoice_type'],
'invoice_content' => $this->param['invoice_content'],
'invoice_rate' => $order_config['invoice_rate'],
];
if ($invoice_type == 1) {
$invoice_delivery_money = $order_config['invoice_money'];
//未定义发票收货地址的话,会默认使用收发货地址
if (empty($this->param['invoice_full_address'])) {
if ($this->delivery['delivery_type'] == 'express' || $this->delivery['delivery_type'] == 'local') {
$invoice_full_address = $this->delivery['member_address']['full_address'] . $this->delivery['member_address']['address'];
} else if ($this->delivery['delivery_type'] == 'store') { //门店
$delivery_store_info = json_decode($this->delivery['delivery_store_info'], true);
$invoice_full_address = $delivery_store_info['full_address'];
}
} else {
$invoice_full_address = $this->param['invoice_full_address'] ?? '';
}
$this->invoice['invoice_full_address'] = $invoice_full_address ?? '';
} else {
if (empty($this->param['invoice_email'])) {
$this->setError(1, '发票邮箱不能为空!');
} else {
$this->invoice['invoice_email'] = $this->param['invoice_email'];
}
}
if (empty($this->param['invoice_title']) || empty($this->param['invoice_type']) || empty($this->param['invoice_content'] || $this->param['invoice_title_type'] == 0)) {
$this->setError(1, '发票相关项不能为空!');
}
//企业抬头 必须填写税号
if ($this->param['invoice_title_type'] == 2 && empty($this->param['taxpayer_number'])) {
$this->setError(1, '发票相关项不能为空!');
}
}
}
//发票费用和发票邮寄费用
$this->invoice_money = $invoice_money;
$this->invoice_delivery_money = $invoice_delivery_money;
$this->order_money += $this->invoice_money + $this->invoice_delivery_money;
return true;
}
/****************************************************************************** 发票 end *****************************************************************************/
/****************************************************************************** 杂项 start *****************************************************************************/
/**
* 初始化收货地址
* @return true
*/
public function initMemberAddress()
{
$delivery_type = $this->param['delivery']['delivery_type'] ?? '';
if (empty($this->param['delivery']['member_address'])) {
$member_address = new MemberAddress();
$type = 1;
if ($delivery_type == 'local') {
$type = 2;
}
$this->delivery['member_address'] = $member_address->getMemberAddressInfo([['member_id', '=', $this->member_id], ['is_default', '=', 1], ['type', 'in', $type]])['data'];
} else {
$this->delivery['member_address'] = $this->param['delivery']['member_address'];
}
if (!empty($this->delivery['member_address'])) {
if ($delivery_type == 'local') {
//外卖订单 如果收货地址没有定位的话,就不取用地址
$type = $this->delivery['member_address']['type'] ?? 1;
if ($type == 1) {
$this->delivery['member_address'] = [];
}
}
}
return true;
}
/**
* 初始化会员账户
* @return true
*/
public function initMemberAccount()
{
$member_model = new Member();
$member_info = $member_model->getMemberDetail($this->member_id, $this->site_id)['data'] ?? [];
if (!empty($member_info)) {
if (!empty($member_info['pay_password'])) {
$is_pay_password = 1;
} else {
$is_pay_password = 0;
}
unset($member_info['pay_password']);
$member_info['is_pay_password'] = $is_pay_password;
$this->member_account = $member_info;
//初始化会员等级
$this->member_level = model('member_level')->getInfo([
['level_id', '=', $this->member_account['member_level']]
]);
}
return true;
}
/****************************************************************************** 杂项 end *****************************************************************************/
}

View File

@@ -0,0 +1,444 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\ordercreate;
use app\model\express\Express;
use app\model\express\Local;
use app\model\store\Store;
/**
* 订单创建 可调用的工具类
*/
trait DeliveryTool
{
/**
* 获取配送配置数据
* @return true
*/
public function getDeliveryData()
{
$curr_store_id = $this->param['store_id'] ?? 0;
$jielong_id = $this->param['jielong_id'] ?? 0;
$express_type = [];
if ($this->is_virtual == 0) {
//todo 没有活动才会参与计算
if (empty($this->promotion_type)) $trade_result = event('OrderCreateCommonData', ['type' => 'trade', 'order_object' => $this], true);
if (!empty($trade_result)) {
if ($trade_result['code'] >= 0) {
$express_type = $trade_result['data'];
}
} else {
$deliver_type_sort = $this->config('delivery_type_sort');
$deliver_sort_list = explode(',', $deliver_type_sort['value']['deliver_type']);
//根据当前的定位查询本地配送门店或自提门店
$latitude = $this->param['latitude'] ?? 0;
$longitude = $this->param['longitude'] ?? 0;
foreach ($deliver_sort_list as $type) {
// 物流
if ($type == 'express') {
$express_config = $this->config('express');
if ($express_config['is_use'] == 1) {
$title = $express_config['value']['express_name'];
if ($title == '') {
$title = Express::express_type['express']['title'];
}
$express_type[] = ['title' => $title, 'name' => 'express'];
}
}
// 自提
if ($type == 'store') {
$store_config = $this->config('store');
if ($store_config['is_use'] == 1) {
//根据坐标查询门店
$store_model = new Store();
$store_condition = [
['site_id', '=', $this->site_id],
//['is_pickup', '=', 1],
//['status', '=', 1],
['', 'exp', \think\facade\Db::raw('(is_pickup = 1 && status = 1) or store_id = '.$curr_store_id)],
['is_frozen', '=', 0],
];
//考虑门店库存和上下架,进一步过滤可以选择的门店
$this->getAvailableStoreIds();
if($this->available_store_ids != 'all'){
$store_condition[] = ['store_id', 'in', $this->available_store_ids];
}
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$store_list = $store_model->getLocationStoreList($store_condition, '*', $latlng)['data'] ?? [];
$store_list = $this->currStoreToFirstData($store_list);
$title = $store_config['value']['store_name'];
if ($title == '') {
$title = Express::express_type['store']['title'];
}
$express_type[] = ['title' => $title, 'name' => 'store', 'store_list' => $store_list];
}
}
// 外卖
if ($type == 'local') {
$local_config = $this->config('local');
if ($local_config['is_use'] == 1) {
//查询本店的通讯地址
$title = $local_config['value']['local_name'];
if ($title == '') {
$title = '外卖配送';
}
$store_model = new Store();
$store_condition = [
['site_id', '=', $this->site_id],
];
if (addon_is_exit('store', $this->site_id)) {
//$store_condition[] = ['is_o2o', '=', 1];
//$store_condition[] = ['status', '=', 1];
$store_condition[] = ['', 'exp', \think\facade\Db::raw('(is_o2o = 1 && status = 1) or store_id = '.$curr_store_id)];
$store_condition[] = ['is_frozen', '=', 0];
} else {
$store_condition[] = ['is_default', '=', 1];
}
//考虑门店库存和上下架,进一步过滤可以选择的门店
$this->getAvailableStoreIds();
if($this->available_store_ids != 'all'){
$store_condition[] = ['store_id', 'in', $this->available_store_ids];
}
$latlng = [
'lat' => $latitude,
'lng' => $longitude,
];
$store_list_result = $store_model->getLocationStoreList($store_condition, '*', $latlng);
$store_list = $store_list_result['data'];
$store_list = $this->currStoreToFirstData($store_list);
$express_type[] = ['title' => $title, 'name' => 'local', 'store_list' => $store_list];
}
}
}
}
}
if(!empty($jielong_id)){
//社群接龙只保留门店自提
foreach ($express_type as $key => $value){
if($value['name'] != 'store'){
unset($express_type[$key]);
continue;
}
$store_list = $value['store_list'] ?? [];
if(empty($store_list)){
$this->setError(1, '没有可以自提的门店!');
}
}
$this->jielong_info = model('promotion_jielong')->getInfo([ [ 'jielong_id', '=', $jielong_id ] ], '*');
$express_type = array_values($express_type);
}
$this->delivery['express_type'] = $express_type;
return true;
}
/**
* 配送计算
* @return true
*/
public function calculateDelivery()
{
//整理配送时间格式
$this->getDeliveryTime();
//计算邮费
if ($this->is_virtual == 1) {
//虚拟订单 运费为0
$delivery_money = 0;
$this->delivery['delivery_type'] = '';
} else {
$deliver_type_sort = $this->config('delivery_type_sort');
$deliver_sort_list = explode(',', $deliver_type_sort['value']['deliver_type']);
//查询店铺是否开启快递配送
$express_config = $this->config('express');
//查询店铺是否开启门店自提
$store_config = $this->config('store');
//查询店铺是否开启外卖配送
$local_config = $this->config('local');
//todo 没有活动才会参与计算
if (empty($this->promotion_type)) {
$trade_calc_result = event('OrderCreateCommonData', ['type' => 'trade_calc', 'order_object' => $this, 'deliver_sort_list' => $deliver_sort_list], true);
}
if (empty($trade_calc_result)) {
//如果本地配送开启, 则查询出本地配送的配置
if ($local_config['is_use'] == 1 && isset($this->param['delivery']['store_id'])) {
$local_model = new Local();
$local_info = $local_model->getLocalInfo([['site_id', '=', $this->site_id], ['store_id', '=', $this->param['delivery']['store_id']]])['data'];
$this->delivery['local']['info'] = $local_info;
} else {
$this->delivery['local']['info'] = [];
}
$delivery_array = $this->param['delivery'] ?? [];
$delivery_type = $delivery_array['delivery_type'] ?? 'express';
if ($delivery_type == 'store') {
//门店自提
$delivery_money = 0;
$this->delivery['delivery_type'] = 'store';
if ($store_config['is_use'] == 0) {
$this->setError(1, '门店自提方式未开启!');
}
if (empty($this->param['delivery']['store_id'])) {
$this->setError(1, '门店未选择!');
}
$this->delivery['store_id'] = $this->param['delivery']['store_id'] ?? 0;
$this->storeOrderData();
$this->store_id = $this->param['delivery']['store_id'] ?? 0;
} else {
if (empty($this->delivery['member_address'])) {
$delivery_money = 0;
$this->delivery['delivery_type'] = 'express';
$this->setError(1, '未配置默认收货地址!');
} else {
if ($delivery_type == 'express') {
if ($express_config['is_use'] == 1) {
//物流配送
$express = new Express();
$express_fee_result = $express->calculate(['order_object' => $this]);
if ($express_fee_result['code'] < 0) {
$this->setError(1, $express_fee_result['message']);
$delivery_fee = 0;
} else {
$delivery_fee = $express_fee_result['data']['delivery_fee'];
}
} else {
$this->setError(1, '物流配送方式未开启!');
$delivery_fee = 0;
}
$this->delivery_money = $delivery_fee;
$this->delivery['delivery_type'] = 'express';
} else if ($delivery_type == 'local') {
//外卖配送
$delivery_money = 0;
$this->delivery['delivery_type'] = 'local';
if ($local_config['is_use'] == 0) {
$this->setError(1, '外卖配送方式未开启!');
} else {
if (empty($this->param['delivery']['store_id'])) {
$this->setError(1, '门店未选择!');
}
$this->store_id = $this->param['delivery']['store_id'] ?? 0;
$local_model = new Local();
$local_result = $local_model->calculate(['order_object' => $this]);
$this->delivery['start_money'] = 0;
if ($local_result['code'] < 0) {
$this->delivery['start_money'] = $local_result['data']['start_money_array'][0] ?? 0;
$this->setError($local_result['data']['code'], $local_result['message'], 1);
} else {
$this->delivery_money = $local_result['data']['delivery_money'];
if (!empty($local_result['data']['code'])) {
$this->setError($local_result['data']['code'], $local_result['data']['error'], 1);
}
}
$this->delivery['error'] = $this->error;
$this->delivery['error_msg'] = $this->error_msg;
}
}
}
}
}
//检测门店是否可用
if($this->available_store_ids != 'all' && !empty($this->store_id)){
$available_store_ids = $this->available_store_ids ? explode(',', trim($this->available_store_ids, ',')) : [];
if(!in_array($this->store_id,$available_store_ids)){
$this->setError(1, '所选门店不可用!');
}
}
//是否符合免邮
if ($this->is_free_delivery) {
$this->delivery_money = 0;
}
//重新计算订单总额
$this->getOrderMoney();
}
return true;
}
/**
* 校验商品项的配送方式支持方式
* @param $goods
* @return true
*/
public function checkDeliveryType($goods)
{
$delivery_type = $this->param['delivery']['delivery_type'] ?? '';
if ($delivery_type && strpos($goods['support_trade_type'], $delivery_type) === false) {
$express_type_list = $this->config('delivery_type');
$delivery_type_name = $express_type_list[$delivery_type] ?? '';
$this->error = 1;
$this->error_msg = '有商品不支持' . $delivery_type_name;
}
return true;
}
/**
* 批量校验配送方式
* @return true
*/
public function batchCheckDeliveryType()
{
$delivery_type = $this->param['delivery']['delivery_type'] ?? '';
if (!$this->is_virtual) {
if (!$delivery_type) {
$this->error = 1;
$this->error_msg = '请选择有效的配送方式';
} else {
$express_type_list = $this->config('delivery_type');
$delivery_type_name = $express_type_list[$delivery_type] ?? '';
foreach ($this->goods_list as $v) {
if (strpos($v['support_trade_type'], $delivery_type) === false) {
$this->error = 1;
//$this->error_msg = '商品' . $v['goods_name'] . '不支持' . $delivery_type_name;
$this->error_msg = '部分商品不支持' . $delivery_type_name;
}
}
}
}
return true;
}
/**
* 获取配送时间格式
* @return true
*/
public function getDeliveryTime(){
$delivery_time = $this->param['delivery']['buyer_ask_delivery_time'] ?? [];
$remark = '';
$start_date = $delivery_time['start_date'] ?? '';
$end_date = $delivery_time['end_date'] ?? '';
if($start_date && $end_date){
$start_time = strtotime($start_date);
$end_time = strtotime($end_date);
$start_ymd = date('Y-m-d', $start_time);
$end_ymd = date('Y-m-d', $end_time);
if($start_ymd == $end_ymd){
$remark = $start_ymd.' '.date('H:i:s', $start_time).' ~ '.date('H:i:s', $end_time);
}else{
$remark = $start_date .' ~ '. $end_date;
}
}else if($start_date && !$end_date){
$remark = $start_date;
$start_time = strtotime($start_date);
}else if(!$start_date && $end_date){
$remark = $end_date;
$end_time = strtotime($end_date);
}
if(!empty($this->jielong_id)){
$jielong_info = model('promotion_jielong')->getInfo([ [ 'jielong_id', '=', $this->jielong_id ] ], '*');
if(!empty($jielong_info)){
$start_time = $jielong_info['take_start_time'];
$start_date = date("Y-m-d",$jielong_info['take_start_time']);
$end_time = $jielong_info['take_end_time'];
$end_date = date("Y-m-d",$jielong_info['take_end_time']);
$remark = $start_date.' ~ '.$end_date;
}
}
$this->delivery['buyer_ask_delivery_time'] = [
'start_date' => $start_date,
'start_time' => $start_time ?? '',
'end_date' => $end_date,
'end_time' => $end_time ?? '',
'remark' => $remark
];
return true;
}
/**
* 获取可以购买的门店数据
* @return int[]|string[]
*/
protected function getAvailableStoreIds()
{
if(addon_is_exit('store')){
//要注意是独立库存还是总部库存
$alias = 'sgs';
$join = [
['store s', 'sgs.store_id = s.store_id', 'inner'],
['goods_sku gs', 'sgs.sku_id = gs.sku_id', 'inner'],
];
$condition = [
['sgs.sku_id', 'in', array_column($this->goods_list, 'sku_id')],
['sgs.status', '=', 1],
];
if($this->available_store_ids != 'all'){
$condition[] = ['sgs.store_id', 'in', $this->available_store_ids];
}
$field = "sgs.sku_id,sgs.store_id,IF(s.stock_type = 'store', sgs.stock, gs.stock) as stock";
$store_sku_list = model('store_goods_sku')->getList($condition, $field, '', $alias, $join);
$store_id_data = [];
$sku_num_data = array_column($this->goods_list, 'num','sku_id');
$goods_model = new \app\model\goods\Goods();
foreach($store_sku_list as $store_sku_info){
//如果库存不足尝试库存转换
if($store_sku_info['stock'] < $sku_num_data[$store_sku_info['sku_id']]){
$store_sku_info = $goods_model->goodsStockTransform([$store_sku_info], $store_sku_info['store_id'], 'store')[0];
}
if($store_sku_info['stock'] >= $sku_num_data[$store_sku_info['sku_id']]){
$store_id_data[$store_sku_info['store_id']][$store_sku_info['sku_id']] = $store_sku_info['sku_id'];
}
}
foreach($store_id_data as $store_id=>$data){
if(count($data) < count($sku_num_data)){
unset($store_id_data[$store_id]);
}
}
$this->available_store_ids = array_keys($store_id_data);
$curr_store_id = $this->param['store_id'] ?? 0;
if(!in_array($curr_store_id, $this->available_store_ids)){
$this->available_store_ids[] = $curr_store_id;
}
}
}
/**
* 当前门店排到首位
* @param $store_list
* @return array
*/
protected function currStoreToFirstData($store_list)
{
$curr_store_id = $this->param['store_id'] ?? 0;
$curr_store = null;
foreach($store_list as $key=>$store_info){
if($store_info['store_id'] == $curr_store_id){
$curr_store = $store_info;
unset($store_list[$key]);
}
}
if(!is_null($curr_store)){
array_unshift($store_list, $curr_store);
}
return array_values($store_list);
}
}

View File

@@ -0,0 +1,254 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\ordercreate;
use app\dict\goods\GoodsDict;
use app\model\goods\Goods;
use app\model\order\OrderStock;
use extend\exception\OrderException;
/**
* 订单创建 可调用的工具类
*/
trait GoodsTool
{
/**
* 校验限购
* @return true
*/
public function checkLimitPurchase()
{
if ($this->limit_purchase) {
foreach ($this->limit_purchase as $item) {
//商品长度处理
$goods_name = str_sub($item['goods_name'], 12, true, 'end');
if ($item['min_buy'] > 0 && $item['num'] < $item['min_buy']) {
$this->setError(1, "商品“{$goods_name}{$item['min_buy']}件起售");
break;
}
if ($item['is_limit'] == 1 && $item['max_buy'] > 0) { // 商品做限制购买
if ($item['limit_type'] == 1) { // 单次限制
if ($item['num'] > $item['max_buy']) {
$this->setError(1, "商品“{$goods_name}”每人限购{$item['max_buy']}");
break;
}
} else { // 长期限制
$goods_model = new Goods();
$purchased_num = $goods_model->getGoodsPurchasedNum($item['goods_id'], $this->member_id);
if (($purchased_num + $item['num']) > $item['max_buy']) {
$this->setError(1, "商品“{$goods_name}”每人限购{$item['max_buy']}件,您已购买{$purchased_num}");
break;
}
}
}
}
}
return true;
}
/**
* 计算商品的单价
* @param $goods_info
* @return array
*/
public function getGoodsPrice($goods_info)
{
//判断是否存在限时折扣
$discount_price = $goods_info['discount_price'];
$price = $discount_price;
//计算当前会员的会员购买价
$member_result = $this->getGoodsMemberPrice($goods_info);
if ($member_result['code'] >= 0) {
$member_price = $member_result['data'];
if ($member_price < $price) {
$price = $member_price;
}
}
return $this->success($price);
}
/**
* 获取商品会员价格
* @param $goods_info
* @return array
*/
public function getGoodsMemberPrice($goods_info)
{
if ($this->member_id > 0) {
if (addon_is_exit('memberprice') && !empty($this->member_level)) {
if ($goods_info['is_consume_discount']) {
$price = $goods_info['price'];
if ($goods_info['discount_config'] == 1) {
// 自定义优惠
$goods_info['member_price'] = json_decode($goods_info['member_price'], true);
$value = $goods_info['member_price'][$goods_info['discount_method']][$this->member_account['member_level']] ?? 0;
switch ($goods_info['discount_method']) {
case 'discount':
// 打折
if ($value == 0) {
$member_price = $price;
} else{
$member_price = number_format($price * $value / 10, 2, '.', '');
}
break;
case 'manjian':
if ($value == 0) {
$member_price = $price;
} else{
// 满减
$member_price = number_format($price - $value, 2, '.', '');
}
break;
case 'fixed_price':
if ($value == 0) {
$member_price = $goods_info['price'];
} else{
// 指定价格
$member_price = number_format($value, 2, '.', '');
}
break;
}
} else {
// 默认按会员享受折扣计算
$member_price = number_format($price * $this->member_level['consume_discount'] / 100, 2, '.', '');
}
return $this->success($member_price);
}
}
}
return $this->error();
}
/**
* 商品库存批量转换
* @throws \Exception
*/
public function batchGoodsStockTransform()
{
//自动库存转换
if(addon_is_exit('stock')){
$store_id = $this->param['delivery']['store_id'] ?? $this->param['store_id'];
$transform_model = new \addon\stock\model\stock\Transform();
$transform_stock_data = $transform_model->getGoodsStockTransformData([
'sku_ids' => array_column($this->goods_list, 'sku_id'),
'store_id' => $store_id,
'store_business' => 'store',
]);
foreach ($this->goods_list as $v) {
$goods_class = $v['goods_class'] ?? 0;
if (in_array($goods_class, [GoodsDict::real, GoodsDict::weigh])) {
$transform_data = $transform_stock_data[$v['sku_id']] ?? null;
if(!is_null($transform_data) && $v['stock'] < $v['num'] && $transform_data['transform_stock'] >= $v['num']){
$res = $transform_model->autoGoodsStockTransform([
'transform_data' => $transform_data,
'buy_num' => $v['num'],
'site_id' => $this->site_id,
'store_id' => $store_id,
]);
if($res['code'] < 0) throw new \Exception('库存转换错误:'.$res['message']);
}
}
}
}
}
/**
* 订单项扣除库存
* @return true
*/
public function batchDecOrderGoodsStock()
{
$goods_sku_data = [];
foreach ($this->goods_list as $v) {
$goods_class = $v['goods_class'] ?? 0;
if (in_array($goods_class, [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$goods_sku_data[] = [
'sku_id' => $v['sku_id'],
'num' => $v['num'],
];
}
// $stock_result = $this->skuDecStock($v, $this->store_id);
// if ($stock_result['code'] != 0) throw new OrderException($stock_result['message']);
}
if($goods_sku_data){
$order_stock = new OrderStock();
$stock_result = $order_stock->decOrderSaleStock([
'goods_sku_data' => $goods_sku_data,
'store_id' => $this->store_id,
'create_order_data' => get_object_vars($this)
]);
if ($stock_result['code'] < 0) throw new OrderException($stock_result['message']);
}
return true;
}
/**
* 扣除商品库存
* @param $goods_info
* @param int $store_id
* @return array
*/
public function skuDecStock($goods_info, $store_id = 0)
{
$goods_class = $goods_info['goods_class'] ?? 0;
if (!empty($goods_class)) {
if (in_array($goods_class, [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$order_stock = new OrderStock();
$goods_sku_data = [
[
'sku_id' => $goods_info['sku_id'],
'num' => $goods_info['num']
]
];
$stock_result = $order_stock->decOrderSaleStock([
'goods_sku_data' => $goods_sku_data,
'store_id' => $store_id,
'create_order_data' => get_object_vars($this)
]);
if ($stock_result['code'] < 0) {
return $stock_result;
}
}
}
return $this->success();
}
/**
* 库存校验是否足够
* @return void
*/
public function checkStock(){
$goods_sku_data = [];
foreach ($this->goods_list as $v) {
$goods_class = $v['goods_class'] ?? 0;
if (in_array($goods_class, [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$goods_sku_data[] = [
'sku_id' => $v['sku_id'],
'num' => $v['num'],
'sku_name' => $v['sku_name']
];
}
}
if($goods_sku_data){
$order_stock = new OrderStock();
$order_stock->checkStock([
'goods_sku_data' => $goods_sku_data,
'store_id' => $this->store_id,
'create_order_data' => get_object_vars($this)
]);
}
return true;
}
}

View File

@@ -0,0 +1,934 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\ordercreate;
use addon\coupon\dict\CouponDict;
use addon\coupon\model\Coupon;
use addon\freeshipping\model\Freeshipping;
use addon\manjian\model\Manjian;
use addon\supermember\model\MemberCard;
use addon\supermember\model\MemberLevelOrder;
use app\dict\member_account\AccountDict;
use app\dict\order\OrderPayDict;
use app\model\goods\GoodsCategory as GoodsCategoryModel;
use app\model\member\MemberAccount;
use Exception;
use extend\exception\OrderException;
use think\facade\Db;
/**
* 订单创建 活动优惠项
*/
trait PromotionTool
{
/****************************************************************************** 余额 start *****************************************************************************/
/**
* 使用余额
* @return array
*/
public function useBalance()
{
$balance_config = $this->config('balance');
//扣除余额(统一扣除)
if ($this->balance_money > 0 && $balance_config['balance_show'] == 1) {
$from_type = $this->order_from_type ?: 'order';
$this->pay_type = OrderPayDict::balance;
$balance_money = $this->member_account['balance_money']; //储值余额
$member_balance = $this->member_account['balance']; //现金余额
$member_account_model = new MemberAccount();
$surplus_balance = $this->balance_money;
//优先扣除储值余额
if ($member_balance > 0) {
$real_balance = min($member_balance, $surplus_balance);
$result = $member_account_model->addMemberAccount($this->site_id, $this->member_id, AccountDict::balance, -$real_balance, $from_type, $this->order_id, '订单消费扣除');
if ($result['code'] < 0) throw new OrderException($result['message']);
$surplus_balance -= $real_balance;
}
if ($surplus_balance > 0) {
$result = $member_account_model->addMemberAccount($this->site_id, $this->member_id, AccountDict::balance_money, -$surplus_balance, $from_type, $this->order_id, '订单消费扣除');
if ($result['code'] < 0) throw new OrderException($result['message']);
}
return $result;
}
}
/**
* 计算余额优惠
* @return true
*/
public function calculateBalcnce()
{
//重新计算订单总额
$this->getOrderMoney();
//使用余额
$is_use_balance = $this->param['is_balance'] ?? 0;
if ($is_use_balance > 0) {
//余额付款
$this->member_balance_money = $this->member_account['balance_total'] ?? 0;
if ($this->member_balance_money > 0) {
$temp_order_money = $this->order_money;
if ($temp_order_money <= $this->member_balance_money) {
$balance_money = $temp_order_money;
} else {
$balance_money = $this->member_balance_money;
}
} else {
$balance_money = 0;
}
$this->balance_money = $balance_money;
$this->member_balance_money -= $this->balance_money;//预减少账户余额,还没有实际扣除
$this->pay_money = $this->order_money - $this->balance_money;
} else {
$this->pay_money = $this->order_money;
}
return true;
}
/****************************************************************************** 余额 end *****************************************************************************/
/****************************************************************************** 满额包邮 start *****************************************************************************/
/**
* 满额包邮
* @return true
*/
public function freeShippingCalculate()
{
if (addon_is_exit('freeshipping', $this->site_id)) {
$free_shipping_model = new Freeshipping();
$district_id = $this->delivery['member_address']['district_id'] ?? 0;
$free_result = $free_shipping_model->calculate($this->goods_money, $district_id, $this->site_id);
if ($free_result['code'] >= 0) {
$this->promotion['freeshipping'] = $free_result['data']; //优惠活动 满额包邮
$this->is_free_delivery = true;
}
}
return true;
}
/****************************************************************************** 满额包邮 end *****************************************************************************/
/****************************************************************************** 会员等级 start *****************************************************************************/
/**
* 会员等级免邮
* @return true
*/
public function memberLevelCalculate()
{
if ($this->member_level) {
$is_free_shipping = $this->member_level['is_free_shipping'] ?? 0;
if ($is_free_shipping > 0) {
$this->promotion['member_level'] = $this->member_level; //优惠活动 满额包邮
$this->is_free_delivery = true;
}
}
return true;
}
/****************************************************************************** 会员等级 end *****************************************************************************/
/****************************************************************************** 订单优惠券 start *****************************************************************************/
/**
* 查询可用优惠券
* @return array
* @throws Exception
*/
public function getOrderCouponList()
{
$this->getOrderCache($this->param['order_key']);
$store_id = $this->store_id;
$condition = array(
['member_id', '=', $this->member_id],
['state', '=', 1],
['site_id', '=', $this->site_id],
//只查看线上的
['use_channel', '<>', 'offline'],
['', 'exp', Db::raw("use_store = 'all' or FIND_IN_SET({$store_id}, use_store)")],
);
$member_coupon_model = new Coupon();
$goods_category_model = new GoodsCategoryModel();
$member_coupon_list = $member_coupon_model->getCouponList($condition)['data'];
$coupon_array = [];
foreach ($member_coupon_list as $k => $v) {
switch ($v['goods_type']) {
//全场优惠券
case CouponDict::all:
if ($v['at_least'] <= $this->goods_money) {
$coupon_array[] = $v;
}
break;
//指定商品可用/不可用优惠券
case CouponDict::selected:
case CouponDict::selected_out:
$coupon_goods_array = explode(',', trim($v['goods_ids'], ','));
$least_money = 0;
$is_support = false;
$judge_res = $v['goods_type'] == CouponDict::selected;
foreach ($this->goods_list as $v_goods) {
if (in_array($v_goods['goods_id'], $coupon_goods_array) == $judge_res) {
$least_money += $v_goods['goods_money'];
$is_support = true;
}
}
if ($is_support && $v['at_least'] <= $least_money) {
$coupon_array[] = $v;
}
break;
//指定分类可用/不可用优惠券
case CouponDict::category_selected:
case CouponDict::category_selected_out:
$category_leaf_ids = $goods_category_model->getGoodsCategoryLeafIds($v['goods_ids'])['data'];
$least_money = 0;
$is_support = false;
foreach ($this->goods_list as $v_goods) {
$goods_category_ids = explode(',', trim($v_goods['category_id'], ','));
$array_intersect = array_intersect($category_leaf_ids, $goods_category_ids);
if ($v['goods_type'] == CouponDict::category_selected) {
$judge_res = count($array_intersect) > 0;
} else {
$judge_res = count($array_intersect) == 0;
}
if ($judge_res) {
$least_money += $v_goods['goods_money'];
$is_support = true;
}
}
if ($is_support && $v['at_least'] <= $least_money) {
$coupon_array[] = $v;
}
break;
}
}
if (!empty($coupon_array)) {
array_multisort(array_column($coupon_array, 'money'), SORT_DESC, $coupon_array);
}
return $coupon_array;
}
/**
* 使用优惠券
* @return void
* @throws Exception
*/
public function useCoupon()
{
if ($this->coupon_id > 0 && $this->coupon_money > 0) {
//优惠券处理方案
$member_coupon_model = new Coupon();
$coupon_use_result = $member_coupon_model->useCoupon($this->coupon_id, $this->member_id, $this->order_id); //使用优惠券
if ($coupon_use_result['code'] < 0) {
throw new OrderException('COUPON_ERROR');
}
}
}
/**
* 优惠券活动
* @return true
*/
public function couponPromotion()
{
$coupon_money = 0;
$coupon_id = $this->param['coupon']['coupon_id'] ?? 0;
if ($coupon_id > 0) {
//查询优惠券信息,计算优惠券费用
$coupon_model = new Coupon();
$coupon_info = $coupon_model->getCouponInfo(
[
['coupon_id', '=', $coupon_id],
['site_id', '=', $this->site_id],
['use_channel', '<>', 'offline'],
['', 'exp', Db::raw("use_store = 'all' or FIND_IN_SET({$this->store_id}, use_store)")],
], '*')['data'] ?? [];
$is_coupon = false;
$coupon_goods_money = 0;
$goods_list = $this->goods_list;
if (empty($coupon_info)) {
$this->setError(1, '优惠券不存在!');
} else if ($coupon_info['member_id'] == $this->member_id && $coupon_info['state'] == 1) {
$goods_category_model = new GoodsCategoryModel();
$coupon_goods_list = [];
switch ($coupon_info['goods_type']) {
//全场通用优惠券
case CouponDict::all:
if ($coupon_info['at_least'] <= $this->goods_money) {
$is_coupon = true;
} else {
$this->setError(1, '优惠券不可用!');
}
$coupon_goods_money = $this->goods_money;
$coupon_goods_list = $goods_list;
$goods_list = [];
break;
//指定商品可用/不可用
case CouponDict::selected:
case CouponDict::selected_out:
// 指定商品
$coupon_goods_ids = explode(',', $coupon_info['goods_ids']);
$temp_money = 0;
$is_support = false;
$judge_res = $coupon_info['goods_type'] == CouponDict::selected;
foreach ($goods_list as $goods_k => $goods_v) {
if (in_array($goods_v['goods_id'], $coupon_goods_ids) == $judge_res) {
$temp_money += $goods_v['goods_money'];
$coupon_goods_list[] = $goods_v;
unset($goods_list[$goods_k]);
$is_support = true;
}
}
if ($is_support && $temp_money >= $coupon_info['at_least']) {
$is_coupon = true;
}
$coupon_goods_money = $temp_money;
break;
//指定分类可用/不可用
case CouponDict::category_selected:
case CouponDict::category_selected_out:
// 指定商品
$coupon_category_ids = $goods_category_model->getGoodsCategoryLeafIds($coupon_info['goods_ids'])['data'];
$temp_money = 0;
$is_support = false;
foreach ($goods_list as $goods_k => $goods_v) {
$goods_category_ids = explode(',', trim($goods_v['category_id'], ','));
$array_intersect = array_intersect($coupon_category_ids, $goods_category_ids);
if ($coupon_info['goods_type'] == CouponDict::category_selected) {
$judge_res = count($array_intersect) > 0;
} else {
$judge_res = count($array_intersect) == 0;
}
if ($judge_res) {
$temp_money += $goods_v['goods_money'];
$coupon_goods_list[] = $goods_v;
unset($goods_list[$goods_k]);
$is_support = true;
}
}
if ($is_support && $temp_money >= $coupon_info['at_least']) {
$is_coupon = true;
}
$coupon_goods_money = $temp_money;
break;
}
}
if ($is_coupon) {
$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($coupon_money, 2);
}
//计算订单项的金额
$temp_goods_list = $this->distributionGoodsCouponMoney($coupon_goods_list, $coupon_goods_money, $coupon_money);
$goods_list = array_merge($goods_list, $temp_goods_list);
$this->goods_list = $goods_list;
} else {
$this->setError(1, '优惠券不可用!');
}
}
if ($coupon_money > 0) {
if ($coupon_money > $this->order_money) {
$coupon_money = $this->order_money;
}
$this->order_money -= $coupon_money;
$this->coupon_money = $coupon_money;
if ($coupon_id > 0) {
$this->coupon_id = $coupon_id;
}
}
return true;
}
/**
* 按比例摊派优惠券优惠
* @param $goods_list
* @param $goods_money
* @param $coupon_money
* @return mixed
*/
public function distributionGoodsCouponMoney($goods_list, $goods_money, &$coupon_money)
{
$temp_coupon_money = $coupon_money;
$last_key = count($goods_list) - 1;
foreach ($goods_list as $k => $v) {
if ($last_key != $k) {
$item_coupon_money = round($v['real_goods_money'] / $goods_money * $coupon_money, 2);
} else {
$item_coupon_money = $temp_coupon_money;
}
$item_coupon_money = min($item_coupon_money, $v['real_goods_money']);
$temp_coupon_money -= $item_coupon_money;
$goods_list[$k]['coupon_money'] = $item_coupon_money;
$goods_list[$k]['real_goods_money'] -= $item_coupon_money; //真实订单项金额
}
// 如果优惠券没有可抵扣金额
if ($temp_coupon_money == $coupon_money) $coupon_money = 0;
return $goods_list;
}
/****************************************************************************** 订单优惠券 end *****************************************************************************/
/****************************************************************************** 积分 start *****************************************************************************/
/**
* 扣除积分
* @return void
*/
public function usePoint()
{
if ($this->is_point && $this->point > 0) {
$member_account_model = new MemberAccount();
$point_result = $member_account_model->addMemberAccount($this->site_id, $this->member_id, AccountDict::point, -$this->point, 'pointcash', $this->order_id, '订单消费扣除');
if ($point_result['code'] < 0) {
throw new OrderException('积分余额不足');
}
}
}
/**
* 获取订单最大可用积分
* @return true
*/
public function getMaxUsablePoint()
{
$point = 0;
// 获取积分抵现配置
$point_config = $this->config('point');
$config = ['is_use' => $point_config['is_use']];
$config = array_merge($config, $point_config['value']);
$order_money = $this->delivery_money > 0 ? $this->order_money - $this->delivery_money : $this->order_money;
if ($config['is_use']) {
if ($config['is_limit'] == 1 && $order_money < $config['limit']) {
$this->max_usable_point = $point;
return true;
}
$deduction_money = $order_money;
if ($config['is_limit_use'] == 1) {
if ($config['type'] == 0) {
$deduction_money = $config['max_use'];
} else {
$ratio = $config['max_use'] / 100;
$deduction_money = round(($order_money * $ratio), 2);
}
if ($deduction_money > $order_money) {
$deduction_money = $order_money;
}
}
$max_point = round($deduction_money * $config['cash_rate']);
$point = min($max_point, $this->member_account['point']);
}
$this->max_usable_point = $point;
$this->point = $point;
return true;
}
/**
* 计算积分优惠
* @return void
*/
public function calculatePoint()
{
$config = $this->config('point')['value'] ?? [];
if ($this->param['is_point'] && $this->max_usable_point > 0) {
$point_money = round(($this->max_usable_point * (1 / $config['cash_rate'])), 2);
if ($point_money > $this->order_money) {
$point_money = $this->order_money;
}
$this->is_point = 1;
$this->point = $this->max_usable_point;
$this->order_money -= $point_money;
$this->point_money = $point_money;
//计算订单项积分
$this->distributionGoodsPoint();
}
}
/**
* 按比例摊派积分
* @return true
*/
public function distributionGoodsPoint()
{
$temp_point = $this->point;
$temp_point_money = $this->point_money;
$last_key = count($this->goods_list) - 1;
foreach ($this->goods_list as $k => &$v) {
if ($last_key != $k) {
$use_point = round($v['goods_money'] / $this->goods_money * $this->point);
$item_point_money = round($v['goods_money'] / $this->goods_money * $this->point_money, 2);
} else {
$use_point = $temp_point;
$item_point_money = $temp_point_money;
}
$temp_point -= $use_point;
$temp_point_money -= $item_point_money;
$v['use_point'] = $use_point;
$v['point_money'] = $item_point_money;
$real_goods_money = $v['real_goods_money'] - $item_point_money;
$real_goods_money = max($real_goods_money, 0);
$v['real_goods_money'] = $real_goods_money; //真实订单项金额
}
return true;
}
/****************************************************************************** 积分 end *****************************************************************************/
/****************************************************************************** 满减 start *****************************************************************************/
/**
* 满减优惠
* @return true
*/
public function manjianPromotion()
{
//先查询全部商品的满减套餐 进行中
$manjian_model = new Manjian();
$all_info = $manjian_model->getManjianInfo([['manjian_type', '=', 1], ['site_id', '=', $this->site_id], ['status', '=', 1]], 'manjian_name,type,goods_ids,rule_json,manjian_id')['data'];
$goods_list = $this->goods_list;
//存在全场满减(不考虑部分满减情况)
if (!empty($all_info)) {
$discount_array = $this->getManjianDiscountMoney($all_info);
$all_info['discount_array'] = $discount_array;
$all_info['rule'] = json_decode($all_info['rule_json'], true);
//判断有没有优惠
$temp_goods_list = $this->distributionGoodsDiscount($goods_list, $this->goods_money, $discount_array['real_discount_money'], isset($discount_array['rule']['free_shipping']));
$goods_list = $temp_goods_list;
$manjian_list[] = $all_info;
$discount_money = $discount_array['real_discount_money'];
$this->goods_list = $goods_list;
$this->promotion_money += $discount_money;
if (!empty($discount_array['rule'])) {
$this->manjian_rule_list[] = [
'manjian_info' => $all_info,
'rule' => $discount_array['rule'],
'sku_ids' => ''
];
$this->promotion['manjian'] = $manjian_list;
}
} else {
$goods_ids = array_unique(array_column($this->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'];
$show_manjian_list = [];
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;
$sku_ids[] = $goods_item['sku_id'];
unset($goods_list[$goods_k]);
}
}
$discount_array = $this->getManjianDiscountMoney($v, $item_goods_list);
$temp_goods_list = $this->distributionGoodsDiscount($item_goods_list, $item_goods_data['goods_money'], $discount_array['real_discount_money'], isset($discount_array['rule']['free_shipping']), $sku_ids);
$goods_list = array_merge($goods_list, $temp_goods_list);
$manjian_list[$k]['rule'] = json_decode($v['rule_json'], true);
$manjian_list[$k]['discount_array'] = $discount_array;
$discount_money += $discount_array['real_discount_money'];
if (!empty($discount_array['rule'])) {
$this->manjian_rule_list[] = [
'manjian_info' => $v,
'rule' => $discount_array['rule'],
'sku_ids' => $sku_ids
];
//只显示符合条件的满减活动
$show_manjian_list[] = $v;
}
}
$this->promotion['manjian'] = $show_manjian_list;
$this->goods_list = $goods_list;
$this->promotion_money += $discount_money;
}
}
if (!empty($this->promotion['manjian'])) {
foreach ($this->promotion['manjian'] as &$v) {
$discount_array = $v['discount_array'] ?? [];
if ($discount_array) {
$rule = $discount_array['rule'];
if ($rule) {
$coupon_ids = $rule['coupon'] ?? '';
if ($coupon_ids) {
$coupon_ids = explode(',', $coupon_ids);
$coupon_num_arr = explode(',', $rule['coupon_num']);
$coupon_list = (new Coupon())->getCouponTypeList([['coupon_type_id', 'in', $coupon_ids]])['data'] ?? [];
// $coupon_list = array_column($coupon_list, null, 'coupon_type_id');
foreach ($coupon_list as &$coupon_v) {
$item_coupon_type_id = $coupon_v['coupon_type_id'];
$coupon_v['give_num'] = $coupon_num_arr[array_search($item_coupon_type_id, $coupon_ids)] ?? 1;
}
$v['discount_array']['rule']['coupon_list'] = $coupon_list;
}
}
}
}
}
return true;
}
/**
* 满减优惠金额
* @param $manjian_info
* @return array
*/
public function getManjianDiscountMoney($manjian_info, $promotion_goods = [])
{
if (empty($promotion_goods)) {
$goods_money = $this->goods_money;
$value = $manjian_info['type'] == 0 ? $this->goods_money : $this->goods_num;
} else {
$goods_money = array_sum(array_column($promotion_goods, 'goods_money'));
$goods_num = array_sum(array_column($promotion_goods, 'num'));
$value = $manjian_info['type'] == 0 ? $goods_money : $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 distributionGoodsDiscount($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($v['goods_money'] / $goods_money * $discount_money, 2);
} else {
$item_discount_money = $temp_discount_money;
}
$item_discount_money = min($item_discount_money, $v['real_goods_money']);
$temp_discount_money -= $item_discount_money;
$goods_list[$k]['promotion_money'] += $item_discount_money;
$goods_list[$k]['real_goods_money'] -= $item_discount_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;
}
/**
* 记录满减
* @return true
*/
public function createManjian()
{
if (!empty($this->manjian_rule_list)) {
$mansong_data = [];
foreach ($this->manjian_rule_list as $item) {
// 检测是否有赠送内容
if (isset($item['rule']['point']) || isset($item['rule']['coupon'])) {
$mansong_data[] = [
'manjian_id' => $item['manjian_info']['manjian_id'],
'site_id' => $this->site_id,
'manjian_name' => $item['manjian_info']['manjian_name'],
'point' => isset($item['rule']['point']) ? round($item['rule']['point']) : 0,
'coupon' => $item['rule']['coupon'] ?? 0,
'coupon_num' => $item['rule']['coupon_num'] ?? '',
'order_id' => $this->order_id,
'member_id' => $this->member_id,
'order_sku_ids' => !empty($item['sku_ids']) ? implode($item['sku_ids']) : '',
];
}
}
if (!empty($mansong_data)) {
model('promotion_mansong_record')->addList($mansong_data);
}
}
return true;
}
/****************************************************************************** 满减 end *****************************************************************************/
/****************************************************************************** 商品次卡 start *****************************************************************************/
/**
* 查询商品可用次卡
* @return true
*/
public function getMemberGoodsCardPromotion()
{
if (addon_is_exit('cardservice', $this->site_id)) {
$member_card = new \addon\cardservice\model\MemberCard();
$common_card = [];
foreach ($this->goods_list as &$goods_item) {
$sku_id = $goods_item['sku_id'];
$condition = [
['mgci.member_id', '=', $this->member_id],
['mgci.sku_id', '=', $sku_id],
['mgc.status', '=', 1],
['', 'exp', Db::raw("( (mgc.card_type = 'timercard') OR (mgc.card_type = 'oncecard' AND mgci.num > mgci.use_num) OR (mgc.card_type = 'commoncard' AND mgc.total_num > mgc.total_use_num) )")]
];
$card_ids = array_filter(array_map(function ($item) {
if ($item['total_use_num'] >= $item['total_num']) return $item['card_id'];
}, $common_card));
if (!empty($card_ids)) $condition[] = ['mgci.card_id', 'not in', $card_ids];
// 查询可用的卡项
$card_list = $member_card->getCartItemList($condition, 'mgci.item_id,mgci.card_id,mgci.num,mgci.use_num,mgci.member_verify_id,mgc.end_time,mgc.total_num,mgc.total_use_num,mgc.card_type,mgc.goods_name', '', 'mgci', [
['member_goods_card mgc', 'mgc.card_id = mgci.card_id', 'inner'],
])['data'];
if (!empty($card_list)) {
$card_item_id = $this->param['member_goods_card'] && isset($this->param['member_goods_card'][$sku_id]) ? $this->param['member_goods_card'][$sku_id] : 0;
$card_list = array_column($card_list, null, 'item_id');
// 抵扣判断
if (isset($card_list[$card_item_id])) {
$card_item = $card_list[$card_item_id];
$card_id = $card_item['card_id'];
if ($card_item['card_type'] == 'commoncard') {
if (isset($common_card[$card_id])) {
$card_item['num'] = $common_card[$card_id]['total_num'] - $common_card[$card_id]['total_use_num'];
} else {
$card_item['num'] = $card_item['total_num'] - $card_item['total_use_num'];
}
} else if ($card_item['card_type'] == 'timecard') {
$card_item['num'] = $goods_item['num'];
} else {
$card_item['num'] -= $card_item['use_num'];
}
$num = min($card_item['num'], $goods_item['num']);
$promotion_money = round($goods_item['price'] * $num, 2);
//定义商品项的属性
$goods_item['promotion_money'] += $promotion_money;
$goods_item['card_promotion_money'] = $promotion_money;
$goods_item['real_goods_money'] = round($goods_item['real_goods_money'] - $promotion_money, 2);
$goods_item['card_use_num'] = $num;
// 针对通卡进行处理
if ($card_item['card_type'] == 'commoncard') {
if (isset($common_card[$card_id])) {
$common_card[$card_id]['total_use_num'] += $num;
} else {
$common_card[$card_id] = [
'card_id' => $card_id,
'total_num' => $card_item['total_num'],
'total_use_num' => $card_item['total_use_num'] + $num
];
}
}
$this->promotion_money += $promotion_money;
} else {
unset($this->param['member_goods_card'][$sku_id]);
}
$goods_item['member_card_list'] = $card_list;
}
}
//使用的会员卡
$this->member_goods_card = $this->param['member_goods_card'] ?? [];
}
return true;
}
/**
* 使用次卡
* @return true
*/
public function useCard()
{
$this->getOrderGoodsList();
foreach ($this->order_goods_list as $k => $v) {
// 使用次卡
if ($v['card_item_id']) {
$card_use_res = (new \addon\cardservice\model\MemberCard())->cardUse([
'item_id' => $v['card_item_id'],
'num' => $this->goods_list[$k]['card_use_num'],
'type' => 'order',
'relation_id' => $v['order_goods_id'],
'store_id' => $this->store_id
]);
if ($card_use_res['code'] != 0) throw new OrderException($card_use_res['message']);
}
}
return true;
}
/**
* 获取会员卡商品价格
* @param $goods_sku_info
* @return array
*/
public function getMemberCardGoodsPrice($goods_sku_info)
{
$res = [
'discount_price' => 0, // 折扣价(默认等于单价)
'member_price' => 0, // 会员价
'price' => 0 // 最低价格
];
$res['discount_price'] = $goods_sku_info['discount_price'];
$res['price'] = $goods_sku_info['discount_price'];
if (!addon_is_exit('memberprice') || empty($this->recommend_member_card)) return $this->success($res);
$level_id = $this->recommend_member_card['level_id'];
if ($goods_sku_info['is_consume_discount']) {
if ($goods_sku_info['discount_config'] == 1) {
// 自定义优惠
$goods_sku_info['member_price'] = json_decode($goods_sku_info['member_price'], true);
$value = $goods_sku_info['member_price'][$goods_sku_info['discount_method']][$level_id] ?? 0;
switch ($goods_sku_info['discount_method']) {
case 'discount':
// 打折
if ($value == 0) {
$res['member_price'] = $goods_sku_info['price'];
} else {
$res['member_price'] = number_format($goods_sku_info['price'] * $value / 10, 2, '.', '');
}
break;
case 'manjian':
if ($value == 0) {
$res['member_price'] = $goods_sku_info['price'];
} else {
// 满减
$res['member_price'] = number_format($goods_sku_info['price'] - $value, 2, '.', '');
}
break;
case 'fixed_price':
if ($value == 0) {
$res['member_price'] = $goods_sku_info['price'];
} else {
// 指定价格
$res['member_price'] = number_format($value, 2, '.', '');
}
break;
}
} else {
// 默认按会员享受折扣计算
$res['member_price'] = number_format($goods_sku_info['price'] * $this->recommend_member_card['consume_discount'] / 100, 2, '.', '');
}
if ($res['member_price'] < $res['price']) {
$res['price'] = $res['member_price'];
}
}
return $this->success($res);
}
/****************************************************************************** 商品次卡 end *****************************************************************************/
/****************************************************************************** 超级会员卡 end *****************************************************************************/
/**
* 获取推荐会员卡
* @return true
*/
public function getRecommendMemberCard()
{
if (!empty($this->member_account)) {
if (addon_is_exit('supermember', $this->site_id)) {
if (!$this->member_account['member_level_type']) {
$store_id = $this->param['store_id'] ?? 0;
//todo 门店线上不参与推荐会员卡关联购买
// if (addon_is_exit('store') && $store_id > 0) {
$member_card_model = new MemberCard();
$recommend_member_card = $member_card_model->getRecommendMemberCard($this->site_id)['data'] ?? [];
if (!empty($recommend_member_card)) {
$recommend_member_card['discount_money'] = 0;
$recommend_member_card['charge_rule'] = json_decode($recommend_member_card['charge_rule'], true);
$this->recommend_member_card = $recommend_member_card;
}
}
// }
}
//是否使用推荐会员卡
$this->recommend_member_card_data['is_open_card'] = $this->param['is_open_card'] ?? 0;
}
return true;
}
/**
* 计算会员卡开卡金额
* @return true
*/
public function calculateMemberCardMoney()
{
$money = 0;
$is_open_card = $this->recommend_member_card_data['is_open_card'] ?? 0;
if (!empty($this->recommend_member_card) && $is_open_card) {
$charge_rule = $this->recommend_member_card['charge_rule'];
$member_card_unit = $this->param['member_card_unit'];
$this->member_card_money = $charge_rule[$member_card_unit] ?? 0;
$this->recommend_member_card_data['member_card_unit'] = $member_card_unit;
}
return true;
}
/**
* 同步创建会员卡订单
* @return true
*/
public function createMemberCard()
{
if (!empty($this->recommend_member_card) && $this->recommend_member_card_data['is_open_card']) {
$member_level_order = new MemberLevelOrder();
$member_card_unit = $this->recommend_member_card_data['member_card_unit'];
$level_order_result = $member_level_order->create(
['out_trade_no' => $this->out_trade_no,
'member_id' => $this->member_id,
'site_id' => $this->site_id,
'level_id' => $this->recommend_member_card['level_id'],
'period_unit' => $member_card_unit
]
);
if ($level_order_result['code'] < 0) throw new OrderException($level_order_result['message']);
$level_order = $level_order_result['data'];
model('order')->update(['member_card_order' => $level_order['order_id']], [['order_id', '=', $this->order_id]]);
}
return true;
}
/****************************************************************************** 超级会员卡 end *****************************************************************************/
}