extrac prices pdfco
This commit is contained in:
parent
6b65b31932
commit
1804605cad
@ -108,9 +108,9 @@ class LoginController extends Controller
|
|||||||
|
|
||||||
// Reindirizza in base al ruolo
|
// Reindirizza in base al ruolo
|
||||||
if ($user->hasRole('Admin')) {
|
if ($user->hasRole('Admin')) {
|
||||||
return redirect()->to('userarea/import_dashboard.php');
|
return redirect()->to('userarea/import_xls.php');
|
||||||
} elseif ($user->hasRole('User')) {
|
} elseif ($user->hasRole('User')) {
|
||||||
return redirect()->to('userarea/import_dashboard.php');
|
return redirect()->to('userarea/import_xls.php');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Se il ruolo non è specificato, reindirizza alla home predefinita
|
// Se il ruolo non è specificato, reindirizza alla home predefinita
|
||||||
|
|||||||
@ -47,6 +47,7 @@
|
|||||||
"smalot/pdfparser": "^2.12",
|
"smalot/pdfparser": "^2.12",
|
||||||
"socialiteproviders/microsoft": "^4.7",
|
"socialiteproviders/microsoft": "^4.7",
|
||||||
"spatie/laravel-query-builder": "^5.0",
|
"spatie/laravel-query-builder": "^5.0",
|
||||||
|
"spatie/pdf-to-text": "^1.54",
|
||||||
"vanguardapp/activity-log": "^6.0",
|
"vanguardapp/activity-log": "^6.0",
|
||||||
"vanguardapp/announcements": "^6.0",
|
"vanguardapp/announcements": "^6.0",
|
||||||
"vanguardapp/plugins": "^6.0",
|
"vanguardapp/plugins": "^6.0",
|
||||||
|
|||||||
60
composer.lock
generated
60
composer.lock
generated
@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "97382155de516648df8ab1f1c50ab1d5",
|
"content-hash": "d55364bafa22e40dedff454d54442d59",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "akaunting/laravel-setting",
|
"name": "akaunting/laravel-setting",
|
||||||
@ -5290,6 +5290,64 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-05-10T08:19:35+00:00"
|
"time": "2024-05-10T08:19:35+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/pdf-to-text",
|
||||||
|
"version": "1.54.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/pdf-to-text.git",
|
||||||
|
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/pdf-to-text/zipball/ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
|
||||||
|
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.4|^8.0",
|
||||||
|
"symfony/process": "^4.0|^5.0|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"pestphp/pest-plugin-laravel": "^1.3",
|
||||||
|
"phpunit/phpunit": "^9.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\PdfToText\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Extract text from a pdf",
|
||||||
|
"homepage": "https://github.com/spatie/pdf-to-text",
|
||||||
|
"keywords": [
|
||||||
|
"pdf-to-text",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/pdf-to-text/issues",
|
||||||
|
"source": "https://github.com/spatie/pdf-to-text/tree/1.54.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2025-06-13T15:23:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
"version": "v7.1.1",
|
"version": "v7.1.1",
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 6.0 KiB |
73
public/userarea/extract_prices.php
Normal file
73
public/userarea/extract_prices.php
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once __DIR__ . "/../../vendor/autoload.php";
|
||||||
|
|
||||||
|
use Spatie\PdfToText\Pdf;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1) Percorso PDF
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$pdfFile = __DIR__ . "/listino.pdf";
|
||||||
|
|
||||||
|
if (!file_exists($pdfFile)) {
|
||||||
|
die(json_encode(["error" => "PDF non trovato: $pdfFile"]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 2) Estrazione testo usando Poppler
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$poppler = 'C:\poppler\Library\bin\pdftotext.exe';
|
||||||
|
|
||||||
|
try {
|
||||||
|
$text = Pdf::getText($pdfFile, $poppler);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
die(json_encode(["error" => $e->getMessage()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 3) Normalizzazione
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$text = preg_replace('/[ ]{2,}/', ' ', $text);
|
||||||
|
$text = str_replace("\t", " ", $text);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4) REGEX PER IL LISTINO CASSINA
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$regex = '/(\d{3}\s+\d{2,3}\s*[A-Z]?)\s+([^0-9]+?)\s+((?:\d{1,2}[.,]\d{2,3}\s+)+)/';
|
||||||
|
|
||||||
|
preg_match_all($regex, $text, $matches, PREG_SET_ORDER);
|
||||||
|
|
||||||
|
$results = [];
|
||||||
|
|
||||||
|
foreach ($matches as $m) {
|
||||||
|
|
||||||
|
$codice = trim($m[1]);
|
||||||
|
$descr = trim($m[2]);
|
||||||
|
$priceChunk = trim($m[3]);
|
||||||
|
|
||||||
|
// Trova tutti i prezzi
|
||||||
|
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $priceChunk, $nums);
|
||||||
|
|
||||||
|
foreach ($nums[0] as $i => $val) {
|
||||||
|
|
||||||
|
// 10,80 → 10.80
|
||||||
|
$val = str_replace(',', '.', $val);
|
||||||
|
|
||||||
|
$results[] = [
|
||||||
|
"codice" => $codice,
|
||||||
|
"descrizione" => $descr,
|
||||||
|
"colonna" => "COL_" . ($i + 1),
|
||||||
|
"prezzo" => floatval($val)
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 5) Output JSON
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
header("Content-Type: application/json");
|
||||||
|
|
||||||
|
echo json_encode([
|
||||||
|
"items" => count($results),
|
||||||
|
"data" => $results
|
||||||
|
], JSON_PRETTY_PRINT);
|
||||||
218
public/userarea/extract_prices_pdfco.php
Normal file
218
public/userarea/extract_prices_pdfco.php
Normal file
@ -0,0 +1,218 @@
|
|||||||
|
<?php
|
||||||
|
header("Content-Type: application/json; charset=utf-8");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1) CONFIGURAZIONE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
|
||||||
|
$fileToken = "filetoken://37bb07a8561409d281b32bcd023ff3dc33de92a8f65aae5af7";
|
||||||
|
|
||||||
|
// opzionale: passare un token via GET
|
||||||
|
if (isset($_GET['token']) && $_GET['token'] !== "") {
|
||||||
|
$fileToken = $_GET['token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 2) PDF.CO → JSON2
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$endpoint = "https://api.pdf.co/v1/pdf/convert/to/json2";
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
"url" => $fileToken,
|
||||||
|
"inline" => true,
|
||||||
|
"detectTables" => true,
|
||||||
|
"pages" => ""
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = curl_init($endpoint);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Content-Type: application/json",
|
||||||
|
"x-api-key: $apiKey"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
|
||||||
|
if (!$response) {
|
||||||
|
echo json_encode(["error" => "Errore CURL: " . curl_error($ch)]);
|
||||||
|
curl_close($ch);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$json = json_decode($response, true);
|
||||||
|
|
||||||
|
if (!isset($json["body"]["document"]["page"]["row"])) {
|
||||||
|
echo json_encode([
|
||||||
|
"error" => true,
|
||||||
|
"message" => "JSON PDF.co non contiene tabelle utili",
|
||||||
|
"raw" => $json
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$rows = $json["body"]["document"]["page"]["row"];
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 3) FUNZIONI UTILITARIE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
|
// Formato A – 291 02F
|
||||||
|
function isCodeTypeA($txt)
|
||||||
|
{
|
||||||
|
return preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', $txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Estrai blocchi tipo "499 3A 14 5.475"
|
||||||
|
function extractTypeCBlocks($line)
|
||||||
|
{
|
||||||
|
preg_match_all(
|
||||||
|
'/(\d{3})\s+([0-9A-Z]{1,3})\s+(\d{2})\s+(\d{1,2}\.\d{3})/',
|
||||||
|
$line,
|
||||||
|
$m,
|
||||||
|
PREG_SET_ORDER
|
||||||
|
);
|
||||||
|
|
||||||
|
$out = [];
|
||||||
|
foreach ($m as $b) {
|
||||||
|
$out[] = [
|
||||||
|
"codice" => $b[1],
|
||||||
|
"variante" => $b[2],
|
||||||
|
"dimensione" => $b[3],
|
||||||
|
"prezzo" => floatval(str_replace(".", "", $b[4]))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4) PARSER UNICO (GESTISCE TUTTI I FORMATI)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
$currentCode = null;
|
||||||
|
$currentDesc = "";
|
||||||
|
$currentPrices = [];
|
||||||
|
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
|
||||||
|
// Ricostruisco la riga
|
||||||
|
$line = "";
|
||||||
|
foreach ($row["column"] as $col) {
|
||||||
|
if (!isset($col["text"]["text"])) continue;
|
||||||
|
$t = trim($col["text"]["text"]);
|
||||||
|
if ($t !== "") $line .= " " . $t;
|
||||||
|
}
|
||||||
|
$line = trim($line);
|
||||||
|
if ($line === "") continue;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4A — FORMATO CASSINA A (FIX prezzi concatenati)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (preg_match('/^(\d{3}\s+[0-9A-Z]{2,3})\s+(.*)$/', $line, $mA)) {
|
||||||
|
|
||||||
|
$codice = trim($mA[1]);
|
||||||
|
$resto = trim($mA[2]);
|
||||||
|
|
||||||
|
// Estrae TUTTI i prezzi concatenati (es. "10,808.9906.460...")
|
||||||
|
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $resto, $matchesPrezzi);
|
||||||
|
|
||||||
|
if (count($matchesPrezzi[0]) >= 2) {
|
||||||
|
|
||||||
|
// Descrizione SENZA prezzi
|
||||||
|
$descr = trim(preg_replace('/\d{1,2}[.,]\d{2,3}/', '', $resto));
|
||||||
|
|
||||||
|
// Conversione valori
|
||||||
|
$vals = array_map(function ($v) {
|
||||||
|
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
|
||||||
|
}, $matchesPrezzi[0]);
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
"type" => "A",
|
||||||
|
"codice" => $codice,
|
||||||
|
"descrizione" => $descr,
|
||||||
|
"prezzi" => $vals
|
||||||
|
];
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4B — FORMATO VECCHIO CASSINA (003 BC cromata … 8 prezzi)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (preg_match(
|
||||||
|
'/^(\d{3}\s+[A-Z]{1,3})\s+([A-Za-zÀ-ù\s]+?)\s+((?:\d{1,2}[.,]\d{2,3}\s*){8,})$/',
|
||||||
|
$line,
|
||||||
|
$mB
|
||||||
|
)) {
|
||||||
|
$codice = trim($mB[1]);
|
||||||
|
$descr = trim($mB[2]);
|
||||||
|
$valuesString = trim($mB[3]);
|
||||||
|
|
||||||
|
preg_match_all('/\d{1,2}[.,]\d{2,3}/', $valuesString, $vv);
|
||||||
|
|
||||||
|
$vals = array_map(function ($v) {
|
||||||
|
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
|
||||||
|
}, $vv[0]);
|
||||||
|
|
||||||
|
$categorie = ["Z", "Y", "X", "O", "L", "F/COL", "E/COM", "ALTRO"];
|
||||||
|
|
||||||
|
$prezziMappati = [];
|
||||||
|
foreach ($vals as $i => $v) {
|
||||||
|
$key = $categorie[$i] ?? ("COL_" . ($i + 1));
|
||||||
|
$prezziMappati[$key] = $v;
|
||||||
|
}
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
"type" => "B1",
|
||||||
|
"codice" => $codice,
|
||||||
|
"descrizione" => $descr,
|
||||||
|
"prezzi" => $prezziMappati
|
||||||
|
];
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4C — FORMATO LISTINO2 (499 3A 14 5.475 ripetuti)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$blocks = extractTypeCBlocks($line);
|
||||||
|
|
||||||
|
if (!empty($blocks)) {
|
||||||
|
|
||||||
|
$desc = $line;
|
||||||
|
foreach ($blocks as $b) {
|
||||||
|
$pattern = sprintf(
|
||||||
|
'/%s\s+%s\s+%s\s+\d{1,2}\.\d{3}/',
|
||||||
|
$b["codice"],
|
||||||
|
$b["variante"],
|
||||||
|
$b["dimensione"]
|
||||||
|
);
|
||||||
|
$desc = preg_replace($pattern, "", $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = trim($desc);
|
||||||
|
|
||||||
|
$items[] = [
|
||||||
|
"type" => "C",
|
||||||
|
"descrizione" => $desc,
|
||||||
|
"varianti" => $blocks
|
||||||
|
];
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 5) OUTPUT FINALE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
echo json_encode([
|
||||||
|
"status" => "ok",
|
||||||
|
"total" => count($items),
|
||||||
|
"items" => $items
|
||||||
|
], JSON_PRETTY_PRINT);
|
||||||
137
public/userarea/extract_prices_table.php
Normal file
137
public/userarea/extract_prices_table.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
header("Content-Type: application/json; charset=utf-8");
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* CONFIG
|
||||||
|
******************************************************/
|
||||||
|
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
|
||||||
|
$fileToken = "filetoken://61a780917907f86a340290d22c449357dc68950e9066bd67b2";
|
||||||
|
|
||||||
|
// Se passi ?token=xxx usa quello
|
||||||
|
if (!empty($_GET['token'])) {
|
||||||
|
$fileToken = $_GET['token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* 1) ESTRAGGO CSV (solo pagine con tabelle vere)
|
||||||
|
******************************************************/
|
||||||
|
$endpointCsv = "https://api.pdf.co/v1/pdf/convert/to/csv";
|
||||||
|
|
||||||
|
$payloadCsv = [
|
||||||
|
"url" => $fileToken,
|
||||||
|
"inline" => true,
|
||||||
|
"detectTables" => true,
|
||||||
|
"pages" => "all",
|
||||||
|
"extractColumnBy" => "vertical_lines",
|
||||||
|
"csvSeparator" => ";"
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = curl_init($endpointCsv);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Content-Type: application/json",
|
||||||
|
"x-api-key: $apiKey"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payloadCsv));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$csvResponse = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$csvJson = json_decode($csvResponse, true);
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* 2) ESTRAGGO ANCHE TESTO (per pagine NON tabellari)
|
||||||
|
******************************************************/
|
||||||
|
$endpointText = "https://api.pdf.co/v1/pdf/convert/to/text";
|
||||||
|
|
||||||
|
$payloadText = [
|
||||||
|
"url" => $fileToken,
|
||||||
|
"inline" => true,
|
||||||
|
"pages" => "all"
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = curl_init($endpointText);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Content-Type: application/json",
|
||||||
|
"x-api-key: $apiKey"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payloadText));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$textResponse = curl_exec($ch);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$textJson = json_decode($textResponse, true);
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* 3) PARSER CSV → TABELLE FORMATO A
|
||||||
|
******************************************************/
|
||||||
|
$formatoA = [];
|
||||||
|
|
||||||
|
if (isset($csvJson["csv"])) {
|
||||||
|
$rows = explode("\n", $csvJson["csv"]);
|
||||||
|
|
||||||
|
foreach ($rows as $r) {
|
||||||
|
$cols = str_getcsv($r, ";");
|
||||||
|
|
||||||
|
if (count($cols) < 2) continue;
|
||||||
|
if (!preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', trim($cols[0]))) continue;
|
||||||
|
|
||||||
|
$formatoA[] = [
|
||||||
|
"codice" => trim($cols[0]),
|
||||||
|
"descrizione" => trim($cols[1]),
|
||||||
|
"prezzi" => array_map(fn($x) => is_numeric(str_replace(",", ".", $x))
|
||||||
|
? floatval(str_replace(",", ".", $x))
|
||||||
|
: null, array_slice($cols, 2))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* 4) PARSER TESTUALE → FORMATO B (pagina tipo 499…)
|
||||||
|
******************************************************/
|
||||||
|
$formatoB = [];
|
||||||
|
|
||||||
|
if (isset($textJson["body"])) {
|
||||||
|
|
||||||
|
$text = $textJson["body"];
|
||||||
|
|
||||||
|
// pattern codice tipo “499 3A 14”
|
||||||
|
$codeRegex = '/\b(\d{3}\s+[A-Z0-9]{1,2}\s+\d{2})\b/';
|
||||||
|
|
||||||
|
// pattern prezzo “5.475” o “5475” o “6.085”
|
||||||
|
$priceRegex = '/\b\d{1,2}\.?\d{3}\b/';
|
||||||
|
|
||||||
|
// Cerca combinazioni CODICE + PREZZO ripetute sulla stessa riga
|
||||||
|
$linee = explode("\n", $text);
|
||||||
|
|
||||||
|
foreach ($linee as $line) {
|
||||||
|
|
||||||
|
if (!preg_match_all($codeRegex, $line, $codici)) continue;
|
||||||
|
if (!preg_match_all($priceRegex, $line, $prezzi)) continue;
|
||||||
|
|
||||||
|
$codici = $codici[1];
|
||||||
|
$prezzi = $prezzi[0];
|
||||||
|
|
||||||
|
// Se quantità corrispondono → coppie 1:1
|
||||||
|
if (count($codici) == count($prezzi)) {
|
||||||
|
for ($i = 0; $i < count($codici); $i++) {
|
||||||
|
$formatoB[] = [
|
||||||
|
"codice" => $codici[$i],
|
||||||
|
"prezzo" => floatval(str_replace(".", "", $prezzi[$i]))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************
|
||||||
|
* 5) OUTPUT
|
||||||
|
******************************************************/
|
||||||
|
echo json_encode([
|
||||||
|
"status" => "ok",
|
||||||
|
"formatoA" => $formatoA,
|
||||||
|
"formatoB" => $formatoB,
|
||||||
|
], JSON_PRETTY_PRINT);
|
||||||
@ -45,139 +45,140 @@ $pdo = $db->getConnection();
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<?php include('include/navbar.php'); ?>
|
<div class="wrapper">
|
||||||
<div class="dashboard-main-wrapper wrapper">
|
<?php include('include/navbar.php'); ?>
|
||||||
<?php include('include/topbar.php'); ?>
|
<div class="dashboard-main-wrapper wrapper">
|
||||||
|
<?php include('include/topbar.php'); ?>
|
||||||
|
|
||||||
<div class="dashboard-body">
|
<div class="dashboard-body">
|
||||||
<div class="card shadow-sm">
|
<div class="card shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="d-flex flex-wrap justify-content-between align-items-center mb-3">
|
<div class="d-flex flex-wrap justify-content-between align-items-center mb-3">
|
||||||
<h4 class="mb-0">Imported Data</h4>
|
<h4 class="mb-0">Imported Data</h4>
|
||||||
<div class="d-flex align-items-center gap-2">
|
<div class="d-flex align-items-center gap-2">
|
||||||
<label for="clientFilter" class="form-label mb-0 me-2">Filter by Client:</label>
|
<label for="clientFilter" class="form-label mb-0 me-2">Filter by Client:</label>
|
||||||
<select id="clientFilter" class="form-select form-select-sm" style="width: 220px;">
|
<select id="clientFilter" class="form-select form-select-sm" style="width: 220px;">
|
||||||
<option value="">All Clients</option>
|
<option value="">All Clients</option>
|
||||||
<?php
|
<?php
|
||||||
// carichiamo i clienti dal DB
|
// carichiamo i clienti dal DB
|
||||||
$clients = $pdo->query("SELECT idclient, client_name FROM clients ORDER BY client_name")->fetchAll(PDO::FETCH_ASSOC);
|
$clients = $pdo->query("SELECT idclient, client_name FROM clients ORDER BY client_name")->fetchAll(PDO::FETCH_ASSOC);
|
||||||
foreach ($clients as $cl) {
|
foreach ($clients as $cl) {
|
||||||
echo '<option value="' . htmlspecialchars($cl['idclient']) . '">' . htmlspecialchars($cl['client_name']) . '</option>';
|
echo '<option value="' . htmlspecialchars($cl['idclient']) . '">' . htmlspecialchars($cl['client_name']) . '</option>';
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</select>
|
</select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="d-flex justify-content-between align-items-center mb-2">
|
||||||
<div class="d-flex justify-content-between align-items-center mb-2">
|
<div>
|
||||||
<div>
|
<button id="updatePricesBtn" class="btn btn-warning btn-sm" style="display:none;">
|
||||||
<button id="updatePricesBtn" class="btn btn-warning btn-sm" style="display:none;">
|
<i class="fas fa-sync-alt"></i> Aggiorna Prezzi
|
||||||
<i class="fas fa-sync-alt"></i> Aggiorna Prezzi
|
</button>
|
||||||
</button>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="importTable" class="table table-striped table-bordered w-100">
|
<table id="importTable" class="table table-striped table-bordered w-100">
|
||||||
|
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th></th> <!-- Checkbox column -->
|
<th></th> <!-- Checkbox column -->
|
||||||
<th>ID</th>
|
<th>ID</th>
|
||||||
<th>Collection</th>
|
<th>Collection</th>
|
||||||
<th>Category</th>
|
<th>Category</th>
|
||||||
<th>Model</th>
|
<th>Model</th>
|
||||||
<th>Model Description</th>
|
<th>Model Description</th>
|
||||||
<th>Mod.Code</th>
|
<th>Mod.Code</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<th>Finish.Code</th>
|
<th>Finish.Code</th>
|
||||||
<th>Finishing Description</th>
|
<th>Finishing Description</th>
|
||||||
<th>Available Qty</th>
|
<th>Available Qty</th>
|
||||||
<th>WH</th>
|
<th>WH</th>
|
||||||
<th>Price</th>
|
<th>Price</th>
|
||||||
<th>Actions</th>
|
<th>Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
</table>
|
</table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php include('include/footer.php'); ?>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php include('include/footer.php'); ?>
|
<?php include('jsinclude.php'); ?>
|
||||||
</div>
|
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
|
||||||
|
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
|
||||||
|
|
||||||
<?php include('jsinclude.php'); ?>
|
<script>
|
||||||
<script src="https://cdn.datatables.net/1.13.6/js/jquery.dataTables.min.js"></script>
|
$(document).ready(function() {
|
||||||
<script src="https://cdn.datatables.net/1.13.6/js/dataTables.bootstrap5.min.js"></script>
|
let table = $('#importTable').DataTable({
|
||||||
|
ajax: {
|
||||||
<script>
|
url: 'import_list_data.php',
|
||||||
$(document).ready(function() {
|
dataSrc: ''
|
||||||
let table = $('#importTable').DataTable({
|
|
||||||
ajax: {
|
|
||||||
url: 'import_list_data.php',
|
|
||||||
dataSrc: ''
|
|
||||||
},
|
|
||||||
columns: [{
|
|
||||||
data: null,
|
|
||||||
orderable: false,
|
|
||||||
searchable: false,
|
|
||||||
className: 'text-center',
|
|
||||||
render: function() {
|
|
||||||
return '<input type="checkbox" class="row-check" />';
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
columns: [{
|
||||||
data: 'id'
|
data: null,
|
||||||
},
|
orderable: false,
|
||||||
{
|
searchable: false,
|
||||||
data: 'collection',
|
className: 'text-center',
|
||||||
className: 'editable'
|
render: function() {
|
||||||
},
|
return '<input type="checkbox" class="row-check" />';
|
||||||
{
|
}
|
||||||
data: 'category',
|
},
|
||||||
className: 'noedit text-muted'
|
{
|
||||||
},
|
data: 'id'
|
||||||
{
|
},
|
||||||
data: 'model',
|
{
|
||||||
className: 'editable'
|
data: 'collection',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'model_description',
|
{
|
||||||
className: 'editable'
|
data: 'category',
|
||||||
},
|
className: 'noedit text-muted'
|
||||||
{
|
},
|
||||||
data: 'mod_code',
|
{
|
||||||
className: 'text-muted'
|
data: 'model',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'description',
|
{
|
||||||
className: 'editable'
|
data: 'model_description',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'finish_code',
|
{
|
||||||
className: 'editable'
|
data: 'mod_code',
|
||||||
},
|
className: 'text-muted'
|
||||||
{
|
},
|
||||||
data: 'finishing_description',
|
{
|
||||||
className: 'editable'
|
data: 'description',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'available_qty',
|
{
|
||||||
className: 'editable'
|
data: 'finish_code',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'wh',
|
{
|
||||||
className: 'editable'
|
data: 'finishing_description',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: 'price',
|
{
|
||||||
className: 'editable'
|
data: 'available_qty',
|
||||||
},
|
className: 'editable'
|
||||||
{
|
},
|
||||||
data: null,
|
{
|
||||||
orderable: false,
|
data: 'wh',
|
||||||
render: function(data, type, row) {
|
className: 'editable'
|
||||||
return `
|
},
|
||||||
|
{
|
||||||
|
data: 'price',
|
||||||
|
className: 'editable'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: null,
|
||||||
|
orderable: false,
|
||||||
|
render: function(data, type, row) {
|
||||||
|
return `
|
||||||
<button class="btn btn-success btn-sm action-btn save-row" data-id="${row.id}">
|
<button class="btn btn-success btn-sm action-btn save-row" data-id="${row.id}">
|
||||||
<i class="fas fa-save"></i>
|
<i class="fas fa-save"></i>
|
||||||
</button>
|
</button>
|
||||||
@ -185,228 +186,239 @@ $pdo = $db->getConnection();
|
|||||||
<i class="fas fa-trash"></i>
|
<i class="fas fa-trash"></i>
|
||||||
</button>
|
</button>
|
||||||
`;
|
`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
],
|
||||||
],
|
pageLength: 25,
|
||||||
pageLength: 25,
|
order: [
|
||||||
order: [
|
[1, 'desc']
|
||||||
[1, 'desc']
|
],
|
||||||
],
|
responsive: true,
|
||||||
responsive: true,
|
autoWidth: false
|
||||||
autoWidth: false
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
// === Filtro per Client ===
|
// === Filtro per Client ===
|
||||||
$('#clientFilter').on('change', function() {
|
$('#clientFilter').on('change', function() {
|
||||||
const selectedClient = $(this).val();
|
const selectedClient = $(this).val();
|
||||||
|
|
||||||
// Ricarica i dati passando il parametro idclient
|
// Ricarica i dati passando il parametro idclient
|
||||||
table.ajax.url('import_list_data.php' + (selectedClient ? '?idclient=' + selectedClient : '')).load();
|
table.ajax.url('import_list_data.php' + (selectedClient ? '?idclient=' + selectedClient : '')).load();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// === Inline Editing ===
|
// === Inline Editing ===
|
||||||
$('#importTable tbody').on('click', 'td.editable', function() {
|
$('#importTable tbody').on('click', 'td.editable', function() {
|
||||||
const cell = table.cell(this);
|
const cell = table.cell(this);
|
||||||
const rowData = table.row(cell.index().row).data();
|
const rowData = table.row(cell.index().row).data();
|
||||||
const colName = table.column(cell.index().column).dataSrc();
|
const colName = table.column(cell.index().column).dataSrc();
|
||||||
const originalValue = rowData[colName] ?? '';
|
const originalValue = rowData[colName] ?? '';
|
||||||
|
|
||||||
// Evita doppia apertura
|
// Evita doppia apertura
|
||||||
if ($(this).find('input').length > 0) return;
|
if ($(this).find('input').length > 0) return;
|
||||||
|
|
||||||
const input = $('<input type="text" class="form-control form-control-sm"/>')
|
const input = $('<input type="text" class="form-control form-control-sm"/>')
|
||||||
.val(originalValue)
|
.val(originalValue)
|
||||||
.css({
|
.css({
|
||||||
'min-width': '120px',
|
'min-width': '120px',
|
||||||
'height': '24px',
|
'height': '24px',
|
||||||
'padding': '0 4px'
|
'padding': '0 4px'
|
||||||
|
});
|
||||||
|
|
||||||
|
$(this).html(input);
|
||||||
|
input.focus();
|
||||||
|
|
||||||
|
// Gestione conferma o uscita
|
||||||
|
input.on('blur keydown', function(e) {
|
||||||
|
if (e.type === 'blur' || e.key === 'Enter') {
|
||||||
|
const newValue = $(this).val();
|
||||||
|
// Aggiorna in memoria e interfaccia
|
||||||
|
rowData[colName] = newValue;
|
||||||
|
table.row(cell.index().row).data(rowData).draw(false);
|
||||||
|
|
||||||
|
const td = $(table.cell(cell.index()).node());
|
||||||
|
if (newValue !== originalValue) {
|
||||||
|
td.addClass('modified'); // evidenzia modificato
|
||||||
|
} else {
|
||||||
|
td.removeClass('modified');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// === Salvataggio singola riga ===
|
||||||
|
$('#importTable').on('click', '.save-row', function() {
|
||||||
|
const rowData = table.row($(this).closest('tr')).data();
|
||||||
|
$.ajax({
|
||||||
|
url: 'import_list_save.php',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
row: JSON.stringify(rowData)
|
||||||
|
},
|
||||||
|
success: function(res) {
|
||||||
|
Swal.close();
|
||||||
|
|
||||||
|
// Se il server restituisce già JSON, non serve JSON.parse()
|
||||||
|
let json = (typeof res === 'object') ? res : null;
|
||||||
|
if (!json) {
|
||||||
|
try {
|
||||||
|
json = JSON.parse(res);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("Invalid JSON from server:", res);
|
||||||
|
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.status === 'ok') {
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Successo',
|
||||||
|
text: `Aggiornati ${json.updated} prezzi.`,
|
||||||
|
icon: 'success',
|
||||||
|
timer: 2000,
|
||||||
|
showConfirmButton: false
|
||||||
|
});
|
||||||
|
table.ajax.reload(null, false); // 🔁 aggiorna tabella
|
||||||
|
} else {
|
||||||
|
console.error("Errore backend:", json);
|
||||||
|
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function(xhr, status, err) {
|
||||||
|
Swal.fire('Errore', 'Errore di rete o server non raggiungibile.', 'error');
|
||||||
|
console.error("AJAX error:", status, err, xhr.responseText);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// === Eliminazione con conferma ===
|
||||||
|
$('#importTable').on('click', '.delete-row', function() {
|
||||||
|
const id = $(this).data('id');
|
||||||
|
Swal.fire({
|
||||||
|
title: 'Are you sure?',
|
||||||
|
text: 'This record will be permanently deleted.',
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Yes, delete it',
|
||||||
|
cancelButtonText: 'Cancel'
|
||||||
|
}).then(result => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'import_list_delete.php',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
id: id
|
||||||
|
},
|
||||||
|
success: function(res) {
|
||||||
|
let json;
|
||||||
|
try {
|
||||||
|
json = JSON.parse(res);
|
||||||
|
} catch (e) {
|
||||||
|
Swal.fire('Error', res, 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (json.status === 'ok') {
|
||||||
|
Swal.fire('Deleted', 'Row removed successfully.', 'success');
|
||||||
|
table.ajax.reload(null, false);
|
||||||
|
} else {
|
||||||
|
Swal.fire('Error', json.message, 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error: function() {
|
||||||
|
Swal.fire('Error', 'Request failed.', 'error');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// === Gestione selezione righe e pulsante Aggiorna Prezzi ===
|
||||||
|
$('#importTable').on('change', '.row-check', function() {
|
||||||
|
const checkedCount = $('#importTable .row-check:checked').length;
|
||||||
|
$('#updatePricesBtn').toggle(checkedCount > 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// === Aggiornamento prezzi con ChatPDF ===
|
||||||
|
$('#updatePricesBtn').on('click', function() {
|
||||||
|
const selectedRows = [];
|
||||||
|
|
||||||
|
$('#importTable .row-check:checked').each(function() {
|
||||||
|
const row = table.row($(this).closest('tr')).data();
|
||||||
|
if (row) selectedRows.push(row);
|
||||||
});
|
});
|
||||||
|
|
||||||
$(this).html(input);
|
if (selectedRows.length === 0) {
|
||||||
input.focus();
|
Swal.fire('Notice', 'Seleziona almeno una riga.', 'info');
|
||||||
|
return;
|
||||||
// Gestione conferma o uscita
|
|
||||||
input.on('blur keydown', function(e) {
|
|
||||||
if (e.type === 'blur' || e.key === 'Enter') {
|
|
||||||
const newValue = $(this).val();
|
|
||||||
// Aggiorna in memoria e interfaccia
|
|
||||||
rowData[colName] = newValue;
|
|
||||||
table.row(cell.index().row).data(rowData).draw(false);
|
|
||||||
|
|
||||||
const td = $(table.cell(cell.index()).node());
|
|
||||||
if (newValue !== originalValue) {
|
|
||||||
td.addClass('modified'); // evidenzia modificato
|
|
||||||
} else {
|
|
||||||
td.removeClass('modified');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// === Salvataggio singola riga ===
|
const clientId = $('#clientFilter').val();
|
||||||
$('#importTable').on('click', '.save-row', function() {
|
if (!clientId) {
|
||||||
const rowData = table.row($(this).closest('tr')).data();
|
Swal.fire('Notice', 'Seleziona prima un cliente.', 'info');
|
||||||
$.ajax({
|
return;
|
||||||
url: 'import_list_save.php',
|
}
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
row: JSON.stringify(rowData)
|
|
||||||
},
|
|
||||||
success: function(res) {
|
|
||||||
Swal.close();
|
|
||||||
|
|
||||||
// Se il server restituisce già JSON, non serve JSON.parse()
|
Swal.fire({
|
||||||
let json = (typeof res === 'object') ? res : null;
|
title: 'Aggiornare i prezzi?',
|
||||||
if (!json) {
|
text: `Verranno interrogati i prezzi per ${selectedRows.length} prodotti.`,
|
||||||
try {
|
icon: 'question',
|
||||||
json = JSON.parse(res);
|
showCancelButton: true,
|
||||||
} catch (e) {
|
confirmButtonText: 'Procedi',
|
||||||
console.error("Invalid JSON from server:", res);
|
cancelButtonText: 'Annulla'
|
||||||
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
|
}).then(result => {
|
||||||
return;
|
if (result.isConfirmed) {
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (json.status === 'ok') {
|
|
||||||
Swal.fire({
|
Swal.fire({
|
||||||
title: 'Successo',
|
title: 'Aggiornamento in corso...',
|
||||||
text: `Aggiornati ${json.updated} prezzi.`,
|
allowOutsideClick: false,
|
||||||
icon: 'success',
|
didOpen: () => Swal.showLoading()
|
||||||
timer: 2000,
|
});
|
||||||
showConfirmButton: false
|
|
||||||
|
$.ajax({
|
||||||
|
url: 'update_prices_chatpdf.php',
|
||||||
|
type: 'POST',
|
||||||
|
data: {
|
||||||
|
rows: JSON.stringify(selectedRows),
|
||||||
|
idclient: clientId
|
||||||
|
},
|
||||||
|
success: function(res) {
|
||||||
|
Swal.close();
|
||||||
|
|
||||||
|
// Se il server ha già restituito un oggetto JSON, usiamolo direttamente
|
||||||
|
let json = (typeof res === "object") ? res : null;
|
||||||
|
|
||||||
|
// Se invece è una stringa JSON, parse
|
||||||
|
if (!json) {
|
||||||
|
try {
|
||||||
|
json = JSON.parse(res);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("JSON parse error:", res);
|
||||||
|
Swal.fire('Errore', 'Risposta non valida dal server.', 'error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ora siamo sicuri che json è un oggetto valido
|
||||||
|
if (json.status === 'ok') {
|
||||||
|
Swal.fire('Successo', `Aggiornati ${json.updated} prezzi.`, 'success');
|
||||||
|
table.ajax.reload(null, false);
|
||||||
|
} else {
|
||||||
|
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
error: function() {
|
||||||
|
Swal.fire('Errore', 'Aggiornamento fallito.', 'error');
|
||||||
|
}
|
||||||
});
|
});
|
||||||
table.ajax.reload(null, false); // 🔁 aggiorna tabella
|
|
||||||
} else {
|
|
||||||
console.error("Errore backend:", json);
|
|
||||||
Swal.fire('Errore', json.message || 'Errore sconosciuto.', 'error');
|
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
error: function(xhr, status, err) {
|
|
||||||
Swal.fire('Errore', 'Errore di rete o server non raggiungibile.', 'error');
|
|
||||||
console.error("AJAX error:", status, err, xhr.responseText);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// === Eliminazione con conferma ===
|
|
||||||
$('#importTable').on('click', '.delete-row', function() {
|
|
||||||
const id = $(this).data('id');
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Are you sure?',
|
|
||||||
text: 'This record will be permanently deleted.',
|
|
||||||
icon: 'warning',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: 'Yes, delete it',
|
|
||||||
cancelButtonText: 'Cancel'
|
|
||||||
}).then(result => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
$.ajax({
|
|
||||||
url: 'import_list_delete.php',
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
id: id
|
|
||||||
},
|
|
||||||
success: function(res) {
|
|
||||||
let json;
|
|
||||||
try {
|
|
||||||
json = JSON.parse(res);
|
|
||||||
} catch (e) {
|
|
||||||
Swal.fire('Error', res, 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (json.status === 'ok') {
|
|
||||||
Swal.fire('Deleted', 'Row removed successfully.', 'success');
|
|
||||||
table.ajax.reload(null, false);
|
|
||||||
} else {
|
|
||||||
Swal.fire('Error', json.message, 'error');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
Swal.fire('Error', 'Request failed.', 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// === Gestione selezione righe e pulsante Aggiorna Prezzi ===
|
|
||||||
$('#importTable').on('change', '.row-check', function() {
|
|
||||||
const checkedCount = $('#importTable .row-check:checked').length;
|
|
||||||
$('#updatePricesBtn').toggle(checkedCount > 0);
|
|
||||||
});
|
|
||||||
|
|
||||||
// === Aggiornamento prezzi con ChatPDF ===
|
|
||||||
$('#updatePricesBtn').on('click', function() {
|
|
||||||
const selectedRows = [];
|
|
||||||
|
|
||||||
$('#importTable .row-check:checked').each(function() {
|
|
||||||
const row = table.row($(this).closest('tr')).data();
|
|
||||||
if (row) selectedRows.push(row);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (selectedRows.length === 0) {
|
|
||||||
Swal.fire('Notice', 'Seleziona almeno una riga.', 'info');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const clientId = $('#clientFilter').val();
|
|
||||||
if (!clientId) {
|
|
||||||
Swal.fire('Notice', 'Seleziona prima un cliente.', 'info');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Aggiornare i prezzi?',
|
|
||||||
text: `Verranno interrogati i prezzi per ${selectedRows.length} prodotti.`,
|
|
||||||
icon: 'question',
|
|
||||||
showCancelButton: true,
|
|
||||||
confirmButtonText: 'Procedi',
|
|
||||||
cancelButtonText: 'Annulla'
|
|
||||||
}).then(result => {
|
|
||||||
if (result.isConfirmed) {
|
|
||||||
Swal.fire({
|
|
||||||
title: 'Aggiornamento in corso...',
|
|
||||||
allowOutsideClick: false,
|
|
||||||
didOpen: () => Swal.showLoading()
|
|
||||||
});
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: 'update_prices_chatpdf.php',
|
|
||||||
type: 'POST',
|
|
||||||
data: {
|
|
||||||
rows: JSON.stringify(selectedRows),
|
|
||||||
idclient: clientId
|
|
||||||
},
|
|
||||||
success: function(res) {
|
|
||||||
Swal.close();
|
|
||||||
let json;
|
|
||||||
try {
|
|
||||||
json = JSON.parse(res);
|
|
||||||
} catch (e) {
|
|
||||||
Swal.fire('Errore', res, 'error');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (json.status === 'ok') {
|
|
||||||
Swal.fire('Successo', `Aggiornati ${json.updated} prezzi.`, 'success');
|
|
||||||
table.ajax.reload(null, false);
|
|
||||||
} else {
|
|
||||||
Swal.fire('Errore', json.message, 'error');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
error: function() {
|
|
||||||
Swal.fire('Errore', 'Aggiornamento fallito.', 'error');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
</script>
|
||||||
|
</div> <!-- end wrapper -->
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@ -22,9 +22,10 @@
|
|||||||
<ul>
|
<ul>
|
||||||
<!-- <li> <a href="index.php"><i class='bx bx-radio-circle'></i>Default</a>
|
<!-- <li> <a href="index.php"><i class='bx bx-radio-circle'></i>Default</a>
|
||||||
</li> -->
|
</li> -->
|
||||||
<li> <a href="import_dashboard.php"><i class='bx bx-radio-circle'></i>XLS Import</a>
|
<li> <a href="import_xls.php"><i class='bx bx-radio-circle'></i>XLS Import</a>
|
||||||
|
</li>
|
||||||
|
<li> <a href="import_list.php"><i class='bx bx-radio-circle'></i>Imported LIST</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
217
public/userarea/jsonraw.php
Normal file
217
public/userarea/jsonraw.php
Normal file
@ -0,0 +1,217 @@
|
|||||||
|
<?php
|
||||||
|
header("Content-Type: application/json; charset=utf-8");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1) CONFIGURAZIONE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$apiKey = "info@claudiosironi.com_Qfh02D7sAvi2tcx3ZchHpusNaBquCKhJw81fEnkHe2ersQDVOex4IokhCCzaFAz1";
|
||||||
|
$fileToken = "filetoken://61a780917907f86a340290d22c449357dc68950e9066bd67b2";
|
||||||
|
|
||||||
|
// opzionale: passare un token via GET
|
||||||
|
if (isset($_GET['token']) && $_GET['token'] !== "") {
|
||||||
|
$fileToken = $_GET['token'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 2) PDF.CO → JSON2 (TUTTE LE PAGINE)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$endpoint = "https://api.pdf.co/v1/pdf/convert/to/json2";
|
||||||
|
|
||||||
|
$payload = [
|
||||||
|
"url" => $fileToken,
|
||||||
|
"inline" => true,
|
||||||
|
"detectTables" => true,
|
||||||
|
"pages" => "all"
|
||||||
|
];
|
||||||
|
|
||||||
|
$ch = curl_init($endpoint);
|
||||||
|
curl_setopt($ch, CURLOPT_POST, true);
|
||||||
|
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||||
|
"Content-Type: application/json",
|
||||||
|
"x-api-key: $apiKey"
|
||||||
|
]);
|
||||||
|
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
|
||||||
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||||
|
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
|
||||||
|
if (!$response) {
|
||||||
|
echo json_encode(["error" => "Errore CURL: " . curl_error($ch)]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
$json = json_decode($response, true);
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 3) VALIDAZIONE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (!isset($json["body"]["document"]["page"])) {
|
||||||
|
echo json_encode([
|
||||||
|
"error" => true,
|
||||||
|
"message" => "PDF.co JSON senza pagine valide",
|
||||||
|
"raw" => $json
|
||||||
|
]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$pages = $json["body"]["document"]["page"];
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 4) FUNZIONI UTILI
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
|
||||||
|
// Formato A – 291 02F
|
||||||
|
function isCodeTypeA($txt)
|
||||||
|
{
|
||||||
|
return preg_match('/^\d{3}\s+[0-9A-Z]{2,3}$/', $txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Formato C – blocchi ripetuti (499 3A 14 5.475)
|
||||||
|
function extractTypeCBlocks($line)
|
||||||
|
{
|
||||||
|
preg_match_all(
|
||||||
|
'/(\d{3})\s+([0-9A-Z]{1,3})\s+(\d{2})\s+(\d{1,3}\.\d{3})/',
|
||||||
|
$line,
|
||||||
|
$m,
|
||||||
|
PREG_SET_ORDER
|
||||||
|
);
|
||||||
|
|
||||||
|
$out = [];
|
||||||
|
foreach ($m as $b) {
|
||||||
|
$out[] = [
|
||||||
|
"codice" => $b[1],
|
||||||
|
"variante" => $b[2],
|
||||||
|
"dimensione" => $b[3],
|
||||||
|
"prezzo" => floatval(str_replace(".", "", $b[4]))
|
||||||
|
];
|
||||||
|
}
|
||||||
|
return $out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 5) PARSER PER UNA SINGOLA RIGA (ricostruita)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
function parseLine($line)
|
||||||
|
{
|
||||||
|
// FORMATO A
|
||||||
|
if (preg_match('/^(\d{3}\s+[0-9A-Z]{2,3})\s+(.*)$/', $line, $mA)) {
|
||||||
|
|
||||||
|
$codice = trim($mA[1]);
|
||||||
|
$resto = trim($mA[2]);
|
||||||
|
|
||||||
|
preg_match_all('/\d{1,3}[.,]\d{2,3}/', $resto, $matchesPrezzi);
|
||||||
|
|
||||||
|
if (count($matchesPrezzi[0]) >= 2) {
|
||||||
|
|
||||||
|
$descr = trim(preg_replace('/\d{1,3}[.,]\d{2,3}/', '', $resto));
|
||||||
|
|
||||||
|
$vals = array_map(function ($v) {
|
||||||
|
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
|
||||||
|
}, $matchesPrezzi[0]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
"type" => "A",
|
||||||
|
"codice" => $codice,
|
||||||
|
"descrizione" => $descr,
|
||||||
|
"prezzi" => $vals
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FORMATO B1
|
||||||
|
if (preg_match(
|
||||||
|
'/^(\d{3}\s+[A-Z]{1,3})\s+([A-Za-zÀ-ù0-9\s]+?)\s+((?:\d{1,3}[.,]\d{2,3}\s*){4,})$/',
|
||||||
|
$line,
|
||||||
|
$mB
|
||||||
|
)) {
|
||||||
|
$codice = trim($mB[1]);
|
||||||
|
$descr = trim($mB[2]);
|
||||||
|
$valuesString = trim($mB[3]);
|
||||||
|
|
||||||
|
preg_match_all('/\d{1,3}[.,]\d{2,3}/', $valuesString, $vv);
|
||||||
|
|
||||||
|
$vals = array_map(function ($v) {
|
||||||
|
return floatval(str_replace(",", ".", str_replace(".", "", $v)));
|
||||||
|
}, $vv[0]);
|
||||||
|
|
||||||
|
return [
|
||||||
|
"type" => "B1",
|
||||||
|
"codice" => $codice,
|
||||||
|
"descrizione" => $descr,
|
||||||
|
"prezzi" => $vals
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// FORMATO C (ripetuto in riga)
|
||||||
|
$blocks = extractTypeCBlocks($line);
|
||||||
|
|
||||||
|
if (!empty($blocks)) {
|
||||||
|
|
||||||
|
$desc = $line;
|
||||||
|
foreach ($blocks as $b) {
|
||||||
|
$pattern = sprintf(
|
||||||
|
'/%s\s+%s\s+%s\s+\d{1,3}\.\d{3}/',
|
||||||
|
$b["codice"],
|
||||||
|
$b["variante"],
|
||||||
|
$b["dimensione"]
|
||||||
|
);
|
||||||
|
$desc = preg_replace($pattern, "", $desc);
|
||||||
|
}
|
||||||
|
|
||||||
|
$desc = trim($desc);
|
||||||
|
|
||||||
|
return [
|
||||||
|
"type" => "C",
|
||||||
|
"descrizione" => $desc,
|
||||||
|
"varianti" => $blocks
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nessun match
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 6) PROCESSAMENTO DI TUTTE LE PAGINE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
$items = [];
|
||||||
|
|
||||||
|
foreach ($pages as $p) {
|
||||||
|
|
||||||
|
if (!isset($p["row"])) continue;
|
||||||
|
|
||||||
|
// Ricostruisco tutte le vere righe (“flat lines”)
|
||||||
|
$flatLines = [];
|
||||||
|
|
||||||
|
foreach ($p["row"] as $row) {
|
||||||
|
$line = "";
|
||||||
|
foreach ($row["column"] as $col) {
|
||||||
|
if (!empty($col["text"]["text"])) {
|
||||||
|
$line .= " " . trim($col["text"]["text"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$line = trim($line);
|
||||||
|
if ($line !== "") {
|
||||||
|
$flatLines[] = $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applico i parser su ogni riga ricostruita
|
||||||
|
foreach ($flatLines as $l) {
|
||||||
|
$parsed = parseLine($l);
|
||||||
|
if ($parsed !== null) {
|
||||||
|
$items[] = $parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 7) OUTPUT FINALE
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
echo json_encode([
|
||||||
|
"status" => "ok",
|
||||||
|
"total" => count($items),
|
||||||
|
"items" => $items
|
||||||
|
], JSON_PRETTY_PRINT);
|
||||||
BIN
public/userarea/listino.pdf
Normal file
BIN
public/userarea/listino.pdf
Normal file
Binary file not shown.
4
vendor/composer/autoload_classmap.php
vendored
4
vendor/composer/autoload_classmap.php
vendored
@ -6660,6 +6660,10 @@ return array(
|
|||||||
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => $vendorDir . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
|
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => $vendorDir . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
|
||||||
'Spatie\\LaravelPackageTools\\Package' => $vendorDir . '/spatie/laravel-package-tools/src/Package.php',
|
'Spatie\\LaravelPackageTools\\Package' => $vendorDir . '/spatie/laravel-package-tools/src/Package.php',
|
||||||
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => $vendorDir . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
|
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => $vendorDir . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\BinaryNotFoundException' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/BinaryNotFoundException.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\CouldNotExtractText' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/CouldNotExtractText.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\PdfNotFound' => $vendorDir . '/spatie/pdf-to-text/src/Exceptions/PdfNotFound.php',
|
||||||
|
'Spatie\\PdfToText\\Pdf' => $vendorDir . '/spatie/pdf-to-text/src/Pdf.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedFilter' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedFilter.php',
|
'Spatie\\QueryBuilder\\AllowedFilter' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedFilter.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedInclude' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedInclude.php',
|
'Spatie\\QueryBuilder\\AllowedInclude' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedInclude.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedSort' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedSort.php',
|
'Spatie\\QueryBuilder\\AllowedSort' => $vendorDir . '/spatie/laravel-query-builder/src/AllowedSort.php',
|
||||||
|
|||||||
1
vendor/composer/autoload_psr4.php
vendored
1
vendor/composer/autoload_psr4.php
vendored
@ -54,6 +54,7 @@ return array(
|
|||||||
'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
|
'Symfony\\Component\\Clock\\' => array($vendorDir . '/symfony/clock'),
|
||||||
'Spatie\\QueryBuilder\\Database\\Factories\\' => array($vendorDir . '/spatie/laravel-query-builder/database/factories'),
|
'Spatie\\QueryBuilder\\Database\\Factories\\' => array($vendorDir . '/spatie/laravel-query-builder/database/factories'),
|
||||||
'Spatie\\QueryBuilder\\' => array($vendorDir . '/spatie/laravel-query-builder/src'),
|
'Spatie\\QueryBuilder\\' => array($vendorDir . '/spatie/laravel-query-builder/src'),
|
||||||
|
'Spatie\\PdfToText\\' => array($vendorDir . '/spatie/pdf-to-text/src'),
|
||||||
'Spatie\\LaravelPackageTools\\' => array($vendorDir . '/spatie/laravel-package-tools/src'),
|
'Spatie\\LaravelPackageTools\\' => array($vendorDir . '/spatie/laravel-package-tools/src'),
|
||||||
'Spatie\\LaravelIgnition\\' => array($vendorDir . '/spatie/laravel-ignition/src', $vendorDir . '/spatie/error-solutions/legacy/laravel-ignition'),
|
'Spatie\\LaravelIgnition\\' => array($vendorDir . '/spatie/laravel-ignition/src', $vendorDir . '/spatie/error-solutions/legacy/laravel-ignition'),
|
||||||
'Spatie\\Ignition\\' => array($vendorDir . '/spatie/ignition/src', $vendorDir . '/spatie/error-solutions/legacy/ignition'),
|
'Spatie\\Ignition\\' => array($vendorDir . '/spatie/ignition/src', $vendorDir . '/spatie/error-solutions/legacy/ignition'),
|
||||||
|
|||||||
9
vendor/composer/autoload_static.php
vendored
9
vendor/composer/autoload_static.php
vendored
@ -114,6 +114,7 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
|
|||||||
'Symfony\\Component\\Clock\\' => 24,
|
'Symfony\\Component\\Clock\\' => 24,
|
||||||
'Spatie\\QueryBuilder\\Database\\Factories\\' => 39,
|
'Spatie\\QueryBuilder\\Database\\Factories\\' => 39,
|
||||||
'Spatie\\QueryBuilder\\' => 20,
|
'Spatie\\QueryBuilder\\' => 20,
|
||||||
|
'Spatie\\PdfToText\\' => 17,
|
||||||
'Spatie\\LaravelPackageTools\\' => 27,
|
'Spatie\\LaravelPackageTools\\' => 27,
|
||||||
'Spatie\\LaravelIgnition\\' => 23,
|
'Spatie\\LaravelIgnition\\' => 23,
|
||||||
'Spatie\\Ignition\\' => 16,
|
'Spatie\\Ignition\\' => 16,
|
||||||
@ -440,6 +441,10 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
|
|||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/spatie/laravel-query-builder/src',
|
0 => __DIR__ . '/..' . '/spatie/laravel-query-builder/src',
|
||||||
),
|
),
|
||||||
|
'Spatie\\PdfToText\\' =>
|
||||||
|
array (
|
||||||
|
0 => __DIR__ . '/..' . '/spatie/pdf-to-text/src',
|
||||||
|
),
|
||||||
'Spatie\\LaravelPackageTools\\' =>
|
'Spatie\\LaravelPackageTools\\' =>
|
||||||
array (
|
array (
|
||||||
0 => __DIR__ . '/..' . '/spatie/laravel-package-tools/src',
|
0 => __DIR__ . '/..' . '/spatie/laravel-package-tools/src',
|
||||||
@ -7483,6 +7488,10 @@ class ComposerStaticInitc91cd9c5b1e6a9e8573a14b799ea9342
|
|||||||
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
|
'Spatie\\LaravelPackageTools\\Exceptions\\InvalidPackage' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Exceptions/InvalidPackage.php',
|
||||||
'Spatie\\LaravelPackageTools\\Package' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Package.php',
|
'Spatie\\LaravelPackageTools\\Package' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/Package.php',
|
||||||
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
|
'Spatie\\LaravelPackageTools\\PackageServiceProvider' => __DIR__ . '/..' . '/spatie/laravel-package-tools/src/PackageServiceProvider.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\BinaryNotFoundException' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/BinaryNotFoundException.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\CouldNotExtractText' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/CouldNotExtractText.php',
|
||||||
|
'Spatie\\PdfToText\\Exceptions\\PdfNotFound' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Exceptions/PdfNotFound.php',
|
||||||
|
'Spatie\\PdfToText\\Pdf' => __DIR__ . '/..' . '/spatie/pdf-to-text/src/Pdf.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedFilter' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedFilter.php',
|
'Spatie\\QueryBuilder\\AllowedFilter' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedFilter.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedInclude' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedInclude.php',
|
'Spatie\\QueryBuilder\\AllowedInclude' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedInclude.php',
|
||||||
'Spatie\\QueryBuilder\\AllowedSort' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedSort.php',
|
'Spatie\\QueryBuilder\\AllowedSort' => __DIR__ . '/..' . '/spatie/laravel-query-builder/src/AllowedSort.php',
|
||||||
|
|||||||
61
vendor/composer/installed.json
vendored
61
vendor/composer/installed.json
vendored
@ -8827,6 +8827,67 @@
|
|||||||
],
|
],
|
||||||
"install-path": "../spatie/laravel-query-builder"
|
"install-path": "../spatie/laravel-query-builder"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/pdf-to-text",
|
||||||
|
"version": "1.54.1",
|
||||||
|
"version_normalized": "1.54.1.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/pdf-to-text.git",
|
||||||
|
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/pdf-to-text/zipball/ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
|
||||||
|
"reference": "ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^7.4|^8.0",
|
||||||
|
"symfony/process": "^4.0|^5.0|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"pestphp/pest-plugin-laravel": "^1.3",
|
||||||
|
"phpunit/phpunit": "^9.5"
|
||||||
|
},
|
||||||
|
"time": "2025-06-13T15:23:19+00:00",
|
||||||
|
"type": "library",
|
||||||
|
"installation-source": "dist",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\PdfToText\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Extract text from a pdf",
|
||||||
|
"homepage": "https://github.com/spatie/pdf-to-text",
|
||||||
|
"keywords": [
|
||||||
|
"pdf-to-text",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/pdf-to-text/issues",
|
||||||
|
"source": "https://github.com/spatie/pdf-to-text/tree/1.54.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"install-path": "../spatie/pdf-to-text"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/clock",
|
"name": "symfony/clock",
|
||||||
"version": "v7.1.1",
|
"version": "v7.1.1",
|
||||||
|
|||||||
13
vendor/composer/installed.php
vendored
13
vendor/composer/installed.php
vendored
@ -3,7 +3,7 @@
|
|||||||
'name' => 'loshmis/vanguard',
|
'name' => 'loshmis/vanguard',
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => 'e75be99e43b28088315b19f86eee2e6869c7c844',
|
'reference' => '6b65b31932e62bc55f5c539e7856ca8eb8440782',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@ -688,7 +688,7 @@
|
|||||||
'loshmis/vanguard' => array(
|
'loshmis/vanguard' => array(
|
||||||
'pretty_version' => 'dev-main',
|
'pretty_version' => 'dev-main',
|
||||||
'version' => 'dev-main',
|
'version' => 'dev-main',
|
||||||
'reference' => 'e75be99e43b28088315b19f86eee2e6869c7c844',
|
'reference' => '6b65b31932e62bc55f5c539e7856ca8eb8440782',
|
||||||
'type' => 'project',
|
'type' => 'project',
|
||||||
'install_path' => __DIR__ . '/../../',
|
'install_path' => __DIR__ . '/../../',
|
||||||
'aliases' => array(),
|
'aliases' => array(),
|
||||||
@ -1391,6 +1391,15 @@
|
|||||||
0 => '*',
|
0 => '*',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
'spatie/pdf-to-text' => array(
|
||||||
|
'pretty_version' => '1.54.1',
|
||||||
|
'version' => '1.54.1.0',
|
||||||
|
'reference' => 'ad2a792c7e1e68f1bc9b038dc73cdcf760595fbb',
|
||||||
|
'type' => 'library',
|
||||||
|
'install_path' => __DIR__ . '/../spatie/pdf-to-text',
|
||||||
|
'aliases' => array(),
|
||||||
|
'dev_requirement' => false,
|
||||||
|
),
|
||||||
'symfony/clock' => array(
|
'symfony/clock' => array(
|
||||||
'pretty_version' => 'v7.1.1',
|
'pretty_version' => 'v7.1.1',
|
||||||
'version' => '7.1.1.0',
|
'version' => '7.1.1.0',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user