初始上传

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

275
app/model/order/Config.php Executable file
View File

@@ -0,0 +1,275 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\BaseModel;
use app\model\system\Config as ConfigModel;
use app\model\system\Document;
/**
* 订单交易设置
*/
class Config extends BaseModel
{
/**
* 获取订单事件时间设置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderEventTimeConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_EVENT_TIME_CONFIG']]);
if (empty($res['data']['value'])) {
$res['data']['value'] = [
'auto_close' => 30,//订单未付款自动关闭时间 数字 单位(分钟)
'auto_take_delivery' => 14,//订单发货后自动收货时间 数字 单位(天)
'auto_complete' => 7,//订单收货后自动完成时间 数字 单位(天)
'after_sales_time' => 0,//订单完成后可维权时间 数字 单位(天)
'invoice_status' => 0,//发票状态0关闭 1开启
'invoice_rate' => 0,//发票比率0关闭 1开启
'invoice_content' => '',//发内容0关闭 1开启
'invoice_money' => 0,//发票运费0关闭 1开启
];
}
$res['data']['value']['invoice_type'] = $res['data']['value']['invoice_type'] ?? '1,2';
return $res;
}
/**
* 专用于订单事件相关的配置
* @return void
*/
public static function getOrderConfig($site_id = 1){
$config_model = new Config();
$order_config = $config_model->getOrderEventTimeConfig($site_id)['data'] ?? [];
return $order_config['value'] ?? [];
}
/**
* 设置订单事件时间
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setOrderEventTimeConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '订单事件时间设置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_EVENT_TIME_CONFIG']]);
}
/**
* 获取订单返积分设置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderBackPointConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_BACK_POINT_CONFIG']]);
}
/**
* 设置订单返积分
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setOrderBackPointConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '订单返积分设置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_BACK_POINT_CONFIG']]);
}
/**
* 获取订单评价设置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderEvaluateConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_EVALUATE_CONFIG']]);
if (empty($res['data']['value'])) {
$res['data']['value'] = [
'evaluate_status' => 1,//订单评价状态0关闭 1开启
'evaluate_show' => 1,//显示评价0关闭 1开启
'evaluate_audit' => 1,//评价审核状态0关闭 1开启
];
}
return $res;
}
/**
* 设置订单评价设置
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setOrderEvaluateConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '订单事件时间设置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_EVALUATE_CONFIG']]);
}
/**
* 设置余额支付配置
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setBalanceConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '余额支付配置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'BALANCE_SHOW_CONFIG']]);
}
/**
* 获取余额支付配置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getBalanceConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'BALANCE_SHOW_CONFIG']]);
if (empty($res['data']['value'])) {
$res['data']['value'] = [
'balance_show' => 1 //余额支付配置0关闭 1开启
];
}
return $res;
}
/**
* 设置订单提醒配置
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setOrderRemindConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '订单提醒配置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_REMIND_CONFIG']]);
}
/**
* 获取订单提醒配置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderRemindConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_REMIND_CONFIG']]);
$res['data']['value'] = assignData($res['data']['value'], [
'order_pay_audio' => 'public/static/audio/order_pay_remind.mp3',
'cashier_order_pay_audio' => 'public/static/audio/cashier_order_pay_remind.mp3',
]);
return $res;
}
/**
* 获取订单退款配置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderRefundConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_REFUND_CONFIG']]);
$res['data']['value'] = assignData($res['data']['value'], [
'reason_type' => "未按约定时间发货\n拍错/多拍/不喜欢\n协商一致退款\n其他",
'auto_refund'=> $res['data']['value']['auto_refund'] ?? 0
]);
return $res;
}
/**
* 设置订单退款配置
* @param $data
* @param $site_id
* @param string $app_module
* @return array
*/
public function setOrderRefundConfig($data, $site_id, $app_module = 'shop')
{
$config = new ConfigModel();
return $config->setConfig($data, '订单退款配置', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_REFUND_CONFIG']]);
}
/**
* 订单核销设置
* @param $data
* @param $site_id
* @param $app_module
* @return array
*/
public function setOrderVerifyConfig($data, $site_id, $app_module)
{
$config = new ConfigModel();
return $config->setConfig($data, '核销到期提醒', 1, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_VERIFY_CONFIG']]);
}
/**
* 订单核销设置
* @param $site_id
* @param string $app_module
* @return array
*/
public function getOrderVerifyConfig($site_id, $app_module = 'shop')
{
$config = new ConfigModel();
$res = $config->getConfig([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['config_key', '=', 'ORDER_VERIFY_CONFIG']]);
if (empty($res['data']['value'])) {
$res['data']['value'] = [
'order_verify_time_out' => 1,//核销临期提醒时间
];
}
return $res;
}
/**
* 注册协议
* @param $title
* @param $content
* @param $site_id
* @param string $app_module
* @return array
*/
public function setTransactionDocument($title, $content, $site_id, $app_module = 'shop')
{
$document = new Document();
return $document->setDocument($title, $content, [['site_id', '=', $site_id], ['app_module', '=', $app_module], ['document_key', '=', 'TRANSACTION_AGREEMENT']]);
}
/**
* 查询注册协议
* @param $site_id
* @param string $app_module
* @return array
*/
public function getTransactionDocument($site_id, $app_module = 'shop')
{
$document = new Document();
return $document->getDocument([['site_id', '=', $site_id], ['app_module', '=', $app_module], ['document_key', '=', 'TRANSACTION_AGREEMENT']]);
}
}

460
app/model/order/LocalOrder.php Executable file
View File

@@ -0,0 +1,460 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\dict\order_refund\OrderRefundDict;
use app\model\express\LocalPackage;
use app\model\message\Message;
use app\model\system\Pay as PayModel;
use Exception;
use think\facade\Db;
use think\facade\Queue;
/**
* 外卖订单
*
* @author Administrator
*
*/
class LocalOrder extends OrderCommon
{
/*****************************************************************************************订单基础状态(其他使用)********************************/
// 订单待付款
public const ORDER_CREATE = 0;
// 订单已支付(待发货)
public const ORDER_PAY = 1;
// 订单备货中
public const ORDER_PENDING_DELIVERY = 2;
// 订单已发货(配货)
public const ORDER_DELIVERY = 3;
// 订单已收货
public const ORDER_TAKE_DELIVERY = 4;
// 订单已结算完成
public const ORDER_COMPLETE = 10;
// 订单已关闭
public const ORDER_CLOSE = -1;
/***********************************************************************************订单项 配送状态**************************************************/
// 待发货
public const DELIVERY_WAIT = 0;
// 已发货
public const DELIVERY_DOING = 1;
// 已收货
public const DELIVERY_FINISH = 2;
// 订单类型
public $order_type = 3;
/**
* 基础订单状态(不同类型的订单可以不使用这些状态,但是不能冲突)
* @var array
*/
public $order_status = [
self::ORDER_CREATE => [
'status' => self::ORDER_CREATE,
'name' => '待支付',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon.png',
'action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderAddressUpdate',
'title' => '修改地址',
'color' => ''
],
[
'action' => 'orderAdjustMoney',
'title' => '调整价格',
'color' => ''
],
],
'member_action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderPay',
'title' => '支付',
'color' => ''
],
],
'color' => ''
],
self::ORDER_PAY => [
'status' => self::ORDER_PAY,
'name' => '待发货',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-send.png',
'action' => [
[
'action' => 'orderLocalDelivery',
'title' => '发货',
'color' => ''
],
[
'action' => 'orderAddressUpdate',
'title' => '修改地址',
'color' => ''
],
],
'member_action' => [
],
'color' => ''
],
self::ORDER_DELIVERY => [
'status' => self::ORDER_DELIVERY,
'name' => '已发货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-receive.png',
'action' => [
[
'action' => 'takeDelivery',
'title' => '确认收货',
'color' => ''
],
],
'member_action' => [
[
'action' => 'memberTakeDelivery',
'title' => '确认收货',
'color' => ''
],
],
'color' => ''
],
self::ORDER_TAKE_DELIVERY => [
'status' => self::ORDER_TAKE_DELIVERY,
'name' => '已收货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_COMPLETE => [
'status' => self::ORDER_COMPLETE,
'name' => '已完成',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_CLOSE => [
'status' => self::ORDER_CLOSE,
'name' => '已关闭',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-close.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
];
// 配送状态
public $delivery_status = [
self::DELIVERY_WAIT => [
'status' => self::DELIVERY_WAIT,
'name' => '待发货',
'color' => ''
],
self::DELIVERY_DOING => [
'status' => self::DELIVERY_DOING,
'name' => '已发货',
'color' => ''
],
self::DELIVERY_FINISH => [
'status' => self::DELIVERY_FINISH,
'name' => '已收货',
'color' => ''
]
];
/**
* 订单支付
* @param $data
* @return array
*/
public function orderPay($data)
{
$order_info = $data['order_info'];
$pay_type = $data['pay_type'];
$log_data = $data['log_data'] ?? [];
$member_info = $data['member_info'];
if ($order_info['order_status'] != 0) {
return $this->error();
}
$condition = [
['order_id', '=', $order_info['order_id']],
['order_status', '=', self::ORDER_CREATE],
];
$pay_type_list = $this->getPayType();
$data = [
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name'],
'pay_status' => 1,
'order_status_action' => json_encode($this->order_status[self::ORDER_PAY], JSON_UNESCAPED_UNICODE),
'pay_time' => time(),
'is_enable_refund' => 1,
'pay_type' => $pay_type,
'pay_type_name' => $pay_type_list[$pay_type]
];
//记录订单日志 start
$action = '商家对订单进行了线下支付';
//获取用户信息
if (empty($log_data)) {
$log_data = [
'uid' => $order_info['member_id'],
'nick_name' => $member_info['nickname'],
'action_way' => 1
];
$action = '买家支付了订单';
}
$log_data = array_merge($log_data, [
'order_id' => $order_info['order_id'],
'action' => $action,
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name']
]);
OrderLog::addOrderLog($log_data, $this);
//记录订单日志 end
$result = model('order')->update($data, $condition);
return $this->success($result);
}
/**
* 订单项发货(物流)
* @param $param
* @return array
*/
public function orderGoodsDelivery($param)
{
$delivery_no = $param['delivery_no'] ?? '';//物流单号
$delivery_type = $param['delivery_type'] ?? 'default';
$order_id = $param['order_id'] ?? 0;
$site_id = $param['site_id'];
$store_id = $param['store_id'] ?? 0;
$condition = [
['site_id', '=', $site_id],
['order_id', '=', $order_id],
['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]
];
if ($store_id) $condition[] = ['store_id', '=', $store_id];
$order_goods_list = model('order_goods')->getList($condition, '*');
if (empty($order_goods_list)) {
return $this->error('', '发货货物不可为空!');
}
$condition_refund[] = ['', 'exp', Db::raw('(refund_status=' . OrderRefundDict::REFUND_APPLY . ' or refund_status=' . OrderRefundDict::REFUND_CONFIRM . ') and site_id=' . $site_id . ' and order_id=' . $order_id)];
$order_refund_goods_list = model('order_goods')->getList($condition_refund, 'order_goods_id');
// 已退款的订单项不可发货
if ($order_refund_goods_list) {
return $this->error([], 'ORDER_GOODS_IN_REFUND');
}
model('order_goods')->startTrans();
try {
$order_goods_id_array = [];
$goods_id_array = [];
$member_id = 0;
foreach ($order_goods_list as $order_goods_info) {
$order_goods_id_array[] = $order_goods_info['order_goods_id'];
$order_id = $order_goods_info['order_id'];
$member_id = $order_goods_info['member_id'];
$goods_id_array[] = $order_goods_info['sku_id'] . ':' . number_format($order_goods_info['num']) . ':' . $order_goods_info['sku_name'] . ':' . $order_goods_info['sku_image'];
$data = ['delivery_status' => self::DELIVERY_DOING, 'delivery_status_name' => $this->delivery_status[self::DELIVERY_DOING]['name']];
if (!empty($delivery_no)) {
$data['delivery_no'] = $delivery_no;
}
model('order_goods')->update($data, [
['order_goods_id', '=', $order_goods_info['order_goods_id']],
['delivery_status', '=', self::DELIVERY_WAIT]
]);
}
$order_stock_model = new OrderStock();
$order_info = model('order')->getInfo([['order_id', '=', $order_id]]);
$stock_result = $order_stock_model->decOrderStock([
'store_id' => $order_info['store_id'],
'site_id' => $order_info['site_id'],
'goods_sku_list' => $order_goods_list,
'user_info' => $param['user_info'] ?? []
]);
if ($stock_result['code'] < 0) {
model('order_goods')->rollback();
return $stock_result;
}
// 创建包裹
$order_common_model = new OrderCommon();
$lock_result = $order_common_model->verifyOrderLock($order_id);
if ($lock_result['code'] < 0) {
model('order_goods')->rollback();
return $lock_result;
}
$local_delivery_model = new LocalPackage();
$delivery_data = [
'order_id' => $order_id,
'order_goods_id_array' => $order_goods_id_array,
'goods_id_array' => $goods_id_array,
'goods_array' => $goods_id_array,
'site_id' => $site_id,
'delivery_no' => $delivery_no,
'member_id' => $member_id,
'delivery_type' => $delivery_type,
'deliverer' => $param['deliverer'],
'deliverer_mobile' => $param['deliverer_mobile'],
];
$local_delivery_model->delivery($delivery_data);
//检测整体, 订单中订单项是否全部发放完毕
$res = $this->orderCommonDelivery($order_id);
//发送消息 发给配送员
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'MESSAGE_LOCAL_WAIT_DELIVERY', 'param' => $param, 'site_id' => $param['site_id']]);
model('order_goods')->commit();
return $this->success($res);
} catch (Exception $e) {
model('order_goods')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 订单发货
* @param $order_id
* @return array
*/
public function orderDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id], ['order_status', '=', self::ORDER_PAY]], '*');
if (empty($order_info)) return $this->error([], '订单不存在或已发货!');
//统计订单项目
$count = model('order_goods')->getCount([['order_id', '=', $order_id], ['delivery_status', '=', self::DELIVERY_WAIT], ['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id');
// $delivery_count = model('order_goods')->getCount([['order_id', '=', $order_id], ['delivery_status', '=', self::DELIVERY_DOING], ['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id');
// if ($count == 0 && $delivery_count > 0) {
if ($count == 0) {
$site_id = $order_info['site_id'];
model('order')->startTrans();
try {
//修改订单项的配送状态
$order_data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'delivery_status' => self::DELIVERY_FINISH,
'delivery_status_name' => $this->delivery_status[self::DELIVERY_FINISH]['name'],
'order_status_action' => json_encode($this->order_status[self::ORDER_DELIVERY], JSON_UNESCAPED_UNICODE),
'delivery_time' => time()
];
model('order')->update($order_data, [['order_id', '=', $order_id]]);
model('order')->commit();
//订单自动收货
OrderCron::takeDelivery(['order_id' => $order_id, 'site_id' => $site_id]);
// 订单发货完成,小程序发货信息录入,视频号,同城配送不需要验证
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_id, 'site_id' => $site_id]);
//订单发货消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'ORDER_DELIVERY', 'order_id' => $order_id, 'site_id' => $site_id]);
return $this->success();
} catch (Exception $e) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
} else {
return $this->error();
}
}
/**
* 订单收货
* @param $order_id
* @return array
*/
public function orderTakeDelivery($order_id)
{
return $this->success();
}
/**
* 退款完成操作
* @param $order_goods_info
*/
public function refund($order_goods_info)
{
//是否入库
$order_stock_model = new OrderStock();
if ($order_goods_info['is_refund_stock'] == 1) {
$order_stock_model->incOrderStock($order_goods_info);
} else if ($order_goods_info['delivery_status'] == 0) {
$order_stock_model->incOrderSaleStock([
'store_id' => $order_goods_info['store_id'],
'goods_sku_data' => [
[
'sku_id' => $order_goods_info['sku_id'],
'num' => $order_goods_info['num'],
],
],
]);
}
}
/**
* 订单详情
* @param $order_info
* @return array
*/
public function orderDetail($order_info)
{
$local_package_model = new LocalPackage();
$package_info = $local_package_model->package(['order_id' => $order_info['order_id']])['data'] ?? [];
$data['package_list'] = $package_info;
return $data;
}
}

927
app/model/order/Order.php Executable file
View File

