208 lines
9.4 KiB
PHP
208 lines
9.4 KiB
PHP
<?php
|
|
ini_set('error_log', __DIR__ . '/debug.log');
|
|
|
|
// Laad de class en de .env variabelen
|
|
require_once 'lib/wefact_api.php';
|
|
|
|
// Helper functie om .env bestand te laden ZONDER Composer
|
|
function loadEnv($path) {
|
|
if (!file_exists($path)) return;
|
|
$lines = file($path, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
foreach ($lines as $line) {
|
|
if (strpos(trim($line), '#') === 0) continue;
|
|
list($name, $value) = explode('=', $line, 2);
|
|
$_ENV[trim($name)] = trim($value);
|
|
}
|
|
}
|
|
loadEnv(__DIR__ . '/.env');
|
|
|
|
// --- Configuratie ---
|
|
$wefactApiKey = $_ENV['WEFACT_API_KEY'];
|
|
$mondayApiToken = $_ENV['MONDAY_API_TOKEN'];
|
|
$bedrijvenBoardId = (int)$_ENV['BEDRIJVEN_BOARD_ID'];
|
|
$vakkrachtenBoardId = (int)$_ENV['VAKKRACHTEN_BOARD_ID'];
|
|
|
|
// --- Data Mapping & Helper Functies (ongewijzigd) ---
|
|
$countryCodeMap = [
|
|
'nederland' => 'NL', 'belgiƫ' => 'BE', 'belgium' => 'BE',
|
|
'duitsland' => 'DE', 'germany' => 'DE',
|
|
];
|
|
|
|
function getColumnValue(array $columnValues, string $columnId): ?string {
|
|
foreach ($columnValues as $column) {
|
|
if ($column['id'] === $columnId) return $column['text'];
|
|
}
|
|
return null;
|
|
}
|
|
|
|
function updateMondayColumn(int $boardId, int $itemId, string $columnId, string $newValue, string $mondayToken) {
|
|
$query = 'mutation ($itemId: ID!, $boardId: ID!, $columnId: String!, $newValue: String!) {
|
|
change_simple_column_value(item_id: $itemId, board_id: $boardId, column_id: $columnId, value: $newValue) { id }
|
|
}';
|
|
$variables = ['boardId' => $boardId, 'itemId' => $itemId, 'columnId' => $columnId, 'newValue' => $newValue];
|
|
$payload = json_encode(['query' => $query, 'variables' => $variables]);
|
|
$ch = curl_init('https://api.monday.com/v2');
|
|
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch, CURLOPT_POST, true);
|
|
curl_setopt($ch, CURLOPT_POSTFIELDS, $payload);
|
|
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: ' . $mondayToken]);
|
|
$response = curl_exec($ch);
|
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
if ($httpCode >= 400) {
|
|
error_log("Fout bij updaten Monday kolom {$columnId}: " . $response);
|
|
} else {
|
|
error_log("Monday kolom {$columnId} succesvol bijgewerkt voor item {$itemId}.");
|
|
}
|
|
}
|
|
|
|
function getMondayItemData(int $itemId, string $mondayApiToken): ?array {
|
|
$graphQLQuery = 'query($itemId: [ID!]) { items (ids: $itemId) { name column_values { id text } } }';
|
|
$mondayPayload = json_encode(['query' => $graphQLQuery, 'variables' => ['itemId' => $itemId]]);
|
|
$ch_monday = curl_init('https://api.monday.com/v2');
|
|
curl_setopt($ch_monday, CURLOPT_RETURNTRANSFER, true);
|
|
curl_setopt($ch_monday, CURLOPT_POST, true);
|
|
curl_setopt($ch_monday, CURLOPT_POSTFIELDS, $mondayPayload);
|
|
curl_setopt($ch_monday, CURLOPT_HTTPHEADER, ['Content-Type: application/json', 'Authorization: ' . $mondayApiToken]);
|
|
$mondayResponse = curl_exec($ch_monday);
|
|
curl_close($ch_monday);
|
|
$itemData = json_decode($mondayResponse, true)['data']['items'][0] ?? null;
|
|
if (!$itemData) {
|
|
error_log("Item met ID {$itemId} niet gevonden in Monday.com response.");
|
|
}
|
|
return $itemData;
|
|
}
|
|
|
|
// --- Functies voor Bedrijven en Vakkrachten (ongewijzigd) ---
|
|
function handleBedrijven(array $itemData, int $itemId, WeFactAPI $wefactApi, string $mondayApiToken) {
|
|
global $countryCodeMap, $bedrijvenBoardId;
|
|
$columnValues = $itemData['column_values'];
|
|
$wefactDebtorIdColumn = 'text_mksq79kz';
|
|
$wefactDebtorId = getColumnValue($columnValues, $wefactDebtorIdColumn);
|
|
$debiteurData = array_filter([
|
|
'CompanyName' => $itemData['name'],
|
|
'CompanyNumber' => getColumnValue($columnValues, 'kvk_mkmphj97'),
|
|
'TaxNumber' => getColumnValue($columnValues, 'text_mkpw2a77'),
|
|
'PhoneNumber' => getColumnValue($columnValues, 'telefoon_mkktmz4t'),
|
|
'EmailAddress' => getColumnValue($columnValues, 'e_mail_mkktxyr6'),
|
|
'Address' => getColumnValue($columnValues, 'text_mkpwgxkm'),
|
|
'ZipCode' => getColumnValue($columnValues, 'text_mkpwp7ps'),
|
|
'City' => getColumnValue($columnValues, 'text_mkpw5ek1'),
|
|
'Country' => getColumnValue($columnValues, 'text_mkpwb8q1') ? ($countryCodeMap[strtolower(getColumnValue($columnValues, 'text_mkpwb8q1'))] ?? getColumnValue($columnValues, 'text_mkpwb8q1')) : null,
|
|
'InvoiceEmail' => getColumnValue($columnValues, 'text_mkpw1nxd'),
|
|
], fn($value) => $value !== null && $value !== '');
|
|
if ($wefactDebtorId) {
|
|
error_log("WeFact Debiteur ID {$wefactDebtorId} gevonden. Debiteur wordt bijgewerkt...");
|
|
$debiteurData['DebtorCode'] = $wefactDebtorId;
|
|
$response = $wefactApi->sendRequest('debtor', 'edit', $debiteurData);
|
|
} else {
|
|
error_log("Geen WeFact Debiteur ID gevonden. Nieuwe debiteur wordt aangemaakt...");
|
|
$response = $wefactApi->sendRequest('debtor', 'add', $debiteurData);
|
|
if ($response['status'] === 'success' && isset($response['debtor']['DebtorCode'])) {
|
|
$newDebtorId = $response['debtor']['DebtorCode'];
|
|
error_log("Debiteur succesvol aangemaakt met ID: {$newDebtorId}. Monday wordt bijgewerkt.");
|
|
updateMondayColumn($bedrijvenBoardId, $itemId, $wefactDebtorIdColumn, $newDebtorId, $mondayApiToken);
|
|
}
|
|
}
|
|
if ($response['status'] === 'error') {
|
|
error_log("FOUT van WeFact (Debiteur): " . json_encode($response['errors']));
|
|
} else {
|
|
error_log("SUCCES! Reactie van WeFact (Debiteur): " . json_encode($response));
|
|
}
|
|
}
|
|
|
|
function handleVakkrachten(array $itemData, int $itemId, WeFactAPI $wefactApi, string $mondayApiToken) {
|
|
global $vakkrachtenBoardId;
|
|
$columnValues = $itemData['column_values'];
|
|
$wefactProductIdColumn = 'text_mksqgn4v';
|
|
$wefactProductId = getColumnValue($columnValues, $wefactProductIdColumn);
|
|
$productData = array_filter([
|
|
'ProductName' => $itemData['name'],
|
|
'ProductKeyPhrase' => getColumnValue($columnValues, 'text_mkrhy2ks'),
|
|
], fn($value) => $value !== null && $value !== '');
|
|
if (empty($productData['ProductName'])) {
|
|
error_log("Geen productnaam gevonden voor item {$itemId}. Actie wordt gestopt.");
|
|
return;
|
|
}
|
|
if ($wefactProductId) {
|
|
error_log("WeFact Product ID {$wefactProductId} gevonden. Product wordt bijgewerkt...");
|
|
$productData['ProductCode'] = $wefactProductId;
|
|
$response = $wefactApi->sendRequest('product', 'edit', $productData);
|
|
} else {
|
|
error_log("Geen WeFact Product ID gevonden. Nieuw product wordt aangemaakt...");
|
|
$response = $wefactApi->sendRequest('product', 'add', $productData);
|
|
if ($response['status'] === 'success' && isset($response['product']['ProductCode'])) {
|
|
$newProductId = $response['product']['ProductCode'];
|
|
error_log("Product succesvol aangemaakt met ID: {$newProductId}. Monday wordt bijgewerkt.");
|
|
updateMondayColumn($vakkrachtenBoardId, $itemId, $wefactProductIdColumn, $newProductId, $mondayApiToken);
|
|
}
|
|
}
|
|
if ($response['status'] === 'error') {
|
|
error_log("FOUT van WeFact (Product): " . json_encode($response['errors']));
|
|
} else {
|
|
error_log("SUCCES! Reactie van WeFact (Product): " . json_encode($response));
|
|
}
|
|
}
|
|
|
|
// --- Webserver & Routing Logica ---
|
|
$requestBody = file_get_contents('php://input');
|
|
$data = json_decode($requestBody, true);
|
|
|
|
if (isset($data['challenge'])) {
|
|
header('Content-Type: application/json');
|
|
echo json_encode(['challenge' => $data['challenge']]);
|
|
exit;
|
|
}
|
|
|
|
if (isset($data['event'])) {
|
|
$event = $data['event'];
|
|
$boardId = (int)$event['boardId'];
|
|
$itemId = (int)$event['pulseId'];
|
|
|
|
// --- NIEUW: LOCK MECHANISME OM RACE CONDITIONS TE VOORKOMEN ---
|
|
$lockFileDir = __DIR__ . '/locks';
|
|
if (!is_dir($lockFileDir)) {
|
|
mkdir($lockFileDir, 0775, true);
|
|
}
|
|
$lockFilePath = $lockFileDir . '/' . $itemId . '.lock';
|
|
$lockFileHandle = fopen($lockFilePath, 'c');
|
|
|
|
if ($lockFileHandle === false) {
|
|
error_log("Kon geen lock file handle aanmaken voor item {$itemId}.");
|
|
exit;
|
|
}
|
|
|
|
// Probeer een exclusieve, niet-blokkerende lock te krijgen.
|
|
if (!flock($lockFileHandle, LOCK_EX | LOCK_NB)) {
|
|
// Als het niet lukt, is een ander proces al bezig met dit item.
|
|
error_log("Process voor item {$itemId} is al bezig. Deze instantie wordt gestopt om duplicaten te voorkomen.");
|
|
fclose($lockFileHandle);
|
|
exit;
|
|
}
|
|
|
|
// Zorg ervoor dat de lock altijd wordt vrijgegeven, zelfs bij een fout.
|
|
register_shutdown_function(function() use ($lockFileHandle, $lockFilePath) {
|
|
flock($lockFileHandle, LOCK_UN); // Geef lock vrij
|
|
fclose($lockFileHandle);
|
|
unlink($lockFilePath); // Verwijder het lock-bestand
|
|
});
|
|
// --- EINDE LOCK MECHANISME ---
|
|
|
|
$itemData = getMondayItemData($itemId, $mondayApiToken);
|
|
|
|
if ($itemData) {
|
|
$wefactApi = new WeFactAPI($wefactApiKey);
|
|
|
|
if ($boardId === $bedrijvenBoardId) {
|
|
handleBedrijven($itemData, $itemId, $wefactApi, $mondayApiToken);
|
|
} elseif ($boardId === $vakkrachtenBoardId) {
|
|
handleVakkrachten($itemData, $itemId, $wefactApi, $mondayApiToken);
|
|
} else {
|
|
error_log("Webhook ontvangen van een niet-geconfigureerd bord: ID {$boardId}");
|
|
}
|
|
}
|
|
}
|
|
|
|
http_response_code(200);
|
|
echo json_encode(['message' => 'Event succesvol ontvangen.']);
|
|
?>
|