初始上传

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

494
addon/cashier/model/Cashier.php Executable file
View File

@@ -0,0 +1,494 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\system\Config;
use Exception;
use ZipArchive;
use think\facade\Db;
/**
* @author Administrator
*/
class Cashier extends BaseModel
{
private $path = 'addon/cashier/source';
/**
* 交接班
* @param $user_info
* @param $site_id
* @param $store_id
* @return array
*/
public function changeShifts($user_info, $site_id, $store_id)
{
$data = $this->getShiftsData($site_id, $store_id);
$data = array_merge($data, [
'site_id' => $site_id,
'store_id' => $store_id,
'uid' => $user_info[ 'uid' ]
]);
$id = model('change_shifts_record')->add($data);
if ($id) {
return $this->success($id);
} else {
return $this->error('', '交接班数据添加失败!');
}
}
/**
* 查询班次内数据
* @param $site_id
* @param $store_id
* @return array
*/
public function getShiftsData($site_id, $store_id)
{
$last_info = model('change_shifts_record')->getFirstData([ [ 'site_id', '=', $site_id ], [ 'store_id', '=', $store_id ] ], 'end_time', 'end_time desc');
$start_time = empty($last_info) ? 0 : $last_info[ 'end_time' ];
$end_time = time();
$order_condition = [
[ 'site_id', '=', $site_id ],
[ 'store_id', '=', $store_id ],
[ 'order_scene', '=', 'cashier' ],
[ 'order_status', '=', 10 ],
[ 'finish_time', 'between', [ $start_time, $end_time ] ]
];
$order_condition[ 5 ] = [ 'cashier_order_type', '=', 'goods' ];
$billing_stat = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'cashier_order_type', '=', 'card' ];
$card_stat = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'cashier_order_type', '=', 'recharge' ];
$recharge_stat = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'cash' ];
$cash = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'alipay' ];
$alipay = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'wechatpay' ];
$wechatpay = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'own_wechatpay' ];
$own_wechatpay = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'own_alipay' ];
$own_alipay = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$order_condition[ 5 ] = [ 'pay_type', '=', 'own_pos' ];
$own_pos = model('order')->getInfo($order_condition, 'count(order_id) as num, ifnull(sum(pay_money), 0) as pay_money');
$refund_condition = [
[ 'o.site_id', '=', $site_id ],
[ 'o.store_id', '=', $store_id ],
[ 'o.order_scene', '=', 'cashier' ],
[ 'og.refund_status', 'in', [OrderRefundDict::REFUND_COMPLETE,OrderRefundDict::PARTIAL_REFUND] ],
[ 'og.refund_time', 'between', [ $start_time, $end_time ] ]
];
$refund_stat = model('order_goods')->getInfo($refund_condition, 'count(og.order_goods_id) as num, ifnull(sum(refund_pay_money+shop_active_refund_money), 0) as money', 'og', [
[ 'order o', 'o.order_id = og.order_id', 'inner' ]
]);
$sale_goods_count = $this->getSaleGoodsCount([
['o.store_id', '=', $store_id],
['o.pay_time', '>', $start_time],
['o.pay_time', '<=', $end_time],
])['data'];
return [
'start_time' => $start_time,
'end_time' => $end_time,
'billing_count' => $billing_stat[ 'num' ],
'billing_money' => $billing_stat[ 'pay_money' ],
'buycard_count' => $card_stat[ 'num' ],
'buycard_money' => $card_stat[ 'pay_money' ],
'recharge_count' => $recharge_stat[ 'num' ],
'recharge_money' => $recharge_stat[ 'pay_money' ],
'refund_count' => $refund_stat[ 'num' ],
'refund_money' => $refund_stat[ 'money' ],
'cash_count' => $cash[ 'num' ],
'cash' => $cash[ 'pay_money' ],
'alipay_count' => $alipay[ 'num' ],
'alipay' => $alipay[ 'pay_money' ],
'wechatpay_count' => $wechatpay[ 'num' ],
'wechatpay' => $wechatpay[ 'pay_money' ],
'own_wechatpay_count' => $own_wechatpay[ 'num' ],
'own_wechatpay' => $own_wechatpay[ 'pay_money' ],
'own_alipay_count' => $own_alipay[ 'num' ],
'own_alipay' => $own_alipay[ 'pay_money' ],
'own_pos_count' => $own_pos[ 'num' ],
'own_pos' => $own_pos[ 'pay_money' ],
'sale_goods_count' => $sale_goods_count,
];
}
/**
* 查询交班记录
* @param array $condition
* @param bool $field
* @param string $order
* @param int $page
* @param int $list_rows
* @param string $alias
* @param array $join
* @return array
*/
public function getchangeShiftsPageList($condition = [], $field = true, $order = '', $page = 1, $list_rows = PAGE_LIST_ROWS, $alias = 'a', $join = [])
{
$data = model('change_shifts_record')->pageList($condition, $field, $order, $page, $list_rows, $alias, $join);
return $this->success($data);
}
/**
* 查询交班信息记录
* @param array $condition
* @param bool $field
* @return array
*/
public function getChangeShiftsRecordInfo($condition = [], $field = true, $alias = 'a', $join = null)
{
$data = model('change_shifts_record')->getInfo($condition, $field, $alias, $join);
return $this->success($data);
}
/**
* 刷新收银端
* @return array
*/
public function refreshCashier()
{
try {
$path = $this->path . '/default';
$cashier_path = 'cashregister'; // 收银端生成目录
$config_path = 'cashregister/static/js'; // 收银模板文件目录
if (!is_dir($path) || count(scandir($path)) <= 3) {
return $this->error('', '未找到源码包,请检查目录文件!');
}
if (is_dir($cashier_path)) {
// 先将之前的文件删除
if (count(scandir($cashier_path)) > 1) deleteDir($cashier_path);
} else {
// 创建收银目录
mkdir($cashier_path, intval('0777', 8), true);
}
// 将原代码包拷贝到收银目录下
recurseCopy($path, $cashier_path);
$this->copyFile($config_path);
file_put_contents($cashier_path . '/refresh.log', time());
return $this->success();
} catch (Exception $e) {
return $this->error('', $e->getMessage());
}
}
/**
* 替换配置信息API请求域名地址、图片、地图密钥等
* @param $source_path
* @param string $domain
*/
private function copyFile($source_path, $domain = __ROOT__)
{
$files = scandir($source_path);
foreach ($files as $path) {
if ($path != '.' && $path != '..') {
$temp_path = $source_path . '/' . $path;
if (file_exists($temp_path)) {
if (preg_match('/(index.)(\w{8})(.js)$/', $temp_path)) {
$content = file_get_contents($temp_path);
$content = $this->paramReplace($content, $domain);
file_put_contents($temp_path, $content);
}
}
}
}
}
/**
* 参数替换
* @param $string
* @param string $domain
* @return string|string[]|null
*/
private function paramReplace($string, $domain = __ROOT__)
{
$patterns = [
'/\{\{\$baseUrl\}\}/',
'/\{\{\$imgDomain\}\}/',
'/\{\{\$webSocket\}\}/'
];
$socket_url = (strstr(__ROOT__, 'https://') === false ? str_replace('http', 'ws', __ROOT__) : str_replace('https', 'wss', __ROOT__)) . '/wss';
$replacements = [
$domain,
$domain,
$socket_url,
];
return preg_replace($patterns, $replacements, $string);
}
/**
* 下载收银端uni-app源码
* @return array
*/
public function downloadOs()
{
try {
$source_file_path = $this->path . '/os';
if (!is_dir($source_file_path) || count(scandir($source_file_path)) <= 3) {
return $this->error('', '未找到源码包,请检查目录文件!');
}
$file_arr = getFileMap($source_file_path);
if (!empty($file_arr)) {
$zipname = 'cashier_os_' . date('YmdHi') . '.zip';
$zip = new ZipArchive();
$res = $zip->open($zipname, ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($file_arr as $file_path => $file_name) {
if (is_dir($file_path)) {
$file_path = str_replace($source_file_path . '/', '', $file_path);
$zip->addEmptyDir($file_path);
} else {
$zip_path = str_replace($source_file_path . '/', '', $file_path);
$zip->addFile($file_path, $zip_path);
}
}
$zip->close();
header('Content-Type: application/zip');
header('Content-Transfer-Encoding: Binary');
header('Content-Length: ' . filesize($zipname));
header("Content-Disposition: attachment; filename=\"" . basename($zipname) . "\"");
readfile($zipname);
@unlink($zipname);
}
}
return $this->success();
} catch (Exception $e) {
return $this->error('', $e->getMessage());
}
}
/**
* 获取收银台收款设置
* @param int $site_id
* @param int $store_id
* @return array
*/
public function getCashierCollectMoneyConfig(int $site_id, int $store_id)
{
$config = (new Config())->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'CASHIER_COLLECT_MONEY_CONFIG_' . $store_id ] ])[ 'data' ][ 'value' ];
if (empty($config)) {
$config = [
'reduction' => 1,
'point' => 1,
'balance' => 1,
'balance_safe' => 0,
'sms_verify' => 0,
'pay_type' => [ 'third', 'cash', 'own_wechatpay', 'own_alipay', 'own_pos' ]
];
}
return $this->success($config);
}
/**
* 收银台收款设置
* @param int $site_id
* @param int $store_id
* @param array $config
* @return array
*/
public function setCashierCollectMoneyConfig(int $site_id, int $store_id, array $config)
{
return (new Config())->setConfig($config, '收银端收款设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'CASHIER_COLLECT_MONEY_CONFIG_' . $store_id ] ]);
}
/**
* 设置收银台主题风格配置
* @param $data
* @param int $site_id
* @param string $app_module
* @return array
*/
public function setThemeConfig($data, $site_id = 1, $app_module = 'shop')
{
$config = new Config();
$res = $config->setConfig($data, '收银台主题风格配置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'CASHIER_THEME_CONFIG' ] ]);
return $res;
}
/**
* 获取收银台主题风格配置
* @param int $site_id
* @param string $app_module
* @return array
*/
public function getThemeConfig($site_id = 1, $app_module = 'shop')
{
$config = new Config();
$res = $config->getConfig([
[ 'site_id', '=', $site_id ],
[ 'app_module', '=', $app_module ],
[ 'config_key', '=', 'CASHIER_THEME_CONFIG' ]
]);
if (empty($res[ 'data' ][ 'value' ])) {
$res[ 'data' ][ 'value' ] = $this->getThemeList()[ 'data' ][ 0 ];
}
return $res;
}
/**
* 收银台主题风格列表
* @return array
*/
public function getThemeList()
{
// todo 这里支持扩展色调
$res = [
[
'title' => '橙色', // 标题
'name' => 'orange', // 标识
'color' => '#FA6400' // 主色调
],
[
'title' => '紫色',
'name' => 'purple',
'color' => '#A253FF'
],
[
'title' => '粉色',
'name' => 'pink',
'color' => '#ff08a7'
],
[
'title' => '棕色',
'name' => 'brown',
'color' => '#CFAF70'
],
[
'title' => '绿色',
'name' => 'green',
'color' => '#19C650'
],
[
'title' => '蓝色',
'name' => 'blue',
'color' => '#105CFB'
],
[
'title' => '红色',
'name' => 'red',
'color' => '#F4391c'
]
];
return $this->success($res);
}
/**
* 设置收银台会员搜索方式配置
* @param $data
* @param $store_id
* @param int $site_id
* @param string $app_module
* @return array
*/
public function setMemberSearchWayConfig($data, $store_id, $site_id = 1, $app_module = 'shop')
{
$config = new Config();
$res = $config->setConfig($data, '收银台会员搜索方式配置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', $app_module ], [ 'config_key', '=', 'CASHIER_MEMBER_SEARCH_WAY_CONFIG_' . $store_id ] ]);
return $res;
}
/**
* 获取收银台会员搜索方式配置
* @param $store_id
* @param int $site_id
* @param string $app_module
* @return array
*/
public function getMemberSearchWayConfig($store_id, $site_id = 1, $app_module = 'shop')
{
$config = new Config();
$res = $config->getConfig([
[ 'site_id', '=', $site_id ],
[ 'app_module', '=', $app_module ],
[ 'config_key', '=', 'CASHIER_MEMBER_SEARCH_WAY_CONFIG_' . $store_id ]
]);
if (empty($res[ 'data' ][ 'value' ])) {
$res[ 'data' ][ 'value' ] = [
'way' => 'exact' // exact精确搜索list列表搜索
];
}
return $res;
}
/**
* 获取销售统计
* @param $info
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function getSaleGoodsCount($condition)
{
//分组查询
$list = Db::name('order_goods')
->alias('og')
->join('order o', 'o.order_id = og.order_id', 'inner')
->field("sum(og.num) as num,og.sku_id,IF(o.order_from = 'cashier', 'offline', 'online') as sale_channel")
->where($condition)
->group('og.sku_id,sale_channel')
->select()
->toArray();
//初始化数据
$data = [
'ids' => [],
'num' => 0,
'online_ids' => [],
'online_num' => 0,
'offline_ids' => [],
'offline_num' => 0,
];
//汇总数据
foreach($list as $val){
$data['ids'][$val['sku_id']] = $val['sku_id'];
$data['num'] += $val['num'];
if($val['sale_channel'] == 'online'){
$data['online_ids'][$val['sku_id']] = $val['sku_id'];
$data['online_num'] += $val['num'];
}else{
$data['offline_ids'][$val['sku_id']] = $val['sku_id'];
$data['offline_num'] += $val['num'];
}
}
//id数组转换为种类数量
$data['class_num'] = count($data['ids']);
unset($data['ids']);
$data['online_class_num'] = count($data['online_ids']);
unset($data['online_ids']);
$data['offline_class_num'] = count($data['offline_ids']);
unset($data['offline_ids']);
return $this->success($data);
}
}

139
addon/cashier/model/Group.php Executable file
View File

@@ -0,0 +1,139 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model;
use app\model\BaseModel;
/**
* 用户组
* @author Administrator
*
*/
class Group extends BaseModel
{
/**
* 添加用户组
* @param array $data
* @return array:string mixed
*/
public function addGroup($data)
{
//创建者数据
if(isset($data['create_uid'])){
$user_info = model('user')->getInfo([['uid', '=', $data['create_uid']]], 'uid,username,create_user_data');
$create_user_data = json_decode($user_info['create_user_data'], true);
$create_user_data[] = ['id' => (string)$user_info['uid'], 'name' => $user_info['username']];
$data['create_user_data'] = json_encode($create_user_data, JSON_UNESCAPED_UNICODE);
}
$res = model('cashier_auth_group')->add($data);
if ($res === false) {
return $this->error('', 'UNKNOW_ERROR');
}
return $this->success($res);
}
/**
* 修改用户组
* @param array $data
* @param array $condition
* @return array:string mixed
*/
public function editGroup($data, $condition)
{
$condition[] = ['keyword', '=', ''];//只能删除非系统用户组
$res = model('cashier_auth_group')->update($data, $condition);
if ($res === false) {
return $this->error('', 'UNKNOW_ERROR');
}
return $this->success($res);
}
/**
* 删除用户组(不能批量)
* @param array $group_id
* @param array $condition
* @return array:string mixed
*/
public function deleteGroup($condition)
{
$check_condition = array_column($condition, 2, 0);
$site_id = $check_condition['site_id'] ?? '';
if ($site_id === '') {
return $this->error('', 'REQUEST_SITE_ID');
}
$group_id = $check_condition['group_id'] ?? 0;
if (!is_int($group_id) && $group_id <= 0) {
return $this->error('', 'USER_GROUP_NOT_ALL_DELETE');
}
$temp_count = model('user_group')->getCount([['group_id', '=', $group_id], ['app_module', '=', 'store'], ['site_id', '=', $site_id]], 'uid');
if ($temp_count > 0)
return $this->error('', 'USER_GROUP_USED');
$condition[] = ['keyword', '=', ''];//只能删除非系统用户组
$res = model('cashier_auth_group')->delete($condition);
if ($res === false) {
return $this->error('', 'UNKNOW_ERROR');
}
return $this->success($res);
}
/**
* 获取门店分组列信息
* @param array $condition
* @param string $field
* @return array
*/
public function getStoreGroupColumn($condition = [], $field = '')
{
$res = model('cashier_auth_group')->getColumn($condition, $field);
return $this->success($res);
}
/**
* 获取用户组详情
* @param array $condition
* @return array:string mixed
*/
public function getGroupInfo($condition, $field = '*')
{
$info = model('cashier_auth_group')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取用户组列表
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
* @return array:string mixed
*/
public function getGroupList($condition = [], $field = true, $order = 'group_id asc', $limit = null)
{
$list = model('cashier_auth_group')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取管理组分页列表
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
* @return array:string mixed
*/
public function getGroupPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'group_id asc', $field = '*')
{
$list = model('cashier_auth_group')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

49
addon/cashier/model/Menu.php Executable file
View File

@@ -0,0 +1,49 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model;
use app\model\BaseModel;
use think\facade\Cache;
/**
* @author Administrator
*/
class Menu extends BaseModel
{
/**
* 获取权限列表
* @param $condition
* @param $field
* @return array
*/
public function getMenuList($condition, $field)
{
$data = model('cashier_auth')->getList($condition, $field);
return $this->success($data);
}
/**
* 获取权限信息
* @param $condition
* @param $field
* @return array
*/
public function getMenuValue($condition, $field)
{
$key = json_encode([$condition, $field]);
if (Cache::has('getMenuValue' . $key)) {
return $this->success(Cache::get('getMenuValue' . $key));
}
$value = model('cashier_auth')->getValue($condition, $field);
Cache::tag('cashier_menu')->set('getMenuValue' . $key, $value);
return $this->success($value);
}
}

42
addon/cashier/model/Push.php Executable file
View File

@@ -0,0 +1,42 @@
<?php
namespace addon\cashier\model;
use app\model\BaseModel;
use GatewayClient\Gateway;
use think\facade\Log;
use app\dict\order\OrderDict;
class Push extends BaseModel
{
public function orderPay($order_info)
{
try{
if(!empty($order_info['store_id'])){
$config_info = require root_path().'/config/gateway.php';
Gateway::$registerAddress = $config_info['gateway']['register_address'];
$uid = 'store_'.$order_info['store_id'];
$data = [];
$fields = ['order_id','order_type','order_type_name'];
foreach ($fields as $field){
$data[$field] = $order_info[$field];
}
//语音通知类型
if($order_info['order_type'] == OrderDict::cashier){
$data['audio'] = 'cashier_order_pay_audio';
}else{
$data['audio'] = 'order_pay_audio';
}
if(Gateway::isUidOnline($uid)){
Gateway::sendToUid($uid, json_encode([ 'type' => 'order_pay', 'data' => $data ]));
return success();
}
}
}catch(\Exception $e){
Log::write('订单支付消息推送捕获错误');
Log::write(['file' => $e->getFile(), 'line' => $e->getLine(), 'message' => $e->getMessage()]);
}
}
}

View File

@@ -0,0 +1,256 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use addon\memberrecharge\model\Memberrecharge;
use addon\memberrecharge\model\MemberrechargeOrder;
use app\model\member\Member as MemberModel;
use app\model\order\OrderCommon;
use app\model\order\OrderCreate;
use app\model\order\OrderLog;
use app\model\order\OrderStock;
use app\model\system\Pay;
/**
* 订单创建(收银订单)
*
* @author Administrator
*
*/
class CashierOrder extends OrderCommon
{
//待付款
public const ORDER_CREATE = 0;
// 订单已支付
public const ORDER_PAY = 1;
// 订单已完成
public const ORDER_COMPLETE = 10;
// 订单已关闭
public const ORDER_CLOSE = -1;
// 订单类型
public $order_type = 5;
// 订单来源
public $order_from_list = [ 'cashier' => [ 'name' => '收银台' ] ];
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' => ''
]
],
'member_action' => [
[
'action' => 'orderClose',
'title' => '关闭订单',
'color' => ''
],
],
'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 $pay_type = [
'cash' => '现金支付',
'BALANCE' => '余额支付',
'own_wechatpay' => '个人微信',
'own_alipay' => '个人支付宝',
'own_pos' => '个人pos刷卡',
'ONLINE_PAY' => '在线支付',
];
public $cashier_order_type = [
'goods' => '消费',
'card' => '售卡',
'recharge' => '充值',
];
//todo 切勿调用,占位
public $delivery_status_list = [
0 => '待发货',
1 => '已发货',
2 => '已收货'
];
public function getPayType($params = [])
{
return $this->pay_type;
}
public function getCashierOrderType()
{
return $this->cashier_order_type;
}
public function refund($params)
{
if ($params[ 'is_refund_stock' ] == 1) {
$order_stock_model = new OrderStock();
$order_stock_model->incOrderStock($params);
}
return $this->success();
}
public function orderDetail($order_info)
{
return [];
}
/**
* 订单完成
* @param $params
* @return array
*/
public function complete($params)
{
$site_id = $params[ 'site_id' ];
$order_id = $params[ 'order_id' ];
$out_trade_no = $params['out_trade_no'];
$cashier_order_model = new CashierOrder();
$cashier_data = [
'order_status' => 10,
'finish_time' => time(),
'order_status_name' => $cashier_order_model->order_status[ 10 ][ 'name' ],
'order_status_action' => json_encode($cashier_order_model->order_status[ 10 ], JSON_UNESCAPED_UNICODE)
];
$cashier_condition = [
[ 'order_id', '=', $order_id ],
];
model('order')->update($cashier_data, $cashier_condition);
//订单支付完成后针对充值要增加充值订单支付
if ($params[ 'cashier_order_type' ] == 'recharge') {
$recharge_order_model = new MemberrechargeOrder();
$recharge_model = new Memberrecharge();
$member_model = new MemberModel();
$pay = new Pay();
$order_goods_list = model('order_goods')->getList([ [ 'order_id', '=', $params[ 'order_id' ] ] ]);
foreach ($order_goods_list as $k => $v) {
$recharge_id = $v[ 'sku_id' ];
$goods_money = $v[ 'goods_money' ];
//获取用户头像
$member_info = $member_model->getMemberInfo([ [ 'member_id', '=', $params[ 'member_id' ] ] ], 'headimg,nickname')[ 'data' ];
//获取套餐信息
if ($recharge_id > 0) {
//套餐字段
$field = 'recharge_id,recharge_name,cover_img,face_value,buy_price,point,growth,coupon_id';
$recharge_info = $recharge_model->getMemberRechargeInfo([ [ 'recharge_id', '=', $recharge_id ] ], $field)[ 'data' ];
if (empty($recharge_info)) {
return $this->error('', '无效的充值套餐');
}
} else {
$recharge_info = array (
"recharge_id" => 0,
"recharge_name" => '自定义面额充值',
"cover_img" => '',
"face_value" => $goods_money,
"buy_price" => $goods_money,
"point" => 0,
"growth" => 0,
"coupon_id" => 0,
);
}
$order_no = (new OrderCreate())->createOrderNo();
$data = [
'recharge_id' => $recharge_id,//套餐id
'face_value' => $recharge_info['face_value'],//自定义充值面额
'member_id' => $params[ 'member_id' ],
'order_from' => $params[ 'order_from' ],
'order_from_name' => $params[ 'order_from_name' ],
'site_id' => $site_id,
'relate_id' => $params[ 'order_id' ],
'relate_type' => 'order',
'store_id' => $params[ 'store_id' ],
'order_no' => $order_no,
'out_trade_no' => $out_trade_no,
'recharge_name' => $recharge_info[ 'recharge_name' ],
'cover_img' => $recharge_info[ 'cover_img' ],
'buy_price' => $recharge_info[ 'buy_price' ],
'pay_money' => $recharge_info[ 'buy_price' ],
'point' => $recharge_info[ 'point' ],
'growth' => $recharge_info[ 'growth' ],
'coupon_id' => $recharge_info[ 'coupon_id' ],
'status' => 1,
'create_time' => time(),
'member_img' => $member_info[ 'headimg' ],
'nickname' => $member_info[ 'nickname' ],
];
$recharge_order_model->addMemberRechargeOrder($data);
//充值订单支付
$result = $recharge_order_model->orderPay([
'out_trade_no' => $out_trade_no,
'pay_type' => $params['pay_type'],
]);
if($result['code'] < 0){
return $result;
}
}
}
$log_data = [
'order_id' => $order_id,
'action' => 'complete',
'site_id' => $site_id,
'is_auto' => 1
];
(new OrderLog())->addLog($log_data);
return $this->success();
}
public function orderPay()
{
}
}