@@ -0,0 +1,927 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\electronicsheet\model\ElectronicsheetDelivery;
use app\dict\order_refund\OrderRefundDict;
use app\model\express\ExpressDelivery;
use app\model\express\ExpressPackage;
use app\model\message\Message;
use app\model\system\Cron;
use Exception;
use PhpOffice\PhpSpreadsheet\IOFactory;
use think\facade\Queue;
/**
* 普通(快递)订单
*
* @author Administrator
*
*/
class Order extends OrderCommon
{
/*****************************************************************************************订单状态***********************************************/
// 订单创建
public const ORDER_CREATE = 0;
// 订单已支付
public const ORDER_PAY = 1;
// 订单备货中
public const ORDER_PENDING_DELIVERY = 2;
// 订单已发货(配货)
public const ORDER_DELIVERY = 3;
// 订单已收货
public const ORDER_TAKE_DELIVERY = 4;
// 订单已结算完成
public const ORDER_COMPLETE = 10;
// 订单已关闭
public const ORDER_CLOSE = -1;
// 订单类型
public const DELIVERY_WAIT = 0;
/***********************************************************************************订单项 配送状态**************************************************/
// 待发货
public const DELIVERY_DOING = 1;
// 已发货
public const DELIVERY_FINISH = 2;
// 已收货
public $order_type = 1;
// 订单状态
public $order_status = [
self::ORDER_CREATE => [
'status' => self::ORDER_CREATE,
'name' => '待支付',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon.png',
'action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderAddressUpdate',
'title' => '修改地址',
'color' => ''
],
[
'action' => 'orderAdjustMoney',
'title' => '调整价格',
'color' => ''
],
],
'member_action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => '',
],
[
'action' => 'orderPay',
'title' => '支付',
'color' => ''
],
],
'color' => ''
],
self::ORDER_PAY => [
'status' => self::ORDER_PAY,
'name' => '待发货',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-send.png',
'action' => [
[
'action' => 'orderDelivery',
'title' => '发货',
'color' => ''
],
[
'action' => 'orderAddressUpdate',
'title' => '修改地址',
'color' => ''
],
],
'member_action' => [],
'color' => ''
],
self::ORDER_DELIVERY => [
'status' => self::ORDER_DELIVERY,
'name' => '已发货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-receive.png',
'action' => [
[
'action' => 'takeDelivery',
'title' => '确认收货',
'color' => ''
],
],
'member_action' => [
[
'action' => 'memberTakeDelivery',
'title' => '确认收货',
'color' => ''
],
[
'action' => 'trace',
'title' => '查看物流',
'color' => ''
],
],
'color' => ''
],
self::ORDER_TAKE_DELIVERY => [
'status' => self::ORDER_TAKE_DELIVERY,
'name' => '已收货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [],
'member_action' => [
[
'action' => 'trace',
'title' => '查看物流',
'color' => ''
],
],
'color' => ''
],
self::ORDER_COMPLETE => [
'status' => self::ORDER_COMPLETE,
'name' => '已完成',
'icon' => 'public/uniapp/order/order-icon-received.png',
'is_allow_refund' => 1,
'action' => [],
'member_action' => [
[
'action' => 'trace',
'title' => '查看物流',
'color' => ''
],
],
'color' => ''
],
self::ORDER_CLOSE => [
'status' => self::ORDER_CLOSE,
'name' => '已关闭',
'icon' => 'public/uniapp/order/order-icon-close.png',
'is_allow_refund' => 0,
'action' => [],
'member_action' => [],
'color' => ''
]
];
/**
* 订单状态(发货列表)
*/
public $delivery_order_status = [
self::ORDER_PAY => [
'status' => self::ORDER_PAY,
'name' => '待发货',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-send.png',
'action' => [
[
'action' => 'orderDelivery',
'title' => '发货',
'color' => ''
],
[
'action' => 'orderAddressUpdate',
'title' => '修改地址',
'color' => ''
],
],
'member_action' => [],
'color' => ''
]
];
// 配送状态
public $delivery_status = [
self::DELIVERY_WAIT => [
'status' => self::DELIVERY_WAIT,
'name' => '待发货',
'color' => ''
],
self::DELIVERY_DOING => [
'status' => self::DELIVERY_DOING,
'name' => '已发货',
'color' => ''
],
self::DELIVERY_FINISH => [
'status' => self::DELIVERY_FINISH,
'name' => '已收货',
'color' => ''
]
];
/**
* 订单支付
* @param $data
* @return array
*/
public function orderPay($data)
{
$order_info = $data['order_info'];
$member_info = $data['member_info'];
$pay_type = $data['pay_type'];
$pay_type_list = $this->getPayType();
if ($order_info['order_status'] != self::ORDER_CREATE) return $this->error([], '当前订单未处于待付款状态,无法支付!');
$condition = [
['order_id', '=', $order_info['order_id']],
['order_status', '=', self::ORDER_CREATE],
];
$data = [
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name'],
'pay_status' => 1,
'order_status_action' => json_encode($this->order_status[self::ORDER_PAY], JSON_UNESCAPED_UNICODE),
'refund_status_action' => json_encode(OrderRefundDict::getStatus(OrderRefundDict::REFUND_NOT_APPLY), JSON_UNESCAPED_UNICODE),
'pay_time' => time(),
'is_enable_refund' => 1,
'pay_type' => $pay_type,
'pay_type_name' => $pay_type_list[$pay_type]
];
$result = model('order')->update($data, $condition);
//记录订单日志 start
$action = '商家对订单进行了线下支付';
//获取用户信息
if (empty($log_data)) {
$log_data = [
'uid' => $order_info['member_id'],
'nick_name' => $member_info['nickname'],
'action_way' => 1
];
$action = '买家支付了订单';
}
$log_data = array_merge($log_data, [
'order_id' => $order_info['order_id'],
'action' => $action,
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name']
]);
OrderLog::addOrderLog($log_data, $this);
//记录订单日志 end
return $this->success($result);
}
/**
* 批量订单发货(物流)
* @param $param
* @param $order_list
* @return array|int
*/
public function orderBatchDelivery($param, $order_list)
{
model('express_delivery_package')->startTrans();
try {
if (empty($order_list)) {
return $this->error('', '请先选择要发货的订单!');
}
foreach ($order_list as $v) {
$param['order_id'] = $v['order_id'];
$param['order_goods_ids'] = '';
if ($param['type'] == 'electronicsheet') {//电子面单发货
$addon_is_exit = addon_is_exit('electronicsheet', $param['site_id']);
if ($addon_is_exit != 1) {
return $this->error('', '电子面单插件不存在!');
}
$electronicsheet_model = new ElectronicsheetDelivery();
$result = $electronicsheet_model->delivery($param);
if ($result['code'] < 0) {
return $result;
}
$param['delivery_no'] = $result['data']['Order']['LogisticCode'];
} else {
$param['delivery_no'] = $v['delivery_no'];
}
$result = $this->orderGoodsDelivery($param, 2);
if ($result['code'] < 0) {
model('express_delivery_package')->rollback();
return $result;
}
}
model('express_delivery_package')->commit();
return $this->success();
} catch ( Exception $e ) {
model('express_delivery_package')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 订单项发货(物流)
* @param $param
* @param int $type 1订单项发货2整体发货
* @param array $log_data
* @return array|int
*/
public function orderGoodsDelivery($param, $type = 1, $log_data = [])
{
$param['type'] = $param['type'] ?? 'manual';
model('order_goods')->startTrans();
try {
$order_id = $param['order_id'];
$delivery_no = $param['delivery_no']; // 物流单号
$delivery_type = $param['delivery_type'];
if ($delivery_type == 0) {
$express_company_id = 0;
} else {
$express_company_id = $param['express_company_id'] ?? 0;
}
$site_id = $param['site_id'];
if ($type == 1) {
if (empty($param['order_goods_ids']))
return $this->error('', '发货货物不可为空!');
$order_goods_id_array = explode(',', $param['order_goods_ids']);
} else {
$order_goods_id_array = model('order_goods')->getColumn(
[
['order_id', '=', $order_id],
['site_id', '=', $site_id],
['delivery_status', '=', self::DELIVERY_WAIT],
['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]
],
'order_goods_id'
);
}
if (empty($order_goods_id_array))
return $this->error('', '发货货物不可为空!');
$order_id = 0;
$member_id = 0;
$goods_id_array = [];
$order_stock_model = new OrderStock();
$stock_sku_list = [];
foreach ($order_goods_id_array as $k => $v) {
$order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $v], ['site_id', '=', $site_id]], '*');
// 已退款的订单项不可发货
if ($order_goods_info['refund_status'] == OrderRefundDict::REFUND_COMPLETE) {
model('order_goods')->rollback();
return $this->error([], 'ORDER_GOODS_IS_REFUND');
}
if ($order_goods_info['delivery_status'] == self::DELIVERY_DOING) {
model('order_goods')->rollback();
return $this->error([], 'ORDER_GOODS_IS_DELIVERYED');
}
$order_goods_info['num'] = numberFormat($order_goods_info['num']);
$member_id = $order_goods_info['member_id'];
$goods_id_array[] = $order_goods_info['sku_id'] . ':' . $order_goods_info['num'] . ':' . $order_goods_info['sku_name'] . ':' . $order_goods_info['sku_image'];
$data = ['delivery_status' => self::DELIVERY_DOING, 'delivery_status_name' => $this->delivery_status[self::DELIVERY_DOING]['name']];
if (!empty($delivery_no)) {
$data['delivery_no'] = $delivery_no;
}
$res = model('order_goods')->update($data, [
['order_goods_id', '=', $v],
['delivery_status', '=', self::DELIVERY_WAIT]
]);
$order_id = $order_goods_info['order_id'];
//实际发货扣除库存
$stock_sku_list[] = $order_goods_info;
}
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'store_id,site_id');
$stock_result = $order_stock_model->decOrderStock([
'store_id' => $order_info['store_id'],
'site_id' => $order_info['site_id'],
'goods_sku_list' => $stock_sku_list,
'user_info' => $param['user_info'] ?? []
]);
if ($stock_result['code'] < 0) {
model('order_goods')->rollback();
return $stock_result;
}
// 创建包裹
$order_common_model = new OrderCommon();
$lock_result = $order_common_model->verifyOrderLock($order_id);
if ($lock_result['code'] < 0) {
model('order_goods')->rollback();
return $lock_result;
}
$express_delivery_model = new ExpressDelivery();
$delivery_data = [
'order_id' => $order_id,
'order_goods_id_array' => $order_goods_id_array,
'goods_id_array' => $goods_id_array,
'goods_array' => $goods_id_array,
'site_id' => $site_id,
'delivery_no' => $delivery_no,
'member_id' => $member_id,
'express_company_id' => $express_company_id,
'delivery_type' => $delivery_type,
'type' => $param['type'],
'template_id' => $param['template_id']
];
$delivery_id = $express_delivery_model->delivery($delivery_data);
// 检测整体, 订单中订单项是否全部发放完毕
$res = $this->orderCommonDelivery($order_id, $log_data);
if ($res['code'] < 0) {
model('order_goods')->rollback();
return $res;
}
model('order_goods')->commit();
return $this->success($delivery_id);
} catch ( Exception $e ) {
model('order_goods')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 批量订单发货导入excel文件发货
* @param $param
* @param $site_id
* @param $uid
* @return array
* @throws \PhpOffice\PhpSpreadsheet\Exception
* @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
*/
public function orderFileDelivery($param, $site_id, $uid)
{
//电子面单插件
$addon_is_exit = addon_is_exit('electronicsheet', $site_id);
$PHPReader = IOFactory::createReader('Xlsx');
//载入文件
$PHPExcel = $PHPReader->load($param['path']);
//获取表中的第一个工作表如果要获取第二个把0改为1依次类推
$currentSheet = $PHPExcel->getSheet(0);
//获取总行数
$allRow = $currentSheet->getHighestRow();
if ($allRow < 2) {
return $this->error('', '导入了一个空文件!');
}
$user_info = model('user')->getInfo([['uid', '=', $uid]], 'username');
//添加文件上传记录
$success_num = $allRow - 1;
$error_num = 0;
$data = [
'site_id' => $site_id,
'filename' => $param['filename'],
'path' => $param['path'],
'order_num' => $allRow - 1,
'success_num' => $success_num,
'create_time' => time(),
'uid' => $uid,
'username' => $user_info['username']
];
$res = model('order_import_file')->add($data);
if (!$res) {
return $this->error('', '上传文件失败!');
}
model('order_import_file')->startTrans();
try {
for ($i = 2; $i <= $allRow; $i++) {
$delivery_data = [
'type' => '',//发货方式(手动发货、电子面单)
'express_company_id' => 0,//物流公司
'delivery_type' => 1,//是否需要物流
'site_id' => $site_id,
'template_id' => 0,//电子面单模板id
'delivery_no' => ''
];
//订单编号
$order_no = $PHPExcel->getActiveSheet()->getCell('A' . $i)->getValue();
$order_no = trim($order_no, ' ');
$order_no = preg_replace('/\s+/', '', $order_no);
//订单内容
$order_name = $PHPExcel->getActiveSheet()->getCell('B' . $i)->getValue();
$order_name = trim($order_name, ' ');
//发货方式
$type = $PHPExcel->getActiveSheet()->getCell('F' . $i)->getValue();
$type = trim($type, ' ');
//物流公司名称或电子面单名称
$name = $PHPExcel->getActiveSheet()->getCell('G' . $i)->getValue();
$name = trim($name, ' ');
//物流单号
$delivery_no = $PHPExcel->getActiveSheet()->getCell('H' . $i)->getValue();
$delivery_no = trim($delivery_no, ' ');
if (empty($type)) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '发货方式为空'
]
);
continue;
}
if ($type == '电子面单' && $addon_is_exit == 1) {
if (empty($name)) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '电子面单模板为空'
]
);
continue;
}
$delivery_data['type'] = 'electronicsheet';
$template_id = model('express_electronicsheet')->getValue([['template_name', '=', $name], ['site_id', '=', $site_id]], 'id');
if (empty($template_id)) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '电子面单模板不存在'
]
);
continue;
}
$delivery_data['template_id'] = $template_id;
} elseif ($type == '电子面单' && $addon_is_exit != 1) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '电子面单插件未安装']
);
continue;
} else {
$delivery_data['type'] = 'manual';
if (empty($delivery_no) || empty($name)) {//无需物流
$delivery_data['delivery_type'] = 0;
} else {
$company_id = model('express_company')->getValue([['site_id', '=', $site_id], ['company_name', '=', $name]], 'company_id');
if ($company_id == '') {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '物流公司不存在'
]
);
continue;
}
$delivery_data['express_company_id'] = $company_id;
$delivery_data['delivery_no'] = $delivery_no;
}
}
//获取订单信息
$order_info = model('order')->getInfo([['order_no', '=', $order_no], ['site_id', '=', $site_id]], 'order_id,order_status');
if (empty($order_info) || $order_info['order_status'] != self::ORDER_PAY) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => '订单不存在或者已发货'
]
);
continue;
}
$delivery_data['order_id'] = $order_info['order_id'];
$delivery_data['order_goods_ids'] = '';
if ($delivery_data['type'] == 'electronicsheet') {//电子面单发货
$electronicsheet_model = new ElectronicsheetDelivery();
$result = $electronicsheet_model->delivery($delivery_data);
if ($result['code'] < 0) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => $result['message']
]
);
continue;
}
$delivery_data['delivery_no'] = $result['data']['Order']['LogisticCode'];
}
$result = $this->orderGoodsDelivery($delivery_data, 2);
if ($result['code'] < 0) {
$error_num += 1;
$success_num -= 1;
//修改数量
model('order_import_file')->update(['success_num' => $success_num, 'error_num' => $error_num], [['id', '=', $res]]);
//添加失败记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => -1, 'reason' => $result['message']
]
);
continue;
}
//添加成功记录
model('order_import_file_log')->add(
[
'site_id' => $site_id, 'file_id' => $res, 'order_no' => $order_no, 'order_name' => $order_name,
'status' => 0, 'reason' => ''
]
);
}
model('order_import_file')->commit();
return $this->success();
} catch ( Exception $e ) {
model('order_import_file')->rollback();
//修改数量
model('order_import_file')->update(['success_num' => 0, 'error_num' => $allRow - 1], [['id', '=', $res]]);
return $this->error('', $e->getMessage());
}
}
/**
* 订单收货
* @param $order_id
* @return array
*/
public function orderTakeDelivery($order_id)
{
//保存物流轨迹信息
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'mobile');
$express_package_model = new ExpressPackage();
$express_package_model->package([['order_id', '=', $order_id]], $order_info['mobile'], true);
return $this->success();
}
/**
* 订单收货地址修改
* @param $param
* @param $condition
* @param array $log_data
* @return array
*/
public function orderAddressUpdate($param, $condition, $log_data = [])
{
$province_id = $param['province_id'];
$city_id = $param['city_id'];
$district_id = $param['district_id'];
$community_id = $param['community_id'];
$address = $param['address'];
$full_address = $param['full_address'];
$longitude = $param['longitude'];
$latitude = $param['latitude'];
$mobile = $param['mobile'];
$telephone = $param['telephone'];
$name = $param['name'];
$data = [
'province_id' => $province_id,
'city_id' => $city_id,
'district_id' => $district_id,
'community_id' => $community_id,
'address' => $address,
'full_address' => $full_address,
'longitude' => $longitude,
'latitude' => $latitude,
'mobile' => $mobile,
'telephone' => $telephone,
'name' => $name,
];
$order_info = model('order')->getInfo($condition, '*');
$order_status_array = [self::ORDER_PAY, self::ORDER_CREATE];
if (!in_array($order_info['order_status'], $order_status_array))
return $this->error('', '当前订单状态不可编辑收货地址!');
//记录订单日志 start
if ($log_data) {
$log_data = array_merge($log_data, [
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
]);
OrderLog::addOrderLog($log_data, $this);
}
//记录订单日志 end
$result = model('order')->update($data, $condition);
return $this->success($result);
}
/**
* 退款完成操作
* @param $order_goods_info
*/
public function refund($order_goods_info)
{
//是否入库
$order_stock_model = new OrderStock();
if ($order_goods_info['is_refund_stock'] == 1) {
$order_stock_model->incOrderStock($order_goods_info);
}else if($order_goods_info['delivery_status'] == 0){
$order_stock_model->incOrderSaleStock([
'store_id' => $order_goods_info['store_id'],
'goods_sku_data' => [
[
'sku_id' => $order_goods_info['sku_id'],
'num' => $order_goods_info['num'],
],
],
]);
}
//检测订单项是否否全部发放完毕
$this->orderDelivery($order_goods_info['order_id']);
}
/**
* 订单发货
* @param $order_id
* @param array $log_data
* @return array
*/
public function orderDelivery($order_id, $log_data = [])
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
$site_id = $order_info['site_id'];
// 待发货状态
if ($order_info['order_status'] == self::ORDER_PAY) {
// 统计订单项目
$count = model('order_goods')->getCount([['order_id', '=', $order_id], ['delivery_status', '=', self::DELIVERY_WAIT], ['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id');
// $delivery_count = model('order_goods')->getCount([['order_id', '=', $order_id], ['delivery_status', '=', self::DELIVERY_DOING], ['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]], 'order_goods_id');
// if ($count == 0 && $delivery_count > 0) {
if ($count == 0) {
// 全部发货
model('order')->startTrans();
try {
// 修改订单项的配送状态
$order_data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'delivery_status' => self::DELIVERY_FINISH,
'delivery_status_name' => $this->delivery_status[self::DELIVERY_FINISH]['name'],
'order_status_action' => json_encode($this->order_status[self::ORDER_DELIVERY], JSON_UNESCAPED_UNICODE),
'delivery_time' => time()
];
model('order')->update($order_data, [['order_id', '=', $order_id]]);
if ($log_data) {
// 记录订单日志 start
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name']
]);
OrderLog::addOrderLog($log_data, $this);
//记录订单日志 end
}
//订单自动收货
OrderCron::takeDelivery(['order_id' => $order_id, 'site_id' => $site_id]);
// 订单发货完成,小程序发货信息录入,视频号
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_id, 'site_id' => $site_id]);
model('order')->commit();
// 订单发货消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'ORDER_DELIVERY', 'order_id' => $order_id, 'site_id' => $site_id]);
return $this->success();
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
} else {
if ($log_data) {
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'order_status' => $order_info['order_status'],
'order_status_name' => $this->order_status[$order_info['order_status']]['name']
]);
OrderLog::addOrderLog($log_data, $this);
}
return $this->success();
}
} else {
return $this->success();
}
}
/**
* 订单详情
* @param $order_info
* @return array
*/
public function orderDetail($order_info)
{
return $this->orderPartDeliveryHandle($order_info);
}
/**
* 订单部分发货处理
* @param $order_info
* @return array
*/
public function orderPartDeliveryHandle($order_info)
{
$res = [];
if(isset($order_info['order_status']) && $order_info['order_status'] == self::ORDER_PAY){
$is_delivery = false;
foreach($order_info['order_goods'] as $val){
if($val['delivery_status'] == 1){
$is_delivery = true;
break;
}
}
if($is_delivery){
$res['order_status_name'] = '部分发货';
$order_status_action = json_decode($order_info['order_status_action'], true);
$order_status_action['member_action'][] = [
'action' => 'trace',
'title' => '查看物流',
'color' => ''
];
$res['order_status_action'] = json_encode($order_status_action);
}
}
return $res;
}
/**
* 计算订单销售额
* @param array $condition
* @param string $field
* @return array
*/
public function getOrderMoneySum($condition = [], $field = 'order_money')
{
$res = model('order')->getSum($condition, $field);
return $this->success($res);
}
}

1646
app/model/order/OrderCommon.php Executable file

File diff suppressed because it is too large Load Diff

436
app/model/order/OrderCreate.php Executable file
View File

@@ -0,0 +1,436 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\store\model\Config as StoreConfig;
use app\model\BaseModel;
use app\model\goods\Goods;
use app\model\system\Pay;
use Exception;
/**
* 订单创建(普通订单)
*
*/
class OrderCreate extends BaseModel
{
use OrderCreateTool;
/**
* @var int|mixed
*/
public $jielong_id;
public $jielong_info = [];
public function __construct()
{
$this->modules = [ 'coupon' ];
}
public function create()
{
//读取之前的标识缓存
$this->confirm();
$error_result = $this->checkError();
if ($error_result !== true) {
return $error_result;
}
model('order')->startTrans();
try {
//订单创建数据
$order_insert_data = $this->getOrderInsertData([ 'promotion' ], 'invert');
$order_insert_data[ 'store_id' ] = $this->store_id;
$order_insert_data[ 'create_time' ] = time();
$order_insert_data[ 'is_enable_refund' ] = 0;
//订单类型以及状态
$this->orderType();
$order_insert_data[ 'order_type' ] = $this->order_type[ 'order_type_id' ];
$order_insert_data[ 'order_type_name' ] = $this->order_type[ 'order_type_name' ];
$order_insert_data[ 'order_status_name' ] = $this->order_type[ 'order_status' ][ 'name' ];
$order_insert_data[ 'order_status_action' ] = json_encode($this->order_type[ 'order_status' ], JSON_UNESCAPED_UNICODE);
$this->order_id = model('order')->add($order_insert_data);
$order_goods_insert_data = [];
//订单项目表
foreach ($this->goods_list as $order_goods_v) {
$order_goods_insert_data[] = $this->getOrderGoodsInsertData($order_goods_v);
}
model('order_goods')->addList($order_goods_insert_data);
//todo 满减送
$this->createManjian();
//todo 优惠券(新)
$this->useCoupon();
//扣除余额
$this->useBalance();
//扣除抵现积分
$this->usePoint();
//是否同时开通会员卡
$this->createMemberCard();
//使用次卡
$this->useCard();
//库存转换处理
$this->batchGoodsStockTransform();
//库存处理(卡密商品支付后在扣出库存)//todo 可以再商品中设置扣除库存步骤
$this->batchDecOrderGoodsStock();
model('order')->commit();
//订单创建后事件
$this->orderCreateAfter();
//生成整体付费支付单据
$pay_model = new Pay();
$pay_model->addPay($this->site_id, $this->out_trade_no, $this->pay_type, $this->order_name, $this->order_name, $this->pay_money, '', 'OrderPayNotify', '', $this->order_id, $this->member_id);
return $this->success($this->out_trade_no);
} catch (Exception $e) {
model('order')->rollback();
return $this->error([
'file' => $e->getFile(),
'line' => $e->getLine(),
'message' => $e->getMessage(),
], $e->getMessage());
}
}
/**
* 计算后的进一步计算(不存缓存,每次都是重新计算)
* @return array
*/
public function confirm()
{
$order_key = $this->param[ 'order_key' ];
$this->getOrderCache($order_key);
//初始化地址
$this->initMemberAddress();
//初始化门店信息
$this->initStore();
//优惠运费计算
$this->shopOrderCalculate();
// 会员卡开卡金额
$this->calculateMemberCardMoney();
//配送计算
$this->calculateDelivery();
//批量校验配送方式
$this->batchCheckDeliveryType();
//优惠券活动(采用站点id:coupon_id) **
$this->couponPromotion();
// 积分抵现
if ($this->member_account[ 'point' ] > 0 && addon_is_exit('pointcash', $this->site_id)) {
$this->getMaxUsablePoint();
//计算积分
$this->calculatePoint();
}
//计算发票相关
$this->calculateInvoice();
//计算余额
$this->calculateBalcnce();
$this->pay_money = $this->order_money - $this->balance_money;
//设置过的商品项信息
return get_object_vars($this);
}
/**
* 待付款订单
* @return array
*/
public function orderPayment()
{
$this->calculate();
$this->getDeliveryData();
//todo 这儿认为只有自定义表单会用此钩子
return get_object_vars($this);
}
/**
* 订单计算
* @return true
*/
public function calculate()
{
$this->initMemberAddress(); //初始化地址
$this->initMemberAccount(); //初始化会员账户
$this->getRecommendMemberCard();//查询推荐会员卡
//初始化门店信息
$this->initStore();
//商品列表信息
$this->getOrderGoodsCalculate();
//优惠运费计算
$this->shopOrderCalculate();
//订单初始项
event('OrderPayment', [ 'order_object' => $this ]);
//获取发票相关
$this->getInovice();
//todo 统一检测库存(创建订单操作时扣除库存同理)
// 商品限购判断
$this->checkLimitPurchase();
$this->order_key = create_no();
$this->setOrderCache(get_object_vars($this), $this->order_key);
return true;
}
/**
* 获取商品的计算信息
* @return true
*/
public function getOrderGoodsCalculate()
{
$this->getCartGoodsList();
// 会员卡项抵扣
$this->getMemberGoodsCardPromotion();
//满减优惠
$this->manjianPromotion();
return true;
}
/**
* 获取购物车商品列表信息
* @return array|mixed|void
*/
public function getCartGoodsList()
{
$cart_ids = $this->param[ 'cart_ids' ] ?? [];
$condition = [
[ 'ngs.site_id', '=', $this->site_id ],
[ 'ngs.is_delete', '=', 0 ],
[ 'ngs.goods_state', '=', 1],
[ 'ng.sale_channel', 'in', $this->sale_channel],
];
//组装商品列表
$field = 'ngs.sku_id,ngs.is_limit, ngs.limit_type, ngs.sku_name, ngs.member_price, ngs.is_consume_discount, ngs.discount_config, ngs.discount_method, ngs.sku_no,
ngs.price, ngs.discount_price, ngs.cost_price, ngs.stock, ngs.weight, ngs.volume, ngs.sku_image,
ngs.site_id, ngs.goods_state, ngs.is_virtual, ngs.supplier_id,ngs.form_id,
ngs.is_free_shipping, ngs.shipping_template, ngs.goods_class, ngs.goods_class_name, ngs.goods_id,ns.site_name,ngs.sku_spec_format,ngs.goods_name,ngs.max_buy,ngs.min_buy,ngs.support_trade_type, ngs.is_unify_price,
ngs.sale_channel, ngs.sale_store, ng.category_id, ng.is_unify_price, ng.virtual_deliver_type';
$alias = 'ngs';
$join = [
// [
// 'goods_sku ngs',
// 'ngc.sku_id = ngs.sku_id',
// 'inner'
// ],
[
'site ns',
'ngs.site_id = ns.site_id',
'inner'
],
[
'goods ng',
'ngs.goods_id = ng.goods_id',
'inner',
],
];
//门店独立售价处理
if (addon_is_exit('store', $this->site_id)) {
$store_config = (new StoreConfig())->getStoreBusinessConfig($this->site_id)['data']['value'];
$join[] = ['store_goods_sku sgs', 'sgs.sku_id = ngs.sku_id and sgs.store_id = '.$this->store_id, 'left'];
if($store_config['store_business'] == 'store'){
$field = str_replace('ngs.price', 'IFNULL(IF(ng.is_unify_price = 1,ngs.price,sgs.price), ngs.price) as price', $field);
$field = str_replace('ngs.discount_price', 'IFNULL(IF(ng.is_unify_price = 1,ngs.discount_price,sgs.price), ngs.discount_price) as discount_price', $field);
}
//与门店相关且门店的库存为独立库存则成本价取门店商品的成本价
$delivery_type = $this->param['delivery']['delivery_type'] ?? 'express';
if($store_config['store_business'] == 'shop' && $delivery_type == 'express'){
$delivery_store_id = 0;
}else{
$delivery_store_id = $this->param['delivery']['store_id'] ?? 0;
}
if(!empty($delivery_store_id)){
$store_model = new \app\model\store\Store();
$delivery_store_stock_type = $store_model->getStoreInfo([['store_id', '=', $delivery_store_id]], 'stock_type')['data']['stock_type'];
if($delivery_store_stock_type == 'store'){
$field = str_replace('ngs.cost_price', 'IFNULL(sgs.cost_price, ngs.cost_price) as cost_price', $field);
}
}
}
$this->jielong_id = $this->param[ 'jielong_id' ] ?? 0;
if (!empty($cart_ids)) {
$this->cart_ids = $cart_ids;
$field .= ',ngc.member_id, ngc.sku_id, ngc.num';
if ($this->jielong_id > 0) {
$join[] = [
'promotion_jielong_cart ngc',
'ngc.sku_id = ngs.sku_id',
'inner'
];
} else {
$field .= ',ngc.form_data';
$join[] = [
'goods_cart ngc',
'ngc.sku_id = ngs.sku_id',
'inner'
];
}
$condition[] = [ 'ngc.cart_id', 'in', $cart_ids ];
$condition[] = [ 'ngc.member_id', '=', $this->member_id ];
} else {
$sku_id = $this->param[ 'sku_id' ];
$num = $this->param[ 'num' ];
$field .= ',' . $num . ' as num';
$condition[] = [
'ngs.sku_id', '=', $sku_id
];
}
//只有存在收银插件的情况下才会进行吧此项业务(todo 钩子实现)
$delivery_array = $this->param[ 'delivery' ] ?? [];
$goods_list = model('goods_sku')->getList($condition, $field, '', $alias, $join);
if (!empty($goods_list)) {
$this->goods_list = $goods_list;
$available_store_ids = [];
$available_store_is_all = true;
//计算商品扩展业务相关项
event('OrderGoodsCalculate', [ 'order_object' => $this ], true);
foreach ($this->goods_list as $k => &$v) {
if($v['sale_store'] != 'all'){
$available_store_is_all = false;
$sale_store = explode(',', trim($v['sale_store'], ','));
if(empty($available_store_ids)){
$available_store_ids = $sale_store;
}else{
$available_store_ids = array_intersect($available_store_ids, $sale_store);
}
}
$this->site_name = $v[ 'site_name' ];
$goods_id = $v[ 'goods_id' ];
if ($v[ 'num' ] < 1) {
$this->setError(1, '商品项的购买数量不能小于1');
}
$this->is_virtual = $v[ 'is_virtual' ];
if($v['goods_class'] == \app\dict\goods\GoodsDict::virtual && $v['virtual_deliver_type'] == 'artificial_deliver'){
$this->is_virtual_delivery = 1;
}
$goods_item = $v;
$goods_item[ 'delivery' ] = $delivery_array;
$goods_item[ 'store_id' ] = $this->store_id;
// //整理创建订单时商品的相关价格库存, 有错误的话还回记录错误['error' => [''error_code' => 1, 'message' => '']]
// $goods_calculate = event('OrderGoodsCalculate', $goods_item, true);
// if (!empty($goods_calculate)) {
// if ($goods_calculate['code'] < 0) {
// return $goods_calculate;
// }
// $v = $goods_calculate['data'];
// }
//todo 要核验 当前门店 当前产品是否已经配置上架
//todo 未上架未配置 要记录原因,并且不能生成订单
$price = $this->getGoodsPrice($v)[ 'data' ] ?? 0;
// 是否存在推荐会员卡
if (!empty($this->recommend_member_card)) {
//todo 当前业务门店不存在,所以这儿的价格不作处理
$card_price_info = $this->getMemberCardGoodsPrice($v)[ 'data' ] ?? [];
$card_price = $card_price_info[ 'price' ];
if ($card_price > 0 && $card_price < $price) {
$this->recommend_member_card[ 'discount_money' ] += ($price - $card_price) * $v[ 'num' ];
if ($this->recommend_member_card_data[ 'is_open_card' ]) $price = $card_price;//todo 这儿应该把discount_price 也同步一下的
}
}
$v[ 'form_data' ] = !empty($v[ 'form_data' ]) ? json_decode($v[ 'form_data' ], true) : '';
$v[ 'price' ] = $price;
//实现要注意 discount_price 字段只存在显示作用
if ($this->store_id > 0) {
$v[ 'discount_price' ] = $price;
}
$v[ 'goods_money' ] = $price * $v[ 'num' ];
$v[ 'real_goods_money' ] = $v[ 'goods_money' ];
$v[ 'coupon_money' ] = 0; //优惠券金额
$v[ 'promotion_money' ] = 0; //优惠金额
// $this->goods_list[] = $v;
$order_name = $this->order_name ?? '';
if ($order_name) {
$len = strlen_mb($order_name);
if ($len > 200) {
$this->order_name = str_sub($order_name, 200);
} else {
$this->order_name = string_split($order_name, ',', $v[ 'sku_name' ]);
}
} else {
$this->order_name = string_split('', ',', $v[ 'sku_name' ]);
}
$this->goods_num += $v[ 'num' ];
$this->goods_money += $v[ 'goods_money' ];
//以;隔开的商品项
$goods_list_str = $this->goods_list_str ?? '';
if ($goods_list_str) {
$this->goods_list_str = $goods_list_str . ';' . $v[ 'sku_id' ] . ':' . $v[ 'num' ];
} else {
$this->goods_list_str = $v[ 'sku_id' ] . ':' . $v[ 'num' ];
}
// 商品限购处理
if (isset($this->limit_purchase[ 'goods_' . $goods_id ])) {
$this->limit_purchase[ 'goods_' . $goods_id ][ 'num' ] += $v[ 'num' ];
} else {
$this->limit_purchase[ 'goods_' . $goods_id ] = [
'goods_id' => $v[ 'goods_id' ],
'goods_name' => $v[ 'sku_name' ],
'num' => $v[ 'num' ],
'is_limit' => $v[ 'is_limit' ],
'limit_type' => $v[ 'limit_type' ],
'max_buy' => $v[ 'max_buy' ],
'min_buy' => $v[ 'min_buy' ]
];
}
//校验商品和配送方式
// $this->checkDeliveryType($v);
//有错误也会导致商品无法购买
$item_error = $v[ 'error' ] ?? [];
if (!empty($item_error)) {
$this->setError(1, $item_error[ 'message' ]);
}
}
if($available_store_is_all === false){
$this->available_store_ids = join(',', $available_store_ids);
}
}else{
$this->setError(1, '您要购买的商品已删除或已下架');
}
return true;
}
/**
* 获取店铺订单计算
* @return true
*/
public function shopOrderCalculate()
{
//满额包邮插件
$this->freeShippingCalculate();
//会员等级包邮权益
$this->memberLevelCalculate();
//重新计算订单总额
$this->getOrderMoney();
//理论上是多余的操作
if ($this->order_money < 0) {
$this->order_money = 0;
}
//总结计算
$this->pay_money = $this->order_money;
return true;
}
}

