Skip to content

Commit fbb97b2

Browse files
authored
Merge pull request #8084 from bakaphp/fix/handle-rate-limit
fix: handle reate limit
2 parents d4cef2c + 824e11d commit fbb97b2

File tree

4 files changed

+121
-24
lines changed

4 files changed

+121
-24
lines changed

src/Domains/Connectors/NetSuite/Actions/SyncNetSuiteCustomerItemsListAction.php

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,29 +26,20 @@
2626
*/
2727
class SyncNetSuiteCustomerItemsListAction
2828
{
29-
protected NetSuiteCustomerService $service;
30-
protected NetSuiteProductService $productService;
29+
protected ?NetSuiteCustomerService $service = null;
30+
protected ?NetSuiteProductService $productService = null;
3131

3232
public function __construct(
3333
protected AppInterface $app,
3434
protected CompanyInterface $mainAppCompany,
35-
protected CompanyInterface $buyerCompany
35+
protected CompanyInterface $buyerCompany,
36+
protected array $itemPricingList = []
3637
) {
37-
$this->service = new NetSuiteCustomerService($app, $mainAppCompany);
38-
$this->productService = new NetSuiteProductService($app, $mainAppCompany);
3938
}
4039

4140
public function execute(): array
4241
{
43-
$customerId = $this->buyerCompany->get(CustomFieldEnum::NET_SUITE_CUSTOMER_ID->value);
44-
45-
if (! $customerId) {
46-
throw new Exception('Company not linked to NetSuite');
47-
}
48-
49-
$customerInfo = $this->service->getCustomerById($customerId);
50-
51-
$listOrProductVariantsBarCodeIds = $customerInfo->itemPricingList?->itemPricing ?? [];
42+
$listOrProductVariantsBarCodeIds = $this->getItemPricingList();
5243

5344
$createNewChannel = new CreateChannel(
5445
new Channels(
@@ -65,15 +56,18 @@ public function execute(): array
6556

6657
$totalProcessed = 0;
6758
$missed = [];
68-
foreach ($listOrProductVariantsBarCodeIds as $bardCodeId) {
69-
$config = null;
59+
60+
foreach ($listOrProductVariantsBarCodeIds as $item) {
61+
$barcode = $item['barcode'];
62+
$price = $item['price'];
63+
7064
$variant = Variants::fromApp($this->app)
7165
->fromCompany($this->mainAppCompany)
72-
->where('barcode', $bardCodeId->item->name)
66+
->where('barcode', $barcode)
7367
->first();
7468

7569
if (! $variant) {
76-
$missed[] = $bardCodeId->item->name;
70+
$missed[] = $barcode;
7771

7872
continue;
7973
}
@@ -84,10 +78,10 @@ public function execute(): array
8478
$variantWarehouse,
8579
$channel,
8680
VariantChannel::from([
87-
'price' => $bardCodeId->price,
88-
'discounted_price' => $bardCodeId->price,
89-
'is_published' => $bardCodeId->price > 0,
90-
'config' => $config ?? null,
81+
'price' => $price,
82+
'discounted_price' => $price,
83+
'is_published' => $price > 0,
84+
'config' => null,
9185
])
9286
);
9387
$addVariantToChannel->execute();
@@ -104,4 +98,28 @@ public function execute(): array
10498
'products_not_found' => $missed,
10599
];
106100
}
101+
102+
protected function getItemPricingList(): array
103+
{
104+
if (! empty($this->itemPricingList)) {
105+
return collect($this->itemPricingList)->map(fn (array $item) => [
106+
'barcode' => $item['item_display'] ?? '',
107+
'price' => (float) ($item['price'] ?? 0),
108+
])->all();
109+
}
110+
111+
$customerId = $this->buyerCompany->get(CustomFieldEnum::NET_SUITE_CUSTOMER_ID->value);
112+
113+
if (! $customerId) {
114+
throw new Exception('Company not linked to NetSuite');
115+
}
116+
117+
$this->service = new NetSuiteCustomerService($this->app, $this->mainAppCompany);
118+
$customerInfo = $this->service->getCustomerById($customerId);
119+
120+
return collect($customerInfo->itemPricingList?->itemPricing ?? [])->map(fn ($item) => [
121+
'barcode' => $item->item->name ?? '',
122+
'price' => (float) ($item->price ?? 0),
123+
])->all();
124+
}
107125
}

src/Domains/Connectors/NetSuite/Webhooks/ProcessNetSuiteCompanyCustomerWebhookJob.php

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,16 @@ public function execute(): array
5757
if ($isCompany && $mainCompanyId) {
5858
$mainCompany = Companies::getById($mainCompanyId);
5959

60+
$itemList = collect($payload['sublists']['itempricing'] ?? [])
61+
->filter(fn ($value, $key) => is_string($key) && str_starts_with($key, 'line'))
62+
->values()
63+
->all();
64+
6065
$syncNetSuiteCustomerWithCompany = new SyncNetSuiteCustomerItemsListAction(
6166
$this->receiver->app,
6267
$mainCompany,
63-
$company
68+
$company,
69+
$itemList
6470
);
6571
$syncNetSuiteCustomerWithCompany->execute();
6672

src/Domains/Connectors/NetSuite/Workflow/PushOrderToNetsuiteActivity.php

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
use Kanvas\Workflow\Enums\IntegrationsEnum;
1313
use Kanvas\Workflow\KanvasActivity;
1414
use Override;
15+
use RuntimeException;
1516

1617
class PushOrderToNetsuiteActivity extends KanvasActivity implements WorkflowActivityInterface
1718
{
@@ -20,7 +21,7 @@ public function execute(Model $order, AppInterface $app, array $params): array
2021
{
2122
$this->overwriteAppService($app);
2223

23-
return $this->executeIntegration(
24+
$response = $this->executeIntegration(
2425
entity: $order,
2526
app: $app,
2627
integration: IntegrationsEnum::NETSUITE,
@@ -50,5 +51,31 @@ public function execute(Model $order, AppInterface $app, array $params): array
5051
},
5152
company: $order->company,
5253
);
54+
55+
if ($this->isNetSuiteRateLimitError($response['error'] ?? $response['message'] ?? '')) {
56+
throw new RuntimeException('NetSuite concurrent request limit exceeded. Retrying...');
57+
}
58+
59+
return $response;
60+
}
61+
62+
protected function isNetSuiteRateLimitError(string $message): bool
63+
{
64+
$rateLimitPatterns = [
65+
'concurrent request limit exceeded',
66+
'request blocked',
67+
'rate limit',
68+
'too many requests',
69+
];
70+
71+
$lowerMessage = strtolower($message);
72+
73+
foreach ($rateLimitPatterns as $pattern) {
74+
if (str_contains($lowerMessage, $pattern)) {
75+
return true;
76+
}
77+
}
78+
79+
return false;
5380
}
5481
}

tests/Connectors/Integration/NetSuite/CustomerTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,52 @@ public function testSyncNetSuiteCustomerItemsList()
151151
$this->assertIsArray($result);
152152
}
153153

154+
public function testSyncNetSuiteCustomerItemsListFromPayload()
155+
{
156+
$app = app(Apps::class);
157+
$company = Companies::first();
158+
159+
$buyerCompany = Companies::factory()->create();
160+
$buyerCompany->associateUser($company->user, true, $buyerCompany->defaultBranch);
161+
162+
$itemPricingList = [
163+
[
164+
'item' => '492',
165+
'level' => '-1',
166+
'price' => '3.14',
167+
'sys_id' => '20859524076679148',
168+
'currency' => '1',
169+
'item_display' => '4511338002063',
170+
'sys_parentid' => '20859524069940939',
171+
'currency_display' => 'USD',
172+
],
173+
[
174+
'item' => '494',
175+
'level' => '-1',
176+
'price' => '3.14',
177+
'sys_id' => '20859524076673028',
178+
'currency' => '1',
179+
'item_display' => '4511338002087',
180+
'sys_parentid' => '20859524069940939',
181+
'currency_display' => 'USD',
182+
],
183+
];
184+
185+
$syncCustomerItemsList = new SyncNetSuiteCustomerItemsListAction(
186+
$app,
187+
$company,
188+
$buyerCompany,
189+
$itemPricingList
190+
);
191+
$result = $syncCustomerItemsList->execute();
192+
193+
$this->assertIsArray($result);
194+
$this->assertArrayHasKey('channel', $result);
195+
$this->assertArrayHasKey('total_processed', $result);
196+
$this->assertArrayHasKey('products_not_found', $result);
197+
$this->assertEquals(2, $result['total_items']);
198+
}
199+
154200
public function testGetCustomerInvoiceByNumber()
155201
{
156202
$company = Companies::first();

0 commit comments

Comments
 (0)