View File

@@ -0,0 +1,815 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use addon\cashier\model\Cashier;
use addon\coupon\dict\CouponDict;
use addon\coupon\model\Coupon;
use addon\pointcash\model\Config as PointConfig;
use app\model\BaseModel;
use app\model\goods\GoodsCategory as GoodsCategoryModel;
use app\model\member\Member;
use app\model\order\OrderCreateTool;
/**
* 收银订单计算
* Class CashierOrderCalculate
* @package addon\cashier\model\order
*/
class CashierOrderCalculate extends BaseModel
{
use OrderCreateTool;
/**
* 计算
* @param $params
* @return array
*/
public function calculate($params)
{
$site_id = $params['site_id'];
$out_trade_no = $params['out_trade_no'];
$member_id = $params['member_id'] ?? 0;
if ($member_id == 0) {
unset($params['member_id']);
}
$this->member_id = $member_id;
$this->initMemberAccount();
$condition = [
['out_trade_no', '=', $out_trade_no]
];
$cashier_order_info = model('order')->getInfo($condition);
if (empty($cashier_order_info))
return $this->error();
$order_id = $cashier_order_info['order_id'];
$alias = 'og';
$join = [
['goods_sku gs', 'og.sku_id = gs.sku_id', 'inner'],
['goods g', 'og.goods_id = g.goods_id', 'inner'],
];
$order_goods_condition = [
['og.order_id', '=', $order_id]
];
$field = 'og.*, gs.is_consume_discount,gs.discount_config,gs.member_price,gs.discount_method, g.category_id';
$cashier_order_goods_list = model('order_goods')->getList($order_goods_condition, $field, '', $alias, $join);
$cashier_order_info['goods_list'] = $cashier_order_goods_list;
//todo 判断当前订单是否绑定了会员
$cashier_order_info = $this->calculateByMember($cashier_order_info, $member_id);
$cashier_order_goods_list = $cashier_order_info['goods_list'];
$cashier_order_info['collectmoney_config'] = (new Cashier())->getCashierCollectMoneyConfig($cashier_order_info['site_id'], $cashier_order_info['store_id'])['data'];
$is_calculate = isset($params['promotion']);
$promotion = $params['promotion'] ?? [];
$order_money = $cashier_order_info['order_money'];
$original_money = $order_money;
$cashier_order_info['original_money'] = $original_money;
$cashier_order_info['goods_num'] = numberFormat($cashier_order_info['goods_num']);
$cashier_order_info = array_merge($cashier_order_info, $promotion, $params);
$order_goods_id_map = [];
foreach ($cashier_order_goods_list as $goods_k => $goods_info) {
$item_order_goods_id = $goods_info['order_goods_id'];
$order_goods_id_map[$goods_k] = $item_order_goods_id;
$cashier_order_goods_list[$goods_k]['num'] = numberFormat($goods_info['num']);
}
$cashier_order_info['order_goods_id_map'] = $order_goods_id_map;
$cashier_order_info['goods_list'] = $cashier_order_goods_list;
if ($member_id > 0) {
$member_model = new Member();
$member_account_info = $member_model->getMemberDetail($member_id, $site_id)['data'] ?? [];
$cashier_order_info['member_account'] = $member_account_info;
}
$result = $this->promotionCalculate($cashier_order_info, $is_calculate);
if ($result['code'] < 0) {
return $result;
}
$result_data = $result['data'];
return $this->payCalculate($result_data);
}
/**
* 绑定会员后,根据会员信息重新计算订单
* @param $cashier_order_info
* @param $member_id
* @return mixed
*/
public function calculateByMember($cashier_order_info, $member_id)
{
$order_member_id = $cashier_order_info['member_id'];
if (!$order_member_id) {
if ($member_id > 0) {
$site_id = $cashier_order_info['site_id'];
//重新计算订单
$cashier_order_type = $cashier_order_info['cashier_order_type'];
$goods_list = $cashier_order_info['goods_list'];
$goods_money = 0;
$real_goods_money = 0;
foreach ($goods_list as &$v) {
$price = $v['price'];
$v['price'] = $price;
$item_goods_money = $v['goods_money'];
$item_real_goods_money = $v['real_goods_money'];
$item_num = $v['num'];
if (in_array($cashier_order_type, ['goods', 'card'])) {
$item_sku_id = $v['sku_id'] ?? 0;
if ($item_sku_id > 0) {
//无码商品不参与会员价
$item_is_adjust_price = $v['is_adjust_price'];
if (!$item_is_adjust_price) {
$member_price_result = $this->getGoodsMemberPrice($v);
if ($member_price_result['code'] >= 0) {
$price = $member_price_result['data'];
$v['is_member_price'] = true;
}
$v['price'] = $price;
$item_goods_money = $price * $item_num;
$item_real_goods_money = $price * $item_num;
$v['goods_money'] = $item_goods_money;
$v['real_goods_money'] = $item_real_goods_money;
}
}
}
$goods_money += $item_goods_money;
$real_goods_money += $item_real_goods_money;
}
$cashier_order_info['goods_money'] = $goods_money;
$cashier_order_info['real_goods_money'] = $real_goods_money;
$cashier_order_info['goods_list'] = $goods_list;
$order_money = $real_goods_money;
$cashier_order_info['order_money'] = $order_money;
$pay_money = $order_money;
$cashier_order_info['pay_money'] = $pay_money;
$cashier_order_info['is_bind_member'] = 1;//是否绑定会员
$cashier_order_info['member_id'] = $member_id;
}
}
return $cashier_order_info;
}
/**
* 活动计算
* @param $calculate
* @param bool $is_calculate
* @return array
*/
public function promotionCalculate($calculate, $is_calculate = true)
{
if ($is_calculate) {
$member_id = $calculate['member_id'] ?? 0;
if ($member_id > 0) {
$coupon_calculate = $this->couponCalculate($calculate);
if ($coupon_calculate['code'] < 0)
return $coupon_calculate;
$calculate = $coupon_calculate['data'];
}
$reduction_calculate = $this->reductionCalculate($calculate);
if ($reduction_calculate['code'] < 0)
return $reduction_calculate;
$calculate = $reduction_calculate['data'];
if ($member_id > 0 && $calculate['collectmoney_config']['point'] > 0) {
$point_calculate = $this->pointCalculate($calculate);
if ($point_calculate['code'] < 0)
return $point_calculate;
$calculate = $point_calculate['data'];
}
if ($member_id > 0 && $calculate['collectmoney_config']['balance'] > 0) {
$balance_calculate = $this->balanceCalculate($calculate);
if ($balance_calculate['code'] < 0)
return $balance_calculate;
$calculate = $balance_calculate['data'];
}
$offset = $calculate['offset'] ?? [];
$calculate['offset'] = $offset;
}
return $this->success($calculate);
}
/**
* 优惠券计算
* @param $calculate_data
* @return array
*/
public function couponCalculate($calculate_data)
{
$member_id = $calculate_data['member_id'] ?? 0;
if ($member_id > 0) {
$order_type = $calculate_data['cashier_order_type'];
//只有开单和卡项可以用优惠券
if (in_array($order_type, ['goods', 'card'])) {
$pay_money = $calculate_data['pay_money'];
$order_money = $calculate_data['order_money'];
$site_id = $calculate_data['site_id'];
$goods_list = $calculate_data['goods_list'] ?? [];
$is_can_coupon = true;
foreach ($goods_list as $v) {
$trade_type = $v['goods_class'];
if ($trade_type == 'money') {
$is_can_coupon = false;
}
}
$goods_ids = array_unique(array_column($goods_list, 'goods_id'));
$goods_money = $calculate_data['goods_money'];//优惠券现在取用的是商品价用作门槛
$real_goods_money = $goods_money;
$offset = $calculate_data['offset'] ?? [];
if ($order_money > 0 && $pay_money > 0) {
$condition = [
['member_id', '=', $member_id],
['state', '=', 1],
['site_id', '=', $site_id],
['use_channel', '<>', CouponDict::channel_online],
['use_store', 'like', ['%'.$calculate_data['store_id'].'%', '%all%'], 'or'],
];
$member_coupon_model = new Coupon();
$member_coupon_list = $member_coupon_model->getCouponList($condition)['data'];
$coupon_array = [];
$coupon_model = new Coupon();
foreach ($member_coupon_list as $k => $v) {
$is_available = $coupon_model->judgeCouponAvailable($v, $goods_list, $goods_money);
if($is_available){
$coupon_array[] = $v;
}
}
$member_coupon_list = $coupon_array;
}
$default_coupon_id = 0;
$default_coupon_end_time = 0;
$default_coupon_type = '';
$default_coupon_discount = 0;
$default_coupon_offset_money = 0;
$default_coupon_money = 0;
$temp_member_coupon_list = [];
$temp_cache_coupon = [];//用以减轻I/O压力
if (!empty($member_coupon_list)) {
$goods_category_model = new GoodsCategoryModel();
foreach ($member_coupon_list as $k => $v) {
// $parent_id = $v['coupon_type_id'];
$coupon_id = $v['coupon_id'];
$at_least = $v['at_least'];//最小条件
$item_type = $v['type'];//reward-满减 discount-折扣 random-随机
$goods_type = $v['goods_type'];
$intersect = [];
if ($goods_type == 1) {
// 全场
$intersect = $goods_ids;
} elseif ($goods_type == 2) {
// 指定商品
$item_goods_ids = explode(',', $v['goods_ids']);
$intersect = array_intersect($item_goods_ids, $goods_ids);
} elseif ($goods_type == 3) {
// 指定不参与商品
$item_goods_ids = explode(',', $v['goods_ids']);
$intersect = array_diff($goods_ids, $item_goods_ids);
} elseif ($goods_type == CouponDict::category_selected || $goods_type == CouponDict::category_selected_out) {
// 指定参与/不参与分类
$category_leaf_ids = $goods_category_model->getGoodsCategoryLeafIds($v['goods_ids'])['data'];
$item_goods_ids = [];
foreach ($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) {
$item_goods_ids[] = $v_goods['goods_id'];
}
}
$intersect = array_intersect($goods_ids, $item_goods_ids);
}
//计算这几个商品的商品总价
$goods_sum = 0;
$coupon_order_goods_ids = [];
$item_coupon_goods_list = [];
foreach ($goods_list as $goods_k => $goods_v) {
$item_id = $goods_v['goods_id'];
if (in_array($item_id, $intersect)) {
$goods_sum += $goods_v['real_goods_money'] ?? 0;//这儿用 商品价还是商品真实价格
$coupon_order_goods_ids[] = $goods_v['order_goods_id'];
$item_coupon_goods_list[] = $goods_v;
}
}
//判断它支持的商品的商品金额够不够最低金额
if ($goods_sum < $at_least) {
//移除会员优惠券
unset($member_coupon_list[$k]);
continue;
}
switch ($item_type) {
case 'reward'://满减
$item_coupon_money = $v['money'];
if ($item_coupon_money > $goods_sum) {
$item_coupon_money = $goods_sum;
}
break;
case 'discount'://折扣
$item_discount = $v['discount'];//折扣
$item_discount_limit = $v['discount_limit'];//最多抵扣
//计算折扣优惠金额
$item_coupon_money = $goods_sum * (10 - $item_discount) / 10;
$item_coupon_money = $item_coupon_money > $item_discount_limit && $item_discount_limit != 0 ? $item_discount_limit : $item_coupon_money;
$item_coupon_money = min($item_coupon_money, $goods_sum);
$item_coupon_money = moneyFormat($item_coupon_money);
break;
case 'divideticket'://随机
$item_coupon_money = $v['money'];
if ($item_coupon_money > $goods_sum) {
$item_coupon_money = $goods_sum;
}
break;
}
$member_coupon_list[$k]['coupon_goods_money'] = $goods_sum;
$member_coupon_list[$k]['coupon_money'] = $item_coupon_money;
$member_coupon_list[$k]['coupon_order_goods_ids'] = $coupon_order_goods_ids;
$member_coupon_list[$k]['coupon_goods_list'] = $item_coupon_goods_list;
//一个准则,折扣券不优先用
if ($item_coupon_money > $default_coupon_money) {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
if ($item_type == 'discount') {
$default_coupon_discount = $v['discount'];
} else {
$default_coupon_offset_money = $v['money'];
}
$default_coupon_money = $item_coupon_money;
} else if ($item_coupon_money == $default_coupon_money) {
if ($item_type == 'discount') {
if ($default_coupon_type == $item_type) {
if ($v['discount_limit'] < $default_coupon_discount) {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
$default_coupon_discount = $v['discount'];
} else if ($v['discount_limit'] == $default_coupon_discount) {
if ($v['end_time'] < $default_coupon_end_time) {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
$default_coupon_discount = $v['discount'];
}
}
}
} else {
if ($default_coupon_type == $item_type) {
if ($v['money'] < $default_coupon_offset_money) {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
$default_coupon_discount = $v['money'];
} else if ($v['money'] == $default_coupon_offset_money) {
if ($v['end_time'] < $default_coupon_end_time) {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
$default_coupon_discount = $v['money'];
}
}
} else {
$default_coupon_id = $coupon_id;
$default_coupon_end_time = $v['end_time'];
$default_coupon_type = $item_type;
$default_coupon_offset_money = $v['money'];
}
}
}
}
$temp_member_coupon_list = array_column($member_coupon_list, null, 'coupon_id');
}
$coupon_id = $calculate_data['coupon_id'] ?? '';
$coupon_money = 0;
$coupon_order_goods_ids = [];
//计算优惠券优惠
if (!empty($coupon_id)) {
$item_coupon_info = $temp_member_coupon_list[$coupon_id] ?? [];
//剔除非法代金券
if (empty($item_coupon_info)) {
$coupon_id = 0;
} else {
$item_coupon_money = $item_coupon_info['coupon_money'];
$real_goods_money -= $item_coupon_money;
$coupon_money += $item_coupon_money;
$coupon_order_goods_ids = $item_coupon_info['coupon_order_goods_ids'];
$coupon_goods_list = $item_coupon_info['coupon_goods_list'];
$coupon_goods_money = $item_coupon_info['coupon_goods_money'];
if ($item_coupon_money > $coupon_goods_money) {
$item_coupon_money = $coupon_goods_money;
}
$coupon_goods_list = $this->goodsCouponCalculate($coupon_goods_list, $coupon_goods_money, $item_coupon_money);
$coupon_goods_column = array_column($coupon_goods_list, null, 'order_goods_id');
foreach ($goods_list as $k => $v) {
if (in_array($v['order_goods_id'], $coupon_order_goods_ids)) {
$goods_list[$k] = $coupon_goods_column[$v['order_goods_id']];
}
}
}
}
if ($is_can_coupon) {
$coupon_switch = !empty($member_coupon_list);
} else {
$coupon_switch = false;
}
$coupon_array = [
'member_coupon_list' => $member_coupon_list ?? [],
'coupon_switch' => $coupon_switch
];
$offset['coupon_array'] = $coupon_array;
$calculate_data['offset'] = $offset;
$calculate_data['real_goods_money'] = $real_goods_money;
$calculate_data['coupon_money'] = $coupon_money;
$calculate_data['goods_list'] = $goods_list;
$calculate_data['coupon_id'] = $coupon_id;
$calculate_data['coupon_order_goods_ids'] = $coupon_order_goods_ids;
$pay_money -= $coupon_money;
$order_money -= $coupon_money;
$calculate_data['pay_money'] = $pay_money;
$calculate_data['order_money'] = $order_money;
}
}
return $this->success($calculate_data);
}
/**
* 按比例摊派优惠券优惠
* @param $goods_list
* @param $goods_money
* @param $coupon_money
* @return mixed
*/
public function goodsCouponCalculate($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 = moneyFormat($v['real_goods_money'] / $goods_money * $coupon_money);
} else {
$item_coupon_money = $temp_coupon_money;
}
$temp_coupon_money -= $item_coupon_money;
$goods_list[$k]['coupon_money'] = $item_coupon_money;
$real_goods_money = $v['real_goods_money'] - $item_coupon_money;
$real_goods_money = max($real_goods_money, 0);
$goods_list[$k]['real_goods_money'] = $real_goods_money; //真实订单项金额
}
return $goods_list;
}
/**
* 调价计算
* @param $cashier_order_info
* @return array
*/
public function reductionCalculate($cashier_order_info)
{
$offset = $cashier_order_info['offset'] ?? [];
$reduction = $cashier_order_info['reduction'] ?? 0;//调整金额
$order_money = $cashier_order_info['order_money'];
$promotion_money = $cashier_order_info['promotion_money'];
$pay_money = $cashier_order_info['pay_money'];
if ($reduction > 0) {
$offset_money = $cashier_order_info['offset_money'] ?? 0;
if ($reduction > $order_money) {
$reduction = $order_money;
}
$order_money -= $reduction;
if ($reduction > $pay_money) {
$reduction = $pay_money;
}
$pay_money -= $reduction;
$offset['reduction'] = $reduction;
$cashier_order_info['reduction'] = $reduction;
$offset_money += $reduction;
$promotion_money += $reduction;
$calculate_data['offset_money'] = $offset_money;
}
$cashier_order_info['pay_money'] = $pay_money;
$cashier_order_info['offset'] = $offset;
$cashier_order_info['promotion_money'] = $promotion_money;
$cashier_order_info['order_money'] = $order_money;
//同步订单项列表real_goods_money
$cashier_order_info = $this->calculateGoodsList($cashier_order_info, $reduction);
return $this->success($cashier_order_info);
}
/**
* 优惠金额
* @param $cashier_order_info
* @param $money
* @return mixed
*/
public function calculateGoodsList($cashier_order_info, $money)
{
if ($money > 0) {
$goods_list = $cashier_order_info['goods_list'];
$temp_money = $money;
foreach ($goods_list as &$v) {
$real_goods_money = $v['real_goods_money'];
if ($real_goods_money >= $temp_money) {
$real_goods_money -= $temp_money;
} else {
$real_goods_money = 0;
}
$item_money = $temp_money;
$temp_money -= $item_money;
$v['real_goods_money'] = $real_goods_money;
}
$cashier_order_info['goods_list'] = $goods_list;
}
return $cashier_order_info;
}
/**
* 积分计算
* @param $cashier_order_info
* @return array
*/
public function pointCalculate($cashier_order_info)
{
$member_account = $cashier_order_info['member_account'] ?? [];
if (addon_is_exit('pointcash')) {
if (!empty($member_account)) {
$order_type = $cashier_order_info['cashier_order_type'];
if (in_array($order_type, ['goods', 'card'])) {
$site_id = $cashier_order_info['site_id'];
$offset = $cashier_order_info['offset'] ?? [];
$pay_money = $cashier_order_info['pay_money'];
$offset_money = $cashier_order_info['offset_money'] ?? 0;
$order_money = $cashier_order_info['order_money'];
$site_type = $cashier_order_info['site_type'] ?? '';
$point = 0;
$point_money = 0;
$use_point_money = 0;
$use_point = 0;
$is_use_point = $cashier_order_info['is_use_point'] ?? 0;//使用积分
//积分
$point_config_model = new PointConfig();
$point_config = $point_config_model->getPointCashConfig($site_id)['data'];
$point_value = $point_config['value'];
$is_use = $point_config['is_use'];
if ($is_use > 0) {
$is_limit = $point_value['is_limit'];
if ($is_limit == 1) {
$limit = $point_value['limit'];
if ($order_money < $limit) {
return $this->success($cashier_order_info);
}
}
$max_point_money = 0;
if ($point_value['is_limit_use'] == 1) {
if ($point_value['type'] == 0) {
$max_point_money = $point_value['max_use'];
} else {
$ratio = $point_value['max_use'] / 100;
$max_point_money = round(($order_money * $ratio), 2);
}
if ($max_point_money > $order_money) {
$max_point_money = $order_money;
}
}
$point_exchange_rate = $point_value['cash_rate'] ?? 0;//积分兑换比率 为0的话认为没有开启积分兑换
if ($point_exchange_rate > 0) {
$member_account_point = $member_account['point'];//会员积分
if ($member_account_point > 0) {//拥有积分大于0
$point_money = round($member_account_point / $point_exchange_rate, 2);//积分抵扣金额
if ($point_money > $pay_money) {
$point_money = $pay_money;
}
if ($max_point_money != 0 && $point_money > $max_point_money) {
$point_money = $max_point_money;
}
$point = ceil($point_money * $point_exchange_rate);
}
}
}
$point_array = [
'point' => $point,
'point_money' => $point_money,
'point_switch' => false
];
if ($pay_money > 0) {
if ($point > 0) {
$point_array['point_switch'] = true;
//存在可用积分且选用了积分抵扣
if ($is_use_point) {
$order_money -= $point_money;
$pay_money -= $point_money;
$use_point_money = $point_money;
$use_point = $point;
}
} else {
$is_use_point = 0;
}
} else {
$is_use_point = 0;
}
$offset['point_array'] = $point_array;
$cashier_order_info['offset'] = $offset;
$cashier_order_info['order_money'] = $order_money;
$cashier_order_info['is_use_point'] = $is_use_point;
$offset_money += $use_point_money;
$cashier_order_info['offset_money'] = $offset_money;
$cashier_order_info['point_money'] = $use_point_money;//积分抵扣多少金额
$cashier_order_info['point'] = $use_point;//使用多少个积分
$cashier_order_info['pay_money'] = $pay_money;
if ($is_use_point == 1) {
//同步订单项列表real_goods_money
$cashier_order_info = $this->calculateGoodsList($cashier_order_info, $point_money);
}
}
}
}
return $this->success($cashier_order_info);
}
/**
* 余额计算
* @param $cashier_order_info
* @return array
*/
public function balanceCalculate($cashier_order_info)
{
$offset = $cashier_order_info['offset'] ?? [];
$pay_money = $cashier_order_info['pay_money'];
$order_money = $cashier_order_info['order_money'];
// $promotion = $cashier_order_info['promotion'] ?? [];
$is_use_balance = $cashier_order_info['is_use_balance'] ?? 0;
$member_account = $cashier_order_info['member_account'] ?? [];
if (!empty($member_account)) {
$order_type = $cashier_order_info['cashier_order_type'];
if (in_array($order_type, ['goods', 'card'])) {
$member_balance_total = $member_account['balance_total'] ?? 0;
$offset_money = $cashier_order_info['offset_money'] ?? 0;
$balance_money = 0;
if ($member_balance_total > 0) {
$balance_money = min($member_balance_total, $pay_money);
}
$balance_array = [
'balance' => $balance_money,
'balance_money' => $balance_money,
'balance_switch' => false
];
$total_balance = 0;
if ($pay_money > 0) {
if ($balance_money > 0) {
$balance_array['balance_switch'] = true;
if ($is_use_balance > 0) {
$total_balance = $balance_money;
$pay_money -= $balance_money;
}
} else {
$is_use_balance = 0;
}
} else {
$is_use_balance = 0;
}
$offset['balance'] = $balance_array;
$cashier_order_info['is_use_balance'] = $is_use_balance;
$cashier_order_info['order_money'] = $order_money;
$cashier_order_info['pay_money'] = $pay_money;
$cashier_order_info['offset'] = $offset;
$cashier_order_info['total_balance'] = $total_balance ?? 0;
$offset_money += $total_balance;
$cashier_order_info['offset_money'] = $offset_money;
}
}
return $this->success($cashier_order_info);
}
/**
* 支付计算
* @param $cashier_order_info
* @return array
*/
public function payCalculate($cashier_order_info)
{
$member_id = $cashier_order_info['member_id'] ?? 0;
$pay_money = $cashier_order_info['pay_money'];
$pay_type = $cashier_order_info['pay_type'] ?? '';
if ($pay_type == 'third') {
$pay_type = 'ONLINE_PAY';
}
$online_type = empty($cashier_order_info['online_type']) ? $pay_type : $cashier_order_info['online_type'];
$paid_money = 0;
$cash = $cashier_order_info['cash'] ?? 0;
$balance = $cashier_order_info['total_balance'];
$online_money = $cashier_order_info['online_money'] ?? 0;
switch ($online_type) {
case 'cash':
$cash = $cashier_order_info['cash'];
$paid_money += $cash;
break;
case 'online':
$online_money = $pay_money;
$paid_money += $online_money;
break;
case 'own_wechatpay':
$own_wechatpay = $pay_money;
$paid_money += $own_wechatpay;
break;
case 'own_alipay':
$own_alipay = $pay_money;
$paid_money += $own_alipay;
break;
case 'own_pos':
$own_pos = $pay_money;
$paid_money += $own_pos;
break;
}
$surplus_money = $pay_money - $paid_money;
if ($surplus_money < 0) {
$cash_change = abs($surplus_money);
}
$data = [
'pay_money' => $pay_money,
'paid_money' => $paid_money,
'surplus_money' => $surplus_money,
'cash' => $cash,
'cash_change' => $cash_change ?? 0,
'total_balance' => $balance,//总余额
'online_money' => $online_money,
'online_type' => $online_type,
'own_wechatpay' => $own_wechatpay ?? 0,
'own_alipay' => $own_alipay ?? 0,
'own_pos' => $own_pos ?? 0,
'pay_type' => $pay_type,
];
if ($member_id > 0) {
$data['member_id'] = $member_id;
}
$data = array_merge($cashier_order_info, $data);
return $this->success($data);
}
public function roundCalculate($cashier_order_info)
{
$offset = $cashier_order_info['offset'] ?? [];
$reduction = $cashier_order_info['reduction'] ?? 0;//调整金额
$order_money = $cashier_order_info['order_money'];
$promotion_money = $cashier_order_info['promotion_money'];
$round_type = $cashier_order_info['round_type'];//收银台 抹零方式 1抹分 2抹角
$pay_money = $cashier_order_info['pay_money'];
if (!empty($round_type)) {
$offset_money = $cashier_order_info['offset_money'] ?? 0;
$new_order_money = 0;
switch ($round_type) {
case 1:
$new_order_money = round(intval($order_money * 10) / 10, 2);
break;
case 2:
$new_order_money = round(intval($order_money * 100) / 100, 2);
break;
}
$round_money = $order_money - $new_order_money;
// if ($round_money > $order_money) {
// $round_money = $pay_money;
// }
$order_money -= $round_money;
// if ($round_money > $pay_money) {
// $round_money = $pay_money;
// }
$pay_money -= $round_money;
$offset['round'] = $round_money;
$cashier_order_info['round_money'] = $round_money;
$offset_money += $round_money;
$promotion_money += $round_money;
$calculate_data['offset_money'] = $offset_money;
}
$cashier_order_info['pay_money'] = $pay_money;
$cashier_order_info['offset'] = $offset;
$cashier_order_info['promotion_money'] = $promotion_money;
$cashier_order_info['order_money'] = $order_money;
return $this->success($cashier_order_info);
}
}

