diff --git a/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importApiloInvoices.php b/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importApiloInvoices.php index 31795caf..6f4381a9 100644 --- a/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importApiloInvoices.php +++ b/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importApiloInvoices.php @@ -3,7 +3,6 @@ //error_reporting(LC_ALL); //ini_set('display_errors', 1); // ?XDEBUG_SESSION_START=PHPSTORM -//importInvoices(); function apilo_importInvoices() { $apilo_config = apilo_loadConfiguration(); @@ -14,7 +13,8 @@ function apilo_importInvoices() $offset = intval($db->fetchByAssoc($dbRes)['last_id']); $invoices = apilo_loadInvoices($apilo_config['token'], $offset); - if (isset($invoices->error)) { + brecho($apilo_config); + if (isset($invoices->errors)) { if (apilo_refreshToken($apilo_config['refreshToken'], $apilo_config['clientId'], $apilo_config['clientSecret']) == true) { //$apilo_config = apilo_loadConfiguration(); //$invoices = apilo_loadInvoices($apilo_config['token'], $offset); @@ -23,6 +23,8 @@ function apilo_importInvoices() } } + brecho($invoices); + $GLOBALS['log']->bimit('----- Importing invoices from Apilo, documents count', count($invoices->documents)); $platforms = apilo_loadPlatformsList($apilo_config['token']); diff --git a/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importTEMUInvoices.php b/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importTEMUInvoices.php index a25b4b0c..bbde531d 100644 --- a/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importTEMUInvoices.php +++ b/modules/EcmInvoiceOuts/BimIT-eCommerceInvoices/importTEMUInvoices.php @@ -1,82 +1,164 @@ = 2 && $json[0] === '"' && substr($json, -1) === '"') return substr($json, 1, -1); - return $json; +function noquote($v){ + $j = json_encode($v, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + return (is_string($v) && $j[0]==='"' && substr($j,-1)==='"') ? substr($j,1,-1) : $j; } - -function temu_sign_md5(array $params, $secret) -{ - ksort($params, SORT_STRING); - $buf = $secret; - foreach ($params as $k => $v) { - if ($v !== '' && $v !== null) { - $buf .= $k . json_stringify_no_outer_quotes($v); +function sign_md5($p, $secret){ + ksort($p, SORT_STRING); + $s = $secret; + foreach($p as $k=>$v){ if($v!=='' && $v!==null) $s .= $k . noquote($v); } + $s .= $secret; + return strtoupper(md5($s)); +} +function parse_date_to_ts_start($s){ + $s = trim($s); + $fmts = array('Y-m-d','d.m.Y','Y/m/d','d-m-Y','d/m/Y'); + foreach ($fmts as $f){ + $dt = DateTime::createFromFormat($f, $s); + if ($dt && $dt->format($f) === $s){ + $dt->setTime(0,0,0); + return (int)$dt->format('U'); } } - $buf .= $secret; - return strtoupper(md5($buf)); + // fallback + $t = strtotime($s); + if ($t !== false){ return (int)strtotime(date('Y-m-d 00:00:00', $t)); } + return null; +} +function parse_date_to_ts_end($s){ + $ts = parse_date_to_ts_start($s); + if ($ts === null) return null; + return $ts + 86399; // 23:59:59 } -function http_post_json_diag($url, array $body) -{ +$fromTs = parse_date_to_ts_start($dateFromStr); +$toTs = parse_date_to_ts_end($dateToStr); + +if ($fromTs === null || $toTs === null){ + die('
Błędny format daty od/do
'); +} + +$totalMatched = 0; +$page = 1; +$maxPages = 500; // bezpiecznik + +echo '
'; + +while ($page <= $maxPages) { + // 1) request listy + $biz = array( + "type" => "bg.order.list.v2.get", + //"regionId" => 162, + "pageNumber" => $page, + "pageSize" => $pageSize, + // "parentOrderStatus" => $parentOrderStatus + ); + $common = array( + 'app_key' => $APP_KEY, + 'access_token' => $ACCESS_TOKEN, + 'data_type' => 'JSON', + 'timestamp' => (int)floor(microtime(true)), + ); + $req = $biz + $common; + $req['sign'] = sign_md5($req, $APP_SECRET); + $payload = json_encode($req, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + $ch = curl_init(); - $payload = json_encode($body, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES); - curl_setopt_array($ch, [ - CURLOPT_URL => $url, // <— jawnie ustawiamy URL (by uniknąć „malformed”) + curl_setopt_array($ch, array( + CURLOPT_URL => $BASE_URL, CURLOPT_RETURNTRANSFER => true, CURLOPT_POST => true, - CURLOPT_HTTPHEADER => ['Content-Type: application/json'], - CURLOPT_POSTFIELDS => $payload, // JSON body jak w Postmanie - CURLOPT_CONNECTTIMEOUT => 30, - CURLOPT_TIMEOUT => 60, - CURLOPT_SSL_VERIFYPEER => true, - CURLOPT_SSL_VERIFYHOST => 2, - CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4, - ]); + CURLOPT_HTTPHEADER => array('Content-Type: application/json'), + CURLOPT_POSTFIELDS => $payload + )); $resp = curl_exec($ch); - if ($resp === false) { - $errno = curl_errno($ch); - $err = curl_error($ch); - curl_close($ch); - die("cURL error: #$errno $err\nURL: $url\nBODY: $payload\n"); - } - $code = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $cerr = curl_error($ch); curl_close($ch); - return [$code, $resp]; + + var_dump($resp); + + if ($resp === false) { + echo "
cURL error: " . htmlspecialchars($cerr, ENT_QUOTES, 'UTF-8') . "
"; + break; + } + + $data = json_decode($resp, true); + if (!is_array($data) || !isset($data['result']['pageItems']) || !is_array($data['result']['pageItems'])) { + break; + } + + $items = $data['result']['pageItems']; + if (!count($items)) { + break; + } + + usort($items, function($a, $b){ + $ta = isset($a['parentOrderMap']['parentOrderTime']) ? (int)$a['parentOrderMap']['parentOrderTime'] : 0; + $tb = isset($b['parentOrderMap']['parentOrderTime']) ? (int)$b['parentOrderMap']['parentOrderTime'] : 0; + if ($ta == $tb) return 0; + return ($ta > $tb) ? -1 : 1; + }); + + $minTsOnPage = null; + foreach ($items as $row) { + if (!isset($row['parentOrderMap']['parentOrderSn'])) continue; + $parentOrderSn = $row['parentOrderMap']['parentOrderSn']; + $orderTs = isset($row['parentOrderMap']['parentOrderTime']) ? (int)$row['parentOrderMap']['parentOrderTime'] : 0; + + if ($minTsOnPage === null || $orderTs < $minTsOnPage) $minTsOnPage = $orderTs; + + if ($orderTs >= $fromTs && $orderTs <= $toTs) { + // trafienie — drukujemy wybrane pola + $issueHuman = $orderTs ? date('Y-m-d H:i:s', $orderTs) : '(brak)'; + + echo '
'; + echo '
Numer zamówienia: ' . htmlspecialchars($parentOrderSn, ENT_QUOTES, 'UTF-8') . '
'; + echo '
Status: ' . htmlspecialchars($row['parentOrderMap']['parentOrderStatus'], ENT_QUOTES, 'UTF-8') . '
'; + echo '
Data wystawienia: ' . htmlspecialchars($issueHuman, ENT_QUOTES, 'UTF-8') + . ' (epoch: ' . (int)$orderTs . ')
'; + + echo '
Produkty (extCode, soldFactor):
'; + if (isset($row['orderList']) && is_array($row['orderList']) && count($row['orderList'])>0) { + echo ''; + } else { + echo '
brak productList w orderList
'; + } + + $totalMatched++; + } + } + + if ($minTsOnPage !== null && $minTsOnPage < $fromTs) { + break; + } + + $page++; } -// ==== REQUEST: najpierw lista v2 (tak jak wcześniej) ==== -$biz = [ - 'type' => 'bg.order.list.v2.get', - 'parentOrderStatus' => 0, - 'regionId' => 211, - 'pageNumber' => 1, // jeśli router zgłosi błąd paramów, zamień na 'pageNo' - 'pageSize' => 1, -]; - -// common wg Twojego pre-request -$common = [ - 'app_key' => $APP_KEY, - 'access_token' => $ACCESS_TOKEN, - 'data_type' => $DATA_TYPE, - 'timestamp' => (int)floor(microtime(true)), -]; - -$req = $biz + $common; -$req['sign'] = temu_sign_md5($req, $APP_SECRET); - -list($http, $raw) = http_post_json_diag($BASE_URL, $req); - -echo "HTTP $http\n=== REQUEST BODY ===\n", json_encode($req, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES), "\n"; -echo "=== RAW RESPONSE ===\n$raw\n"; \ No newline at end of file +echo '
'; +echo '
Łącznie dopasowanych zamówień: ' . (int)$totalMatched . '
'; +echo '
Zakres dat: ' . htmlspecialchars(date('Y-m-d H:i:s', $fromTs), ENT_QUOTES, 'UTF-8') + . ' — ' . htmlspecialchars(date('Y-m-d H:i:s', $toTs), ENT_QUOTES, 'UTF-8') . '
'; +echo '
'; \ No newline at end of file diff --git a/modules/EcmSales/EditView.php b/modules/EcmSales/EditView.php index 237dd557..e5948440 100755 --- a/modules/EcmSales/EditView.php +++ b/modules/EcmSales/EditView.php @@ -40,13 +40,13 @@ if (isset($_REQUEST['record']) && $_REQUEST['isDuplicate'] == "false") { if (isset($focus->id) && $focus->id != '') { $focus->format_all_fields(); } -} else if (isset($_REQUEST['ecommerceZS'])) { +} else if (isset($_REQUEST['ecommerceZSApilo'])) { $new_number = true; $focus->stock_id = 'cf16804e-f698-5e09-2da3-6553588446ae'; $focus->register_date = date("d.m.Y"); $focus->parent_id = 'b5612f7f-85e5-f930-293e-62cead14b424'; $db = $GLOBALS['db']; - $invoiceIds = $_SESSION[$_REQUEST['ecommerceZS']]; + $invoiceIds = $_SESSION[$_REQUEST['ecommerceZSApilo']]; $i = $db->fetchByAssoc($db->query("SELECT register_date FROM ecommerce_invoices WHERE id = '$invoiceIds[0]'")); $focus->delivery_date = date("d.m.Y"); $focus->payment_date = date("d.m.Y"); @@ -92,6 +92,65 @@ GROUP BY ip.ecmproduct_id, ip.price_netto; $documentNos[] = $row['document_no']; } $focus->pdf_text = "Dotyczy faktur: " . implode(', ', $documentNos); +} else if (isset($_REQUEST['ecommerceZSTemu'])) { + $orders = json_decode($_SESSION[$_REQUEST['ecommerceZSTemu']]); + $new_number = true; + $focus->stock_id = 'cf16804e-f698-5e09-2da3-6553588446ae'; + $focus->register_date = date("d.m.Y"); + $focus->parent_id = '8b99791c-4e32-4443-fa57-69037059fe3f'; + $db = $GLOBALS['db']; + $invoiceIds = $_SESSION[$_REQUEST['ecommerceZSApilo']]; + $focus->delivery_date = date("d.m.Y"); + $focus->payment_date = date("d.m.Y"); + $focus->send_date = date("d.m.Y"); + $focus->payment_date_days = 0; + $focus->status = 's30'; + $focus->order_source = 'temu-'.$_REQUEST['temuCountry']; + + $documentNos = array(); + $products = array(); + foreach ($orders as $order) { + $documentNos[] = $order->orderNumber; + foreach($order->products as $product) { + $prod = $db->fetchByAssoc($db->query("SELECT id, name, code, unit_id FROM ecmproducts WHERE code = '".$product->extCode."' AND deleted = 0")); + if (!isset($prod)) { + echo 'Brak produktu, nie wystawiaj dokumentu! '.$product->extCode.'
'; + } else { + $products[] = array( + 'product_id' => $prod['id'], + 'product_code' => $prod['code'], + 'name' => $prod['name'], + 'quantity' => $product->soldFactor, + 'price_start' => 0.01, + 'price_netto' => 0.01, + 'unit_id' => $prod['unit_id'], + 'unit_name' => $app_list_strings['ecmproducts_unit_dom'][$prod['unit_id']], + 'ecmvat_name' => '0%', + 'ecmvat_value' => 0, + 'ecmvat_id' => '9b783d21-5548-6653-e1d6-49610eb3f9dd', + ); + } + } + $prod = $db->fetchByAssoc($db->query("SELECT id FROM ecmproducts WHERE code = '".$order->productCode."'")); + } + + $groupedProducts = array(); + + foreach ($products as $p) { + $pid = $p['product_id']; + if (!isset($groupedProducts[$pid])) { + $groupedProducts[$pid] = $p; + } else { + $groupedProducts[$pid]['quantity'] += $p['quantity']; + } + } + $groupedProducts = array_values($groupedProducts); + + $edit->ss->assign('ECOMMERCE_PRODUCTS', json_encode($groupedProducts)); + + $query = "SELECT document_no FROM ecommerce_invoices WHERE id IN ('" . implode('\',\'', $invoiceIds) . "')"; + $res = $db->query($query); + $focus->pdf_text = "Dotyczy zamówień: " . implode(', ', $documentNos); } else if ($_REQUEST['isDuplicate'] == "true") { $new_number = true; $duplicate = true; diff --git a/modules/EcmSales/bimit_importTemuOrders.php b/modules/EcmSales/bimit_importTemuOrders.php new file mode 100644 index 00000000..67f49e19 --- /dev/null +++ b/modules/EcmSales/bimit_importTemuOrders.php @@ -0,0 +1,166 @@ +$v){ if($v!=='' && $v!==null) $s .= $k . noquote($v); } + $s .= $secret; + return strtoupper(md5($s)); +} + +function getTemuOrders($from, $to, $country, $pageSize = 50){ + $APP_KEY = '02cbeff8afd35247294810033b036cfe'; + $APP_SECRET = '8ecfa21b55cddf66c66043cbb80756efc4ba6596'; + $ACCESS_TOKEN_DE = 'eploouslfhwjwwzvz5okvmu29stwwdw9l3ullz8pv6y4raips8gouzwcqmv'; + $ACCESS_TOKEN_PL = 'eplyaf6ogcpewjtzytw8q9ahvx7haqntzk8wsz7vokjusvpry93gy9cvn2c'; + $ACCESS_TOKEN_FR = 'eplhrdwtdgjpfelzmyelnsifakqjzfza6rpa8neb7nqc8djxj11hlenl3u2'; + $BASE_URL = 'https://openapi-b-eu.temu.com/openapi/router'; + $REGION_ID = 162; + // --- parse daty --- + if (!is_int($from)) $from = strtotime($from); + if (!is_int($to)) $to = strtotime($to); + + if (!$from || !$to) return []; + if ($from > $to) { $tmp = $from; $from = $to; $to = $tmp; } + + + $page = 1; + $out = []; + $seenAnyInRange = false; + $guardPages = 500; + + while ($guardPages-- > 0) { + $biz = array( + "type" => "bg.order.list.v2.get", + //"regionId" => $REGION_ID, + "pageNumber" => $page, + "pageSize" => $pageSize + ); + switch ($country) { + case 'pl': $ACCESS_TOKEN = $ACCESS_TOKEN_PL; break; + case 'fr': $ACCESS_TOKEN = $ACCESS_TOKEN_FR; break; + default: $ACCESS_TOKEN = $ACCESS_TOKEN_DE; break; + } + $common = array( + 'app_key' => $APP_KEY, + 'access_token' => $ACCESS_TOKEN, + 'data_type' => 'JSON', + 'timestamp' => (int)floor(microtime(true)), + ); + $req = $biz + $common; + $req['sign'] = sign_md5($req, $APP_SECRET); + + $payload = json_encode($req, JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES); + + $ch = curl_init(); + curl_setopt_array($ch, array( + CURLOPT_URL => $BASE_URL, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_POST => true, + CURLOPT_HTTPHEADER => array('Content-Type: application/json'), + CURLOPT_POSTFIELDS => $payload, + CURLOPT_TIMEOUT => 30, + )); + $resp = curl_exec($ch); + $http = curl_getinfo($ch, CURLINFO_HTTP_CODE); + $cerr = curl_error($ch); + curl_close($ch); + + if ($resp === false || $http !== 200) { + break; + } + + $data = json_decode($resp, true); + if ($data['success'] == false) { + var_dump('Błąd ładowania zamówień TEMU '.$country.': '.$data['errorMsg']); + break; + } + if (!is_array($data) + || !isset($data['result']['pageItems']) + || !is_array($data['result']['pageItems']) + || count($data['result']['pageItems']) === 0) { + break; + } + $items = $data['result']['pageItems']; + + usort($items, function($a, $b){ + $ta = isset($a['parentOrderMap']['parentOrderTime']) ? (int)$a['parentOrderMap']['parentOrderTime'] : 0; + $tb = isset($b['parentOrderMap']['parentOrderTime']) ? (int)$b['parentOrderMap']['parentOrderTime'] : 0; + if ($ta == $tb) return 0; + return ($ta > $tb) ? -1 : 1; + }); + + $maxTs = isset($items[0]['parentOrderMap']['parentOrderTime']) ? (int)$items[0]['parentOrderMap']['parentOrderTime'] : 0; + $last = $items[count($items)-1]; + $minTs = isset($last['parentOrderMap']['parentOrderTime']) ? (int)$last['parentOrderMap']['parentOrderTime'] : 0; + + foreach ($items as $row) { + if (!isset($row['parentOrderMap']['parentOrderSn'])) continue; + + $ts = isset($row['parentOrderMap']['parentOrderTime']) ? (int)$row['parentOrderMap']['parentOrderTime'] : 0; + if ($ts < $from || $ts > $to) continue; + + $pst = isset($row['parentOrderMap']['parentOrderStatus']) ? (int)$row['parentOrderMap']['parentOrderStatus'] : -1; + if (!($pst === 4 || $pst === 5)) continue; + + $seenAnyInRange = true; + + $orderSn = $row['parentOrderMap']['parentOrderSn']; + + // check if order exitst + $db = $GLOBALS['db']; + $exists = $db->fetchByAssoc($db->query("SELECT id FROM ecmsales WHERE pdf_text LIKE '%$orderSn%'")); + if (isset($exists['id'])) continue; + + $products = array(); + + if (isset($row['orderList']) && is_array($row['orderList'])) { + foreach ($row['orderList'] as $ol) { + if (!isset($ol['productList']) || !is_array($ol['productList'])) continue; + foreach ($ol['productList'] as $p) { + // hacks :) + if ($p['extCode'] == 'FR00259_52_15g_amz_de-1') { + $p['extCode'] = 'FR00259_52_15g_amz_de'; + } + if ($p['extCode'] == 'FR00138_1000_amz_de-1') { + $p['extCode'] = 'FR00138_1000_amz_de'; + } + $products[] = array( + 'extCode' => isset($p['extCode']) ? $p['extCode'] : null, + 'soldFactor' => isset($p['soldFactor']) ? $p['soldFactor'] : null, + ); + } + } + } + + $out[] = array( + 'orderNumber' => $orderSn, + 'issueTime' => $ts, + 'issueDate' => $ts ? date('Y-m-d H:i:s', $ts) : null, + 'products' => $products, + 'raw' => $row, + ); + } + + if ($minTs >= $from) { + $page++; + continue; + } + if ($maxTs < $from) { + break; + } + if (!$seenAnyInRange) { + $page++; + continue; + } + break; + } + usort($out, function($a, $b){ + if ($a['issueTime'] == $b['issueTime']) return 0; + return ($a['issueTime'] > $b['issueTime']) ? -1 : 1; + }); + return $out; +} \ No newline at end of file diff --git a/modules/EcmSales/eCommerceZS/eCommerceZS.php b/modules/EcmSales/eCommerceZS/eCommerceZS.php index 7abdda27..ad26eb14 100644 --- a/modules/EcmSales/eCommerceZS/eCommerceZS.php +++ b/modules/EcmSales/eCommerceZS/eCommerceZS.php @@ -3,6 +3,8 @@ ini_set('display_errors', 1); ini_set('display_startup_errors', 1); error_reporting(E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED); +require_once ('modules/EcmSales/bimit_importTemuOrders.php'); + $db = $GLOBALS['db']; global $app_list_strings; @@ -18,9 +20,9 @@ if (isset($_REQUEST['date_from'])) { foreach ($invoices as $invoice) { $invoiceIds[] = $invoice['id']; } - $sessionId = create_guid(); - $_SESSION[$sessionId] = $invoiceIds; - $smarty->assign('sessionId', $sessionId); + $sessionIdApilo = create_guid(); + $_SESSION[$sessionIdApilo] = $invoiceIds; + $smarty->assign('sessionIdApilo', $sessionIdApilo); $invoiceNo = array(); foreach ($invoices as $invoice) { @@ -28,6 +30,39 @@ if (isset($_REQUEST['date_from'])) { } $smarty->assign('invoicesNo', join(", ", $invoiceNo)); + $dateFrom = date('Y-m-d', strtotime($_REQUEST['date_from'])); + $dateTo = date('Y-m-d', strtotime($_REQUEST['date_to'])); + + $ordersPl = getTemuOrders($dateFrom.' 00:00:00', $dateTo.' 23:59:59', 'pl', 50); + $orderNoPl = array(); + foreach ($ordersPl as $order) { + $orderNoPl[] = $order['orderNumber']; + } + $smarty->assign('ordersNoPl', join(", ", $orderNoPl)); + $sessionIdTemuPl = create_guid(); + $_SESSION[$sessionIdTemuPl] = json_encode($ordersPl); + $smarty->assign('sessionIdTemuPl', $sessionIdTemuPl); + + $ordersDe = getTemuOrders($dateFrom.' 00:00:00', $dateTo.' 23:59:59', 'de', 50); + $orderNoDe = array(); + foreach ($ordersDe as $order) { + $orderNoDe[] = $order['orderNumber']; + } + $smarty->assign('ordersNoDe', join(", ", $orderNoDe)); + $sessionIdTemuDe = create_guid(); + $_SESSION[$sessionIdTemuDe] = json_encode($ordersDe); + $smarty->assign('sessionIdTemuDe', $sessionIdTemuDe); + + $ordersFr = getTemuOrders($dateFrom.' 00:00:00', $dateTo.' 23:59:59', 'fr', 50); + $orderNoFr = array(); + foreach ($ordersFr as $order) { + $orderNoFr[] = $order['orderNumber']; + } + $smarty->assign('ordersNoFr', join(", ", $orderNoFr)); + $sessionIdTemuFr = create_guid(); + $_SESSION[$sessionIdTemuFr] = json_encode($ordersFr); + $smarty->assign('sessionIdTemuFr', $sessionIdTemuFr); + $smarty->assign('date_from', $_REQUEST['date_from']); $smarty->assign('date_to', $_REQUEST['date_to']); echo $smarty->display(getcwd() . '/modules/EcmSales/eCommerceZS/eCommerceZS.tpl'); diff --git a/modules/EcmSales/eCommerceZS/eCommerceZS.tpl b/modules/EcmSales/eCommerceZS/eCommerceZS.tpl index acaadf0f..98caa74d 100644 --- a/modules/EcmSales/eCommerceZS/eCommerceZS.tpl +++ b/modules/EcmSales/eCommerceZS/eCommerceZS.tpl @@ -63,7 +63,22 @@
-ZS zbiorcza dla FV:
{$invoicesNo} +ZS zbiorcza dla FV (Apilo):
{$invoicesNo}

- \ No newline at end of file + +

+ZS zbiorcza dla zamówień TEMU PL:
{$ordersNoPl} +

+ +

+ZS zbiorcza dla zamówień TEMU DE:
{$ordersNoDe} +

+ +

+ZS zbiorcza dla zamówień TEMU FR:
{$ordersNoFr} +

+ \ No newline at end of file