View File

@@ -0,0 +1,631 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\pointcash\model\Config as PointCashConfig;
use app\dict\order\OrderDict;
use app\dict\order\OrderGoodsDict;
use app\dict\order\OrderPayDict;
use app\model\express\Config as ExpressConfig;
use app\model\order\ordercreate\CommonTool;
use app\model\order\ordercreate\DeliveryTool;
use app\model\order\ordercreate\GoodsTool;
use app\model\order\ordercreate\PromotionTool;
use app\model\system\Cron;
use app\model\system\Pay;
use extend\exception\OrderException;
use think\facade\Cache;
use think\facade\Queue;
/**
* 订单创建 可调用的工具类
*/
trait OrderCreateTool
{
use CommonTool;
use PromotionTool;
use DeliveryTool;
use GoodsTool;
public $site_id = 1;//站点id
public $site_info;
public $store_info;
public $store_id = 0;//门店id
public $available_store_ids = 'all';//可以用的门店
public $cart_ids = [];
public $order_no;
public $out_trade_no;
public $order_key;
public $config = [];//配置
public $coupon_id = 0;//优惠券
public $coupon_money = 0;//优惠券金额
public $order_type = [];//订单类型(array)
public $is_point = 0;//是否使用积分
public $member_id = 0;//会员id
public $member_account = [];//会员账户
public $member_level = [];//会员等级
public $invoice = [];//发票
public $delivery = [];
public $is_limit_start_money = true;//是否限制起送金额
public $is_free_delivery = false;//是否免邮
public $buyer = [];//买家信息
public $param = [];//参数
public $order_data = [];
public $goods_num = 0;//商品数量
public $limit_purchase = [];//限购
public $promotion = [];//活动优惠...
public $manjian_rule_list = [];//满减优惠规则
public $promotion_type;
public $promotion_type_name;
public $site_name = '';
public $goods_money = 0; //商品金额
public $delivery_money = 0; //配送费用
public $adjust_money = 0; //调整金额
public $invoice_money = 0; //发票费用
public $promotion_money = 0; //优惠金额
public $order_money = 0; //订单金额
public $pay_money = 0; //支付总价
public $is_virtual = 0; //是否是虚拟类订单
public $is_virtual_delivery = 0; //虚拟商品是否发货
public $order_name = ''; //订单详情
public $goods_list_str = '';
public $error = 0; //是否有错误
public $error_msg = ''; //错误描述
public $error_show = false;
public $pay_type = OrderPayDict::online_pay;
public $invoice_delivery_money = 0;
public $balance_money = 0;
public $member_balance_money = 0; //会员账户余额(计算过程中会逐次减少)
public $recommend_member_card = []; // 推荐会员卡
public $recommend_member_card_data = [];//推荐会员卡配置规格
public $member_card_money = 0; // 会员卡开卡金额
public $member_goods_card = [];
public $goods_list = [];//商品项数据结构
public $order_id;
public $point_money = 0; // 积分抵现金额
public $order_goods_list = [];//订单项列表
public $order_object_data;
public $modules = [];
public $log = [];
public $order_from_type = 'order';
public $sale_channel = 'all,online,offline';
public $is_check_buyer_ask_delivery_time = true;//特殊业务比如预售不做时间检测
/**
* 设置错误,优先级
* @param $error
* @param $error_msg
* @param string $priority 报错优先级 0 创建时提示 1 计算时提示
*/
public function setError($error, $error_msg, $priority = '0')
{
$this->error = $error;
$this->error_msg = $error_msg;
if ($priority == 1) {
$this->error_show = true;
}
}
/**
* 校验错误
* @return array|true
*/
public function checkError()
{
if ($this->error > 0) {
return $this->error(['error_code' => $this->error], $this->error_msg);
}
return true;
}
/**
* 获取订单创建缓存
* @param $key
* @return mixed
*/
public function getOrderCache($key)
{
$order_cache = Cache::get($key, []);
if (empty($order_cache)) throw new OrderException('订单已过期');
foreach ($order_cache as $k => $v) {
$this->$k = $v;
}
return $order_cache;
}
/**
* 设置订单缓存
* @param $data
* @param $key
* @return mixed
*/
public function setOrderCache($data, $key = '')
{
if (empty($key)) {
$key = create_no();
}
unset($data['param']);
Cache::tag('order_cache')->set($key, $data, 30000);
return $key;
}
/**
* 删除订单缓存
* @param $key
* @return true
*/
public function deleteOrderCache($key = '')
{
Cache::delete($key ?: $this->order_key);
return true;
}
/**
* 定义传入参数
* @param $param
* @return $this
*/
public function setParam($param)
{
$this->param = $param;
$this->member_id = $this->param['member_id'];
$this->site_id = $this->param['site_id'];
$this->order_from = $this->param['order_from'] ?? '';//订单来源
$this->order_from_name = $this->param['order_from_name'] ?? '';//订单来源名称
$this->sale_channel = $this->param['sale_channel'] ?? 'all,online,offline';//销售渠道
return $this;
}
/**
* 重新计算订单总额
* @return void
*/
public function getOrderMoney()
{
$this->order_money = round($this->goods_money + $this->delivery_money - $this->promotion_money + $this->member_card_money - $this->point_money - $this->coupon_money + $this->invoice_money + $this->invoice_delivery_money,2);
$this->order_money = max($this->order_money, 0);
return $this->order_money;
}
/**
* 增加订单自动关闭事件
*/
public function addOrderCronClose()
{
//计算订单自动关闭时间
$order_config = $this->config('order');
$now_time = time();
if ($order_config['auto_close'] > 0) {
$execute_time = $now_time + $order_config['auto_close'] * 60; //自动关闭时间
$cron_model = new Cron();
$cron_model->addCron(1, 0, '订单自动关闭', 'CronOrderClose', $execute_time, $this->order_id);
// 订单催付通知
// 未付款订单将会在订单关闭前10分钟对买家进行催付提醒
if ($this->pay_money > 0) {
$cron_model->addCron(1, 0, '订单催付通知', 'CronOrderUrgePayment', $execute_time - 600, $this->order_id);
}
}
}
/**
* 配置设置或查询
* @param $key
* @return array|mixed
*/
public function config($key)
{
//查询购物配置
$config = $this->config[$key] ?? [];
if (empty($this->config[$key])) {
switch ($key) {
case 'order'://交易配置
$config_model = new Config();
$order_config = $config_model->getOrderEventTimeConfig($this->site_id)['data'] ?? [];
$config = $order_config['value'] ?? [];
break;
case 'point'://积分交易配置
$config_model = new PointCashConfig();
$config = $config_model->getPointCashConfig($this->site_id)['data'];
break;
case 'balance'://余额交易配置
$config_model = new Config();
$config = $config_model->getBalanceConfig($this->site_id)['data']['value'] ?? [];
break;
case 'delivery_type':
$config = (new ExpressConfig())->getExpressTypeList($this->site_id) ?? [];
break;
case 'delivery_type_sort':
$config = (new ExpressConfig())->getDeliverTypeSort($this->site_id)['data'] ?? [];
break;
case 'express'://物流配置
$express_config_model = new ExpressConfig();
$config = $express_config_model->getExpressConfig($this->site_id)['data'] ?? [];
break;
case 'store'://门店自提配置
$express_config_model = new ExpressConfig();
$config = $express_config_model->getStoreConfig($this->site_id)['data'] ?? [];
break;
case 'local'://本地配送配置
$express_config_model = new ExpressConfig();
$config = $express_config_model->getLocalDeliveryConfig($this->site_id)['data'] ?? [];
break;
case 'store_business':
$store_config_model = new \addon\store\model\Config();
$config = $store_config_model->getStoreBusinessConfig($this->site_id)['data']['value'] ?? [];
break;
}
$this->config[$key] = $config;
}
return $config;
}
/**
* 获取订单添加的公共数据
* @param array $modules 数据组件标识
* @param string $op and 包含 invert 无交集
* @return array
*/
public function getOrderInsertData($modules = [], $op = 'and')
{
$data = [];
//公共的订单数据
$this->order_no = $this->createOrderNo();
$pay_model = new Pay();
$this->out_trade_no = $pay_model->createOutTradeNo($this->member_id);
$common_data = [
'order_no' => $this->order_no,
'out_trade_no' => $this->out_trade_no,
'site_id' => $this->site_id,
'site_name' => $this->site_name,
'member_id' => $this->member_id,
'order_from' => $this->order_from,
'order_from_name' => $this->order_from_name,
'buyer_ip' => request()->ip(),
];
$data = array_merge($data, $common_data);
//传入数据
$buyer_message = $this->param['buyer_message'];
$input_data = [
'buyer_message' => $buyer_message,
];
$data = array_merge($data, $input_data);
//订单数据
$order_data = [
'goods_money' => $this->goods_money,
'delivery_money' => $this->delivery_money,
'coupon_money' => $this->coupon_money ?? 0,
'point_money' => $this->point_money,
'adjust_money' => $this->adjust_money,
'invoice_money' => $this->invoice_money,
'invoice_delivery_money' => $this->invoice_delivery_money,
'promotion_money' => $this->promotion_money,
'order_money' => $this->order_money,
'balance_money' => $this->balance_money,
'pay_money' => $this->pay_money,
'member_card_money' => $this->member_card_money,
'order_name' => $this->order_name,
'goods_num' => $this->goods_num,
];
$data = array_merge($data, $order_data);
if ($this->getInsertDataWhereResult($modules, 'invoice', $op)) {
//发票信息
if (isset($this->param['is_invoice']) && $this->param['is_invoice'] == 1) {
$invoice_data = [
'taxpayer_number' => $this->invoice['taxpayer_number'] ?? '',
'invoice_rate' => $this->invoice['invoice_rate'] ?? 0,
'invoice_content' => $this->invoice['invoice_content'] ?? '',
'invoice_full_address' => $this->invoice['invoice_full_address'] ?? '',
'is_invoice' => $this->param['is_invoice'] ?? 0,
'invoice_type' => $this->invoice['invoice_type'] ?? 0,
'invoice_title' => $this->invoice['invoice_title'] ?? '',
'is_tax_invoice' => $this->invoice['is_tax_invoice'] ?? '',
'invoice_email' => $this->invoice['invoice_email'] ?? '',
'invoice_title_type' => $this->invoice['invoice_title_type'] ?? 0,
];
$data = array_merge($data, $invoice_data);
}
}
if ($this->getInsertDataWhereResult($modules, 'delivery', $op)) {
//配送数据
$express_type_list = $this->config('delivery_type');
$delivery_type_name = $express_type_list[$this->delivery['delivery_type']] ?? '';
$buyer_ask_delivery_time = $this->delivery['buyer_ask_delivery_time'] ?? [];
$delivery_data = [
'delivery_type' => $this->delivery['delivery_type'],
'delivery_type_name' => $delivery_type_name,
'delivery_store_id' => $this->delivery['delivery_store_id'] ?? 0,
'delivery_store_name' => $this->delivery['delivery_store_name'] ?? '',
'delivery_store_info' => $this->delivery['delivery_store_info'] ?? '',
'buyer_ask_delivery_time' => $buyer_ask_delivery_time['remark'] ?? '',//定时达
'delivery_start_time' => $buyer_ask_delivery_time['start_time'] ?? '',//配送开始时间
'delivery_end_time' => $buyer_ask_delivery_time['end_time'] ?? '',//配送结束时间
];
$data = array_merge($data, $delivery_data);
}
if ($this->getInsertDataWhereResult($modules, 'take', $op)) {
$this->orderType();
//允许门店配送和虚拟商品传入手机号
$order_type = $this->order_type['order_type_id'] ?? '';
if(in_array($order_type, [OrderDict::virtual, OrderDict::store])){
$this->delivery['member_address']['name'] = $this->param['member_address']['name'] ?? '';
$this->delivery['member_address']['mobile'] = $this->param['member_address']['mobile'] ?? '';
}
//收货人数据
$take_data = [
'name' => $this->delivery['member_address']['name'] ?? '',
'mobile' => $this->delivery['member_address']['mobile'] ?? '',
'telephone' => $this->delivery['member_address']['telephone'] ?? '',
'province_id' => $this->delivery['member_address']['province_id'] ?? '',
'city_id' => $this->delivery['member_address']['city_id'] ?? '',
'district_id' => $this->delivery['member_address']['district_id'] ?? '',
'community_id' => $this->delivery['member_address']['community_id'] ?? '',
'address' => $this->delivery['member_address']['address'] ?? '',
'full_address' => $this->delivery['member_address']['full_address'] ?? '',
'longitude' => $this->delivery['member_address']['longitude'] ?? '',
'latitude' => $this->delivery['member_address']['latitude'] ?? '',
];
$data = array_merge($data, $take_data);
}
//活动数据
if ($this->getInsertDataWhereResult($modules, 'promotion', $op)) {
$promotion_data = [
'promotion_type' => $this->promotion_type,
'promotion_type_name' => $this->promotion_type_name,
'promotion_status_name' => '',
];
$data = array_merge($data, $promotion_data);
}
//优惠数据
if ($this->getInsertDataWhereResult($modules, 'discount', $op)) {
$discount_data = [
'coupon_id' => $this->coupon_id,
];
$data = array_merge($data, $discount_data);
}
return $data;
}
/**
* 生成订单编号
* @return string
*/
public function createOrderNo()
{
$time_str = date('YmdHi');
$max_no = Cache::get($this->site_id . '_' . $this->member_id . '_' . $time_str);
if (empty($max_no)) {
$max_no = 1;
} else {
$max_no = $max_no + 1;
}
$order_no = $time_str . $this->member_id . sprintf('%03d', $max_no);
Cache::set($this->site_id . '_' . $this->member_id . '_' . $time_str, $max_no);
return $order_no;
}
/**
* @param $modules
* @param $key
* @param $op
* @return bool
*/
public function getInsertDataWhereResult($modules, $key, $op)
{
if ($op == 'and') {
if (!$modules || in_array($key, $modules)) {
return true;
}
} else if ($op == 'invert') {
if (!($modules && in_array($key, $modules))) {
return true;
}
}
return false;
}
/**
* 订单项数据整理
* @param $data
* @return array
*/
public function getOrderGoodsInsertData($data)
{
if ($data['num'] < 0) throw new OrderException('商品购买数量不能小于0');
return [
'order_id' => $this->order_id,
'site_id' => $this->site_id,
'store_id' => $this->store_id,
'order_no' => $this->order_no,
'member_id' => $this->member_id,
'sku_id' => $data['sku_id'],
'sku_name' => $data['sku_name'],
'sku_image' => $data['sku_image'],
'sku_no' => $data['sku_no'],
'is_virtual' => $data['is_virtual'],
'goods_class' => $data['goods_class'],
'goods_class_name' => $data['goods_class_name'],
'price' => $data['price'],
'cost_price' => $data['cost_price'],
'num' => $data['num'],
'goods_money' => $data['goods_money'],
'cost_money' => $data['cost_price'] * $data['num'],
'goods_id' => $data['goods_id'],
'delivery_status' => OrderGoodsDict::wait_delivery,
'delivery_status_name' => OrderGoodsDict::getDeliveryStatus(OrderGoodsDict::wait_delivery),
'real_goods_money' => $data['real_goods_money'],
'coupon_money' => $data['coupon_money'] ?? 0,
'promotion_money' => $data['promotion_money'],
'goods_name' => $data['goods_name'],
'sku_spec_format' => $data['sku_spec_format'],
'supplier_id' => $data['supplier_id'] ?? 0,
'is_fenxiao' => $data['is_fenxiao'] ?? 1,
'use_point' => $data['use_point'] ?? 0,
'point_money' => $data['point_money'] ?? 0.00,
'card_item_id' => $this->member_goods_card[$data['sku_id']] ?? 0,
'card_promotion_money' => $data['card_promotion_money'] ?? 0.00,
];
}
/**
* 获取订单项列表(只适用于订单 订单项已创建之后的时机)
* @return array|mixed
*/
public function getOrderGoodsList()
{
if (!$this->order_goods_list) {
$this->order_goods_list = model('order_goods')->getList([['order_id', '=', $this->order_id]]);
}
return $this->order_goods_list;
}
/**
* 获取订单对象数据
* @return array
*/
public function getOrderObjectData()
{
if (!$this->order_object_data) {
$this->order_object_data = get_object_vars($this);
}
return $this->order_object_data;
}
/**
* 订单类型判断
* @return true
*/
public function orderType()
{
if ($this->is_virtual == 1) {
$order = new VirtualOrder();
$this->order_type = [
'order_type_id' => 4,
'order_type_name' => '虚拟订单',
'order_status' => $order->order_status[0]
];
} else {
if ($this->delivery['delivery_type'] == 'express') {
$order = new Order();
$this->order_type = [
'order_type_id' => 1,
'order_type_name' => '普通订单',
'order_status' => $order->order_status[0]
];
} elseif ($this->delivery['delivery_type'] == 'store') {
$order = new StoreOrder();
$this->order_type = [
'order_type_id' => 2,
'order_type_name' => '自提订单',
'order_status' => $order->order_status[0]
];
} elseif ($this->delivery['delivery_type'] == 'local') {
$order = new LocalOrder();
$this->order_type = [
'order_type_id' => 3,
'order_type_name' => '外卖订单',
'order_status' => $order->order_status[0]
];
}
}
return true;
}
/**
* 订单创建后事件
* @return true
*/
public function orderCreateAfter()
{
Queue::push('app\job\order\OrderCreateAfter', ['create_data' => get_object_vars($this), 'order_object' => $this]);
return true;
}
/**
* 注入对象
* @param $data
* @return $this
*/
public function invokeClass($data)
{
foreach ($data as $k => $v) {
$this->$k = $v;
}
return $this;
}
/**
* 初始化订单开票基础信息
*/
public function initInvoice($param)
{
$this->order_id = $param['order_id'] ?? 0;
if(empty($this->order_id)){
return $this->error('', '缺少订单id');
}
$order_info = model('order')->getInfo([['order_id', '=', $this->order_id]], 'order_id,order_status,goods_money,promotion_money,coupon_money,point_money');
if (!$order_info) {
return $this->error('', '订单不存在');
}
if($order_info['invoice_status'] == 1){
return $this->error('', '订单已开票,请勿重复操作');
}
$this->param = $param;
$this->invokeClass($order_info);
return $this->success();
}
/**
* 更新发票数据
*/
public function saveInvoice(): array
{
$invoice_data = [
'taxpayer_number' => $this->invoice['taxpayer_number'] ?? '',
'invoice_rate' => $this->invoice['invoice_rate'] ?? 0,
'invoice_content' => $this->invoice['invoice_content'] ?? '',
'invoice_full_address' => $this->invoice['invoice_full_address'] ?? '',
'is_invoice' => $this->param['is_invoice'] ?? 0,
'invoice_type' => $this->invoice['invoice_type'] ?? 0,
'invoice_title' => $this->invoice['invoice_title'] ?? '',
'is_tax_invoice' => $this->invoice['is_tax_invoice'] ?? '',
'invoice_email' => $this->invoice['invoice_email'] ?? '',
'invoice_title_type' => $this->invoice['invoice_title_type'] ?? 0,
];
$result = model("order")->update($invoice_data,[['order_id','=',$this->order_id]]);
if($result){
return $this->success($result);
}
return $this->error([],'发票信息更新失败,请重试');
}
public function setStoreId($store_id){
$this->store_id = $store_id;
return $this;
}
}

104
app/model/order/OrderCron.php Executable file
View File

@@ -0,0 +1,104 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\express\LocalPackage;
use app\model\message\Message;
use app\model\system\Cron;
use Exception;
use think\facade\Db;
use think\facade\Queue;
/**
* 订单任务事件
* @author Administrator
*/
class OrderCron extends BaseModel
{
public static function close($data){
$order_id = $data['order_id'];
$now_time = time();
$order_config = Config::getOrderConfig($data['site_id']);
if ($order_config['auto_close'] > 0) {
$execute_time = $now_time + $order_config['auto_close'] * 60; //自动关闭时间
}
$cron_model = new Cron();
$cron_model->addCron(1, 0, '订单自动关闭', 'CronOrderClose', $execute_time, $order_id);
return true;
}
public function urgepayment(){
}
/**
* 自动完成事件
* @param $data
* @return array
*/
public static function complete($data){
$order_id = $data['order_id'];
$site_id = $data['site_id'];
//获取订单自动完成时间
$order_config = Config::getOrderConfig($site_id);
$now_time = time();
if (!empty($order_config)) {
$execute_time = $now_time + $order_config[ 'auto_complete' ] * 86400;//自动完成时间
} else {
$execute_time = $now_time + 86400;//尚未配置 默认一天
}
//设置订单自动完成事件
$cron_model = new Cron();
$cron_model->addCron(1, 0, '订单自动完成', 'CronOrderComplete', $execute_time, $order_id);
return true;
}
/**
* 关闭售后
* @param $data
* @return void
*/
public static function afterSaleClose($data){
$after_sales_time = $data['after_sales_time'];
$order_id = $data['order_id'];
$cron = new Cron();
$execute_time = strtotime("+ {$after_sales_time} day");
$cron->addCron(1, 0, '订单售后自动关闭', 'CronOrderAfterSaleClose', $execute_time, $order_id);
return true;
}
/**
* 自动收货
* @param $data
* @return true
*/
public static function takeDelivery($data){
$order_id = $data['order_id'];
$site_id = $data['site_id'];
$expire_time = $data['expire_time'] ?? 0;
if($expire_time == 0){
// 获取订单自动收货时间
$order_config = Config::getOrderConfig($site_id);
$now_time = time(); //当前时间
if ($order_config['auto_take_delivery'] > 0) {
$execute_time = $now_time + $order_config['auto_take_delivery'] * 86400; // 自动收货时间
}
}
if(!empty($execute_time)){
$cron_model = new Cron();
$cron_model->addCron(1, 0, '订单自动收货', 'CronOrderTakeDelivery', $execute_time, $order_id);
}
return true;
}
}

700
app/model/order/OrderExport.php Executable file
View File

