AI CSV
This commit is contained in:
@@ -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,17 +238,16 @@ 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'];
|
$db = $GLOBALS['db'];
|
||||||
$exportDir = __DIR__ . "/export";
|
$exportDir = __DIR__ . "/export";
|
||||||
|
|
||||||
@@ -511,7 +506,11 @@ SELECT
|
|||||||
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 (
|
||||||
@@ -523,6 +522,15 @@ LEFT JOIN (
|
|||||||
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',
|
||||||
@@ -603,8 +611,6 @@ ORDER BY es.register_date DESC, es.document_no DESC, i.position;
|
|||||||
echo implode("\n", $report);
|
echo implode("\n", $report);
|
||||||
exit;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user