Exclude cancelled and fully refunded Etsy orders from dispatch lists
Deploy HickLab3D Dashboard / Deploy to production (push) Successful in 28s
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:
co-authored by
Claude Sonnet 5.5
parent
8a281b5b61
commit
504a867351
+22
-4
@@ -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
|
||||
{
|
||||
return $this->cache->remember('etsy.receipts.'.$connection->shop_id, 300, fn (): array => $this->get(
|
||||
'application/shops/'.$connection->shop_id.'/receipts', $this->accessToken($connection), [
|
||||
'was_paid' => 'true', 'was_shipped' => 'false', 'limit' => 20,
|
||||
]), $fresh);
|
||||
return $this->cache->remember('etsy.receipts.'.$connection->shop_id, 300, function () use ($connection): array {
|
||||
$response = $this->get('application/shops/'.$connection->shop_id.'/receipts', $this->accessToken($connection), [
|
||||
'was_paid' => 'true', 'was_shipped' => 'false', 'limit' => 50,
|
||||
]);
|
||||
$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
|
||||
|
||||
@@ -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]));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user