@@ -0,0 +1,700 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\BaseModel;
use Exception;
use think\facade\Db;
/**
* 订单导出
* @author Administrator
*/
class OrderExport extends BaseModel
{
public $order_field = [
'order_no' => '订单编号',
//单商户店铺名称没有必要导出
//'site_name' => '店铺名称',
'order_name' => '订单内容',
'order_from_name' => '订单来源',
'order_type_name' => '订单类型',
'order_promotion_name' => '营销活动类型',
'out_trade_no' => '支付流水号',
'out_trade_no_2' => '支付流水号(多次支付)',
'delivery_code' => '整体提货编码',
'order_status_name' => '订单状态',
'pay_status' => '支付状态',
'delivery_status' => '配送状态',
'pay_type_name' => '支付方式',
'delivery_type_name' => '配送方式',
'nickname' => '购买人',
'name' => '客户姓名',
'mobile' => '客户手机',
'telephone' => '客户固定电话',
'province_name' => '省',
'city_name' => '市',
'district_name' => '县',
'full_address' => '详细地址',
'buyer_ip' => '客户ip',
'buyer_ask_delivery_time' => '客户要求配送时间',
'buyer_message' => '客户留言信息',
'goods_money' => '商品总金额',
'delivery_money' => '配送费用',
'promotion_money' => '订单优惠金额',
'coupon_money' => '优惠券金额',
'order_money' => '订单合计金额',
'adjust_money' => '订单调整金额',
'balance_money' => '余额支付金额',
'pay_money' => '抵扣之后应付金额',
'refund_money' => '订单退款金额',
'create_time' => '下单时间',
'pay_time' => '支付时间',
'delivery_time' => '配送时间',
'sign_time' => '签收时间',
'finish_time' => '完成时间',
'remark' => '卖家留言',
'goods_num' => '商品件数',
'delivery_status_name' => '发货状态',
'is_settlement' => '是否进行结算',
'delivery_store_name' => '门店名称',
'promotion_type_name' => '营销类型',
'form_data' => '表单数据'
];
public $order_field_sample = [
//单商户店铺名称没有必要导出
//'site_name' => '店铺名称',
'order_id' => '订单ID',
'order_no' => '订单编号',
'out_trade_no' => '支付流水号',
'delivery_store_name' => '门店名称',
'order_from_name' => '订单来源',
'order_type_name' => '订单类型',
'promotion_type_name' => '营销类型',
'order_status_name' => '订单状态',
'nickname' => '买家昵称',
'name' => '收货人姓名',
'mobile' => '收货人电话',
'full_address' => '收货地址',
'buyer_message' => '买家留言',
'remark' => '商家备注',
'goods_money' => '商品总金额',
'goods_num' => '商品总件数',
];
//订单商品信息
public $order_goods_field = [
'create_time' => '下单时间',
'pay_time' => '支付时间',
'sku_name' => '商品名称',
'sku_no' => '商品编码',
'goods_class_name' => '商品类型',
'price' => '商品卖价',
'cost_price' => '成本价',
'num' => '购买数量',
'goods_money' => '商品总价',
'cost_money' => '成本总价',
'delivery_status_name' => '配送状态',
'delivery_no' => '配送单号',
'refund_status_name' => '退款状态',
'refund_no' => '退款编号',
'refund_type' => '退货方式',
'refund_apply_money' => '退款申请金额',
'refund_reason' => '退款原因',
'refund_real_money' => '实际退款金额',
'refund_delivery_name' => '退款公司名称',
'refund_delivery_no' => '退款单号',
'refund_time' => '实际退款时间',
'refund_refuse_reason' => '退款拒绝原因',
'refund_action_time' => '申请退款时间',
'real_goods_money' => '实际商品购买价',
'refund_remark' => '退款说明',
'refund_delivery_remark' => '买家退货说明',
'refund_address' => '退货地址',
'is_refund_stock' => '是否返还库存',
'form_data' => '表单数据'
];
public $define_data = [
'pay_status' => ['type' => 2, 'data' => ['未支付', '已支付']],//支付状态
'delivery_status' => ['type' => 2, 'data' => ['待发货', '已发货', '已收货']],//配送状态
'refund_status' => ['type' => 2, 'data' => ['未退款', '已退款']],//退款状态
// 'buyer_ask_delivery_time' => [ 'type' => 1 ],//购买人要求配送时间
'create_time' => ['type' => 1],//支付时间
'pay_time' => ['type' => 1],//支付时间
'delivery_time' => ['type' => 1],//订单配送时间
'sign_time' => ['type' => 1],//订单签收时间
'finish_time' => ['type' => 1],//订单完成时间
'refund_time' => ['type' => 1],//退款到账时间
'refund_action_time' => ['type' => 1],//实际退款时间
'is_settlement' => ['type' => 2, 'data' => ['否', '是']],//是否进行结算
'refund_type' => ['type' => 2, 'data' => [1 => '仅退款', 2 => '退款退货']],//退货方式
'is_refund_stock' => ['type' => 2, 'data' => ['否', '是']],//是否返还库存
'form_data' => ['type' => 3],//表单数据
];
/**
* 查询订单项数据并导出
* @param $condition
* @param $condition_desc
* @param $site_id
* @param $join
* @param $is_verify
* @param $order_label
* @return array
*/
public function orderExport($condition, $condition_desc, $site_id, $join, $is_verify, $order_label)
{
set_time_limit(0);
try {
//预先创建导出的记录
$data = array(
'condition' => json_encode($condition_desc),
'create_time' => time(),
'type' => 1,//订单
'status' => 0,
'site_id' => $site_id
);
$records_result = $this->addExport($data);
$export_id = $records_result['data'];
if (empty($export_id)) return $this->error(null, '创建导出记录失败');
//导出字段预处理
$export_field = $this->order_field;
$field_value = [];
$field_key = [];
$field_key_array = [];
foreach ($export_field as $k => $v) {
$field_value[] = $v;
$field_key[] = "{\$$k}";
$field_key_array[] = $k;
}
//创建目录
$file_path = 'upload/order_csv/';
if (!dir_mkdir($file_path)) return $this->error(null, '导出目录创建失败');
//创建并打开文件
$file_name = date('YmdHis');
$file_path = $file_path . $file_name . '.csv';
$fp = fopen($file_path, 'w');
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
//写入第一行
$first_line = implode(',', $field_value);
fwrite($fp, $first_line . "\n");
//导出数据
$alias = 'o';
$join = [
['member m', 'm.member_id = o.member_id', 'left'],
['form_data fm', "fm.relation_id = o.order_id and scene = 'order'", 'left'],
];
if ($is_verify != 'all') {
$join[] = ['verify v', 'v.verify_code = o.virtual_code', 'left'];
}
$order_table = Db::name('order')->where($condition)->alias($alias);
$order_table = $this->parseJoin($order_table, $join);
$temp_line = implode(',', $field_key) . "\n";
$table_field = 'o.*,m.nickname,fm.form_data';
$order_table->field($table_field)->chunk(5000, function ($item_list) use ($fp, $temp_line, $field_key_array) {
//写入导出信息
$this->itemExport($item_list, $field_key_array, $temp_line, $fp);
unset($item_list);
}, 'o.order_id');
$order_table->removeOption();
fclose($fp); //每生成一个文件关闭
unset($order_table);
//更改导出记录
$records_data = array(
'path' => $file_path,
'status' => 1
);
$records_condition = array(
['export_id', '=', $export_id]
);
$this->editExport($records_data, $records_condition);
return $this->success();
} catch ( Exception $e ) {
return $this->error([], $e->getMessage() . $e->getFile() . $e->getLine());
}
}
/**
* 查询订单项数据并导出
* @param $condition
* @param $condition_desc
* @param $site_id
* @param $is_verify
* @param $order_label
* @return array
*/
public function orderGoodsExport($condition, $condition_desc, $site_id, $is_verify, $order_label)
{
set_time_limit(0);
$is_install_supply = addon_is_exit('supply');
try {
//预先创建导出的记录
$data = array(
'condition' => json_encode($condition_desc),
'create_time' => time(),
'type' => 2,//订单项
'status' => 0,
'site_id' => $site_id
);
$records_result = $this->addExport($data);
$export_id = $records_result['data'];
if (empty($export_id)) return $this->error(null, '创建导出记录失败');
//导出字段预处理
$export_field = array_merge($this->order_field_sample, $this->order_goods_field);
if($is_install_supply) $export_field['supplier_name'] = '供应商';
$field_value = [];
$field_key = [];
$field_key_array = [];
foreach ($export_field as $k => $v) {
$field_value[] = $v;
$field_key[] = "{\$$k}"; //为了防止部分代码被筛选中替换, 给变量前后两边增加字符串
$field_key_array[] = $k;
}
//创建目录
$file_path = 'upload/order_csv/';
if (!dir_mkdir($file_path)) return $this->error(null, '导出目录创建失败');
//创建并打开文件
$file_name = date('YmdHis');//csv文件名
$file_path = $file_path . $file_name . '.csv';
$fp = fopen($file_path, 'w');
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
//写入第一行表头
$first_line = implode(',', $field_value);
fwrite($fp, $first_line . "\n");
//导出数据
$alias = 'og';
$join = [
['order o', 'o.order_id = og.order_id', 'left'],
['member m', 'm.member_id = og.member_id', 'left'],
['form_data fm', "fm.relation_id = og.order_goods_id and scene = 'goods'", 'left'],
];
if ($is_verify != 'all') {
$join[] = ['verify v', 'v.verify_code = o.virtual_code', 'left'];
}
if($is_install_supply){
$join[] = ['supplier s', 'og.supplier_id = s.supplier_id', 'left'];
}
//查询字段
$order_field = 'o.create_time,o.pay_time,o.order_id,o.order_no,o.site_name,o.order_name,o.order_from_name,o.order_type_name,o.order_promotion_name,o.out_trade_no,o.out_trade_no_2,o.delivery_code,o.order_status_name,o.pay_status,o.delivery_status,o.refund_status,o.pay_type_name,o.delivery_type_name,o.name,o.mobile,o.telephone,o.full_address,o.buyer_ip,o.buyer_ask_delivery_time,o.buyer_message,o.goods_money,o.delivery_money,o.promotion_money,o.coupon_money,o.order_money,o.adjust_money,o.balance_money,o.pay_money,o.refund_money,o.pay_time,o.delivery_time,o.sign_time,o.finish_time,o.remark,o.goods_num,o.delivery_status_name,o.is_settlement,o.delivery_store_name,o.promotion_type_name,o.address,m.nickname';
$order_goods_field = 'og.order_goods_id,og.sku_name,og.sku_no,og.is_virtual,og.goods_class_name,og.price,og.cost_price,og.num,og.goods_money,og.cost_money,og.delivery_no,og.refund_no,og.refund_type,og.refund_apply_money,og.refund_reason,og.refund_real_money,og.refund_delivery_name,og.refund_delivery_no,og.refund_time,og.refund_refuse_reason,og.refund_action_time,og.real_goods_money,og.refund_remark,og.refund_delivery_remark,og.refund_address,og.is_refund_stock,og.refund_status_name,fm.form_data';
if($is_install_supply){
$order_goods_field .= ',IF(s.title is null, "", s.title) as supplier_name';
}
$table_field = $order_field . ',' . $order_goods_field;
$order_table = Db::name('order_goods')->where($condition)->alias($alias);
$order_table = $this->parseJoin($order_table, $join);
$temp_line = implode(',', $field_key) . "\n";
$export_order_field = $this->order_field_sample;
$export_order_id = 0;
$order_table->field($table_field)->chunk(5, function ($item_list) use ($fp, $temp_line, $field_key_array, $export_order_field, &$export_order_id) {
$item_list = $item_list->toArray();
//数据合并处理
foreach($item_list as &$val){
if($val['order_id'] != $export_order_id){
$export_order_id = $val['order_id'];
}else{
foreach($export_order_field as $field=>$field_name){
$val[$field] = '';
}
}
}
//写入导出信息
$this->itemExport($item_list, $field_key_array, $temp_line, $fp);
unset($item_list);
});
$order_table->removeOption();
fclose($fp); //每生成一个文件关闭
unset($order_table);
//更新导出记录
$records_data = array(
'path' => $file_path,
'status' => 1
);
$records_condition = array(
['export_id', '=', $export_id]
);
$this->editExport($records_data, $records_condition);
return $this->success();
} catch ( Exception $e ) {
return $this->error([], $e->getMessage() . $e->getLine());
}
}
/**
* 查询订单项数据并导出
* @param $condition
* @param $condition_desc
* @param int $site_id
* @return array
*/
public function orderRefundExport($condition, $condition_desc, $site_id = 0)
{
set_time_limit(0);
try {
//预先创建导出的记录
$data = array(
'condition' => json_encode($condition_desc),
'create_time' => time(),
'status' => 0,
'site_id' => $site_id
);
$records_result = $this->addRefundExport($data);
$export_id = $records_result['data'];
if (empty($export_id)) return $this->error(null, '创建导出记录失败');
//创建目录
$file_path = 'upload/order_csv/';
if (!dir_mkdir($file_path)) return $this->error(null, '导出目录创建失败');
//创建并打开文件
$file_name = date('YmdHis');
$file_path = $file_path . $file_name . '.csv';
$fp = fopen($file_path, 'w'); //生成临时文件
fwrite($fp, chr(0xEF) . chr(0xBB) . chr(0xBF));
//导出字段预处理
$export_field = array_merge($this->order_goods_field, $this->order_field);
$field_value = [];
$field_key = [];
$field_key_array = [];
foreach ($export_field as $k => $v) {
$field_value[] = $v;
$field_key[] = "{\$$k}";
$field_key_array[] = $k;
}
//写入第一行表头
$first_line = implode(',', $field_value);
fwrite($fp, $first_line . "\n");
//导出数据
$alias = 'og';
$join = [
['order o', 'o.order_id = og.order_id', 'left']
];
$order_field = 'o.order_no,o.site_name,o.order_name,o.order_from_name,o.order_type_name,o.order_promotion_name,o.out_trade_no,o.out_trade_no_2,o.delivery_code,o.order_status_name,o.pay_status,o.delivery_status,o.refund_status,o.pay_type_name,o.delivery_type_name,o.name,o.mobile,o.telephone,o.full_address,o.buyer_ip,o.buyer_ask_delivery_time,o.buyer_message,o.goods_money,o.delivery_money,o.promotion_money,o.coupon_money,o.order_money,o.adjust_money,o.balance_money,o.pay_money,o.refund_money,o.pay_time,o.delivery_time,o.sign_time,o.finish_time,o.remark,o.goods_num,o.delivery_status_name,o.is_settlement,o.delivery_store_name,o.promotion_type_name,o.address';
$order_goods_field = 'og.order_goods_id,og.sku_name,og.sku_no,og.is_virtual,og.goods_class_name,og.price,og.cost_price,og.num,og.goods_money,og.cost_money,og.delivery_no,og.refund_no,og.refund_type,og.refund_apply_money,og.refund_reason,og.refund_real_money,og.refund_delivery_name,og.refund_delivery_no,og.refund_time,og.refund_refuse_reason,og.refund_action_time,og.real_goods_money,og.refund_remark,og.refund_delivery_remark,og.refund_address,og.is_refund_stock,og.refund_status_name';
$table_field = $order_field . ',' . $order_goods_field;
$order_table = Db::name('order_goods')->where($condition)->alias($alias);
$order_table = $this->parseJoin($order_table, $join);
$temp_line = implode(',', $field_key) . "\n";
$order_table->field($table_field)->chunk(5000, function ($item_list) use ($fp, $temp_line, $field_key_array) {
//写入导出信息
$this->itemExport($item_list, $field_key_array, $temp_line, $fp);
unset($item_list);
});
$order_table->removeOption();
fclose($fp);
unset($order_table);
//将同步导出记录状态
$records_data = array(
'path' => $file_path,
'status' => 1
);
$records_condition = array(
['export_id', '=', $export_id]
);
$this->editRefundExport($records_data, $records_condition);
return $this->success();
} catch ( Exception $e ) {
return $this->error([], $e->getMessage() . $e->getLine());
}
}
/**
*
* @param $db_obj
* @param $join
* @return mixed
*/
public function parseJoin($db_obj, $join)
{
foreach ($join as $item) {
list($table, $on, $type) = $item;
$type = strtolower($type);
switch ($type) {
case 'left':
$db_obj = $db_obj->leftJoin($table, $on);
break;
case 'inner':
$db_obj = $db_obj->join($table, $on);
break;
case 'right':
$db_obj = $db_obj->rightjoin($table, $on);
break;
case 'full':
$db_obj = $db_obj->fulljoin($table, $on);
break;
default:
break;
}
}
return $db_obj;
}
/**
* 给csv写入新的数据
* @param $item_list
* @param $field_key
* @param $temp_line
* @param $fp
*/
public function itemExport($item_list, $field_key, $temp_line, $fp)
{
if(method_exists($item_list, 'toArray')){
$item_list = $item_list->toArray();
}
$item_list = $this->handleData($item_list, $field_key);
foreach ($item_list as $k => $item_v) {
$new_line_value = $temp_line;
if (isset($item_v['goods_num']) && $item_v['goods_num'] !== '') {
$item_v['goods_num'] = numberFormat($item_v['goods_num']);
}
if (isset($item_v['num']) && $item_v['num'] !== '') {
$item_v['num'] = numberFormat($item_v['num']);
}
//省市县
if($item_v['full_address'] !== ''){
$address_arr = explode('-', $item_v['full_address']);
$item_v['province_name'] = !empty($address_arr[0]) ? $address_arr[0] : '';
$item_v['city_name'] = !empty($address_arr[1]) ? $address_arr[1] : '';
$item_v['district_name'] = !empty($address_arr[2]) ? $address_arr[2] : '';
}else{
$item_v['province_name'] = '';
$item_v['city_name'] = '';
$item_v['district_name'] = '';
}
foreach ($item_v as $key => $value) {
$value = trim($value);
if ($key == 'full_address' && !empty($value)) {
$address = $item_v['address'] ?? '';
$value = $value . $address;
}
//CSV比较简单记得转义 逗号就好
$values = str_replace(',', '\\', $value . "\t");
$values = str_replace("\n", '', $values);
$values = str_replace("\r", '', $values);
$new_line_value = str_replace("{\$$key}", $values, $new_line_value);
}
//写入第一行表头
fwrite($fp, $new_line_value);
//销毁变量, 防止内存溢出
unset($new_line_value);
}
}
/**
* 数据处理
* @param $data
* @param $field
* @return array
*/
public function handleData($data, $field)
{
$define_data = $this->define_data;
foreach ($data as $k => $v) {
//获取键
$keys = array_keys($v);
foreach ($keys as $key) {
if($v[$key] === '') continue;
if (in_array($key, $field)) {
if (array_key_exists($key, $define_data)) {
$type = $define_data[$key]['type'];
switch ($type) {
case 1:
$data[$k][$key] = time_to_date((int)$v[$key]);
break;
case 2:
$define_data_data = $define_data[$key]['data'];
$data[$k][$key] = !empty($v[$key]) ? $define_data_data[$v[$key]] : '';
break;
case 3:
if (!empty($v[$key])) {
$form_data = json_decode($v[$key], true);
$form_content = '';
if (is_array($form_data)) {
foreach ($form_data as $item) {
$form_content .= $item['value']['title'] . '' . $item['val'] . '';
}
}
$data[$k][$key] = $form_content;
}
break;
}
}
}
}
}
return $data;
}
/**
* 添加导出记录
* @param $data
* @return array
*/
public function addExport($data)
{
$res = model('order_export')->add($data);
return $this->success($res);
}
/**
* 更新导出记录
* @param $data
* @param $condition
* @return array
*/
public function editExport($data, $condition)
{
$res = model('order_export')->update($data, $condition);
return $this->success($res);
}
/**
* 删除导出记录
* @param $condition
* @return array
*/
public function deleteExport($condition)
{
//先查询数据
$list = model('order_export')->getList($condition, '*');
if (!empty($list)) {
foreach ($list as $k => $v) {
if (file_exists($v['path'])) {
//删除物理文件路径
if (!unlink($v['path'])) {
//失败
} else {
//成功
}
}
}
$res = model('order_export')->delete($condition);
}
return $this->success($res ?? '');
}
/**
* 获取导出记录
* @param $condition
* @param string $field
* @param string $order
* @return array
*/
public function getExport($condition, $field = '*', $order = '')
{
$list = model('order_export')->getList($condition, $field, $order);
return $this->success($list);
}
/**
* 导出记录
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getExportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$list = model('order_export')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
/**
* 删除导出记录
* @param $condition
* @return array
*/
public function deleteRefundExport($condition)
{
$res = model('order_refund_export')->delete($condition);
return $this->success($res);
}
/**
* 添加导出记录
* @param $data
* @return array
*/
public function addRefundExport($data)
{
$res = model('order_refund_export')->add($data);
return $this->success($res);
}
/**
* 更新导出记录
* @param $data
* @param $condition
* @return array
*/
public function editRefundExport($data, $condition)
{
$res = model('order_refund_export')->update($data, $condition);
return $this->success($res);
}
/**
* 获取导出记录
* @param $condition
* @param string $field
* @param string $order
* @return array
*/
public function getRefundExport($condition, $field = '*', $order = '')
{
$list = model('order_refund_export')->getList($condition, $field, $order);
return $this->success($list);
}
/**
* 导出记录
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getRefundExportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$list = model('order_refund_export')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

71
app/model/order/OrderGoods.php Executable file
View File

@@ -0,0 +1,71 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\BaseModel;
/**
* 商品
*/
class OrderGoods extends BaseModel
{
/**
* 获取商品sku分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @param string $alias
* @param string $join
* @return array
*/
public function getOrderGoodsPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*', $alias = '', $join = '')
{
$res = model('order_goods')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
foreach ($res['list'] as &$v) {
if (isset($v['num'])) {
$v['num'] = numberFormat($v['num']);
}
}
return $this->success($res);
}
/**
* 订单项商品真实支付金额
* @param $params
* @return array
*/
public function getOrderRealPayGoodsMoney($params)
{
$order_goods_id = $params['order_goods_id'];
$order_id = $params['order_id'];
$condition = array(
['order_id', '=', $order_id]
);
$order_info = model('order')->getInfo($condition, 'order_money, pay_money, delivery_money, coupon_money, balance_money, invoice_money, point_money');
$order_money = $order_info['order_money'];
$pay_money = $order_info['pay_money'];
$delivery_money = $order_info['delivery_money'];
$invoice_money = $order_info['invoice_money'];
$balance_money = $order_info['balance_money'];
$coupon_money = $order_info['coupon_money'];
$point_money = $order_info['point_money'];
$real_pay_goods_money = $pay_money - $delivery_money - $invoice_money;//总的商品真实支付金额
$real_goods_money = $order_money - $delivery_money - $invoice_money;
$item_real_goods_money = $params['real_goods_money'];//订单项真实支付金额
$item_real_pay_goods_money = $real_goods_money > 0 ? round($item_real_goods_money / $real_goods_money * $real_pay_goods_money, 2) : 0;//四舍五入可能会多
return $this->success($item_real_pay_goods_money);
}
}

View File

@@ -0,0 +1,85 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\BaseModel;
use Exception;
class OrderImportFile extends BaseModel
{
/**
* 详情
* @param array $condition
* @param string $filed
* @return array
*/
public function getOrderImportFileInfo($condition = [], $filed = '*')
{
$info = model('order_import_file')->getInfo($condition, $filed);
return $this->success($info);
}
/**
* 删除
* @param $id
* @param $site_id
* @return array
*/
public function deleteOrderImportFile($id, $site_id)
{
model('order_import_file')->startTrans();
try {
model('order_import_file')->delete([['id', '=', $id], ['site_id', '=', $site_id]]);
model('order_import_file_log')->delete([['file_id', '=', $id]]);
model('order_import_file')->commit();
return $this->success();
} catch ( Exception $e ) {
model('order_import_file')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getOrderImportFilePageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('order_import_file')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getOrderImportFilePageLogList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*', $alias = '', $join = '')
{
$list = model('order_import_file_log')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
}

224
app/model/order/OrderLog.php Executable file
View File

@@ -0,0 +1,224 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\member\Member;
use app\model\system\User;
/**
* 订单日志
* Class OrderLog
* @package app\model\order
*/
class OrderLog extends OrderCommon
{
/**
* 获取订单日志列表
* @param $condition
* @param string $field
* @param string $order
* @param OrderCommon $instance
* @return array
*/
public static function getOrderLogList($condition, $field = '*', $order = 'action_time desc', OrderCommon $instance)
{
$res = model('order_log')->getList($condition, $field, $order);
return $instance->success($res);
}
/**
* 获取订单日志数量
* @param $condition
* @param OrderCommon $instance
* @return array
*/
public static function getOrderLogCount($condition, OrderCommon $instance)
{
$res = model('order_log')->getCount($condition);
return $instance->success($res);
}
/**
* 添加订单日志
* @param array $data
* @param OrderCommon $instance
* @return array
*/
public static function addOrderLog($data, OrderCommon $instance)
{
$data['action_time'] = time();//操作时间
$res = model('order_log')->add($data);
return $instance->success($res);
}
public function addLog($params)
{
$action = $params['action'];//操作类型
$is_auto = $params['is_auto'] ?? false;//是否是自动任务,如果是自动任务的话调用的时候就需要传递此值
$site_id = $params['site_id'];//站点id
$order_id = $params['order_id'];//订单id
$member_id = $params['member_id'] ?? 0;//操作会员id
$member_model = new Member();
$scene = $params['scene'] ?? '';//场景值 shop 店铺管理员 store 门店管理员 member 会员操作 cron 自动任务
if ($is_auto) {
$actioner_mode = '3';
$actioner_id = 0;
$actioner_name = '系统任务';
} else {
//todo 散客日志
$actioner_mode = 1;
$actioner_id = 0;
$actioner_name = '';
if ($member_id > 0) {
$member_condition = array(
['member_id', '=', $member_id],
);
$member_info = $member_model->getMemberInfo($member_condition, 'nickname,headimg')['data'] ?? [];
$actioner_mode = '1';
$actioner_id = $member_id;
$actioner_name = $member_info['nickname'] ?? '';
}
$operater_array = $params['operater'] ?? [];//操作管理员id
if (!empty($operater_array)) {
$user_model = new User();
$operater = $operater_array['uid'];
$user_condition = array(
['uid', '=', $operater],
['site_id', '=', $site_id]
);
$user_info = $user_model->getUserInfo($user_condition, 'username')['data'] ?? [];
$actioner_mode = 2;
$actioner_id = $operater;
$actioner_name = $user_info['username'];
}
}
$order_info = $this->getOrderDetail($order_id)['data'] ?? [];
if (empty($order_info))
return $this->error([], '订单不存在!');
// $balance_money = $order_info['balance_money'];//余额
// $coupon_money = $order_info['coupon_money'];//优惠券金额
// $point_money = $order_info['point_money'];//积分抵扣金额
// $hongbao_money = $order_info['hongbao_money'];//红包金额
$buyer_id = $order_info['member_id'];//买家
if (!empty($member_info) && $buyer_id == $member_id) {
$buyer_name = $member_info['nickname'];
} else {
$buyer_member_condition = array(
['member_id', '=', $member_id],
);
$buyer_member_info = $member_model->getMemberInfo($buyer_member_condition, 'nickname,headimg')['data'] ?? [];
$buyer_name = $buyer_member_info['nickname'] ?? '';
}
// $shipping_money = $order_info['delivery_money'];//运费
// $order_money = $order_info['order_money'];//订单金额
// $pay_money = $order_info['pay_money'];//支付金额
// $adjust_money = $order_info['adjust_money'];//调整金额
$close_time = time_to_date($order_info['close_time']);
// $trade_time = time_to_date($order_info['trade_time']);
// $send_time = time_to_date($order_info['send_time']);
$complete_time = time_to_date($order_info['finish_time']);
// $pay_type_name = $order_info['pay_type_name'];
$remark = $order_info['remark'];
// $trade_type = $order_info['trade_type'];
$close_cause = $order_info['close_cause'] ?? '';
$order_scene = $order_info['order_scene'];
// $full_address = $order_info['full_address'];//详细地址
$order_info['action'] = $action;
$order_log = event('OrderLog', $order_info, true);
if ($buyer_id > 0) {
if (!empty($buyer_name)) {
$buyer_name = '买家' . '【' . $buyer_name . '】';
} else {
$buyer_name = '买家';
}
} else {
$buyer_name = '散客';
}
if (empty($order_log)) {
switch ($action) {
case 'create'://订单创建
$content = $buyer_name . '下单了';
break;
case 'close'://订单关闭
$content = '订单被关闭';
if (!empty($close_cause)) {
$content .= '关闭原因';
}
break;
// case 'editaddress'://修改地址
// $content = "订单修改收货地址,新收货地址为:{$full_address}";
// break;
// case 'adjust'://订单调价
// $content = "卖家操作订单调价,调整金额:{$adjust_money},当前订单总额为:{$order_money}";
// break;
case 'pay'://订单支付
if (isset($params['operater']) && !empty($params['operater'])) {
$content = '收银员【' . $actioner_name . '】收款,订单支付成功';
} else {
$content = $buyer_name . '已支付订单';
}
break;
// case 'delivery'://发货
// $content = '卖家已发货,发货时间:' . $send_time;
// break;
// case 'receive'://收货
// $content = '买家已收货,收货时间:' . $trade_time;
// break;
// case 'local'://配送
// $content = '订单已经开始配送';
// break;
// case 'takelocal'://接收配送
// $content = '买家已接收配送';
// break;
// case 'store'://提货
// $content = '已提货';
// break;
case 'complete'://完成
$content = '订单已完成';
break;
case 'remark'://卖家备注
$content = '卖家备注:' . $remark;
break;
case 'refund':
$content = $params['content'] ?? '';
break;
}
} else {
if ($order_log['code'] < 0) {
return $order_log;
}
$content = $order_log['data']['content'];
}
$order_status_name = $order_info['order_status_name'];
$order_status = $order_info['order_status'];
$data = [
'order_id' => $order_id,
'order_status' => $order_status,
'order_status_name' => $order_status_name,
'action_way' => $actioner_mode,
'uid' => $actioner_id,
'nick_name' => $actioner_name,
'action_time' => time(),
'action' => $content,
];
$res = model('order_log')->add($data);
return $this->success();
}
}

984
app/model/order/OrderMessage.php Executable file
View File

@@ -0,0 +1,984 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\aliapp\model\Message as AliappMessage;
use addon\weapp\model\Message as WeappMessage;
use addon\wechat\model\Message as WechatMessage;
use app\dict\order\OrderDict;
use app\model\BaseModel;
use app\model\member\Member;
use app\model\message\Sms;
use app\model\shop\ShopAcceptMessage;
use app\model\system\Pay as PayModel;
use GuzzleHttp\Exception\GuzzleException;
/**
* 订单消息操作
*
* @author Administrator
*
*/
class OrderMessage extends BaseModel
{
/************************************************ 会员消息 start ************************************************************/
/**
* 订单催付通知
* @param $data
*/
public function messageOrderUrgePayment($data)
{
trace('进入订单催付消息发送');
$order_info = model('order')->getInfo([['order_id', '=', $data['order_id']]], 'full_address,site_id,create_time,address,order_no,mobile,member_id,order_type,create_time,order_name,order_money');
//计算订单自动关闭时间
$order_config = Config::getOrderConfig();
$execute_time = $order_info['create_time'] + $order_config['auto_close'] * 60; //自动关闭时间
//会员信息
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]])['data'];
// 发送短信
if (!empty($member_info) && !empty($member_info['mobile'])) {
$var_parse = [
'goodsname' => replaceSpecialChar(str_sub($order_info['order_name'])),//商品名称
'expiretime' => date('d', $execute_time) . '日' . date('H', $execute_time) . '时' . date('i', $execute_time) . '分'
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model = new Sms();
$res = $sms_model->sendMessage($data);
trace($res, '订单催付短信发送结果');
}
// 【弃用,暂无模板信息,无法使用,等待后续微信支持后开发】公众号模板消息
// if (!empty($member_info) && !empty($member_info[ "wx_openid" ])) {
// $wechat_model = new WechatMessage();
// $data[ "openid" ] = $member_info[ "wx_openid" ];
// $data[ "template_data" ] = [
// 'keyword1' => $order_info[ 'order_no' ],
// 'keyword2' => $order_info[ 'order_name' ],
// 'keyword3' => '待支付',
// 'keyword4' => '请在' . time_to_date($execute_time) . '前完成支付'
// ];
// $data[ "page" ] = $this->handleUrl($order_info[ 'order_type' ], $data[ 'order_id' ]);
// $res = $wechat_model->sendMessage($data);
// trace($res, '订单催付公众号模板消息发送结果');
// }
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string1' => [
'value' => $order_info['order_no']
],
'thing2' => [
'value' => $order_info['order_name']
],
'character_string3' => [
'value' => $order_info['order_money'],
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $data['order_id']);
$res = $weapp_model->sendMessage($data);
trace($res, '订单催付小程序订阅消息发送结果');
}
}
/**
* 处理订单链接
* @param $order_type
* @param $order_id
* @return string
*/
public function handleUrl($order_type, $order_id)
{
return 'pages/order/detail?order_id=' . $order_id;
}
/**
* 消息发送——支付成功
* @param $params
* @throws GuzzleException
*/
public function messagePaySuccess($params)
{
$member_model = new Member();
$member_info_result = $member_model->getMemberInfo([['member_id', '=', $params['member_id']]]);
$member_info = $member_info_result['data'];
// 发送短信
if (!empty($member_info) && !empty($member_info['mobile'])) {
$var_parse = [
'orderno' => $params['order_no'],
'username' => replaceSpecialChar($member_info['nickname']),
'ordermoney' => $params['order_money'],
];
$params['sms_account'] = $member_info['mobile'] ?? '';//手机号
$params['var_parse'] = $var_parse;
$sms_model = new Sms();
$res = $sms_model->sendMessage($params);
trace($res, '订单支付短信发送结果');
}
// 绑定微信公众号才发送
if (!empty($member_info) && !empty($member_info['wx_openid'])) {
$wechat_model = new WechatMessage();
$data = $params;
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'time4' => time_to_date($params['create_time']), // 下单时间
'character_string2' => $params['order_no'], // 订单号
'thing3' => str_sub($params['order_name']), // 商品名称
'amount5' => $params['order_money'], // 支付金额
];
$data['page'] = $this->handleUrl($params['order_type'], $params['order_id']);
$res = $wechat_model->sendMessage($data);
trace($res, '订单支付公众号发送结果');
}
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data = $params;
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string1' => [
'value' => $params['order_no']
],
'time2' => [
'value' => time_to_date($params['create_time'])
],
'thing4' => [
'value' => str_sub($params['order_name'])
],
'amount3' => [
'value' => $params['order_money']
],
];
$data['page'] = $this->handleUrl($params['order_type'], $params['order_id']);
$res = $weapp_model->sendMessage($data);
trace($res, '订单支付小程序订阅号发送结果');
}
//发送支付宝订阅消息
if (!empty($member_info) && !empty($member_info['ali_openid']) && addon_is_exit('aliapp', $params['site_id'])) {
$aliapp_model = new AliappMessage();
$data = $params;
$data['openid'] = $member_info['ali_openid'];
$data['template_data'] = [
'keyword1' => [
'value' => '已支付'
],
'keyword2' => [
'value' => time_to_date($params['create_time'])
],
'keyword3' => [
'value' => str_sub($params['order_name'])
],
'keyword4' => [
'value' => '¥' . $params['order_money']
]
];
$data['page'] = $this->handleUrl($params['order_type'], $params['order_id']);
$res = $aliapp_model->sendMessage($data);
trace($res, '订单支付支付宝小程序订阅号发送结果');
}
}
/**
* 订单关闭提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderClose($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,order_name,create_time,order_money,close_time');
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]])['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
// 发送微信公众号模板消息
if (!empty($member_info) && !empty($member_info['wx_openid'])) {
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'character_string1' => $order_info['order_no'], // 订单号
'thing7' => str_sub($order_info['order_name']), // 商品名称
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
}
// 发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'thing4' => [
'value' => str_sub($order_info['order_name'])
],
'character_string1' => [
'value' => $order_info['order_no']
],
'time3' => [
'value' => time_to_date($order_info['create_time'])
],
'amount6' => [
'value' => $order_info['order_money']
],
'time5' => [
'value' => time_to_date($order_info['close_time'])
],
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 买家订单完成通知商家
* @param $data
* @throws GuzzleException
*/
public function messageBuyerOrderComplete($data)
{
//发送短信
// $sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,order_name,create_time,finish_time');
$shop_accept_message_model = new ShopAcceptMessage();
$result = $shop_accept_message_model->getShopAcceptMessageList();
$list = $result['data'];
//发送模板消息
if (!empty($list)) {
foreach ($list as $v) {
if (!empty($v['wx_openid'])) {
$wechat_model = new WechatMessage();
$data['openid'] = $v['wx_openid'];
$data['template_data'] = [
'character_string7' => $order_info['order_no'], // 订单号
'thing5' => str_sub($order_info['order_name']), // 商品名称
'time10' => time_to_date($order_info['finish_time']), // 完成时间
];
$data['page'] = $this->handleMobileShopUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
}
}
}
}
/**
* 处理商家端订单页面路径
* @param $order_type
* @param $order_id
* @return string
*/
public function handleMobileShopUrl($order_type, $order_id)
{
switch ($order_type) {
case 2:
return 'pages/order/detail/store?order_id=' . $order_id . '&template=store';
case 3:
return 'pages/order/detail/local?order_id=' . $order_id . '&template=local';
case 4:
return 'pages/order/detail/virtual?order_id=' . $order_id . '&template=virtual';
default:
return 'pages/order/detail/basis?order_id=' . $order_id . '&template=basis';
}
}
/**
* 订单完成提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderComplete($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,order_name,create_time,finish_time');
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]])['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
//发送模板消息
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'character_string7' => $order_info['order_no'],
'thing5' => str_sub($order_info['order_name']),
'time10' => time_to_date($order_info['create_time']),
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string1' => [
'value' => $order_info['order_no']
],
'thing2' => [
'value' => str_sub($order_info['order_name'])
],
'time4' => [
'value' => time_to_date($order_info['finish_time'])
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 订单发货提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderDelivery($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,order_name,goods_num,order_money,delivery_time');
$member_model = new Member();
$member_info_result = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]]);
$member_info = $member_info_result['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
// 发送模板消息
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'character_string2' => $order_info['order_no'], // 订单编号
'thing4' => str_sub($order_info['order_name']), // 商品名称
'number5' => numberFormat($order_info['goods_num']), // 商品数量
'amount8' => $order_info['order_money'], // 订单金额
'time12' => time_to_date($order_info['delivery_time']), // 发货时间
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string2' => [
'value' => $order_info['order_no']
],
'thing1' => [
'value' => str_sub($order_info['order_name'])
],
'amount7' => [
'value' => $order_info['order_money']
],
'date3' => [
'value' => time_to_date($order_info['delivery_time'] ? $order_info['delivery_time'] : time())
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 订单收货提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderTakeDelivery($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,full_address,address,name,order_name,sign_time');
$member_model = new Member();
$member_info_result = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]]);
$member_info = $member_info_result['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
//发送模板消息
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'keyword1' => $order_info['full_address'] . $order_info['address'],
'keyword2' => $order_info['name'],
'keyword3' => $order_info['order_no'],
'keyword4' => str_sub($order_info['order_name']),
'keyword5' => time_to_date($order_info['sign_time']),
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string1' => [
'value' => $order_info['order_no']
],
'thing2' => [
'value' => str_sub($order_info['order_name'])
],
'time7' => [
'value' => time_to_date($order_info['sign_time'])
],
'thing9' => [
'value' => str_sub($order_info['name'])
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 订单退款同意提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderRefundAgree($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id');
$member_model = new Member();
$member_info_result = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]]);
$member_info = $member_info_result['data'];
$order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $data['order_goods_id']]], 'refund_apply_money,refund_time,refund_action_time');
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
//发送模板消息
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'character_string5' => $order_info['order_no'], // 订单编号
'amount2' => $order_goods_info['refund_apply_money'], // 退款金额
'time4' => time_to_date(time()), // 退款时间
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string3' => [
'value' => $order_info['order_no']
],
'amount1' => [
'value' => $order_goods_info['refund_apply_money']
],
'phrase7' => [
'value' => '成功'
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 订单退款拒绝提醒
* @param $data
* @throws GuzzleException
*/
public function messageOrderRefundRefuse($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id');
$order_goods_info = model('order_goods')->getInfo([['order_goods_id', '=', $data['order_goods_id']]], 'refund_apply_money,refund_time,refund_action_time');
$member_model = new Member();
$member_info_result = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]]);
$member_info = $member_info_result['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
//发送模板消息
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'character_string1' => $order_info['order_no'], // 订单编号
'amount2' => $order_goods_info['refund_apply_money'], // 退款金额
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$wechat_model->sendMessage($data);
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string4' => [
'value' => $order_info['order_no']
],
'amount3' => [
'value' => $order_goods_info['refund_apply_money']
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $order_id);
$weapp_model->sendMessage($data);
}
}
/**
* 核销码过期提醒
* @param $data
*/
public function messageVerifyCodeExpire($data)
{
// 发送短信
$sms_model = new Sms();
// 商品表
$goods_virtual_info = model('goods_virtual')->getInfo([['order_id', '=', $data['relate_id']]]);
// 总核销次数
$total_verify_num = model('goods_virtual')->getCount([['order_id', '=', $data['relate_id']]]);
// 已核销次数
$verify_num = model('goods_virtual')->getCount([['order_id', '=', $data['relate_id']], ['is_veirfy', '=', 1]]);
// 剩余次数
$residue = $total_verify_num - $verify_num;
// 用户信息
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $goods_virtual_info['member_id']]])['data'];
$order_info = model('order')->getInfo([['order_id', '=', $goods_virtual_info['order_id']]], 'mobile,order_no,order_name,order_type,pay_time');
trace($residue);
if ($residue > 0) {
// 公众号模板消息
// 【弃用,暂无模板信息,无法使用,等待后续微信支持后开发】绑定微信公众号才发送
// if (!empty($member_info) && !empty($member_info[ "wx_openid" ])) {
// $wechat_model = new WechatMessage();
// $data[ "openid" ] = $member_info[ "wx_openid" ];
// $data[ "template_data" ] = [
// 'keyword1' => $order_info[ 'order_no' ],
// 'keyword2' => $order_info[ 'order_name' ],
// 'keyword3' => '已过期'
// ];
// $wechat_model->sendMessage($data);
// }
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'character_string1' => [
'value' => $order_info['order_no'],
],
'time2' => [
'value' => time_to_date($order_info['pay_time'])
],
'time3' => [
'value' => time_to_date(time())
],
'thing5' => [
'value' => '您的订单核销码已过期',
],
];
$weapp_model->sendMessage($data);
}
// 短信通知
if (!empty($member_info) && !empty($member_info['mobile'])) {
//"desc" => '您购买的'.$goods_virtual_info['sku_name'].'将在'.date('Y-m-d H:i:s',$goods_virtual_info['expire_time']).'到期',//商品名称,
$var_parse = [
'sitename' => replaceSpecialChar($data['site_info']['site_name']),
'sku_name' => $goods_virtual_info['sku_name']
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
}
}
}
/************************************************ 会员消息 end ************************************************************/
/**
* 核销商品临期提醒
* @param $data
*/
public function messageVerifyOrderOutTime($data)
{
// 商品表
$goods_virtual_info = model('goods_virtual')->getInfo([['order_id', '=', $data['order_id']]]);
// 总核销次数
$total_verify_num = model('goods_virtual')->getCount([['order_id', '=', $data['order_id']]]);
// 已核销次数
$verify_num = model('goods_virtual')->getCount([['order_id', '=', $data['order_id']], ['is_veirfy', '=', 1]]);
// 剩余次数
$residue = $total_verify_num - $verify_num;
// 用户信息
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $goods_virtual_info['member_id']]])['data'];
// 手机号
$order_info = model('order')->getInfo([['order_id', '=', $data['order_id']]], 'order_type,mobile,order_no,order_name');
if ($residue > 0) {
// 公众号模板消息
// 【弃用,暂无模板信息,无法使用,等待后续微信支持后开发】绑定微信公众号才发送
// if (!empty($member_info) && !empty($member_info[ "wx_openid" ])) {
// $wechat_model = new WechatMessage();
// $data[ "openid" ] = $member_info[ "wx_openid" ];
// $data[ "template_data" ] = [
// 'keyword1' => $order_info[ 'order_no' ],
// 'keyword2' => str_sub($order_info[ 'order_name' ]),
// 'keyword3' => '未核销'
// ];
// $wechat_model->sendMessage($data);
// }
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
// 核销码临近到期时间(小时)
$config_model = new Config();
$verify_config = $config_model->getOrderVerifyConfig($data['site_id'])['data']['value'];
$order_verify_out_time = $verify_config['order_verify_time_out'] ?? 24;
$time_strtime = $order_verify_out_time * 3600;
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'thing1' => [
'value' => str_sub($order_info['order_name'])
],
'date2' => [
'value' => time_to_date(time() + $time_strtime),
],
'thing3' => [
'value' => '请在到期前核销,以免影响您的使用!',
]
];
$weapp_model->sendMessage($data);
}
// 短信消息
$sms = new Sms();
$var_parse = [
'username' => $member_info['username'],//用户名称
'sku_name' => $goods_virtual_info['sku_name'],//商品名称
'expire_time' => date('Y-m-d H:i:s', $goods_virtual_info['expire_time'])//到期时间
];
$data['sms_account'] = $order_info['phone'];//手机号
$data['var_parse'] = $var_parse;
$sms->sendMessage($data);
}
}
/**
* 订单核销通知
* @param $data
* @throws GuzzleException
*/
public function messageOrderVerify($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_type,order_no,mobile,member_id,order_name,goods_num,sign_time,delivery_store_name');
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]])['data'];
$var_parse = [
'orderno' => $order_info['order_no'],//订单编号
];
$data['sms_account'] = $member_info['mobile'];//手机号
$data['var_parse'] = $var_parse;
$sms_model->sendMessage($data);
// 公众号模板消息
//绑定微信公众号才发送
if (!empty($member_info) && !empty($member_info['wx_openid'])) {
$wechat_model = new WechatMessage();
$data['openid'] = $member_info['wx_openid'];
$data['template_data'] = [
'thing2' => str_sub($order_info['order_name']),// 商品名称
'character_string6' => 1, // 核销数量
'time4' => time_to_date(time()), // 核销时间
];
$wechat_model->sendMessage($data);
}
//发送订阅消息
if (!empty($member_info) && !empty($member_info['weapp_openid'])) {
$weapp_model = new WeappMessage();
$data['openid'] = $member_info['weapp_openid'];
$data['template_data'] = [
'phrase1' => [
'value' => '已核销'
],
'time2' => [
'value' => time_to_date(time()),
],
'character_string3' => [
'value' => $order_info['order_no'],
]
];
$data['page'] = $this->handleUrl($order_info['order_type'], $data['order_id']);
$weapp_model->sendMessage($data);
}
}
/**
* 买家发起退款,卖家通知
* @param $data
* @throws GuzzleException
*/
public function messageOrderRefundApply($data)
{
//发送短信
$sms_model = new Sms();
$order_goods_id = $data['order_goods_id'];
$order_goods_info = model('order_goods')->getInfo(['order_goods_id' => $order_goods_id], '*');
$order_info = model('order')->getInfo([['order_id', '=', $order_goods_info['order_id']]], 'order_no,mobile,member_id,site_id,name,order_type');
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $order_info['member_id']]])['data'];
$var_parse = [
'username' => replaceSpecialChar($member_info['nickname']),//会员名
'orderno' => $order_info['order_no'],//订单编号
'goodsname' => mb_substr(replaceSpecialChar($order_goods_info['sku_name']), 0, 25, 'UTF8'),//商品名称
'refundno' => $order_goods_info['refund_no'],//退款编号
'refundmoney' => $order_goods_info['refund_apply_money'],//退款申请金额
'refundreason' => replaceSpecialChar($order_goods_info['refund_reason']),//退款原因
];
$data['var_parse'] = $var_parse;
// $site_id = $data['site_id'];
// $shop_info = model("shop")->getInfo([["site_id", "=", $site_id]], "mobile,email");
// $message_data["sms_account"] = $shop_info["mobile"];//手机号
$shop_accept_message_model = new ShopAcceptMessage();
$result = $shop_accept_message_model->getShopAcceptMessageList();
$list = $result['data'];
if (!empty($list)) {
foreach ($list as $v) {
$message_data = $data;
$message_data['sms_account'] = $v['mobile'];//手机号
$sms_model->sendMessage($message_data);
if ($v['wx_openid'] != '') {
$wechat_model = new WechatMessage();
$data['openid'] = $v['wx_openid'];
$data['template_data'] = [
'character_string3' => $order_goods_info['order_no'], // 订单编号
'time10' => time_to_date($order_goods_info['refund_action_time']), // 申请时间
'thing2' => str_sub($order_goods_info['sku_name']), // 商品名称
'amount1' => $order_goods_info['refund_apply_money'], // 退款金额
];
$data['page'] = 'pages/order/refund/detail?order_goods_id=' . $order_goods_id;
$wechat_model->sendMessage($data);
}
}
}
}
/**
* 买家已退款,卖家通知
* @param $data
* @throws GuzzleException
*/
public function messageOrderRefundDelivery($data)
{
//发送短信
$sms_model = new Sms();
$order_id = $data['order_goods_info']['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_no');
$var_parse = [
'orderno' => $order_info['order_no'],//商品名称
];
// $site_id = $data['site_id'];
// $shop_info = model("shop")->getInfo([["site_id", "=", $site_id]], "mobile,email");
// $message_data["sms_account"] = $shop_info["mobile"];//手机号
$data['var_parse'] = $var_parse;
$shop_accept_message_model = new ShopAcceptMessage();
$result = $shop_accept_message_model->getShopAcceptMessageList();
$list = $result['data'];
if (!empty($list)) {
foreach ($list as $v) {
$message_data = $data;
$message_data['sms_account'] = $v['mobile'];//手机号
$sms_model->sendMessage($message_data);
if ($v['wx_openid'] != '') {
$wechat_model = new WechatMessage();
$data['openid'] = $v['wx_openid'];
$data['template_data'] = [
'character_string6' => $data['order_goods_info']['order_no'], // 订单号
'thing3' => str_sub($data['order_goods_info']['sku_name']), // 商品名称
'time4' => time_to_date(time()), // 申请时间
];
$data['page'] = 'pages/order/refund/detail?order_goods_id=' . $data['order_goods_info']['order_goods_id'];
$wechat_model->sendMessage($data);
}
}
}
}
/**
* 买家支付成功,卖家通知
* @param $data
* @throws GuzzleException
*/
public function messageBuyerPaySuccess($data)
{
//发送短信
$sms_model = new Sms();
$var_parse = [
'orderno' => $data['order_no'],//订单编号
'ordermoney' => $data['order_money'],//退款申请金额
];
// $site_id = $data['site_id'];
// $shop_info = model("shop")->getInfo([["site_id", "=", $site_id]], "mobile,email");
// $message_data["sms_account"] = $shop_info["mobile"];//手机号
$data['var_parse'] = $var_parse;
$shop_accept_message_model = new ShopAcceptMessage();
$result = $shop_accept_message_model->getShopAcceptMessageList();
$list = $result['data'];
if (!empty($list)) {
foreach ($list as $v) {
$message_data = $data;
$message_data['sms_account'] = $v['mobile'];//手机号
$sms_model->sendMessage($message_data);
$member_model = new Member();
$member_info = $member_model->getMemberInfo([['member_id', '=', $data['member_id']]])['data'];
if ($v['wx_openid'] != '') {
$wechat_model = new WechatMessage();
$data['openid'] = $v['wx_openid'];
$data['template_data'] = [
'time4' => time_to_date($data['pay_time']), // 支付时间
'character_string2' => $data['order_no'], // 订单编号
'thing1' => str_sub($member_info['nickname'], 16), // 客户名称
'thing8' => str_sub($data['order_name']), // 产品名称
'amount3' => $data['order_money'], // 订单金额
];
$data['page'] = $this->handleMobileShopUrl($data['order_type'], $data['order_id']);
$wechat_model->sendMessage($data);
}
}
}
}
/**
* 外卖订单 指定配送员后 同步短信推送
* @param $param
* @throws \GuzzleHttp\Exception\GuzzleException
*/
public function messageLocalWaitDelivery($param)
{
//短信推送业务
$order_info = model('order')->getInfo([['order_id', '=', $param['param']['order_id']]], 'out_trade_no');
$pay_model = new PayModel();
$pay_info = $pay_model->getPayInfo($order_info['out_trade_no'])['data'];
if (!empty($pay_info)) {
$sms_model = new Sms();
if (!empty($param['param']['deliverer_mobile'])) {
$message_data = [
'var_parse' => [
'order_name' => str_sub(replaceSpecialChar($pay_info['pay_body']), 25),
'pay_money' => $pay_info['pay_money'],
'out_trade_no' => $pay_info['out_trade_no'],
],
'sms_account' => $param['param']['deliverer_mobile'],
];
$sms_model->sendMessage(array_merge($param, $message_data));
}
}
}
}

