Exclude cancelled and fully refunded Etsy orders from dispatch lists
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 28s

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
Hickmeister
2026-10-11 20:25:47 +01:00
co-authored by Claude Sonnet 5.5
parent 8a281b5b61
commit 504a867351
2 changed files with 44 additions and 4 deletions
+22 -4
View File
@@ -64,12 +64,30 @@ class Etsy
]); ]);
} }
/** Paid, unshipped orders that still need dispatching, excluding cancelled and fully refunded ones. */
public function receipts(EtsyConnection $connection, bool $fresh = false): array public function receipts(EtsyConnection $connection, bool $fresh = false): array
{ {
return $this->cache->remember('etsy.receipts.'.$connection->shop_id, 300, fn (): array => $this->get( return $this->cache->remember('etsy.receipts.'.$connection->shop_id, 300, function () use ($connection): array {
'application/shops/'.$connection->shop_id.'/receipts', $this->accessToken($connection), [ $response = $this->get('application/shops/'.$connection->shop_id.'/receipts', $this->accessToken($connection), [
'was_paid' => 'true', 'was_shipped' => 'false', 'limit' => 20, 'was_paid' => 'true', 'was_shipped' => 'false', 'limit' => 50,
]), $fresh); ]);
$results = array_values(array_filter($response['results'] ?? [], fn ($receipt): bool => is_array($receipt) && ! $this->isCancelledOrRefunded($receipt)));
return ['count' => count($results), 'results' => $results] + $response;
}, $fresh);
}
/** @param array<string, mixed> $receipt */
public function isCancelledOrRefunded(array $receipt): bool
{
if (in_array(strtolower((string) ($receipt['status'] ?? '')), ['canceled', 'cancelled'], true) || ! empty($receipt['was_canceled'])) {
return true;
}
$total = (float) ($receipt['grandtotal']['amount'] ?? 0) / max(1, (int) ($receipt['grandtotal']['divisor'] ?? 1));
$refunded = collect($receipt['refunds'] ?? [])->sum(fn ($refund): float => (float) ($refund['amount']['amount'] ?? 0) / max(1, (int) ($refund['amount']['divisor'] ?? 1)));
return $total > 0 && $refunded >= $total;
} }
public function listings(EtsyConnection $connection): array public function listings(EtsyConnection $connection): array
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace Tests\Unit;
use App\Services\Etsy;
use App\Services\IntegrationCache;
use Tests\TestCase;
class EtsyReceiptFilterTest extends TestCase
{
public function test_cancelled_and_fully_refunded_orders_are_not_outstanding(): void
{
$etsy = new Etsy(new IntegrationCache);
$total = ['amount' => 1500, 'divisor' => 100, 'currency_code' => 'GBP'];
$this->assertTrue($etsy->isCancelledOrRefunded(['status' => 'Canceled', 'grandtotal' => $total]));
$this->assertTrue($etsy->isCancelledOrRefunded(['status' => 'Paid', 'grandtotal' => $total, 'refunds' => [['amount' => ['amount' => 1500, 'divisor' => 100]]]]));
$this->assertTrue($etsy->isCancelledOrRefunded(['status' => 'Paid', 'grandtotal' => $total, 'refunds' => [['amount' => ['amount' => 1000, 'divisor' => 100]], ['amount' => ['amount' => 500, 'divisor' => 100]]]]));
$this->assertFalse($etsy->isCancelledOrRefunded(['status' => 'Paid', 'grandtotal' => $total, 'refunds' => [['amount' => ['amount' => 500, 'divisor' => 100]]]]));
$this->assertFalse($etsy->isCancelledOrRefunded(['status' => 'Paid', 'grandtotal' => $total]));
}
}