| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- <?php
- declare(strict_types=1);
- namespace plugin\saiadmin\app\service\promotion;
- use app\miniapi\model\MiniCheckout;
- use plugin\saiadmin\app\model\water\WaterAccount;
- use plugin\saiadmin\app\model\water\WaterDelivery;
- use plugin\saiadmin\app\model\water\WaterEnterprise;
- use plugin\saiadmin\app\model\water\WaterLedger;
- use plugin\saiadmin\app\model\water\WaterModel;
- use plugin\saiadmin\app\model\water\WaterPromotionReferral;
- use plugin\saiadmin\app\model\water\WaterSku;
- use plugin\saiadmin\app\service\WaterBusiness;
- use plugin\saiadmin\exception\ApiException;
- final class PromotionRewards
- {
- public static function delivery(WaterPromotionReferral $referral): ?WaterDelivery
- {
- $order = $referral->order;
- if (!$order) {
- return null;
- }
- return WaterDelivery::query()->where('enterprise_id', $referral->invited_id)->where('sku_id', $order->sku_id)
- ->where('id', '>', (int) $referral->delivery_floor_id)
- ->where('status', 'completed')->where('delivered_qty', '>', 0)
- ->where('created_at', '>=', $order->created_at)->where('received_at', '>=', $order->created_at)
- ->orderBy('received_at')->orderBy('id')->first();
- }
- public function review(array $input, int $actor): array
- {
- $id = WaterBusiness::positive($input['id'] ?? null, '奖励记录');
- $revision = WaterBusiness::positive($input['revision'] ?? null, '记录版本');
- $decision = $input['decision'] ?? '';
- $note = $input['note'] ?? '';
- if (!in_array($decision, ['issued', 'rejected'], true) || !is_string($note)
- || trim($note) === '' || mb_strlen($note) > 500) {
- throw new ApiException('请选择审核结果并填写1至500字的核实说明');
- }
- if ($decision === 'issued' && ($input['receipt_refund_checked'] ?? null) !== true) {
- throw new ApiException('请先核实真实收款、无退款及重复客户情况');
- }
- $note = trim($note);
- return WaterModel::transaction(function () use ($id, $revision, $decision, $note, $actor) {
- $snapshot = WaterPromotionReferral::query()->find($id);
- if (!$snapshot) {
- throw new ApiException('奖励记录不存在');
- }
- // Match receipt/inventory lock order: SKU -> enterprise(s) -> referral -> account.
- $sku = WaterSku::query()->lockForUpdate()->find($snapshot->sku_id);
- $ids = [(int) $snapshot->inviter_id, (int) $snapshot->invited_id];
- sort($ids, SORT_NUMERIC);
- $companies = WaterEnterprise::query()->whereIn('id', $ids)->orderBy('id')->lockForUpdate()->get();
- $row = WaterPromotionReferral::query()->lockForUpdate()->find($id);
- if (!$row) {
- throw new ApiException('奖励记录不存在');
- }
- if (in_array($row->status, ['issued', 'rejected'], true)) {
- if ($row->status === $decision && $row->review_note === $note) {
- return ['id' => $id, 'status' => $row->status, 'replayed' => true];
- }
- throw new ApiException('奖励已经处理,请刷新查看');
- }
- if ($row->status !== 'pending' || (int) $row->revision !== $revision) {
- throw new ApiException('尚未首购或记录已更新,请刷新查看');
- }
- $delivery = null;
- if ($decision === 'issued') {
- if (!$sku || (int) $sku->status !== 1 || $companies->count() !== 2
- || $companies->contains(fn ($company) => (int) $company->status !== 1)) {
- throw new ApiException('企业或赠水规格已停用或不存在');
- }
- $order = $row->order;
- $checkout = $row->checkout_id ? MiniCheckout::query()->find($row->checkout_id) : null;
- $amount = (int) $row->purchase_amount_cents;
- if (!$order || (int) $order->enterprise_id !== (int) $row->invited_id
- || $amount < max(1, (int) $row->min_amount_cents)
- || str_starts_with($order->reference, 'TEST-') || str_contains($order->package_name, '测试')) {
- throw new ApiException('首购收款记录不符合奖励条件');
- }
- if ($row->checkout_id) {
- if (!$checkout || $checkout->status !== 'paid' || (int) $checkout->enterprise_id !== (int) $row->invited_id
- || (int) $checkout->amount_cents !== $amount || !str_starts_with($order->reference, $checkout->code . '-')) {
- throw new ApiException('首购结算记录不符合奖励条件');
- }
- } elseif ((int) $order->amount_cents !== $amount) {
- throw new ApiException('首购金额已发生变化,不能发放奖励');
- }
- $delivery = self::delivery($row);
- if (!$delivery) {
- throw new ApiException('首购后尚无对应规格的有效完整签收');
- }
- $account = WaterAccount::query()->where('enterprise_id', $row->inviter_id)
- ->where('sku_id', $row->sku_id)->lockForUpdate()->first();
- if (!$account) {
- $account = WaterAccount::query()->create([
- 'enterprise_id' => $row->inviter_id, 'sku_id' => $row->sku_id,
- 'updated_at' => date('Y-m-d H:i:s'),
- ]);
- $account->refresh();
- }
- $account->entitlement = (int) $account->entitlement + (int) $row->quantity;
- $account->updated_at = date('Y-m-d H:i:s');
- $account->save();
- }
- $row->fill([
- 'status' => $decision, 'reviewed_by' => $actor, 'reviewed_at' => date('Y-m-d H:i:s'),
- 'review_note' => $note, 'delivery_id' => $delivery?->id, 'revision' => $revision + 1,
- ])->save();
- WaterLedger::query()->create([
- 'kind' => $decision === 'issued' ? 'promotion_reward' : 'promotion_reject',
- 'created_by' => $actor, 'sku_id' => $row->sku_id, 'enterprise_id' => $row->inviter_id,
- 'quantity' => $decision === 'issued' ? (int) $row->quantity : 0,
- 'reference' => 'promotion:' . $id,
- 'note' => '邀请企业#' . $row->invited_id . ',首购#' . $row->order_id . ',' . $note,
- 'created_at' => date('Y-m-d H:i:s'),
- ]);
- return ['id' => $id, 'status' => $decision];
- });
- }
- }
|