feat: 完善协议管理、师傅资质认证、分账配置并完成测试环境全量部署与同步
这个提交包含在:
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace app\api\controller;
|
||||
|
||||
use app\common\library\CommissionService;
|
||||
use app\common\library\FinanceConfigService;
|
||||
use app\common\library\InvoiceService;
|
||||
use app\common\library\OrderStatus;
|
||||
use think\Db;
|
||||
@@ -645,6 +647,12 @@ class Merchant extends Base
|
||||
$this->error("第 {$rowNo} 条订单计算金额异常");
|
||||
}
|
||||
|
||||
$resolvedProvince = mb_substr(trim((string)(isset($item['province']) && $item['province'] !== '' ? $item['province'] : ($merchant['province'] ?: ''))), 0, 50);
|
||||
$resolvedCity = mb_substr(trim((string)(isset($item['city']) && $item['city'] !== '' ? $item['city'] : ($merchant['city'] ?: ''))), 0, 50);
|
||||
if ($resolvedProvince === '' || $resolvedCity === '') {
|
||||
$this->error("第 {$rowNo} 条订单缺少服务省份或城市信息,请在Excel或表格中填写后再提交");
|
||||
}
|
||||
|
||||
$preparedRows[] = [
|
||||
'svc' => $svc,
|
||||
'service_id' => (int)$svc['id'],
|
||||
@@ -655,8 +663,8 @@ class Merchant extends Base
|
||||
'goods_num' => $goodsNum,
|
||||
'contact' => mb_substr($contact ?: '买家', 0, 50),
|
||||
'mobile' => $mobile,
|
||||
'province' => mb_substr(trim((string)(isset($item['province']) && $item['province'] !== '' ? $item['province'] : ($merchant['province'] ?: '贵州省'))), 0, 50),
|
||||
'city' => mb_substr(trim((string)(isset($item['city']) && $item['city'] !== '' ? $item['city'] : ($merchant['city'] ?: '贵阳市'))), 0, 50),
|
||||
'province' => $resolvedProvince,
|
||||
'city' => $resolvedCity,
|
||||
'district' => mb_substr(trim((string)(isset($item['district']) ? $item['district'] : ($merchant['district'] ?: ''))), 0, 50),
|
||||
'address' => mb_substr($address, 0, 255),
|
||||
'floor' => $floor,
|
||||
@@ -678,6 +686,9 @@ class Merchant extends Base
|
||||
$isMonthly = false;
|
||||
$batchNo = 'MB' . date('YmdHis') . mt_rand(1000, 9999);
|
||||
$now = time();
|
||||
// 事务外一次性预加载生效抽佣规则与默认兜底配置,循环内纯内存匹配快照(零额外 SQL)
|
||||
$activeCommRules = CommissionService::getActiveRules();
|
||||
$commDefaults = FinanceConfigService::getCommissionDefaults();
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
@@ -697,6 +708,13 @@ class Merchant extends Base
|
||||
$calc = $pRow['calc'];
|
||||
$payAmt = round((float)$calc['pay_amount'], 2);
|
||||
$unitPrice = round((float)$calc['base_amount'] / max(1, (int)$pRow['goods_num']), 2);
|
||||
$commMatch = CommissionService::matchOrderSnapshot([
|
||||
'price_type' => 'fixed',
|
||||
'customer_type' => 'merchant',
|
||||
'cat_id' => (int)$pRow['cat_id'],
|
||||
'urgent' => (int)$pRow['urgent'],
|
||||
'order_amount' => $payAmt,
|
||||
], $activeCommRules, $commDefaults);
|
||||
|
||||
$orderId = (int)Db::name('order')->insertGetId([
|
||||
'order_no' => $orderNo,
|
||||
@@ -724,9 +742,11 @@ class Merchant extends Base
|
||||
'floor_amount' => $calc['floor_amount'],
|
||||
'urgent_amount' => $calc['urgent_amount'],
|
||||
'discount_amount' => 0.00,
|
||||
'total_amount' => $calc['total_amount'],
|
||||
'pay_amount' => $payAmt,
|
||||
'status' => $initStatus,
|
||||
'total_amount' => $calc['total_amount'],
|
||||
'pay_amount' => $payAmt,
|
||||
'commission_rate' => $commMatch['commission_rate'],
|
||||
'commission_snapshot' => $commMatch['commission_snapshot'],
|
||||
'status' => $initStatus,
|
||||
'pay_status' => $initPayStatus,
|
||||
'pay_type' => $initPayType,
|
||||
'pay_time' => $initPayTime,
|
||||
@@ -825,124 +845,13 @@ class Merchant extends Base
|
||||
}
|
||||
|
||||
/**
|
||||
* 商户端:预付商家按批次号支付待支付批量订单
|
||||
* 商户端:预付商家按批次号支付待支付批量订单(严禁模拟免付兜底,预付订单须逐笔走真实微信支付)
|
||||
* @ApiMethod (POST)
|
||||
*/
|
||||
public function payBatch()
|
||||
{
|
||||
$merchant = $this->requireMerchant();
|
||||
$batchNo = trim((string)$this->request->post('batch_no', ''));
|
||||
$payType = trim((string)$this->request->post('pay_type', 'wechat'));
|
||||
if ($payType === '') {
|
||||
$payType = 'mock';
|
||||
}
|
||||
if ($batchNo === '') {
|
||||
$this->error('缺少批次号 batch_no');
|
||||
}
|
||||
|
||||
$batchLinks = Db::name('merchant_order')->where('batch_no', $batchNo)->select();
|
||||
if (empty($batchLinks)) {
|
||||
$this->error('批次订单不存在');
|
||||
}
|
||||
$batchOrderIds = [];
|
||||
foreach ($batchLinks as $link) {
|
||||
if ((int)$link['merchant_id'] !== (int)$merchant['id']) {
|
||||
$this->error('无权操作该批次订单', null, 403);
|
||||
}
|
||||
$oid = (int)$link['order_id'];
|
||||
if ($oid > 0) {
|
||||
$batchOrderIds[] = $oid;
|
||||
}
|
||||
}
|
||||
$batchOrderIds = array_values(array_unique($batchOrderIds));
|
||||
if (empty($batchOrderIds)) {
|
||||
$this->error('该批次下无有效订单');
|
||||
}
|
||||
|
||||
$paidCount = 0;
|
||||
$paidTotal = 0.00;
|
||||
$paidOrderIds = [];
|
||||
$now = time();
|
||||
|
||||
Db::startTrans();
|
||||
try {
|
||||
$lockedMerchant = Db::name('merchant')->where('id', (int)$merchant['id'])->lock(true)->find();
|
||||
$orders = Db::name('order')
|
||||
->where('id', 'in', $batchOrderIds)
|
||||
->lock(true)
|
||||
->select();
|
||||
|
||||
foreach ($orders as $ord) {
|
||||
if ((int)$ord['pay_status'] === 1 || (int)$ord['status'] !== OrderStatus::PENDING_PAY) {
|
||||
continue;
|
||||
}
|
||||
$oid = (int)$ord['id'];
|
||||
$amt = round((float)$ord['pay_amount'], 2);
|
||||
$txId = 'BATCH' . date('YmdHis', $now) . mt_rand(1000, 9999);
|
||||
|
||||
Db::name('order')->where('id', $oid)->update([
|
||||
'status' => OrderStatus::PENDING_ACCEPT,
|
||||
'pay_status' => 1,
|
||||
'pay_type' => $payType,
|
||||
'pay_time' => $now,
|
||||
'transaction_id' => $txId,
|
||||
'updatetime' => $now,
|
||||
]);
|
||||
|
||||
$this->addLog($oid, OrderStatus::PENDING_ACCEPT, "企业批次支付完成(批次 {$batchNo}),订单已进入接单大厅", 'user', $this->uid());
|
||||
$paidCount++;
|
||||
$paidTotal = round($paidTotal + $amt, 2);
|
||||
$paidOrderIds[] = $oid;
|
||||
}
|
||||
|
||||
if ($paidCount === 0) {
|
||||
throw new \InvalidArgumentException('该批次没有待支付的订单,请勿重复支付');
|
||||
}
|
||||
|
||||
if ($lockedMerchant) {
|
||||
Db::name('merchant')->where('id', (int)$lockedMerchant['id'])->update([
|
||||
'order_count' => (int)$lockedMerchant['order_count'] + $paidCount,
|
||||
'total_amount' => round((float)$lockedMerchant['total_amount'] + $paidTotal, 2),
|
||||
'updatetime' => $now,
|
||||
]);
|
||||
}
|
||||
|
||||
Db::commit();
|
||||
} catch (\think\exception\HttpResponseException $e) {
|
||||
Db::rollback();
|
||||
throw $e;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
Db::rollback();
|
||||
$this->error($e->getMessage());
|
||||
return;
|
||||
} catch (\Exception $e) {
|
||||
Db::rollback();
|
||||
\think\Log::error('[Merchant::payBatch] ' . $e->getMessage());
|
||||
$this->error('批次支付失败:' . $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$masters = Db::name('master')
|
||||
->where('verify_status', 'pass')
|
||||
->where('work_status', 'on')
|
||||
->where('user_id', '<>', $this->uid())
|
||||
->limit(20)
|
||||
->select();
|
||||
foreach ($masters as $m) {
|
||||
$this->notify('master', (int)$m['id'], '企业批量新工单就绪', "同城有 {$paidCount} 笔企业批量工单进入接单大厅,请尽快前往查看抢单!", 'order', (int)$paidOrderIds[0]);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\think\Log::error('[Merchant::payBatch broadcast] ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$this->success('批次支付成功,订单已进入接单大厅', [
|
||||
'batch_no' => $batchNo,
|
||||
'count' => $paidCount,
|
||||
'paid_count' => $paidCount,
|
||||
'total_amount' => round($paidTotal, 2),
|
||||
'order_ids' => $paidOrderIds,
|
||||
]);
|
||||
$this->requireMerchant();
|
||||
$this->error('系统已全面禁用模拟支付通道,企业预付工单请逐笔使用真实微信支付完成付款(月结授信企业导单时已直接授信进入大厅)');
|
||||
}
|
||||
|
||||
protected function merchantInfo()
|
||||
|
||||
在新工单中引用
屏蔽一个用户