PromotionPolicy.php 3.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. <?php
  2. declare(strict_types=1);
  3. namespace plugin\saiadmin\app\service\promotion;
  4. use plugin\saiadmin\app\model\water\WaterPromotionSetting;
  5. use plugin\saiadmin\app\model\water\WaterSku;
  6. use plugin\saiadmin\app\model\water\WaterModel;
  7. use plugin\saiadmin\app\model\water\WaterLedger;
  8. use plugin\saiadmin\app\service\WaterBusiness;
  9. use plugin\saiadmin\exception\ApiException;
  10. final class PromotionPolicy
  11. {
  12. public const RULES = '企业管理员在首购前绑定邀请码;每家企业仅绑定一次。首笔非测试购水达到绑定时约定金额,购水后完成对应规格配送签收,经后台核实收款及退款情况后,向邀请企业发放约定水权益。奖励不可提现,不增加实物库存;与代理佣金分别记账。';
  13. public static function current(): array
  14. {
  15. $schema = (new WaterPromotionSetting())->getConnection()->getSchemaBuilder();
  16. $row = $schema->hasTable('sa_water_promotion_setting')
  17. ? WaterPromotionSetting::query()->with('sku')->find(1) : null;
  18. return [
  19. 'initialized' => $row !== null,
  20. 'enabled' => (bool) ($row?->enabled ?? false),
  21. 'sku_id' => $row?->sku_id === null ? null : (int) $row->sku_id,
  22. 'sku_name' => $row?->sku?->name,
  23. 'quantity' => (int) ($row?->quantity ?? 0),
  24. 'min_amount_cents' => (int) ($row?->min_amount_cents ?? 0),
  25. 'revision' => (int) ($row?->revision ?? 0),
  26. 'rules' => self::RULES,
  27. ];
  28. }
  29. public static function save(array $input, int $actor): array
  30. {
  31. if (!is_bool($input['enabled'] ?? null)) {
  32. throw new ApiException('活动开关必须为布尔值');
  33. }
  34. $revision = WaterBusiness::positive($input['revision'] ?? null, '规则版本');
  35. $quantity = WaterBusiness::positive($input['quantity'] ?? null, '奖励桶数', true);
  36. $minimum = WaterBusiness::positive($input['min_amount_cents'] ?? null, '首购门槛', true);
  37. $sku = WaterBusiness::positive($input['sku_id'] ?? 0, '赠水规格', true);
  38. if ($quantity > 10000 || $minimum > 100000000) {
  39. throw new ApiException('奖励最多10000桶,首购门槛最多1000000元');
  40. }
  41. if ($input['enabled'] && (!$quantity || !$sku)) {
  42. throw new ApiException('启用前请选择赠水规格并配置奖励桶数');
  43. }
  44. if ($sku && !WaterSku::query()->where('id', $sku)->where('status', 1)->exists()) {
  45. throw new ApiException('赠水规格不存在或已停用');
  46. }
  47. return WaterModel::transaction(function () use ($input, $actor, $revision, $quantity, $minimum, $sku) {
  48. $row = WaterPromotionSetting::query()->lockForUpdate()->find(1);
  49. if (!$row || (int) $row->revision !== $revision) {
  50. throw new ApiException('规则未初始化或已更新,请刷新后再试');
  51. }
  52. $row->fill([
  53. 'enabled' => $input['enabled'], 'sku_id' => $sku ?: null,
  54. 'quantity' => $quantity, 'min_amount_cents' => $minimum,
  55. 'revision' => $revision + 1, 'updated_by' => $actor,
  56. 'updated_at' => date('Y-m-d H:i:s'),
  57. ])->save();
  58. WaterLedger::query()->create([
  59. 'kind' => 'promotion_policy', 'created_by' => $actor, 'sku_id' => $sku,
  60. 'enterprise_id' => 0, 'quantity' => 0, 'reference' => 'promotion:policy:' . ($revision + 1),
  61. 'note' => json_encode($row->toArray(), JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR),
  62. 'created_at' => date('Y-m-d H:i:s'),
  63. ]);
  64. return self::current();
  65. });
  66. }
  67. }