From 0cd6bc2aa6aa3d68fc6bb874da32ca903cfa28e2 Mon Sep 17 00:00:00 2001 From: O K Date: Sat, 27 Dec 2025 13:19:23 +0200 Subject: [PATCH] improve calculateRate --- usps_api_bridge.php | 101 ++++++++++++++++++++++++++++---------------- 1 file changed, 64 insertions(+), 37 deletions(-) diff --git a/usps_api_bridge.php b/usps_api_bridge.php index 6dae81d..dbede74 100644 --- a/usps_api_bridge.php +++ b/usps_api_bridge.php @@ -153,9 +153,7 @@ class Usps_Api_Bridge extends Module return $helper->generateForm([$fields_form]); } - - - public function calculateRate($params, $shipping_cost, $products, $originalModule) + public function calculateRate($params, $shipping_cost, $products, $originalModule) { require_once(dirname(__FILE__) . '/classes/UspsV3Client.php'); @@ -163,61 +161,86 @@ class Usps_Api_Bridge extends Module $token = $this->getAccessToken(); if (!$token) return false; - // 2. Identify Service - $carrierId = $params->id_carrier; + + // 2. Identify Service (Use the Module's ID, not the Cart's ID) + // $originalModule->id_carrier is the carrier currently being calculated in the loop. + $carrierId = (int)$originalModule->id_carrier; + + // Fallback for edge cases where module ID might be missing (rare) + if (!$carrierId && isset($params->id_carrier)) { + $carrierId = (int)$params->id_carrier; + } + + // 3. Get Method Code $sql = 'SELECT code FROM `' . _DB_PREFIX_ . 'uspsl_method` WHERE id_carrier = ' . (int)$carrierId; $methodCode = Db::getInstance()->getValue($sql); + // If this carrier ID isn't in the USPS table, it's not a USPS carrier (or map is broken) if (!$methodCode) return false; + // --- 4. CHECK LEGACY DB CACHE --- + // (Moved after method identification so we query cache for the CORRECT carrier) + $zhCache = false; + $canCache = class_exists('\UspsPsLabels\Cache') && class_exists('\UspsPsLabels\CacheRate'); - // 4. Pack Products + if ($canCache) { + $zhCache = \UspsPsLabels\Cache::cacheCart($params->id); + + if (Validate::isLoadedObject($zhCache)) { + $sql = 'SELECT rate FROM `' . _DB_PREFIX_ . 'uspsl_cache_rate` + WHERE id_cache = ' . (int)$zhCache->id . ' + AND id_carrier = ' . (int)$carrierId; // Use the correct ID here too! + + $cachedRate = Db::getInstance()->getValue($sql); + + if ($cachedRate !== false && $cachedRate !== null) { + return (float)$cachedRate + $shipping_cost; + } + } + } + // ------------------------------- + + // 5. Determine International Status & Map Code + $destAddress = new Address($params->id_address_delivery); + $isInternational = ($destAddress->id_country != Country::getByIso('US')); + + $newApiClass = $this->mapServiceCodeToApiClass($methodCode, $isInternational); + if (!$newApiClass) return false; + + // 6. Pack Products $packedBoxes = $originalModule->getHelper()->getCarrierHelper()->packProducts($products, $params->id); if (empty($packedBoxes)) return false; - // 5. Setup Client + // 7. Setup Client $client = new UspsV3Client($token, (bool)Configuration::get('USPS_BRIDGE_LIVE_MODE')); $totalPrice = 0; - // Determine Price Type $legacyPriceSetting = (int)Configuration::get('USPSL_COMMERCIAL'); $requestedPriceType = ($legacyPriceSetting > 0) ? 'COMMERCIAL' : 'RETAIL'; - // 6. Address Data + // 8. Address Data $originZip = $this->getOriginZip($originalModule); - $destAddress = new Address($params->id_address_delivery); - $originZip = substr(preg_replace('/[^0-9]/', '', $originZip), 0, 5); $destZip = substr(preg_replace('/[^0-9]/', '', $destAddress->postcode), 0, 5); - $isInternational = ($destAddress->id_country != Country::getByIso('US')); - $newApiClass = $this->mapServiceCodeToApiClass($methodCode, $isInternational); - if (!$newApiClass) return false; - // 7. Loop through boxes - foreach ($packedBoxes as $packedBox) { - // Weight (Lbs) - Min 0.1 to avoid errors + // 9. Loop through boxes + foreach ($packedBoxes as $packedBox) { + $weightInLbs = $this->convertUnit($packedBox->getWeight(), 'g', 'lbs', 3); if ($weightInLbs < 0.1) $weightInLbs = 0.1; - // Dimensions (Inches) - $box = $packedBox->getBox(); + $box = $packedBox->getBox(); $length = $this->convertUnit($box->getOuterLength(), 'mm', 'in', 2); $width = $this->convertUnit($box->getOuterWidth(), 'mm', 'in', 2); $height = $this->convertUnit($box->getOuterDepth(), 'mm', 'in', 2); - // --- PROCESSING CATEGORY LOGIC (FIXED) --- - // "NONSTANDARD" is the V3 equivalent of a generic "Parcel" or "Package". - // We only use "MACHINABLE" if it is strictly Ground Advantage AND fits dimensions. - // For Priority/Express, "NONSTANDARD" finds the correct Retail/Commercial SKU. - $category = 'NONSTANDARD'; - + $category = 'NONSTANDARD'; if ($newApiClass === 'USPS_GROUND_ADVANTAGE') { if ($length <= 22 && $width <= 18 && $height <= 15 && $weightInLbs >= 0.375 && $weightInLbs <= 25) { $category = 'MACHINABLE'; } } - // ----------------------------------------- $payload = [ 'originZIPCode' => $originZip, @@ -229,45 +252,49 @@ class Usps_Api_Bridge extends Module 'priceType' => $requestedPriceType, 'mailingDate' => date('Y-m-d', strtotime('+1 day')), 'processingCategory' => $category, - 'rateIndicator' => 'SP' // SP = Single Piece (Variable dimensions) + 'rateIndicator' => 'SP' ]; - // Handle Flat Rates $flatRateIndicator = $this->mapBoxToRateIndicator($box->getReference()); if ($flatRateIndicator) { $payload['rateIndicator'] = $flatRateIndicator; - // Flat rates technically ignore dims/category, but we keep valid enums } - // --- SEND REQUEST --- + $response = $this->sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip); - // Retry Logic: If Commercial fails, try Retail if (isset($response['error']) && $payload['priceType'] === 'COMMERCIAL') { - // $this->log("Commercial failed (" . $response['error'] . "). Retrying RETAIL."); $payload['priceType'] = 'RETAIL'; $response = $this->sendApiRequest($client, $payload, $isInternational, $destAddress, $destZip); } - // Error Handling if (isset($response['error'])) { - // $this->log("API Fatal Error: " . $response['error']); - // $this->log("Payload: " . json_encode($payload)); return false; } - // Parse Price if (isset($response['totalBasePrice'])) { $totalPrice += (float)$response['totalBasePrice']; } elseif (isset($response['rateOptions'][0]['totalBasePrice'])) { $totalPrice += (float)$response['rateOptions'][0]['totalBasePrice']; } else { - // $this->log("API Response missing price."); return false; } } + // --- 10. SAVE TO LEGACY DB CACHE --- + if ($canCache && Validate::isLoadedObject($zhCache)) { + $newCacheRate = new \UspsPsLabels\CacheRate(); + $newCacheRate->id_cache = $zhCache->id; + $newCacheRate->id_carrier = $carrierId; // Use Correct ID + $newCacheRate->code = $methodCode; + $newCacheRate->rate = $totalPrice; + $newCacheRate->save(); + } + // ---------------------------------- + return $totalPrice + $shipping_cost; } + + /** * Helper to send request with Runtime Caching & Domestic/Intl switching */