61
app/model/order/OrderPay.php Executable file
View File

@@ -0,0 +1,61 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\model\system\Pay;
use think\facade\Log;
/**
* 订单支付相关
*
* @author Administrator
*
*/
class OrderPay extends OrderCommon
{
/**
* 改变订单的交易流水号
* @param $params
* @return array
*/
public function resetOrderTradeNo($params)
{
$out_trade_no = $params['out_trade_no'];
$order_condition = array(
['pay_status', '=', 0]
);
$order_condition[] = ['out_trade_no', '=', $out_trade_no];
$order_info = model('order')->getInfo($order_condition, 'pay_money,order_name,out_trade_no,order_id,pay_status,site_id,member_id,member_card_order');
//判断订单数是否匹配
if (empty($order_info))
return $this->error([], '没有可支付订单!');
$pay_model = new Pay();
$result = $pay_model->closePay($out_trade_no);//关闭旧支付单据
if ($result['code'] < 0) {
return $result;
}
$member_id = $order_info['member_id'];
$new_out_trade_no = $pay_model->createOutTradeNo($member_id ?? 0);
$update_data = array(
'out_trade_no' => $new_out_trade_no
);
model('order')->update($update_data, [['out_trade_no', '=', $out_trade_no], ['pay_status', '=', 0]]);
model('member_level_order')->update($update_data, [['out_trade_no', '=', $out_trade_no], ['pay_status', '=', 0]]);
Log::write('resetOrderTradeNo_old_'.$out_trade_no.'_new_'.$new_out_trade_no);
$pay_model->addPay($order_info['site_id'], $new_out_trade_no, '', $order_info['order_name'], $order_info['order_name'], $order_info['pay_money'], '', 'OrderPayNotify', '', $order_info['order_id'], $order_info['member_id']);
return $this->success($new_out_trade_no);
}
}

