diff --git a/app/Criteria/WhereUpdatedAfter.php b/app/Criteria/WhereUpdatedAfter.php new file mode 100644 index 000000000..6729e725a --- /dev/null +++ b/app/Criteria/WhereUpdatedAfter.php @@ -0,0 +1,14 @@ +where('updated_at', '>=', $this->value); + } +} diff --git a/app/Criteria/WhereUpdatedBefore.php b/app/Criteria/WhereUpdatedBefore.php new file mode 100644 index 000000000..46f11e4d3 --- /dev/null +++ b/app/Criteria/WhereUpdatedBefore.php @@ -0,0 +1,19 @@ +value, ':')) { + $this->value = Str::before($this->value, 'T') . 'T23:59:59'; + } + + return $query->where('updated_at', '<=', $this->value); + } +} diff --git a/app/Http/Requests/OrderIndexRequest.php b/app/Http/Requests/OrderIndexRequest.php index b6f4ed194..9ea835b6f 100644 --- a/app/Http/Requests/OrderIndexRequest.php +++ b/app/Http/Requests/OrderIndexRequest.php @@ -20,6 +20,8 @@ public function rules(): array 'paid' => ['sometimes', 'boolean'], 'from' => ['nullable', 'date'], 'to' => ['nullable', 'date', 'after_or_equal:from'], + 'updated_from' => ['nullable', 'date'], + 'updated_to' => ['nullable', 'date', 'after_or_equal:updated_from'], 'metadata' => ['nullable', 'array'], 'metadata_private' => ['nullable', 'array'], 'ids' => ['array'], diff --git a/app/Models/Order.php b/app/Models/Order.php index 300ff7ba0..fb4ce4895 100644 --- a/app/Models/Order.php +++ b/app/Models/Order.php @@ -11,6 +11,8 @@ use App\Criteria\WhereCreatedBefore; use App\Criteria\WhereHasStatusHidden; use App\Criteria\WhereInIds; +use App\Criteria\WhereUpdatedAfter; +use App\Criteria\WhereUpdatedBefore; use App\Enums\PaymentStatus; use App\Enums\ShippingType; use App\Models\Contracts\SortableContract; @@ -88,6 +90,8 @@ final class Order extends Model implements SortableContract 'paid', 'from' => WhereCreatedAfter::class, 'to' => WhereCreatedBefore::class, + 'updated_from' => WhereUpdatedAfter::class, + 'updated_to' => WhereUpdatedBefore::class, 'metadata' => MetadataSearch::class, 'metadata_private' => MetadataPrivateSearch::class, 'ids' => WhereInIds::class, diff --git a/docs/paths/Orders.yml b/docs/paths/Orders.yml index 114b50d08..5bc6feeb3 100644 --- a/docs/paths/Orders.yml +++ b/docs/paths/Orders.yml @@ -47,6 +47,18 @@ Orders: schema: type: string format: date-time + - name: updated_from + in: query + description: 'Date datetime updated from' + schema: + type: string + format: date-time + - name: updated_to + in: query + description: 'Date datetime updated to' + schema: + type: string + format: date-time - name: metadata in: query description: search by metadata diff --git a/tests/Feature/OrderTest.php b/tests/Feature/OrderTest.php index 118865483..3ec959053 100644 --- a/tests/Feature/OrderTest.php +++ b/tests/Feature/OrderTest.php @@ -545,6 +545,42 @@ public function testIndexSearchByFrom($user): void ->assertJsonFragment(['id' => $order2->getKey()]); } + /** + * @dataProvider authProvider + */ + public function testIndexSearchByUpdatedFrom($user): void + { + $this->{$user}->givePermissionTo('orders.show'); + + $status = Status::factory()->create(); + + $from = $this->order->updated_at; + + Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => Carbon::yesterday(), + ])->create(); + + $order2 = Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => Carbon::tomorrow(), + ])->create(); + + $response = $this + ->actingAs($this->{$user}) + ->json('GET', '/orders', [ + 'updated_from' => $from, + ]); + + $response + ->assertOk() + ->assertJsonCount(2, 'data') + ->assertJsonFragment(['id' => $this->order->getKey()]) + ->assertJsonFragment(['id' => $order2->getKey()]); + } + /** * @dataProvider authProvider */ @@ -581,6 +617,42 @@ public function testIndexSearchByTo($user): void ->assertJsonFragment(['id' => $order1->getKey()]); } + /** + * @dataProvider authProvider + */ + public function testIndexSearchByUpdatedTo($user): void + { + $this->{$user}->givePermissionTo('orders.show'); + + $status = Status::factory()->create(); + + $to = $this->order->updated_at; + + $order1 = Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => Carbon::yesterday(), + ])->create(); + + Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => Carbon::tomorrow(), + ])->create(); + + $response = $this + ->actingAs($this->{$user}) + ->json('GET', '/orders', [ + 'updated_to' => $to, + ]); + + $response + ->assertOk() + ->assertJsonCount(2, 'data') + ->assertJsonFragment(['id' => $this->order->getKey()]) + ->assertJsonFragment(['id' => $order1->getKey()]); + } + /** * @dataProvider authProvider */ @@ -628,6 +700,53 @@ public function testIndexSearchByFromTo($user): void ->assertJsonFragment(['id' => $order->getKey()]); } + /** + * @dataProvider authProvider + */ + public function testIndexSearchByUpdatedFromUpdatedTo($user): void + { + $this->{$user}->givePermissionTo('orders.show'); + + $status = Status::factory()->create(); + + $now = Carbon::create(2020, 02, 02, 10); + + $this->travelTo($now); + + $from = $now->subHour(); + $to = $now->addHour(); + + Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => $now->subDay(), + ])->create(); + + Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => $now->addDay(), + ])->create(); + + $order = Order::factory([ + 'shipping_method_id' => $this->shippingMethod->getKey(), + 'status_id' => $status->getKey(), + 'updated_at' => $now->subMinutes(30), + ])->create(); + + $response = $this + ->actingAs($this->{$user}) + ->json('GET', '/orders', [ + 'updated_from' => $from, + 'updated_to' => $to, + ]); + + $response + ->assertOk() + ->assertJsonCount(1, 'data') + ->assertJsonFragment(['id' => $order->getKey()]); + } + /** * @dataProvider authProvider */