260 lines
8.9 KiB
PHP
260 lines
8.9 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Dealer;
|
|
|
|
use App\Enums\DealerDeliveryBillStatus;
|
|
use App\Enums\DealerWalletAction;
|
|
use App\Enums\PayWay;
|
|
use App\Enums\WxpayTradeType;
|
|
use App\Exceptions\BizException;
|
|
use App\Models\DealerDeliveryBill;
|
|
use App\Models\DealerDeliveryProduct;
|
|
use App\Models\DealerOrder;
|
|
use App\Models\DealerOrderProduct;
|
|
use App\Models\DealerProduct;
|
|
use App\Models\DealerUserProduct;
|
|
use App\Models\DealerUserProductLog;
|
|
use App\Models\PayLog;
|
|
use App\Models\User;
|
|
use App\Services\Payment\WxpayService;
|
|
use App\Services\PayService;
|
|
use Illuminate\Support\Arr;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class DealerDeliveryBillService
|
|
{
|
|
/**
|
|
* 创建提货单
|
|
*
|
|
* @param \App\Models\User $user
|
|
* @param array $deliveryProducts
|
|
* @param array $consignee
|
|
* @param string|null $remark
|
|
* @param int|null $DealerOrder
|
|
* @return \App\Models\DealerDeliveryBill
|
|
*/
|
|
public function create(User $user, array $deliveryProducts, array $consignee, ?string $remark = null, ?DealerOrder $dealerOrder = null): DealerDeliveryBill
|
|
{
|
|
$deliveryProductIds = Arr::pluck($deliveryProducts, 'id');
|
|
|
|
// 批零商品
|
|
$products = DealerProduct::findMany($deliveryProductIds);
|
|
|
|
if (count($deliveryProducts) !== $products->count()) {
|
|
throw new BizException('提货单商品已丢失');
|
|
}
|
|
|
|
// 经销商的商品库存
|
|
$dealerProducts = $user->dealerProducts()
|
|
->whereIn('product_id', $deliveryProductIds)
|
|
->get();
|
|
|
|
// 创建提货单
|
|
$deliveryBill = DealerDeliveryBill::create([
|
|
'user_id' => $user->id,
|
|
'shipping_fee' => app_settings('dealer.delivery_bill_shipping_fee', 0),
|
|
'remark' => $remark,
|
|
'consignee_name' => $consignee['name'],
|
|
'consignee_telephone' => $consignee['telephone'],
|
|
'consignee_zone' => $consignee['zone'],
|
|
'consignee_address' => $consignee['address'],
|
|
'status' => DealerDeliveryBillStatus::Pending,
|
|
'order_id' => $dealerOrder?->id,
|
|
]);
|
|
|
|
$mapProducts = $products->keyBy('id');
|
|
$mapDealerProducts = $dealerProducts->keyBy('product_id');
|
|
|
|
$dealerProductLogs = [];
|
|
$deliveryBillProducts = [];
|
|
|
|
foreach ($deliveryProducts as $deliveryProduct) {
|
|
$product = Arr::get($mapProducts, $deliveryProduct['id']);
|
|
$dealerProduct = Arr::get($mapDealerProducts, $product->id);
|
|
|
|
if ($dealerProduct?->deposit_stock < $deliveryProduct['qty']) {
|
|
throw new BizException("{$product->name} 库存不足");
|
|
}
|
|
|
|
$dealerProduct->decrement('deposit_stock', $deliveryProduct['qty']);
|
|
|
|
$dealerProductLogs[] = [
|
|
'user_id' => $dealerProduct->user_id,
|
|
'product_id' => $dealerProduct->product_id,
|
|
'type' => DealerUserProductLog::TYPE_DEPOSIT_TRANSFER_OUT,
|
|
'qty' => $deliveryProduct['qty'],
|
|
'remark' => "提货单【{$deliveryBill->sn}】",
|
|
'is_deposit' => true,
|
|
'created_at' => $deliveryBill->created_at,
|
|
'updated_at' => $deliveryBill->updated_at,
|
|
];
|
|
|
|
$deliveryBillProducts[] = [
|
|
'delivery_bill_id' => $deliveryBill->id,
|
|
'product_id' => $product->id,
|
|
'qty' => $deliveryProduct['qty'],
|
|
'created_at' => $deliveryBill->created_at,
|
|
'updated_at' => $deliveryBill->updated_at,
|
|
];
|
|
}
|
|
|
|
DealerUserProductLog::insert($dealerProductLogs);
|
|
|
|
DealerDeliveryProduct::insert($deliveryBillProducts);
|
|
|
|
return $deliveryBill;
|
|
}
|
|
|
|
/**
|
|
* 提货单付款
|
|
*
|
|
* @param \App\Models\DealerDeliveryBill $deliveryBill
|
|
* @param \App\Enums\PayWay $payWay
|
|
* @return array
|
|
*
|
|
* @throws \App\Exceptions\BizException
|
|
*/
|
|
public function pay(DealerDeliveryBill $deliveryBill, PayWay $payWay): array
|
|
{
|
|
if (! $deliveryBill->isPending()) {
|
|
throw new BizException('提货单状态不是待付款');
|
|
}
|
|
|
|
$method = match ($payWay) {
|
|
PayWay::Wallet => 'payUsingWallet',
|
|
PayWay::WxpayH5, PayWay::WxpayJsApi => 'payUsingWxpay',
|
|
default => 'payUsingDefault',
|
|
};
|
|
|
|
if (! method_exists($this, $method)) {
|
|
throw new BizException('交易非法');
|
|
}
|
|
|
|
$payLog = $deliveryBill->payLogs()->create([
|
|
'pay_way' => $payWay,
|
|
]);
|
|
|
|
return [
|
|
'pay_way' => $payLog->pay_way,
|
|
'data' => $this->{$method}($deliveryBill, $payLog),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* 取消提货单
|
|
*
|
|
* @param DealerDeliveryBill $deliveryBill
|
|
* @return void
|
|
*/
|
|
public function cancel(DealerDeliveryBill $deliveryBill)
|
|
{
|
|
if (! $deliveryBill->isPending()) {
|
|
throw new BizException('提货单状态不是待付款');
|
|
}
|
|
|
|
$deliveryBill->update([
|
|
'status' => DealerDeliveryBillStatus::Cancelled,
|
|
]);
|
|
|
|
$dealerProductLogs = [];
|
|
|
|
foreach ($deliveryBill->deliveryProducts as $deliveryProduct) {
|
|
DealerUserProduct::where([
|
|
'user_id' => $deliveryBill->user_id,
|
|
'product_id' => $deliveryProduct->product_id,
|
|
])->update([
|
|
'deposit_stock' => DB::raw("deposit_stock + {$deliveryProduct->qty}"),
|
|
]);
|
|
|
|
$dealerProductLogs[] = [
|
|
'user_id' => $deliveryBill->user_id,
|
|
'product_id' => $deliveryProduct->product_id,
|
|
'type' => DealerUserProductLog::TYPE_DEPOSIT_TRANSFER_REVOKE,
|
|
'qty' => $deliveryProduct->qty,
|
|
'remark' => "撤销提货单【{$deliveryBill->sn}】",
|
|
'is_deposit' => true,
|
|
'created_at' => $deliveryBill->updated_at,
|
|
'updated_at' => $deliveryBill->updated_at,
|
|
];
|
|
}
|
|
|
|
//撤回已发货的本地库存
|
|
if ($deliveryBill->order_id) {
|
|
$dealerOrder = DealerOrder::with('products')->find($deliveryBill->order_id);
|
|
foreach ($dealerOrder->products as $product) {
|
|
if ($product->qty > 0 && $dealerOrder->local_status == 1) {
|
|
$userProduct = $dealerOrder->consignor->dealerProducts()->firstOrCreate([
|
|
'product_id'=> $product->product_id,
|
|
]);
|
|
$userProduct->increment('stock', $product->qty);
|
|
$dealerProductLogs[] = [
|
|
'user_id' => $dealerOrder->consignor_id,
|
|
'product_id' => $product->product_id,
|
|
'type' => DealerUserProductLog::TYPE_ORDER_OUT_REVOKE,
|
|
'qty' => $product->qty,
|
|
'remark' => "撤销订单发货【{$dealerOrder->sn}】",
|
|
'is_deposit' => false,
|
|
'created_at' => $deliveryBill->updated_at,
|
|
'updated_at' => $deliveryBill->updated_at,
|
|
];
|
|
}
|
|
//将云仓发货的数量挪回来
|
|
DealerOrderProduct::where('id', $product->id)->update([
|
|
'qty' => $product->qty + $product->deposit_qty,
|
|
'deposit_qty' => 0,
|
|
]);
|
|
}
|
|
$dealerOrder->update([
|
|
'local_status'=>0,
|
|
]);
|
|
}
|
|
|
|
DealerUserProductLog::insert($dealerProductLogs);
|
|
}
|
|
|
|
/**
|
|
* 使用余额支付
|
|
*
|
|
* @param \App\Models\DealerDeliveryBill $deliveryBill
|
|
* @param \App\Models\PayLog $payLog
|
|
* @return void
|
|
*/
|
|
protected function payUsingWallet(DealerDeliveryBill $deliveryBill, PayLog $payLog)
|
|
{
|
|
(new WalletService())->changeBalance(
|
|
$deliveryBill->user,
|
|
bcmul($deliveryBill->shipping_fee, '-1', 2),
|
|
DealerWalletAction::DeliveryBillPaid,
|
|
"提货单号:{$deliveryBill->sn}",
|
|
$deliveryBill
|
|
);
|
|
|
|
(new PayService())->handleSuccess($payLog, [
|
|
'pay_at' => now(),
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* 使用微信支付
|
|
*
|
|
* @param \App\Models\DealerDeliveryBill $deliveryBill
|
|
* @param \App\Models\PayLog $payLog
|
|
* @return array
|
|
*/
|
|
protected function payUsingWxpay(DealerDeliveryBill $deliveryBill, PayLog $payLog): array
|
|
{
|
|
if (is_null($tradeType = WxpayTradeType::tryFromPayWay($payLog->pay_way))) {
|
|
throw new BizException('支付方式 非法');
|
|
}
|
|
|
|
$params = [
|
|
'body' => app_settings('app.app_name').'-批零订单',
|
|
'out_trade_no' => $payLog->pay_sn,
|
|
'total_fee' => bcmul($deliveryBill->shipping_fee, '100'),
|
|
'trade_type' => $tradeType->value,
|
|
];
|
|
|
|
return (new WxpayService())->pay($params, 'yzk_h5');
|
|
}
|
|
}
|