* Copyright (C) 2019 Cedric Ancelin * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ use Luracast\Restler\RestException; use Sabre\Xml\Element; require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php'; require_once DOL_DOCUMENT_ROOT . '/product/stock/class/productlot.class.php'; require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php'; require_once DOL_DOCUMENT_ROOT . '/categories/class/categorie.class.php'; require_once DOL_DOCUMENT_ROOT . '/variants/class/ProductAttribute.class.php'; require_once DOL_DOCUMENT_ROOT . '/variants/class/ProductAttributeValue.class.php'; require_once DOL_DOCUMENT_ROOT . '/variants/class/ProductCombination.class.php'; require_once DOL_DOCUMENT_ROOT . '/variants/class/ProductCombination2ValuePair.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/sellproduct.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/apiuserhandler.class.php'; require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/jegy.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbloginlog.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbexchangerate.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbticket.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbdevices.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbdevicesservicelocation.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbdevicesservicelocationproduct.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbticketinvoiceprinting.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/utils/globalconst.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/utils/emailtemplatehandler.php'; include_once DOL_DOCUMENT_ROOT . '/core/class/CMailFile.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbticketnaplo.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbtickethandler.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/gpsposition.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/userloginnaplo.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/utils/countryhandler.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/utils/entityhandler.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/discountnaplo.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/settlements/class/groupusers.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/rollerstorage/class/packagehistory.class.php'; require_once DOL_DOCUMENT_ROOT . '/product/inventory/class/inventory.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/apiproductlisthelper.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/apiinvoicehelper.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/ticket_checker.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/api_bbus_helper.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/api_bbus_log.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbapilock.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/exchangerateupdater.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/bbticketvalidationcoords.class.php'; require_once DOL_DOCUMENT_ROOT . '/custom/bbus/class/api_curl.class.php'; /** * API class for products * * @access protected * @class DolibarrApiAccess {@requires user,external} */ class BBus extends DolibarrApi { use CurlApi; private $code; private $printingTime; private $status = 0; private $device_id; private $service_location_id; private $bbTicketRowId; private $facture_id; private $isValid = true; private User $user; const EMAIL_TEMPLATE = 'multiticketprinting'; const GLOBAL_CONF_SEND_TO_EMAIL = 'BBUS_INVOICE_PRINTING_ALERT_EMAIL'; const GLOBAL_CONF_EMAIL_FROM = 'BBUS_INVOICE_PRINTING_ALERT_EMAIL_FROM'; public function __construct() { global $db, $conf, $user; $this->db = $db; $this->user = $user; } #------------------------------------------------- # Vásárlási folyamat #------------------------------------------------- /** * Get app config * * Return an array with config params. * * @return array|mixed Data without useless information * * @url GET config * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function config(): array { global $user, $conf; $helper = new ApiBBusHelper(); // company $companyData = $helper->getCompany(); $config = [ 'exchange_rate' => ExchangeRateUpdater::getExchangeRate(ExchangeRateUpdater::EUR, $conf->entity), 'invoice' => [ 'header' => [ 'name' => $companyData['company_data']['NOM'], 'tax_number' => $companyData['company_data']['TVAINTRA'], 'address' => [ 'zip' => $companyData['company_data']['ZIP'], 'city' => $companyData['company_data']['TOWN'], 'address' => $companyData['company_data']['ADDRESS'] ] ], 'customer' => $helper->getAppCustomers(), 'vat_percent' => 27, 'entity' => $user->entity, 'account_id' => $helper->getAccountRowid($user->entity), 'currencies' => $helper->getCurrenciesRowid($user->entity), 'payments_mode' => $helper->getPaymentsMode($user->entity) ] ]; ApiBbusLog::appLog("User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); ApiBbusLog::appLog(json_encode([ 'config' => $config ])); return $config; } /** * Check user and eventdetail type permissions * * Return a result. * * @return array|mixed Data without useless information * * @url GET checkPermission */ public function checkPermission() { global $user, $db; $permissionArray = []; $groupUsersObj = new GroupUsers($db); $result = $groupUsersObj->fetchAll('desc', 'rowid', 1, 0, ["customsql" => "fk_user = {$user->id}"]); if ($result == -1 || empty($result)) { return $permissionArray; } dol_include_once('/eventwizard/class/eventdetails.class.php'); $sqlBasicService = "SELECT pe.basic_service FROM llx_product as p INNER JOIN llx_product_extrafields as pe ON pe.fk_object = p.rowid GROUP BY pe.basic_service"; $resultBasicServices = $db->query($sqlBasicService); if ($db->num_rows($resultBasicServices) > 0) { while ($row = $db->fetch_object($resultBasicServices)) { $basicServices[] = $row->basic_service; } } $sqlBasicServicesTable = "SELECT basic_service_id, ref FROM llx_bbus_basicServices ORDER BY basic_service_id ASC"; $resultBasicServicesObj = $db->query($sqlBasicServicesTable); if ($db->num_rows($resultBasicServicesObj) > 0) { while ($bsrow = $db->fetch_object($resultBasicServicesObj)) { foreach ($basicServices as $item) { if ($bsrow->basic_service_id == $item && $item != 2) { $permissionArray[$item] = $bsrow->ref; } } } } return $permissionArray; } /** * Products list with children * * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) * @param int $category Use this param to filter list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)" * @param bool $ids_only Return only IDs of product instead of all properties (faster, above all if list is long) * @param int $variant_filter Use this param to filter list (0 = all, 1=products without variants, 2=parent of variants, 3=variants only) * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0 * @param int $includestockdata Load also information about stock (slower) * @return array Array of product objects * * @url GET /products * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function products($sortfield = 't.ref', $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $ids_only = false, $variant_filter = 0, $pagination_data = false, $includestockdata = 0): array { if (!DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(403); } //$sqlfilters .= " AND ef.basic_service < '3'"; return (new ApiProductListHelper)->list($sortfield, $sortorder, $limit, $page, $mode, $category, $sqlfilters, $ids_only, $variant_filter, $pagination_data, $includestockdata); } /** * Create invoice * * @param array $invoice Invoice data * @param array $lines Invoice lines * @param array $payment Invoice payment * @param string $cardPaymentLog Card payment log data * * @return array|mixed Data without useless information * * @url POST /invoice */ public function invoice(array $invoice, array $lines, array $payment, string $cardPaymentLog = '', string $sendId = '') { global $user; $lockLabel = 'CREATE_INVOICE'; if (empty($sendId)) { $sendId = substr(md5(rand()), 0, 8); } /** * LOG SECTION */ ApiBbusLog::appLog("{$sendId} === NEW INVOICE ==="); dol_syslog("{$sendId} === NEW INVOICE ===", LOG_INFO, 0); ApiBbusLog::appLog("{$sendId} REQUEST: {$sendId}"); dol_syslog("{$sendId} REQUEST: {$sendId}", LOG_INFO, 0); ApiBbusLog::appLog("{$sendId} User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); dol_syslog("{$sendId} User: {$user->firstname} {$user->lastname} (ID: {$user->id})", LOG_INFO, 0); ApiBbusLog::appLog("{$sendId} " . json_encode([ 'invoice' => $invoice, //'lines' => $lines, 'payment' => $payment, 'cardPaymentLog' => $cardPaymentLog ])); /** * CHECK RIGHTS */ if (!DolibarrApiAccess::$user->rights->facture->creer) { ApiBbusLog::appLog("{$sendId} Insufficient rights"); throw new RestException(401, 'Insufficient rights'); } $apiInvoiceHelper = new ApiInvoiceHelper; /** * handle invoice basic data */ $invoiceObj = $apiInvoiceHelper->createInvoice($invoice, $sendId); /** * handle invoice line(s) */ $products = []; foreach ($lines as $line) { $invoiceObj = $apiInvoiceHelper->addLineToInvoice($invoiceObj, $line, $sendId); $product = $apiInvoiceHelper->loadProductToResult($line); if (!empty($product)) { $products[] = $product; } } $invoiceObj->fetch_lines(); foreach ($products as &$row) { foreach ($invoiceObj->lines as $line) { if ($line->product_ref == $row['ref']) { //$row['price'] = $line->total_ttc; $row['price'] = $line->multicurrency_total_ttc; $row['total_tva'] = $line->total_tva; //$row['total_tva'] = $line->multicurrency_total_tva; } } } /** * validate */ $invoiceObj = $apiInvoiceHelper->validateInvoice($invoiceObj, $sendId); /** * set payment */ $apiInvoiceHelper->setPayment($invoiceObj, $payment, $sendId); /** * save card payment data */ if (!empty($cardPaymentLog)) { $invoiceObj = $apiInvoiceHelper->saveCardPaymentLog($invoiceObj, $cardPaymentLog, $sendId); } ApiBbusLog::appLog("{$sendId} Invoice created. ID: {$invoiceObj->id} REF: {$invoiceObj->ref} REQ: {$sendId}"); dol_syslog("{$sendId} Invoice created. ID: {$invoiceObj->id} REF: {$invoiceObj->ref} REQ: {$sendId}", LOG_INFO, 0); //$bbApiLock->delete($user); ApiBbusLog::appLog("{$sendId}####################################################################"); dol_syslog("{$sendId}####################################################################", LOG_INFO, 0); return [ 'sendId' => $sendId, 'invoice' => [ 'id' => $invoiceObj->id, 'ref' => $invoiceObj->ref, 'total' => $invoiceObj->multicurrency_total_ttc ], 'products' => $products, ]; } /** * Post invoice ref and creation date for data recording * * Return an array with success information. * * @param string $ref Facture ref * @param string $datetime invoice creation date * @param string $type_id type_id * * @return array|mixed Data without useless information * * @url POST printdate * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function dateHandler(string $ref, string $datetime, string $type_id = null) { global $user; $helper = new ApiBBusHelper(); if (!DolibarrApiAccess::$user->rights->produit->lire) { ApiBbusLog::appLog("!DolibarrApiAccess::user->rights->produit->lire"); throw new RestException(403); } if (empty($ref)) { ApiBbusLog::appLog("Empty ref!"); throw new RestException(401, 'Empty ref!'); } if (empty($datetime)) { ApiBbusLog::appLog("Empty datetime!"); throw new RestException(401, 'Empty datetime!'); } ApiBbusLog::appLog("=== dateHandler ==="); ApiBbusLog::appLog("Facture: {$ref}"); $printDate = DateTime::createFromFormat('Y-m-d H:i:s', $datetime); ApiBbusLog::appLog("User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); $now = new DateTime('now'); $now = (clone $now)->modify('+2 minutes'); $validDate = (clone $now)->modify('-5 minutes'); $datetime = $printDate->format('Y-m-d H:i:s'); $datetime_timestamp = strtotime($datetime); if ($validDate <= $printDate && $printDate <= $now) { $server_host = $this->getServerHost($type_id); # Keresztvásárlás if ($server_host == 'excelia') { $this->localDateHandler($ref, $datetime, $datetime_timestamp, $now); } else { ApiBbusLog::appLog("dateHandler: cURL"); $this->curlDateHandler($ref, $datetime); } } else { ApiBbusLog::appLog("dateHandler: Invalid date"); throw new RestException(401, 'Invalid date'); } return 'OK'; } private function localDateHandler($ref, $datetime, $datetime_timestamp, $now) { global $user; $helper = new ApiBBusHelper(); $facture_id = $helper->getFactureIdForInvoicePrinting($ref); if(empty($facture_id)){ ApiBbusLog::appLog("localDateHandler: facture_id because cross-shopping"); $printedCopies = $this->checkPrintedCopiesWithRef($ref); }else{ $printedCopies = $this->checkPrintedCopies($facture_id); } // Leellenőrzöm, hogy a számla volt-e már nyomtatva ApiBbusLog::appLog("printedCopies: {$printedCopies}"); if ($printedCopies == 0) { ApiBbusLog::appLog("printedCopies: no copies"); if(empty($facture_id)){ $bbTicketsByFacture = $this->getTicketsByInvoiceNumber($ref); }else{ $bbTicketsByFacture = $this->getTicketsByFactureId($facture_id); } foreach ($bbTicketsByFacture as $ticket) { // Rogzitem a bbticketinvoiceprinting tablaba a rekordot $helper->setPrintingInvoiceObject($user, $facture_id, $datetime, $datetime_timestamp, $ticket, $ref); } } else { if(empty($facture_id)){ $ticketIds = $helper->getTicketIdsForCrossShopping($ref); }else{ $ticketIds = $helper->getTicketIdsByFactureId($facture_id); } $ticketObj = new stdClass(); foreach ($ticketIds as $key => $value) { // Rogzitem a bbticketinvoiceprinting tablaba a rekordot $ticketObj->id = $key; $ticketObj->ticket_id = $value; $helper->setPrintingInvoiceObject($user, $facture_id, $datetime, $datetime_timestamp, $ticketObj, $ref); } // e-mail küldése $helper->sendMail($facture_id, $datetime, $now->format('Y-m-d H:i:s')); return 'Multiprinting'; } } private function getTicketsByFactureId($facture_id) { $bbticket = new BbTicket($this->db); $bbTicketsByFacture = $bbticket->fetchAll('', '', 0, 0, ['customsql' => 'fk_facture = ' . intval($facture_id)]); if ($bbTicketsByFacture < 1) { throw new RestException(404, 'BBTicket not found'); } return $bbTicketsByFacture; } private function getTicketsByInvoiceNumber($ref) { $bbticket = new BbTicket($this->db); $bbTicketsByFacture = $bbticket->fetchAll('', '', 0, 0, ["customsql" => "invoice_number = '" . $ref . "'"]); if ($bbTicketsByFacture < 1) { ApiBbusLog::appLog("getTicketsByInvoiceNumber: BBTicket not found"); throw new RestException(404, 'BBTicket not found'); } ApiBbusLog::appLog("getTicketsByInvoiceNumber: I got it"); return $bbTicketsByFacture; } private function checkPrintedCopies($facture_id) { $bbticketinvoiceprinting = new BbTicketInvoicePrinting($this->db); $copies = $bbticketinvoiceprinting->fetchAll('ASC', 'rowid', 0, 0, ['customsql' => 'fk_facture = ' . intval($facture_id)]); return (is_array($copies)) ? count($copies) : 0; } private function checkPrintedCopiesWithRef($ref) { $bbticketinvoiceprinting = new BbTicketInvoicePrinting($this->db); $copies = $bbticketinvoiceprinting->fetchAll('ASC', 'rowid', 0, 0, ["customsql" => "invoice_number = '" . $ref . "'"]); return (is_array($copies)) ? count($copies) : 0; } private function curlDateHandler($ref, $datetime) { $params = compact('ref', 'datetime'); $datehandlerPostFields = json_encode($params); ApiBbusLog::appLog("dateHandler: {$datehandlerPostFields}"); $this->curlRunner('bbus/printdate', $datehandlerPostFields, 'POST', true); } /** * Generate events * * @return array|mixed Data without useless information * * @url GET /getDatetime * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getDatetime() { $dateArray = []; $now = dol_now(); $dateArray = ["timestamp" => $now, "date" => date("Y-m-d", $now), "datetime" => date("Y-m-d H:i:s", $now)]; return $dateArray; } #------------------------------------------------- # Egyéb #------------------------------------------------- /** * First ticket validation * * @param string $code * * @return array|mixed Data without useless information * * @url POST search */ public function search($code) { $this->checkUserReadPermission(); global $user; $this->code = $code; $this->facture_id = $this->getFactureRowIdByFactureId(); $sql = "SELECT bt.*, pr.ref as product_ref, pr.label as product_label, btp.printing_date, btp.printing_date_timestamp FROM llx_bbus_bbticketinvoiceprinting as btp INNER JOIN llx_bbus_bbticket AS bt ON bt.rowid = btp.ticket_id INNER JOIN llx_product AS pr ON pr.rowid = bt.ticket_id WHERE btp.fk_facture = {$this->facture_id} AND btp.printing_date = ( SELECT MIN(printing_date) FROM llx_bbus_bbticketinvoiceprinting AS btp2 WHERE btp2.fk_facture = {$this->facture_id} )"; $ticketsData = $this->db->query($sql); while ($row = pg_fetch_assoc($ticketsData)) { $now = date("Y-m-d H:i:s"); if ($row['usage'] == $row['usable_occasions'] && $row['usable_occasions'] != 0) { $this->isValid = false; } if ($row['available_at'] < $now || ((!is_null($row['expire_at']) && !empty($row['expire_at'])) && $row['expire_at'] < $now)) { $this->isValid = false; } $row['facture_ref'] = $code; $row['isValid'] = $this->isValid; $sub = []; foreach ($row as $key => $value) { $sub[$key] = $value; } $json[] = $sub; } return $json; } /** * Értékesítések * * @param date $date Date * * * @return array|mixed Data without useless information * * @url POST getsaleditems */ public function getsaleditems($date = null) { global $user; if (!DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(403); } //$date = isset($date) ? $date : date("Y-m-d"); $date = date("Y-m-d"); $apiBbusHelper = new ApiBBusHelper(); $facturesArray = $apiBbusHelper->getSaledItems($date); return $apiBbusHelper->getSaledItemsArray($facturesArray); } /** LOG OK * Get properties of a product object by barcode * * Return an array with product information. * * @param string $code Facture ID and timestamp of printing * * @return array|mixed Data without useless information * * @url POST ticketinfos */ public function getinfos($code) { global $user; $helper = new ApiBBusHelper(); ApiBbusLog::getinfosLog('=== NEW TICKETINFOS ==='); ApiBbusLog::getinfosLog("User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); ApiBbusLog::getinfosLog("DOLAPIKEY: {$user->api_key}"); $ticketsFromBbticketinvoiceprinting = []; $code_and_timstamp = explode('_', $code); $this->code = $code_and_timstamp[0]; if (empty($this->code)) { ApiBbusLog::getinfosLog('Code or mac is empty!'); ApiBbusLog::getinfosLog('================='); throw new RestException(404, 'Code or mac is empty!'); } $this->printingTime = $code_and_timstamp[1]; if (empty($this->printingTime)) { ApiBbusLog::getinfosLog('Timestamp is empty!'); ApiBbusLog::getinfosLog('================='); throw new RestException(404, 'Timestamp is empty!'); } if (!DolibarrApiAccess::$user->rights->bbus->ticket->validation) { ApiBbusLog::getinfosLog('No access: Ticket Validation!'); ApiBbusLog::getinfosLog('================='); throw new RestException(403); } ApiBbusLog::getinfosLog("Code: {$this->code}"); ApiBbusLog::getinfosLog("Code: {$this->printingTime}"); //Kikeresem a facture_id-t $facture = new Facture($this->db); $sql = "SELECT * FROM " . $this->db->prefix() . $facture->table_element . " WHERE ref ILIKE '{$this->code}'"; $factureResult = $this->db->query($sql); if (pg_num_rows($factureResult) < 1) { ApiBbusLog::getinfosLog('Invoice not found!'); ApiBbusLog::getinfosLog('================='); throw new RestException(404, 'Invoice not found!'); } while ($row = pg_fetch_assoc($factureResult)) { $selectedFacture_id = $row['rowid']; } ApiBbusLog::getinfosLog('Facture ID: ' . (string) $selectedFacture_id); $sql = "SELECT rowid FROM " . $this->db->prefix() . $facture->table_element . " WHERE fk_facture_source = {$selectedFacture_id} AND type = 2"; $res = $this->db->query($sql); if (pg_num_rows($res) > 0) { ApiBbusLog::getinfosLog('Invoice has a Credit account!'); ApiBbusLog::getinfosLog('================='); throw new RestException(404, 'Invoice has a Credit account.'); } // Kikeresem az llx_bbus_bbticketinvoiceprinting táblából a timestamp-hez tartozo jegy Id(ka)t $bbticketinvoiceprinting = new BbTicketInvoicePrinting($this->db); $result = $bbticketinvoiceprinting->fetchAll('', '', 0, 0, ['customsql' => "printing_date_timestamp = '{$this->printingTime}' AND fk_facture = {$selectedFacture_id}"]); $helper->checkResult($result, 'bbticketinvoiceprinting'); foreach ($result as $device) { $ticketsFromBbticketinvoiceprinting[] = $device->ticket_id; } $inString = implode(', ', $ticketsFromBbticketinvoiceprinting); //echo $inString;exit; // A ticket_id alapjan, hogy a jegyek kozott szerepel-e es ervenyes-e $bbticket = new BbTicket($this->db); $sql = "SELECT tic.rowid as ticketrowid, tic.*, bbd.*, fac.* FROM " . $this->db->prefix() . $bbticket->table_element . " AS tic INNER JOIN public.llx_product as bbd ON tic.ticket_id = bbd.rowid INNER JOIN public.llx_facture as fac ON tic.fk_facture = fac.rowid WHERE tic.rowid IN ({$inString})"; $statement = $this->db->query($sql); while ($row = pg_fetch_assoc($statement)) { $sub = []; foreach ($row as $key => $value) { $sub[$key] = $value; } $json[] = $sub; } ApiBbusLog::getinfosLog('Status: OK!'); ApiBbusLog::getinfosLog('====================='); return $json; } /** * Get properties of a product object by barcode * * Return an array with product information. * * * @return array|mixed Data without useless information * * @url GET product */ public function getProducts() { global $user; $productsArray = []; $products = new Product($this->db); $sql = "SELECT price, default_vat_code, rowid FROM " . $this->db->prefix() . $products->table_element . " WHERE fk_product_type = 1 ORDER BY rowid ASC"; $res = $this->db->query($sql); while ($row = pg_fetch_assoc($res)) { $productsArray[$row['rowid']] = $row; } return 'OK'; } /** LOG OK * Validate a product bbticket id. * * Return an array with product validation data. * * @param string $code Facture ID and timestamp of printing * @param string $ticketid Ticketid (bbticket rowid) * @param string $imei IMEI (Mobile IMEI number) * * @return array|mixed Data without useless information * * @url POST ticketvalidationbyphone */ public function validateTicket($code, $ticketid, $imei) { global $user; $logId = ApiBbusLog::getLogId(); ApiBbusLog::ticketvalidationByPhone("{$logId} === NEW TICKETVALIDATION BY PHONE ==="); ApiBbusLog::ticketvalidationByPhone("{$logId} User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); ApiBbusLog::ticketvalidationByPhone("{$logId} DOLAPIKEY: {$user->api_key}"); ApiBbusLog::ticketvalidationByPhone("{$logId} code: {$code}"); $ticketChecker = new TicketChecker(); $ticketChecker->setCode($code); $ticketChecker->setTimestamp($code, 'ticketvalidationByPhone', $logId); $ticketChecker->SetTicketidFromPhone($ticketid, $logId); $ticketChecker->setImei($imei, $logId); $this->checkUserValidatePermission(); $ticketChecker->setFactureId('ticketvalidationByPhone', $logId); $ticketChecker->checkBbTicketInvoicePrinting(); $selectedTicket = $ticketChecker->getDataOfTheSelectedTicket(); $ticketChecker->setBbTicketRowId($selectedTicket->id); $ticketChecker->checkExceptionHandlers($selectedTicket, 'ticketvalidationByPhone', $logId); $ticketChecker->setMergedTickets($selectedTicket, 'ticketvalidationByPhone', $logId); $ticketChecker->saveData($selectedTicket); ApiBbusLog::ticketvalidationByPhone("{$logId} Status: OK!"); ApiBbusLog::ticketvalidationByPhone("{$logId} ================="); return 'OK'; } /** LOG OK * Get properties of a product object by barcode * * Return an array with product information. * * @param string $code Facture ID and timestamp of printing * @param string $mac MAC adress of the device * * @return array|mixed Data without useless information * * @url POST barcode * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getByBarcode(string $code, string $mac, string $lat = null, string $lon = null) { global $user; $logId = ApiBbusLog::getLogId(); ApiBbusLog::getByBarcode("{$logId} === NEW OBU validation ==="); ApiBbusLog::getByBarcode("{$logId} User: {$user->firstname} {$user->lastname} (ID: {$user->id})"); ApiBbusLog::getByBarcode("{$logId} DOLAPIKEY: {$user->api_key}"); $bbticket = new BbTicket($this->db); $ticketChecker = new TicketChecker(); if (empty($code) || empty($mac)) { ApiBbusLog::getByBarcode("{$logId} Code or mac is empty!"); throw new RestException(404, 'Code or mac is empty!'); } ApiBbusLog::getByBarcode("{$logId} Code: " . $code); ApiBbusLog::getByBarcode("{$logId} MAC: " . $mac); ApiBbusLog::getByBarcode("{$logId} Latitude: " . $lat); ApiBbusLog::getByBarcode("{$logId} Longitude: " . $lon); $ticketChecker->setMac($mac); $ticketChecker->setCode($code); $ticketChecker->setLat($lat); $ticketChecker->setLon($lon); $ticketChecker->setTimestamp($code, 'getByBarcode', $logId); $this->checkUserReadPermission(); $ticketChecker->setFactureId('getByBarcode', $logId); $ticketChecker->setFilsArray(); $ticketChecker->setTicketId($logId); $selectedTicket = $ticketChecker->getDataOfTheSelectedTicket(); $ticketChecker->setBbTicketRowId($selectedTicket->id); $ticketChecker->check5Minutes($logId); $ticketChecker->checkExceptionHandlers($selectedTicket, 'getByBarcode', $logId); $ticketChecker->setMergedTickets($selectedTicket, 'getByBarcode', $logId); $ticketChecker->saveCoordinates($logId); $ticketChecker->saveData($selectedTicket); ApiBbusLog::getByBarcode("{$logId} Status: OK!"); ApiBbusLog::getByBarcode("{$logId} ================="); return 'OK'; } /** * Save customer data (zip or countrycode) in facture table * * Return a result. * * @param string $facture_id Facture rowid * @param string $customerdatazip Customer data ZIP * @param string $customerdatacountrycode Customer data Countrycode * * @return array|mixed Data without useless information * * @url POST customerDataHandler * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function customerDataHandler(string $facture_id, string $customerdatazip = null, string $customerdatacountrycode = null) { $helper = new ApiBBusHelper(); if (is_null($customerdatazip) && is_null($customerdatacountrycode)) { dol_syslog("Nem sikerult a facture updateje. Ref: " . $this->facture_id, LOG_DEBUG | LOG_INFO | LOG_WARNING | LOG_ERR); throw new RestException(404, 'Empty params'); } $sql = "UPDATE " . $this->db->prefix() . "facture_extrafields SET "; $sql .= !is_null($customerdatazip) ? "customer_data_zip = '{$customerdatazip}' " : "customer_data_countrycode = '{$customerdatacountrycode}' "; $sql .= "WHERE fk_object = '{$facture_id}'"; $helper->factureUpdate($sql, $facture_id); return "OK"; } /** * Create naplo for userlogout * * Return a result. * * @return array|mixed Data without useless information * * @url POST logoutNaploCreator * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function logoutNaploCreator() { global $user, $db; $error = 0; $db->begin(); $helper = new ApiBBusHelper(); $group_user_id = $helper->getGroupUserIdByUserId($user->id); if ($group_user_id == -1) { $error++; } $result = $helper->isLastStatusLogout($user); if ($result !== '') { return date('Y-m-d H:i:s', $result); } $userLoginNaplo = new UserLoginNaplo($db); $userLoginNaplo->login_logout_status = 1; $userLoginNaplo->user_id = $user->id; $result = $userLoginNaplo->create($user); if ($result < 0) { $error++; } $userNaploObj = new UserNaplo($db); $userNaploObj->user_id = $user->id; $userNaploObj->group_user_id = $group_user_id; $userNaploObj->status = 0; $result = $userNaploObj->create($user); if ($result < 0) { $error++; } $groupUsersObj = new GroupUsers($db); $sql = "SELECT rowid FROM " . MAIN_DB_PREFIX . "settlements_groupusers WHERE fk_user = {$user->id}"; $data = $db->query($sql); $dataArray = pg_fetch_assoc($data); $selectedGroupId = $dataArray['rowid']; if (isset($selectedGroupId)) { $resultKickOff = $groupUsersObj->deleteLine($user, $selectedGroupId); if (!$resultKickOff) { $error++; } } if ($error) { $db->rollback(); } $db->commit(); return 'OK'; } /** * Get the discount unit From Product * * Return a result. * * @param int $product_id Product rowid * * @return string discount unit * * @url POST getDiscountUnit * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getDiscountUnit(int $product_id) { global $db, $user; $ProductObj = new Product($db); $ProductObj->fetch($product_id); return $ProductObj->array_options['discount_period']; } /** * Create naplo for Discount * * Return a result. * * @param int $facture_id Facture rowid * @param int $product_id Product rowid * @param int $discount Discount * @param string $discount_unit Discount unit * * @return array|mixed Data without useless information * * @url POST createDiscountNaplo * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function createDiscountNaplo(int $facture_id, int $product_id, int $discount, string $discount_unit) { global $db, $user; $discountNaploObj = new DiscountNaplo($db); $discountNaploObj->fk_facture = $facture_id; $discountNaploObj->fk_product = $product_id; $discountNaploObj->discount = $discount; $discountNaploObj->discount_unit = $discount_unit; $result = $discountNaploObj->create($user); if ($result < 0) { return false; } return $result; } /** * Get the products from Product * * Return a result. * * @param int $entity entity * * @return array|mixed Data without useless information * * @url POST getHotelSalesProducts * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getHotelSalesProducts(int $entity) { global $db, $user; $sql = "SELECT p.* FROM public.llx_product AS p INNER JOIN public.llx_product_extrafields as pe ON pe.fk_object = p.rowid WHERE p.entity = {$entity} AND pe.hotelsales = 1"; $products = $this->db->query($sql); $row = pg_fetch_all($products); return $row; } private function checkUserReadPermission() { if (!DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(403); } } private function checkUserValidatePermission() { if (!DolibarrApiAccess::$user->rights->bbus->ticket->validation) { throw new RestException(403); } } private function getFactureRowIdByFactureId() { $facture = new Facture($this->db); $sqlFacture = "SELECT rowid FROM public.llx_facture WHERE ref ILIKE '%{$this->code}%'"; $result = $this->db->query($sqlFacture); if (pg_num_rows($result) > 0) { while ($adatok = pg_fetch_assoc($result)) { $factureRowid = $adatok['rowid']; } } else { throw new RestException(404, 'Invoice not found.'); } $sql = "SELECT rowid FROM llx_facture WHERE fk_facture_source = {$factureRowid} AND type = 2"; $res = $this->db->query($sql); if (pg_num_rows($res) > 0) { throw new RestException(404, 'Invoice has a Credit account.'); } return $factureRowid; } private function saveBbTicketNaplo($user) { $bbTicketNaplo = new BbTicketNaplo($this->db); $bbTicketNaplo->ticket_row_id = $this->bbTicketRowId; $bbTicketNaplo->bbservicelocation_id = isset($this->service_location_id) ? $this->service_location_id : null; $bbTicketNaplo->device_id = isset($this->device_id) ? $this->device_id : null; $bbTicketNaplo->status = $this->status; if ($bbTicketNaplo->create($user) < 0) { dol_syslog('Nem sikerult menteni a bbticketNaplo tablaba a rekordot.', LOG_DEBUG | LOG_INFO | LOG_WARNING | LOG_ERR); throw new RestException(500, 'Nem sikerult menteni a bbticketNaplo tablaba a rekordot.'); } } /** * @param string $ref Facture ref * * @return array|mixed Data without useless information * * @url POST getTicketsByFactureInvoiceNumber * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getTicketsByFactureInvoiceNumber($ref) { $bbTicketsByFacture = []; $sql = "SELECT rowid as id, ticket_id FROM llx_bbus_bbticket WHERE invoice_number ILIKE '%{$ref}%'"; $result = $this->db->query($sql); if ($this->db->num_rows($result) > 0) { while ($row = $this->db->fetch_object($result)) { $bbTicketsByFacture[] = $row; } } else { throw new RestException(404, 'BBTicket not found'); } return $bbTicketsByFacture; } /** * @param string $facture_id Facture ref * * @return array|mixed Data without useless information * * @url POST getRefFromFacture * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getRefFromFacture(string $facture_id) { global $user; $facture = new Facture($this->db); $sql = "SELECT ref FROM " . $this->db->prefix() . $facture->table_element . " WHERE rowid = " . $facture_id; $res = $this->db->query($sql); while ($adatok = pg_fetch_assoc($res)) { print_r($adatok['ref']); exit; } return 'OK'; } /** * Get properties of a product object by barcode * * Return an array with product information. * * @param string $barcode Barcode of element * @param int $includestockdata Load also information about stock (slower) * @param bool $includesubproducts Load information about subproducts * @param bool $includeparentid Load also ID of parent product (if product is a variant of a parent product) * @param bool $includetrans Load also the translations of product label and description * * @return array|mixed Data without useless information * * @url GET profileimage/{id} * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getUserImage(int $id) { $image = null; $dolApiKey = $_SERVER['HTTP_DOLAPIKEY'] ?? null; if (empty($dolApiKey)) { throw new RestException(401, 'Access not allowed'); } $user = (new ApiUserHandler)->getUser($id, $dolApiKey); if (empty($user->photo)) { throw new RestException(404, 'Photo not found'); } else { $originalFile = get_exdir(0, 0, 0, 0, $user, 'user') . 'photos/' . $user->photo; $originalFile = DOL_DOCUMENT_ROOT . '/documents/users/' . $originalFile; $filename = basename($originalFile); $originalFileOsEncoded = dol_osencode($originalFile); // New file name encoded in OS encoding charset $fileContent = file_get_contents($originalFileOsEncoded); $image = [ 'filename' => $filename, 'content-type' => dol_mimetype($filename), 'filesize' => filesize($originalFile), 'content' => base64_encode($fileContent), 'encoding' => 'base64' ]; } return $image; } /** * Create invoices from the order * * @param int $id_order (Row)Id of the order * @param int $id_soc Id of 3th party * @return array Response * @url POST invoicesFromOrder * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function invoicesFromOrder(int $id_order, int $id_soc = 0): array { // echo ini_get('memory_limit'); // exit; if (!DolibarrApiAccess::$user->rights->facture->creer) { throw new RestException(401, "Insuffisant rights"); } require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php'; // Standard or deposit invoice, not from a Predefined template invoice // Si facture standard $this->now = time(); $this->invoices = []; $element == 'order'; $element = $subelement = 'commande'; //etalon obj: $object = new Facture($this->db); // $extrafields = new ExtraFields($db); $defaultDevSocId = 1; $this->defaultSocId = (isset($_ENV['DEFAULT_SOCID']) && (int) $_ENV['DEFAULT_SOCID']) ? (int) $_ENV['DEFAULT_SOCID'] : $defaultDevSocId; $object->socid = (empty((int) $id_soc)) ? $this->defaultSocId : (int) $id_soc; $object->type = null; $object->ref = null; $object->date = $this->now; // $object->date_pointoftax = $date_pointoftax; // $object->note_public = trim(GETPOST('note_public', 'restricthtml')); // $object->note_private = trim(GETPOST('note_private', 'restricthtml')); // $object->ref_client = GETPOST('ref_client'); $object->model_pdf = null; // $object->fk_project = GETPOST('projectid', 'int'); // $object->cond_reglement_id = (GETPOST('type') == 3 ? 1 : GETPOST('cond_reglement_id')); // $object->mode_reglement_id = GETPOST('mode_reglement_id'); // $object->fk_account = GETPOST('fk_account', 'int'); // $object->amount = price2num(GETPOST('amount')); // $object->remise_absolue = price2num(GETPOST('remise_absolue'), 'MU'); // $object->remise_percent = price2num(GETPOST('remise_percent'), '', 2); // $object->fk_incoterms = GETPOST('incoterm_id', 'int'); // $object->location_incoterms = GETPOST('location_incoterms', 'alpha'); // $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha'); // $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int'); $object->fetch_thirdparty(); // If creation from another object of another module (Example: origin=propal, originid=1) $object->origin = $element; $object->origin_id = $id_order; // Possibility to add external linked objects with hooks $object->linked_objects[$object->origin] = $object->origin_id; // link with order if it is a shipping invoice if (is_array($_POST['other_linked_objects']) && !empty($_POST['other_linked_objects'])) { $object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']); } // dol_include_once('/' . $element . '/class/' . $subelement . '.class.php'); $classname = ucfirst($subelement); $srcobject = new $classname($this->db); $result = $srcobject->fetch($id_order); if ($result > 0) { $lines = $srcobject->lines; if (empty($lines) && method_exists($srcobject, 'fetch_lines')) { $srcobject->fetch_lines(); $lines = $srcobject->lines; } /* // If we create a standard invoice with a percent, we change amount by changing the qty if (is_array($lines)) { foreach ($lines as $line) { // We keep ->subprice and ->pa_ht, but we change the qty $line->qty = price2num($line->qty * $valuestandardinvoice / 100, 'MS'); } } */ $fk_parent_line = 0; $num = count($lines); $invNum = 0; for ($i = 0; $i < $num; $i++) { // if (!in_array($lines[$i]->id, $selectedLines)) { // continue; // Skip unselected lines // } //!!! create invoice by line: $quantity = $lines[$i]->qty; for ($j = 0; $j < $quantity; $j++) { $this->invoices[$invNum] = clone $object; if ($id = $this->invoices[$invNum]->create(DolibarrApiAccess::$user)) { $this->invoices[$invNum]->update_price(1, 'auto', 0, $mysoc); $label = (!empty($lines[$i]->label) ? $lines[$i]->label : ''); $desc = (!empty($lines[$i]->desc) ? $lines[$i]->desc : $lines[$i]->libelle); if ($this->invoices[$invNum]->situation_counter == 1) { $lines[$i]->situation_percent = 0; } if ($lines[$i]->subprice < 0 && empty($conf->global->INVOICE_KEEP_DISCOUNT_LINES_AS_IN_ORIGIN)) { // Negative line, we create a discount line require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php'; $discount = new DiscountAbsolute($db); $discount->fk_soc = $this->invoices[$invNum]->socid; $discount->amount_ht = abs($lines[$i]->total_ht); $discount->amount_tva = abs($lines[$i]->total_tva); $discount->amount_ttc = abs($lines[$i]->total_ttc); $discount->tva_tx = $lines[$i]->tva_tx; $discount->fk_user = DolibarrApiAccess::$user->id; $discount->description = $desc; $discount->multicurrency_subprice = abs($lines[$i]->multicurrency_subprice); $discount->multicurrency_amount_ht = abs($lines[$i]->multicurrency_total_ht); $discount->multicurrency_amount_tva = abs($lines[$i]->multicurrency_total_tva); $discount->multicurrency_amount_ttc = abs($lines[$i]->multicurrency_total_ttc); $discountid = $discount->create(DolibarrApiAccess::$user); if ($discountid > 0) { $result = $this->invoices[$invNum]->insert_discount($discountid); // This include link_to_invoice } else { setEventMessages($discount->error, $discount->errors, 'errors'); $error++; break; } } else { // Positive line $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0); // Date start $date_start = false; if ($lines[$i]->date_debut_prevue) { $date_start = $lines[$i]->date_debut_prevue; } if ($lines[$i]->date_debut_reel) { $date_start = $lines[$i]->date_debut_reel; } if ($lines[$i]->date_start) { $date_start = $lines[$i]->date_start; } // Date end $date_end = false; if ($lines[$i]->date_fin_prevue) { $date_end = $lines[$i]->date_fin_prevue; } if ($lines[$i]->date_fin_reel) { $date_end = $lines[$i]->date_fin_reel; } if ($lines[$i]->date_end) { $date_end = $lines[$i]->date_end; } // Reset fk_parent_line for no child products and special product if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) { $fk_parent_line = 0; } // Extrafields if (method_exists($lines[$i], 'fetch_optionals')) { $lines[$i]->fetch_optionals(); $array_options = $lines[$i]->array_options; } $tva_tx = $lines[$i]->tva_tx; if (!empty($lines[$i]->vat_src_code) && !preg_match('/\(/', $tva_tx)) { $tva_tx .= ' (' . $lines[$i]->vat_src_code . ')'; } // View third's localtaxes for NOW and do not use value from origin. // TODO Is this really what we want ? Yes if source is template invoice but what if proposal or order ? $localtax1_tx = get_localtax($tva_tx, 1, $this->invoices[$invNum]->thirdparty); $localtax2_tx = get_localtax($tva_tx, 2, $this->invoices[$invNum]->thirdparty); $result = $this->invoices[$invNum]->addline( $desc, $lines[$i]->subprice, // $lines[$i]->qty, 1, $tva_tx, $localtax1_tx, $localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, $lines[$i]->fk_remise_except, 'HT', 0, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $this->invoices[$invNum]->origin, $lines[$i]->rowid, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $array_options, $lines[$i]->situation_percent, $lines[$i]->fk_prev_id, $lines[$i]->fk_unit, 0, '', 1 ); if ($result > 0) { $lineid = $result; } else { $lineid = 0; $error++; break; } // Defined the new fk_parent_line if ($result > 0 && $lines[$i]->product_type == 9) { $fk_parent_line = $result; } } } $invNum++; } } } else { setEventMessages($srcobject->error, $srcobject->errors, 'errors'); $error++; } $num = count($this->invoices); $return = [ 'validated' => [] ]; // $used_mem = round(memory_get_usage(false) / 1024 / 1024); //mb // $used_mem = round(memory_get_usage(true) / 1024 / 1024); //mb // echo $used_mem. " / ".$allowed_mem; // echo ini_get('memory_limit'); // exit; for ($i = 0; $i < $num; $i++) { //!!! validation // $idwarehouse = 0; // $notrigger = 0; // $result = $this->invoices[$i]->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger); $id = $this->invoices[$i]->id; $result = $this->invoices[$i]->validate(DolibarrApiAccess::$user, '', null); if ($result >= 0) { // Define output language if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) { global $langs; $outputlangs = $langs; $newlang = ''; if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang) && GETPOST('lang_id', 'aZ09')) { $newlang = GETPOST('lang_id', 'aZ09'); } if (!empty($conf->global->MAIN_MULTILANGS) && empty($newlang)) { $newlang = $this->invoices[$i]->thirdparty->default_lang; } if (!empty($newlang)) { $outputlangs = new Translate("", $conf); $outputlangs->setDefaultLang($newlang); $outputlangs->load('products'); } $model = $this->invoices[$i]->model_pdf; $ret = $this->invoices[$i]->fetch($id); // Reload to get new records // PDF $hidedetails = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS)) ? 1 : 0; $hidedesc = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC)) ? 1 : 0; $hideref = (!empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF)) ? 1 : 0; $result = $this->invoices[$i]->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref); if ($result < 0) { //... // setEventMessages($this->invoices[$i]->error, $this->invoices[$i]->errors, 'errors'); } } } else { // if (count($this->invoices[$i]->errors)) { // setEventMessages(null, $this->invoices[$i]->errors, 'errors'); // } else { // setEventMessages($this->invoices[$i]->error, $this->invoices[$i]->errors, 'errors'); // } } // if ($result == 0) { // throw new RestException(304, 'Error nothing done. May be object is already validated'); // } // if ($result < 0) { // throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error); // } // $this->invoices[$i] = $this->invoicees[$i]->fetch($id); if (!$this->invoices[$i]) { throw new RestException(404, 'Invoice not found'); } $this->invoices[$i] = parent::_cleanObjectDatas($this->invoices[$i]); unset($this->invoices[$i]->note); unset($this->invoices[$i]->address); unset($this->invoices[$i]->barcode_type); unset($this->invoices[$i]->barcode_type_code); unset($this->invoices[$i]->barcode_type_label); unset($this->invoices[$i]->barcode_type_coder); unset($this->invoices[$i]->canvas); if (!DolibarrApi::_checkAccessToResource('facture', $id)) { throw new RestException(401, 'Access not allowed for login ' . DolibarrApiAccess::$user->login); } $return['validated'][] = $this->invoices[$i]->ref; } return $return; } /** * Jegy generálás -> (order?->) invoice -> payment -> jegy -> qr on the bill * * Return an array with prcess information. * * @param array $orderDetails Order details * * @return array|mixed Data without useless information * * @url POST order * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function jegy(array $orderDetails) { $return = [ "request" => $orderDetails ]; $Jegy = new Jegy(); $return['hash'] = [ $Jegy->generate_hash(), $Jegy->generate_hash(1), $Jegy->generate_hash(20), $Jegy->generate_hash(50), $Jegy->generate_hash(100), ]; return $return; } /** * Get groupId for REACT * * Return an ID. * * @return integer Data without useless information * * @url GET getGroupId * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getGroupId(): array { global $user, $db; $sql = "SELECT fk_settlements_group FROM public.llx_settlements_groupusers WHERE fk_user = {$user->id} ORDER BY rowid DESC LIMIT 1"; $result = $db->query($sql); while ($row = pg_fetch_assoc($result)) { return $row; } return []; } /** * Insert a row into login log table * * @param string $login Login name * * @return array|mixed Data without useless information * * @url POST savelogin * * @throws RestException 404 */ public function saveLogin(string $login) { $error = 0; $this->db->begin(); $user = new User($this->db); //$user->fetch(0, $login, 0, 0, 1); $user->fetch(0, $login, 0, 0); if (empty($user->id)) { throw new RestException(404, 'User not found'); } $log = new BbLoginLog($this->db); $log->entity = 1; $log->description = 'Login from App'; $id = $log->create($user); if ($id < 1) { $error++; throw new RestException(500, 'Log failure'); } $now = dol_now(); $userremoteip = getUserRemoteIP(); $sql = "UPDATE " . $this->db->prefix() . "user SET"; $sql .= " datepreviouslogin = datelastlogin,"; $sql .= " ippreviouslogin = iplastlogin,"; $sql .= " datelastlogin = '" . $this->db->idate($now) . "',"; $sql .= " iplastlogin = '" . $this->db->escape($userremoteip) . "',"; $sql .= " tms = tms"; // La date de derniere modif doit changer sauf pour la mise a jour de date de derniere connexion $sql .= " WHERE rowid = " . ((int) $user->id); $resql = $this->db->query($sql); if (!$resql) { $error++; $this->error = $this->db->lasterror() . ' sql=' . $sql; } if (!$error) { $this->db->commit(); return 'OK'; } else { $this->db->rollback(); } } /** * Receive GPS coordinates of the device * * @param string $licplate License plate of the vehicle * @param string $lat GPS latitude coordinate * @param string $lon GPS longitude coordinate * * @return string|mixed Data without useless information * * @url GET /gps_coords * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 * @throws RestException 500 */ public function gpsCoords(string $licplate, string $lat, string $lon): string { if (!(new GpsPosition)->save($licplate, $lat, $lon)) { throw new RestException(500, 'Save failure'); } return 'OK'; } /** * Receive GPS coordinates of the device * * @param string $licplate License plate of the vehicle * @param string $lat GPS latitude coordinate * @param string $lon GPS longitude coordinate * * @return string|mixed Data without useless information * * @url POST /gps_position * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 * @throws RestException 500 */ public function gpsPosition(string $licplate, string $lat, string $lon): string { if (!(new GpsPosition)->save($licplate, $lat, $lon)) { throw new RestException(500, 'Save failure'); } return 'OK'; } /** * List of countries * * Return an array with country name and code. * * @param string $lang * @param string $search * * @return array|mixed Data without useless information * * @url GET /countries * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function countries(string $lang = 'hu', string $search = ''): array { return (new CountryHandler)->getCountries($lang, $search); } /** * List of entities * * Return an array with companies data. * * @return array|mixed Data without useless information * * @url GET /entities * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function entities(): array { return (new EntityHandler)->getEntities(); } /** * List of assets received * * Return an array with assets received. * * @return array|mixed Data without useless information * * @url GET /assets_received * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function assetsReceived(): array { global $user, $db; $packageHistory = new PackageHistory($db); $inventoryObj = new Inventory($db); $sql = "SELECT pt.device_id, i.ref, i.title, ie.unique_identifier, (SELECT ph.date_creation FROM " . $this->db->prefix() . $packageHistory->table_element . " as ph WHERE user_id = {$user->id} AND DATE(ph.date_creation) = CURRENT_DATE ORDER BY ph.rowid DESC LIMIT 1) AS ph_date_creation FROM llx_settlements_packagetool pt INNER JOIN llx_inventory as i ON i.rowid = pt.device_id INNER JOIN llx_inventory_extrafields as ie ON ie.fk_object = i.rowid WHERE pt.package_id = (SELECT ph.package_id FROM public.llx_rollerstorage_packagehistory as ph WHERE user_id = {$user->id} AND DATE(ph.date_creation) = CURRENT_DATE ORDER BY ph.rowid DESC LIMIT 1) ORDER BY pt.rowid DESC"; //print $sql;exit; $result = $db->query($sql); $changeSql = "SELECT ref, title FROM " . $this->db->prefix() . $inventoryObj->table_element . " WHERE ref ILIKE '%Change%'"; $resultCh = $db->query($changeSql); if ($result > 0 && $resultCh > 0) { while ($row = $db->fetch_object($result)) { $row = (array) $row; $date = $row['ph_date_creation']; $device[] = [ "name" => isset($row['title']) ? $row['title'] : '', "sku" => isset($row['unique_identifier']) ? $row['unique_identifier'] : '' ]; } $change = []; while ($rowCh = $db->fetch_object($resultCh)) { $rowCh = (array) $rowCh; $ChangeArray = explode('_', $rowCh['ref']); $key = isset($ChangeArray[1]) ? strtolower($ChangeArray[1]) : ''; if (!empty($key)) { $change[$key] = isset($rowCh['title']) ? $rowCh['title'] : ''; } } } else { return []; } return [ 'date' => $date, 'devices' => $device, 'change' => $change ]; } /** * Save card payment log * * @param string $invoice_ref * @param string $data * * @return array|mixed Data without useless information * * @url POST /cardpaymentlog * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function cardPaymentLog(string $invoice_ref, string $data) { $result = 'OK'; $facture = new Facture($this->db); if ($facture->fetch(0, $invoice_ref) > 0) { $facture->array_options['options_payment_log'] = $data; $facture->updateExtraField('payment_log'); $json = json_decode($data, true); if (!empty($json['authorization_number'])) { $sql = " UPDATE " . MAIN_DB_PREFIX . "paiement SET num_paiement='" . $json['authorization_number'] . "' WHERE rowid=( SELECT fk_paiement FROM " . MAIN_DB_PREFIX . "paiement_facture WHERE fk_facture={$facture->id} ) "; $this->db->query($sql); } } else { $result = 'Missing invoice'; } return $result; } /** * Products list with children * * @param string $sortfield Sort field * @param string $sortorder Sort order * @param int $limit Limit for list * @param int $page Page number * @param int $mode Use this param to filter list (0 for all, 1 for only product, 2 for only service) * @param int $category Use this param to filter list by category * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.tobuy:=:0) and (t.tosell:=:1)" * @param bool $ids_only Return only IDs of product instead of all properties (faster, above all if list is long) * @param int $variant_filter Use this param to filter list (0 = all, 1=products without variants, 2=parent of variants, 3=variants only) * @param bool $pagination_data If this parameter is set to true the response will include pagination data. Default value is false. Page starts from 0 * @param int $includestockdata Load also information about stock (slower) * @return array Array of product objects * * @url GET /productshotel * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function productshotel($sortfield = 't.ref', $sortorder = 'ASC', $limit = 100, $page = 0, $mode = 0, $category = 0, $sqlfilters = '', $ids_only = false, $variant_filter = 0, $pagination_data = false, $includestockdata = 0): array { if (!DolibarrApiAccess::$user->rights->produit->lire) { throw new RestException(403); } return (new ApiProductListHelper)->listhotel($sortfield, $sortorder, $limit, $page, $mode, $category, $sqlfilters, $ids_only, $variant_filter, $pagination_data, $includestockdata); } /** * Get the saled factures data by user * * @param string $date Date * * @return array|mixed Data without useless information * * @url POST /saledfacturesbyuser */ function saledfacturesbyuser(string $date) { global $user, $db; $date = date("Y-m-d", dol_now()); $fulldate = date("Y-m-d H:i:s", dol_now()); $apiBbusHelper = new ApiBBusHelper(); $from = $apiBbusHelper->getGroupLoginDate($date); $to = $apiBbusHelper->getGroupLogout($date, $from); $array = []; if (strtotime($fulldate) > strtotime($to)) { return $array; } $sql = "SELECT f.rowid as facture_rowid, f.ref AS facture_ref, f.datec, f.multicurrency_code, pa.libelle, pai.note AS transaction_id, fdet.fk_product AS product_id, pr.label AS product_label, pr.ref AS product_ref, pr.description, pass.fk_product_pere AS bundle_id, pr2.label AS bundle_label, pr2.ref AS bundle_ref, fdet.multicurrency_total_tva AS base_tva, fdet.multicurrency_total_ttc AS base_ttc, fdete.discount_percent, fdete.discount_hours, pr.default_vat_code, f.multicurrency_total_ttc AS bundle_ttc, (SELECT rate FROM llx_multicurrency_rate AS mc WHERE mc.fk_multicurrency = f.fk_multicurrency AND mc.entity = {$user->entity} ORDER BY mc.rowid DESC LIMIT 1) AS rate, (SELECT date_start FROM llx_eventwizard_eventhistory AS evev WHERE evev.fk_facture = f.rowid) AS date_start FROM llx_facture AS f INNER JOIN llx_facture_extrafields AS fe ON fe.fk_object = f.rowid INNER JOIN llx_c_paiement AS pa ON pa.id = f.fk_mode_reglement INNER JOIN llx_paiement_facture AS pafa ON pafa.fk_facture = f.rowid INNER JOIN llx_paiement AS pai ON pai.rowid = pafa.fk_paiement INNER JOIN llx_facturedet AS fdet ON fdet.fk_facture = f.rowid INNER JOIN llx_product AS pr ON pr.rowid = fdet.fk_product left JOIN llx_product_association AS pass ON pass.fk_product_fils = pr.rowid LEFT JOIN llx_product AS pr2 ON pr2.rowid = pass.fk_product_pere LEFT JOIN llx_facturedet_extrafields AS fdete ON fdet.rowid = fdete.fk_object WHERE f.datec BETWEEN '{$from}' AND '{$to}' AND f.fk_user_closing = $user->id ORDER BY f.rowid DESC"; //print $sql;exit; $data = $db->query($sql); if ($db->num_rows($data > 0)) { while ($row = $db->fetch_object($data)) { $tmpArray = (array) $row; if ($tmpArray['transaction_id'] != '') { $jsonArray = json_decode($tmpArray['transaction_id']); $row->transaction_id = $jsonArray->card_transaction_id; } $row->bundle_id = $row->bundle_id == '' ? $row->product_id : $row->bundle_id; $row->bundle_label = $row->bundle_label == '' ? $row->product_label : $row->bundle_label; $row->bundle_ref = $row->bundle_ref == '' ? $row->product_ref : $row->bundle_ref; $array[$row->facture_rowid]['ref'] = $row->facture_ref; $array[$row->facture_rowid]['bundle_name'] = $row->bundle_label; $array[$row->facture_rowid]['currency'] = $row->multicurrency_code; $array[$row->facture_rowid]['total_price'] = $row->bundle_ttc; $array[$row->facture_rowid]['type'] = $row->libelle; $array[$row->facture_rowid]['transaction_id'] = $row->transaction_id; $array[$row->facture_rowid]['rate'] = $row->rate; $array[$row->facture_rowid]['date'] = $row->datec; $array[$row->facture_rowid]['lines'][$row->product_id] = (array) $row; } return $array; } else { return $array; } } /** * List of assets received * * Return an array with assets received. * * @return array|mixed Data without useless information * * @url GET /getAllUsersOfTheGroup * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function getAllUsersOfTheGroup(): array { global $user, $db; $array = []; $sql = "SELECT u.rowid, u.firstname, u.lastname, u.login, ue.nickname, u.email, u.office_phone, u.user_mobile, u.personal_mobile FROM llx_settlements_groupusers AS gu INNER JOIN llx_user_extrafields as ue ON ue.fk_object = gu.fk_user INNER JOIN llx_user as u ON u.rowid = gu.fk_user WHERE gu.fk_settlements_group = (SELECT gu2.fk_settlements_group FROM llx_settlements_groupusers as gu2 WHERE gu2.fk_user = {$user->id})"; $data = $db->query($sql); while ($row = $db->fetch_object($data)) { $array[] = [ 'id' => $row->rowid, 'name' => $row->firstname . ' ' . $row->lastname, 'login' => $row->login, 'email' => $row->email, 'nickname' => $row->nickname ? $row->nickname : '', 'office_phone' => $row->office_phone, 'user_mobile' => $row->user_mobile, 'personal_mobile' => $row->personal_mobile ]; } return $array; } #------------------------------------------------- # Event generator #------------------------------------------------- /** * Generate events * * @return array|mixed Data without useless information * * @url GET /genEvents * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function genEvents() { $period = new DatePeriod( new DateTime('2024-07-16'), new DateInterval('P1D'), new DateTime('2024-10-16') ); $size = 30; $buffer = 5; $dates = []; foreach ($period as $date) { if (rand(0, 1)) { $eventDate = $date->format('Y-m-d'); $eventTimes = array_rand( array_flip([ '09:00', '10:00', '11:00', '12:00', '13:00', '14:00', '15:00', '16:00', '17:00', '18:00', '19:00', '20:00' ]), rand(1, 12) ); /* print $eventDate; print "\r\n"; print_r($eventTimes); */ if (is_array($eventTimes)) { foreach ($eventTimes as $eventTime) { $duration = rand(1, 3); $dates[$eventDate][] = [ 'start' => $eventTime, 'duration' => '0' . $duration . ':00:00', ]; } } } } //print_r($dates);exit; $eventdetail_id = 1; $dates = ['dates' => $dates, 'id_eventdetails' => $eventdetail_id]; dol_include_once('/eventwizard/class/eventdetails.class.php'); $object = new EventDetails($this->db); $object->fetch($eventdetail_id); $object->genEvents($dates, $eventdetail_id); //print_r($dates);exit; return []; } /** * Generate events * * @return array|mixed Data without useless information * * @url GET /updateeventextrafields * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function updateEventsExtrafields() { $sql = "SELECT ac.id FROM llx_actioncomm as ac LEFT JOIN llx_actioncomm_extrafields as ace ON ace.fk_object = ac.id WHERE ac.code = 'AC_EVENT' AND ace.max_num IS NULL"; $result1 = $this->db->query($sql); while ($row1 = $this->db->fetch_object($result1)) { print_r($row1); $participants = rand(1, 20); $sql2 = "INSERT INTO llx_actioncomm_extrafields (fk_object, max_num, buffer, participants) VALUES ({$row1->id}, 30, 5, $participants)"; $result = $this->db->query($sql2); } } #------------------------------------------------- # Facture generator #------------------------------------------------- /** * Generate factures * * @return array|mixed Data without useless information * * @url POST /generateFactures * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function generateFactures() { $numberOfFactures = 1; for ($i = 0; $i < $numberOfFactures; $i++) { $currencyRand = rand(0, 1); $currencyText = [0 => 'HUF', 1 => 'EUR']; $currencyNumber = [0 => 3, 1 => 5]; $reglementRand = rand(14, 15); //$reglementRand = rand(106, 107); ## STAGING $mode_reglement_id = $reglementRand; $paymentid = $reglementRand; $accountid = [0 => 4, 1 => 5]; $deduction = rand(1, 5) == 3 ? 1 : null; $storno = rand(1, 5) == 1 ? 1 : null; $invoice = ["mode_reglement_id" => $mode_reglement_id, "array_options_app_facture" => 1, "array_options_commission_deduction" => $deduction, "array_options_marked_for_storno" => $storno, "multicurrency_code" => $currencyText[$currencyRand], "fk_multicurrency" => $currencyNumber[$currencyRand], "array_options_customer_data_zip" => null]; $linesHUFBundle = [ ["desc" => "", "subprice" => "787.4015", "qty" => 1, "tva_tx" => "27.0", "localtax1_tx" => "0.000", "localtax2_tx" => "0.000", "fk_product" => "102", "remise_percent" => "0", "date_start" => "", "date_end" => "", "fk_code_ventilation" => 0, "info_bits" => "0", "fk_remise_except" => null, "product_type" => "1", "rang" => "-1", "special_code" => "0", "fk_parent_line" => null, "fk_fournprice" => null, "pa_ht" => "0.00000000", "label" => "", "array_options" => [], "situation_percent" => "100", "fk_prev_id" => null, "fk_unit" => null, "price_base_type" => "HT"], ["desc" => "", "subprice" => "13333.3333", "qty" => 1, "tva_tx" => "5.0", "localtax1_tx" => "0.000", "localtax2_tx" => "0.000", "fk_product" => "108", "remise_percent" => "0", "date_start" => "", "date_end" => "", "fk_code_ventilation" => 0, "info_bits" => "0", "fk_remise_except" => null, "product_type" => "1", "rang" => "-1", "special_code" => "0", "fk_parent_line" => null, "fk_fournprice" => null, "pa_ht" => "0.00000000", "label" => "", "array_options" => [], "situation_percent" => "100", "fk_prev_id" => null, "fk_unit" => null, "price_base_type" => "HT"] ]; $linesEURBundle = [ ["desc" => "", "subprice" => "2.3622", "qty" => 1, "tva_tx" => "27.0", "localtax1_tx" => "0.000", "localtax2_tx" => "0.000", "fk_product" => "101", "remise_percent" => "0", "date_start" => "", "date_end" => "", "fk_code_ventilation" => 0, "info_bits" => "0", "fk_remise_except" => null, "product_type" => "1", "rang" => "-1", "special_code" => "0", "fk_parent_line" => null, "fk_fournprice" => null, "pa_ht" => "0.00000000", "label" => "", "array_options" => [], "situation_percent" => "100", "fk_prev_id" => null, "fk_unit" => null, "price_base_type" => "HT"], ["desc" => "", "subprice" => "33.3333", "qty" => 1, "tva_tx" => "5.0", "localtax1_tx" => "0.000", "localtax2_tx" => "0.000", "fk_product" => "107", "remise_percent" => "0", "date_start" => "", "date_end" => "", "fk_code_ventilation" => 0, "info_bits" => "0", "fk_remise_except" => null, "product_type" => "1", "rang" => "-1", "special_code" => "0", "fk_parent_line" => null, "fk_fournprice" => null, "pa_ht" => "0.00000000", "label" => "", "array_options" => [], "situation_percent" => "100", "fk_prev_id" => null, "fk_unit" => null, "price_base_type" => "HT"] ]; $linesEURSimple = [ ["desc" => "", "subprice" => "12.5984", "qty" => 1, "tva_tx" => "27.0", "localtax1_tx" => "0.000", "localtax2_tx" => "0.000", "fk_product" => "132", "remise_percent" => "0", "date_start" => "", "date_end" => "", "fk_code_ventilation" => 0, "info_bits" => "0", "fk_remise_except" => null, "product_type" => "1", "rang" => "-1", "special_code" => "0", "fk_parent_line" => null, "fk_fournprice" => null, "pa_ht" => "0.00000000", "label" => "", "array_options" => [], "situation_percent" => "100", "fk_prev_id" => null, "fk_unit" => null, "price_base_type" => "HT"], ]; $linesArray = [ 0 => $linesEURBundle, 1 => $linesEURSimple, 2 => $linesHUFBundle ]; if ($currencyRand == 1) { $lineRand = rand(0, 1); $lines = $linesArray[$lineRand]; } else { $lines = $linesArray[2]; } $payment = ["datepaye" => time(), "paymentid" => $paymentid, "closepaidinvoices" => "yes", "accountid" => $accountid[$currencyRand]]; $comment = "{\"timestamp\":\"1704241200\",\"merchant_id\":\"000000000014202\",\"acquirer_id\":\"88105000003\",\"operation_number\":\"000037\",\"termid\":\"36002058\",\"pan\":\"428312******1789\",\"exp\":\"****\",\"stan\":\"000007\",\"authorization_number\":\"282597\",\"trans_type\":\"CLI\",\"amount\":\"2.0\",\"cvm\":\"2\",\"billnumber\":\"AcTbHmcWsMGcF6Nf\",\"card_transaction_id\":\"AcTbHmcWsMGcF6Nf\"}"; $payment['comment'] = $reglementRand == 15 ? '' : $comment; //$payment['comment'] = $reglementRand == 107 ? '' : $comment; ## STAGING $cardPaymentLog = ""; /* print_r($invoice); print_r($lines); print_r($payment); exit; */ $invoiceNumber = $this->invoice($invoice, $lines, $payment, $cardPaymentLog, $sendId = ''); $ref = $invoiceNumber['invoice']['ref']; $datetime = date("Y-m-d H:i:s", $payment['datepaye']); $multiprint = rand(1, 5); $this->dateHandler($ref, $datetime); if ($multiprint == 2 || $multiprint == 3) { $prints = rand(1, 5); $dateofprint = $payment['datepaye']; for ($i = 0; $i < $prints; $i++) { $dateofprint = strtotime('+5 seconds', $dateofprint); $datetime = date("Y-m-d H:i:s", $dateofprint); $this->dateHandler($ref, $datetime); } } } return 'OK'; } #------------------------------------------------- # CURL #------------------------------------------------- /** * Check Printed copies * * Return an array with details * * @return array|mixed data without useless information * * @param string $ref //selected evet from llx_event * * @url POST curlCheckPrintedCopies * @throws RestException 401 Not allowed * @throws RestException 404 Not found */ public function curlCheckPrintedCopies(string $ref) { $bbticketinvoiceprinting = new BbTicketInvoicePrinting($this->db); $copies = $bbticketinvoiceprinting->fetchAll('ASC', 'rowid', 0, 0, ["customsql" => "invoice_number ILIKE '%{$ref}%'"]); return (is_array($copies)) ? count($copies) : 0; } /** * @param string $datetime * @param string $datetime_timestamp * @param array $ticket * @param string $ref * * * @return array|mixed Data without useless information * * @url POST curlSetPrintingInvoiceObject * * @throws RestException 401 * @throws RestException 403 * @throws RestException 404 */ public function curlSetPrintingInvoiceObject(string $datetime, string $datetime_timestamp, array $ticket, string $ref) { global $user; $helper = new ApiBBusHelper(); $helper->setPrintingInvoiceObject($user, null, $datetime, $datetime_timestamp, (object)$ticket, $ref); } }