scopeConfig->isSetFlag(self::BASE . 'general/enabled'); } public function getApiBaseUrl(): string { return rtrim((string)$this->scopeConfig->getValue(self::BASE . 'general/api_base_url'), '/'); } public function getAppId(): string { return trim((string)$this->scopeConfig->getValue(self::BASE . 'general/app_id')); } public function getAppSecret(): string { $value = (string)$this->scopeConfig->getValue(self::BASE . 'general/app_secret'); return $value !== '' ? (string)$this->encryptor->decrypt($value) : ''; } public function getPlatformCode(int $websiteId): int { return $this->getStoreMapping($websiteId)['platform_code']; } public function getLingxingStoreId(int $websiteId): string { return $this->getStoreMapping($websiteId)['store_id']; } public function getWarehouseId(int $websiteId = 0): string { return trim((string)$this->getWebsiteValue('general/warehouse_id', $websiteId)); } public function getLogisticsTypeId(int $websiteId = 0): string { return trim((string)$this->getWebsiteValue('general/logistics_type_id', $websiteId)); } /** @return string[] */ public function getEligibleStatuses(): array { $value = (string)$this->scopeConfig->getValue(self::BASE . 'general/eligible_statuses'); return array_values(array_filter(array_map('trim', explode(',', $value)))); } public function getOrderBatchSize(): int { return min(100, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'orders/batch_size'))); } public function getOrderMaxAttempts(): int { return min(50, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'orders/max_attempts'))); } public function getStockDeductionType(): int { return (int)$this->scopeConfig->getValue(self::BASE . 'orders/stock_deduction_type') === 2 ? 2 : 1; } public function getShipmentPageSize(): int { return min(200, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'shipments/page_size'))); } public function getShipmentMaxPages(): int { return min(100, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'shipments/max_pages'))); } public function getShipmentMaxAttempts(): int { return min(50, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'shipments/max_attempts'))); } public function shouldNotifyCustomer(): bool { return $this->scopeConfig->isSetFlag(self::BASE . 'shipments/notify_customer'); } public function isSkuSyncEnabled(): bool { return $this->scopeConfig->isSetFlag(self::BASE . 'sku_sync/enabled'); } public function getSkuSyncPageSize(): int { return min(200, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'sku_sync/page_size'))); } public function getSuccessLogRetentionDays(): int { return min(365, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'logging/success_retention_days'))); } public function getErrorLogRetentionDays(): int { return min(730, max(1, (int)$this->scopeConfig->getValue(self::BASE . 'logging/error_retention_days'))); } public function hasStoreMapping(int $websiteId): bool { $mapping = $this->getStoreMapping($websiteId); return $mapping['platform_code'] > 0 && $mapping['store_id'] !== ''; } public function assertCredentialsReady(): void { if ($this->getApiBaseUrl() === '' || $this->getAppId() === '' || $this->getAppSecret() === '') { throw new \RuntimeException('Lingxing API base URL, App ID and App Secret must be configured.'); } } public function assertOrderMappingReady(int $websiteId): void { $mapping = $this->getStoreMapping($websiteId); if ($mapping['platform_code'] <= 0 || $mapping['store_id'] === '') { throw new \RuntimeException(sprintf( 'No Lingxing store is configured for Magento Website ID %d.', $websiteId )); } if (($this->getWarehouseId($websiteId) === '') !== ($this->getLogisticsTypeId($websiteId) === '')) { throw new \RuntimeException('Lingxing warehouse and logistics type must either both be set or both be blank.'); } } /** @return array{platform_code:int, store_id:string} */ private function getStoreMapping(int $websiteId): array { $value = trim((string)$this->scopeConfig->getValue( self::BASE . 'general/store_mapping', ScopeInterface::SCOPE_WEBSITE, $websiteId )); [$platformCode, $storeId] = array_pad(explode('|', $value, 2), 2, ''); return ['platform_code' => max(0, (int)$platformCode), 'store_id' => trim($storeId)]; } private function getWebsiteValue(string $path, int $websiteId): mixed { if ($websiteId <= 0) { return $this->scopeConfig->getValue(self::BASE . $path); } return $this->scopeConfig->getValue(self::BASE . $path, ScopeInterface::SCOPE_WEBSITE, $websiteId); } }