1440
app/model/order/OrderRefund.php Executable file

File diff suppressed because it is too large Load Diff

286
app/model/order/OrderStock.php Executable file
View File

@@ -0,0 +1,286 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\stock\model\stock\Stock as StockAddonModel;
use app\dict\goods\GoodsDict;
use app\model\BaseModel;
use app\model\stock\GoodsStock;
use app\model\stock\SaleStock;
use app\model\store\Store;
use app\model\storegoods\StoreGoods;
use extend\exception\StockException;
use think\facade\Cache;
/**
* 商品库存
*/
class OrderStock extends BaseModel
{
/**
* 扣除订单库存
* @param $sku_id
* @param $num
* @param int $store_id
* @param array $sku_info
* @param array $create_data
* @return array
*/
public function decOrderSaleStock($params)
{
$store_id = $params['store_id'] ?? 0;
$goods_sku_data = $params['goods_sku_data'] ?? [];
$sale_stock_model = new SaleStock();
$create_order_data = $params['create_order_data'];
if ($store_id > 0) {
$store_info = $create_order_data['store_info'] ?? [];
if (empty($store_info)) {
$store_model = new Store();
$store_condition = [
['store_id', '=', $store_id]
];
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
}
$stock_type = $store_info['stock_type'];
if ($stock_type == 'all') {//如果总部统一库存的话就扣除总店的
$store_id = 0;
}
}
$params = [
'goods_sku_list' => $goods_sku_data,
'store_id' => $store_id,
'is_allow_negative' => false
];
$sale_stock_result = $sale_stock_model->decGoodsStock($params);
if ($sale_stock_result['code'] < 0) {
return $sale_stock_result;
}
return $this->success();
}
/**
* 返还订单库存
* @param $sku_id
* @param $num
* @param int $store_id
* @return array
*/
public function incOrderSaleStock($params)
{
$store_id = $params['store_id'] ?? 0;
$goods_sku_data = $params['goods_sku_data'] ?? [];
$sale_stock_model = new SaleStock();
if ($store_id > 0) {
$store_model = new Store();
$store_condition = [
['store_id', '=', $store_id]
];
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
$stock_type = $store_info['stock_type'];
if ($stock_type == 'all') {//如果总部统一库存的话就扣除总店的
$store_id = 0;
}
}
$params = [
'goods_sku_list' => $goods_sku_data,
'store_id' => $store_id
];
$sale_stock_result = $sale_stock_model->incGoodsStock($params);
if ($sale_stock_result['code'] < 0) {
return $sale_stock_result;
}
return $this->success();
}
/**
* 扣除库存(用于订单)
* @param $params
* @return array
*/
public function decOrderStock($params)
{
$params['is_out_stock'] = $params['is_out_stock'] ?? 0;//不再改变销售库存
$store_id = $params['store_id'] ?? 0;
//是否允许负库存
$is_allow_negative = $params['is_allow_negative'] ?? false;
if ($store_id > 0) {
$store_model = new Store();
$store_condition = [
['store_id', '=', $store_id]
];
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
$stock_type = $store_info['stock_type'];
if ($stock_type == 'all') {//如果总部统一库存的话就扣除总店的
$params['store_id'] = 0;
}
}
$is_exist = addon_is_exit('stock');
if ($is_exist) {
$stock_model = new StockAddonModel();
}
$goods_sku_list = $params['goods_sku_list'] ?? [];
if (!empty($goods_sku_list)) {
$goods_sku_list_1 = [];
$goods_sku_list_2 = [];
foreach ($goods_sku_list as $k => $v) {
if ($is_exist && $v['goods_class'] == GoodsDict::real) {
$goods_sku_list_1[] = $v;
} else {
if (in_array($v['goods_class'], [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$goods_sku_list_2[] = $v;
}
}
}
if (!empty($goods_sku_list_1)) {
$params['goods_sku_list'] = $goods_sku_list_1;
$params['key'] = 'SEAILCK';
$result = $stock_model->changeStock($params);
if ($result['code'] < 0) {
return $result;
}
}
if (!empty($goods_sku_list_2)) {
$params['goods_sku_list'] = $goods_sku_list_2;
$goods_stock_model = new GoodsStock();
$result = $goods_stock_model->decGoodsStock($params);
if ($result['code'] < 0) {
return $result;
}
}
} else {
$goods_class = $params['goods_class'];
$params['stock'] = $params['num'] ?? $params['stock'];
if ($is_exist && $goods_class == GoodsDict::real) {
$params['key'] = 'SEAILCK';
$result = $stock_model->changeStock($params);
} else {//没有的话直接生成支付单据
$goods_stock_model = new GoodsStock();
$result = $goods_stock_model->decGoodsStock($params);
}
}
return $result ?? $this->success();
}
/**
* 返还库存(用于订单)
* @param $params
* @return array
*/
public function incOrderStock($params)
{
$store_id = $params['store_id'] ?? 0;
if ($store_id > 0) {
$store_model = new Store();
$store_condition = [
['store_id', '=', $store_id]
];
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
$stock_type = $store_info['stock_type'];
if ($stock_type == 'all') {//如果总部统一库存的话就返还总店的
$params['store_id'] = 0;
}
}
$is_exist = addon_is_exit('stock');
if ($is_exist) {
$stock_model = new StockAddonModel();
}
$goods_sku_list = $params['goods_sku_list'] ?? [];
if (!empty($goods_sku_list)) {
$goods_sku_list_1 = [];
$goods_sku_list_2 = [];
foreach ($goods_sku_list as $v) {
if ($is_exist && $v['goods_class'] == GoodsDict::real) {
$goods_sku_list_1[] = $v;
} else {
if (in_array($v['goods_class'], [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$goods_sku_list_2[] = $v;
}
}
}
if (!empty($goods_sku_list_1)) {
$params['goods_sku_list'] = $goods_sku_list_1;
$params['key'] = 'REFUND';
$result = $stock_model->changeStock($params);
if ($result['code'] < 0) {
return $result;
}
}
if (!empty($goods_sku_list_2)) {
$params['goods_sku_list'] = $goods_sku_list_2;
$goods_stock_model = new GoodsStock();
$result = $goods_stock_model->incGoodsStock($params);
if ($result['code'] < 0) {
return $result;
}
}
} else {
$goods_class = $params['goods_class'];
$params['stock'] = $params['num'] ?? $params['stock'];
if ($is_exist && $goods_class == GoodsDict::real) {
$params['key'] = 'REFUND';
$result = $stock_model->changeStock($params);
} else {//没有的话直接生成支付单据
$goods_stock_model = new GoodsStock();
$result = $goods_stock_model->incGoodsStock($params);
}
}
return $result ?? $this->success();
}
/**
* 校验商品库存是否足够
* @return void
*/
public function checkStock($params){
$store_id = $params['store_id'] ?? 0;
$goods_sku_data = $params['goods_sku_data'];
$store_model = new Store();
if ($store_id > 0) {
$store_condition = [
['store_id', '=', $store_id]
];
$store_info = $store_model->getStoreInfo($store_condition)['data'] ?? [];
$stock_type = $store_info['stock_type'];
if ($stock_type == 'all') {//如果总部统一库存的话就扣除总店的
$store_id = 0;
}
}
if($store_id == 0){
$store_info = $store_model->getDefaultStore()['data'] ?? [];
$store_id = $store_info['store_id'];
}
$goods_sku_ids = array_column($goods_sku_data, 'sku_id');
$goods_sku_list = model('store_goods_sku')->getColumn([['sku_id', 'in', $goods_sku_ids], ['store_id', '=', $store_id]], '*', 'sku_id');
foreach($goods_sku_data as $v){
$item_sku_id = $v['sku_id'];
$item_sku_name = $v['sku_name'];
$item_goods_sku = $goods_sku_list[$item_sku_id] ?? [];
if(!$item_goods_sku) throw new StockException('商品:【'.$item_sku_name.'】 库存不足!');
$item_num = $v['num'];
if($item_num > $item_goods_sku['stock']) throw new StockException('商品:【'.$item_sku_name.'】 库存不足!');
}
return true;
}
}

345
app/model/order/StoreOrder.php Executable file
View File

@@ -0,0 +1,345 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use app\dict\order\OrderGoodsDict;
use app\dict\order_refund\OrderRefundDict;
use app\model\message\Message;
use app\model\verify\Verify;
use think\db\exception\DbException;
use think\facade\Queue;
/**
* 门店自提订单
*
* @author Administrator
*
*/
class StoreOrder extends OrderCommon
{
/************************************************************* 订单状态 ***********************************************/
// 订单创建
public const ORDER_CREATE = 0;
// 订单已支付
public const ORDER_PAY = 1;
// 订单待提货
public const ORDER_PENDING_DELIVERY = 2;
// 订单已发货(配货)
public const ORDER_DELIVERY = 3;
// 订单已收货
public const ORDER_TAKE_DELIVERY = 4;
// 订单已结算完成
public const ORDER_COMPLETE = 10;
// 订单已关闭
public const ORDER_CLOSE = -1;
// 订单类型
public $order_type = 2;
// 订单状态
public $order_status = [
self::ORDER_CREATE => [
'status' => self::ORDER_CREATE,
'name' => '待支付',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon.png',
'action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderAdjustMoney',
'title' => '调整价格',
'color' => ''
],
],
'member_action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderPay',
'title' => '支付',
'color' => ''
],
],
'color' => ''
],
self::ORDER_PENDING_DELIVERY => [
'status' => self::ORDER_PENDING_DELIVERY,
'name' => '待提货',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-send.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_TAKE_DELIVERY => [
'status' => self::ORDER_TAKE_DELIVERY,
'name' => '已提货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_COMPLETE => [
'status' => self::ORDER_COMPLETE,
'name' => '已完成',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_CLOSE => [
'status' => self::ORDER_CLOSE,
'name' => '已关闭',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-close.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
];
/**
* 门店订单
* @param $data
* @return array
* @throws DbException
*/
public function orderPay($data)
{
$order_info = $data['order_info'];
$member_info = $data['member_info'];
$pay_type = $data['pay_type'];
$member_id = $order_info['member_id'] ?? 0;
$log_data = $data['log_data'] ?? [];
$condition = [
['order_id', '=', $order_info['order_id']],
['order_status', '=', self::ORDER_CREATE],
];
$verify = new Verify();
$order_goods_list = model('order_goods')->getList([['order_id', '=', $order_info['order_id']]], 'sku_image,sku_name,price,num,order_goods_id,goods_id,sku_id');
$item_array = [];
foreach ($order_goods_list as $k => $v) {
$item_array[] = [
'img' => $v['sku_image'],
'name' => $v['sku_name'],
'price' => $v['price'],
'num' => numberFormat($v['num']),
'order_goods_id' => $v['order_goods_id'],
'remark_array' => [
]
];
// 增加门店商品销量
model('store_goods')->setInc([['goods_id', '=', $v['goods_id']], ['store_id', '=', $order_info['delivery_store_id']]], 'sale_num', $v['num']);
model('store_goods_sku')->setInc([['sku_id', '=', $v['sku_id']], ['store_id', '=', $order_info['delivery_store_id']]], 'sale_num', $v['num']);
}
$pay_time = time();
$remark_array = [
['title' => '订单金额', 'value' => $order_info['order_money']],
['title' => '订单编号', 'value' => $order_info['order_no']],
['title' => '创建时间', 'value' => time_to_date($order_info['create_time'])],
['title' => '付款时间', 'value' => time_to_date($pay_time)],
['title' => '收货地址', 'value' => $order_info['full_address']],
['title' => '选择门店', 'value' => $order_info['delivery_store_name']],
];
$verify_content_json = $verify->getVerifyJson($item_array, $remark_array);
$code = $verify->addVerify('pickup', $order_info['site_id'], $order_info['site_name'], $verify_content_json, 0, 1, $order_info['delivery_store_id'], $member_id);
$pay_type_list = $this->getPayType();
$data = [
'order_status' => self::ORDER_PENDING_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_PENDING_DELIVERY]['name'],
'pay_status' => 1,
'order_status_action' => json_encode($this->order_status[self::ORDER_PENDING_DELIVERY], JSON_UNESCAPED_UNICODE),
'delivery_code' => $code['data']['verify_code'],
'pay_time' => $pay_time,
'is_enable_refund' => 1,
'pay_type' => $pay_type,
'pay_type_name' => $pay_type_list[$pay_type]
];
//记录订单日志 start
$action = '商家对订单进行了线下支付';
//获取用户信息
if (empty($log_data)) {
$log_data = [
'uid' => $order_info['member_id'],
'nick_name' => $order_info['name'],
'action_way' => 1
];
$action = '买家支付了订单';
}
$log_data = array_merge($log_data, [
'order_id' => $order_info['order_id'],
'action' => $action,
'order_status' => self::ORDER_PENDING_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_PENDING_DELIVERY]['name']
]);
OrderLog::addOrderLog($log_data, $this);
//记录订单日志 end
model('order')->update($data, $condition);
$order_goods_data = [
'delivery_status_name' => '待提货'
];
$res = model('order_goods')->update($order_goods_data, [['order_id', '=', $order_info['order_id']]]);
$verify->qrcode($code['data']['verify_code'], 'all', 'pickup', $order_info['site_id']);
// 订单发货完成,小程序发货信息录入,视频号
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
return $this->success($res);
}
/**
* 主动提货
* @param $delivery_code
* @return array
*/
public function verify($delivery_code)
{
$order_info = model('order')->getInfo([['delivery_code', '=', $delivery_code]], 'order_id, order_type, sign_time, order_status, delivery_code,site_id');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$result = $this->activeTakeDelivery($order_info['order_id']);
if ($result['code'] < 0) {
return $result;
}
//核销发送通知
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'VERIFY', 'order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
return $result;
}
/**
* 主动提货
* @param $order_id
* @return array
*/
public function activeTakeDelivery($order_id)
{
$order_condition = [
['order_id', '=', $order_id],
['order_type', '=', 2]
];
$order_info = model('order')->getInfo($order_condition, 'delivery_code, order_status, site_id');
//应该在这儿主动调用核销的方法函数
if (empty($order_info))
return $this->error([], '订单不存在!');
if ($order_info['order_status'] != self::ORDER_PENDING_DELIVERY)
return $this->error([], '只有待提货状态的订单才可以提货!');
$result = $this->orderCommonTakeDelivery($order_id);
if ($result['code'] < 0) {
return $result;
}
//核销发送通知
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'VERIFY', 'order_id' => $order_id, 'site_id' => $order_info['site_id']]);
return $result;
}
/**
* 订单提货
* @param $order_id
* @return array
*/
public function orderTakeDelivery($order_id)
{
$res = model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '已提货'], [['order_id', '=', $order_id], ['refund_status', '<>', OrderRefundDict::REFUND_COMPLETE]]);
$order_goods_list = model('order_goods')->getList([['order_id', '=', $order_id]]);
foreach ($order_goods_list as &$v) {
$v['num'] = numberFormat($v['num']);
}
//todo 默认先将提货的发货和收货一体化,将扣除库存统一放在这
$order_stock_model = new OrderStock();
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'store_id,site_id');
$stock_result = $order_stock_model->decOrderStock([
'store_id' => $order_info['store_id'],
'site_id' => $order_info['site_id'],
'goods_sku_list' => $order_goods_list
]);
if ($stock_result['code'] < 0) {
return $stock_result;
}
return $this->success($res);
}
/**
* 退款完成操作
* @param $order_goods_info
*/
public function refund($order_goods_info)
{
//是否入库
$order_stock_model = new OrderStock();
if ($order_goods_info['is_refund_stock'] == 1) {
$order_stock_model->incOrderStock($order_goods_info);
}else if($order_goods_info['delivery_status'] == 0){
$order_stock_model->incOrderSaleStock([
'store_id' => $order_goods_info['store_id'],
'goods_sku_data' => [
[
'sku_id' => $order_goods_info['sku_id'],
'num' => $order_goods_info['num'],
],
],
]);
}
}
/**
* 订单详情
* @param $order_info
* @return array
*/
public function orderDetail($order_info)
{
return [];
}
}

943
app/model/order/VirtualOrder.php Executable file
View File

