Commit ea6c7efb by yink

feat: 新增支付记录功能并优化订单管理

- 添加支付记录控制器及路由
- 优化订单管理界面,增加支付类型、积分抵扣等字段
- 新增核销码生成功能并保存二维码路径
- 在订单分账逻辑中添加日志记录及异常处理
parent d75710c0
......@@ -99,6 +99,50 @@ protected function grid()
$filter->panel();
$filter->like('order.order_sn', '订单号')->width(3);
$filter->like('users.phone', '下单会员手机号')->width(3);
// 添加商家筛选
$filter->where('merchant_id', function ($query) {
$query->whereHas('order', function ($q) {
$q->where('merchant_id', $this->input);
});
}, '商家')->select(Merchant::pluck('name', 'id'))->width(3);
// 添加员工筛选
$filter->where('staff_id', function ($query) {
$query->whereHas('order', function ($q) {
$q->where('staff_id', $this->input);
});
}, '员工')->select(StoreAdminUsers::pluck('name', 'id'))->width(3);
// 添加时间范围快捷筛选
$filter->scope('today', '今日')->whereDate('created_at', date('Y-m-d'));
$filter->scope('month', '本月')->whereMonth('created_at', date('m'));
$filter->scope('quarter', '本季度')->where(function ($query) {
$month = date('m');
$year = date('Y');
if ($month >= 1 && $month <= 3) {
// 第一季度 (1-3月)
$start = date('Y-m-d', strtotime('first day of January'));
$end = date('Y-m-d', strtotime('last day of March'));
} elseif ($month >= 4 && $month <= 6) {
// 第二季度 (4-6月)
$start = date('Y-m-d', strtotime('first day of April'));
$end = date('Y-m-d', strtotime('last day of June'));
} elseif ($month >= 7 && $month <= 9) {
// 第三季度 (7-9月)
$start = date('Y-m-d', strtotime('first day of July'));
$end = date('Y-m-d', strtotime('last day of September'));
} else {
// 第四季度 (10-12月)
$start = date('Y-m-d', strtotime('first day of October'));
$end = date('Y-m-d', strtotime('last day of December'));
}
$query->whereBetween('created_at', [$start, $end]);
});
$filter->scope('year', '本年')->whereYear('created_at', date('Y'));
$filter->between('created_at', '创建时间')->datetime()->width(4);
});
......@@ -106,7 +150,7 @@ protected function grid()
//先注释,目前没有手动分账金额给平台说法
//先注释,目前没有手动分账金额给平台的功能
// $grid->actions(function (Grid\Displayers\Actions $actions) {
// //分账给平台
// if ($actions->row->is_div == 0 && in_array($actions->row->sh_type, [1, 2])) {
......
<?php
namespace App\Admin\Controllers;
use App\Models\PaymentRecord;
use App\Models\TotalOrder;
use App\Models\User;
use Dcat\Admin\Form;
use Dcat\Admin\Grid;
use Dcat\Admin\Show;
use Dcat\Admin\Http\Controllers\AdminController;
class PaymentRecordController extends AdminController
{
/**
* Make a grid builder.
*
* @return Grid
*/
protected function grid()
{
return Grid::make(PaymentRecord::with(['user']), function (Grid $grid) {
$grid->addTableClass(['table-text-center']);
$grid->model()->orderBy('created_at','DESC');
$grid->column('id')->sortable();
$grid->column('order_sn','订单号');
$grid->column('other_order','外部订单ID');
$grid->column('payment_id','支付ID')->limit(10);
$grid->column('party_order_id','支付订单ID')->limit(10);
$grid->column('money','金额');
$grid->column('uid','用户ID');
$grid->column('user.name','用户');
$grid->column('created_at','支付时间');
$grid->disableViewButton();
$grid->disableEditButton();
$grid->disableCreateButton();
$grid->disableActions();
$grid->simplePaginate();
$grid->disableFilterButton();
$grid->quickSearch('user.name')->placeholder('搜索用户');
$grid->filter(function (Grid\Filter $filter) {
$filter->equal('id');
});
});
}
/**
* Make a show builder.
*
* @param mixed $id
*
* @return Show
*/
protected function detail($id)
{
return Show::make($id, new PaymentRecord(), function (Show $show) {
$show->field('id');
$show->field('pay_type');
$show->field('order_id');
$show->field('other_order');
$show->field('money');
$show->field('uid');
$show->field('created_at');
$show->field('updated_at');
});
}
/**
* Make a form builder.
*
* @return Form
*/
protected function form()
{
return Form::make(new PaymentRecord(), function (Form $form) {
$form->display('id');
$form->text('pay_type');
$form->text('order_id');
$form->text('other_order');
$form->text('money');
$form->text('uid');
$form->display('created_at');
$form->display('updated_at');
});
}
}
......@@ -53,11 +53,41 @@ protected function grid()
2 => '解冻中',
3 => '冻结中'
]);
$filter->between('created_at', '创建时间')->datetime();
// 添加时间范围筛选
$filter->scope('today', '今日')->whereDate('created_at', date('Y-m-d'));
$filter->scope('month', '本月')->whereMonth('created_at', date('m'));
$filter->scope('quarter', '本季度')->where(function ($query) {
$month = date('m');
$year = date('Y');
if ($month >= 1 && $month <= 3) {
// 第一季度 (1-3月)
$start = date('Y-m-d', strtotime('first day of January'));
$end = date('Y-m-d', strtotime('last day of March'));
} elseif ($month >= 4 && $month <= 6) {
// 第二季度 (4-6月)
$start = date('Y-m-d', strtotime('first day of April'));
$end = date('Y-m-d', strtotime('last day of June'));
} elseif ($month >= 7 && $month <= 9) {
// 第三季度 (7-9月)
$start = date('Y-m-d', strtotime('first day of July'));
$end = date('Y-m-d', strtotime('last day of September'));
} else {
// 第四季度 (10-12月)
$start = date('Y-m-d', strtotime('first day of October'));
$end = date('Y-m-d', strtotime('last day of December'));
}
$query->whereBetween('created_at', [$start, $end]);
});
$filter->scope('year', '本年')->whereYear('created_at', date('Y'));
$filter->between('created_at', '自定义时间范围')->datetime();
});
// 添加导出按钮
$grid->export()->filename('积分记录-'.date('YmdHis'))->rows(function ($rows) {
$grid->export()->filename('积分记录-' . date('YmdHis'))->rows(function ($rows) {
foreach ($rows as $index => &$row) {
// 处理增减类别
$row['change_type'] = $row['change_type'] == 1 ? '增加' : '减少';
......@@ -141,4 +171,50 @@ protected function form()
//$form->display('created_at', '创建时间');
});
}
/**
* 积分统计方法
*
* @param string $period 统计周期 (day/month/quarter/year)
* @param string|null $date 指定日期 (格式: Y-m-d)
* @return array
*/
public function pointStatistics($period = 'day', $date = null)
{
$query = UserPointChangeRec::query();
switch ($period) {
case 'day':
$query->whereDate('created_at', $date ?? date('Y-m-d'));
break;
case 'month':
$query->whereMonth('created_at', $date ?? date('m'));
break;
case 'quarter':
$quarter = $date ? ceil(date('m', strtotime($date)) / 3) : ceil(date('m') / 3);
$startMonth = (($quarter - 1) * 3) + 1;
$endMonth = $quarter * 3;
$startDate = date('Y-m-d', strtotime(date('Y') . '-' . $startMonth . '-01'));
$endDate = date('Y-m-t', strtotime(date('Y') . '-' . $endMonth . '-01'));
$query->whereBetween('created_at', [$startDate, $endDate]);
break;
case 'year':
$query->whereYear('created_at', $date ?? date('Y'));
break;
}
$increase = (clone $query)->where('change_type', 1)->sum('point_amount');
$decrease = (clone $query)->where('change_type', 0)->sum('point_amount');
return [
'period' => $period,
'date' => $date ?? ($period === 'day' ? date('Y-m-d') : ($period === 'month' ? date('Y-m') : ($period === 'quarter' ? 'Q' . ceil(date('m') / 3) : date('Y')))),
'increase' => $increase,
'decrease' => $decrease,
'net_change' => $increase - $decrease
];
}
}
......@@ -6,6 +6,7 @@
use Dcat\Admin\Widgets\Form;
use Dcat\Admin\Contracts\LazyRenderable;
use Dcat\Admin\Traits\LazyWidget;
use App\Http\Controllers\Api\SystemSettingController;
......@@ -31,6 +32,11 @@ public function handle(array $input)
$order->order_status = 2; //待领取状态
$order->verification_code = $code;
$order->verifi_code_at = date("Y-m-d H:i:s");
//生成核销码二维码,保存路径到数据库,后面直接返回前端
$path = SystemSettingController::GetQrCode($order->verification_code);
$order->verification_code_img = $path;
$order->save();
return $this->response()->success('确认成功')->refresh();
}
......
......@@ -93,5 +93,6 @@
$router->resource('user-point-change-rec', 'UserPointChangeRecController'); //积分记录
$router->resource('payment-record', 'PaymentRecordController'); //支付记录
});
......@@ -10,6 +10,9 @@
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use App\Models\Adapay;
use App\Models\OrderInfo;
use App\Models\UserPointChangeRec;
class LoginController extends BaseController
{
......@@ -219,4 +222,20 @@ public function simulateLogin(Request $request)
'Authorization' => $accessToken
]);
}
public function test(Request $request)
{
$id = $request->id ?? 7;
$orderObj= OrderInfo::find($id);
userPointChangeRec::pointUnfreezeimg($orderObj);
return $this->JsonResponse(['id' => $id]);
}
}
......@@ -647,6 +647,18 @@ public function scanCodeVerifi(Request $request)
$orderObj->verifier_id = $verObj->id;
$orderObj->verifier = $verObj->name;
$orderObj->verification_at = date("Y-m-d H:i:s");
//查询是否纯积分抵扣订单
if ($orderObj->pay_type == 2) {
//积分抵扣,直接核销退出
Log::add('scanCodeVerifi-point', $orderObj);
$orderObj->save();
Log::add('核销操作', $orderObj->toArray());
return $this->JsonResponse('');
}
//$orderObj->save();
try {
//接入微信小程序发货管理
......
......@@ -143,7 +143,12 @@ public function updateOrderStatusToDiv(Request $request)
foreach ($orderList as $kk => $order) {
$orderObj = OrderInfo::find($order->id);
if (Adapay::handlePaymentConfirmAndDivide($orderObj->order_no, $orderObj->id)) {
if (!$orderObj) {
Log::add('updateOrderStatusToDiv订单不存在:'.$order->id, json_encode($orderObj, JSON_UNESCAPED_UNICODE));
continue;
}
if (Adapay::handlePaymentConfirmAndDivide($orderObj->order_sn, $orderObj->id)) {
$orderObj->is_div = 1;
$orderObj->save();
} else {
......@@ -190,9 +195,9 @@ public static function pointUnfreezeEnd(Request $request)
->get();
if ($records->isEmpty()) {
// Log::add('point_unfreeze_end', [
// 'msg' => '没有找到可完成的解冻积分记录'
// ]);
Log::add('point_unfreeze_end', [
'msg' => '没有找到可完成的解冻积分记录'
]);
return true;
}
......@@ -208,7 +213,6 @@ public static function pointUnfreezeEnd(Request $request)
->where('id', $record->id)
->update([
'point_state' => 1, // 已完成
'updated_at' => date('Y-m-d H:i:s')
]);
// 将积分转入用户账户
......
......@@ -85,6 +85,7 @@ public function qrCode(Request $request)
// 返回二维码图片的Base64编码
//return response()->json(['status' => 'success', 'qrcode' => 'data:image/png;base64,' . base64_encode($qrCode)]);
}
//
public function companyIntro(Request $request)
{
......@@ -123,4 +124,55 @@ public function getBj(Request $request)
return $this->JsonResponse(['bj' => $bj]);
}
//生成二维码-纯函数使用
public static function GetQrCode($code)
{
$writer = new PngWriter();
//$str = "#小程序://留日指南/AYpQ1H8PIFNvUaC";
$qrCode = QrCode::create($code)
->setEncoding(new Encoding('UTF-8'))
->setErrorCorrectionLevel(new ErrorCorrectionLevelLow())
->setSize(300)
->setMargin(10)
->setRoundBlockSizeMode(new RoundBlockSizeModeMargin())
->setForegroundColor(new Color(0, 0, 0))
->setBackgroundColor(new Color(255, 255, 255));
$result = $writer->write($qrCode);
//$dataUri = $result->getDataUri();
// 指定保存路径
$folder_name = "/qrcode/" . date("Ymd", time());
$filename = md5( $code ).date("YmdHis", time()) . ".png";
$savePath = public_path() . "/uploads" . $folder_name . "/";
if (!file_exists($savePath)) {
mkdir($savePath, 0755, true);
}
$result->saveToFile($savePath . $filename);
//加个判断
if (!file_exists($savePath. $filename)) {
Log::add('getQrCode', [
'code' => $code,
'msg' => '二维码生成失败'
]);
return "";
}
$filepath = $folder_name . "/" . $filename;
//$qrCode->writeFile($savePath);
return $filepath;
// 返回二维码图片的Base64编码
//return response()->json(['status' => 'success', 'qrcode' => 'data:image/png;base64,' . base64_encode($qrCode)]);
}
}
......@@ -498,6 +498,14 @@ public static function handlePaymentConfirmAndDivide($order_no, $order_id)
$payment_confirm = new \NwVVVS\AdapaySdk\PaymentConfirm(); //支付确认
//交易记录
$prObj = PaymentRecord::where('order_sn', $order_no)->first();
Log::add('debug', ['order_sn' => $order_no]);
if (!$prObj) {
Log::add('handlePaymentConfirmAndDivide', ['order_sn' => $order_no]);
return false;
}
# 支付确认参数设置
$payment_params = array(
"payment_id" => $prObj->payment_id,
......
......@@ -42,6 +42,7 @@ public static function divide($order_id, $payconfirm_no = '')
$total_amount = 0; //订单商品总价
$merchant_proportion = ''; //佣金比例
$sp_ogid = ''; //参与分佣商品ID
$employeeObj = []; //员工对象;
$commissionPreData = [
'merchant_member_id' => '',
'merchant_amount' => 0,
......@@ -51,7 +52,7 @@ public static function divide($order_id, $payconfirm_no = '')
'employee_amount' => 0,
];
$hfCompanyMObj =[];
$hfCompanyMObj = [];
//商户是否实名
$isMerchantRealName = 0;
if ($merchant_id) {
......@@ -64,18 +65,22 @@ public static function divide($order_id, $payconfirm_no = '')
->where('user_id', $buyer_id)
->first();
$hfEmployeeMObj =[];
$hfEmployeeMObj = [];
//员工是否实名
$isEmployeeRealName = 0;
if ($employee) {
$employeeObj = StoreAdminUsers::find($employee->employee_id);
//打印分账员工
Log::add('divide', "订单ID:{$order_id},分账员工:{$employeeObj->name}");
$hfEmployeeMObj = HfCompanyMember::where('merchant_id', $employeeObj->merchant_id)->first();
$isEmployeeRealName = ($hfEmployeeMObj->status == 'succeeded') ? 1 : 0;
}
$ogList = OrderGoods::where("order_id", $order_id)->get(); //订单商品
$cash_ratio=1;//现金支付比例,默认100%
$cash_ratio = 1; //现金支付比例,默认100%
//判断支付类型,纯现金还是现金+积分,计算订单内商品金额与实付金额比例,最终分佣为实付金额的比例
if ($orderObj->pay_type == 1) { //纯现金支付
$cash_ratio = 1;
......@@ -85,7 +90,7 @@ public static function divide($order_id, $payconfirm_no = '')
->select(DB::raw('SUM(goods_price * goods_number) as total'))
->value('total');
//计算现金支付比例
$cash_ratio =number_format( ($orderObj->order_amount / $orderGoodCash) * 100,4);//保留4位小数
$cash_ratio = number_format(($orderObj->order_amount / $orderGoodCash) * 100, 4); //保留4位小数
}
Log::info("订单ID:{$order_id},支付类型:{$orderObj->pay_type},现金支付比例:{$cash_ratio}");
......@@ -100,13 +105,21 @@ public static function divide($order_id, $payconfirm_no = '')
$sp_ogid = $item->id . ",";
//应该分给商家的金额
$merchant_divide_price = number_format($goods_amount * ($merchant_commission / 100)*$cash_ratio , 2);
$employee_divide_price =0;
$merchant_divide_price = number_format($goods_amount * ($merchant_commission / 100) * $cash_ratio, 2);
$employee_divide_price = 0;
$employee_divide_price_log = $merchant_divide_price;
//应该分给商家的金额
Log::add('divide', "员工分佣:{$employeeObj->commission_rate}");
//员工分佣记录
if ($employee && $employeeObj->commission_rate >= 1 && $employeeObj->commission_rate < 100) {
// 基于商家分到佣金计算员工分佣
//应该分给商家的金额
Log::add('divide', "员工分佣:{$employee}, 员工分佣记录:{$employee_divide_price}, 商户分佣记录:{$merchant_divide_price}");
// 基于商家分到佣金计算员工分佣
$employee_divide_price = number_format($merchant_divide_price * ($employeeObj->commission_rate / 100), 2);
$employeePreData['employee_amount'] += $employee_divide_price;
$employeePreData['employee_member_id'] = $hfEmployeeMObj->member_id;
......@@ -114,23 +127,14 @@ public static function divide($order_id, $payconfirm_no = '')
//商户分佣记录
if ($merchant_id && $merchant_commission >= 1 && $merchant_commission < 100) {
$merchant_divide_price = $merchant_divide_price-$employee_divide_price;
$merchant_divide_price = $merchant_divide_price - $employee_divide_price;
$commissionPreData['merchant_amount'] += $merchant_divide_price;
$commissionPreData['merchant_member_id'] = $hfCompanyMObj->member_id;
// //收益直接到商户账户->【改成实时查询了,不记录总的佣金】
// $merObj = Merchant::find($merchant_id);
// //汇付参数
// $member_id = $hfCompanyMObj->member_id;
// if ($member_id) {
// $merObj->total_revenue += $divide_price;
// $merObj->save();
// }
}
//应该分给商家的金额
Log::add('divide', ",应该分给商家的金额:{$employee_divide_price_log}, 员工分佣记录:{$employee_divide_price}, 商户分佣记录:{$merchant_divide_price}");
}
//商户佣金
......
......@@ -145,4 +145,50 @@ public static function getYearData()
}
return $data;
}
// public static function getOrderTitle($order_sn){
// $order = self::find($order_sn);
// $project = '';
// $service_name =Service::find($order->service_id)->name ?? '';
// $business_name = Business::find($order->business_id)->name ?? '';
// switch ($order->business_id){
// case 1:
// case 2:
// case 4:
// $project = $service_name;
// break;
// case 3:
// $project = $business_name.'('.$service_name.')';
// break;
// case 5:
// case 6:
// $project = $business_name;
// break;
// default:
// $goods_id = StoreOrder::where(['order_id'=>$order_id])->first()->goods_id;
// $goods_name = StoreGood::find($goods_id)->title ??'';
// $project = '商城订单-'.$goods_name;
// }
// return $project;
// }
}
<?php
return [
'labels' => [
'PaymentRecord' => '用户支付记录',
'city' => 'City',
],
'fields' => [
'province_id' => '省份',
'city_id' => '城市',
],
'options' => [],
];
......@@ -28,6 +28,7 @@
//调试路由
Route::post('simulate-login','LoginController@simulateLogin'); //模拟登陆
Route::get('test1','LoginController@test'); //测试内容-什么都测
Route::post('manual-divide','OrderDivideRecordController@manualDivide'); //手动分账【开发手动调接口修正数据】
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment