This commit is contained in:
Michał Zieliński
2025-09-24 19:27:41 +02:00
parent d5d1d1ac28
commit 76dd05d591

View File

@@ -18,7 +18,6 @@ function sendInvoice($record)
); );
echo json_encode($response); echo json_encode($response);
} }
function sendProduct($record) function sendProduct($record)
{ {
require_once('modules/EcmProducts/EcmProduct.php'); require_once('modules/EcmProducts/EcmProduct.php');
@@ -35,7 +34,6 @@ function sendProduct($record)
); );
echo json_encode($response); echo json_encode($response);
} }
function copySaleFromTwinpol($record) function copySaleFromTwinpol($record)
{ {
$db = $GLOBALS['db']; $db = $GLOBALS['db'];
@@ -118,7 +116,7 @@ function copySaleFromTwinpol($record)
$prod['ecmvat_id'] = $vat_id; $prod['ecmvat_id'] = $vat_id;
$prod['ecmvat_value'] = $vat_value; $prod['ecmvat_value'] = $vat_value;
$prod['ecmvat_name'] = $vat_name; $prod['ecmvat_name'] = $vat_name;
$prod['price_brutto'] = round($prod['price_netto'] + ($prod['price_netto'] * ($prod['ecmvat_value'] / 100)), 2); $prod['price_netto'] = round((float)$price_start - ((float)$price_start * ((float)$product->discount / 100)), 2);
$prod['total_netto'] = round($prod['price_netto'] * $prod['quantity'], 2); $prod['total_netto'] = round($prod['price_netto'] * $prod['quantity'], 2);
$prod['total_brutto'] = round($prod['total_netto'] + ($prod['total_netto'] * ($prod['ecmvat_value'] / 100)), 2); $prod['total_brutto'] = round($prod['total_netto'] + ($prod['total_netto'] * ($prod['ecmvat_value'] / 100)), 2);
@@ -215,7 +213,6 @@ ILN: " . $sale->shipping_iln;
echo '<a target="new" href="https://crm.e5.pl/index.php?module=EcmSales&action=DetailView&record=' . $newId . '">Utworzono ZS.</a>'; echo '<a target="new" href="https://crm.e5.pl/index.php?module=EcmSales&action=DetailView&record=' . $newId . '">Utworzono ZS.</a>';
die(); die();
} }
// local helpers // local helpers
function getProduct($code) function getProduct($code)
{ {
@@ -230,7 +227,6 @@ function getProduct($code)
return $prod; return $prod;
} }
} }
function makeCUrlRequest($url) function makeCUrlRequest($url)
{ {
$curl = curl_init(); $curl = curl_init();
@@ -242,23 +238,22 @@ function makeCUrlRequest($url)
curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_URL, $url);
return curl_exec($curl); return curl_exec($curl);
} }
function brecho($msg) function brecho($msg)
{ {
echo '<br><br>'; echo '<br><br>';
var_dump($msg); var_dump($msg);
echo '<br><br>'; echo '<br><br>';
} }
function createCSVReports() function createCSVReports()
{ {
{ generateProductComponentsCSV();
$db = $GLOBALS['db'];
$exportDir = __DIR__ . "/export";
$jobs = [ $db = $GLOBALS['db'];
[ $exportDir = __DIR__ . "/export";
'sql' => "
$jobs = [
[
'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -294,10 +289,10 @@ GROUP BY
ii.price_netto ii.price_netto
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'invoices_2024.csv', 'filename' => 'invoices_2024.csv',
], // invoices 2024 ], // invoices 2024
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -333,10 +328,10 @@ GROUP BY
ii.price_netto ii.price_netto
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'invoices_2025.csv', 'filename' => 'invoices_2025.csv',
], // invoices 2025 ], // invoices 2025
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -379,10 +374,10 @@ GROUP BY
ii.total_netto_corrected ii.total_netto_corrected
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'correct_invoices_2024.csv', 'filename' => 'correct_invoices_2024.csv',
], // correct invoices 2024 ], // correct invoices 2024
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -425,10 +420,10 @@ GROUP BY
ii.total_netto_corrected ii.total_netto_corrected
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'correct_invoices_2025.csv', 'filename' => 'correct_invoices_2025.csv',
], // correct invoices 2025 ], // correct invoices 2025
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -463,10 +458,10 @@ GROUP BY
ii.quantity ii.quantity
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'rw_2025.csv', 'filename' => 'rw_2025.csv',
], // rw 2025 ], // rw 2025
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.document_no, i.document_no,
i.register_date, i.register_date,
@@ -501,34 +496,47 @@ GROUP BY
ii.quantity ii.quantity
ORDER BY i.register_date DESC; ORDER BY i.register_date DESC;
", ",
'filename' => 'rw_2024.csv', 'filename' => 'rw_2024.csv',
], // rw 2024 ], // rw 2024
[ [
'sql' => " 'sql' => "
SELECT SELECT
ss.product_code, ss.product_code,
ss.product_name, ss.product_name,
ss.product_id, ss.product_id,
COALESCE(NULLIF(ss.quantity, ''), 0) AS quantity, COALESCE(NULLIF(ss.quantity, ''), 0) AS quantity,
s.name, s.name,
COALESCE(si.ordered_quantity, 0) AS ordered_quantity CASE
WHEN s.id = 'c7afd71a-4c3a-bde4-138d-4acaee1644e4' THEN COALESCE(si.ordered_quantity, 0)
WHEN s.id = '368479db-22c5-0220-3a14-4bc426b1c709' THEN COALESCE(poi.ordered_quantity, 0)
ELSE 0
END AS ordered_quantity
FROM ecmstockstates AS ss FROM ecmstockstates AS ss
JOIN ecmstocks AS s ON ss.stock_id = s.id JOIN ecmstocks AS s ON ss.stock_id = s.id
LEFT JOIN ( LEFT JOIN (
SELECT SELECT
i.ecmproduct_id, i.ecmproduct_id,
SUM(i.quantity) AS ordered_quantity SUM(i.quantity) AS ordered_quantity
FROM ecmsaleitems AS i FROM ecmsaleitems AS i
JOIN ecmsales AS es ON es.id = i.ecmsale_id JOIN ecmsales AS es ON es.id = i.ecmsale_id
WHERE es.status IN ('s20','s30') AND es.deleted = '0' AND i.deleted = '0' AND es.register_date >= '2025-06-01' WHERE es.status IN ('s20','s30') AND es.deleted = '0' AND i.deleted = '0' AND es.register_date >= '2025-06-01'
GROUP BY i.ecmproduct_id GROUP BY i.ecmproduct_id
) AS si ON si.ecmproduct_id = ss.product_id ) AS si ON si.ecmproduct_id = ss.product_id
LEFT JOIN (
SELECT
poi.ecmproduct_id,
SUM(poi.quantity) AS ordered_quantity
FROM ecmpurchaseorderitems AS poi
JOIN ecmpurchaseorders AS po ON po.id = poi.ecmpurchaseorder_id
WHERE po.status IN ('accepted','registered') AND po.deleted = '0' AND poi.deleted = '0' AND po.register_date >= '2025-06-01'
GROUP BY poi.ecmproduct_id
) AS poi ON poi.ecmproduct_id = ss.product_id
WHERE ss.stock_id IN ('c7afd71a-4c3a-bde4-138d-4acaee1644e4','368479db-22c5-0220-3a14-4bc426b1c709') WHERE ss.stock_id IN ('c7afd71a-4c3a-bde4-138d-4acaee1644e4','368479db-22c5-0220-3a14-4bc426b1c709')
ORDER BY quantity + 0 DESC;", ORDER BY quantity + 0 DESC;",
'filename' => 'stocks.csv', 'filename' => 'stocks.csv',
],// stocks ],// stocks
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.code AS product_code, i.code AS product_code,
i.name AS product_name, i.name AS product_name,
@@ -552,10 +560,10 @@ WHERE es.status IN ('s20','s30')
AND es.register_date >= '2025-06-01' AND es.register_date >= '2025-06-01'
ORDER BY es.register_date DESC, es.document_no DESC, i.position; ORDER BY es.register_date DESC, es.document_no DESC, i.position;
", ",
'filename' => 'zs.csv', 'filename' => 'zs.csv',
], //sales ], //sales
[ [
'sql' => " 'sql' => "
SELECT SELECT
i.code AS product_code, i.code AS product_code,
i.name AS product_name, i.name AS product_name,
@@ -578,33 +586,31 @@ WHERE es.status IN ('accepted','registered')
AND es.register_date >= '2025-06-01' AND es.register_date >= '2025-06-01'
ORDER BY es.register_date DESC, es.document_no DESC, i.position; ORDER BY es.register_date DESC, es.document_no DESC, i.position;
", ",
'filename' => 'zz.csv', 'filename' => 'zz.csv',
], //orders ], //orders
]; ];
$report = []; $report = [];
foreach ($jobs as $job) { foreach ($jobs as $job) {
$sql = $job['sql']; $sql = $job['sql'];
$filename = $job['filename']; $filename = $job['filename'];
$headers = isset($job['headers']) ? $job['headers'] : null; $headers = isset($job['headers']) ? $job['headers'] : null;
$res = $db->query($sql); $res = $db->query($sql);
$fullpath = rtrim($exportDir, "/") . "/" . $filename; $fullpath = rtrim($exportDir, "/") . "/" . $filename;
$result = exportToCSVFile($res, $fullpath, $headers, ';', true); $result = exportToCSVFile($res, $fullpath, $headers, ';', true);
if ($result['ok']) { if ($result['ok']) {
$report[] = "OK → {$result['path']} (wiersze: {$result['rows']})" . PHP_EOL; $report[] = "OK → {$result['path']} (wiersze: {$result['rows']})" . PHP_EOL;
} else { } else {
$report[] = "ERR → {$result['path']} ({$result['error']})" . PHP_EOL;; $report[] = "ERR → {$result['path']} ({$result['error']})" . PHP_EOL;;
}
} }
echo implode("\n", $report);
exit;
} }
}
echo implode("\n", $report);
exit;
}
function exportToCSVFile($res, $fullpath, array $headers = null, $delimiter = ';', $withBom = true) function exportToCSVFile($res, $fullpath, array $headers = null, $delimiter = ';', $withBom = true)
{ {
$db = $GLOBALS['db']; $db = $GLOBALS['db'];
@@ -671,3 +677,159 @@ function exportToCSVFile($res, $fullpath, array $headers = null, $delimiter = ';
$chmod_ok = @chmod($fullpath, 0664); $chmod_ok = @chmod($fullpath, 0664);
return ['ok' => true, 'path' => $fullpath, 'rows' => $count, 'chmod' => $chmod_ok, 'error' => null]; return ['ok' => true, 'path' => $fullpath, 'rows' => $count, 'chmod' => $chmod_ok, 'error' => null];
} }
function generateProductComponentsCSV()
{
$db = $GLOBALS['db'];
$exportDir = __DIR__ . "/export";
$filename = 'product_components.csv';
$fullpath = rtrim($exportDir, "/") . "/" . $filename;
if (!is_dir($exportDir)) {
if (!@mkdir($exportDir, 0775, true)) {
echo "Błąd: Nie mogę utworzyć katalogu: $exportDir";
return;
}
}
$productsWithComponents = $db->query("
SELECT DISTINCT p.id, p.code, p.name
FROM ecmproducts p
INNER JOIN ecmproductcomponents c ON p.id = c.ecmproduct_id
WHERE p.deleted = '0' AND c.deleted = '0' AND p.active = '1'
ORDER BY p.code
");
$fp = @fopen($fullpath, 'w');
if ($fp === false) {
echo "Błąd: Nie mogę otworzyć pliku do zapisu: $fullpath";
return;
}
fwrite($fp, "\xEF\xBB\xBF");
$headers = [
'Poziom_1_Kod', 'Poziom_1_Nazwa', 'Poziom_1_Ilosc',
'Poziom_2_Kod', 'Poziom_2_Nazwa', 'Poziom_2_Ilosc',
'Poziom_3_Kod', 'Poziom_3_Nazwa', 'Poziom_3_Ilosc',
'Poziom_4_Kod', 'Poziom_4_Nazwa', 'Poziom_4_Ilosc',
'Poziom_5_Kod', 'Poziom_5_Nazwa', 'Poziom_5_Ilosc',
'Poziom_6_Kod', 'Poziom_6_Nazwa', 'Poziom_6_Ilosc',
'Poziom_7_Kod', 'Poziom_7_Nazwa', 'Poziom_7_Ilosc',
'Poziom_8_Kod', 'Poziom_8_Nazwa', 'Poziom_8_Ilosc',
'Poziom_9_Kod', 'Poziom_9_Nazwa', 'Poziom_9_Ilosc',
'Poziom_10_Kod', 'Poziom_10_Nazwa', 'Poziom_10_Ilosc'
];
fputcsv($fp, $headers, ';');
$totalRows = 0;
while ($product = $db->fetchByAssoc($productsWithComponents)) {
$rows = generateComponentRows($product['id'], $product['code'], $product['name'], 1.0, [], $db);
foreach ($rows as $row) {
fputcsv($fp, $row, ';');
$totalRows++;
}
}
fclose($fp);
echo "Wygenerowano plik CSV: $fullpath (wiersze: $totalRows)";
}
function generateComponentRows($productId, $productCode, $productName, $quantity, $path, $db, $level = 1)
{
if (in_array($productId, array_column($path, 'id'))) {
return [];
}
if ($level > 10) {
return [];
}
$rows = [];
$currentPath = $path;
$currentPath[] = [
'id' => $productId,
'code' => $productCode,
'name' => $productName,
'quantity' => $quantity
];
$componentsQuery = $db->query("
SELECT
c.ecmcomponent_id,
c.quantity,
p.code,
p.name
FROM ecmproductcomponents c
INNER JOIN ecmproducts p ON c.ecmcomponent_id = p.id
WHERE c.ecmproduct_id = '$productId'
AND c.deleted = '0'
AND p.deleted = '0'
ORDER BY c.position, p.code
");
$hasComponents = false;
while ($component = $db->fetchByAssoc($componentsQuery)) {
$hasComponents = true;
// Oblicz rzeczywistą ilość komponentu (ilość z hierarchii wyżej * ilość komponentu)
$totalQuantity = bcmul($quantity, $component['quantity'], 6);
// Sprawdź czy komponent ma swoje komponenty (rekurencja)
$subRows = generateComponentRows(
$component['ecmcomponent_id'],
$component['code'],
$component['name'],
$totalQuantity,
$currentPath,
$db,
$level + 1
);
if (empty($subRows)) {
// Komponent nie ma pod-komponentów, dodaj wiersz z kompletną ścieżką
$row = createCSVRow($currentPath, $component['ecmcomponent_id'], $component['code'], $component['name'], $totalQuantity);
$rows[] = $row;
} else {
// Komponent ma pod-komponenty, dodaj wszystkie zwrócone wiersze
$rows = array_merge($rows, $subRows);
}
}
// Jeśli produkt nie ma komponentów i jesteśmy na poziomie > 1, zwróć pusty array
// (główny produkt zawsze musi być pokazany)
if (!$hasComponents && $level > 1) {
$row = createCSVRow($currentPath);
$rows[] = $row;
}
return $rows;
}
function createCSVRow($path, $lastComponentId = null, $lastComponentCode = null, $lastComponentName = null, $lastQuantity = null)
{
// Utwórz tablicę z 30 elementami (10 poziomów * 3 kolumny: kod, nazwa, ilość)
$row = array_fill(0, 30, '');
// Wypełnij ścieżkę
foreach ($path as $index => $item) {
if ($index < 10) { // Maksymalnie 10 poziomów
$row[$index * 3] = $item['code']; // Kod
$row[$index * 3 + 1] = $item['name']; // Nazwa
$row[$index * 3 + 2] = $item['quantity']; // Ilość
}
}
// Dodaj ostatni komponent jeśli został przekazany
if ($lastComponentId !== null && count($path) < 10) {
$lastIndex = count($path);
$row[$lastIndex * 3] = $lastComponentCode;
$row[$lastIndex * 3 + 1] = $lastComponentName;
$row[$lastIndex * 3 + 2] = $lastQuantity;
}
return $row;
}