@@ -0,0 +1,943 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order;
use addon\cardservice\model\MemberCard;
use app\dict\goods\GoodsDict;
use app\dict\order\OrderGoodsDict;
use app\model\goods\VirtualGoods;
use app\model\message\Message;
use app\model\system\Cron;
use app\model\verify\Verify as VerifyModel;
use app\model\verify\VerifyRecord;
use Exception;
use think\facade\Db;
use think\facade\Queue;
/**
* 虚拟订单
* Class VirtualOrder
* @package app\model\order
*/
class VirtualOrder extends OrderCommon
{
/*****************************************************************************************订单状态***********************************************/
// 订单创建
public const ORDER_CREATE = 0;
// 订单已支付
public const ORDER_PAY = 1;
// 订单待收货
public const ORDER_DELIVERY = 3;
// 订单已收货
public const ORDER_TAKE_DELIVERY = 4;
// 订单已结算完成
public const ORDER_COMPLETE = 10;
// 订单已关闭
public const ORDER_CLOSE = -1;
// 订单待使用
public const ORDER_WAIT_VERIFY = 11;
//订单已使用
public const ORDER_VERIFYED = 12;
// 订单类型
public $order_type = 4;
// 订单状态
public $order_status = [
self::ORDER_CREATE => [
'status' => self::ORDER_CREATE,
'name' => '待支付',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon.png',
'action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderAdjustMoney',
'title' => '调整价格',
'color' => ''
],
],
'member_action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
[
'action' => 'orderPay',
'title' => '支付',
'color' => ''
],
],
'color' => ''
],
self::ORDER_PAY => [
'status' => self::ORDER_PAY,
'name' => '待发货',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-send.png',
'action' => [
[
'action' => 'orderVirtualDelivery',
'title' => '发货',
'color' => ''
],
],
'member_action' => [],
'color' => ''
],
self::ORDER_DELIVERY => [
'status' => self::ORDER_DELIVERY,
'name' => '待收货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
[
'action' => 'memberVirtualTakeDelivery',
'title' => '确认使用',
'color' => ''
],
],
'color' => ''
],
self::ORDER_TAKE_DELIVERY => [
'status' => self::ORDER_TAKE_DELIVERY,
'name' => '已收货',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_WAIT_VERIFY => [
'status' => self::ORDER_WAIT_VERIFY,
'name' => '待使用',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-close.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_VERIFYED => [
'status' => self::ORDER_VERIFYED,
'name' => '已使用',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-close.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_COMPLETE => [
'status' => self::ORDER_COMPLETE,
'name' => '已完成',
'is_allow_refund' => 1,
'icon' => 'public/uniapp/order/order-icon-received.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
self::ORDER_CLOSE => [
'status' => self::ORDER_CLOSE,
'name' => '已关闭',
'is_allow_refund' => 0,
'icon' => 'public/uniapp/order/order-icon-close.png',
'action' => [
],
'member_action' => [
],
'color' => ''
],
];
/**
* 订单支付
* @param $data
* @return array|mixed|void
*/
public function orderPay($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$pay_type = $data['pay_type'];
$log_data = $data['log_data'] ?? [];
$pay_type_list = $this->getPayType();
$member_info = $data['member_info'];
$data = [
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name'],
'order_status_action' => json_encode($this->order_status[self::ORDER_PAY], JSON_UNESCAPED_UNICODE),
'pay_status' => 1,
'pay_time' => time(),
'is_enable_refund' => 1,
'pay_type' => $pay_type,
'pay_type_name' => $pay_type_list[$pay_type]
];
//记录订单日志 start
$action = '商家对订单进行了线下支付';
//获取用户信息
if (empty($log_data)) {
$log_data = [
'uid' => $order_info['member_id'],
'nick_name' => $member_info['nickname'],
'action_way' => 1
];
$action = '买家支付了订单';
}
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'action' => $action,
'order_status' => self::ORDER_PAY,
'order_status_name' => $this->order_status[self::ORDER_PAY]['name'],
]);
OrderLog::addOrderLog($log_data, $this);
//记录订单日志 end
model('order')->update($data, [['order_id', '=', $order_id]]);
$goods_id = model('order_goods')->getValue([['order_id', '=', $order_id]], 'goods_id');
//判断商品是否需要核销
$goods_info = model('goods')->getInfo([['goods_id', '=', $goods_id]], '*');
if ($order_info['is_lock'] == 0) {
if (!in_array($order_info['promotion_type'], ['pintuan', 'pinfan'])) {
switch($goods_info['goods_class']){
case GoodsDict::virtual://虚拟商品
switch ($goods_info['virtual_deliver_type']) {
case GoodsDict::virtual_auto_deliver:// 自动发货
$this->virtualDelivery($order_info, [
'uid' => 0,
'nick_name' => '系统操作',
'action' => '系统自动发货',
'action_way' => 2,
]);
break;
case GoodsDict::virtual_artificial_deliver:// 手动发货
break;
case GoodsDict::virtual_verify:// 到店核销
$order_status_item = $this->order_status[self::ORDER_WAIT_VERIFY];
$data = [
'order_status' => self::ORDER_WAIT_VERIFY,
'order_status_name' => $order_status_item['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
// 是否需要核销
if ($goods_info['is_need_verify']) {
//虚拟产品发货
$this->virtualOrderTakeDelivery($order_id);
} else {
//虚拟产品收货
$this->orderCommonTakeDelivery($order_id);
}
break;
}
break;
case GoodsDict::virtualcard://卡密
$order_status_item = $this->order_status[self::ORDER_DELIVERY];
$order_status_item['action'] = [];
$order_status_item['member_action'] = [];
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
// 卡密商品发货
$result = $this->virtualCardTakeDelivery($order_id);
if ($result['code'] < 0) {
return $result;
}
break;
case GoodsDict::service://服务商品
$order_status_item = $this->order_status[self::ORDER_DELIVERY];
$order_status_item['action'] = [];
$order_status_item['member_action'] = [];
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
$this->serviceGoodsTakeDelivery($order_id);
break;
case GoodsDict::card://卡项
$order_status_item = $this->order_status[self::ORDER_DELIVERY];
$order_status_item['action'] = [];
$order_status_item['member_action'] = [];
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
$this->cardServiceTakeDelivery($order_id);
break;
}
}
}
return $this->success();
}
/**
* 虚拟发货
* @param $params
* @return array
*/
public function virtualDelivery($params, $log_data = [])
{
$order_id = $params['order_id'] ?? 0;
//todo 核验订单是否处于锁定
$local_result = $this->verifyOrderLock($order_id);
if ($local_result['code'] < 0)
return $local_result;
$site_id = $params['site_id'] ?? 0;
$condition = [['order_id', '=', $params['order_id']]];
if ($site_id > 0) {
$condition[] = ['site_id', '=', $site_id];
}
$order_info = $this->getOrderInfo($condition)['data'] ?? [];
if (empty($order_info))
return $this->error([], '找不到订单!');
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($this->order_status[self::ORDER_DELIVERY], JSON_UNESCAPED_UNICODE),
'delivery_time' => time(),
];
$res = model('order')->update($data, $condition);
$goods_id = model('order_goods')->getValue([['order_id', '=', $order_id]], 'goods_id');
//判断商品是否需要核销
$goods_info = model('goods')->getInfo([['goods_id', '=', $goods_id]], 'virtual_receive_type,virtual_deliver_type');
// 记录订单日志 start
if(!empty($log_data)){
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name']
]);
OrderLog::addOrderLog($log_data, $this);
}
//增加卡项商品的自动发货
Queue::push('app\job\order\OrderDeliveryAfter', ['order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
if (!empty($goods_info)) {
$virtual_receive_type = $goods_info['virtual_receive_type'];
if ($virtual_receive_type == 'auto_receive') {
// 自动收货
$result = $this->virtualTakeDelivery($params, [
'uid' => 0,
'nick_name' => '系统操作',
'action' => '系统自动收货',
'action_way' => 2,
]);
if ($result['code'] < 0) {
return $result;
}
}else{
//定时任务收货
OrderCron::takeDelivery(['order_id' => $order_id, 'site_id' => $site_id]);
}
}
// 订单发货消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'ORDER_DELIVERY', 'order_id' => $order_id, 'site_id' => $site_id]);
return $this->success();
}
public function virtualTakeDelivery($params, $log_data = [])
{
$order_id = $params['order_id'] ?? 0;
$site_id = $params['site_id'] ?? 0;
$member_id = $params['member_id'] ?? 0;
$condition = [['order_id', '=', $order_id]];
if ($site_id > 0) {
$condition[] = ['site_id', '=', $site_id];
}
if ($member_id > 0) {
$condition[] = ['member_id', '=', $member_id];
}
$order_info = $this->getOrderInfo($condition)['data'] ?? [];
if (empty($order_info))
return $this->error([], '找不到订单!');
//虚拟产品收货
$result = $this->orderCommonTakeDelivery($order_id, $log_data);
if ($result['code'] < 0) {
return $result;
}
return $this->success();
}
/**
* 订单自动发货
* @param $order_id
* @return array
*/
public function virtualOrderTakeDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$site_id = $order_info['site_id'];
model('order')->startTrans();
try {
//订单项变为已发货
model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '待使用'], [['order_id', '=', $order_id]]);
$order_goods_info = model('order_goods')->getInfo([['order_id', '=', $order_id]], 'sku_id,sku_name,sku_image,price,num,goods_id,order_goods_id');//订单项详情
if (!empty($order_goods_info)) {
$order_goods_info['num'] = numberFormat($order_goods_info['num']);
}
//判断商品是否需要核销
$goods_info = model('goods_sku')->getInfo([['gs.sku_id', '=', $order_goods_info['sku_id']]], 'g.is_need_verify,g.verify_validity_type,g.virtual_indate,gs.verify_num', 'gs', [['goods g', 'g.goods_id = gs.goods_id', 'left']]);
if ($goods_info['is_need_verify']) {
switch ($goods_info['verify_validity_type']) {
case 0:
$expire_time = 0;
break;
case 1:
$expire_time = strtotime('+' . $goods_info['virtual_indate'] . 'days');
break;
case 2:
$expire_time = $goods_info['virtual_indate'];
break;
}
if ($expire_time > 0) {
//添加自动收货事件
OrderCron::takeDelivery(['order_id' => $order_id, 'site_id' => $site_id, 'expire_time' => $expire_time]);
// 核销码临近到期时间(小时)
$config_model = new Config();
$verify_config = $config_model->getOrderVerifyConfig($site_id)['data']['value'];
$order_verify_out_time = $verify_config['order_verify_time_out'] ?? 24;
$time_strtime = $order_verify_out_time * 3600;
$cron_model = new Cron();
//核销商品临期提醒
$cron_model->addCron(1, 0, '核销商品临期提醒', 'VerifyOrderOutTime', $expire_time - $time_strtime, $order_id);
//核销码过期提醒
$cron_model->addCron(1, 0, '核销码过期提醒', 'CronVerifyCodeExpire', $expire_time, $order_id);
}
$count = $goods_info['verify_num'] * $order_goods_info['num'];
// for ($i = 1; $i <= $count; $i++) {
//创建待核销记录
$verify_model = new VerifyModel();
$item_array = [
[
'img' => $order_goods_info['sku_image'],
'name' => $order_goods_info['sku_name'],
'price' => $order_goods_info['price'],
'num' => 1,
'order_goods_id' => $order_goods_info['order_goods_id'],
'remark_array' => [
['title' => '联系人', 'value' => $order_info['name'] . $order_info['mobile']]
]
],
];
$remark_array = [
['title' => '订单金额', 'value' => $order_info['order_money']],
['title' => '订单编号', 'value' => $order_info['order_no']],
['title' => '创建时间', 'value' => time_to_date($order_info['create_time'])],
['title' => '付款时间', 'value' => time_to_date($order_info['pay_time'])],
];
$verify_content_json = $verify_model->getVerifyJson($item_array, $remark_array);
$code_result = $verify_model->addVerify('virtualgoods', $site_id, $order_info['site_name'], $verify_content_json, $expire_time, $count, 0, $order_info['member_id']);
$code = $code_result['data']['verify_code'];
$verify_model->qrcode($code, 'all', 'virtualgoods', $site_id);//生成二维码
//自动收发货
$order_data = [
'virtual_code' => $code,
];
$res = model('order')->update($order_data, [['order_id', '=', $order_id]]);
//生成所购买的产品
$virtual_goods_model = new VirtualGoods();
$goods_virtual_data = [
'site_id' => $site_id,
'order_id' => $order_id,
'order_no' => $order_info['order_no'],
'sku_id' => $order_goods_info['sku_id'],
'sku_name' => $order_goods_info['sku_name'],
'code' => $code,
'member_id' => $order_info['member_id'],
'sku_image' => $order_goods_info['sku_image'],
'expire_time' => $expire_time,
'sold_time' => time(),
'goods_id' => $order_goods_info['goods_id'],
'verify_total_count' => $count
];
$virtual_goods_model->addGoodsVirtual($goods_virtual_data);
// }
}
model('order')->commit();
return $this->success($res);
} catch ( Exception $e ) {
model('order')->rollback();
throw new \Exception('虚拟订单提货错误:'.$e->getMessage());
//return $this->error('', $e->getMessage());
}
}
/**
* 卡密商品自动发货 收货(可以分为两个函数 一个发货一个收货)
* @param $order_id
* @return array|mixed|void
*/
public function virtualCardTakeDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_no,site_id,site_name,member_id,order_type,
sign_time,order_status,delivery_code,create_time,name,pay_time,pay_money,mobile,is_lock,order_money');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
model('order')->startTrans();
try {
//订单项变为已发货
model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '已发货'], [['order_id', '=', $order_id]]);
$order_goods_info = model('order_goods')->getInfo([['order_id', '=', $order_id]], '*');//订单项详情
if (!empty($order_goods_info)) {
$order_goods_info['num'] = numberFormat($order_goods_info['num']);
}
//库存处理(卡密商品支付后在扣出库存)//todo 可以再商品中设置扣除库存步骤
$order_stock_model = new OrderStock();
$item_goods_class = $order_goods_info['goods_class'];
if ($item_goods_class == GoodsDict::virtualcard) {
//库存变化
$order_stock_model->decOrderStock($order_goods_info);
}
//TODO 并发情况下 同时查询会触发覆盖比如A找到id为8的数据修改B也找到id为8的数修改那么最后只能有一个用户关联到
//$goods_virtual_list = model('goods_virtual')->pageList([ [ 'order_id', '=', 0 ], [ 'sku_id', '=', $order_goods_info[ 'sku_id' ] ] ], 'id', 'id asc', 1, $order_goods_info[ 'num' ])['list'];
$goods_virtual_list = Db::name('goods_virtual')
->where([['order_id', '=', 0], ['sku_id', '=', $order_goods_info['sku_id']]])
->limit($order_goods_info['num'])
->field('id')
->order('id asc')
->lock(true)
->select()
->toArray();
if (count($goods_virtual_list) != $order_goods_info['num']) {
//主动退款
$order_refund_model = new OrderRefund();
$refund_result = $order_refund_model->activeRefund($order_id, '', '卡密库存不足主动退款');
if ($refund_result['code'] < 0) {
model('order')->rollback();
return $refund_result;
}
model('order')->commit();
return $this->error('', '卡密库存不足!');
}
$ids = array_column($goods_virtual_list, 'id');
model('goods_virtual')->update([
'order_id' => $order_id,
'order_no' => $order_info['order_no'],
'member_id' => $order_info['member_id'],
'sold_time' => time()
], [['id', 'in', $ids]]);
// 订单自动收货
$this->orderCommonTakeDelivery($order_id);
model('order')->commit();
return $this->success();
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 订单自动发货(服务商品)
* @param $order_id
* @return array
*/
public function serviceGoodsTakeDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_no,site_id,site_name,member_id,order_type,
sign_time,order_status,delivery_code,create_time,name,pay_time,pay_money,mobile,is_lock,order_money');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$site_id = $order_info['site_id'];
model('order')->startTrans();
try {
//订单项变为已发货
model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '已发货'], [['order_id', '=', $order_id]]);
$order_goods_info = model('order_goods')->getInfo([['order_id', '=', $order_id]], 'sku_id,sku_name,sku_image,price,num,goods_id,order_goods_id');//订单项详情
if (!empty($order_goods_info)) {
$order_goods_info['num'] = numberFormat($order_goods_info['num']);
}
//判断商品是否需要核销
$goods_info = model('goods_sku')->getInfo([['gs.sku_id', '=', $order_goods_info['sku_id']]], 'g.is_need_verify,g.verify_validity_type,g.virtual_indate,gs.verify_num', 'gs', [['goods g', 'g.goods_id = gs.goods_id', 'left']]);
switch ($goods_info['verify_validity_type']) {
case GoodsDict::service_permanent://永久
$expire_time = 0;
break;
case GoodsDict::service_day://购买后几日有效
$expire_time = strtotime('+' . $goods_info['virtual_indate'] . 'days');
break;
case GoodsDict::service_day_expire://指定时间过期1
$expire_time = $goods_info['virtual_indate'];
break;
}
//添加自动收货事件
if ($expire_time > 0) {
$cron = new Cron();
OrderCron::takeDelivery(['order_id' => $order_id, 'site_id' => $site_id, 'expire_time' => $expire_time]);
// 核销码临近到期时间(小时)
$config_model = new Config();
$verify_config = $config_model->getOrderVerifyConfig($site_id)['data']['value'];
$order_verify_out_time = $verify_config['order_verify_time_out'] ?? 24;
$time_strtime = $order_verify_out_time * 3600;
//核销商品临期提醒
$cron->addCron(1, 0, '核销商品临期提醒', 'VerifyOrderOutTime', $expire_time - $time_strtime, $order_id);
//核销码过期提醒
$cron->addCron(1, 0, '核销码过期提醒', 'CronVerifyCodeExpire', $expire_time, $order_id);
}
$count = $order_goods_info['num'];
//创建待核销记录
$verify_model = new VerifyModel();
$item_array = [
[
'img' => $order_goods_info['sku_image'],
'name' => $order_goods_info['sku_name'],
'price' => $order_goods_info['price'],
'num' => 1,
'order_goods_id' => $order_goods_info['order_goods_id'],
'remark_array' => [
['title' => '联系人', 'value' => $order_info['name'] . $order_info['mobile']]
]
],
];
$remark_array = [
['title' => '订单金额', 'value' => $order_info['order_money']],
['title' => '订单编号', 'value' => $order_info['order_no']],
['title' => '创建时间', 'value' => time_to_date($order_info['create_time'])],
['title' => '付款时间', 'value' => time_to_date($order_info['pay_time'])],
];
$verify_content_json = $verify_model->getVerifyJson($item_array, $remark_array);
$code_result = $verify_model->addVerify('virtualgoods', $site_id, $order_info['site_name'], $verify_content_json, $expire_time, $count, 0, $order_info['member_id']);
$code = $code_result['data']['verify_code'];
$verify_model->qrcode($code, 'all', 'virtualgoods', $site_id);//生成二维码
//自动收发货
$order_data = [
'virtual_code' => $code,
];
$res = model('order')->update($order_data, [['order_id', '=', $order_id]]);
//生成所购买的产品
$virtual_goods_model = new VirtualGoods();
$goods_virtual_data = [
'site_id' => $site_id,
'order_id' => $order_id,
'order_no' => $order_info['order_no'],
'sku_id' => $order_goods_info['sku_id'],
'sku_name' => $order_goods_info['sku_name'],
'code' => $code,
'member_id' => $order_info['member_id'],
'sku_image' => $order_goods_info['sku_image'],
'expire_time' => $expire_time,
'sold_time' => time(),
'goods_id' => $order_goods_info['goods_id'],
'verify_total_count' => $count
];
$virtual_goods_model->addGoodsVirtual($goods_virtual_data);
model('order')->commit();
return $this->success($res);
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 卡项发货设置(需要增加卡项核销)
* @param $order_id
* @return array
*/
public function cardServiceTakeDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$site_id = $order_info['site_id'];
model('order')->startTrans();
try {
//订单项变为已发货
model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '已发货'], [['order_id', '=', $order_id]]);
$order_goods_info = model('order_goods')->getInfo([['order_id', '=', $order_id]], 'sku_id,sku_name,sku_image,price,num,goods_id,order_goods_id');//订单项详情
if (!empty($order_goods_info)) {
$order_goods_info['num'] = numberFormat($order_goods_info['num']);
}
//创建卡项
$member_card = new MemberCard();
$card_data = [
'store_id' => 0,
'goods_id' => $order_goods_info['goods_id'],
'num' => $order_goods_info['num'],
'member_id' => $order_info['member_id'],
'site_id' => $site_id,
'order_id' => $order_id
];
$res_card = $member_card->create($card_data);
if ($res_card['code'] < 0) {
model('order')->rollback();
return $this->error('', $res_card['message']);
}
// 订单自动收货
$this->orderCommonTakeDelivery($order_id);
model('order')->commit();
return $this->success(1);
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 自动发货
* @param $order_id
* @return array
*/
public function orderTakeDelivery($order_id)
{
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], 'order_no,site_id,site_name,member_id,order_type,
sign_time,order_status,delivery_code,create_time,name,pay_time,pay_money,mobile,is_lock,order_money');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$res = model('order_goods')->update(['delivery_status' => OrderGoodsDict::delivery, 'delivery_status_name' => '已发货'], [['order_id', '=', $order_id]]);
return $this->success($res);
}
/**
* 退款完成操作
* @param $order_goods_info
*/
public function refund($order_goods_info)
{
$type = true;
if (addon_is_exit('virtualcard')) {
$virtual_card = (new \addon\virtualcard\model\VirtualGoods())->getGoodsClass();
if ($order_goods_info['goods_class'] == $virtual_card['id']) $type = false;
}
if ($type) {
//删除已退款订单项会员虚拟商品, 并退回商品库存
//无需判断订单项是否需要入库
$item_param = [
'sku_id' => $order_goods_info['sku_id'],
'num' => $order_goods_info['num'],
];
//返还库存
$order_stock_model = new OrderStock();
$order_stock_model->incOrderStock($order_goods_info);
//$goods_stock_model->incStock($item_param);
//删除用户的这条虚拟商品
$goods_virtual_model = new VirtualGoods();
$goods_virtual_model->deleteGoodsVirtual([['order_id', '=', $order_goods_info['order_id']], ['member_id', '=', $order_goods_info['member_id']]]);
}
}
/**
* 订单详情
* @param $order_info
* @return array
*/
public function orderDetail($order_info)
{
$order_id = $order_info['order_id'];
$verify_record_model = new VerifyRecord();
$data = [
'goods_class' => $order_info['order_goods'][0]['goods_class']
];
if ($data['goods_class'] == GoodsDict::virtual) {
$virtual_goods = model('goods_virtual')->getFirstData([['order_id', '=', $order_id]], '*', 'is_veirfy asc');
if (!empty($virtual_goods)) {
$virtual_goods['total_verify_num'] = model('goods_virtual')->getCount([['order_id', '=', $order_id]]);
$virtual_goods['verify_num'] = model('goods_virtual')->getCount([['order_id', '=', $order_id], ['is_veirfy', '=', 1]]);
$verify_code = model('goods_virtual')->getColumn([['order_id', '=', $order_id]], 'code');
$virtual_goods['verify_record'] = [];
if (!empty($verify_code)) {
$virtual_goods['verify_record'] = $verify_record_model->getVerifyRecordsViewList([['verify_code', 'in', $verify_code]], '*', 'verify_time desc')['data'] ?? [];
}
$data['virtual_goods'] = $virtual_goods;
$data['virtual_code'] = $virtual_goods['code'];
}
} else if ($data['goods_class'] == GoodsDict::virtualcard) {
$virtual_goods = model('goods_virtual')->getList([['order_id', '=', $order_id]], '*', 'id asc');
if (!empty($virtual_goods)) {
foreach ($virtual_goods as $key => $item) {
$virtual_goods[$key]['card_info'] = json_decode($item['card_info'], true);
}
$data['virtual_goods'] = $virtual_goods;
}
}
if ($data['goods_class'] == GoodsDict::service) {
$virtual_goods = model('goods_virtual')->getFirstData([['order_id', '=', $order_id]], '*', 'is_veirfy asc');
if (!empty($virtual_goods)) {
$virtual_goods['total_verify_num'] = model('goods_virtual')->getCount([['order_id', '=', $order_id]]);
$virtual_goods['verify_num'] = model('goods_virtual')->getCount([['order_id', '=', $order_id], ['is_veirfy', '=', 1]]);
$verify_code = model('goods_virtual')->getColumn([['order_id', '=', $order_id]], 'code');
$virtual_goods['verify_record'] = [];
if (!empty($verify_code)) {
$virtual_goods['verify_record'] = $verify_record_model->getVerifyRecordsViewList([['verify_code', 'in', $verify_code]], '*', 'verify_time desc')['data'] ?? [];
}
$data['virtual_goods'] = $virtual_goods;
$data['virtual_code'] = $virtual_goods['code'];
}
}
return $data;
}
/**
* to发送
* @param $params
* @return array|mixed|void
*/
public function toSend($params)
{
$order_id = $params['order_id'];
$goods_id = model('order_goods')->getValue([['order_id', '=', $order_id]], 'goods_id');
//判断商品是否需要核销
$goods_info = model('goods')->getInfo([['goods_id', '=', $goods_id]], 'goods_class,is_need_verify,virtual_deliver_type');
$order_info = model('order')->getInfo([['order_id', '=', $order_id]]);
// 虚拟商品
if ($goods_info['goods_class'] == GoodsDict::virtual) {
switch ($goods_info['virtual_deliver_type']) {
case 'auto_deliver':
// 自动发货
$this->virtualDelivery($order_info);
break;
case 'artificial_deliver':
// 手动发货
break;
case 'verify':
// 到店核销
$order_status_item = $this->order_status[self::ORDER_WAIT_VERIFY];
$data = [
'order_status' => self::ORDER_WAIT_VERIFY,
'order_status_name' => $order_status_item['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
if ($goods_info['is_need_verify']) {
//虚拟产品发货
$this->virtualOrderTakeDelivery($order_id);
} else {
//虚拟产品收货
$this->orderCommonTakeDelivery($order_id);
}
break;
}
} elseif ($goods_info['goods_class'] == GoodsDict::virtualcard) {
// 电子卡密商品
$order_status_item = $this->order_status[self::ORDER_DELIVERY];
$order_status_item['action'] = [];
$order_status_item['member_action'] = [];
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
// 卡密商品发货
$result = $this->virtualCardTakeDelivery($order_id);
if ($result['code'] < 0) {
return $result;
}
} elseif ($goods_info['goods_class'] == GoodsDict::service) {
// 服务项目商品
$order_status_item = $this->order_status[self::ORDER_DELIVERY];
$order_status_item['action'] = [];
$order_status_item['member_action'] = [];
$data = [
'order_status' => self::ORDER_DELIVERY,
'order_status_name' => $this->order_status[self::ORDER_DELIVERY]['name'],
'order_status_action' => json_encode($order_status_item, JSON_UNESCAPED_UNICODE),
];
model('order')->update($data, [['order_id', '=', $order_id]]);
$result = $this->serviceGoodsTakeDelivery($order_id);
if ($result['code'] < 0) {
return $result;
}
} elseif ($goods_info['goods_class'] == GoodsDict::card) {
// 卡项套餐商品
$result = $this->cardServiceTakeDelivery($order_id);
if ($result['code'] < 0) {
return $result;
}
}
return $this->success();
}
}

View File

@@ -0,0 +1,205 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\event;
use addon\cardservice\model\MemberCard;
use addon\coupon\model\Coupon;
use app\dict\goods\GoodsDict;
use app\dict\order\OrderDict;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\goods\Goods;
use app\model\member\MemberAccount;
use app\model\message\Message;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use app\model\order\OrderStock;
use app\model\system\Pay;
use think\db\exception\DbException;
/**
* 订单交易设置
*/
class OrderClose extends BaseModel
{
/**
* 校验
* @param $data
* @return array
* @throws DbException
*/
public function check($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
//尝试关闭支付
if ($order_info['pay_status'] == 0) {
$pay_model = new Pay();
$result = $pay_model->closePay($order_info['out_trade_no']);//关闭旧支付单据
if ($result['code'] < 0) {
return $result;
}
}
//订单关闭校验
event('OrderCloseCheck', []);
return $this->success();
}
public function event($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
// $is_exist_refund = $data['is_exist_refund'];
// $refund_goods_card = $data['refund_goods_card'];
// $refund_point = $data['refund_point'];
/******************************************************* 库存相关 **********************************************************/
//库存处理
$condition = array(
['order_id', '=', $order_id]
);
//循环订单项 依次返还库存 并修改状态
$order_goods_list = model('order_goods')->getList($condition, '*');
$order_refund_model = new OrderRefund();
$goods_model = new Goods();
$is_exist_refund = false;//是否存在退款
$refund_goods_card = [];
$refund_point = 0;
$order_stock = new OrderStock();
//用于存放退款库存的数组
$stock_goods_sku_data = [];
foreach ($order_goods_list as $k => $v) {
//如果是已维权完毕的订单项, 库存不必再次返还(todo 收银台订单创建不再扣除库存了)
if ($v['refund_status'] != OrderRefundDict::REFUND_COMPLETE && $order_info['order_type'] != OrderDict::cashier) {
$goods_class = $v['goods_class'] ?? 0;
if (in_array($goods_class, [GoodsDict::real, GoodsDict::virtual, GoodsDict::virtualcard, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
$stock_goods_sku_data[] = [
'sku_id' => $v['sku_id'],
'num' => $v['num']
];
}
//返还积分
$refund_point += $v['use_point'];
// 是否有使用次卡
if ($v['card_item_id']) {
$refund_goods_card[] = ['type' => 'order', 'relation_id' => $v['order_goods_id']];
}
}
if ($v['refund_status'] == OrderRefundDict::REFUND_COMPLETE) {
$is_exist_refund = true;
}
//减少商品销量(必须支付过)
if ($order_info['pay_status'] > 0) {
$goods_model->decGoodsSaleNum($v['sku_id'], $v['num'], $order_info['store_id']);
}
}
/******************************************************* 返还库存 **********************************************************/
if($stock_goods_sku_data){
//返还销售库存
$order_stock->incOrderSaleStock([
'goods_sku_data' => $stock_goods_sku_data,
'store_id' => $order_info['store_id']
]);
}
/******************************************************* 优惠券相关 **********************************************************/
//返还店铺优惠券
$coupon_id = $order_info['coupon_id'];
if ($coupon_id > 0) {
$coupon_model = new Coupon();
$coupon_model->refundCoupon($coupon_id, $order_info['member_id']);
}
//平台优惠券
/******************************************************* 退还余额相关 **********************************************************/
//平台余额 退还余额
if (!$is_exist_refund) {//因为订单完成后 只有全部退款完毕订单才会关闭
$member_account_model = new MemberAccount();
if ($order_info['balance_money'] > 0) {
$result = $member_account_model->addMemberAccount($order_info['site_id'], $order_info['member_id'], 'balance', $order_info['balance_money'], 'refund', $order_id, '订单关闭返还');
}
// 订单关闭返还积分
if ($refund_point > 0) {
$result = $member_account_model->addMemberAccount($order_info['site_id'], $order_info['member_id'], 'point', $refund_point, 'refund', $order_id, '订单关闭返还');
}
}
/******************************************************* 关闭后各插件相关 **********************************************************/
//订单关闭后操作
$close_result = event('OrderClose', $order_info);
if (empty($close_result)) {
foreach ($close_result as $k => $v) {
if (!empty($v) && $v['code'] < 0) {
return $v;
}
}
}
return $this->success();
}
/**
* 后续事件
* @param $data
* @return array
*/
public function after($data)
{
$order_info = $data['order_info'];
$log_data = $data['log_data'];
$close_cause = $data['close_cause'] ?? '';
$order_common_model = new OrderCommon();
/******************************************************* 会员相关 **********************************************************/
/******************************************************* 日志相关 **********************************************************/
//记录订单日志 start
$close_status = OrderCommon::ORDER_CLOSE;
if (!empty($log_data)) {
if ($log_data['action_way'] == 1) {
$member_info = model('member')->getInfo(['member_id' => $log_data['uid']], 'nickname');
$buyer_name = empty($member_info['nickname']) ? '' : '【' . $member_info['nickname'] . '】';
$log_data['nick_name'] = $buyer_name;
$action = '买家关闭了订单';
} else {
$action = '商家关闭了订单';
}
} else {
$action = !empty($close_cause) ? $close_cause : '系统自动关闭了订单(长时间未支付)';
$log_data = [
'uid' => 0,
'nick_name' => '系统',
'action_way' => 2
];
}
$log_data = array_merge($log_data, [
'order_id' => $order_info['order_id'],
'action' => $action,
'order_status' => $close_status,
'order_status_name' => $order_common_model->order_status[$close_status]['name']
]);
OrderLog::addOrderLog($log_data, $order_common_model);
//记录订单日志 end
/******************************************************* 发送消息 **********************************************************/
//订单关闭消息
$message_model = new Message();
$res = $message_model->sendMessage(['keywords' => 'ORDER_CLOSE', 'order_id' => $order_info['order_id'], 'site_id' => $order_info['site_id']]);
return $this->success();
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\event;
use app\model\BaseModel;
use app\model\message\Message;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
/**
* 订单完成设置
*/
class OrderComplete extends BaseModel
{
/**
* 校验
* @param $data
* @return array
*/
public function check($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
/******************************************************* 校验订单锁定相关 **********************************************************/
$lock_result = (new OrderCommon())->verifyOrderLock($order_id);
if ($lock_result['code'] < 0)
return $lock_result;
return $this->success();
}
public function event($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
/******************************************************* 会员账户相关 **********************************************************/
//修改用户表order_complete_money和order_complete_num
model('member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_money', $order_info['order_money'] - $order_info['refund_money']);
model('member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_num');
/******************************************************* 插件相关 **********************************************************/
event('OrderComplete', ['order_id' => $order_id]);
return $this->success();
}
/**
* 后续事件
* @param $data
* @return array
*/
public function after($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$site_id = $order_info['site_id'];
/******************************************************* 日志相关 **********************************************************/
$log_data = array(
'order_id' => $order_id,
'action' => 'complete',
'site_id' => $site_id,
'is_auto' => 1,// todo 当前业务默认是系统任务完成订单
);
(new OrderLog())->addLog($log_data);
/******************************************************* 消息相关 **********************************************************/
$message_model = new Message();
//订单完成
$message_model->sendMessage(['keywords' => 'ORDER_COMPLETE', 'order_id' => $order_id, 'site_id' => $site_id]);
// 买家订单完成通知商家
$message_model->sendMessage(['keywords' => 'BUYER_ORDER_COMPLETE', 'order_id' => $order_id, 'site_id' => $site_id]);
return $this->success();
}
}

View File

@@ -0,0 +1,54 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\event;
use app\model\BaseModel;
/**
* 订单发货设置
*/
class OrderDelivery extends BaseModel
{
/**
* 校验
* @param $data
* @return array
*/
public function check($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
return $this->success();
}
public function event($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
return $this->success();
}
/**
* 后续事件
* @param $data
* @return array
*/
public function after($data)
{
$order_info = $data['order_info'];
return $this->success();
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\event;
use app\model\BaseModel;
use app\model\goods\Goods;
use app\model\member\MemberAccount;
use app\model\message\Message;
use app\model\order\OrderCommon;
use Exception;
use app\model\system\Cron;
/**
* 订单交易设置
*/
class OrderPay extends BaseModel
{
public function check($data)
{
}
public function event($data)
{
$pay_info = $data['pay_info'];
$order_info = $data['order_info'];
//订单余额账户处理
if (($pay_info['balance'] || $pay_info['balance_money']) && $order_info['order_money']) {
//订单处理会员消费业务
$account_result = (new MemberAccount())->addMemberAccountInOrderPay($data);
if (!empty($account_result) && $account_result['code'] < 0) throw new Exception($account_result['message']);
}
//会员业务
$member_info = $data['member_info'];
$data_member = [
'order_money' => $member_info['order_money'] + $order_info['order_money'],
'order_num' => $member_info['order_num'] + 1,
'last_consum_time' => time()
];
model('member')->update($data_member, [['member_id', '=', $member_info['member_id']]]);
$order_info['pay_info'] = $pay_info;
event('OrderPay', $order_info);
return $this->success();
}
public function after($data)
{
$order_id = $data['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
event('OrderPayAfter', $order_info);
//商品业务
$order_goods_list = model('order_goods')->getList([['order_id', '=', $order_id]], 'sku_id,num,goods_class,store_id');
$goods_model = new Goods();
foreach ($order_goods_list as $v) {
$goods_model->incGoodsSaleNum($v['sku_id'], $v['num']);
}
//发送消息
$message_model = new Message();
$param = ['keywords' => 'ORDER_PAY'];
$param = array_merge($param, $order_info);
$message_model->sendMessage($param);
$param = ['keywords' => 'BUYER_PAY'];
$param = array_merge($param, $order_info);
$message_model->sendMessage($param);
//删除定时任务
$cron = new Cron();
$cron->deleteCron([ [ 'event', '=', 'CronOrderClose' ], [ 'relate_id', '=', $order_id ] ]);
$cron->deleteCron([ [ 'event', '=', 'CronOrderUrgePayment' ], [ 'relate_id', '=', $order_id ] ]);
return true;
}
}

View File

@@ -0,0 +1,117 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\event;
use app\dict\order\OrderDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
use app\model\order\OrderCron;
use app\model\order\OrderLog;
use app\model\order\VirtualOrder;
use think\db\exception\DbException;
/**
* 订单交易设置
*/
class OrderTake extends BaseModel
{
/**
* 校验
* @param $data
* @return array|void
* @throws DbException
*/
public function check($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
if (empty($order_info))
return $this->error([], 'ORDER_EMPTY');
$order_common_model = new OrderCommon();
$order_info['goods_num'] = numberFormat($order_info['goods_num']);
$local_result = $this->verifyOrderLock($order_id);
if ($local_result['code'] < 0)
return $local_result;
$order_status = $order_info['order_status'];
$virtual_order_model = new VirtualOrder();
if ($order_status == $order_common_model::ORDER_TAKE_DELIVERY || $order_status == $virtual_order_model::ORDER_VERIFYED) {
// 虚拟商品无需确认收货
return $this->error('', '该订单已收货!');
}
return $this->success();
}
public function event($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$order_status = $data['order_status'];
//改变订单状态
$virtual_order_model = new VirtualOrder();
$order_common_model = new OrderCommon();
//todo 如果是虚拟商品并且有虚拟码的话, 订单状态应该为已使用
$order_model = $order_common_model->getOrderModel($order_info);
if ($order_status == $virtual_order_model::ORDER_WAIT_VERIFY) {
$order_action_array = $order_common_model->getOrderCommonAction($order_model, $virtual_order_model::ORDER_VERIFYED);
} else {
$order_action_array = $order_common_model->getOrderCommonAction($order_model, $order_model::ORDER_TAKE_DELIVERY);
}
$order_data = array(
'order_status' => $order_action_array['order_status'],
'order_status_name' => $order_action_array['order_status_name'],
'order_status_action' => $order_action_array['order_status_action'],
'is_evaluate' => 1,
'evaluate_status' => OrderDict::evaluate_wait,
'evaluate_status_name' => OrderDict::getEvaluateStatus(OrderDict::evaluate_wait),
'sign_time' => time()
);
model('order')->update($order_data, [['order_id', '=', $order_id]]);
OrderCron::complete(['order_id' => $order_id, 'site_id' => $order_info['site_id']]);
return $this->success();
}
/**
* 后续事件
* @param $data
* @return array
*/
public function after($data)
{
$order_info = $data['order_info'];
$order_action_array = $data['order_action_array'];
$log_data = $data['data'];
$order_common_model = new OrderCommon();
//记录订单日志 start
if ($log_data) {
$action = '商家对订单进行了确认收货';
if ($log_data['action_way'] == 1) {
$member_info = model('member')->getInfo(['member_id' => $log_data['uid']], 'nickname');
$buyer_name = empty($member_info['nickname']) ? '' : '【' . $member_info['nickname'] . '】';
$log_data['nick_name'] = $buyer_name;
$action = '买家确认收到货物';
}
$log_data = array_merge($log_data, [
'order_id' => $order_info['order_id'],
'action' => $action,
'order_status' => $order_action_array['order_status'],
'order_status_name' => $order_action_array['order_status_name'],
]);
OrderLog::addOrderLog($log_data, $order_common_model);
}
return $this->success();
}
}

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 *****************************************************************************/
}

View File

@@ -0,0 +1,163 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 商家主动退款
*/
class ActiveRefund extends BaseModel
{
/**
* 校验
* @param $param
* @return mixed
*/
public static function check($param)
{
$instance = new self;
$order_goods_id = $param[ 'order_goods_id' ];
$shop_active_refund_money_type = $param[ 'shop_active_refund_money_type' ];
$shop_active_refund_money = $param[ 'shop_active_refund_money' ];
//退款方式
$refund_money_type_arr = OrderRefundDict::getRefundMoneyType();
if(!isset($refund_money_type_arr[$shop_active_refund_money_type])){
return $instance->error(null, '退款方式有误!');
}
//订单项检测
$order_goods_info = model('order_goods')->getInfo([ 'order_goods_id' => $order_goods_id ]);
if (empty($order_goods_info)) return $instance->error(null, '订单项不存在!');
if($order_goods_info['shop_active_refund'] == 1) return $instance->error(null, '已操作过主动退款');
if ($order_goods_info[ 'refund_status' ] != OrderRefundDict::REFUND_NOT_APPLY &&
$order_goods_info[ 'refund_status' ] != OrderRefundDict::REFUND_DIEAGREE) {
return $instance->error(null, '存在进行中的退款!');
}
//订单检测
$order_id = $order_goods_info[ 'order_id' ];
$order_info = model('order')->getInfo([ 'order_id' => $order_id ]);
if (empty($order_info)) return $instance->error([], '订单不存在!');
if ($order_info[ 'is_enable_refund' ] == 0) {
if ($order_info[ 'promotion_type' ] == 'pinfan') {
return $instance->error(null, '拼团活动正在进行中,待拼成功后可发起退款!');
}
return $instance->error(null, '当前订单不允许退款!');
}
//退款金额检测
$order_refund_model = new OrderRefund();
$refund_apply_money_array = $order_refund_model->getOrderRefundMoney($order_goods_id);//可退款金额 通过计算获得
$refund_apply_money = $refund_apply_money_array[ 'refund_money' ];
if($shop_active_refund_money < 0){
return $instance->error(null, '主动退款金额不可小于0');
}
if ($shop_active_refund_money > $refund_apply_money){
return $instance->error(null, '主动退款金额不能大于可退款总额!');
}
if($refund_apply_money > 0 && $shop_active_refund_money == 0){
return $instance->error(null, '主动退款金额不可为0');
}
//退货数量检测
$param['is_refund_stock'] = $param['is_refund_stock'] ?? 0;
$param['refund_stock_num'] = $param['refund_stock_num'] ?? $order_goods_info['num'];
if($param['is_refund_stock'] == 1){
if($param['refund_stock_num'] > $order_goods_info['num']){
return $instance->error(null, '主动退货数量不可大于订单数量!');
}
$order_goods_info['refund_stock_num'] = $param['refund_stock_num'];
}
return $instance->success([
'order_goods_info' => $order_goods_info,
'order_info' => $order_info,
'refund_apply_money' => $refund_apply_money,
]);
}
/**
* 执行事件
* @param $param
* @return true
* @throws DbException
*/
public static function event($param)
{
$order_goods_info = $param['order_goods_info'];
// if($order_goods_info['refund_status'] == OrderRefundDict::REFUND_COMPLETE){
// $order_refund_model = new OrderRefund();
// $order_refund_model->orderGoodsRefund($order_goods_info);
// }
//返还库存
$param['is_refund_stock'] = $param['is_refund_stock'] ?? 0;
$param['refund_stock_num'] = isset($param['refund_stock_num']) && $param['refund_stock_num']>0 ? $param['refund_stock_num'] : $order_goods_info['num'];
$order_refund_model = new OrderRefund();
$order_goods_info['num'] = $param['refund_stock_num'] ?:$order_goods_info['num'];
$order_refund_model->orderGoodsRefund($order_goods_info);
//更新退款金额
$order_info = $param['order_info'];
$order_id = $order_info['order_id'];
$refund_total_real_money = model('order_goods')->getSum([ [ 'order_id', '=', $order_id ], [ 'refund_status', '=', OrderRefundDict::REFUND_COMPLETE ] ], 'refund_real_money');
$refund_total_real_money += model('order_goods')->getSum([ [ 'order_id', '=', $order_id ], [ 'shop_active_refund', '=', 1 ] ], 'shop_active_refund_money');
model('order')->update(['refund_money' => $refund_total_real_money], [['order_id', '=', $order_id]]);
}
/**
* 后续事件
* @param $param
* @return array|true
*/
public static function after($param)
{
$shop_active_refund_money = $param[ 'shop_active_refund_money' ];
$shop_active_refund_remark = $param[ 'shop_active_refund_remark' ];
$user_info = $param['user_info'];
$order_goods_info = $param['order_goods_info'];
$order_info = $param['order_info'];
//记录订单日志
$log_data = [
'uid' => $user_info['uid'],
'nick_name' => $user_info['username'],
'action' => '商品【'.$order_goods_info['sku_name'].'】商家主动退款,退款金额:'.$shop_active_refund_money.'元,退款说明:'.$shop_active_refund_remark,
'action_way' => 2,
'order_id' => $order_goods_info['order_id'],
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
];
$order_common_model = new OrderCommon();
OrderLog::addOrderLog($log_data, $order_common_model);
//记录退款日志
$order_refund_model = new OrderRefund();
$order_refund_model->addOrderRefundLog(
$order_goods_info['order_goods_id'],
$order_goods_info['refund_status'],
'商家主动退款',
2,
$user_info['uid'],
$user_info['username'],
'退款金额:'.$shop_active_refund_money.'元,退款说明:'.$shop_active_refund_remark,
);
return true;
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\model\BaseModel;
use app\model\message\Message;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use extend\exception\RefundException;
use think\db\exception\DbException;
/**
* 订单申请退款
*/
class Apply extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
$order_info = $data['order_info'];
//判断是否允许申请退款
if ($order_info['is_enable_refund'] == 0) {
if ($order_info['promotion_type'] == 'pinfan' || $order_info['promotion_type'] == 'pintuan') throw new RefundException('拼团活动正在进行中,拼团成功后可再次发起退款!');
throw new RefundException('当前订单不支持退款!');
}
//订单申请退款校验
event('OrderRefundApplyCheck', []);
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_info = $data['order_info'];
$order_refund_model = new OrderRefund();
//校验订单是否需要锁定
$order_refund_model->verifyOrderLock($order_info['order_id']);
event('orderRefundApply', $data);//传入订单类型以及订单项id
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_info = $data['order_info'];
$order_goods_info = $data['order_goods_info'];
$log_data = $data['log_data'] ?? [];
$refund_log_data = $data['refund_log_data'] ?? [];
$order_refund_model = new OrderRefund();
$order_refund_model->addOrderRefundLog(...$refund_log_data);
// 发起维权 关闭订单评价
model('order')->update(['is_evaluate' => 0], ['order_id' => $order_goods_info['order_id']]);
//记录订单日志 start
if ($log_data) {
$order_common_model = new OrderCommon();
$log_data['action'] = '商品【'.$order_goods_info['sku_name'].'】'.$log_data['action'];
$log_data = array_merge($log_data, [
'order_id' => $order_goods_info['order_id'],
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
]);
OrderLog::addOrderLog($log_data, $order_common_model);
}
//订单会员申请退款消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'BUYER_REFUND', 'order_goods_id' => $order_goods_info['order_goods_id'], 'site_id' => $order_goods_info['site_id']]);
return true;
}
}

View File

@@ -0,0 +1,87 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\dict\order\OrderDict;
use app\model\BaseModel;
use app\model\order\Order as OrderModel;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单取消退款
*/
class Cancel extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_info = $data['order_info'];
$order_refund_model = new OrderRefund();
//订单锁定
$order_refund_model->verifyOrderLock($order_info['order_id']);
// 维权拒绝 评价锁定放开
if ($order_info['evaluate_status'] != OrderDict::evaluate_again) {
model('order')->update(['is_evaluate' => 1], [['order_id', '=', $order_info['order_id']], ['order_status', 'in', [OrderModel::ORDER_TAKE_DELIVERY, OrderModel::ORDER_COMPLETE]]]);
}
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$order_goods_info = $data['order_goods_info'];
$log_data = $data['log_data'] ?? [];
$member_info = $data['member_info'];
$order_refund_model = new OrderRefund();
//记录订单日志 start
if ($log_data) {
$order_common_model = new OrderCommon();
// $order_info = model('order')->getInfo(['order_id' => $order_id], 'order_status,order_status_name,member_id,site_id,is_video_number');
$log_data['action'] = '商品【'.$order_goods_info['sku_name'].'】'.$log_data['action'];
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
]);
OrderLog::addOrderLog($log_data, $order_common_model);
}
//记录退款日志 end
$order_refund_model->addOrderRefundLog($order_goods_info['order_goods_id'], 0, '买家撤销退款申请', 1, $member_info['member_id'], $member_info['nickname']);
event('MemberCancelRefund', $data);//传入订单类型以及订单项id
return true;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单关闭退款
*/
class Close extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_goods_info = $data['order_goods_info'];
$order_refund_model = new OrderRefund();
$order_refund_model->verifyOrderLock($order_goods_info['order_id']);
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_info = $data['order_info'];
$user_info = $data['user_info'];
$order_goods_info = $data['order_goods_info'];
$order_common_model = new OrderCommon();
//记录订单日志 start
$log_data = [
'uid' => $user_info['uid'],
'nick_name' => $user_info['username'],
'action' => '商家关闭了维权',
'action_way' => 2,
'order_id' => $order_goods_info['order_id'],
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
];
OrderLog::addOrderLog($log_data, $order_common_model);
//记录订单日志 end
//退款日志
$order_refund_model = new OrderRefund();
$order_refund_model->addOrderRefundLog(
$order_goods_info['order_goods_id'],
OrderRefundDict::REFUND_NOT_APPLY,
'卖家关闭本次维权',
2,
$user_info['uid'],
$user_info['username']
);
event('MemberCancelRefund', $data);//传入订单类型以及订单项id
return true;
}
}

View File

@@ -0,0 +1,81 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\model\BaseModel;
use app\model\message\Message;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单审核退款
*/
class Confirm extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_info = $data['order_info'];
$user_info = $data['user_info'];
$order_goods_info = $data['order_goods_info'];
// $log_data = $data['log_data'] ?? [];
$refund_status = $data['refund_status'];
$order_common_model = new OrderCommon();
$log_data = [
'uid' => $user_info['uid'],
'nick_name' => $user_info['username'],
'action' => '商品【'.$order_goods_info['sku_name'].'】商家同意了退款申请,等待转账',
'action_way' => 2,
'order_id' => $order_goods_info['order_id'],
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
];
OrderLog::addOrderLog($log_data, $order_common_model);
$order_refund_model = new OrderRefund();
//记录订单日志 end
$order_refund_model->addOrderRefundLog($order_goods_info['order_goods_id'], $refund_status, '卖家确认退款', 2, $user_info['uid'], $user_info['username']);
//订单退款同意消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'ORDER_REFUND_AGREE', 'order_id' => $order_goods_info['order_id'], 'order_goods_id' => $order_goods_info['order_goods_id'], 'site_id' => $order_goods_info['site_id']]);
//后续事件
event('OrderRefundConfirmAfter', $data);
return true;
}
}

View File

@@ -0,0 +1,82 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\model\BaseModel;
use app\model\message\Message;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 买家退货
*/
class Delivery extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
$order_info = $data['order_info'];
$member_info = $data['member_info'];
$order_goods_info = $data['order_goods_info'];
event('OrderRefundDeliveryCheck', []);
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_info = $data['order_info'] ?? [];
$member_info = $data['member_info'] ?? [];
$order_goods_info = $data['order_goods_info'] ?? [];
// $order_refund_model = new OrderRefund();
event('orderRefundDelivery', $data);
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
// $order_info = $data['order_info'];
$member_info = $data['member_info'];
$order_goods_info = $data['order_goods_info'];
// $log_data = $data['log_data'] ?? [];
$order_refund_model = new OrderRefund();
$order_refund_model->addOrderRefundLog(
$order_goods_info['order_goods_id'],
$data['refund_status'],
$data['refund_delivery_name'] . ':' . $data['refund_delivery_no'],
1,
$member_info['member_id'],
$member_info['nickname']);
//买家已退货提醒
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'BUYER_DELIVERY_REFUND', 'order_goods_info' => $order_goods_info, 'site_id' => $order_goods_info['site_id']]);
return true;
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单退款完成
*/
class Finish extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$user_info = $data['user_info'] ?? [];
$order_goods_info = $data['order_goods_info'] ?? [];
$order_goods_id = $order_goods_info['order_goods_id'];
$order_info = $data['order_info'] ?? [];
$order_refund_model = new OrderRefund();
//订单项退款后各种订单操作
$order_refund_model->orderGoodsRefund($order_goods_info);
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$user_info = $data['user_info'];
$order_goods_info = $data['order_goods_info'];
$order_goods_id = $order_goods_info['order_goods_id'];
$order_info = $data['order_info'];
$member_id = $order_info['member_id'];
$refund_real_money = $order_goods_info['refund_real_money'];
$order_refund_model = new OrderRefund();
//累加会员销售额
model('member')->setDec(
[['member_id', '=', $member_id]],
'order_money',
$refund_real_money
);
//退货日志
$order_refund_model->addOrderRefundLog(
$order_goods_id,
OrderRefundDict::REFUND_COMPLETE,
'维权完成',
2,
$user_info['uid'],
$user_info['username'],
'维权完成,退款金额:¥' . $refund_real_money
);
//后续事件
event('OrderRefundFinishAfter', $data);
return true;
}
}