View File

@@ -0,0 +1,693 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use addon\cardservice\model\MemberCard;
use app\dict\goods\GoodsDict;
use app\model\BaseModel;
use app\model\order\OrderCreateTool;
use app\model\system\Cron;
use app\model\system\Pay;
use Exception;
use extend\exception\OrderException;
use think\facade\Queue;
/**
* 订单创建(收银台订单)
* Class CashierOrderCreate
* @package addon\cashier\model\order
*/
class CashierOrderCreate extends BaseModel
{
use OrderCreateTool;
public $error_printf = [];
public $real_goods_money = 0;
public $cashier_order_type;
public function create()
{
$order_key = $this->param['order_key'] ?? '';
//获取订单缓存
$this->getOrderCache($order_key);
$check_error = $this->checkError();
if ($check_error['code'] < 0) {
return $check_error;
}
model('order')->startTrans();
try {
$pay_model = new Pay();
$this->out_trade_no = $pay_model->createOutTradeNo($this->member_id);
$this->order_no = $this->createOrderNo();
$order_type = 5;//收银订单
//买家信息
$member_info = $this->member_account ?? [];
$nickname = $member_info['nickname'] ?? '';//会员昵称
$mobile = $member_info['mobile'] ?? '';
$nickname = !empty($nickname) ? $nickname : $mobile;
$store_name = $this->store_info['store_name'] ?? '';
$extend = $this->param['extend'] ?? [];
$sell_time = $this->param['create_time'] ?? 0;
if ($sell_time == 0) {
$sell_time = time();
} else {
$sell_time = strtotime($sell_time);
}
//操作人
$operator = $this->param['operator'] ?? [];
$operator_id = $operator['uid'] ?? 0;
$operator_name = $operator['username'] ?? '';
//订单来源
$order_from = 'cashier';
$order_from_name = (new CashierOrder())->order_from_list[$order_from]['name'] ?? '';
$cashier_order_model = new CashierOrder();
//创建订单
$data_order = [
'order_no' => $this->order_no,
'site_id' => $this->site_id,
'site_name' => $this->site_info['site_name'],
'order_name' => $this->order_name,
'out_trade_no' => $this->out_trade_no,
'member_id' => $this->member_id,
'name' => $nickname,
'mobile' => $mobile,
'pay_money' => $this->pay_money,
'goods_money' => $this->goods_money,
'real_goods_money' => $this->real_goods_money,
'order_money' => $this->order_money,
'store_id' => $this->store_id,
'create_time' => time(),
'order_from' => $order_from,
'order_from_name' => $order_from_name,
'order_type' => $order_type,
'order_type_name' => '收银订单',
'order_status' => 0,
'order_status_name' => '待支付',
'order_status_action' => json_encode($cashier_order_model->order_status[0], JSON_UNESCAPED_UNICODE),
'cashier_sell_time' => $sell_time,
'cashier_order_type' => $this->cashier_order_type,
'cashier_operator_id' => $operator_id,
'cashier_operator_name' => $operator_name,
'order_scene' => 'cashier',
'goods_num' => $this->goods_num ?? 1,
'remark' => $this->param['remark'] ?? ''
];
$this->order_id = model('order')->add($data_order);
$insert_order_goods_list = [];
foreach ($this->goods_list as $goods_v) {
$card_item_id = $goods_v['card_item_id'] ?? 0;
//订单项目表
$insert_order_goods_list[] = [
'order_id' => $this->order_id,
'site_id' => $this->site_id,
'member_id' => $this->member_id,
'goods_id' => $goods_v['goods_id'],
'sku_id' => $goods_v['sku_id'],
'goods_name' => $goods_v['goods_name'],
'sku_name' => $goods_v['sku_name'],
'sku_no' => $goods_v['sku_no'] ?? '',
'sku_image' => $goods_v['goods_image'] ?? '',
'spec_name' => $goods_v['spec_name'] ?? '',
'price' => $goods_v['price'],
'cost_price' => $goods_v['cost_price'] ?? 0,
'num' => $goods_v['num'],
'goods_money' => $goods_v['goods_money'],
'is_virtual' => $goods_v['is_virtual'] ?? 1,
'goods_class' => $goods_v['goods_class'],
'goods_class_name' => $goods_v['goods_class_name'],
'store_id' => $this->store_id,
'extend' => json_encode($extend),
'real_goods_money' => $goods_v['real_goods_money'],
'card_item_id' => $card_item_id,
'card_promotion_money' => $goods_v['card_promotion_money'] ?? 0,//次卡抵扣优惠
'supplier_id' => $goods_v['supplier_id'] ?? 0,
'is_adjust_price' => $goods_v['is_adjust_price'] ?? 0,//是否调整过价格
];
}
model('order_goods')->addList($insert_order_goods_list);
//批量扣除库存
// $this->batchDecOrderGoodsStock();
//库存转换
$this->batchGoodsStockTransform();
//校验库存是否足够
$this->checkStock();
model('order')->commit();
//订单后续任务
$this->cashierOrderCreateAfter();
$res = [
'order_id' => $this->order_id,
'out_trade_no' => $this->out_trade_no
];
// 生成整体付费支付单据
$pay_model->addPay($this->site_id, $this->out_trade_no, $this->pay_type, $this->order_name, $this->order_name, $this->pay_money, '', 'CashierOrderPayNotify', '', $this->order_id, $this->member_id);
return $this->success($res);
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 校验错误
* @return array
*/
public function checkError()
{
if (!empty($this->error)) {
$error_msg = $this->getError();
return $this->error(['error_code' => $this->error, 'error_msg' => $error_msg], $error_msg);
} else {
return $this->success();
}
}
/**
* 获取错误
* @return string
*/
protected function getError()
{
$error_list = [
'GOODS_STOCK_EMPTY' => '%s库存不足%s',
'ADDRESS_EMPTY' => '%s收货地址必须选择!%s',
'TRADE_TYPE_EMPTY' => '%s配送方式必须选择!%s',
'GOODS_LESS_MIN_NUM' => '%s商品数量不能小于最小购买量%s',
'GOODS_OUT_MAX_NUM' => '%s商品数量不能超出最大购买量%s',
'MOBILE_EMPTY' => '%s联系人手机号不能为空%s',
'NAME_EMPTY' => '%s联系人名称不能为空%s',
'YUEYUE_ERROR' => '%s %s',
];
$error_msg = $error_list[$this->error] ?? '';
return sprintf($error_msg, $this->error_printf[0] ?? '', $this->error_printf[1] ?? '');
}
/**
* 订单创建后续事件(收银台专用)
* @return true
*/
public function cashierOrderCreateAfter()
{
// $log_data = array(
// 'order_id' => $this->order_id,
// 'action' => 'create',
// 'site_id' => $this->site_id,
// 'member_id' => $this->member_id
// );
// (new OrderLog())->addLog($log_data);
// //执行自动关闭
// $this->addOrderCronClose(); //增加关闭订单自动事件
// //自动删除时间
// $this->addOrderCronDelete(); // 增加订单自动删除事件5分钟内未支付
Queue::push('addon\cashier\job\order\CashierOrderCreateAfter', ['create_data' => get_object_vars($this), 'order_object' => $this]);
return true;
}
/**
* 计算
* @return array
*/
public function calculate()
{
//初始化仓库门店
$this->initStore();
//初始化会员
$this->initMemberAccount();
//初始化站点信息
$this->initSiteData();
//计算产品项目
$this->getItemList();
$this->order_money = $this->real_goods_money;
$this->pay_money = $this->order_money;
$this->order_key = create_no();
$order_cache = get_object_vars($this);
$this->setOrderCache(get_object_vars($this), $this->order_key);
//库存转换
$goods_model = new \app\model\goods\Goods();
$order_cache['goods_list'] = $goods_model->goodsStockTransform($order_cache['goods_list'], $this->store_id, 'store');
return $order_cache;
}
/**
* 购买项列表
* @return true
* @throws Exception
*/
public function getItemList()
{
$type = $this->param['type'] ?? '';
$data_result = event('CashierCalculate', ['order_object' => $this], true);
if (empty($data_result)) {
$sku_array = $this->param['sku_array'] ?? [];
if (!$sku_array) throw new OrderException('缺少必要的商品参数!');
switch ($type) {
case 'goods':
$this->cashier_order_type = 'goods';
//处理产品数据
//消费分为产品和买单(暂)
$product_id_array = [];
$money_array = [];//买单
foreach ($sku_array as $v) {
$money = $v['money'] ?? 0;
$sku_id = $v['sku_id'] ?? 0;
$num = $v['num'] ?? 1;
if ($money > 0) {
$money_array[] = ['money' => $money, 'sku_id' => $sku_id, 'num' => $num];
} elseif ($sku_id > 0) {
$product_id_array[] = $v;
}
}
$this->toCalculate($product_id_array);
//无码商品
$this->moneyCalculate($money_array);
if (empty($this->goods_list)) throw new OrderException('缺少必填参数商品数据');
// $this->goods_list = array_reverse($this->goods_list);
break;
case 'card'://卡项
$this->cashier_order_type = 'card';
$this->cardCalculate();
break;
}
}
return true;
}
/**
* 产品计算(主要用于商品)计算
* @param $product_array
* @return true
*/
public function toCalculate($product_array)
{
if (!empty($product_array)) {
//查询商品
$this->getShopGoodsList($product_array);
//商品部分的计算
$this->goodsCalculate();
$this->order_money = moneyFormat($this->real_goods_money + $this->delivery_money);
$this->pay_money = $this->order_money;
}
return true;
}
/**
* 获取立即购买商品信息
* @param $sku_array
* @return true
*/
public function getShopGoodsList($sku_array)
{
$sku_ids = array_column($sku_array, 'sku_id');
$field = 'gs.site_id,gs.goods_id,gs.sku_id,gs.goods_name,gs.sku_name,gs.spec_name,gs.sku_image,g.goods_image,gs.price as sku_price,gs.sku_no,
g.is_virtual,g.min_buy,g.max_buy,g.unit,g.goods_spec_format,g.unit,gs.supplier_id,
g.goods_class,g.goods_class_name,g.is_unify_price,g.pricing_type,
gs.member_price, gs.is_consume_discount, gs.discount_config, gs.discount_method, g.category_id,
(IFNULL(sgs.sale_num, 0)+g.virtual_sale) as sale_num,
IFNULL(IF(g.is_unify_price = 1,gs.price,sgs.price), gs.price) as price';
$alias = 'gs';
$join = [
['goods g', 'g.goods_id = gs.goods_id', 'inner'],
[
'store_goods_sku sgs',
'sgs.sku_id = gs.sku_id and sgs.store_id = ' . $this->store_id,
'left'
]
];
//判断是统一库存还是独立库存
$store_model = new \app\model\store\Store();
$store_info = $store_model->getStoreInfo([['store_id', '=', $this->store_id]])['data'];
if ($store_info[ 'stock_type' ] == 'store') {
$field .= ',IFNULL(sgs.stock, 0) as stock,IFNULL(sgs.real_stock, 0) as real_stock';
$field .= ',IFNULL(sgs.cost_price, gs.cost_price) as cost_price';
}else{
$field .= ',gs.stock,gs.real_stock';
$field .= ',gs.cost_price';
}
$goods_condition = [
['gs.is_delete', '=', 0],
['sgs.status', '=', 1],
// [ 'gs.goods_state', '=', 1 ],
['gs.sku_id', 'in', $sku_ids],
['gs.site_id', '=', $this->site_id]
];
$temp_goods_list = model('goods_sku')->getList($goods_condition, $field, '', $alias, $join);
if (empty($temp_goods_list)) throw new OrderException('商品不存在!');
foreach ($temp_goods_list as $k => &$v) {
$v['sale_num'] = numberFormat($v['sale_num']);
$v['stock'] = numberFormat($v['stock']);
}
$column_goods_list = array_column($temp_goods_list, null, 'sku_id');
$order_name = '';
$goods_num = 0;
$goods_list = [];
//分配关联商品数据
unset($v);
foreach ($sku_array as $k => $v) {
$sku_id = $v['sku_id'];
$goods_info = $column_goods_list[$sku_id] ?? 0;
if (empty($goods_info)) throw new OrderException('存在无法购买的商品!');
$order_name = string_split($order_name, ',', $goods_info['goods_name']);
$item_num = $v['num'] ?? 1;
if (isset($v['price'])) {
$goods_info['price'] = $v['price'];
$goods_info['is_adjust_price'] = 1;
}
if ($goods_info['goods_class'] != GoodsDict::weigh) {
if ($item_num < 1) throw new OrderException('商品数量不能小于1');
} else {
if ($item_num < 0) throw new OrderException('称重重量不能小于0');
//只有称重商品会只传商品总价
if (isset($v['goods_money'])) {
$goods_info['goods_money'] = $v['goods_money'];
if ($v['goods_money'] > 0) {
$goods_info['price'] = round($v['goods_money'] / $item_num, 2);
} else {
$goods_info['price'] = 0;
}
$goods_info['is_adjust_price'] = 1;
}
}
$goods_info['card_item_id'] = $v['card_item_id'] ?? 0;
$goods_num += $item_num;
// $goods_info[ 'trade_type' ] = $goods_info['goods_class'];//业务类型
$goods_info['num'] = $item_num;
$goods_info['sku_image'] = explode(',', $goods_info['sku_image'])[0] ?? '';
$goods_info['goods_image'] = explode(',', $goods_info['goods_image'])[0] ?? '';
$goods_list[] = $goods_info;
}
$this->goods_list = $goods_list;
$this->order_name = $order_name;
$this->goods_num = $goods_num;
return true;
}
/**
* 商品计算
* @return true
*/
public function goodsCalculate()
{
//具备某个参数(控制是否是单品活动)
//计算订单总额 ,订单总优惠 ,
$goods_money = 0;
$real_goods_money = 0;
foreach ($this->goods_list as $k => $v) {
// 计算单价 可能情况 (折扣价 会员价)
$goods_item = $v;
$num = $goods_item['num'];//购买数量
//商品类主体中应该封装一个函数用于获取商品价格(可能还会有关联会员价 满减 折扣....)
$is_adjust_price = $v['is_adjust_price'] ?? 0;
if (!$is_adjust_price) {
//自定义价格的话,不再参与会员价
if ($v['is_unify_price'] == 1) {
$price = moneyFormat($v['sku_price']);
} else {
$price = moneyFormat($v['price']);
}
$v['price'] = $price;
$member_price_result = $this->getGoodsMemberPrice($v);
if ($member_price_result['code'] >= 0) {
$price = $member_price_result['data'];
$goods_item['is_member_price'] = true;
}
$goods_item['price'] = $price;
} else {
$price = $goods_item['price'];
}
//称重商品已经拥有了商品总价
$item_goods_money = $goods_item['goods_money'] ?? moneyFormat($price * $num);
$goods_item['goods_money'] = $item_goods_money;
$goods_item['site_id'] = $this->site_id;
// $min_buy = $goods_item[ 'min_buy' ];
// $max_buy = $goods_item[ 'max_buy' ];
// if ($min_buy > 0 && $min_buy > $num)
// $this->setError('GOODS_LESS_MIN_NUM');
//
// if ($max_buy > 0 && $max_buy < $num)
// $this->setError('GOODS_OUT_MAX_NUM');
$item_real_goods_money = $goods_item['goods_money'];
$goods_item['real_goods_money'] = $item_real_goods_money;
//卡项
$goods_item = $this->itemCardCalculate($goods_item);
if (empty($goods_item)) {
unset($this->goods_list[$k]);
continue;
} else {
$item_goods_money = $goods_item['goods_money'];
$item_real_goods_money = $goods_item['real_goods_money'];
}
$goods_money += $item_goods_money;
$real_goods_money += $item_real_goods_money;
$goods_item['real_goods_money'] = $item_real_goods_money;
$this->goods_list[$k] = $goods_item;
}
$this->goods_money = $goods_money;
$this->real_goods_money = $real_goods_money;
return true;
}
/**
* 商品卡项抵扣(抵扣会将商品单价视为0)
* @param $goods_item
* @return array
*/
public function itemCardCalculate($goods_item)
{
$card_item_id = $goods_item['card_item_id'] ?? 0;
$sku_id = $goods_item['sku_id'];
if ($card_item_id > 0) {
$num = $goods_item['num'];
$member_card_model = new MemberCard();
$card_item_params = [
'member_id' => $this->member_id,
'sku_id' => $sku_id,
'item_id' => $card_item_id
];
$item_card_result = $member_card_model->getUseCardNum($card_item_params);
if ($item_card_result['code'] < 0) {
return [];
}
$item_card_data = $item_card_result['data'];
$card_item_info = $item_card_data['card_item_info'];
$card_info = $item_card_data['card_info'];
$goods_item['card_item_info'] = $card_item_info;
$goods_item['card_info'] = $card_info;
$card_num = $item_card_data['card_num'];
$goods_item['card_num'] = $card_num;
if ($card_num > 0) {
if ($num > $card_num) {
$num = $card_num;
}
}
$goods_item['num'] = $num;
$price = $goods_item['price'];
$card_promotion_money = moneyFormat($price * $num);
$goods_money = moneyFormat($price * $num);
$goods_item['price'] = $price;
$goods_item['goods_money'] = $goods_money;
$real_goods_money = moneyFormat($goods_money - $card_promotion_money);
$real_goods_money = max($real_goods_money, 0);
$goods_item['card_promotion_money'] = $card_promotion_money;
$goods_item['real_goods_money'] = $real_goods_money;
}
return $goods_item;
}
/**
* 买单计算
* @param $money_array
* @return true
*/
public function moneyCalculate($money_array)
{
if (!empty($money_array)) {
$goods_image = 'public/uniapp/cashier/cashier-order-money.png';
foreach ($money_array as $k => $v) {
$num = $v['num'] ?? 1;
$item_price = $v['money'];
if ($item_price > 0) {
$sku_id = $v['sku_id'];
$item_goods_money = moneyFormat($item_price * $num);
$item_order_name = $item_goods_money . '元买单';
$sku_name = '无码商品';
$this->goods_list[] = [
'goods_id' => 0,
'sku_id' => $sku_id,
'price' => $item_price,
'num' => $num,
'goods_money' => $item_goods_money,
'goods_name' => $item_order_name,
'sku_name' => $sku_name,
'goods_image' => $goods_image,
'spec_name' => '',
'goods_class' => 'money',
'goods_class_name' => '无码商品',
'real_goods_money' => $item_goods_money
];
$this->goods_money += $item_goods_money;
$this->real_goods_money += $item_goods_money;
$this->order_name = string_split($this->order_name, ',', $item_order_name);
$this->goods_num += $num;
}
}
}
return true;
}
/**
* 卡项的计算
* @return true
*/
public function cardCalculate()
{
$sku_array = $this->param['sku_array'];
$sku_ids = array_column($sku_array, 'sku_id');
$sku_num_array = array_column($sku_array, 'num', 'sku_id');
// $sku_ids = $data['sku_ids'];//sku_id数组weight
$field = 'gs.site_id,gs.goods_id,gs.sku_id,gs.goods_name,gs.sku_name,gs.spec_name,gs.sku_image,g.goods_image,sgs.price,gs.price as sku_price,gs.sku_no,
g.is_virtual,g.unit,sgs.stock,g.min_buy,g.max_buy,g.goods_spec_format,g.unit,gs.supplier_id,
g.goods_class,g.goods_class_name,(sgs.sale_num + g.virtual_sale) as sale_num,g.is_unify_price,
gs.member_price, gs.is_consume_discount, gs.discount_config, gs.discount_method, g.category_id';
$alias = 'gs';
$join = [
['goods g', 'g.goods_id = gs.goods_id', 'inner'],
[
'store_goods_sku sgs',
'sgs.sku_id = gs.sku_id and sgs.store_id = ' . $this->store_id,
'left'
]
];
$goods_condition = [
['gs.is_delete', '=', 0],
['sgs.status', '=', 1],
['gs.sku_id', 'in', $sku_ids],
['gs.site_id', '=', $this->site_id],
];
$goods_list = model('goods_sku')->getList($goods_condition, $field, '', $alias, $join);
$order_name = '';
$goods_num = 0;
foreach ($goods_list as $k => $v) {
$sku_id = $v['sku_id'];
$order_name = string_split($order_name, ',', $v['goods_name']);
$item_num = $sku_num_array[$sku_id] ?? 1;
$goods_num += $item_num;
$goods_info = $v;
//自定义价格
if (isset($item_num['price'])) {
$goods_info['price'] = $item_num['price'];
$goods_info['is_adjust_price'] = 1;
}
$is_virtual = $is_virtual ?? $v['is_virtual'];
$goods_info['num'] = $item_num;
$goods_info['sale_num'] = numberFormat($goods_info['sale_num']);
$goods_info['stock'] = numberFormat($goods_info['stock']);
$goods_list[$k] = $goods_info;
}
$this->order_name = $order_name;
$this->goods_num = $goods_num;
//具备某个参数(控制是否是单品活动)
//计算订单总额 ,订单总优惠 ,
$goods_money = 0;
$real_goods_money = 0;
foreach ($goods_list as $k => $v) {
// 计算单价 可能情况 (折扣价 会员价)
$goods_item = $v;
//自定义价格的话,不再参与会员价
$is_adjust_price = $v['is_adjust_price'] ?? 0;
if (!$is_adjust_price) {
//商品类主体中应该封装一个函数用于获取商品价格(可能还会有关联会员价 满减 折扣....)
if ($v['is_unify_price'] == 1) {
$price = moneyFormat($v['sku_price']);
} else {
$price = moneyFormat($v['price']);
}
$v['price'] = $price;
$member_price_result = $this->getGoodsMemberPrice($v);
if ($member_price_result['code'] >= 0) {
$price = $member_price_result['data'];
$goods_item['is_member_price'] = true;
}
$goods_item['price'] = $price;
} else {
$price = $goods_item['price'];
}
$num = $goods_item['num'];//购买数量
$item_goods_money = moneyFormat($price * $num);//商品总额()
// $min_buy = $goods_item[ 'min_buy' ];
// $max_buy = $goods_item[ 'max_buy' ];
// if ($min_buy > 0 && $min_buy > $num) {
// $this->setError('GOODS_LESS_MIN_NUM');
// }
// if ($max_buy > 0 && $max_buy < $num) {
// $this->setError('GOODS_OUT_MAX_NUM');
// }
$goods_money += $item_goods_money;
$item_real_goods_money = $item_goods_money;
$real_goods_money += $item_real_goods_money;
$goods_item['goods_money'] = $item_goods_money;
$goods_item['real_goods_money'] = $item_real_goods_money;
$goods_item['sku_image'] = explode(',', $goods_item['sku_image'])[0] ?? '';
$goods_item['goods_image'] = explode(',', $goods_item['goods_image'])[0] ?? '';
$goods_list[$k] = $goods_item;
}
$this->goods_list = $goods_list;
$this->goods_money = moneyFormat($goods_money);
$this->real_goods_money = moneyFormat($real_goods_money);
return true;
}
/**
* 订单自动删除事件5分钟内未支付
* @return true
*/
public function addOrderCronDelete()
{
//计算订单自动关闭时间
$now_time = time();
$execute_time = $now_time + 5 * 60; // 5分钟自动删除时间
$cron_model = new Cron();
$cron_model->addCron(1, 0, '订单自动删除5分钟内未支付', 'CronOrderDelete', $execute_time, $this->order_id);
return true;
}
/**
* 设置错误
* @param $error_code
* @param array $error_printf
*/
protected function setError($error_code, $error_printf = [])
{
$this->error = $error_code;
$this->error_printf = $error_printf;
}
}

View File

@@ -0,0 +1,703 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use addon\cardservice\model\MemberCard;
use addon\coupon\model\MemberCoupon;
use addon\memberconsume\model\Consume;
use addon\store\model\settlement\OrderSettlement;
use app\dict\member_account\AccountDict;
use app\model\BaseModel;
use app\model\member\Member;
use app\model\member\MemberAccount;
use app\model\order\OrderCommon;
use app\model\order\OrderLog;
use app\model\order\OrderRefund;
use app\model\order\OrderStock;
use app\model\store\Stat;
use app\model\system\Pay;
use Exception;
use think\facade\Log;
use think\facade\Queue;
use addon\cashier\model\Push as PushModel;
/**
* 收银订单
*/
class CashierOrderPay extends BaseModel
{
/**
* 创建支付单据
* @param $params
* @return array
*/
public function createPay($params)
{
$out_trade_no = $params['out_trade_no'];
$cache = $this->getCache($out_trade_no)['data'] ?? [];
$promotion = $cache['promotion'] ?? [];
$member_id = $cache['member_id'] ?? 0;
$site_id = $params['site_id'];
$params['member_id'] = $member_id;
$params['promotion'] = $promotion;
$calculate_model = new CashierOrderCalculate();
$calculate_result = $calculate_model->calculate($params);
if ($calculate_result['code'] < 0) {
return $calculate_result;
}
$calculate = $calculate_result['data'];
$pay_model = new Pay();
$pay_info = $pay_model->getPayInfo($out_trade_no)['data'] ?? [];
if (empty($pay_info)) {
return $this->error('', '未获取到支付信息!');
}
$pay_money = $pay_info['pay_money'];
$surplus_money = $calculate['surplus_money'];
if ($pay_money != $surplus_money || $pay_info['pay_status'] == -1) {
$pay_result = $pay_model->rewritePay($out_trade_no, $surplus_money);
if ($pay_result['code'] < 0) return $pay_result;
$new_out_trade_no = $pay_result['data'];
//如果金额与上次一样的话就不需要生成新的支付
// 生成整体付费支付单据
// $pay_model->addPay($site_id, $out_trade_no, 'ONLINE_PAY', $calculate[ 'order_name' ], $calculate[ 'order_name' ], $surplus_money, '', 'CashierOrderPayNotify', '');
$this->setCache($new_out_trade_no, ['promotion' => $promotion, 'member_id' => $calculate['member_id'] ?? 0]);
model('order')->update(
['out_trade_no' => $new_out_trade_no],
[
['out_trade_no', '=', $out_trade_no]
]
);
$out_trade_no = $new_out_trade_no;
}
return $this->success($out_trade_no);
}
public function getCache($out_trade_no)
{
$pay_model = new Pay();
$pay_info = $pay_model->getPayInfo($out_trade_no)['data'] ?? [];
$cache = !empty($pay_info['pay_json']) ? json_decode($pay_info['pay_json'], true) : [];
// $cache = Cache::get('cashier_cache_' . $out_trade_no);
return $this->success($cache);
}
public function setCache($out_trade_no, $json)
{
$pay_model = new Pay();
$data = [
'pay_json' => json_encode($json)
];
$condition = [
['out_trade_no', '=', $out_trade_no]
];
$pay_model->edit($data, $condition);
//写入单据表
// Cache::set('cashier_cache_' . $out_trade_no, $json);
return $this->success();
}
/**
* 去支付
* @param $params
* @return array
*/
public function doPay($params)
{
$out_trade_no = $params['out_trade_no'];
$cache = $this->getCache($out_trade_no)['data'] ?? [];
$promotion = $cache['promotion'] ?? [];
$member_id = $cache['member_id'] ?? 0;
$condition = [
['out_trade_no', '=', $out_trade_no]
];
$info = model('order')->getInfo($condition);
$pay_type = $params['pay_type'];
$calculate_params = [
'site_id' => $info['site_id'],//站点id
'out_trade_no' => $out_trade_no,
'store_id' => $info['store_id'],
'online_type' => $params['online_type'] ?? $pay_type,
'pay_type' => $pay_type,
'member_id' => $member_id,
];
if (!empty($promotion)) {
$calculate_params['promotion'] = $promotion;
}
return $this->confirm($calculate_params);
}
/**
* 确认支付,生成订单
* @param $params
* @return array
*/
public function confirm($params)
{
try {
$calculate_model = new CashierOrderCalculate();
$result = $calculate_model->calculate($params);
if ($result['code'] < 0)
return $result;
$calculate = $result['data'];
$is_bind_member = $calculate['is_bind_member'] ?? 0;//是否要绑定会员
if ($is_bind_member > 0) {
//订单绑定会员,修改订单的价格商品金额
$this->bingMember($calculate, $calculate['member_id']);
}
$surplus_money = $calculate['surplus_money'];
if ($surplus_money <= 0) {
if(isset($calculate['is_use_balance']) && $calculate['is_use_balance'] == 1){
$calculate['pay_type'] = 'BALANCE';
}
$result = $this->orderPay($calculate);
if ($result['code'] < 0)
return $result;
} else {
return $this->error([], '当前收银订单未支付!');
}
return $this->success();
} catch ( Exception $e ) {
return $this->error('', $e->getMessage());
}
}
/**
* 绑定会员
* @param $cashier_order_info
* @param $member_id
* @return array
*/
public function bingMember($cashier_order_info, $member_id)
{
$site_id = $cashier_order_info['site_id'];
//重新计算订单
$order_id = $cashier_order_info['order_id'];
$goods_list = $cashier_order_info['goods_list'];
foreach ($goods_list as $k => $v) {
$item_order_goods_id = $v['order_goods_id'];
$price = $v['price'];
$item_goods_money = $v['goods_money'];
$item_real_goods_money = $v['real_goods_money'];
model('order_goods')->update(
[
'price' => $price,
'goods_money' => $item_goods_money,
'real_goods_money' => $item_real_goods_money,
'member_id' => $member_id
],
[
['order_goods_id', '=', $item_order_goods_id],
['site_id', '=', $site_id]
]
);
}
$goods_money = $cashier_order_info['goods_money'];
$real_goods_money = $cashier_order_info['real_goods_money'];
$order_money = $cashier_order_info['order_money'];
$pay_money = $cashier_order_info['pay_money'];
model('order')->update(
[
'goods_money' => $goods_money,
'real_goods_money' => $real_goods_money,
'order_money' => $order_money,
'pay_money' => $pay_money,
'member_id' => $member_id
],
[
['order_id', '=', $order_id],
['site_id', '=', $site_id]
]
);
return $this->success();
}
/**
* 订单线上支付
* @param $calculate
* @return array
*/
public function orderPay($calculate)
{
$out_trade_no = $calculate['out_trade_no'];
$cashier_condition = [
['out_trade_no', '=', $out_trade_no],
];
$cashier_order_info = model('order')->getInfo($cashier_condition, '*');
if ($cashier_order_info['order_status'] != 0) return $this->error([], '订单未处于待支付状态!');
model('order')->startTrans();
try {
$cashier_order_info['goods_num'] = numberFormat($cashier_order_info['goods_num']);
$pay_type = empty($calculate['pay_type']) ? 'ONLINE_PAY' : $calculate['pay_type'];
$order_common_model = new OrderCommon();
$pat_type_list = $order_common_model->getPayType(['order_type' => $cashier_order_info['order_type']]);
$pay_model = new Pay();
$pay_model->edit(['pay_type' => $pay_type, 'pay_time' => time(), 'pay_status' => 2, 'pay_money' => $calculate['pay_money']], [['out_trade_no', '=', $out_trade_no]]);
$cashier_order_type = $cashier_order_info['cashier_order_type'];
switch ($cashier_order_type) {
case 'goods':
$is_enable_refund = 1;
break;
case 'recharge':
$is_enable_refund = 0;
break;
case 'card':
$is_enable_refund = 1;
break;
}
$data = [
'pay_money' => $calculate['pay_money'],
'pay_type' => $pay_type,
'pay_type_name' => $pat_type_list[$pay_type] ?? '',
'pay_status' => 1,
'pay_time' => time(),
'reduction' => $calculate['reduction'] ?? 0,
'round_money' => $calculate['round_money'],
'order_money' => $calculate['order_money'],
'promotion_money' => $calculate['promotion_money'] ?? 0,
'balance_money' => $calculate['total_balance'],//总余额 todo 暂时先不区分可提现和不可提现余额
'coupon_id' => $calculate['coupon_id'],
'coupon_money' => $calculate['coupon_money'] ?? 0,
'is_enable_refund' => $is_enable_refund,
'point_money' => $calculate['point_money'] ?? 0,
'point' => $calculate['point'] ?? 0
];
$member_id = $params['member_id'] ?? 0;
if ($member_id > 0) {
$data['member_id'] = $member_id;
}
$out_trade_no = $calculate['out_trade_no'];
$condition = [
['out_trade_no', '=', $out_trade_no],
];
model('order')->update($data, $condition);
$goods_list = $calculate['goods_list'];
foreach ($goods_list as $v) {
model('order_goods')->update(
[
'real_goods_money' => $v['real_goods_money'],
'coupon_money' => $v['coupon_money']
],
[
['order_goods_id', '=', $v['order_goods_id']]
]
);
}
//扣除抵扣项
$offset_result = $this->deductOffset($calculate);
if ($offset_result['code'] < 0) {
model('order')->rollback();
return $offset_result;
}
// 用户线上支付
if (in_array($pay_type, ['wechatpay', 'alipay'])) {
$log_data = [
'order_id' => $cashier_order_info['order_id'],
'action' => 'pay',
'site_id' => $cashier_order_info['site_id'],
'member_id' => $cashier_order_info['member_id'],
];
} else {
// 收银员收款
$log_data = [
'order_id' => $cashier_order_info['order_id'],
'action' => 'pay',
'site_id' => $cashier_order_info['site_id'],
'member_id' => $cashier_order_info['member_id'],
'operater' => [
'uid' => $cashier_order_info['cashier_operator_id']
]
];
}
(new OrderLog())->addLog($log_data);
$cashier_order_model = new CashierOrder();
$result = $cashier_order_model->complete(array_merge($cashier_order_info, [
'pay_type' => $pay_type,
'pay_type_name' => $pat_type_list[$pay_type] ?? ''
]));
if($result['code'] < 0){
model('order')->rollback();
return $result;
}
model('order')->commit();
Queue::push('addon\cashier\job\order\CashierOrderPayAfter', $cashier_order_info);
return $this->success();
} catch ( Exception $e ) {
model('order')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 抵扣扣除
* @param $calculate_data
* @return array
*/
public function deductOffset($calculate_data)
{
//使用优惠券
$coupon_result = $this->useCoupon($calculate_data);
if ($coupon_result['code'] < 0) {
return $coupon_result;
}
//扣除积分
$point_result = $this->deductPoint($calculate_data);
if ($point_result['code'] < 0) {
return $point_result;
}
//抵扣余额
$balance_result = $this->deductBalance($calculate_data);
if ($balance_result['code'] < 0) {
return $balance_result;
}
return $this->success();
}
public function useCoupon($calculate_data)
{
$coupon_id = $calculate_data['coupon_id'] ?? 0;
//只有开单和卡项可以用优惠券
$cashier_order_type = $calculate_data['cashier_order_type'];
if (in_array($cashier_order_type, ['goods', 'card'])) {
if (!empty($coupon_id)) {
$order_id = $calculate_data['order_id'];
$member_coupon_model = new MemberCoupon();
//扣除优惠券
$result = $member_coupon_model->useMemberCoupon($coupon_id, $calculate_data['member_id'], $order_id);
if ($result['code'] < 0) {
return $result;
}
}
}
return $this->success();
}
/**
* 扣除积分
* @param $calculate_data
* @return array
*/
public function deductPoint($calculate_data)
{
$member_id = $calculate_data['member_id'];
$site_id = $calculate_data['site_id'];
$point = $calculate_data['point'] ?? 0;
$order_id = $calculate_data['order_id'] ?? 0;
$point_money = $calculate_data['point_money'] ?? 0;
$order_type = $calculate_data['cashier_order_type'];
if (in_array($order_type, ['goods', 'card'])) {
if ($point > 0) {
$is_use_point = $calculate_data['is_use_point'] ?? 0;
if ($is_use_point > 0) {
$from_type = 'order';
$relate_tag = '积分抵扣';
$remark = '收银订单积分抵扣,扣除积分:' . $point;
$member_account_model = new MemberAccount();
$result = $member_account_model->addMemberAccount($site_id, $member_id, AccountDict::point, -$point, $from_type, $relate_tag, $remark, $order_id);
if ($result['code'] < 0) {
return $result;
}
}
}
}
return $this->success();
}
/**
* 扣除余额
* @param $calculate_data
* @return array
*/
public function deductBalance($calculate_data)
{
$member_id = $calculate_data['member_id'];
$site_id = $calculate_data['site_id'];
$cashier_order_type = $calculate_data['cashier_order_type'];
$order_id = $calculate_data['order_id'] ?? 0;
$is_use_balance = $calculate_data['is_use_balance'] ?? 0;
if (in_array($cashier_order_type, ['goods', 'card'])) {
//判断是否已经扣除过余额
if ($is_use_balance > 0) {
$balance_money = $calculate_data['total_balance'] ?? 0;
if ($balance_money > 0) {
$member_model = new Member();
$member_account_model = new MemberAccount();
$member_condition = [
['member_id', '=', $member_id],
['site_id', '=', $site_id]
];
$member_info = $member_model->getMemberInfo($member_condition)['data'] ?? [];
$member_balance = $member_info['balance'];//储值余额
$member_balance_money = $member_info['balance_money'];//现金余额
$order_data = [];
//优先扣除可不提现余额
$surplus = $balance_money;
$temp_balance = $member_balance;
if ($member_balance > $surplus) {
$temp_balance = $surplus;
}
$surplus -= $temp_balance;
$from_type = 'order';
$relate_tag = '余额抵扣';
$remark = '订单名称:' . $calculate_data['order_name'] . ',订单编号:' . $calculate_data['out_trade_no'] ?? ',订单金额:' . $calculate_data['order_money'] . ',订单余额抵扣,扣除储值余额:' . $temp_balance;
$remark = '收银订单余额抵扣';
if ($temp_balance > 0) {
$result = $member_account_model->addMemberAccount($site_id, $member_id, AccountDict::balance, -$temp_balance, $from_type, $relate_tag, $remark, $order_id);
if ($result['code'] < 0) {
return $result;
}
$order_data['balance'] = $temp_balance;
}
//扣除现金余额
$temp_balance = $member_balance_money;
if ($member_balance_money > $surplus) {
$temp_balance = $surplus;
}
$from_type = 'order';
$relate_tag = '余额抵扣';
$remark = '订单名称:' . $calculate_data['order_name'] . ',订单编号:' . $calculate_data['out_trade_no'] . ',订单金额:' . $calculate_data['order_money'] . ',订单余额抵扣,扣除储值余额:' . $temp_balance;
$remark = '收银订单余额抵扣';
if ($temp_balance > 0) {
$result = $member_account_model->addMemberAccount($site_id, $member_id, AccountDict::balance_money, -$temp_balance, $from_type, $relate_tag, $remark, $order_id);
if ($result['code'] < 0) {
return $result;
}
$order_data['balance_money'] = $temp_balance;
}
if (!empty($order_data)) {
$order_condition = [
['order_id', '=', $order_id]
];
model('order')->update($order_data, $order_condition);
}
}
}
}
return $this->success();
}
/**
* 订单创建后续
* @param $cashier_order_info
*/
public function cashierOrderPayAfter($cashier_order_info)
{
$order_id = $cashier_order_info['order_id'];
//模拟订单支付后操作钩子
if (addon_is_exit('memberconsume')) {
$consume_model = new Consume();
$consume_model->memberConsume(['out_trade_no' => $cashier_order_info['out_trade_no'], 'status' => 'pay'], $order_id);
}
//模拟订单完成后操作钩子
if (addon_is_exit('memberconsume')) {
$consume_model = new Consume();
$consume_model->memberConsume(['out_trade_no' => $cashier_order_info['out_trade_no'], 'status' => 'complete'], $order_id);
}
//收银台的订单因部分不可抗力不能进行公共的订单完成事件,所以主动调用门店订单分成结算
if (addon_is_exit('store')) {
(new OrderSettlement())->orderSettlementAccount(['order_id' => $order_id]);
}
$this->create($cashier_order_info);
//自动库存转换
if(in_array($cashier_order_info['cashier_order_type'], ['goods'])){
$order_goods_list = model('order_goods')->getList([['order_id', '=', $cashier_order_info['order_id']]], 'order_goods_id,sku_id,store_id');
}
//订单支付后消息推送
(new PushModel())->orderPay($cashier_order_info);
return true;
}
/**
* 订单创建
* @param $params
* @return array
*/
public function create($params)
{
Log::write('收银订单创建' . json_encode($params));
$out_trade_no = $params['out_trade_no'];
$cashier_condition = [
['out_trade_no', '=', $out_trade_no],
];
$cashier_order_info = model('order')->getInfo($cashier_condition, '*');
model('order')->startTrans();
try {
$cashier_order_info['goods_num'] = numberFormat($cashier_order_info['goods_num']);
$cashier_order_id = $cashier_order_info['order_id'];
$store_id = $cashier_order_info['store_id'];
//拆分订单
$order_goods_condition = [
['order_id', '=', $cashier_order_id],
];
$order_goods_list = model('order_goods')->getList($order_goods_condition);
foreach ($order_goods_list as $k => $v) {
$order_goods_list[$k]['num'] = numberFormat($v['num']);
}
$site_id = $cashier_order_info['site_id'];
$cashier_order_data = $cashier_order_info;
$cashier_order_data['goods_list'] = $order_goods_list;
$member_id = $cashier_order_info['member_id'];
$cashier_order_type = $cashier_order_info['cashier_order_type'];
//根据商品类型合并订单组
$cashier_order_refund_model = new CashierOrderRefund();
$order_refund_model = new OrderRefund();
$store_stat = new Stat();
$stat_data = [];
switch ($cashier_order_type) {
case 'goods':
$cashier_trade_model = new CashierTrade();
$member_card_model = new MemberCard();
$item_list = [];
foreach ($order_goods_list as $k => $v) {
$card_item_id = $v['card_item_id'];
if ($card_item_id > 0) {
$num = $v['num'];
$order_goods_id = $v['order_goods_id'];
$type = 'order';
//订单使用此卡
$item_params = [
'item_id' => $card_item_id,
'num' => $num,
'type' => $type,
'relation_id' => $order_goods_id,
'store_id' => $store_id
];
$item_list[] = $item_params;
}
}
if (!empty($item_list)) {
$user_card_result = $member_card_model->cardUse($item_list);
if ($user_card_result['code'] < 0) {
Log::write('使用此卡错误' . json_encode($user_card_result));
$cashier_order_data['refund_reason'] = $user_card_result['message'];
$refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款');
//todo 理论上退款转账不会导致退失败
if ($refund_result['code'] < 0) {
Log::write('收银订单主动退款失败(卡项):' . json_encode($refund_result));
model('order')->rollback();
return $refund_result;
}
model('order')->commit();
return $user_card_result;
}
}
foreach ($order_goods_list as $k => $v) {
$cashier_result = $cashier_trade_model->toSend($v, $cashier_order_info);
if ($cashier_result['code'] < 0) {
$cashier_order_data['refund_reason'] = $cashier_result['message'];
Log::write('收银订单退款失败:' . json_encode($cashier_result));
$refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款');
//todo 理论上退款转账不会导致退失败
if ($refund_result['code'] < 0) {
Log::write('收银订单主动退款失败:' . json_encode($refund_result));
model('order')->rollback();
return $refund_result;
}
model('order')->commit();
return $cashier_result;
}
}
// 统计数据
$stat_data['billing_count'] = 1;
$stat_data['billing_money'] = $cashier_order_info['pay_money'];
break;
case 'recharge':
// 统计数据
$stat_data['recharge_count'] = 1;
$stat_data['recharge_money'] = $cashier_order_info['pay_money'];
break;
case 'card':
$cashier_trade_model = new CashierTrade();
foreach ($order_goods_list as $k => $v) {
$cashier_result = $cashier_trade_model->toSend($v, $cashier_order_info);
if ($cashier_result['code'] < 0) {
// $refund_res = $cashier_order_refund_model->orderRefund(['order_id' => $order_id]);
// model('order')->commit();
// return $refund_res;
$refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款');
//todo 理论上退款转账不会导致退失败
if ($refund_result['code'] < 0) {
Log::write('收银订单主动退款失败CARD' . json_encode($refund_result));
model('order')->rollback();
return $refund_result;
}
model('order')->commit();
return $cashier_result;
}
}
// 统计数据
$stat_data['buycard_count'] = 1;
$stat_data['buycard_money'] = $cashier_order_info['pay_money'];
break;
}
$order_stock_model = new OrderStock();
$stock_params = [
'store_id' => $store_id,
'goods_sku_list' => $order_goods_list,
'site_id' => $cashier_order_info['site_id'],
'user_info' => [
'uid' => $cashier_order_info['cashier_operator_id'],
'username' => $cashier_order_info['cashier_operator_name'],
],
'is_out_stock' => 1
];
$result = $order_stock_model->decOrderStock($stock_params);
if ($result['code'] < 0) {
// $refund_result = $order_refund_model->activeRefund($cashier_order_id, '', '订单退款');
// //todo 理论上退款转账不会导致退失败
// if ($refund_result['code'] < 0) {
// Log::write('收银订单扣除库存失败CARD' . json_encode($refund_result));
// model('order')->rollback();
// return $result;
// }
// model('order')->commit();
// return $result;
}
// 统计下单人数
if ($member_id) {
$count = model('order')->getCount([['member_id', '=', $member_id], ['pay_status', '=', 1], ['store_id', '=', $store_id]]);
if ($count == 1) $stat_data['order_member_count'] = 1;
if ($cashier_order_info['balance_money']) $stat_data['balance_money'] = $cashier_order_info['balance_money'];
}
// 添加统计数据
if (!empty($stat_data)) {
$stat_data['site_id'] = $site_id;
$stat_data['store_id'] = $store_id;
$store_stat->addStoreStat($stat_data);
}
model('order')->commit();
return $this->success();
} catch ( Exception $e ) {
model('order')->rollback();
Log::write('收银单支付完成错误:' . $e->getMessage() . $e->getFile() . $e->getLine());
return $this->error('', $e->getMessage());
}
}
}

View File

@@ -0,0 +1,124 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use app\dict\order_refund\OrderRefundDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
use app\model\order\OrderRefund;
use Exception;
/**
* 收银订单
*
* @author Administrator
*
*/
class CashierOrderRefund extends BaseModel
{
public function getRefundApplyData($params)
{
$store_id = $params['store_id'];
$site_id = $params['site_id'];
$order_id = $params['order_id'];
$order_refund_model = new OrderRefund();
$refund_array = empty($params['refund_array']) ? [] : json_decode($params['refund_array'], true);
if (empty($refund_array))
return $this->error([], '请选择要退款的订单项!');
$refund_list = [];
foreach ($refund_array as $k => $refund_v) {
$item = $order_refund_model->getOrderGoodsRefundInfo($refund_v, $site_id, $store_id)['data'] ?? [];
if (!empty($item)) {
$order_info = $item['order_info'];
$refund_list[] = $item;
}
}
if (empty($refund_list))
return $this->error([], '请选择要退款的订单项!');
$refund_data = [];
$refund_transfer_type = $this->getRefundTransferType($order_info);
$refund_data['refund_transfer_type'] = $refund_transfer_type;
$refund_data['refund_list'] = $refund_list;
return $this->success($refund_data);
}
/**
* 退款转账方式
* @param array $params
* @return array
*/
public function getRefundTransferType($params = [])
{
$list = [
'2' => ['name' => '线下退款', 'desc' => '与客户协商一致, 在线下以现金、微信或支付宝等形式退款给客户'],
];
$list['1'] = ['name' => '原路退款', 'desc' => '与客户协商一致,原路退款给客户'];
return $list;
}
public function refund($params)
{
//参数
$order_id = $params['order_id'];
$store_id = $params['store_id'];
$site_id = $params['site_id'];
$refund_transfer_type = $params['refund_transfer_type'];
$refund_array = $params['refund_array'];
$refund_remark = $params['refund_remark'];
//订单基本检测
$order_common_model = new OrderCommon();
$order_condition = [
['order_id', '=', $order_id],
['site_id', '=', $site_id],
['store_id', '=', $store_id],
];
$order_info = $order_common_model->getOrderInfo($order_condition)['data'] ?? [];
if (empty($order_info)){
return $this->error([], '订单不存在!');
}
if($order_info['is_settlement'] == 1 && $refund_transfer_type == OrderRefundDict::back){
return $this->error([], '订单已结算,不支持原路退款!');
}
model('order_goods')->startTrans();
try {
$order_refund_model = new OrderRefund();
foreach ($refund_array as $order_goods_id => $refund_money) {
$res = $order_refund_model->shopActiveRefund([
'order_goods_id' => $order_goods_id,
'shop_active_refund_money' => $refund_money['refund_money'],
'shop_active_refund_remark' => $refund_remark,
'shop_active_refund_money_type' => $refund_transfer_type,
'user_info' => $params['operator'],
'refund_status' => $refund_money['refund_status'],
'is_refund_stock'=>$refund_money['is_refund_stock'] ?? 1, //新增是否返还库存
'refund_stock_num'=>$refund_money['refund_stock_num'] ?? 0 //返还库存数量
]);
if($res['code'] < 0){
model('order_goods')->rollback();
return $res;
}
}
model('order_goods')->commit();
return $this->success();
} catch ( Exception $e ) {
model('order_goods')->rollback();
return $this->error('', $e->getMessage());
}
}
}

View File

@@ -0,0 +1,128 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use addon\cardservice\model\MemberCard;
use app\dict\goods\GoodsDict;
use app\dict\order\OrderGoodsDict;
use app\model\BaseModel;
use app\model\goods\Goods;
/**
* 收银业务操作
*
* @author Administrator
*
*/
class CashierTrade extends BaseModel
{
public function toSend($item, $order_info)
{
$action_type = $item['goods_class'];//操作类型
if (in_array($action_type, [GoodsDict::real, GoodsDict::service, GoodsDict::card, GoodsDict::weigh])) {
switch ($action_type) {
case GoodsDict::card://卡项
$result = $this->toCard($item, $order_info);
break;
case GoodsDict::real://实物
$result = $this->toGoods($item, $order_info);
break;
case GoodsDict::weigh://称重商品
$result = $this->toGoods($item, $order_info);
break;
case GoodsDict::service://服务
$result = $this->toService($item, $order_info);
break;
}
if (!empty($result)) {
if ($result['code'] < 0) {
return $result;
}
}
//累加销量
$goods_model = new Goods();
$goods_model->incGoodsSaleNum($item['sku_id'], $item['num'], $item['store_id'] ?? 0);
}
$order_goods_data = [
//配送状态
'delivery_status' => OrderGoodsDict::delivery_finish,
'delivery_status_name' => OrderGoodsDict::getDeliveryStatus(OrderGoodsDict::delivery_finish),
];
model('order_goods')->update($order_goods_data, [['order_goods_id', '=', $item['order_goods_id']]]);
return $this->success();
}
/**
* 生成卡项
* @param $params
* @param $order_info
* @return array
*/
public function toCard($params, $order_info)
{
$member_card_model = new MemberCard();
$num = $params['num'];
// $i = 0;
// while ($i < $num) {
$result = $member_card_model->create($params);
if ($result['code'] < 0) {
return $result;
}
// $i++;
// }
return $this->success();
}
/**
* 实物处理
* @param $params
* @param $order_info
*/
public function toGoods($params, $order_info)
{
// $store_id = $order_info['store_id'];
//
// //扣除库存
// $order_stock_model = new OrderStock();
// $stock_params = array(
// 'store_id' => $store_id,
// 'sku_id' => $params['sku_id'],
// 'goods_id' => $params['goods_id'],
// 'stock' => $params['num'],
// 'goods_class' => $params['goods_class'],
// 'site_id' => $order_info['site_id'],
// 'user_info' => [
// 'uid' => $order_info['cashier_operator_id'],
// 'username' => $order_info['cashier_operator_name'],
// ]
// );
// $result = $order_stock_model->decOrderStock($stock_params);
// return $result;
}
/**
* 生成预约服务
* @param $params
* @param $order_info
* @return array
*/
public function toService($params, $order_info)
{
$store_id = $order_info['store_id'];
return $this->success();
}
}

View File

@@ -0,0 +1,236 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 上海牛之云网络科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\cashier\model\order;
use app\model\BaseModel;
use Exception;
use think\facade\Log;
/**
* 挂单
*
* @author Administrator
*
*/
class PendOrder extends BaseModel
{
/**
* 添加
* @param $param
* @return array
*/
public function add($param)
{
$res = $this->handleData($param);
if ($res['code'] != 0) return $res;
$param = $res['data'];
model('cashier_pendorder')->startTrans();
try {
$order_id = model('cashier_pendorder')->add([
'site_id' => $param['site_id'],
'store_id' => $param['store_id'],
'member_id' => $param['member_id'] ?? 0,
'create_time' => time(),
'remark' => $param['remark'] ?? '',
'order_money' => $param['order_money'],
'discount_money' => $param['discount_money'] ?? 0.00,
'discount_data' => $param['discount'] ?? ''
]);
$order_goods = [];
foreach ($param['goods'] as $item) {
$order_goods[] = [
'order_id' => $order_id,
'site_id' => $param['site_id'],
'store_id' => $param['store_id'],
'goods_id' => $item['goods_id'],
'sku_id' => $item['sku_id'],
'num' => $item['num'],
'price' => $item['price'],
'goods_class' => $item['goods_class']
];
}
model('cashier_pendorder_goods')->addList($order_goods);
model('cashier_pendorder')->commit();
return $this->success($order_id);
} catch ( Exception $e ) {
model('cashier_pendorder')->rollback();
Log::write('挂单出现错误,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
return $this->error();
}
}
private function handleData($param)
{
$store_info = model('store')->getInfo([['site_id', '=', $param['site_id']], ['store_id', '=', $param['store_id']]], 'store_id');
if (empty($store_info)) return $this->error('', '门店不存在!');
$param['order_money'] = 0;
$join = [
['goods g', 'sku.goods_id=g.goods_id', 'inner'],
['store_goods_sku sgs', 'sku.sku_id=sgs.sku_id and sgs.store_id=' . $param['store_id'], 'inner'],
];
foreach ($param['goods'] as $k => $item) {
if (isset($item['money']) && $item['money'] > 0) {
$param['goods'][$k]['price'] = round($item['money'], 2);
$param['goods'][$k]['goods_class'] = 'money';
} else {
$sku_info = model('goods_sku')->getInfo([['sku.sku_id', '=', $item['sku_id']]], 'sku.goods_class,IF(g.is_unify_price = 1,sku.price,sgs.price) as price', 'sku', $join);
if (empty($sku_info)) return $this->error('', '不存在的商品!');
$param['goods'][$k]['price'] = !empty($item['price']) ? $item['price'] : $sku_info['price'];
$param['goods'][$k]['goods_class'] = $sku_info['goods_class'];
}
$param['order_money'] += ($param['goods'][$k]['price'] * $item['num']);
}
return $this->success($param);
}
/**
* 编辑
* @param $param
* @return array
*/
public function edit($param)
{
$res = $this->handleData($param);
if ($res['code'] != 0) return $res;
$param = $res['data'];
model('cashier_pendorder')->startTrans();
try {
$condition = [
['site_id', '=', $param['site_id']],
['store_id', '=', $param['store_id']],
['order_id', '=', $param['order_id']]
];
model('cashier_pendorder')->update([
'member_id' => $param['member_id'] ?? 0,
'remark' => $param['remark'] ?? '',
'order_money' => $param['order_money'],
'discount_money' => $param['discount_money'] ?? 0.00,
'discount_data' => $param['discount'] ?? ''
], $condition);
model('cashier_pendorder_goods')->delete($condition);
$order_goods = [];
foreach ($param['goods'] as $item) {
$order_goods[] = [
'order_id' => $param['order_id'],
'store_id' => $param['store_id'],
'site_id' => $param['site_id'],
'goods_id' => $item['goods_id'],
'sku_id' => $item['sku_id'],
'num' => $item['num'],
'price' => $item['price'],
'goods_class' => $item['goods_class']
];
}
model('cashier_pendorder_goods')->addList($order_goods);
model('cashier_pendorder')->commit();
return $this->success($param['order_id']);
} catch ( Exception $e ) {
model('cashier_pendorder')->rollback();
Log::write('挂单出现错误,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
return $this->error();
}
}
/**
* 挂单表编辑
* @param $data
* @param $where
* @return array
*/
public function update($data, $where)
{
$res = model('cashier_pendorder')->update($data, $where);
if ($res) {
return $this->success($res);
} else {
return $this->error();
}
}
/**
* 删除订单
* @param $param
* @return array
*/
public function delete($param)
{
model('cashier_pendorder')->startTrans();
try {
$res = model('cashier_pendorder')->delete([
['site_id', '=', $param['site_id']],
['store_id', '=', $param['store_id']],
['order_id', '=', $param['order_id']]
]);
if (!$res) {
model('cashier_pendorder')->rollback();
return $this->error();
}
model('cashier_pendorder_goods')->delete([['order_id', '=', $param['order_id']]]);
model('cashier_pendorder')->commit();
return $this->success();
} catch ( Exception $e ) {
model('cashier_pendorder')->rollback();
Log::write('挂单删除出现错误,错误原因:' . $e->getMessage() . $e->getFile() . $e->getLine());
return $this->error();
}
}
/**
* 查询挂单分页列表
* @param array $condition
* @param bool $field
* @param string $order
* @param int $page
* @param int $list_rows
* @param string $alias
* @param array $join
* @return array
*/
public function getOrderPageList($condition = [], $field = true, $order = '', $page = 1, $list_rows = PAGE_LIST_ROWS, $alias = 'a', $join = [])
{
$data = model('cashier_pendorder')->pageList($condition, $field, $order, $page, $list_rows, $alias, $join);
return $this->success($data);
}
/**
* 查询挂单商品项列表
* @param array $condition
* @param bool $field
* @param string $order
* @param string $alias
* @param array $join
* @return array
*/
public function getOrderGoodsList($condition = [], $field = true, $order = '', $alias = 'a', $join = [])
{
$list = model('cashier_pendorder_goods')->getList($condition, $field, $order, $alias, $join);
foreach ($list as $k => $v) {
if (isset($v['num'])) {
$list[$k]['num'] = numberFormat($v['num']);
}
}
return $this->success($list);
}
}