SaveFulfillment.php 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. <?php
  2. declare(strict_types=1);
  3. namespace app\miniapi\service\driver;
  4. use app\miniapi\exception\ApiException;
  5. use app\miniapi\http\Fields;
  6. use app\miniapi\http\Input;
  7. use app\miniapi\model\MiniPhoto;
  8. use app\miniapi\model\MiniTaskRecord;
  9. use plugin\saiadmin\app\model\water\WaterDelivery;
  10. use plugin\saiadmin\app\service\WaterFulfillment;
  11. /** Draft and final submission share validation; only final submission settles the delivery. */
  12. final class SaveFulfillment extends InTransitAction
  13. {
  14. public function __construct(private readonly bool $complete)
  15. {
  16. }
  17. public function fields(): array
  18. {
  19. return [
  20. 'request_key',
  21. 'accepted_qty',
  22. 'empty_returned',
  23. 'receiver',
  24. 'reason',
  25. 'photo_ids',
  26. 'confirmed',
  27. ];
  28. }
  29. protected function handle(WaterDelivery $task, array $input, int $user): array
  30. {
  31. $id = (int) $task->id;
  32. $data = [
  33. 'accepted_qty' => Input::integer($input['accepted_qty'] ?? null, 'accepted_qty', 0, (int) $task->quantity),
  34. 'empty_returned' => Input::integer($input['empty_returned'] ?? 0, 'empty_returned', 0, 10000000),
  35. 'receiver' => Fields::text($input, 'receiver', 60),
  36. 'reason' => Fields::text($input, 'reason', 255, false),
  37. 'photo_ids' => $this->photos($id, $input['photo_ids'] ?? []),
  38. ];
  39. if (!$this->complete) {
  40. MiniTaskRecord::recordEvent($id, $user, 'draft', $data);
  41. return [
  42. 'id' => $id,
  43. 'saved' => true,
  44. ];
  45. }
  46. if (($input['confirmed'] ?? false) !== true || !$data['photo_ids']) {
  47. throw new ApiException(42201, '请上传履约照片并确认实际数量', 422);
  48. }
  49. if (!MiniTaskRecord::query()->where([
  50. 'delivery_id' => $id,
  51. 'kind' => 'checkin',
  52. 'user_id' => $user,
  53. ])->exists()) {
  54. throw new ApiException(40902, '请先完成到达打卡', 409);
  55. }
  56. $result = (new WaterFulfillment())->receive(['id' => $id] + $data, 0);
  57. MiniTaskRecord::recordEvent($id, $user, 'complete', $data);
  58. return $result;
  59. }
  60. private function photos(int $delivery, mixed $photos): array
  61. {
  62. if (!is_array($photos) || !array_is_list($photos) || count($photos) > 4) {
  63. throw new ApiException(42201, '履约照片最多4张', 422);
  64. }
  65. $photos = array_map(fn ($id) => Input::integer($id, 'photo_ids', 1, 2147483647), $photos);
  66. if (count(array_unique($photos)) !== count($photos)
  67. || MiniPhoto::query()->where('delivery_id', $delivery)->whereIn('id', $photos)->count() !== count($photos)) {
  68. throw new ApiException(42201, '照片不属于当前配送任务', 422);
  69. }
  70. return $photos;
  71. }
  72. }