View File

@@ -0,0 +1,143 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use addon\cardservice\model\MemberCard;
use app\dict\goods\GoodsDict;
use app\dict\member_account\AccountDict;
use app\dict\order\OrderDict;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\member\MemberAccount;
use app\model\order\Order;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use app\model\verify\Verify as VerifyModel;
use extend\exception\RefundException;
use think\db\exception\DbException;
/**
* 订单退款完成
*/
class FinishAction extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_goods_info = $data['order_goods_info'];
$order_goods_id = $order_goods_info['order_goods_id'];
$order_info = $data['order_info'];
$order_id = $order_info['order_id'];
$order_refund_model = new OrderRefund();
$is_all_refund = $data['is_all_refund'];
$refund_total_real_money = $data['refund_total_real_money'];
$member_id = $order_info['member_id'];
$site_id = $order_info['site_id'];
//更新订单锁定状态
$order_refund_model->verifyOrderLock($order_id);
if ($order_goods_info['refund_mode'] == OrderRefundDict::refund) {
//虚拟商品 退款 修改核销码状态
if ($order_goods_info['goods_class'] == GoodsDict::virtual) {
$verify_goods_condition = [
['order_no', '=', $order_info['order_no']],
['site_id', '=', $site_id]
];
model('goods_virtual')->update(['is_veirfy' => VerifyModel::STATUS_REFUNDED], $verify_goods_condition);
$verify_model = new VerifyModel();
$verify_condition = [
['verify_code', '=', $order_info['virtual_code']],
['site_id', '=', $site_id]
];
$verify_model->editVerify(['is_verify' => VerifyModel::STATUS_REFUNDED], $verify_condition);
}
// 退还积分 只有退款时返还 售后不返还
if ($order_goods_info['use_point'] > 0) {
$member_account_model = new MemberAccount();
$point_result = $member_account_model->addMemberAccount(
$site_id,
$member_id,
AccountDict::point,
$order_goods_info['use_point'],
'refund',
$order_id,
'订单退款返还!'
);
if ($point_result['code'] < 0) {
throw new RefundException($point_result['message']);
}
}
}
//订单修改
$order_update_data = [
'refund_money' => $refund_total_real_money,
];
// 如果售后完成关闭订单评价
if ($is_all_refund && $order_info['order_status'] == Order::ORDER_COMPLETE) {
$order_update_data['is_evaluate'] = 0;
} else if ($order_info['order_status'] == Order::ORDER_COMPLETE || $order_info['order_status'] == Order::ORDER_TAKE_DELIVERY) {
if ($order_info['evaluate_status'] != OrderDict::evaluate_again) {
$order_update_data['is_evaluate'] = 1;
}
}
model('order')->update($order_update_data, [['order_id', '=', $order_id]]);
//统一写入退款日志
if (!empty($log_data)) {
$order_common_model = new OrderCommon();
$log_data = array_merge($log_data, [
'order_id' => $order_id,
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
]);
OrderLog::addOrderLog($log_data, $order_common_model);
}
//订单退款完成操作(满减送奖励收回)
event('OrderRefundFinish', ['order_goods_info' => $order_goods_info, 'order_info' => $order_info, 'is_all_refund' => $is_all_refund]);
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_goods_info = $data['order_goods_info'] ?? [];
$order_info = $data['order_info'] ?? [];
$order_refund_model = new OrderRefund();
$order_id = $order_info['order_id'] ?? 0;
$member_id = $order_info['member_id'] ?? 0;
$site_id = $order_info['site_id'] ?? 0;
return true;
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\model\BaseModel;
use app\model\message\Message;
use app\model\order\Order as OrderModel;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单申请退款
*/
class Refuse extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
// $order_info = $data['order_info'];
// $user_info = $data['user_info'];
// $order_goods_info = $data['order_goods_info'];
//
//
// //订单申请退款校验
// event('OrderRefundRefuseCheck', []);
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
$order_info = $data['order_info'];
$user_info = $data['user_info'] ?? [];
$order_goods_info = $data['order_goods_info'];
$order_refund_model = new OrderRefund();
//订单锁定或解锁
$order_refund_model->verifyOrderLock($order_goods_info['order_id']);
// 维权拒绝 评价锁定放开
model('order')->update(['is_evaluate' => 1], [['order_id', '=', $order_info['order_id']], ['order_status', 'in', [OrderModel::ORDER_TAKE_DELIVERY, OrderModel::ORDER_COMPLETE]]]);
event('OrderRefundRefuse', $data);
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$order_info = $data['order_info'];
$order_goods_info = $data['order_goods_info'];
$user_info = $data['user_info'];
$log_data = $data['log_data'] ?? [];
$order_refund_model = new OrderRefund();
$log_desc = empty($data['refund_refuse_reason']) ? '' : '拒绝原因:' . $data['refund_refuse_reason'];
$order_refund_model->addOrderRefundLog($order_goods_info['order_goods_id'], $data['refund_status'], '卖家拒绝退款', 2, $user_info['uid'], $user_info['username'], $log_desc);
if ($log_data) {
$order_common_model = new OrderCommon();
$log_data = array_merge($log_data, [
'order_id' => $order_goods_info['order_id'],
'order_status' => $order_info['order_status'],
'order_status_name' => $order_info['order_status_name']
]);
OrderLog::addOrderLog($log_data, $order_common_model);
}
//订单退款拒绝消息
$message_model = new Message();
$message_model->sendMessage(['keywords' => 'ORDER_REFUND_REFUSE', 'order_id' => $order_goods_info['order_id'], 'order_goods_id' => $order_goods_info['order_goods_id'], 'site_id' => $order_goods_info['site_id']]);
event('OrderRefundRefuseAfter', $data);
return true;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace app\model\order\orderrefund;
use app\model\BaseModel;
use app\model\order\OrderRefund;
use think\db\exception\DbException;
/**
* 订单审核退款
*/
class TakeDelivery extends BaseModel
{
/**
* 校验
* @param $data
* @return array|true
* @throws DbException
*/
public static function check($data)
{
return true;
}
/**
* 退款执行事件
* @param $data
* @return true
* @throws DbException
*/
public static function event($data)
{
return true;
}
/**
* 后续事件
* @param $data
* @return array|true
*/
public static function after($data)
{
$user_info = $data['user_info'];
$order_goods_info = $data['order_goods_info'];
$refund_status = $data['refund_status'];
$order_refund_model = new OrderRefund();
$order_refund_model->addOrderRefundLog(
$order_goods_info['order_goods_id'],
$refund_status,
'卖家确认收到退货',
2,
$user_info['uid'],
$user_info['username']);
//后续事件
event('OrderRefundTakeDeliveryAfter', $data);
return true;
}
}