2024-04-27 09:23:34 +02:00
|
|
|
<?php
|
2025-09-15 19:40:04 +02:00
|
|
|
function sendInvoice($record)
|
|
|
|
|
{
|
2025-07-06 08:39:16 +00:00
|
|
|
require_once('modules/EcmInvoiceOuts/EcmInvoiceOut.php');
|
|
|
|
|
$inv = new EcmInvoiceOut();
|
|
|
|
|
$inv->retrieve($record);
|
|
|
|
|
$pl = $inv->getPositionList();
|
2025-09-15 19:40:04 +02:00
|
|
|
$response = array(
|
2025-07-06 08:39:16 +00:00
|
|
|
'document_no' => $inv->document_no,
|
|
|
|
|
'register_date' => $inv->register_date,
|
|
|
|
|
'payment_date' => $inv->payment_date,
|
|
|
|
|
'total_netto' => $inv->total_netto,
|
|
|
|
|
'total_brutto' => $inv->total_brutto,
|
|
|
|
|
'currency_id' => $inv->currency_id,
|
|
|
|
|
'currency_value' => $inv->currency_value,
|
|
|
|
|
'vats_summary' => $inv->vats_summary,
|
|
|
|
|
'position_list' => $pl
|
|
|
|
|
);
|
|
|
|
|
echo json_encode($response);
|
|
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
function sendProduct($record)
|
|
|
|
|
{
|
2025-07-06 08:39:16 +00:00
|
|
|
require_once('modules/EcmProducts/EcmProduct.php');
|
|
|
|
|
$prod = new EcmProduct();
|
|
|
|
|
$prod->retrieve($record);
|
2025-09-15 19:40:04 +02:00
|
|
|
$response = array(
|
2025-07-06 08:39:16 +00:00
|
|
|
'name' => $prod->name,
|
|
|
|
|
'code' => $prod->code,
|
|
|
|
|
'ean' => $prod->ean,
|
|
|
|
|
'vat' => $prod->vat_value,
|
|
|
|
|
'unit_id' => $prod->unit_id,
|
|
|
|
|
'product_category_id' => $prod->product_category_id,
|
|
|
|
|
'product_category_name' => $prod->product_category_name
|
|
|
|
|
);
|
|
|
|
|
echo json_encode($response);
|
|
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
function copySaleFromTwinpol($record)
|
|
|
|
|
{
|
2025-07-06 08:39:16 +00:00
|
|
|
$db = $GLOBALS['db'];
|
|
|
|
|
|
|
|
|
|
// check if sale exists
|
|
|
|
|
$exists = $db->fetchByAssoc($db->query("SELECT id, document_no FROM ecmsales WHERE edi_zs_id='$record'"));
|
|
|
|
|
if (isset($exists)) {
|
|
|
|
|
echo "ZS istnieje: ";
|
2025-09-15 19:40:04 +02:00
|
|
|
echo '<a target="new" href="https://crm.e5.pl/index.php?module=EcmSales&action=DetailView&record=' . $exists['id'] . '">' . $exists['document_no'] . '</a>';
|
2025-07-06 08:39:16 +00:00
|
|
|
die();
|
2024-04-27 09:23:34 +02:00
|
|
|
}
|
2024-09-30 08:44:00 +00:00
|
|
|
|
2025-09-15 19:40:04 +02:00
|
|
|
$res = makeCUrlRequest("https://crm.twinpol.com/REST/index.php?key=d68dac4c-f784-4e1b-8267-9ffcfa0eda4c&action=getSale&record=" . $record);
|
2025-07-06 08:39:16 +00:00
|
|
|
$sale = json_decode($res);
|
|
|
|
|
$sale->position_list = json_decode($sale->position_list);
|
2025-09-15 19:40:04 +02:00
|
|
|
echo "Numer dokumentu TwinPol: <b>" . $sale->document_no . "</b><br>";
|
2025-07-06 08:39:16 +00:00
|
|
|
|
|
|
|
|
$gotAllProducts = true; // hope :)
|
|
|
|
|
$newPositionList = array();
|
2025-09-15 19:40:04 +02:00
|
|
|
$total_netto = 0;
|
|
|
|
|
$total_brutto = 0;
|
|
|
|
|
$total_discount = 0;
|
|
|
|
|
$vats = array();
|
|
|
|
|
foreach ($sale->position_list as $product) {
|
|
|
|
|
echo 'Produkt: ' . $product->product_code;
|
2025-07-06 08:39:16 +00:00
|
|
|
$p = getProduct(trim($product->product_code));
|
|
|
|
|
if (!$p) {
|
|
|
|
|
echo ' (produkt nie istnieje w bazie E5)<br>';
|
|
|
|
|
$gotAllProducts = false;
|
|
|
|
|
continue;
|
|
|
|
|
} else {
|
|
|
|
|
// pricebook price?
|
|
|
|
|
$pricebookPrice = $db->fetchByAssoc($db->query("
|
|
|
|
|
SELECT price FROM ecmpricebooks_ecmproducts
|
|
|
|
|
WHERE ecmpricebook_id = '3e78ac33-7c46-1b94-0a67-653a17c06f9e'
|
|
|
|
|
AND ecmproduct_id='$p->id'
|
|
|
|
|
AND deleted=0 LIMIT 0,1"));
|
|
|
|
|
if (isset($pricebookPrice)) {
|
|
|
|
|
$price_start = $pricebookPrice['price'];
|
2025-09-15 19:40:04 +02:00
|
|
|
echo " Cena: " . $price_start . " (<a href=\"https://crm.e5.pl/index.php?module=EcmPriceBooks&action=DetailView&record=3e78ac33-7c46-1b94-0a67-653a17c06f9e\" target=\"new\">Amazon_2023</a>)<br>";
|
2024-04-27 09:23:34 +02:00
|
|
|
} else {
|
2025-07-06 08:39:16 +00:00
|
|
|
// invoice price?
|
|
|
|
|
$fvPrice = $db->fetchByAssoc($db->query("
|
|
|
|
|
SELECT i.id, i.document_no, ii.price_start, ii.ecmvat_value, ii.ecmvat_name, ii.ecmvat_id
|
|
|
|
|
FROM ecminvoiceoutitems AS ii
|
|
|
|
|
INNER JOIN ecminvoiceouts AS i
|
|
|
|
|
ON i.id = ii.ecminvoiceout_id
|
|
|
|
|
WHERE
|
|
|
|
|
i.parent_id= '1b9643ca-5b1a-8f9b-b809-586b5619b068' AND
|
|
|
|
|
i.currency_id = 'PLN' AND
|
|
|
|
|
ii.ecmproduct_id = '$p->id'
|
|
|
|
|
ORDER BY i.register_date DESC
|
|
|
|
|
LIMIT 0,1
|
|
|
|
|
"));
|
2025-09-15 19:40:04 +02:00
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
if (!isset($fvPrice)) {
|
|
|
|
|
$price_start = 0;
|
|
|
|
|
echo " <b>Brak ceny</b><br>";
|
2025-07-16 18:05:37 +02:00
|
|
|
$vat_id = $product->ecmvat_id;
|
|
|
|
|
$vat_name = $product->ecmvat_name;
|
|
|
|
|
$vat_value = $product->ecmvat_value;
|
2024-04-27 09:23:34 +02:00
|
|
|
} else {
|
2025-07-06 08:39:16 +00:00
|
|
|
$price_start = $fvPrice['price_start'];
|
2025-07-16 18:05:37 +02:00
|
|
|
$vat_id = $fvPrice['ecmvat_id'];
|
|
|
|
|
$vat_name = $fvPrice['ecmvat_name'];
|
|
|
|
|
$vat_value = $fvPrice['ecmvat_value'];
|
2025-09-15 19:40:04 +02:00
|
|
|
echo " Cena: " . $price_start . " (<a href=\"https://crm.e5.pl/index.php?module=EcmInvoiceOuts&action=DetailView&record=" . $fvPrice['id'] . "\" target=\"new\">" . $fvPrice['document_no'] . "</a>)<br>";
|
2024-04-27 09:23:34 +02:00
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
}
|
2025-07-06 08:39:16 +00:00
|
|
|
|
|
|
|
|
$prod = array();
|
2024-04-27 09:23:34 +02:00
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
if (!isset($product->discount)) {
|
|
|
|
|
$product->discount = 0;
|
|
|
|
|
}
|
|
|
|
|
$prod['quantity'] = $product->quantity;
|
|
|
|
|
$prod['discount'] = $product->discount;
|
|
|
|
|
$prod['price_start'] = $price_start;
|
2025-09-15 19:40:04 +02:00
|
|
|
$prod['price_netto'] = round($price_start - ($price_start * ($product->discount / 100)), 2);
|
2025-07-16 18:05:37 +02:00
|
|
|
$prod['ecmvat_id'] = $vat_id;
|
|
|
|
|
$prod['ecmvat_value'] = $vat_value;
|
|
|
|
|
$prod['ecmvat_name'] = $vat_name;
|
2025-09-24 19:27:41 +02:00
|
|
|
$prod['price_netto'] = round((float)$price_start - ((float)$price_start * ((float)$product->discount / 100)), 2);
|
2025-07-06 08:39:16 +00:00
|
|
|
$prod['total_netto'] = round($prod['price_netto'] * $prod['quantity'], 2);
|
2025-09-15 19:40:04 +02:00
|
|
|
$prod['total_brutto'] = round($prod['total_netto'] + ($prod['total_netto'] * ($prod['ecmvat_value'] / 100)), 2);
|
2025-07-06 08:39:16 +00:00
|
|
|
|
|
|
|
|
$total_netto += $prod['total_netto'];
|
|
|
|
|
$total_brutto += $prod['total_brutto'];
|
|
|
|
|
$total_discount = ($prod['price_start'] - $prod['price_netto']) * $prod['quantity'];
|
|
|
|
|
|
|
|
|
|
if (isset($vats[$prod['ecmvat_value']])) {
|
|
|
|
|
$vats[$prod['ecmvat_value']] += $prod['total_netto'];
|
|
|
|
|
} else {
|
2025-09-15 19:40:04 +02:00
|
|
|
$vats[$prod['ecmvat_value']] = $prod['total_netto'];
|
2024-04-27 09:23:34 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
$prod['date_entered'] = date('Y-m-d H:i:s');
|
|
|
|
|
$prod['date_modified'] = date('Y-m-d H:i:s');
|
|
|
|
|
$prod['modified_user_id'] = null;
|
|
|
|
|
$prod['assigned_user_id'] = null;
|
|
|
|
|
$prod['created_by'] = null;
|
|
|
|
|
$prod['deleted'] = '0';
|
|
|
|
|
$prod['product_id'] = $p->id;
|
|
|
|
|
$prod['position'] = $product->position;
|
|
|
|
|
$prod['product_code'] = $p->code;
|
|
|
|
|
$prod['name'] = $product->name;
|
|
|
|
|
$prod['unit_id'] = $product->unit_id;
|
|
|
|
|
$prod['unit_name'] = $product->unit_name;
|
|
|
|
|
$prod['category_id'] = $p->product_category_id;
|
|
|
|
|
$prod['recipient_code'] = $product->recipient_code;
|
|
|
|
|
$prod['ean'] = $p->ean;
|
|
|
|
|
array_push($newPositionList, $prod);
|
2024-04-27 09:23:34 +02:00
|
|
|
}
|
2025-07-06 08:39:16 +00:00
|
|
|
}
|
|
|
|
|
$vats_summary = '';
|
2025-09-15 19:40:04 +02:00
|
|
|
foreach ($vats as $k => $v) {
|
|
|
|
|
$vats_summary .= $k . '%:' . $v . ',';
|
2025-07-06 08:39:16 +00:00
|
|
|
}
|
2024-04-27 09:23:34 +02:00
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
if (!$gotAllProducts) {
|
|
|
|
|
echo 'Brak produktow w bazie E5. Dokument nie zostal skopiowany.';
|
|
|
|
|
die();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require_once('modules/EcmSales/EcmSale.php');
|
|
|
|
|
$new = new EcmSale();
|
|
|
|
|
$new->position_list = $newPositionList;
|
|
|
|
|
$new->parent_id = "1b9643ca-5b1a-8f9b-b809-586b5619b068";
|
|
|
|
|
$new->parent_name = "Twinpol Sp. z o.o.";
|
|
|
|
|
$new->parent_address_street = "al. Lipowa 48";
|
|
|
|
|
$new->parent_address_city = "Obrowo";
|
|
|
|
|
$new->parent_address_postalcode = "87-126";
|
|
|
|
|
$new->parent_address_country = "Polska";
|
|
|
|
|
$new->parent_nip = "8792676609";
|
|
|
|
|
$new->parent_iln = "5909000837119";
|
|
|
|
|
$new->pricebook_id = "13b29aa1-48f0-de58-7630-59c22756c5e4";
|
|
|
|
|
$new->status = "s30";
|
|
|
|
|
$new->type = "sales_order";
|
|
|
|
|
$new->name = $sale->name;
|
|
|
|
|
$new->ecmpaymentcondition_name = "90 dni";
|
|
|
|
|
$new->ecmpaymentcondition_id = "28de9f83-abd3-9a5d-4df9-4df9b7e0031f";
|
|
|
|
|
$new->parent_document_no = $sale->parent_document_no;
|
|
|
|
|
$new->register_date = $sale->register_date;
|
|
|
|
|
$new->send_date = $sale->send_date;
|
|
|
|
|
$new->delivery_date = $sale->delivery_date;
|
|
|
|
|
$new->ecmlanguage = "pl_pl";
|
|
|
|
|
$new->currency_id = 'PLN';
|
|
|
|
|
$new->total_netto = $total_netto;
|
|
|
|
|
$new->total_brutto = $total_brutto;
|
|
|
|
|
$new->discount = $total_discount;
|
|
|
|
|
$new->vats_summary = $vats_summary;
|
|
|
|
|
$new->shipping_address_name = $sale->parent_name;
|
|
|
|
|
$new->shipping_address_street = $sale->parent_address_street;
|
|
|
|
|
$new->shipping_address_postalcode = $sale->parent_address_postalcode;
|
|
|
|
|
$new->shipping_address_city = $sale->parent_address_city;
|
|
|
|
|
$new->shipping_address_country = $sale->parent_address_country;
|
|
|
|
|
$new->shipping_iln = $sale->parent_iln;
|
|
|
|
|
$new->shipping_nip = $sale->parent_nip;
|
|
|
|
|
$new->edi_zs_id = $sale->id;
|
|
|
|
|
$new->edi_zs_document_no = $sale->document_no;
|
|
|
|
|
$new->pdf_text =
|
2025-09-15 19:40:04 +02:00
|
|
|
"Dostawa
|
|
|
|
|
" . $sale->shipping_address_name . "
|
|
|
|
|
" . $sale->shipping_address_street . "
|
|
|
|
|
" . $sale->shipping_address_postalcode . " " . $sale->shipping_address_city . "
|
|
|
|
|
" . $sale->shipping_address_country . "
|
|
|
|
|
NIP: " . $sale->shipping_nip . "
|
|
|
|
|
ILN: " . $sale->shipping_iln;
|
2024-04-27 09:23:34 +02:00
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
$newId = $new->save(true);
|
2024-04-27 09:23:34 +02:00
|
|
|
|
2025-07-06 08:39:16 +00:00
|
|
|
//update E5 number in Twinpol
|
|
|
|
|
$res = $db->fetchByAssoc($db->query("SELECT document_no FROM ecmsales WHERE id='$newId'"));
|
|
|
|
|
$document_no = str_replace(" ", "%20", $res['document_no']);
|
|
|
|
|
makeCUrlRequest("https://crm.twinpol.com/REST/index.php?key=d68dac4c-f784-4e1b-8267-9ffcfa0eda4c&action=updateSaleE5Number&record=$record&e5_record=$newId&e5_document_no=$document_no");
|
2024-04-27 09:23:34 +02:00
|
|
|
|
2025-09-15 19:40:04 +02:00
|
|
|
echo '<a target="new" href="https://crm.e5.pl/index.php?module=EcmSales&action=DetailView&record=' . $newId . '">Utworzono ZS.</a>';
|
2025-07-06 08:39:16 +00:00
|
|
|
die();
|
|
|
|
|
}
|
2024-04-27 09:23:34 +02:00
|
|
|
// local helpers
|
2025-09-15 19:40:04 +02:00
|
|
|
function getProduct($code)
|
|
|
|
|
{
|
2024-04-27 09:23:34 +02:00
|
|
|
$db = $GLOBALS['db'];
|
|
|
|
|
$res = $db->fetchByAssoc($db->query("SELECT * FROM ecmproducts WHERE code='$code' AND deleted=0"));
|
|
|
|
|
if (!$res) {
|
|
|
|
|
return null;
|
|
|
|
|
} else {
|
|
|
|
|
require_once('modules/EcmProducts/EcmProduct.php');
|
|
|
|
|
$prod = new EcmProduct();
|
|
|
|
|
$prod->retrieve($res['id']);
|
|
|
|
|
return $prod;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
function makeCUrlRequest($url)
|
|
|
|
|
{
|
2024-04-27 09:23:34 +02:00
|
|
|
$curl = curl_init();
|
2025-09-15 19:40:04 +02:00
|
|
|
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'GET');
|
2024-04-27 09:23:34 +02:00
|
|
|
curl_setopt($curl, CURLOPT_VERBOSE, 1);
|
|
|
|
|
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
|
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
|
|
|
|
|
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
|
|
|
|
|
curl_setopt($curl, CURLOPT_URL, $url);
|
|
|
|
|
return curl_exec($curl);
|
|
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
function brecho($msg)
|
|
|
|
|
{
|
2024-04-27 09:23:34 +02:00
|
|
|
echo '<br><br>';
|
|
|
|
|
var_dump($msg);
|
|
|
|
|
echo '<br><br>';
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
function createCSVReports()
|
|
|
|
|
{
|
2025-11-10 07:47:51 +00:00
|
|
|
// generateProductComponentsCSV();
|
2025-08-26 22:14:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
$db = $GLOBALS['db'];
|
|
|
|
|
$exportDir = __DIR__ . "/export";
|
|
|
|
|
|
|
|
|
|
$jobs = [
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-26 22:14:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
2025-08-27 07:56:31 +02:00
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
2025-08-26 22:14:04 +02:00
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS group_ks,
|
|
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
|
|
|
|
ii.quantity,
|
2025-11-07 10:21:54 +01:00
|
|
|
ii.price_netto,
|
2025-11-10 07:47:51 +00:00
|
|
|
cur.name AS currency_name
|
2025-08-26 22:14:04 +02:00
|
|
|
FROM ecminvoiceouts AS i
|
|
|
|
|
INNER JOIN ecminvoiceoutitems AS ii ON i.id = ii.ecminvoiceout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
2025-11-07 10:21:54 +01:00
|
|
|
INNER JOIN currencies AS cur ON cur.id = i.currency_id
|
2025-08-26 22:14:04 +02:00
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
|
|
|
|
AND cb.deleted = 0
|
|
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
|
|
|
|
WHERE i.type = 'normal' AND YEAR(i.register_date) = 2024
|
|
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
|
|
|
|
ii.quantity,
|
|
|
|
|
ii.price_netto
|
|
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'invoices_2024.csv',
|
|
|
|
|
], // invoices 2024
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-26 22:14:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
2025-08-27 07:56:31 +02:00
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
2025-08-26 22:14:04 +02:00
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS group_ks,
|
|
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
|
|
|
|
ii.quantity,
|
2025-11-07 10:21:54 +01:00
|
|
|
ii.price_netto,
|
2025-11-10 07:47:51 +00:00
|
|
|
cur.name AS currency_name
|
2025-08-26 22:14:04 +02:00
|
|
|
FROM ecminvoiceouts AS i
|
|
|
|
|
INNER JOIN ecminvoiceoutitems AS ii ON i.id = ii.ecminvoiceout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
2025-11-07 10:21:54 +01:00
|
|
|
INNER JOIN currencies AS cur ON cur.id = i.currency_id
|
2025-08-26 22:14:04 +02:00
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
|
|
|
|
AND cb.deleted = 0
|
|
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
|
|
|
|
WHERE i.type = 'normal' AND YEAR(i.register_date) = 2025
|
|
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
|
|
|
|
ii.quantity,
|
|
|
|
|
ii.price_netto
|
|
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'invoices_2025.csv',
|
|
|
|
|
], // invoices 2025
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-27 08:58:11 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
oi.document_no AS FV,
|
|
|
|
|
oi.register_date AS FV_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
|
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
|
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS group_ks,
|
|
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
|
|
|
|
ii.quantity_corrected AS quantity_correced,
|
2025-11-07 10:21:54 +01:00
|
|
|
ii.total_netto_corrected AS total_netto_corrected,
|
|
|
|
|
cur.name AS currency_name
|
2025-08-27 08:58:11 +02:00
|
|
|
FROM ecminvoiceouts AS i
|
|
|
|
|
INNER JOIN ecminvoiceoutitems AS ii ON i.id = ii.ecminvoiceout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
|
|
|
|
INNER JOIN ecminvoiceouts AS oi ON oi.id = i.ecminvoiceout_id
|
2025-11-07 10:21:54 +01:00
|
|
|
INNER JOIN currencies AS cur ON cur.id = i.currency_id
|
2025-08-27 08:58:11 +02:00
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
|
|
|
|
AND cb.deleted = 0
|
|
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
|
|
|
|
WHERE i.type = 'correct' AND YEAR(i.register_date) = 2024
|
|
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
oi.document_no,
|
|
|
|
|
oi.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
|
|
|
|
ii.quantity,
|
|
|
|
|
ii.price_netto,
|
|
|
|
|
ii.quantity_corrected,
|
|
|
|
|
ii.total_netto_corrected
|
|
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'correct_invoices_2024.csv',
|
|
|
|
|
], // correct invoices 2024
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-27 08:58:11 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
oi.document_no AS FV,
|
|
|
|
|
oi.register_date AS FV_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
|
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
|
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS group_ks,
|
|
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
|
|
|
|
ii.quantity_corrected AS quantity_correced,
|
2025-11-07 10:21:54 +01:00
|
|
|
ii.total_netto_corrected AS total_netto_corrected,
|
|
|
|
|
cur.name AS currency_name
|
2025-08-27 08:58:11 +02:00
|
|
|
FROM ecminvoiceouts AS i
|
|
|
|
|
INNER JOIN ecminvoiceoutitems AS ii ON i.id = ii.ecminvoiceout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
|
|
|
|
INNER JOIN ecminvoiceouts AS oi ON oi.id = i.ecminvoiceout_id
|
2025-11-07 10:21:54 +01:00
|
|
|
INNER JOIN currencies AS cur ON cur.id = i.currency_id
|
2025-08-27 08:58:11 +02:00
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
|
|
|
|
AND cb.deleted = 0
|
|
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
2025-08-27 09:01:48 +02:00
|
|
|
WHERE i.type = 'correct' AND YEAR(i.register_date) = 2025
|
2025-08-27 08:58:11 +02:00
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
oi.document_no,
|
|
|
|
|
oi.register_date,
|
|
|
|
|
i.parent_name,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
|
|
|
|
ii.quantity,
|
|
|
|
|
ii.price_netto,
|
|
|
|
|
ii.quantity_corrected,
|
|
|
|
|
ii.total_netto_corrected
|
|
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'correct_invoices_2025.csv',
|
|
|
|
|
], // correct invoices 2025
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-26 22:14:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
2025-08-27 07:56:31 +02:00
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
2025-08-26 22:14:04 +02:00
|
|
|
ELSE 'Nieznane'
|
2025-08-27 07:56:31 +02:00
|
|
|
END AS group_ks,
|
2025-08-26 22:14:04 +02:00
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
2025-08-27 07:56:31 +02:00
|
|
|
s.name AS stock,
|
|
|
|
|
ii.quantity
|
|
|
|
|
FROM ecmstockdocinsideouts AS i
|
|
|
|
|
INNER JOIN ecmstockdocinsideoutitems AS ii ON i.id = ii.ecmstockdocinsideout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
|
|
|
|
INNER JOIN ecmstocks AS s ON i.stock_id = s.id
|
|
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
2025-08-26 22:14:04 +02:00
|
|
|
AND cb.deleted = 0
|
2025-08-27 07:56:31 +02:00
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
|
|
|
|
WHERE YEAR(i.register_date) = 2025
|
2025-08-26 22:14:04 +02:00
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
2025-08-27 07:56:31 +02:00
|
|
|
s.name,
|
|
|
|
|
ii.quantity
|
2025-08-26 22:14:04 +02:00
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'rw_2025.csv',
|
|
|
|
|
], // rw 2025
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-08-26 22:14:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
CASE p.group_ks
|
|
|
|
|
WHEN 1 THEN 'Towar handlowy'
|
|
|
|
|
WHEN 2 THEN 'Wyrób gotowy'
|
2025-08-27 07:56:31 +02:00
|
|
|
WHEN 3 THEN 'Surowiec'
|
|
|
|
|
WHEN 4 THEN 'Usługa'
|
2025-08-26 22:14:04 +02:00
|
|
|
ELSE 'Nieznane'
|
2025-08-27 07:56:31 +02:00
|
|
|
END AS group_ks,
|
2025-08-26 22:14:04 +02:00
|
|
|
GROUP_CONCAT(c.name ORDER BY cb.position SEPARATOR ' | ') AS category,
|
2025-08-27 07:56:31 +02:00
|
|
|
s.name AS stock,
|
|
|
|
|
ii.quantity
|
|
|
|
|
FROM ecmstockdocinsideouts AS i
|
|
|
|
|
INNER JOIN ecmstockdocinsideoutitems AS ii ON i.id = ii.ecmstockdocinsideout_id
|
|
|
|
|
INNER JOIN ecmproducts AS p ON ii.ecmproduct_id = p.id
|
|
|
|
|
INNER JOIN ecmstocks AS s ON i.stock_id = s.id
|
|
|
|
|
LEFT JOIN ecmproductcategories_bean AS cb ON cb.bean_id COLLATE utf8_general_ci = p.id COLLATE utf8_general_ci
|
|
|
|
|
AND cb.bean_name = 'EcmProducts'
|
2025-08-26 22:14:04 +02:00
|
|
|
AND cb.deleted = 0
|
2025-08-27 07:56:31 +02:00
|
|
|
LEFT JOIN ecmproductcategories AS c ON c.id = cb.ecmproductcategory_id
|
|
|
|
|
WHERE YEAR(i.register_date) = 2024
|
2025-08-26 22:14:04 +02:00
|
|
|
GROUP BY
|
|
|
|
|
i.document_no,
|
|
|
|
|
i.register_date,
|
|
|
|
|
p.code,
|
|
|
|
|
p.name,
|
|
|
|
|
p.group_ks,
|
2025-08-27 07:56:31 +02:00
|
|
|
s.name,
|
|
|
|
|
ii.quantity
|
2025-08-26 22:14:04 +02:00
|
|
|
ORDER BY i.register_date DESC;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'rw_2024.csv',
|
|
|
|
|
], // rw 2024
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-09-15 19:40:04 +02:00
|
|
|
SELECT
|
|
|
|
|
ss.product_code,
|
|
|
|
|
ss.product_name,
|
|
|
|
|
ss.product_id,
|
|
|
|
|
COALESCE(NULLIF(ss.quantity, ''), 0) AS quantity,
|
|
|
|
|
s.name,
|
2025-09-24 19:27:41 +02:00
|
|
|
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
|
2025-09-15 19:40:04 +02:00
|
|
|
FROM ecmstockstates AS ss
|
2025-09-24 19:27:41 +02:00
|
|
|
JOIN ecmstocks AS s ON ss.stock_id = s.id
|
|
|
|
|
LEFT JOIN (
|
2025-09-15 19:40:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.ecmproduct_id,
|
|
|
|
|
SUM(i.quantity) AS ordered_quantity
|
|
|
|
|
FROM ecmsaleitems AS i
|
2025-09-24 19:27:41 +02:00
|
|
|
JOIN ecmsales AS es ON es.id = i.ecmsale_id
|
2025-09-23 14:00:31 +02:00
|
|
|
WHERE es.status IN ('s20','s30') AND es.deleted = '0' AND i.deleted = '0' AND es.register_date >= '2025-06-01'
|
2025-09-15 19:40:04 +02:00
|
|
|
GROUP BY i.ecmproduct_id
|
|
|
|
|
) AS si ON si.ecmproduct_id = ss.product_id
|
2025-09-24 19:27:41 +02:00
|
|
|
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
|
2025-09-23 14:00:31 +02:00
|
|
|
WHERE ss.stock_id IN ('c7afd71a-4c3a-bde4-138d-4acaee1644e4','368479db-22c5-0220-3a14-4bc426b1c709')
|
2025-09-15 19:40:04 +02:00
|
|
|
ORDER BY quantity + 0 DESC;",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'stocks.csv',
|
|
|
|
|
],// stocks
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-09-15 19:40:04 +02:00
|
|
|
SELECT
|
|
|
|
|
i.code AS product_code,
|
|
|
|
|
i.name AS product_name,
|
|
|
|
|
i.quantity,
|
|
|
|
|
i.price_netto,
|
|
|
|
|
es.document_no,
|
2025-09-23 14:08:33 +02:00
|
|
|
es.parent_name,
|
2025-09-15 19:40:04 +02:00
|
|
|
CASE es.status
|
|
|
|
|
WHEN 's20' THEN 'Oczekujący'
|
|
|
|
|
WHEN 's30' THEN 'Zaakceptowany'
|
|
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS status,
|
|
|
|
|
es.register_date,
|
|
|
|
|
es.delivery_date,
|
|
|
|
|
es.send_date
|
|
|
|
|
FROM ecmsaleitems AS i
|
|
|
|
|
JOIN ecmsales AS es ON es.id = i.ecmsale_id
|
2025-09-17 10:11:11 +00:00
|
|
|
WHERE es.status IN ('s20','s30')
|
2025-09-15 19:40:04 +02:00
|
|
|
AND es.deleted = '0'
|
|
|
|
|
AND i.deleted = '0'
|
2025-09-23 14:00:31 +02:00
|
|
|
AND es.register_date >= '2025-06-01'
|
2025-09-17 10:11:11 +00:00
|
|
|
ORDER BY es.register_date DESC, es.document_no DESC, i.position;
|
2025-09-15 19:40:04 +02:00
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'zs.csv',
|
|
|
|
|
], //sales
|
|
|
|
|
[
|
|
|
|
|
'sql' => "
|
2025-09-17 10:11:11 +00:00
|
|
|
SELECT
|
|
|
|
|
i.code AS product_code,
|
|
|
|
|
i.name AS product_name,
|
|
|
|
|
i.quantity,
|
|
|
|
|
i.price_start,
|
|
|
|
|
es.document_no,
|
2025-09-23 14:08:33 +02:00
|
|
|
es.parent_name,
|
2025-09-17 10:11:11 +00:00
|
|
|
CASE es.status
|
|
|
|
|
WHEN 'accepted' THEN 'Zaakceptowany'
|
|
|
|
|
WHEN 'registered' THEN 'Zarejestrowany'
|
|
|
|
|
ELSE 'Nieznane'
|
|
|
|
|
END AS status,
|
|
|
|
|
es.register_date,
|
|
|
|
|
es.delivery_date
|
|
|
|
|
FROM ecmpurchaseorderitems AS i
|
|
|
|
|
JOIN ecmpurchaseorders AS es ON es.id = i.ecmpurchaseorder_id
|
|
|
|
|
WHERE es.status IN ('accepted','registered')
|
|
|
|
|
AND es.deleted = '0'
|
|
|
|
|
AND i.deleted = '0'
|
2025-09-23 14:00:31 +02:00
|
|
|
AND es.register_date >= '2025-06-01'
|
2025-09-17 10:11:11 +00:00
|
|
|
ORDER BY es.register_date DESC, es.document_no DESC, i.position;
|
|
|
|
|
",
|
2025-09-24 19:27:41 +02:00
|
|
|
'filename' => 'zz.csv',
|
|
|
|
|
], //orders
|
|
|
|
|
];
|
2025-08-26 22:14:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
$report = [];
|
|
|
|
|
foreach ($jobs as $job) {
|
|
|
|
|
$sql = $job['sql'];
|
|
|
|
|
$filename = $job['filename'];
|
|
|
|
|
$headers = isset($job['headers']) ? $job['headers'] : null;
|
2025-08-26 22:14:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
$res = $db->query($sql);
|
|
|
|
|
$fullpath = rtrim($exportDir, "/") . "/" . $filename;
|
2025-08-26 22:14:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
$result = exportToCSVFile($res, $fullpath, $headers, ';', true);
|
2025-08-26 22:14:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
if ($result['ok']) {
|
|
|
|
|
$report[] = "OK → {$result['path']} (wiersze: {$result['rows']})" . PHP_EOL;
|
|
|
|
|
} else {
|
|
|
|
|
$report[] = "ERR → {$result['path']} ({$result['error']})" . PHP_EOL;;
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
2025-09-15 19:40:04 +02:00
|
|
|
|
2025-09-24 19:27:41 +02:00
|
|
|
echo implode("\n", $report);
|
|
|
|
|
exit;
|
|
|
|
|
}
|
2025-08-26 22:14:04 +02:00
|
|
|
function exportToCSVFile($res, $fullpath, array $headers = null, $delimiter = ';', $withBom = true)
|
|
|
|
|
{
|
|
|
|
|
$db = $GLOBALS['db'];
|
|
|
|
|
|
|
|
|
|
$dir = dirname($fullpath);
|
|
|
|
|
if (!is_dir($dir)) {
|
|
|
|
|
if (!@mkdir($dir, 0775, true)) {
|
2025-09-15 19:40:04 +02:00
|
|
|
return ['ok' => false, 'path' => $fullpath, 'rows' => 0, 'error' => "Nie mogę utworzyć katalogu: $dir"];
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (!is_writable($dir)) {
|
2025-09-15 19:40:04 +02:00
|
|
|
return ['ok' => false, 'path' => $fullpath, 'rows' => 0, 'error' => "Katalog nie jest zapisywalny: $dir"];
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$fp = @fopen($fullpath, 'w');
|
|
|
|
|
if ($fp === false) {
|
2025-09-15 19:40:04 +02:00
|
|
|
return ['ok' => false, 'path' => $fullpath, 'rows' => 0, 'error' => "Nie mogę otworzyć pliku do zapisu: $fullpath"];
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BOM dla Excel PL
|
|
|
|
|
if ($withBom) {
|
|
|
|
|
fwrite($fp, "\xEF\xBB\xBF");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// pobierz pierwszy wiersz, by ewentualnie zbudować nagłówki
|
|
|
|
|
$first = $db->fetchByAssoc($res);
|
|
|
|
|
|
|
|
|
|
// brak danych → pusty plik z ewentualnym nagłówkiem (jeśli podany ręcznie)
|
|
|
|
|
if (!$first) {
|
|
|
|
|
if ($headers !== null) {
|
|
|
|
|
fputcsv($fp, $headers, $delimiter);
|
|
|
|
|
}
|
|
|
|
|
fclose($fp);
|
2025-09-15 19:40:04 +02:00
|
|
|
return ['ok' => true, 'path' => $fullpath, 'rows' => 0, 'error' => null];
|
2025-08-26 22:14:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// dynamiczne nagłówki, jeśli nie podano
|
|
|
|
|
if ($headers === null) {
|
|
|
|
|
$headers = array_keys($first);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// wypisz nagłówki
|
|
|
|
|
fputcsv($fp, $headers, $delimiter);
|
|
|
|
|
|
|
|
|
|
// zapisz pierwszy wiersz w kolejności nagłówków
|
|
|
|
|
$line = [];
|
2025-09-15 19:40:04 +02:00
|
|
|
foreach ($headers as $h) {
|
|
|
|
|
$line[] = isset($first[$h]) ? $first[$h] : '';
|
|
|
|
|
}
|
2025-08-26 22:14:04 +02:00
|
|
|
fputcsv($fp, $line, $delimiter);
|
|
|
|
|
$count = 1;
|
|
|
|
|
|
|
|
|
|
// pozostałe wiersze
|
|
|
|
|
while ($row = $db->fetchByAssoc($res)) {
|
|
|
|
|
$line = [];
|
2025-09-15 19:40:04 +02:00
|
|
|
foreach ($headers as $h) {
|
|
|
|
|
$line[] = isset($row[$h]) ? $row[$h] : '';
|
|
|
|
|
}
|
2025-08-26 22:14:04 +02:00
|
|
|
fputcsv($fp, $line, $delimiter);
|
|
|
|
|
$count++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fclose($fp);
|
|
|
|
|
$chmod_ok = @chmod($fullpath, 0664);
|
2025-09-15 19:40:04 +02:00
|
|
|
return ['ok' => true, 'path' => $fullpath, 'rows' => $count, 'chmod' => $chmod_ok, 'error' => null];
|
2025-09-24 19:27:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|