初始上传

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

141
addon/store/model/Category.php Executable file
View File

@@ -0,0 +1,141 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use think\facade\Cache;
use app\model\BaseModel;
use app\model\system\Config;
/**
* 门店分类
*/
class Category extends BaseModel
{
/**
* 门店分类设置
* @param $data
* @param $site_id
* @return array
*/
public function setCategoryConfig($data, $site_id)
{
return ( new Config() )->setConfig($data, '门店分类设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STORE_CATEGORY' ] ]);
}
/**
* 获取门店分类设置
* @param $site_id
* @return array
*/
public function getCategoryConfig($site_id)
{
$data = ( new Config() )->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'STORE_CATEGORY' ] ]);
if (empty($data[ 'data' ][ 'value' ])) {
$data[ 'data' ][ 'value' ] = [
'status' => 0
];
}
return $data;
}
/**
* 添加门店分类
*
* @param array $data
*/
public function addStoreCategory($data)
{
$res = model('store_category')->add($data);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 修改门店分类
*
* @param array $data
* @param array $condition
*/
public function editStoreCategory($data, $condition)
{
$check_condition = array_column($condition, 2, 0);
$category_id = $check_condition['category_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($category_id)) return $this->error('', 'category_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_category')->update($data, $condition);
if (isset($data[ 'category_name' ]) && !empty($data[ 'category_name' ])) model('store')->update([ 'category_name' => $data[ 'category_name' ] ], [ [ 'category_id', '=', $category_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 删除门店分类
* @param array $condition
*/
public function deleteStoreCategory($condition)
{
$check_condition = array_column($condition, 2, 0);
$category_id = isset($check_condition[ 'category_id' ]) ? array_filter(explode(',', $check_condition[ 'category_id' ])) : [];
$site_id = $check_condition['site_id'] ?? 0;
if (empty($category_id)) return $this->error('', 'category_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_category')->delete($condition);
model('store')->update([ 'category_name' => '', 'category_id' => '' ], [ [ 'category_id', 'in', $category_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag('store_category')->clear();
return $this->success($res);
}
/**
* 获取门店分类信息
*
* @param array $condition
* @param string $field
*/
public function getStoreCategoryInfo($condition = [], $field = '*')
{
$info = model('store_category')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取门店分类列表
*
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreCategoryList($condition = [], $field = '*', $order = 'sort asc, category_id asc', $limit = null)
{
$list = model('store_category')->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
*/
public function getStoreCategoryPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'category_id desc', $field = '*')
{
$list = model('store_category')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

150
addon/store/model/Config.php Executable file
View File

@@ -0,0 +1,150 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\order\OrderCommon as OrderCommonModel;
use app\model\system\Config as ConfigModel;
use app\model\BaseModel;
use Carbon\Carbon;
use app\model\system\Cron;
/**
* 店铺设置信息
*/
class Config extends BaseModel
{
/**
* 门店结算相关设置
* @param $site_id
* @return array
*/
public function getStoreWithdrawConfig($site_id)
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
//数据格式化
if (addon_is_exit('cashier') == 1) {
$order_common_model = new OrderCommonModel();
$pay_type = $order_common_model->getPayType([ 'order_type' => 5 ]);
} else {
$pay_type = [];
}
$data = [
//是否进行门店结算
'is_settlement' => $res[ 'data' ][ 'value' ][ 'is_settlement' ] ?? 0,
//结算周期 1 按天 2. 按周 3. 按月 4. 立即结算
'period_type' => $res[ 'data' ][ 'value' ][ 'period_type' ] ?? 4,
//结算比率
'settlement_rate' => $res[ 'data' ][ 'value' ][ 'settlement_rate' ] ?? 0,
// 结算付款控制
'settlement_pay_type' => $res[ 'data' ][ 'value' ][ 'settlement_pay_type' ] ?? implode(',', array_keys($pay_type)),
//结算成本控制 cuppon,point,balance,fenxiao_commission
'settlement_cost' => $res[ 'data' ][ 'value' ][ 'settlement_cost' ] ?? '',//'cuppon,point,balance,fenxiao_commission'
//是否允许提现
'is_withdraw' => $res[ 'data' ][ 'value' ][ 'is_withdraw' ] ?? 0,
//是否提现审核
'is_audit' => $res[ 'data' ][ 'value' ][ 'is_audit' ] ?? 0,
//是否自动转账
'is_auto_transfer' => $res[ 'data' ][ 'value' ][ 'is_auto_transfer' ] ?? 0,
//可提现账户类型 wechatalipay bank
'withdraw_type' => $res[ 'data' ][ 'value' ][ 'withdraw_type' ] ?? '',
'withdraw_least' => $res[ 'data' ][ 'value' ][ 'withdraw_least' ] ?? 0, // 提现最低金额
];
$res[ 'data' ][ 'value' ] = $data;
return $res;
}
/**
* 门店结算相关设置
*/
public function setStoreWithdrawConfig($site_id, $data)
{
$config = new ConfigModel();
$res = $config->setConfig($data, '门店结算设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
$cron = new Cron();
$execute_time = 0;
switch ( $data[ 'period_type' ] ) {
case 1://
$date = strtotime(date('Y-m-d 00:00:00'));
$execute_time = strtotime('+1day', $date);
break;
case 2://
$execute_time = Carbon::parse('next monday')->timestamp;
break;
case 3://
$execute_time = Carbon::now()->addMonth()->firstOfMonth()->timestamp;
break;
}
if ($execute_time > 0) {
$cron->deleteCron([ [ 'event', '=', 'StoreWithdrawPeriodCalc' ], [ 'relate_id', '=', $site_id ] ]);
$cron->addCron('2', '1', '门店周期结算', 'StoreWithdrawPeriodCalc', $execute_time, $site_id, $data[ 'period_type' ]);
}
return $res;
}
/**
* 获取门店运营相关设置
* @param $site_id
*/
public function getStoreBusinessConfig($site_id)
{
$config = new ConfigModel();
$res = $config->getConfig([ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_BUSINESS' ] ]);
//数据格式化
$data = [
//门店运营模式 shop店铺整体运营 store连锁门店运营模式
'store_business' => $res[ 'data' ][ 'value' ][ 'store_business' ] ?? 'shop',
//是否允许切换门店
'is_allow_change' => $res[ 'data' ][ 'value' ][ 'is_allow_change' ] ?? 1,
'confirm_popup_control' => $res[ 'data' ][ 'value' ][ 'confirm_popup_control' ] ?? 1, // 门店确认弹窗
//门店控制权限
'store_auth' => $res[ 'data' ][ 'value' ][ 'store_auth' ] ?? '',//'config,balance,point,coupon,adjust'
];
$res[ 'data' ][ 'value' ] = $data;
return $res;
}
/**
* 门店结算相关设置
*/
public function setStoreBusinessConfig($site_id, $data)
{
$config = new ConfigModel();
$res = $config->setConfig($data, '门店功能设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_BUSINESS' ] ]);
return $res;
}
/**
* addSettlementCron 添加门店结算计划任务 默认为3 - 月
*/
public function addSettlementCron($site_id)
{
$config = new ConfigModel();
$config->setConfig([ 'period_type' => 3 ], '门店结算设置', 1, [ [ 'site_id', '=', $site_id ], [ 'app_module', '=', 'shop' ], [ 'config_key', '=', 'SHOP_STORE_WITHDRAW' ] ]);
$cron = new Cron();
$execute_time = Carbon::now()->addMonth()->firstOfMonth()->timestamp;
$cron->deleteCron([ [ 'event', '=', 'StoreWithdrawPeriodCalc' ], [ 'relate_id', '=', $site_id ] ]);
$res = $cron->addCron('2', '1', '门店周期结算', 'StoreWithdrawPeriodCalc', $execute_time, $site_id, 3);
return $this->success($res);
}
}

145
addon/store/model/Label.php Executable file
View File

@@ -0,0 +1,145 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use think\facade\Db;
use think\facade\Cache;
use app\model\BaseModel;
/**
* 门店标签
*/
class Label extends BaseModel
{
/**
* 添加门店标签
*
* @param array $data
*/
public function addStoreLabel($data)
{
$count = model('store_label')->getCount([ [ 'label_name', '=', $data[ 'label_name' ] ], [ 'site_id', '=', $data[ 'site_id' ] ] ]);
if ($count) return $this->error('', '该标签名称已存在');
$res = model('store_label')->add($data);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 修改门店标签
*
* @param array $data
* @param array $condition
*/
public function editStoreLabel($data, $condition)
{
$check_condition = array_column($condition, 2, 0);
$label_id = $check_condition['label_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($label_id)) return $this->error('', 'label_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$count = model('store_label')->getCount([ [ 'label_id', '<>', $label_id ], [ 'label_name', '=', $data[ 'label_name' ] ], [ 'site_id', '=', $site_id ] ]);
if ($count) return $this->error('', '该标签名称已存在');
$old_label_name = model('store_label')->getValue($condition, 'label_name');
$res = model('store_label')->update($data, $condition);
model('store')->update([ 'label_name' => Db::raw("REPLACE(label_name, ',{$old_label_name},', ',{$data['label_name']},')") ], [ [ 'site_id', '=', $site_id ], [ 'label_id', 'like', "%,$label_id,%" ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 修改排序
* @param $sort
* @param $label_id
* @param $site_id
* @return array
*/
public function modifySort($sort, $label_id, $site_id)
{
$site_id = $site_id ?? '';
if ($site_id === '') {
return $this->error('', 'REQUEST_SITE_ID');
}
$res = model('store_label')->update([ 'sort' => $sort ], [ [ 'label_id', '=', $label_id ], [ 'site_id', '=', $site_id ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 删除门店标签
* @param $condition
* @return array
*/
public function deleteStoreLabel($condition)
{
$check_condition = array_column($condition, 2, 0);
$label_id = $check_condition['label_id'] ?? 0;
$site_id = $check_condition['site_id'] ?? 0;
if (empty($label_id)) return $this->error('', 'label_id不能为空');
if (empty($site_id)) return $this->error('', 'site_id不能为空');
$res = model('store_label')->delete($condition);
$old_label_name = model('store_label')->getValue($condition, 'label_name');
model('store')->update([ 'label_name' => Db::raw("REPLACE(label_name, ',{$old_label_name},', '')") ], [ [ 'site_id', '=', $site_id ], [ 'label_id', 'like', "%,$label_id,%" ] ]);
Cache::tag("store_label")->clear();
return $this->success($res);
}
/**
* 获取门店标签信息
* @param array $condition
* @param string $field
* @return array
*/
public function getStoreLabelInfo($condition = [], $field = '*')
{
$info = model('store_label')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 获取门店标签列表
*
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreLabelList($condition = [], $field = '*', $order = 'sort asc,label_id desc', $limit = null)
{
$list = model('store_label')->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
*/
public function getStoreLabelPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'sort asc,label_id desc', $field = '*')
{
$list = model('store_label')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
}

27
addon/store/model/Menu.php Executable file
View File

@@ -0,0 +1,27 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
/**
* 菜单管理
* @author Administrator
*
*/
class Menu extends BaseModel
{
public function uninstall()
{
$res = model("menu")->delete([ [ 'app_module', '=', 'store' ] ]);
return $this->success($res);
}
}

233
addon/store/model/Settlement.php Executable file
View File

@@ -0,0 +1,233 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\dict\order\OrderPayDict;
use app\model\BaseModel;
use app\model\order\OrderCommon;
/**
* 门店订单与结算
*/
class Settlement extends BaseModel
{
/**
* 店铺门店结算
* @param $site_id
* @param $end_time
* @return array
*/
public function settlement($site_id, $end_time)
{
//获取最近的店铺结算时间
$last_time = model('shop')->getInfo([ [ 'site_id', '=', $site_id ] ], 'store_settlement_time');
$start_time = $last_time[ 'store_settlement_time' ];
//查询门店结算配置
$config_model = new Config();
$config = $config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
if ($config[ 'is_settlement' ] != 1) {
return $this->success();
}
$period_type = $config[ 'period_type' ];
//结算周期为4的话是立即结算
if ($period_type == 4)
return $this->success();
$period_type = array ( 1 => 'day', 2 => 'week', 3 => 'month' )[ $period_type ] ?? 'day';
//只有开启周期性结算开关,才会进行
if (( $end_time - $start_time ) < ( 3600 * 20 )) {
return $this->success();
}
//店铺列表
$store_list = model('store')->getList([ [ 'site_id', '=', $site_id ] ], 'site_name, store_id, store_name, account');
model('store_settlement')->startTrans();
try {
$store_withdraw_model = new StoreWithdraw();
//循环各个店铺数据
foreach ($store_list as $store) {
$store_id = $store[ 'store_id' ];
//周期性结算会将所有抽成全部提现
$store_commission = $store[ 'account' ];
$withdraw_id = 0;
if ($store_commission > 0) {
$apply_params = array (
'site_id' => $site_id,
'store_id' => $store_id,
'money' => $store_commission,
'settlement_type' => $period_type
);
$withdraw_result = $store_withdraw_model->apply($apply_params);
$withdraw_id = $withdraw_result[ 'data' ];
}
$this->addSettlement([
'site_id' => $site_id,
'store_id' => $store_id,
'start_time' => $start_time,
'end_time' => $end_time,
'store_commission' => $store_commission,
'withdraw_id' => $withdraw_id,
])['data'];
}
model('shop')->update([ 'store_settlement_time' => $end_time ], [ [ 'site_id', '=', $site_id ] ]);
model('store_settlement')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_settlement')->rollback();
return $this->error($e->getMessage());
}
}
/**
* 添加结算
* @param $param
* @return array
*/
public function addSettlement($param)
{
$site_id = $param['site_id'];
$store_id = $param['store_id'];
$start_time = $param['start_time'];
$end_time = $param['end_time'];
$store_commission = $param['store_commission'];
$withdraw_id = $param['withdraw_id'];
$store_info = model('store')->getInfo([['store_id', '=', $store_id]], 'store_name,site_name');
$online_settlement = model('order')->getInfo([
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
[ 'pay_type', '<>', OrderPayDict::offline_pay ],//todo 支付方式应该都可以
], 'sum(pay_money) as order_money, sum(refund_money) as refund_money, sum(commission) as commission');
$offline_settlement = model('order')->getInfo([
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
[ 'pay_type', '=', 'offlinepay' ],
], 'sum(pay_money) as offline_order_money, sum(refund_money) as offline_refund_money');
$settlement = [
'settlement_no' => date('YmdHi') . $store_id . rand(1111, 9999),
'site_id' => $site_id,
'site_name' => $store_info[ 'site_name' ],
'store_id' => $store_id,
'store_name' => $store_info[ 'store_name' ],
'order_money' => $online_settlement[ 'order_money' ] ?? 0,
'refund_money' => $online_settlement[ 'refund_money' ] ?? 0,
'commission' => $online_settlement[ 'commission' ] ?? 0,
'offline_order_money' => $offline_settlement[ 'offline_order_money' ] ?? 0,
'offline_refund_money' => $offline_settlement[ 'offline_refund_money' ] ?? 0,
'create_time' => $end_time,
'start_time' => $start_time,
'end_time' => $end_time,
'store_commission' => $store_commission,
'withdraw_id' => $withdraw_id,
];
$store_settlement_id = model('store_settlement')->add($settlement);
model('order')->update([ 'store_settlement_id' => $store_settlement_id, 'is_settlement' => 1 ], [
[ 'order_status', '=', 10 ],
[ 'is_settlement', '=', 0 ],
[ 'store_id', '=', $store_id ],
[ 'finish_time', '<=', $end_time ],
]);
return $this->success($store_settlement_id);
}
/**
* 获取详情
* @param $condition
* @param string $fields
* @return array
*/
public function getSettlementInfo($condition, $fields = '*')
{
$res = model('store_settlement')->getInfo($condition, $fields);
return $this->success($res);
}
/**
* 修改结算记录
* @param $data
* @param $condition
* @return array
*/
public function editSettlement($data, $condition)
{
$res = model('store_settlement')->update($data, $condition);
return $this->success($res);
}
/**
* 获取店铺待结算订单金额
* @param array $condition
* @return array|mixed
*/
public function getStoreSettlementData($condition = [])
{
$money_info = model('order')->getInfo($condition, 'sum(order_money) as order_money, sum(refund_money) as refund_money, sum(shop_money) as shop_money, sum(platform_money) as platform_money, sum(refund_shop_money) as refund_shop_money, sum(refund_platform_money) as refund_platform_money, sum(commission) as commission');
if (empty($money_info) || $money_info == null) {
$money_info = [
'order_money' => 0,
'refund_money' => 0,
'shop_money' => 0,
'platform_money' => 0,
'refund_shop_money' => 0,
'refund_platform_money' => 0,
'commission' => 0
];
}
return $money_info;
}
/**
* 获取店铺结算周期结算分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreSettlementPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '', $field = '*')
{
$list = model('store_settlement')->pageList($condition, $field, $order, $page, $page_size);
return $this->success($list);
}
/**
* 拒绝提现后的处理
* @param $withdraw_id
* @return array
*/
public function refuseWithdraw($withdraw_id)
{
$settlement_info = model('store_settlement')->getInfo([['withdraw_id', '=', $withdraw_id]]);
if(!empty($settlement_info)){
$store_settlement_id = $settlement_info['id'];
model('order')->update(['is_settlement' => 0, 'store_settlement_id' => 0], [['store_settlement_id', '=', $store_settlement_id]]);
}
return $this->success();
}
}

51
addon/store/model/Stat.php Executable file
View File

@@ -0,0 +1,51 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
/**
* 门店订单与结算
*/
class Stat extends BaseModel
{
/**
* 统计
* @param $params
*/
public function getStoreAccountSum($condition, $field)
{
$sum = model('store')->getSum($condition, $field);
return $this->success($sum);
}
/**
* 门店订单的销售额和销售量排行
* @param $params
*/
public function getStoreOrderRank($params)
{
$site_id = $params[ 'site_id' ];
$join = [
[ 'order o', '(o.store_id = s.store_id and o.pay_status = 1 and o.is_delete = 0) || o.store_id is null ', 'left' ]
];
$group = 's.store_id';
$limit = 5;
$order = $params[ 'order' ] == 'num' ? 'order_num desc' : 'order_money desc';
$field = 'ifnull(count(o.order_id), 0) as order_num, ifnull(sum(o.order_money), 0) as order_money,s.store_name';
$condition = array (
[ 's.site_id', '=', $site_id ],
);
$list = model('store')->getList($condition, $field, $order, 's', $join, $group, $limit);
return $this->success($list);
}
}

View File

@@ -0,0 +1,304 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\system\Export as ExportModel;
use think\facade\Db;
class StoreAccount extends BaseModel
{
public $period_types = [ 1, 2, 3 ];//转账周期类型1.天 2. 周 3. 月
public $from_type = [
'order' => [
'type_name' => '订单结算',
'type_url' => '',
],
'refund' => [
'type_name' => '订单退款',
'type_url' => '',
],
'withdraw' => [
'type_name' => '门店提现',
'type_url' => '',
],
];
/**
* 获取门店转账设置
*/
public function getStoreWithdrawConfig($site_id)
{
$config = new Config();
$res = $config->getStoreWithdrawConfig($site_id);
return $res;
}
/**
* 获取门店待结算订单金额
*/
public function getWaitSettlementInfo($store_id)
{
$money_info = model('order')->getInfo([
[ 'store_id', '=', $store_id ],
[ 'order_status', '=', 10 ],
[ 'store_settlement_id', '=', 0 ]
], 'sum(order_money) as order_money, sum(refund_money) as refund_money, sum(shop_money) as shop_money, sum(platform_money) as platform_money, sum(refund_shop_money) as refund_shop_money, sum(refund_platform_money) as refund_platform_money, sum(commission) as commission');
if (empty($money_info) || $money_info == null) {
$money_info = [
'order_money' => 0,
'refund_money' => 0,
'shop_money' => 0,
'platform_money' => 0,
'refund_shop_money' => 0,
'refund_platform_money' => 0,
'commission' => 0
];
}
return $money_info;
}
/**
* 门店账户记录操作
* @param $params
*/
public function addStoreAccount($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ];
$account_data = $params[ 'account_data' ];
$remark = $params[ 'remark' ];
$from_type = $params[ 'from_type' ];
$related_id = $params[ 'related_id' ];
$is_limit = $params[ 'is_limit' ] ?? 1;//是否限制不能小于0
model('store_account')->startTrans();
try {
//账户检测
$store_account = Db::name('store')->where([
[ 'store_id', '=', $store_id ],
[ 'site_id', '=', $site_id ]
])->field('account')->lock(true)->find();
$account_new_data = round((float) $store_account[ 'account' ] + (float) $account_data, 2);
if ($is_limit == 1 && (float) $account_new_data < 0) {
model('store_account')->rollback();
$msg = '账户余额不足';
return $this->error('', $msg);
}
//添加记录
$type_info = $this->from_type[ $from_type ];
$data = array (
'site_id' => $site_id,
'store_id' => $store_id,
'account_data' => $account_data,
'from_type' => $from_type,
'type_name' => $type_info[ 'type_name' ],
'create_time' => time(),
'remark' => $remark,
'related_id' => $related_id,
);
model('store_account')->add($data);
//账户更新
model('store')->update([
'account' => $account_new_data
], [
[ 'store_id', '=', $store_id ]
]);
model('store_account')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_account')->rollback();
return $this->error('', $e->getMessage());
}
}
public function getStoreAccountInfo($condition, $field = '*', $alias = 'a', $join = [])
{
$info = model('store_account')->getInfo($condition, $field, $alias, $join);
return $this->success($info);
}
/**
* 获取账户分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array|\multitype
*/
public function getStoreAccountPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'create_time desc,id desc', $field = '*', $alias = 'a', $join = [])
{
$list = model('store_account')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取账户列表
* @param array $condition
* @param string $field
* @param string $order
* @param null $limit
* @return array|\multitype
*/
public function getStoreAccountList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_account')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 添加门店账户导出
* @param $input
* @return array
*/
public function addStoreAccountExport($input, $export_store_id = 0)
{
$remark = $input['remark'] ?? '';
$start_date = $input['start_date'] ?? '';
$end_date = $input['end_date'] ?? '';
$from_type = $input['from_type'] ?? '';
$store_id = $input['store_id'] ?? 0;
$site_id = $input['site_id'];
$account_model = new StoreAccount();
$store_model = new \app\model\store\Store();
//组装条件和条件说明
$condition = [ [ 'sa.site_id', '=', $site_id ] ];
$condition_desc = [];
if (!empty($remark)) {
$condition[] = [ 'sa.remark', 'like', '%' . $remark . '%' ];
$condition_desc[] = ['name' => '备注信息', 'value' => $remark];
}
if (!empty($from_type)) {
$condition[] = [ 'sa.from_type', '=', $from_type ];
$from_type_list = $account_model->from_type;
$condition_desc[] = ['name' => '来源类型', 'value' => $from_type_list[$from_type]['type_name']];
}
if ($store_id > 0) {
$condition[] = [ 'sa.store_id', '=', $store_id ];
$store_info = $store_model->getStoreInfo([['store_id', '=', $store_id]], 'store_name')['data'];
$condition_desc[] = ['name' => '门店名称', 'value' => $store_info['store_name']];
}
$time_name = '';
if (!empty($start_date) && empty($end_date)) {
$condition[] = [ 'sa.create_time', '>=', date_to_time($start_date) ];
$time_name = $start_date . '起';
} elseif (empty($start_date) && !empty($end_date)) {
$condition[] = [ 'sa.create_time', '<=', date_to_time($end_date) ];
$time_name = '至' . $end_date;
} elseif (!empty($start_date) && !empty($end_date)) {
$condition[] = [ 'sa.create_time', 'between', [ date_to_time($start_date), date_to_time($end_date) ] ];
$time_name = $start_date . ' 至 ' . $end_date;
}
if($time_name) $condition_desc[] = [ 'name' => '发生时间', 'value' => $time_name ];
$param = [
'site_id' => $site_id,
'store_id' => $export_store_id,
'from_type' => 'store_account',
'from_type_name' => '门店账户',
'condition_desc' => $condition_desc,
'query' => [
'table' => 'store_account',
'alias' => 'sa',
'join' => [
['store s', 'sa.store_id = s.store_id', 'inner'],
],
'condition' => $condition,
'field' => 'sa.*,s.store_name',
'chunk_field' => 'sa.id',
'chunk_order' => 'asc',
],
'export_field' => [
['field' => 'store_name', 'name' => '门店名称'],
['field' => 'type_name', 'name' => '来源方式'],
['field' => 'account_data', 'name' => '记录金额'],
['field' => 'create_time', 'name' => '发生时间'],
['field' => 'remark', 'name' => '备注'],
['field' => 'related_no', 'name' => '关联编号'],
],
'handle' => function($item_list){
foreach($item_list as &$item){
$item['create_time'] = date('Y-m-d H:i:s', $item['create_time']);
}
return $this->getRelatedInfo($item_list);
},
];
$export_model = new ExportModel();
return $export_model->export($param);
}
/**
* 获取关联单号
* @param $item_list
* @return mixed
*/
public function getRelatedInfo($item_list)
{
$order_ids = $refund_ids = $withdraw_ids = [];
$order_list = $refund_list = $withdraw_list = [];
foreach($item_list as $item){
switch($item['from_type']){
case 'order':
$order_ids[] = $item['related_id'];
break;
case 'refund':
$refund_ids[] = $item['related_id'];
break;
case 'withdraw':
$withdraw_ids[] = $item['related_id'];
break;
}
}
if(!empty($order_ids)){
$order_list = model('order')->getList([['order_id', 'in', $order_ids]], 'order_id,order_no,order_from');
$order_list = array_column($order_list, null, 'order_id');
}
if(!empty($refund_ids)){
$alias = 'og';
$join = [
['order o', 'o.order_id = og.order_id', 'inner'],
];
$field = 'og.order_goods_id,og.refund_no,o.order_id,o.order_no,o.order_from';
$refund_list = model('order_goods')->getList([['og.order_goods_id', 'in', $refund_ids]], $field, '', $alias, $join);
$refund_list = array_column($refund_list, null, 'order_goods_id');
}
if(!empty($withdraw_ids)){
$withdraw_list = model('store_withdraw')->getList([['withdraw_id', 'in', $withdraw_ids]], 'withdraw_id,withdraw_no');
$withdraw_list = array_column($withdraw_list, null, 'withdraw_id');
}
foreach($item_list as &$item){
switch($item['from_type']){
case 'order':
$item['related_no'] = $order_list[$item['related_id']]['order_no'] ?? '';
$item['related_info'] = $order_list[$item['related_id']] ?? null;
break;
case 'refund':
$item['related_no'] = $refund_list[$item['related_id']]['refund_no'] ?? '';
$item['related_info'] = $refund_list[$item['related_id']] ?? null;
break;
case 'withdraw':
$item['related_no'] = $withdraw_list[$item['related_id']]['withdraw_no'] ?? '';
$item['related_info'] = $withdraw_list[$item['related_id']] ?? null;
break;
}
}
return $item_list;
}
}

100
addon/store/model/StoreGoods.php Executable file
View File

@@ -0,0 +1,100 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
class StoreGoods extends BaseModel
{
/**
* 商品编辑之后
*/
public function goodsEditAfter($goods_id, $site_id)
{
// $store_list = model('store')->getList([ [ 'site_id', '=', $site_id ] ], 'store_id');
// if (!empty($store_list)) {
// $goods_sku = model('goods_sku')->getColumn([ [ 'goods_id', '=', $goods_id ] ], 'sku_id');
// model('store_goods_sku')->startTrans();
// try {
// foreach ($store_list as $v) {
// $store_id = $v[ 'store_id' ];
// $store_goods_sku = model('store_goods_sku')->getColumn([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ], 'sku_id');
// if (!empty($store_goods_sku)) {
//
// model('store_goods_sku')->delete([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ], [ 'sku_id', 'not in', $goods_sku ] ]);
// $stock = model('store_goods_sku')->getSum([ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ], 'stock');
// model('store_goods')->update([ 'stock' => $stock ], [ [ 'store_id', '=', $store_id ], [ 'goods_id', '=', $goods_id ] ]);
// }
// }
//
// model('store_goods_sku')->commit();
return $this->success();
// } catch (\Exception $e) {
// model('store_goods_sku')->rollback();
// return $this->error('', $e->getMessage());
// }
// }
}
/**
* 门店详情
* @param $condition
* @param string $fields
* @return array
*/
public function getStoreGoodsInfo($condition, $fields = '*')
{
$info = model('store_goods')->getInfo($condition, $fields);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'sale_num' ])) {
$info[ 'sale_num' ] = numberFormat($info[ 'sale_num' ]);
}
if (isset($info[ 'real_stock' ])) {
$info[ 'real_stock' ] = numberFormat($info[ 'real_stock' ]);
}
}
return $this->success($info);
}
/**
* 获取门店商品列表
* @param array $condition
* @param string $field
* @param string $order
* @param string $limit
*/
public function getStoreGoodsList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_goods')->getList($condition, $field, $order, '', '', '', $limit);
foreach ($list as &$v) {
$v[ 'store_goods_skus' ] = model('store_goods_sku')->getList([
[ 'store_id', '=', $v[ 'store_id' ] ],
[ 'goods_id', '=', $v[ 'goods_id' ] ]
], 'sku_id,goods_id,stock,sale_num');
if (isset($v[ 'stock' ])) {
$v[ 'stock' ] = numberFormat($v[ 'stock' ]);
}
if (isset($v[ 'sale_num' ])) {
$v[ 'sale_num' ] = numberFormat($v[ 'sale_num' ]);
}
if (isset($v[ 'real_stock' ])) {
$v[ 'real_stock' ] = numberFormat($v[ 'real_stock' ]);
}
}
return $this->success($list);
}
}

View File

@@ -0,0 +1,315 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\goods\Goods;
class StoreGoodsSku extends BaseModel
{
/**
* 添加店铺sku
* @param $data
* @return array
*/
public function addStoreGoodsSku($data)
{
$res = model('store_goods_sku')->add($data);
//判断当前有没有store_goods
$store_goods_info = model('store_goods')->getInfo([ [ 'goods_id', '=', $data[ 'goods_id' ] ], [ 'store_id', '=', $data[ 'store_id' ] ] ], 'id');
if (empty($store_goods_info)) {
$store_goods_data = [
'goods_id' => $data[ 'goods_id' ],
'store_id' => $data[ 'store_id' ],
'create_time' => time(),
];
model('store_goods')->add($store_goods_data);
}
return $this->success($res);
}
/**
* 获取门店商品sku详情
* @param $condition
* @param string $field
* @return array
*/
public function getStoreGoodsSkuInfo($condition, $field = '*')
{
$res = model('store_goods_sku')->getInfo($condition, $field);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'sale_num' ])) {
$info[ 'sale_num' ] = numberFormat($info[ 'sale_num' ]);
}
if (isset($info[ 'real_stock' ])) {
$info[ 'real_stock' ] = numberFormat($info[ 'real_stock' ]);
}
}
return $this->success($res);
}
/**
* 增加库存
* @param param
*/
public function incStock($param)
{
$condition = array (
[ 'store_id', '=', $param[ 'store_id' ] ],
[ 'sku_id', '=', $param[ 'sku_id' ] ]
);
$num = $param[ 'stock' ];
$store_sku_info = model('store_goods_sku')->getInfo($condition, 'id, goods_id');
if (empty($store_sku_info))
return $this->error(-1, "");
//编辑sku库存
$result = model('store_goods_sku')->setInc($condition, 'stock', $num);
model('store_goods')->setInc([ [ 'goods_id', '=', $store_sku_info[ 'goods_id' ] ], [ 'store_id', '=', $param[ 'store_id' ] ] ], 'stock', $num);
return $this->success($result);
}
/**
* 减少库存
* @param $param
* @return array
*/
public function decStock($param)
{
$condition = array (
[ 'store_id', '=', $param[ 'store_id' ] ],
[ 'sku_id', '=', $param[ 'sku_id' ] ]
);
$num = $param[ 'stock' ];
$store_sku_info = model('store_goods_sku')->getInfo($condition, 'id, goods_id, stock');
if (empty($store_sku_info)) {
return $this->error(-1, '库存不足!');
}
$store_sku_info[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if (( $store_sku_info[ 'stock' ] - $num ) < 0) {
return $this->error(-1, '库存不足!');
}
//编辑sku库存
$result = model('store_goods_sku')->setDec($condition, 'stock', $num);
model('store_goods')->setDec([ [ 'goods_id', '=', $store_sku_info[ 'goods_id' ] ], [ 'store_id', '=', $param[ 'store_id' ] ] ], 'stock', $num);
return $this->success($result);
}
/**
* 编辑门店商品库存信息
* @param $goods_sku_array
*/
public function editStock($store_goods_sku_array)
{
model('store_goods_sku')->startTrans();
try {
foreach ($store_goods_sku_array as $item) {
$sku_info_result = $this->getStoreGoodsSkuInfo([ [ "store_id", "=", $item[ "store_id" ] ], [ "sku_id", "=", $item[ "sku_id" ] ] ], "sku_id");
$sku_info = $sku_info_result[ "data" ];
if (empty($sku_info)) {
$sku_data = array (
"goods_id" => $item[ "goods_id" ],
"sku_id" => $item[ "sku_id" ],
"store_id" => $item[ "store_id" ],
);
$this->addStoreGoodsSku($sku_data);
}
if ($item[ 'stock' ] > 0) {
$item_result = $this->incStock($item);
} else {
$item[ 'stock' ] = abs($item[ 'stock' ]);
$item_result = $this->decStock($item);
}
if ($item_result[ "code" ] < 0) {
model('store_goods_sku')->rollback();
return $item_result;
}
}
model('store_goods_sku')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_goods_sku')->rollback();
return $this->error($e->getMessage());
}
}
/**
* 门店库存批量修改导入excel
* @param $param
* @param $site_id
* @return array
*/
public function importStoreGoodsStock($param, $site_id, $store_id)
{
$PHPReader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader('Xlsx');
//载入文件
$PHPExcel = $PHPReader->load($param[ 'path' ]);
//获取表中的第一个工作表如果要获取第二个把0改为1依次类推
$currentSheet = $PHPExcel->getSheet(0);
//获取总行数
$allRow = $currentSheet->getHighestRow();
if ($allRow < 2) {
return $this->error('', '导入了一个空文件');
}
//添加文件上传记录
$error_num = 0;
$data = [
'site_id' => $site_id,
'store_id' => $store_id,
'filename' => $param[ 'filename' ],
'path' => $param[ 'path' ],
'sku_num' => $allRow - 1,
'create_time' => time()
];
$res = model('store_stock_import')->add($data);
if (!$res) {
return $this->error('', '上传文件失败');
}
model('store_stock_import')->startTrans();
try {
for ($i = 2; $i <= $allRow; $i++) {
//商品id
$goods_id = $PHPExcel->getActiveSheet()->getCell('A' . $i)->getValue();
$goods_id = trim($goods_id, ' ');
//商品名称
$goods_name = $PHPExcel->getActiveSheet()->getCell('B' . $i)->getValue();
$goods_name = trim($goods_name, ' ');
//sku_id
$sku_id = $PHPExcel->getActiveSheet()->getCell('C' . $i)->getValue();
$sku_id = trim($sku_id, ' ');
//sku名称
$sku_name = $PHPExcel->getActiveSheet()->getCell('D' . $i)->getValue();
$sku_name = trim($sku_name, ' ');
//库存(增/减)
$stock = $PHPExcel->getActiveSheet()->getCell('F' . $i)->getValue();
$stock = trim($stock, ' ');
if (empty($goods_id) || empty($sku_id) || empty($stock)) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => '商品编号、sku编号或者库存为空'
]
);
continue;
}
$goods_model = new Goods();
$sku_info = $goods_model->getGoodsSkuInfo([ [ 'sku_id', '=', $sku_id ], [ 'goods_id', '=', $goods_id ], [ 'site_id', '=', $site_id ] ]);
if (empty($sku_info[ 'data' ])) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => '商品不存在'
]
);
continue;
}
$sku_info_result = $this->getStoreGoodsSkuInfo([ [ "store_id", "=", $store_id ], [ "sku_id", "=", $sku_id ] ], "sku_id");
$sku_info = $sku_info_result[ "data" ];
if (empty($sku_info)) {
$sku_data = array (
"goods_id" => $goods_id,
"sku_id" => $sku_id,
"store_id" => $store_id,
);
$this->addStoreGoodsSku($sku_data);
}
$store_data = [
'store_id' => $store_id,
'sku_id' => $sku_id,
'stock' => $stock
];
if ($stock > 0) {
$item_result = $this->incStock($store_data);
} else {
$store_data[ 'stock' ] = abs($store_data[ 'stock' ]);
$item_result = $this->decStock($store_data);
}
if ($item_result[ "code" ] < 0) {
$error_num += 1;
model('store_stock_import')->update([ 'error_num' => $error_num ], [ [ 'id', '=', $res ] ]);
//添加失败记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => -1, 'reason' => $item_result[ 'message' ]
]
);
continue;
}
//添加记录
model('store_stock_import_log')->add(
[
'store_id' => $store_id, 'file_id' => $res, 'goods_id' => $goods_id, 'goods_name' => $goods_name, 'sku_id' => $sku_id,
'sku_name' => $sku_name, 'stock' => $stock, 'status' => 0, 'reason' => ''
]
);
}
model('store_stock_import')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_stock_import')->rollback();
model('store_stock_import')->update([ 'error_num' => $allRow - 1 ], [ [ 'id', '=', $res ] ]);
return $this->error('', $e->getMessage());
}
}
/**
* 核验门店库存是否足够
* @param $params
*/
public function checkStoreGoodsSkuStock($params)
{
$store_id = $params[ 'store_id' ];
$goods_id = $params[ 'goods_id' ];
$sku_id = $params[ 'sku_id' ];
$site_id = $params[ 'site_id' ];
$num = $params[ 'num' ];
$sku_condition = array (
[ 'goods_id', '=', $goods_id ],
[ 'sku_id', '=', $sku_id ],
[ 'store_id', '=', $store_id ],
);
$store_sku_info = model('store_goods_sku')->getInfo($sku_condition, 'stock');
if (empty($store_sku_info)) {
return $this->error(-1, '库存不足!');
}
$store_sku_info[ 'stock' ] = numberFormat($store_sku_info[ 'stock' ]);
if (( $store_sku_info[ 'stock' ] - $num ) < 0) {
return $this->error(-1, '库存不足!');
}
return $this->success();
}
}

224
addon/store/model/StoreMember.php Executable file
View File

@@ -0,0 +1,224 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use think\facade\Db;
use app\model\system\Address;
/**
* 店铺会员表
*/
class StoreMember extends BaseModel
{
/**
* 添加店铺关注会员
* @param $site_id
* @param $member_id
* @param int $is_subscribe
* @return array
*/
public function addStoreMember($store_id, $member_id)
{
$shop_member_info = model("store_member")->getInfo([ [ 'store_id', '=', $store_id ], [ 'member_id', '=', $member_id ] ], 'id');
if (!empty($shop_member_info)) {
return $this->success();
} else {
$data = [
'store_id' => $store_id,
'member_id' => $member_id,
'create_time' => time(),
];
$res = model("store_member")->add($data);
}
return $this->success($res);
}
/**
* 获取店铺会员分页列表
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getStoreMemberPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = '')
{
$field = 'nm.member_id, nm.source_member, nm.username, nm.nickname, nm.mobile, nm.email, nm.headimg, nm.status, nm.member_level,nm.member_level_name,nm.balance,nm.balance_money,nsm.store_id, nsm.create_time';
$alias = 'nsm';
$join = [
[
'member nm',
'nsm.member_id = nm.member_id',
'inner'
],
];
$list = model("store_member")->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取会员店铺分页列表
* @param array $condition
* @param number $page
* @param string $page_size
* @param string $order
* @param string $field
*/
public function getMemberShopPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'nsm.subscribe_time desc', $field = 'ns.site_id, ns.site_name, ns.is_own, ns.logo, ns.telephone,ns.sub_num, nsm.subscribe_time,ns.seo_description,ns.shop_desccredit,ns.shop_servicecredit,ns.shop_deliverycredit,ns.shop_sales,ns.shop_sales,ns.is_own')
{
$alias = 'nsm';
$join = [
[
'shop ns',
'nsm.site_id = ns.site_id',
'inner'
],
];
$list = model("shop_member")->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取门店会员数量
* @param $condition
* @param string $alias
* @param array $join
* @param null $group
* @return array
*/
public function getMemberCount($condition, $alias = 'a', $join = [], $group = null)
{
$db = Db::name('store_member')->where($condition);
if (!empty($join)) {
$db = $this->parseJoin($db->alias($alias), $join);
}
if (!empty($group)) {
$db = $db->group($group);
}
$count = $db->count();
return $this->success($count);
}
/**
* 获取门店已购会员数
*/
public function getPurchasedMemberCount($store_id)
{
$prefix = config("database")[ "connections" ][ "mysql" ][ "prefix" ];
$res = model("store_member")->query("SELECT GROUP_CONCAT(member_id) as member_id FROM {$prefix}store_member WHERE store_id = {$store_id}");
if (isset($res[ 0 ]) && isset($res[ 0 ][ 'member_id' ]) && !empty($res[ 0 ][ 'member_id' ])) {
$condition = [
[ 'delivery_store_id', '=', $store_id ],
[ 'member_id', 'in', $res[ 0 ][ 'member_id' ] ]
];
$res = model('order')->getList($condition, 'order_id', '', 'a', [], 'member_id');
return $this->success(count($res));
}
return $this->success(0);
}
/**
* 按地域分布查询会员数量
* @param $site_id
* @param bool $handle
* @return array
*/
public function getMemberCountByArea($site_id, $handle = false)
{
$total_count = $this->getMemberCount([ [ 'site_id', '=', $site_id ] ]);
$address = new Address();
$list = $address->getAreaList([ [ 'pid', '=', 0 ] ], 'id,shortname', 'sort asc');
$data = [];
if ($total_count[ 'data' ]) {
foreach ($list[ 'data' ] as $item) {
$count = $this->getMemberCount([ [ 'nsm.site_id', '=', $site_id ], [ 'nma.is_default', '=', 1 ], [ 'nma.province_id', '=', $item[ 'id' ] ] ], 'nsm', [ [ 'member_address nma', 'nsm.member_id = nma.member_id', 'left' ] ], 'nma.member_id');
if ($handle) {
if ($count[ 'data' ] > 0) {
$data[] = [
'name' => $item['shortname'],
'value' => $count['data'],
'ratio' => $count['data'] > 0 ? sprintf("%.2f", $count['data'] / $total_count['data'] * 100) : 0
];
}
} else {
$data[] = [
'name' => $item['shortname'],
'value' => $count['data'],
'ratio' => $count['data'] > 0 ? sprintf("%.2f", $count['data'] / $total_count['data'] * 100) : 0
];
}
}
}
if ($handle) {
array_multisort(array_column($data, 'value'), SORT_DESC, $data);
}
return $this->success([
'page_count' => 1,
'count' => $total_count[ 'data' ],
'list' => $data
]);
}
/**
* 处理表连接
* @param unknown $db_obj
* @param unknown $join
*/
protected function parseJoin($db_obj, $join)
{
foreach ($join as $item) {
list($table, $on, $type) = $item;
$type = strtolower($type);
switch ( $type ) {
case "left":
$db_obj = $db_obj->leftJoin($table, $on);
break;
case "inner":
$db_obj = $db_obj->join($table, $on);
break;
case "right":
$db_obj = $db_obj->rightjoin($table, $on);
break;
case "full":
$db_obj = $db_obj->fulljoin($table, $on);
break;
default:
break;
}
}
return $db_obj;
}
/**
* 查询会员信息
* @param unknown $where
* @param string $field
* @param string $alias
* @param string $join
* @param string $data
*/
public function getMemberInfo($where = [], $field = true, $alias = 'a', $join = null, $data = null)
{
$info = model("store_member")->getInfo($where, $field, $alias, $join, $data);
if (empty($info)) return $this->error('MEMBER_NOT_EXIST', 'MEMBER_NOT_EXIST');
else return $this->success($info);
}
}

102
addon/store/model/StoreOrder.php Executable file
View File

@@ -0,0 +1,102 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\verify\Verify;
class StoreOrder extends BaseModel
{
/**
* 基础支付方式(不考虑实际在线支付方式或者货到付款方式)
* @var unknown
*/
public $pay_type = [
'offlinepay' => '现金'
];
/**
* 获取支付方式
*/
public function getPayType($site_id)
{
//获取订单基础的其他支付方式
$pay_type = $this->pay_type;
//获取当前所有在线支付方式
$onlinepay = event('PayType', [ "app_type" => "pc", 'site_id' => $site_id ]);
if (!empty($onlinepay)) {
foreach ($onlinepay as $k => $v) {
$pay_type[ $v[ 'pay_type' ] ] = $v[ 'pay_type_name' ];
}
}
return $pay_type;
}
/**
* 订单支付后操作
* @param $order
*/
public function orderPay($order)
{
if (empty($order[ 'delivery_store_id' ])) {
return $this->success();
}
model('store')->startTrans();
try {
model('store')->setInc([ [ 'store_id', '=', $order[ 'delivery_store_id' ] ] ], 'order_num');
model('store')->setInc([ [ 'store_id', '=', $order[ 'delivery_store_id' ] ] ], 'order_money', $order[ 'order_money' ]);
model('store_member')->setInc([ [ 'member_id', '=', $order[ 'member_id' ] ] ], 'order_num');
model('store_member')->setInc([ [ 'member_id', '=', $order[ 'member_id' ] ] ], 'order_money', $order[ 'order_money' ]);
//如果是否门店收银订单,订单会自动核销
if ($order[ 'promotion_type' ] == 'store') {
//主动调用核销流程
$verifier_info = array (
'verifier_id' => 0,
'verifier_name' => '收银台订单自动核销',
"verify_from" => 'store',
'verify_remark' => '门店名称:' . $order[ 'delivery_store_name' ],
);
$verify_model = new Verify();
$result = $verify_model->verify($verifier_info, $order[ 'delivery_code' ]);
if ($result[ 'code' ] < 0) {
model('store')->rollback();
return $result;
}
}
model('store')->commit();
return $this->success();
} catch (\Exception $e) {
model('store')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 门店订单完成后操作 todo 应该删除
* @param $order
*/
public function orderComplete($order_id)
{
// $order_info = model('order')->getInfo([['order_id', '=', $order_id]], '*');
// if (empty($order_info['delivery_store_id'])) {
// return $this->success();
// }
// model('store')->setInc([['store_id', '=', $order_info['delivery_store_id']]], 'order_complete_num');
// model('store')->setInc([['store_id', '=', $order_info['delivery_store_id']]], 'order_complete_money', $order_info['order_money']);
// model('store_member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_num');
// model('store_member')->setInc([['member_id', '=', $order_info['member_id']]], 'order_complete_money', $order_info['order_money']);
// Cache::tag("store")->clear();
return $this->success();
}
}

View File

@@ -0,0 +1,104 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
class StoreStockImport extends BaseModel
{
/**
* 详情
* @param array $condition
* @param string $field
* @return array
*/
public function getStoreStockImportInfo($condition = [], $field = '*')
{
$info = model('store_stock_import')->getInfo($condition, $field);
if (!empty($info)) {
if (isset($info[ 'stock' ])) {
$info[ 'stock' ] = numberFormat($info[ 'stock' ]);
}
if (isset($info[ 'error_num' ])) {
$info[ 'error_num' ] = numberFormat($info[ 'error_num' ]);
}
}
return $this->success($info);
}
/**
* 删除
* @param $id
* @param $store_id
* @return array
*/
public function deleteStoreStockImport($id, $store_id)
{
model('store_stock_import')->startTrans();
try {
model('store_stock_import')->delete([ [ 'id', '=', $id ], [ 'store_id', '=', $store_id ] ]);
model('store_stock_import_log')->delete([ [ 'file_id', '=', $id ] ]);
model('store_stock_import')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_stock_import')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreStockImportPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('store_stock_import')->pageList($condition, $field, $order, $page, $page_size);
foreach ($list as $k => $v) {
if (isset($v[ 'stock' ])) {
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
}
if (isset($v[ 'error_num' ])) {
$list[ $k ][ 'error_num' ] = numberFormat($list[ $k ][ 'error_num' ]);
}
}
return $this->success($list);
}
/**
* 获取导入文件列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array
*/
public function getStoreStockImportPageLogList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'id desc', $field = '*')
{
$list = model('store_stock_import_log')->pageList($condition, $field, $order, $page, $page_size);
foreach ($list as $k => $v) {
if (isset($v[ 'stock' ])) {
$list[ $k ][ 'stock' ] = numberFormat($list[ $k ][ 'stock' ]);
}
}
return $this->success($list);
}
}

View File

@@ -0,0 +1,647 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model;
use app\model\BaseModel;
use app\model\member\MemberAccount;
use app\model\member\Withdraw as MemberWithdraw;
use app\model\store\Store;
use app\model\system\Pay;
use app\model\system\PayTransfer;
use think\facade\Cache;
class StoreWithdraw extends BaseModel
{
const STATUS_WAIT_AUDIT = 0;//待审核
const STATUS_WAIT_TRANSFER = 1;//待转账
const STATUS_SUCCESS = 2;//已转账
const STATUS_IN_PROCESS = 3;//转账中
const STATUS_FAIL = -2;//转账失败
const STATUS_REFUSE = -1;//已拒绝
public $status = array (
self::STATUS_WAIT_AUDIT => '待审核',
self::STATUS_WAIT_TRANSFER => '待转账',
self::STATUS_SUCCESS => '已转账',
self::STATUS_IN_PROCESS => '转账中',
self::STATUS_FAIL => '转账失败',
self::STATUS_REFUSE => '已拒绝',
);
public $settlement_type = array (
'apply' => '申请结算',
'day' => '每日结算',
'week' => '每周结算',
'month' => '每月结算',
);
/**
* 门店账户提现
* @param $params
*/
public function apply($params)
{
$money = $params[ 'money' ] ?? 0;
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ];
$settlement_type = $params[ 'settlement_type' ] ?? 'apply';
$store_config_model = new Config();
$config = $store_config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
$is_audit = $config[ 'is_audit' ];
$is_settlement = $config[ 'is_settlement' ];
if ($is_settlement == 0)
return $this->error([], '门店结算未开启');
$withdraw_least = $config[ 'withdraw_least' ];
$store_model = new Store();
$store_condition = array (
[ 'site_id', '=', $site_id ],
[ 'store_id', '=', $store_id ]
);
$store_info = $store_model->getStoreInfoByAccount($store_condition)[ 'data' ] ?? [];
if (empty($store_info))
return $this->error([], '找不到可结算的门店');
if ($settlement_type == 'apply') {
if ($money < $withdraw_least) {
return $this->error([], '门店最低结算金额为' . $withdraw_least . '元');
}
}
if ($money > $store_info[ 'account' ]) {
return $this->error([], '申请结算金额不能大于门店最大可结算金额');
}
$bank_type = $store_info[ 'bank_type' ];
if ($bank_type == 0)
return $this->error([], '当前门店未配置结算账户,无法结算');
$transfer_type = array ( 3 => 'bank', 2 => 'alipay', 1 => 'wechatpay' )[ $store_info[ 'bank_type' ] ];//转账方式
$transfer_type_list = $this->getTransferType($site_id);
$transfer_type_name = $transfer_type_list[ $transfer_type ] ?? '';
switch ( $transfer_type ) {
case 'bank':
$bank_name = $store_info[ 'bank_type_name' ];
$realname = $store_info[ 'bank_user_name' ];//户头
$account_number = $store_info[ 'bank_type_account' ];
break;
case 'alipay':
$realname = $store_info[ 'bank_user_name' ];
$account_number = $store_info[ 'bank_type_account' ];
break;
case 'wechatpay':
$realname = $store_info[ 'bank_user_name' ];
$account_number = $store_info[ 'bank_type_account' ];
break;
}
$data = array (
'site_id' => $site_id,
'withdraw_no' => $this->createWithdrawNo(),
'store_name' => $store_info[ 'store_name' ],
'store_id' => $store_id,
'transfer_type' => $transfer_type,
'transfer_type_name' => $transfer_type_name,
'money' => $money,
'apply_time' => time(),
'status' => 0,
'status_name' => $this->status[ 0 ],
'realname' => $realname ?? '',
'bank_name' => $bank_name ?? '',
'account_number' => $account_number ?? '',
'settlement_type' => $settlement_type,
'settlement_type_name' => $this->settlement_type[ $settlement_type ]
);
model('store_withdraw')->startTrans();
try {
$withdraw_id = model('store_withdraw')->add($data);
//添加转账记录
$pay_transfer_model = new PayTransfer();
$info = model('store_withdraw')->getInfo([['withdraw_id', '=', $withdraw_id]]);
$pay_transfer_model->add([
"out_trade_no" => $info[ "withdraw_no" ],
"real_name" => $info[ "realname" ],
"amount" => $info[ "money" ],
"desc" => "门店申请提现",
"transfer_type" => $info[ "transfer_type" ],
"account_number" => $info[ "account_number" ],
"site_id" => $info[ "site_id" ],
"is_weapp" => 0,
"member_id" => $info[ 'store_id' ],
'from_type' => 'store_withdraw',
"relate_tag" => $info['withdraw_id'],
]);
//如果是申请提现,也同时生成一个结算单
if($settlement_type == 'apply'){
$start_time = 0;
$last_withdraw_info = model('store_withdraw')->getFirstData([['store_id', '=', $store_id]], '*', 'apply_time desc');
if(!empty($last_withdraw_info)) $start_time = $last_withdraw_info['apply_time'];
$settlement_model = new Settlement();
$settlement_model->addSettlement([
'site_id' => $site_id,
'store_id' => $store_id,
'start_time' => $start_time,
'end_time' => $data['apply_time'],
'store_commission' => $money,
'withdraw_id' => $withdraw_id,
]);
}
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => -$money,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '门店申请结算,结算金额' . $money,
'related_id' => $withdraw_id
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//增加结算中余额
model('store')->setInc([ [ 'store_id', '=', $store_id ] ], 'account_apply', $money);
//结算无需审核的话,就直接结算
if ($is_audit == 0) {
$result = $this->agree([ 'withdraw_id' => $withdraw_id, 'site_id' => $site_id, 'store_id' => $store_id ]);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
}
model('store_withdraw')->commit();
return $this->success($withdraw_id);
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 同意结算申请
* @param $condition
*/
public function agree($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ],
[ 'status', '=', 0 ]
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error(null, '未获取到提现信息');
$data = array (
'status' => 1,
'status_name' => $this->status[ 1 ],
'audit_time' => time(),
);
model('store_withdraw')->update($data, $condition);
$store_config_model = new Config();
$config = $store_config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ];
if($config['is_auto_transfer'] == 1){
$this->transfer($info['withdraw_id']);
}
return $this->success();
}
/**
* 拒绝结算申请
* @param $condition
*/
public function refuse($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ],
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error(null, '提现信息不存在');
if(!in_array($info['status'], [self::STATUS_WAIT_AUDIT, self::STATUS_WAIT_TRANSFER])){
return $this->error(null, '提现状态有误');
}
model('store_withdraw')->startTrans();
try {
$data = array (
'status' => -1,
'status_name' => $this->status[ -1 ],
'refuse_reason' => $params[ 'refuse_reason' ],
'audit_time' => time(),
);
model('store_withdraw')->update($data, $condition);
$money = $info[ 'money' ];
//增加现金余额
$store_id = $info[ 'store_id' ];
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => $money,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '门店结算拒绝,返还金额' . $money.',拒绝原因:'.$params[ 'refuse_reason' ],
'related_id' => $withdraw_id
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//减少结算中余额
model('store')->setDec([ [ 'store_id', '=', $store_id ] ], 'account_apply', $money);
//如果关联结算要把订单的结算状态和结算id清除
$settlement_model = new Settlement();
$settlement_model->refuseWithdraw($withdraw_id);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 结算转账完成
* @param $id
*/
public function transferFinish($params)
{
$site_id = $params[ 'site_id' ];
$store_id = $params[ 'store_id' ] ?? 0;
$withdraw_id = $params[ 'withdraw_id' ];
$condition = array (
[ 'site_id', '=', $site_id ],
[ 'withdraw_id', '=', $withdraw_id ]
);
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error();
$transfer_time = time();
model('store_withdraw')->startTrans();
try {
$store_id = $info[ 'store_id' ];
$data = [
'status' => 2,
'status_name' => $this->status[ 2 ],
'transfer_time' => $transfer_time,
'voucher_img' => $params[ 'voucher_img' ] ?? '',
'voucher_desc' => $params[ 'voucher_desc' ] ?? ''
];
model('store_withdraw')->update($data, $condition);
$store_condition = array (
[ 'store_id', '=', $store_id ]
);
$money = $info[ 'money' ];
//增加已结算余额
model('store')->setInc($store_condition, 'account_withdraw', $money);
//减少结算中余额
model('store')->setDec($store_condition, 'account_apply', $money);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error('', $e->getMessage());
}
}
/**
* 转账
* @param $condition
*/
public function transfer($withdraw_id)
{
$info_result = $this->getStoreWithdrawInfo([ [ "withdraw_id", "=", $withdraw_id ] ]);
if (empty($info_result[ "data" ]))
return $this->error(null, '提现信息有误');
$info = $info_result[ "data" ];
if (!in_array($info[ "transfer_type" ], [ "wechatpay", "alipay" ]))
return $this->error('', "当前提现方式不支持在线转账");
$pay_transfer_model = new PayTransfer();
$transfer_res = $pay_transfer_model->transfer('store_withdraw', $info['withdraw_id']);
return $transfer_res;
}
/**
* 转账结果通知
* @param $param
* @return array
* @throws \think\db\exception\DbException
*/
public function transferNotify($param)
{
$withdraw_id = $param['relate_tag'];
$site_id = $param['site_id'];
$withdraw_info = $this->getStoreWithdrawInfo([
['withdraw_id', '=', $withdraw_id ],
['site_id', '=', $site_id],
], "*")['data'];
if(empty($withdraw_info)){
return $this->error(null, '提现信息有误');
}
//成功的处理
switch($param['status']){
case PayTransfer::STATUS_IN_PROCESS:
return $this->transferInProcess([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
]);
break;
case PayTransfer::STATUS_SUCCESS:
return $this->transferFinish([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
]);
break;
case PayTransfer::STATUS_FAIL:
$resp_data = json_decode($param['resp_data'], true);
$fail_reason = $resp_data['fail_reason'] ?? '';
return $this->transferFail([
'withdraw_id' => $withdraw_info['withdraw_id'],
'site_id' => $withdraw_info['site_id'],
'fail_reason' => $fail_reason,
]);
break;
default:
return $this->error(null, '转账结果状态有误');
}
}
/**
* 转账失败
* @param $param
* @return array
*/
public function transferFail($param)
{
$withdraw_id = $param['withdraw_id'];
$site_id = $param['site_id'];
$fail_reason = $param['fail_reason'];
$condition = [
[ 'withdraw_id', '=', $withdraw_id ],
[ 'site_id', '=', $site_id ],
[ 'status', 'in', [self::STATUS_WAIT_TRANSFER, self::STATUS_IN_PROCESS] ],
];
$info = $this->getStoreWithdrawInfo($condition)['data'];
if (empty($info)) return $this->error(null, '提现信息有误');
model('store_withdraw')->startTrans();
try {
$data = [
'status' => self::STATUS_FAIL,
'status_name' => $this->status[self::STATUS_FAIL],
'refuse_reason' => $fail_reason,
];
model("store_withdraw")->update($data, $condition);
//增加现金余额
$store_id = $info[ 'store_id' ];
$store_account_model = new StoreAccount();
$store_account_data = array (
'account_data' => $info['money'],
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'withdraw',
'remark' => '提现失败返还,原因:'.$fail_reason,
'related_id' => $info['withdraw_id']
);
$result = $store_account_model->addStoreAccount($store_account_data);
if ($result[ 'code' ] < 0) {
model('store_withdraw')->rollback();
return $result;
}
//减少结算中余额
model('store')->setDec([ [ 'store_id', '=', $store_id ] ], 'account_apply', $info['money']);
model('store_withdraw')->commit();
return $this->success();
} catch (\Exception $e) {
model('store_withdraw')->rollback();
return $this->error(['file' => $e->getFile(), 'line' => $e->getLine(), 'message' => $e->getMessage()], $e->getMessage());
}
}
/**
* 转账中
* @param $param
* @return array
*/
public function transferInProcess($param)
{
$withdraw_id = $param['withdraw_id'];
$site_id = $param['site_id'];
$condition = [
[ 'withdraw_id', '=', $withdraw_id ],
[ 'site_id', '=', $site_id ],
[ 'status', '=', self::STATUS_WAIT_TRANSFER ]
];
$info = $this->getStoreWithdrawInfo($condition)['data'];
if (empty($info)) return $this->error(null, '提现信息有误');
model("store_withdraw")->update([
'status' => self::STATUS_IN_PROCESS,
'status_name' => $this->status[self::STATUS_IN_PROCESS],
], [['withdraw_id', '=', $withdraw_id]]);
return $this->success();
}
/**
* 转账方式
*/
public function getTransferType($site_id = 0)
{
$pay_model = new Pay();
$transfer_type_list = $pay_model->getTransferType($site_id);
$data = [];
foreach ($transfer_type_list as $k => $v) {
$data[ $k ] = $v;
}
return $data;
}
/**
* 结算
* @param $condition
*/
public function getStoreWithdrawInfo($condition, $field = '*')
{
$info = model('store_withdraw')->getInfo($condition, $field);
return $this->success($info);
}
/**
* 结算记录
* @param $condition
* @param string $field
*/
public function getStoreWithdrawList($condition = [], $field = '*', $order = '', $limit = null)
{
$list = model('store_withdraw')->getList($condition, $field, $order, '', '', '', $limit);
return $this->success($list);
}
/**
* 获取账户分页列表
* @param array $condition
* @param int $page
* @param int $page_size
* @param string $order
* @param string $field
* @return array|\multitype
*/
public function getStoreWithdrawPageList($condition = [], $page = 1, $page_size = PAGE_LIST_ROWS, $order = 'apply_time desc', $field = '*', $alias = 'a', $join = [])
{
$list = model('store_withdraw')->pageList($condition, $field, $order, $page, $page_size, $alias, $join);
return $this->success($list);
}
/**
* 获取结算单数量
* @param $condition
* @return array
*/
public function getStoreWithdrawCount($condition)
{
$data = model('store_withdraw')->getCount($condition);
return $this->success($data);
}
/**
* 获取结算单字段总和
* @param $condition
* @return array
*/
public function getStoreWithdrawSum($condition, $field)
{
$data = model('store_withdraw')->getSum($condition, $field);
return $this->success($data);
}
/**
* 结算详情
* @param $params
* @return array
*/
public function detail($params)
{
$withdraw_id = $params[ 'withdraw_id' ];
$site_id = $params[ 'site_id' ] ?? 0;
$store_id = $params[ 'store_id' ] ?? 0;
$condition = array (
[ 'withdraw_id', '=', $withdraw_id ]
);
if ($site_id > 0) {
$condition[] = [ 'site_id', '=', $site_id ];
}
if ($store_id > 0) {
$condition[] = [ 'store_id', '=', $store_id ];
}
$info = model('store_withdraw')->getInfo($condition);
if (empty($info))
return $this->error();
$settlement_type = $info[ 'settlement_type' ];
//非主动申请的结算,会有周期性结算信息
if ($settlement_type != 'apply') {
$settlement_model = new Settlement();
$settlement_condition = array (
[ 'withdraw_id', '=', $withdraw_id ]
);
$settlement_info = $settlement_model->getSettlementInfo($settlement_condition)[ 'data' ] ?? [];
if (!empty($settlement_info))
$info[ 'settlement_info' ] = $settlement_info;
}
return $this->success($info);
}
/**
* 翻译
* @param $data
*/
// public function translate($data){
// $settlement_type = $data['settlement_type'] ?? '';
// if(!empty($settlement_type)){
// $data['settlement_type_name'] = $settlement_type;
// }
//
// return $data;
// }
/**
* 结算流水号
*/
private function createWithdrawNo()
{
$cache = Cache::get('store_withdraw_no' . time());
if (empty($cache)) {
Cache::set('niutk' . time(), 1000);
$cache = Cache::get('store_withdraw_no' . time());
} else {
$cache = $cache + 1;
Cache::set('store_withdraw_no' . time(), $cache);
}
$no = date('Ymdhis', time()) . rand(1000, 9999) . $cache;
return $no;
}
/**
* 转账检测
* @param $id
*/
public function transferCheck($id)
{
$info_result = $this->getStoreWithdrawInfo([ [ "withdraw_id", "=", $id ] ]);
if (empty($info_result["data"]))
return $this->error(null, '提现信息缺失');
$info = $info_result["data"];
if(!in_array($info["transfer_type"], ["wechatpay","alipay"]))
return $this->error('', "当前提现方式不支持在线转账");
if($info['status'] != self::STATUS_WAIT_TRANSFER){
return $this->error('', "当前提现单非待转账状态");
}
return $this->success();
}
}

View File

@@ -0,0 +1,368 @@
<?php
/**
* Niushop商城系统 - 团队十年电商经验汇集巨献!
* =========================================================
* Copy right 2019-2029 杭州牛之云科技有限公司, 保留所有权利。
* ----------------------------------------------
* 官方网址: https://www.niushop.com
* =========================================================
*/
namespace addon\store\model\settlement;
use app\model\BaseModel;
use addon\store\model\Config;
use addon\store\model\StoreAccount;
use app\model\store\Store;
use think\facade\Log;
class OrderSettlement extends BaseModel
{
const ACTION_EXECUTE = 1;
const ACTION_RETURN_DATA = 2;
/**
* 门店订单分成计算
* @param $data
* @param $action
*/
public function orderSettlementAccount($data, $action = self::ACTION_EXECUTE)
{
$order_id = $data[ 'order_id' ];
$order_info = model('order')->getInfo([ [ 'order_id', '=', $order_id ] ]);
if(empty($order_info)) return null;
if(empty($order_info['store_id'])) return null;
$store_id = $order_info[ 'store_id' ];
$site_id = $order_info[ 'site_id' ];
$config_model = new Config();
$config = $config_model->getStoreWithdrawConfig($site_id)[ 'data' ][ 'value' ] ?? [];
$is_settlement = $config[ 'is_settlement' ];//结算模式 todo 系统配置的门店计算开关是否会对门店结算开关造成影响
if ($is_settlement > 0) {
$store_model = new Store();
$store_condition = array (
[ 'site_id', '=', $site_id ],
[ 'store_id', '=', $store_id ]
);
$store_info = $store_model->getStoreInfoByAccount($store_condition)[ 'data' ] ?? [];
$is_settlement = $store_info[ 'is_settlement' ];
if ($is_settlement > 0) {
$settlement_pay_type = $config['settlement_pay_type'] ?? [];//参与结算的支付方式
if(!empty($settlement_pay_type)){
if(in_array($order_info['pay_type'], explode(',', $settlement_pay_type))){
$store_settlement_rate = $store_info[ 'settlement_rate' ];
if ($store_settlement_rate > 0) {
$settlement_rate = $store_settlement_rate;
} else {
$settlement_rate = $config[ 'settlement_rate' ];
}
if ($settlement_rate > 0) {
$settlement_rate_calc = $settlement_rate / 100;//计算门店抽成比例
$order_money = $order_info[ 'order_money' ];
//todo 可能还有退款
$settlement_cost = $config[ 'settlement_cost' ];
$settlement_cost_array = explode(',', $settlement_cost);
//总金额
$base_money = $order_money;
$remark = '订单编号:'.$order_info['order_no'].';结算佣金=([订单金额]'.$base_money;
//退款金额
if(!empty($order_info[ 'refund_money' ])){
$base_money -= $order_info[ 'refund_money' ];//todo 这儿涉及到一个问题,退款的金额里面包含一部分余额,可能结算金额不太一致
if($order_info['refund_money'] > 0){
$remark .= '-[退款金额]'.$order_info['refund_money'];
}
}
//余额抵扣
if($order_info['balance_money'] > 0){
$balance_money = $order_info[ 'balance_money' ];
$base_money -= $balance_money;
$remark .= '-[余额抵扣]'.$order_info['balance_money'];
}
//分销佣金
if (in_array('fenxiao_commission', $settlement_cost_array)) {
$commission = $order_info[ 'commission' ];
$base_money -= $commission;
if($order_info['commission'] > 0){
$remark .= '-[分销佣金]'.$order_info['commission'].')';
}
}
//积分抵扣
if (in_array('point', $settlement_cost_array)) {
$point_money = $order_info[ 'point_money' ];
$base_money += $point_money;
if($order_info['point_money'] > 0){
$remark .= '+[积分抵扣]'.$order_info['point_money'];
}
}
//优惠券比较特殊, 不过不扣除要价格优惠券抵扣金额加回去
if (!in_array('coupon', $settlement_cost_array)) {
$coupon_money = $order_info[ 'coupon_money' ];
$base_money += $coupon_money;
if($order_info['coupon_money'] > 0){
$remark .= '+[优惠券券金额]'.$order_info['coupon_money'];
}
}
if ($base_money > 0) {
$store_commission_rate = $settlement_rate;
$store_commission = round($base_money * $settlement_rate_calc, 2);
$remark .= ')*'.$store_commission_rate.'%='.$store_commission;
$order_data = array (
'store_commission_rate' => $store_commission_rate,
'store_commission' => $store_commission
);
$order_condition = array (
[ 'order_id', '=', $order_id ]
);
model('order')->update($order_data, $order_condition);
$store_account_model = new StoreAccount();
//门店账户金额增加
$store_account_data = array (
'account_data' => $store_commission,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'order',
'remark' => $remark,
'related_id' => $order_id
);
if($action == self::ACTION_EXECUTE){
//防止重复添加
$store_account_info = $store_account_model->getStoreAccountInfo([['from_type', '=', 'order'], ['related_id', '=', $order_id]])['data'];
if(empty($store_account_info)){
$store_account_model->addStoreAccount($store_account_data);
}
}else{
return $store_account_data;
}
}
}
}
}
}
}
}
/**
*
* @param $data
* @param $action
*/
public function orderRefundSettlementAccount($data, $action = self::ACTION_EXECUTE)
{
// $order_goods_id = $data[ 'order_goods_id' ];
$order_goods_info = $data['order_goods_info'];
if (empty($order_goods_info))
return null;
$order_goods_id = $order_goods_info['order_goods_id'];
// $order_id = $order_goods_info[ 'order_id' ];
$order_info = $data['order_info'];
if (empty($order_info))
return null;
$site_id = $order_info[ 'site_id' ];
$store_id = $order_info[ 'store_id' ];
$order_scene = $order_info[ 'order_scene' ];
//只有收银台订单会有这种情况
if ($store_id == 0 || $order_scene != 'cashier')
return null;
$refund_money = sprintf("%.2f", $data['refund_money']);
$order_money = $order_info[ 'order_money' ];
if($order_money <= 0)
return null;
if($refund_money <= 0){
return null;
}
$store_commission = $order_info[ 'store_commission' ];
$refund_store_commission = round($store_commission * ( $refund_money / $order_money ), 2);
$store_account_model = new StoreAccount();
//门店账户金额减少
$store_account_data = array (
'account_data' => -$refund_store_commission,
'site_id' => $site_id,
'store_id' => $store_id,
'from_type' => 'refund',
'remark' => "订单编号:{$order_info['order_no']};退款编号:{$order_goods_info['refund_no']};扣除结算佣金=[结算佣金]{$store_commission}*([退款金额]{$refund_money}/[订单金额]{$order_money})={$refund_store_commission}",
'related_id' => $order_goods_id,
'is_limit' => 0
);
if($action == self::ACTION_EXECUTE){
$store_account_model->addStoreAccount($store_account_data);
}else{
return $store_account_data;
}
}
/**
* 矫正任务
* @param array $param
* @return array
*/
public function correctStoreAccountTask($param = [])
{
$last_order_id = $param['last_order_id'] ?? 0;
$store_id = $param['store_id'] ?? 0;
$start_time = time();
$max_exec_time = 50;
$res_list = [];
$is_end = false;
while (true){
if(time() - $start_time > $max_exec_time){
break;
}
$order_info = model('order')->getFirstData([
['order_id', '>', $last_order_id],
['store_id', '=', $store_id],
]);
if(empty($order_info)){
$is_end = true;
break;
}
$res = $this->correctStoreAccount($order_info);
if(!empty($res)) $res_list[$order_info['order_id']] = $res;
$last_order_id = $order_info['order_id'];
}
$account = model('store_account')->getSum([['store_id', '=', $store_id]], 'account_data');
model('store')->update(['account' => $account], [['store_id', '=', $store_id]]);
return [
'res_list' => $res_list,
'last_order_id' => $last_order_id,
'is_end' => $is_end,
'account' => $account,
];
}
/**
* 矫正方法
* @param $order_info
* @return array
*/
public function correctStoreAccount($order_info)
{
$deal_res = [];
$store_account_model = new StoreAccount();
$from_type_list = $store_account_model->from_type;
//矫正退款总额
$order_goods_list = model('order_goods')->getList([
['order_id', '=', $order_info['order_id']],
]);
$refund_money = 0;
foreach($order_goods_list as $order_goods){
if(in_array($order_goods['refund_status'], [3,-3])){
$refund_money += $order_goods['refund_real_money'] + $order_goods['shop_active_refund_money'];
}
}
if($order_info['refund_money'] != $refund_money){
model('order')->update(['refund_money' => $refund_money], [['order_id', '=', $order_info['order_id']]]);
$deal_res[] = "矫正退款总额,{$order_info['refund_money']}=>$refund_money";
}
//清空数据
model('store_account')->delete([['from_type', '=', 'order'], ['related_id', '=', $order_info['order_id']]]);
if(!empty($order_goods_list)){
model('store_account')->delete([['from_type', '=', 'refund'], ['related_id', 'in', array_column($order_goods_list, 'order_goods_id')]]);
}
//重新计算
if($order_info['order_status'] == 10){
$store_account_data = $this->orderSettlementAccount(['order_id' => $order_info['order_id']], self::ACTION_RETURN_DATA);
if(!empty($store_account_data)){
$store_account_data['from_type_name'] = $from_type_list['order']['type_name'];
$store_account_data['create_time'] = time();
model('store_account')->add($store_account_data);
$deal_res[] = $store_account_data['remark'];
}
}
if(!empty($deal_res)){
Log::write('订单结算数据矫正:order_id=>'.$order_info['order_id']);
Log::write($deal_res);
}
return $deal_res;
}
public function findStoreAccountErrorDataTask($param)
{
$last_order_id = $param['last_order_id'] ?? 0;
$store_id = $param['store_id'] ?? 0;
$start_time = time();
$max_exec_time = 50;
$res_list = [];
$is_end = false;
while (true){
if(time() - $start_time > $max_exec_time){
break;
}
$order_info = model('order')->getFirstData([
['order_id', '>', $last_order_id],
['store_id', '=', $store_id],
]);
if(empty($order_info)){
$is_end = true;
break;
}
$res = $this->findStoreAccountErrorData($order_info);
if(!empty($res)) $res_list[$order_info['order_id']] = $res;
$last_order_id = $order_info['order_id'];
}
return [
'res_list' => $res_list,
'last_order_id' => $last_order_id,
'is_end' => $is_end,
];
}
public function findStoreAccountErrorData($order_info)
{
$deal_res = [];
//矫正退款总额
$order_goods_list = model('order_goods')->getList([
['order_id', '=', $order_info['order_id']],
]);
$refund_money = 0;
foreach($order_goods_list as $order_goods){
if(in_array($order_goods['refund_status'], [3,-3])){
$refund_money += $order_goods['refund_real_money'] + $order_goods['shop_active_refund_money'];
}
}
if($order_info['refund_money'] != $refund_money){
model('order')->update(['refund_money' => $refund_money], [['order_id', '=', $order_info['order_id']]]);
$deal_res[] = "矫正退款总额,{$order_info['refund_money']}=>$refund_money";
}
//比对数据库数据和计算数据
$order_goods_ids = join(',', array_column($order_goods_list, 'order_goods_id'));
if(empty($order_goods_ids)) $order_goods_ids = '0';
$store_account_list = model('store_account')->getList([
['', 'exp', \think\facade\Db::raw("(from_type = 'order' and related_id = {$order_info['order_id']}) or (from_type = 'refund' and related_id in ({$order_goods_ids}))")],
]);
$db_store_account = array_sum(array_column($store_account_list, 'account_data'));
if($order_info['order_status'] == 10){
$store_account_data = $this->orderSettlementAccount(['order_id' => $order_info['order_id']], self::ACTION_RETURN_DATA);
}
$calc_store_account = $store_account_data['account_data'] ?? 0;
if($db_store_account <> $calc_store_account){
$deal_res[] = [
"数据库记录:{$db_store_account},实时计算:{$calc_store_account}",
$store_account_list,
];
}
return $deal_res;
}
}