OpenXE/classes/Modules/AmaInvoice/Service/AmaInvoiceService.php

2329 lines
90 KiB
PHP
Raw Permalink Normal View History

2021-05-21 08:49:41 +02:00
<?php
declare(strict_types=1);
namespace Xentral\Modules\AmaInvoice\Service;
use Briefpapier;
use DateTime;
use GutschriftPDF;
use RechnungPDF;
use Xentral\Components\Database\Database;
use Xentral\Components\Filesystem\Adapter\FtpConfig;
use Xentral\Components\Filesystem\FilesystemFactory;
use \Application;
use Xentral\Components\Filesystem\FilesystemInterface;
use Xentral\Components\Filesystem\PathInfo;
use Xentral\Modules\AmaInvoice\Exception\AmazonInvoiceServiceException;
use Xentral\Modules\AmaInvoice\Exception\InvalidArgumentException;
use DateInterval;
use Xentral\Modules\AmaInvoice\Exception\ThrottlingException;
use \DateTimeInterface;
final class AmaInvoiceService
{
/** @var Database $db */
private $db;
/** @var Application $app */
private $app;
/** @var FilesystemFactory $filesystemFactory */
private $filesystemFactory;
/** @var FilesystemInterface $filesystem */
private $filesystem;
/** @var array $config */
private $config;
/** @var bool */
private $useFtp = false;
/**
* AmaInvoiceService constructor.
*
* @param Database $db
* @param FilesystemFactory $filesystemFactory
* @param Application $app
*/
public function __construct($db, $filesystemFactory, $app)
{
$this->db = $db;
$this->filesystemFactory = $filesystemFactory;
$this->app = $app;
}
/**
* @param string $startDate
* @param string $endDate
* @param string $type
*
* @return array
*/
public function getDocumentsByApi($startDate, $endDate, $type = 'inv'): array
{
$response = $this->prepareParametersByXentral($startDate, $endDate, $type);
$response = @json_decode($response, true);
if (empty($response)) {
return [];
}
if (isset($response[0])) {
return $response;
}
if (isset($response['rem_gs_nr']) || isset($response['inv_rech_nr'])) {
return [$response];
}
return [];
}
/**
* @param string $startDate
* @param string $endDate
* @param string $type
*
* @return string
*/
public function prepareParametersByXentral($startDate, $endDate, $type = 'inv'): string
{
$this->loadConfig();
$firmKeyId = $this->config['firmkeyid'];
$clientIdentifier = $this->config['clientidentifier'];
if (empty($firmKeyId)) {
throw new InvalidArgumentException('firmkeyid is empty');
}
if (empty($clientIdentifier)) {
throw new InvalidArgumentException('clientIdentifier is empty');
}
if (empty($startDate)) {
throw new InvalidArgumentException('startdate is empty');
}
if (empty($endDate)) {
throw new InvalidArgumentException('endDate is empty');
}
$startDate = date('Y-m-d', strtotime($startDate));
$endDate = date('Y-m-d', strtotime($endDate));
$now = new DateTime();
$beforeTwoMonths = clone $now;
$beforeTwoMonths->modify('-2 month');
if ($endDate >= $now->format('Y-m-d')) {
throw new InvalidArgumentException('endDate is not in the past');
}
if ($startDate < $beforeTwoMonths->format('Y-m-d')) {
throw new InvalidArgumentException('endDate is older than two months');
}
if ($type !== 'inv' && $type !== 'rem') {
throw new InvalidArgumentException('type must be "inv" or "rem"');
}
$serial = $this->app->erp->Firmendaten('lizenz');
if (empty($clientIdentifier)) {
throw new InvalidArgumentException('lizenz is empty');
}
$url = 'https://amazon.xentral.com/amainvoiceapp.php';
$schluessel = $this->app->erp->Firmendaten('schluessel');
if (empty($clientIdentifier)) {
throw new InvalidArgumentException('schluessel is empty');
}
$paras = [
'firm_key_id' => $firmKeyId,
'client_identifier' => $clientIdentifier,
'start_date' => $startDate,
'end_date' => $endDate,
'data_type' => $type,
'json' => false,
];
$paras = [
'serial' => $serial,
'schluessel' => $schluessel,
'paras' => json_encode($paras),
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($paras));
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
$httpcode = curl_getinfo($ch);
curl_close($ch);
if ($response === 'Throttel is On') {
$this->db->perform(
"INSERT INTO `logfile` ( meldung, dump, module, action, bearbeiter, funktionsname, datum)
VALUES ('Throttel is On', '', 'amainvoice', '', 'Cronjob', '', NOW() )"
);
throw new ThrottlingException($response);
}
$httpcode = $httpcode['http_code'];
if (strpos((string)$httpcode, '2') === 0) {
if ($response === 'Error: Parameters not loaded [0]') {
throw new AmazonInvoiceServiceException($response);
}
return $response;
}
if (!empty($response)) {
$response2 = @json_decode($response, true);
if (!empty($response2['error'])) {
if (!empty($response2['throttled'])) {
$error = $response2['error'];
if (is_array($error)) {
$error = reset($error);
}
$this->db->perform(
"INSERT INTO `logfile` ( meldung, dump, module, action, bearbeiter, funktionsname, datum)
VALUES ('Throttel by xentral is On', '', 'amainvoice', '', 'Cronjob', '', NOW() )"
);
throw new ThrottlingException($error);
}
if (is_array($response2['error'])) {
throw new AmazonInvoiceServiceException(reset($response2['error']));
}
if (is_string($response2['error'])) {
throw new AmazonInvoiceServiceException($response2['error']);
}
}
}
throw new AmazonInvoiceServiceException($response);
}
/**
* @return array
*/
public function getConfig(): array
{
return $this->db->fetchPairs('SELECT `name`, `value` FROM `amainvoice_config`');
}
/**
* @param array $configArr
*/
public function setConfig($configArr): void
{
if (empty($configArr)) {
throw new InvalidArgumentException('Config Array empty');
}
foreach ($configArr as $key => $value) {
if (empty($key)) {
throw new InvalidArgumentException('Config Array invalid');
}
}
$config = $this->getConfig();
foreach ($configArr as $key => $value) {
if (!isset($config[$key])) {
$this->db->perform(
'INSERT INTO `amainvoice_config` (`name`, `value`) VALUES (:name, :value)',
['name' => $key, 'value' => (string)$value]
);
} elseif ((string)$value !== $config[$key]) {
$this->db->perform(
'UPDATE `amainvoice_config` SET `value` = :value WHERE `name` = :name',
['name' => $key, 'value' => (string)$value]
);
}
}
}
/**
* @return array|PathInfo[]
*/
public function getFiles(): array
{
if ($this->config === null) {
$this->loadConfig();
}
if ($this->filesystem === null) {
try {
$now = new DateTime();
$beforeTwoMonths = clone $now;
$beforeTwoMonths->modify('-2 month');
$startDate = new DateTime($this->config['startdate']);
if ($startDate < $beforeTwoMonths) {
$startDate = $beforeTwoMonths;
}
$toDate = clone $now;
$toDate->sub(new DateInterval('P1D'));
$ret = [];
while ($startDate < $toDate) {
$dateFormated = $startDate->format('Y-m-d');
$ret[] = new PathInfo(
[
'type' => 'file',
'filename' => $dateFormated . '.inv',
'path' => $dateFormated . '.inv',
]
);
$ret[] = new PathInfo(
[
'type' => 'file',
'filename' => $dateFormated . '.rem',
'path' => $dateFormated . '.rem',
]
);
$startDate->add(new DateInterval('P1D'));
}
return $ret;
} catch (\Exception $e) {
return [];
}
}
return $this->filesystem->listFiles('');
}
/**
* @return bool
*/
public function hasConfigFileSystem(): bool
{
if ($this->config === null) {
$this->loadConfig();
}
return $this->filesystem !== null;
}
/**
* @return array
*/
public function getNewFiles(): array
{
$files = $this->getFiles();
if (empty($files)) {
return [];
}
$fileNames = [];
foreach ($files as $file) {
$fileName = $file->getPath();
$fileNames[] = $fileName;
}
$inDb = $this->db->fetchPairs(
'SELECT `id`, `filename` FROM `amainvoice_files` WHERE `filename` IN (:filenames)',
['filenames' => $fileNames]
);
$inDb = array_values($inDb);
return array_diff($fileNames, $inDb);
}
/**
* @param string $file
* @param string $to
*
* @return string
*/
public function getFile($file, $to = ''): string
{
try {
if (empty($to)) {
$to = $file;
}
$fileSystemConfig = [
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0664,
],
'dir' => [
'public' => 0775,
'private' => 0775,
],
],
];
if (is_file($this->app->erp->GetTMP() . $to)) {
return $this->app->erp->GetTMP() . $to;
}
$fileSystemTo = $this->filesystemFactory->createLocal($this->app->erp->GetTMP(), $fileSystemConfig);
if ($fileSystemTo->write($to, $this->filesystem->read($file))) {
return $this->app->erp->GetTMP() . $to;
};
} catch (\Exception $e) {
throw $e;
}
throw new InvalidArgumentException('could not download file ' . $file);
}
/**
* @param string $type
* @param string $amazonOrderId
* @param string $number
* @param array $datevRows
* @param array $positions
* @param string $pdfFile
* @param bool $createOrder
*
* @return bool
*/
public function createDocument(
$type,
$amazonOrderId,
$number,
$datevRows,
$positions,
$pdfFile = '',
$createOrder = false
): bool {
if (empty($amazonOrderId)) {
throw new InvalidArgumentException('amazonOrderId is empty');
}
if ($number !== null && empty($number)) {
throw new InvalidArgumentException('document number is empty');
}
if ($type !== 'invoice' && $type !== 'returnorder') {
throw new InvalidArgumentException('type not valid');
}
$order = $this->db->fetchCol(
"SELECT `id`
FROM `auftrag`
WHERE `internet` = :amazonorderid AND `internet` <> '' AND `status` <> 'storniert' ",
['amazonorderid' => $amazonOrderId]
);
$firstOrderId = empty($order) ? null : reset($order);
$orderCreated = false;
$firstDatevRow = reset($datevRows);
$isOrderFbm = true;
if(!empty($firstDatevRow['fulfillmentchannel']) && $firstDatevRow['fulfillmentchannel'] === 'AFN') {
$isOrderFbm = false;
}
$statusInfo = null;
if($isOrderFbm) {
$statusInfo = $this->db->fetchRow(
"SELECT `status`, `schreibschutz`
FROM `auftrag`
WHERE `id` = :order_id ",
['order_id' => (int)$firstOrderId]
);
if(empty($statusInfo) || $statusInfo['status'] !== 'abgeschlossen') {
return false;
}
}
$billaddress1 = $firstDatevRow['billaddress1'];
$billaddress2 = $firstDatevRow['billaddress2'];
$billaddress3 = $firstDatevRow['billaddress3'];
$shipaddress1 = $firstDatevRow['shipaddress1'];
$shipaddress2 = $firstDatevRow['shipaddress2'];
$shipaddress3 = $firstDatevRow['shipaddress3'];
$billStreet3 = '';
$shipStreet3 = '';
if(!empty($billaddress1)) {
$billStreet = $billaddress1;
if(is_numeric($billaddress2)) {
$billStreet .= ' ' . $billaddress2;
$billStreet2 = $billaddress3;
}
else {
$billStreet2 = $billaddress2;
$billStreet3 = $billaddress3;
}
}
else {
$billStreet = $billaddress2;
if(is_numeric($billaddress3)) {
$billStreet .= ' ' . $billaddress3;
}
else {
$billStreet2 = $billaddress2;
}
}
if(!empty($shipaddress1)) {
$shipStreet = $shipaddress1;
if(is_numeric($shipaddress2)) {
$shipStreet .= ' ' . $shipaddress2;
$shipStreet2 = $shipaddress3;
}
else {
$shipStreet2 = $shipaddress2;
$shipStreet3 = $shipaddress3;
}
}
else {
$shipStreet = $shipaddress2;
if(is_numeric($shipaddress3)) {
$shipStreet .= ' ' . $shipaddress3;
}
else {
$shipStreet2 = $shipaddress2;
}
}
if (empty($order) && $createOrder) {
$address = [
'name' => $firstDatevRow['buyername'],
'kundennummer' => $this->app->erp->GetNextKundennummer(),
'strasse' => $billStreet,
'addresszusatz' => $billStreet2,
'ort' => $firstDatevRow['billcity'],
'plz' => $firstDatevRow['billpostalcode'],
'land' => $firstDatevRow['billcountry'],
];
$address['id'] = (int)$this->app->erp->InsertUpdateAdresse($address);
$orderId = (int)$this->app->erp->CreateAuftrag($address['id']);
$this->app->erp->LoadAuftragStandardwerte($orderId, $address['id']);
$order = [
'name' => $firstDatevRow['buyername'],
'strasse' => $billStreet,
'addresszusatz' => $billStreet2,
'ort' => $firstDatevRow['billcity'],
'plz' => $firstDatevRow['billpostalcode'],
'land' => $firstDatevRow['billcountry'],
'email' => $firstDatevRow['buyeremail'],
'lieferstrasse' => $shipStreet,
'lieferaddresszusatz' => $shipStreet2,
'lieferland' => $firstDatevRow['shipcountry'],
'versandart' => $firstDatevRow['carrier'],
'lieferort' => $firstDatevRow['shipcity'],
'lieferplz' => $firstDatevRow['shippostalcode'],
'liefername' => $firstDatevRow['recipientname'],
];
if ($isOrderFbm && !empty($this->config['projectfbm'])) {
$order['projekt'] = $this->config['projectfbm'];
} elseif (!$isOrderFbm && !empty($this->config['projectfba'])) {
$order['projekt'] = $this->config['projectfba'];
}
if (!empty($this->config['paymentmethod'])) {
$order['versandart'] = $this->config['paymentmethod'];
}
$this->app->DB->UpdateArr('auftrag', $orderId, 'id', $order, true);
$this->db->perform(
'UPDATE `auftrag` SET `internet` = :orderid WHERE `id` = :id',
[
'orderid' => $amazonOrderId,
'id' => $orderId,
]
);
$this->app->erp->BelegFreigabe('auftrag', $orderId);
$orderCreated = true;
$order = $this->db->fetchCol(
"SELECT `id`
FROM `auftrag`
WHERE `internet` = :amazonorderid AND `internet` <> '' AND `status` <> 'storniert' ",
['amazonorderid' => $amazonOrderId]
);
$this->app->erp->AuftragProtokoll($orderId, 'Auftrag erstellt durch AmaInvoice');
}
if (empty($order)) {
return false;
//throw new InvalidArgumentException(sprintf('order %s not found', $amazonOrderId));
}
$order = (int)reset($order);
if ($type === 'invoice') {
if ($number !== null) {
$invoice = $this->db->fetchCol(
'SELECT `id` FROM `rechnung` WHERE `auftragid` = :orderid AND `belegnr` = :number',
['orderid' => $order, 'number' => $number]
);
} else {
$invoice = $this->db->fetchCol(
'SELECT `id` FROM `rechnung` WHERE `auftragid` = :orderid',
['orderid' => $order]
);
}
if (!empty($invoice)) {
return false;
}
$forceApproval = $this->app->erp->Firmendaten('schnellanlegen_ohnefreigabe') == '1';
if($forceApproval) {
$db = $this->app->Conf->WFdbname;
$this->app->erp->firmendaten[$db]['schnellanlegen_ohnefreigabe'] = 0;
}
$invoice = (int)$this->app->erp->WeiterfuehrenAuftragZuRechnung($order);
if($isOrderFbm && !empty($statusInfo)) {
$this->db->perform(
'UPDATE `auftrag` SET `status` = :status, `schreibschutz` = :readonly WHERE `id` = :order_id',
[
'status' => $statusInfo['status'],
'readonly' => (int)$statusInfo['schreibschutz'],
'order_id' => $order
]
);
}
if($forceApproval) {
$this->app->erp->firmendaten[$db]['schnellanlegen_ohnefreigabe'] = '1';
}
$invoiceArr = [
'name' => $firstDatevRow['buyername'],
'strasse' => $billStreet,
'addresszusatz' => $billStreet2,
'abteilung' => $billStreet3,
'ort' => $firstDatevRow['billcity'],
'plz' => $firstDatevRow['billpostalcode'],
'land' => $firstDatevRow['billcountry'],
'email' => $firstDatevRow['buyeremail'],
'belegnr' => $number === null ? $firstDatevRow['inv_rech_nr'] : $number,
];
$orderArr = [
'name' => $firstDatevRow['buyername'],
'strasse' => $billStreet,
'addresszusatz' => $billStreet2,
'abteilung' => $billStreet3,
'ort' => $firstDatevRow['billcity'],
'plz' => $firstDatevRow['billpostalcode'],
'land' => $firstDatevRow['billcountry'],
'email' => $firstDatevRow['buyeremail'],
];
if(
$firstDatevRow['buyername'] !== $firstDatevRow['recipientname']
|| $billStreet !== $shipStreet
|| $billStreet2 !== $shipStreet2
) {
$orderArr['abweichendelieferadresse'] = 1;
$orderArr['liefername'] = $firstDatevRow['recipientname'];
$orderArr['lieferstrasse'] = $shipStreet;
$orderArr['lieferadresszusatz'] = $shipStreet2;
$orderArr['lieferabteilung'] = $shipStreet3;
$orderArr['lieferort'] = $firstDatevRow['shipcity'];
$orderArr['lieferplz'] = $firstDatevRow['shippostalcode'];
$orderArr['lieferland'] = $firstDatevRow['shipcountry'];
}
$this->app->DB->UpdateArr('auftrag', $order, 'id', $orderArr, true);
$this->app->DB->UpdateArr('rechnung', $invoice, 'id', $invoiceArr, true);
$this->app->erp->AuftragProtokoll($order, 'Rechnung erstellt durch AmaInvoice');
$this->app->erp->BelegFreigabe('rechnung', $invoice);
$soll = 0;
foreach ($positions as $position) {
$soll += (float)str_replace(',', '.', $position['brutto_total']);
}
$this->addPositions('invoice', $invoice, $positions, $orderCreated ? $order : null);
$this->addDiscountArticles(
'invoice',
$invoice,
$datevRows,
$positions,
$orderCreated ? $order : null
);
$this->addShippingArticles(
'invoice',
$invoice,
$datevRows,
$positions,
$orderCreated ? $order : null
);
$this->app->erp->RechnungNeuberechnen($invoice);
$this->db->perform(
"UPDATE `rechnung`
SET `datum` = :date, `waehrung` = :currency, `soll` = :soll, `extsoll` = :soll,
schreibschutz = 1, `status` = 'versendet'
WHERE `id` = :invoiceId",
[
'date' => $firstDatevRow['date'],
'currency' => $firstDatevRow['currency'],
'invoiceId' => $invoice,
'soll' => $soll,
]
);
if(!empty($firstDatevRow['fulfillmentchannel']) && $firstDatevRow['fulfillmentchannel'] === 'AFN') {
$this->db->perform(
'UPDATE `rechnung` SET `ist` = `soll` WHERE `id` = :invoiceId',
[
'invoiceId' => $invoice,
]
);
}
$this->app->erp->PDFArchivieren('rechnung', $invoice, true);
if (empty($pdfFile) && !empty($firstDatevRow['documentlink'])) {
$content = file_get_contents($firstDatevRow['documentlink']);
$pdfFile = basename($firstDatevRow['documentlink']) . '.pdf';
file_put_contents($this->app->erp->GetTMP() . $pdfFile, $content);
$this->archiveDocument('invoice', $invoice, $pdfFile);
if (is_file($this->app->erp->GetTMP() . $pdfFile)) {
unlink($this->app->erp->GetTMP() . $pdfFile);
}
} elseif (!empty($pdfFile)) {
$this->archiveDocument('invoice', $invoice, $pdfFile);
}
if ($orderCreated && !$isOrderFbm) {
$this->db->perform(
"UPDATE `auftrag`
SET `datum` = :date, `waehrung` = :currency, `gesamtsumme` = :soll, `extsoll` = :soll,
schreibschutz = 1, `status` = 'abgeschlossen'
WHERE `id` = :orderId",
[
'date' => $firstDatevRow['date'],
'currency' => $firstDatevRow['currency'],
'orderId' => $order,
'soll' => $soll,
]
);
$this->app->erp->PDFArchivieren('auftrag', $order, true);
}
return true;
}
if ($type === 'returnorder') {
$invoices = $this->db->fetchCol(
'SELECT `id` FROM `rechnung` WHERE `auftragid` = :orderid',
['orderid' => $order]
);
if (empty($invoices)) {
throw new InvalidArgumentException('invoice not found');
}
$returnOrder = $this->db->fetchCol(
'SELECT `id` FROM `gutschrift` WHERE `rechnungid` IN (:invoiceids) AND `belegnr` = :number',
['invoiceids' => $invoices, 'number' => $number]
);
if (!empty($returnOrder)) {
return false;
}
$invoice = reset($invoices);
$forceApproval = $this->app->erp->Firmendaten('schnellanlegen_ohnefreigabe') == '1';
if($forceApproval) {
$db = $this->app->Conf->WFdbname;
$this->app->erp->firmendaten[$db]['schnellanlegen_ohnefreigabe'] = 0;
}
$returnOrder = $this->app->erp->WeiterfuehrenRechnungZuGutschrift($invoice);
if($forceApproval) {
$this->app->erp->firmendaten[$db]['schnellanlegen_ohnefreigabe'] = 1;
}
$this->app->erp->RechnungProtokoll($invoice, 'Gutschrift erstellt durch AmaInvoice');
$this->db->perform(
'UPDATE `gutschrift` SET `belegnr` = :number WHERE `id` = :id LIMIT 1',
[
'number' => (string)$number,
'id' => (int)$returnOrder,
]
);
$this->app->erp->BelegFreigabe('gutschrift', $returnOrder);
$soll = 0;
foreach ($datevRows as $datevRow) {
$soll += (float)str_replace(',', '.', $datevRow['brutto']);
}
$this->addPositions('returnorder', $returnOrder, $positions);
$this->addDiscountArticles('returnorder', $returnOrder, $datevRows, $positions);
$this->addShippingArticles('returnorder', $returnOrder, $datevRows, $positions);
$this->app->erp->GutschriftNeuberechnen($returnOrder);
$this->db->perform(
"UPDATE `gutschrift`
SET `datum` = :date, `waehrung` = :currency, `soll` = :soll, `extsoll` = :soll,
schreibschutz = 1, `status` = 'versendet'
WHERE `id` = :returnorderid",
[
'date' => $firstDatevRow['date'],
'currency' => $firstDatevRow['currency'],
'returnorderid' => $returnOrder,
'soll' => $soll,
]
);
$this->app->erp->PDFArchivieren('gutschrift', $returnOrder, true);
if (empty($pdfFile) && !empty($firstDatevRow['documentlink'])) {
$content = file_get_contents($firstDatevRow['documentlink']);
$pdfFile = basename($firstDatevRow['documentlink']) . '.pdf';
file_put_contents($this->app->erp->GetTMP() . $pdfFile, $content);
$this->archiveDocument('returnorder', $returnOrder, $pdfFile);
if (is_file($this->app->erp->GetTMP() . $pdfFile)) {
unlink($this->app->erp->GetTMP() . $pdfFile);
}
} elseif (!empty($pdfFile)) {
$this->archiveDocument('returnorder', $returnOrder, $pdfFile);
}
return true;
}
return false;
}
/**
* @param string $file
* @param string $type
* @param string $status
*/
public function markFile($file, $type, $status = ''): void
{
$this->db->perform(
'INSERT INTO `amainvoice_files` (`filename`, `type`, `status`) VALUES (:filename, :type, :status)',
['filename' => $file, 'type' => $type, 'status' => (string)$status]
);
}
/**
* @param string $file
*/
public function cleanFile($file): void
{
$file = $this->app->erp->GetTMP() . $file;
if (!is_file($file)) {
return;
}
@unlink($file);
}
/**
* @param string $file
*
* @return array
*/
public function getPositionFromDatevCsv($file): array
{
$handle = fopen($file, 'rb');
if (empty($handle)) {
throw new InvalidArgumentException('could not open file ' . $file);
}
$firstLine = fgetcsv($handle, 0, ';');
$from = $firstLine[14];
$year = substr($from, 0, 4);
$return = [];
while ($row = fgetcsv($handle, 0, ';')) {
$brutto = $row[0];
$soll = $row[1] === 'S';
$currency = $row[2];
$exchangerate = $row[3];
$konto = $row[6];
$gegenkonto = $row[7];
$bu = $row[8];
$date = $row[9];
if (strlen($date) < 4) {
$date = '0' . $date;
}
$day = substr($date, 0, 2);
$month = substr($date, 2, 2);
$date = $year . '-' . $month . '-' . $day;
$number = $row[10];
$amzOrderId = $row[52];
$marketplace = $row[50];
$ustId = $row[48];
$tax = $row[40];
$euCountry = $row[39];
$customerUstId = $row[58];
$storageCountry = $row[54];
$country = $row[56];
$type = $soll ? 'invoice' : 'returnorder';
if (strpos($number, 'GS') === 0) {
$type = 'returnorder';
}
$return[$type][$amzOrderId][$number] = [
'brutto' => $brutto,
'currency' => $currency,
'exchangerate' => $exchangerate,
'konto' => $konto,
'gegenkonto' => $gegenkonto,
'bu' => $bu,
'date' => $date,
'marketplace' => $marketplace,
'eucountry' => $euCountry,
'tax' => $tax,
'ustid' => $ustId,
'customerustid' => $customerUstId,
'storageCountry' => $storageCountry,
'country' => $country,
];
}
fclose($handle);
return $return;
}
/**
* @param string $file
*/
public function executeImportDateFile($file)
{
$ext = substr($file, -3);
$type = $ext === 'rem' ? 'returnorder' : 'invoice';
$apiPositions = $this->executeGetPostionsByApiAndFilename($file);
foreach ($apiPositions[$type] as $amazonOrderId => $apiSubPositions) {
$document = [$apiSubPositions['document']];
foreach ($apiSubPositions['positions'] as $numberInvoice => $apiSubPosition) {
try {
$this->createDocument(
$type,
$amazonOrderId,
null,
$document,
$apiSubPosition,
'',
$this->isCreateOrderActive()
);
} catch (InvalidArgumentException $e) {
}
}
}
$this->markFile($file, 'api_' . $type, 'imported');
}
/**
* @param bool $isReturnOrder
* @param bool $createOrder
*/
public function executeImportDateDbEntries($isReturnOrder, $createOrder = false): void
{
$apiPositions = $this->getNotImportedPositionsFromDb($isReturnOrder, $createOrder);
$type = $isReturnOrder ? 'returnorder' : 'invoice';
foreach ($apiPositions[$type] as $amazonOrderId => $apiSubPositions) {
$document = [$apiSubPositions['document']];
foreach ($apiSubPositions['positions'] as $numberInvoice => $apiSubPosition) {
try {
$this->createDocument(
$type,
$amazonOrderId,
null,
$document,
$apiSubPosition,
'',
$createOrder
);
} catch (InvalidArgumentException $e) {
}
}
}
}
/**
* @param DateTimeInterface $dateFrom
* @param DateTimeInterface $dateTo
* @param bool $isReturnOrder
*/
public function markDbEntriesToImport($dateFrom, $dateTo, $isReturnOrder): void
{
if (!$isReturnOrder) {
$this->loadConfig();
$createOrder = $this->isCreateOrderActive();
if (!$createOrder) {
$this->db->perform(
"UPDATE `amazoninvoice_position`
SET `create` = 1
WHERE `doctype_id` = 0 AND `create_order` = 0 AND `rem_gs_nr` = ''
AND `inv_date` >= :dateFrom AND `inv_date` >= :dateTo",
[
'dateFrom' => $dateFrom->format('Y-m-d'),
'dateTo' => $dateTo->format('Y-m-d'),
]
);
} else {
$this->db->perform(
"UPDATE `amazoninvoice_position`
SET `create` = 1, `create_order` = 1
WHERE `doctype_id` = 0 AND `create_order` = 0 AND `rem_gs_nr` = ''
AND `inv_date` >= :dateFrom AND `inv_date` >= :dateTo",
[
'dateFrom' => $dateFrom->format('Y-m-d'),
'dateTo' => $dateTo->format('Y-m-d'),
]
);
}
} else {
$this->db->perform(
"UPDATE `amazoninvoice_position`
SET `create` = 1
WHERE `doctype_id` = 0 AND `create_order` = 0 AND `rem_gs_nr` <> ''
AND `rem_gs_nr` >= :dateFrom AND `rem_gs_nr` >= :dateTo",
[
'dateFrom' => $dateFrom->format('Y-m-d'),
'dateTo' => $dateTo->format('Y-m-d'),
]
);
}
}
/**
* @param string $file
*
* @return array|array[]
*/
public function executeGetPostionsByApiAndFilename($file): array
{
$date = substr($file, 0, 10);
$ext = substr($file, -3);
$arr = $this->getDocumentsByApi($date, $date, $ext);
$arr = $this->insertFromApiReturn($arr, $date, $ext === 'rem');
return $this->getPositionsFromApiRequest(
$arr,
$ext === 'rem'
);
}
/**
* @param bool $isReturnOrder
* @param bool $createOrder
*
* @return array|array[]
*/
public function getNotImportedPositionsFromDb($isReturnOrder, $createOrder = false, $hours = 8): array
{
if (!$isReturnOrder) {
if (!$createOrder) {
$arr = $this->db->fetchAll(
"SELECT ap.*
FROM `amazoninvoice_position` AS `ap`
WHERE ap.`create` = 1 AND ap.doctype_id = 0 AND `create_order` = 0 AND ap.rem_gs_nr = ''
ORDER BY ap.`inv_date`, ap.id"
);
} else {
$arr = $this->db->fetchAll(
"SELECT ap.*
FROM `amazoninvoice_position` AS `ap`
WHERE ap.`create` = 1 AND ap.doctype_id = 0 AND `create_order` = 1 AND ap.rem_gs_nr = ''
AND ap.created_at < DATE_SUB(NOW(), INTERVAL :hours HOUR)
ORDER BY ap.`inv_date`, ap.id",
[
'hours' => $hours,
]
);
}
} else {
$arr = $this->db->fetchAll(
"SELECT ap.*
FROM `amazoninvoice_position` AS `ap`
WHERE ap.`create` = 1 AND ap.doctype_id = 0 AND ap.rem_gs_nr <> ''
ORDER BY ap.`rem_date`, ap.id"
);
}
return $this->getPositionsFromApiRequest(
$arr,
$isReturnOrder
);
}
/**
* @param array $arr
* @param string $date
* @param bool $isReturnOrder
*
* @return array
*/
public function insertFromApiReturn($arr, $date, $isReturnOrder): array
{
if ($isReturnOrder) {
$inDb = $this->db->fetchPairs(
'SELECT `rem_gs_nr`, `id` FROM `amazoninvoice_position` WHERE `rem_date` = :date',
['date' => $date]
);
} else {
$inDb = $this->db->fetchPairs(
'SELECT `inv_rech_nr`, `id` FROM `amazoninvoice_position` WHERE `inv_date` = :date',
['date' => $date]
);
}
foreach ($arr as $key => $row) {
if ($isReturnOrder) {
if (!empty($inDb[$row['rem_gs_nr']])) {
$arr[$key]['id'] = $inDb[$row['rem_gs_nr']];
continue;
}
} elseif (!empty($inDb[$row['inv_rech_nr']])) {
$arr[$key]['id'] = $inDb[$row['inv_rech_nr']];
continue;
}
$this->db->perform(
'INSERT INTO `amazoninvoice_position`
(
`inv_rech_nr`,`inv_date`,`amazonorderid`,`shipmentdate`,`buyeremail`,`buyerphonenumber`,
`buyername`,`sku`,`productname`,`quantitypurchased`,`quantityshipped`,`currency`,`mwst`,
`taxrate`,`brutto_total`,`netto_total`,`tax_total`,`itemprice`,`itemprice_netto`,`itemprice_tax`,
`shippingprice`,`shippingprice_netto`,`shippingprice_tax`,`giftwrapprice`,`giftwrapprice_netto`,
`giftwrapprice_tax`,`itempromotiondiscount`,`itempromotiondiscount_netto`,
`itempromotiondiscount_tax`,`shippromotiondiscount`,`shippromotiondiscount_netto`,
`shippromotiondiscount_tax`,`giftwrappromotiondiscount`,`giftwrappromotiondiscount_netto`,
`giftwrappromotiondiscount_tax`,`shipservicelevel`,`recipientname`,`shipaddress1`,`shipaddress2`,
`shipaddress3`,`shipcity`,`shipstate`,`shippostalcode`,`shipcountry`,`shipphonenumber`,
`billaddress1`,`billaddress2`,`billaddress3`,`billcity`,`billstate`,`billpostalcode`,
`billcountry`,`carrier`,`trackingnumber`,`fulfillmentcenterid`,`fulfillmentchannel`,
`saleschannel`,`asin`,`conditiontype`,`quantityavailable`,`isbusinessorder`,`uid`,`vatcheck`,
`documentlink`,`order_id`,`rem_gs_nr`,`orderid`,
`rem_date`,`returndate`,`buyercompanyname`,`quantity`,`remreturnshipcost`,
`remsondererstattung`,`itempromotionid`,`reason`,`rem_gs_nr_real`, `created_at`
) VALUES (
:inv_rech_nr, :inv_date, :amazonorderid, :shipmentdate, :buyeremail, :buyerphonenumber,
:buyername, :sku, :productname, :quantitypurchased, :quantityshipped, :currency, :mwst,
:taxrate, :brutto_total, :netto_total, :tax_total, :itemprice, :itemprice_netto, :itemprice_tax,
:shippingprice, :shippingprice_netto, :shippingprice_tax, :giftwrapprice, :giftwrapprice_netto,
:giftwrapprice_tax, :itempromotiondiscount, :itempromotiondiscount_netto,
:itempromotiondiscount_tax, :shippromotiondiscount, :shippromotiondiscount_netto,
:shippromotiondiscount_tax, :giftwrappromotiondiscount, :giftwrappromotiondiscount_netto,
:giftwrappromotiondiscount_tax, :shipservicelevel, :recipientname, :shipaddress1,
:shipaddress2, :shipaddress3, :shipcity, :shipstate, :shippostalcode, :shipcountry,
:shipphonenumber, :billaddress1, :billaddress2, :billaddress3, :billcity, :billstate,
:billpostalcode, :billcountry, :carrier, :trackingnumber, :fulfillmentcenterid,
:fulfillmentchannel, :saleschannel, :asin, :conditiontype, :quantityavailable,
:isbusinessorder, :uid, :vatcheck, :documentlink, :order_id, :rem_gs_nr, :orderid,
:rem_date, :returndate, :buyercompanyname, :quantity, :remreturnshipcost,
:remsondererstattung, :itempromotionid, :reason, :rem_gs_nr_real, NOW()
) ',
[
'inv_rech_nr' => (string)$row['inv_rech_nr'],
'inv_date' => (string)$row['inv_date'],
'amazonorderid' => (string)$row['amazonorderid'],
'shipmentdate' => (string)$row['shipmentdate'],
'buyeremail' => (string)$row['buyeremail'],
'buyerphonenumber' => (string)$row['buyerphonenumber'],
'buyername' => (string)$row['buyername'],
'sku' => (string)$row['sku'],
'productname' => (string)$row['productname'],
'quantitypurchased' => (string)$row['quantitypurchased'],
'quantityshipped' => (string)$row['quantityshipped'],
'currency' => (string)$row['currency'],
'mwst' => (string)$row['mwst'],
'taxrate' => (string)$row['taxrate'],
'brutto_total' => (string)$row['brutto_total'],
'netto_total' => (string)$row['netto_total'],
'tax_total' => (string)$row['tax_total'],
'itemprice' => (string)$row['itemprice'],
'itemprice_netto' => (string)$row['itemprice_netto'],
'itemprice_tax' => (string)$row['itemprice_tax'],
'shippingprice' => (string)$row['shippingprice'],
'shippingprice_netto' => (string)$row['shippingprice_netto'],
'shippingprice_tax' => (string)$row['shippingprice_tax'],
'giftwrapprice' => (string)$row['giftwrapprice'],
'giftwrapprice_netto' => (string)$row['giftwrapprice_netto'],
'giftwrapprice_tax' => (string)$row['giftwrapprice_tax'],
'itempromotiondiscount' => (string)$row['itempromotiondiscount'],
'itempromotiondiscount_netto' => (string)$row['itempromotiondiscount_netto'],
'itempromotiondiscount_tax' => (string)$row['itempromotiondiscount_tax'],
'shippromotiondiscount' => (string)$row['shippromotiondiscount'],
'shippromotiondiscount_netto' => (string)$row['shippromotiondiscount_netto'],
'shippromotiondiscount_tax' => (string)$row['shippromotiondiscount_tax'],
'giftwrappromotiondiscount' => (string)$row['giftwrappromotiondiscount'],
'giftwrappromotiondiscount_netto' => (string)$row['giftwrappromotiondiscount_netto'],
'giftwrappromotiondiscount_tax' => (string)$row['giftwrappromotiondiscount_tax'],
'shipservicelevel' => (string)$row['shipservicelevel'],
'recipientname' => (string)$row['recipientname'],
'shipaddress1' => (string)$row['shipaddress1'],
'shipaddress2' => (string)$row['shipaddress2'],
'shipaddress3' => (string)$row['shipaddress3'],
'shipcity' => (string)$row['shipcity'],
'shipstate' => (string)$row['shipstate'],
'shippostalcode' => (string)$row['shippostalcode'],
'shipcountry' => (string)$row['shipcountry'],
'shipphonenumber' => (string)$row['shipphonenumber'],
'billaddress1' => (string)$row['billaddress1'],
'billaddress2' => (string)$row['billaddress2'],
'billaddress3' => (string)$row['billaddress3'],
'billcity' => (string)$row['billcity'],
'billstate' => (string)$row['billstate'],
'billpostalcode' => (string)$row['billpostalcode'],
'billcountry' => (string)$row['billcountry'],
'carrier' => (string)$row['carrier'],
'trackingnumber' => (string)$row['trackingnumber'],
'fulfillmentcenterid' => (string)$row['fulfillmentcenterid'],
'fulfillmentchannel' => (string)$row['fulfillmentchannel'],
'saleschannel' => (string)$row['saleschannel'],
'asin' => (string)$row['asin'],
'conditiontype' => (string)$row['conditiontype'],
'quantityavailable' => (string)$row['quantityavailable'],
'isbusinessorder' => (string)$row['isbusinessorder'],
'uid' => (string)$row['uid'],
'vatcheck' => (string)$row['vatcheck'],
'documentlink' => (string)$row['documentlink'],
'order_id' => (string)$row['order_id'],
'rem_gs_nr' => (string)$row['rem_gs_nr'],
'orderid' => (string)$row['orderid'],
'rem_date' => (string)$row['rem_date'],
'returndate' => (string)$row['returndate'],
'buyercompanyname' => (string)$row['buyercompanyname'],
'quantity' => (string)$row['quantity'],
'remreturnshipcost' => (string)$row['remreturnshipcost'],
'remsondererstattung' => (string)$row['remsondererstattung'],
'itempromotionid' => (string)$row['itempromotionid'],
'reason' => (string)$row['reason'],
'rem_gs_nr_real' => (string)$row['rem_gs_nr_real'],
]
);
$arr[$key]['id'] = $this->db->lastInsertId();
}
return $arr;
}
/**
* @param array $arr
* @param bool $isReturnOrder
*
* @return array|array[]
*/
public function getPositionsFromApiRequest($arr, $isReturnOrder = false): array
{
if (empty($arr)) {
return [];
}
$type = $isReturnOrder ? 'returnorder' : 'invoice';
$return = [$type => []];
$numberKey = $isReturnOrder ? 'rem_gs_nr' : 'inv_rech_nr';
$dateKey = $isReturnOrder ? 'rem_date' : 'inv_date';
foreach ($arr as $row) {
$amazonOrder = empty($row['amazonorderid']) ? $row['orderid'] : $row['amazonorderid'];
$number = $row[$numberKey];
$qty = empty($row['quantity']) ? $row['quantitypurchased'] : $row['quantity'];
$taxRate = empty($row['mwst']) ? 0 : $row['taxrate'];
$row['taxrate'] = (float)$row['taxrate'];
$row['date'] = $row[$dateKey];
$row['quantity'] = $qty;
$row['bruttototal'] = $row['brutto_total'];
$row['nettototal'] = $row['netto_total'];
$row['preis'] = empty($row['mwst'])
? $row['itemprice_netto'] / $qty
: $row['itemprice'] / (1 + $row['taxrate'] / 100.0) / $qty;
$row['itemdiscount_price'][$taxRate] = empty($row['mwst'])
? $row['itempromotiondiscount_netto']
: $row['itempromotiondiscount'] / (1 + $row['taxrate'] / 100.0);
$row['shipping_net_price'][$taxRate] = empty($row['mwst'])
? $row['shippingprice_netto']
: $row['shippingprice'] / (1 + $row['taxrate'] / 100.0);
$row['shippingdiscount_price'][$taxRate] = empty($row['mwst'])
? $row['shippromotiondiscount_netto']
: $row['shippromotiondiscount'] / (1 + $row['taxrate'] / 100.0);
$row['giftwrap_price'] = empty($row['mwst'])
? $row['giftwrapprice_netto'] / $qty
: $row['giftwrapprice'] / (1 + $row['taxrate'] / 100.0) / $qty;
$row['giftwrapdiscount_price'] = empty($row['mwst'])
? $row['giftwrappromotiondiscount_netto']
: $row['giftwrappromotiondiscount'] / (1 + $row['taxrate'] / 100.0);
$row['giftwrap_price_with_discount'] = round(
(float)$row['giftwrapprice'] + (float)$row['giftwrappromotiondiscount'],
2
) / $qty;
$row['giftwrap_price_net_with_discount'] = empty($row['mwst'])
? round(
(float)$row['giftwrapprice_netto'] + (float)$row['giftwrappromotiondiscount_netto'],
2
) / $qty : round(
(float)$row['giftwrapprice'] + (float)$row['giftwrappromotiondiscount'],
2
) / $qty / (1.0 + $row['taxrate'] / 100.0);
$row['shipping_price_with_discount'][$taxRate] = round(
(float)$row['shippingprice'] + (float)$row['shippromotiondiscount'],
2
);
if (!isset($return[$type][$amazonOrder]['document'])) {
$return[$type][$amazonOrder]['document'] = $row;
} else {
$return[$type][$amazonOrder]['document']['brutto_total']
= round(
(float)$return[$type][$amazonOrder]['document']['brutto_total'] + (float)$row['brutto_total']
,
2
);
$return[$type][$amazonOrder]['document']['nettototal']
= round(
(float)$return[$type][$amazonOrder]['document']['nettototal'] + (float)$row['nettototal']
,
2
);
if (!isset($return[$type][$amazonOrder]['document']['shipping_net_price'][$taxRate])) {
$return[$type][$amazonOrder]['document']['shipping_net_price'][$taxRate] = 0.0;
}
$return[$type][$amazonOrder]['document']['shipping_net_price'][$taxRate]
= (float)$return[$type][$amazonOrder]['document']['shipping_net_price'][$taxRate]
+ (float)$row['shipping_net_price'][$taxRate];
if (!isset($return[$type][$amazonOrder]['document']['shippingdiscount_price'][$taxRate])) {
$return[$type][$amazonOrder]['document']['shippingdiscount_price'][$taxRate] = 0.0;
}
$return[$type][$amazonOrder]['document']['shippingdiscount_price'][$taxRate]
= (float)$return[$type][$amazonOrder]['document']['shippingdiscount_price'][$taxRate]
+ (float)$row['shippingdiscount_price'][$taxRate];
if (!isset($return[$type][$amazonOrder]['document']['shipping_price_with_discount'][$taxRate])) {
$return[$type][$amazonOrder]['document']['shipping_price_with_discount'][$taxRate] = 0.0;
}
$return[$type][$amazonOrder]['document']['shipping_price_with_discount'][$taxRate]
= (float)$return[$type][$amazonOrder]['document']['shipping_price_with_discount'][$taxRate]
+ (float)$row['shipping_price_with_discount'][$taxRate];
if (!isset($return[$type][$amazonOrder]['document']['itemdiscount_price'][$taxRate])) {
$return[$type][$amazonOrder]['document']['itemdiscount_price'][$taxRate] = 0.0;
}
$return[$type][$amazonOrder]['document']['itemdiscount_price'][$taxRate]
= (float)$return[$type][$amazonOrder]['document']['itemdiscount_price'][$taxRate]
+ (float)$row['itemdiscount_price'][$taxRate];
}
$return[$type][$amazonOrder]['document']['brutto']
= $return[$type][$amazonOrder]['document']['brutto_total'];
$return[$type][$amazonOrder]['positions'][$number][] = $row;
}
return $return;
}
/**
* @param string $file
*
* @return array
*/
public function getPositionFromExportCsv($file): array
{
$handle = fopen($file, 'r');
if (empty($handle)) {
throw new InvalidArgumentException('could not open file ' . $file);
}
$header = fgetcsv($handle, 0, ';');
$headerToKey = array_flip($header);
$isReturnOrder = in_array('rem_gs_nr', $header);
$amazonOrderKey = isset($headerToKey['orderid']) ? $headerToKey['orderid'] : null;
if ($amazonOrderKey === null) {
$amazonOrderKey = isset($headerToKey['amazonorderid']) ? $headerToKey['amazonorderid'] : null;
}
$returnOrderKey = isset($headerToKey['rem_gs_nr']) ? $headerToKey['rem_gs_nr'] : null;
$returnOderDateKey = isset($headerToKey['rem_date']) ? $headerToKey['rem_date'] : null;
$invDateKey = isset($headerToKey['inv_date']) ? $headerToKey['inv_date'] : null;
$invoiceKey = isset($headerToKey['inv_rech_nr']) ? $headerToKey['inv_rech_nr'] : null;
$skuKey = isset($headerToKey['sku']) ? $headerToKey['sku'] : null;
$quantityKey = isset($headerToKey['quantity']) ? $headerToKey['quantity'] : null;
if ($quantityKey === null) {
$quantityKey = isset($headerToKey['quantitypurchased']) ? $headerToKey['quantitypurchased'] : null;
}
$currencyKey = isset($headerToKey['currency']) ? $headerToKey['currency'] : null;
$taxrateKey = isset($headerToKey['taxrate']) ? $headerToKey['taxrate'] : null;
$bruttoTotalKey = isset($headerToKey['brutto_total']) ? $headerToKey['brutto_total'] : null;
$nettoTotalKey = isset($headerToKey['netto_total']) ? $headerToKey['netto_total'] : null;
$mwstKey = isset($headerToKey['mwst']) ? $headerToKey['mwst'] : null;
$dateKey = $isReturnOrder ? $returnOderDateKey : $invDateKey;
$numberKey = $isReturnOrder ? $returnOrderKey : $invoiceKey;
$type = $isReturnOrder ? 'returnorder' : 'invoice';
$return = [
$type => [],
];
while ($row = fgetcsv($handle, 0, ';')) {
$amazonOrder = $row[$amazonOrderKey];
$date = $row[$dateKey];
$number = $row[$numberKey];
$sku = $row[$skuKey];
$quantity = $row[$quantityKey];
$mwst = $row[$mwstKey];
$bruttoTotal = $row[$bruttoTotalKey];
$nettoTotal = $row[$nettoTotalKey];
$taxRate = $row[$taxrateKey];
$currency = $row[$currencyKey];
if (empty($amazonOrder) || empty($number)) {
continue;
}
$return[$type][$amazonOrder][$number][] = [
'date' => $date,
'sku' => $sku,
'quantity' => $quantity,
'mwst' => $mwst,
'bruttototal' => $bruttoTotal,
'nettototal' => $nettoTotal,
'taxrate' => $taxRate,
'currency' => $currency,
];
}
fclose($handle);
return $return;
}
/**
* @return bool
*/
public function isCreateOrderActive()
{
return !empty($this->config['createorder']);
}
private function validateConfig(): void
{
if (!empty($this->config['firmkeyid']) || !empty($this->config['clientidentifier'])) {
foreach (['firmkeyid', 'clientidentifier',] as $name) {
if (!isset($this->config[$name])) {
throw new InvalidArgumentException(sprintf('Config field %s not found', $name));
}
}
return;
}
if (!empty($this->config['ftp'])) {
foreach (['host', 'user', 'pass', 'dir', 'port'] as $name) {
if (!isset($this->config[$name])) {
throw new InvalidArgumentException(sprintf('Config field %s not found', $name));
}
}
} else {
if (empty($this->config['dir'])) {
throw new InvalidArgumentException('Config dir not found');
}
}
}
private function loadConfig(): void
{
$this->config = $this->getConfig();
if (!$this->useFtp) {
$this->config['ftp'] = 0;
}
$this->validateConfig();
if (!empty($this->config['firmkeyid'])) {
return;
}
if (!empty($this->config['ftp'])) {
$host = $this->config['host'];
$user = $this->config['user'];
$pass = $this->config['pass'];
$dir = $this->config['dir'];
$port = $this->config['port'];
$ftpConfig = new FtpConfig($host, $user, $pass, $dir, $port);
$this->filesystem = $this->filesystemFactory->createFtp($ftpConfig);
} else {
$fileSystemConfig = [
'permissions' => [
'file' => [
'public' => 0664,
'private' => 0664,
],
'dir' => [
'public' => 0775,
'private' => 0775,
],
],
];
$this->filesystem = $this->filesystemFactory->createLocal($this->config['dir'], $fileSystemConfig);
}
}
/**
* @param string $doctype
* @param int $doctypeId
*
* @return int|null
*/
private function getAmazonShopIdFromDocument($doctype, $doctypeId): ?int
{
if ($doctype === 'rechnung') {
$invoiceId = $doctypeId;
} else {
$invoiceId = $this->db->fetchValue(
'SELECT `rechnungid` FROM `gutschrift` WHERE `id` = :id',
['id' => $doctypeId]
);
}
if (empty($invoiceId)) {
return null;
}
$orderId = $this->db->fetchValue(
'SELECT `auftragid` FROM `rechnung` WHERE `id` = :id',
['id' => $invoiceId]
);
if (empty($orderId)) {
return null;
}
$shopId = (int)$this->db->fetchValue(
'SELECT `shop` FROM `auftrag` WHERE `id` = :id',
['id' => $orderId]
);
if (empty($shopId)) {
return null;
}
$shopId = $this->db->fetchValue(
'SELECT `id` FROM `shopexport` WHERE `id` = :id AND `modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($shopId)) {
return null;
}
return (int)$shopId;
}
/**
* @param int $shopId
*
* @return int|null
*/
private function getDiscountArticleIdByShopId($shopId): ?int
{
$discountArticle = $this->db->fetchRow(
'SELECT `art`.`id`
FROM `shopexport` AS `s`
LEFT JOIN `artikel` AS `art` ON `s`.`artikelrabatt` = art.id
AND (`art`.`geloescht` = 0 OR `art`.`geloescht` IS NULL)
AND (`art`.`intern_gesperrt` = 0 OR `art`.`intern_gesperrt` IS NULL)
WHERE `s`.`id` = :id AND `s`.`modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($discountArticle)) {
return null;
}
if ($discountArticle['id'] > 0) {
return (int)$discountArticle['id'];
}
return $this->createDiscountArticleByShopId($shopId);
}
/**
* @param int $shopId
*
* @return int|null
*/
private function getShippingArticleIdByShopId($shopId): ?int
{
$shippingArticle = $this->db->fetchRow(
'SELECT `art`.`id`
FROM `shopexport` AS `s`
LEFT JOIN `artikel` AS `art` ON `s`.`artikelporto` = art.id
AND (`art`.`geloescht` = 0 OR `art`.`geloescht` IS NULL)
AND (`art`.`intern_gesperrt` = 0 OR `art`.`intern_gesperrt` IS NULL)
WHERE `s`.`id` = :id AND `s`.`modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($shippingArticle)) {
return null;
}
if ($shippingArticle['id'] > 0) {
return (int)$shippingArticle['id'];
}
return $this->createShippingArticleByShopId($shopId);
}
/**
* @param int $shopId
*
* @return int|null
*/
private function getGiftWrapArticleIdByShopId($shopId): ?int
{
$json = $this->db->fetchValue(
'SELECT `einstellungen_json` FROM `shopexport` WHERE `id` = :id AND `modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($json)) {
return null;
}
$json = @json_decode($json, true);
if (empty($json) || empty($json['felder']) || empty($json['felder']['giftwrap'])) {
return null;
}
return (int)$json['felder']['giftwrap'];
}
/**
* @param int $shopId
*
* @return int|null
*/
private function createDiscountArticleByShopId($shopId): ?int
{
$shop = $this->db->fetchRow(
'SELECT `s`.`projekt`, `art`.`id`
FROM `shopexport` AS `s`
LEFT JOIN `artikel` AS `art` ON `s`.`artikelrabatt` = art.id
AND (`art`.`geloescht` = 0 OR `art`.`geloescht` IS NULL)
AND (`art`.`intern_gesperrt` = 0 OR `art`.`intern_gesperrt` IS NULL)
WHERE `s`.`id` = :id AND `s`.`modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($shop) || !empty($shop['id'])) {
return null;
}
$discountArticle = [
'projekt' => $shop['projekt'],
'name_de' => 'Rabatt',
'name_en' => 'Discount',
'lagerartikel' => 0,
];
$discountArticle['nummer'] = $this->app->erp->GetNextArtikelnummer('', '1', $shop['projekt']);
$discountArticleId = (int)$this->app->erp->InsertUpdateArtikel($discountArticle);
if ($discountArticleId <= 0) {
return null;
}
$this->db->perform(
'UPDATE `shopexport` SET `artikelrabatt` = :articleId WHERE `id` = :shopId ',
[
'articleId' => $discountArticleId,
'shopId' => $shopId,
]
);
return $discountArticleId;
}
/**
* @param int $shopId
*
* @return int|null
*/
private function createShippingArticleByShopId($shopId): ?int
{
$shop = $this->db->fetchRow(
'SELECT `s`.`projekt`, `art`.`id`
FROM `shopexport` AS `s`
LEFT JOIN `artikel` AS `art` ON `s`.`artikelporto` = art.id
AND (`art`.`geloescht` = 0 OR `art`.`geloescht` IS NULL)
AND (`art`.`intern_gesperrt` = 0 OR `art`.`intern_gesperrt` IS NULL)
WHERE `s`.`id` = :id AND `s`.`modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($shop) || !empty($shop['id'])) {
return null;
}
$firstShippingArticle = $this->db->fetchRow(
'SELECT `art`.`id`
FROM `artikel` AS `art`
LEFT JOIN `projekt` AS `p` ON `art`.projekt = p.id
WHERE `art`.`porto` = 1
AND (`art`.`geloescht` IS NOT NULL OR `art`.geloescht = 0)
AND (`art`.`intern_gesperrt` = 0 OR `art`.`intern_gesperrt` IS NULL)
AND (`p`.`id` IS NULL OR p.`oeffentlich` = 1)
'
);
if (!empty($firstShippingArticle)) {
$this->db->perform(
'UPDATE `shopexport` SET `artikelporto` = :articleId WHERE `id` = :shopId ',
[
'articleId' => (int)$firstShippingArticle['id'],
'shopId' => $shopId,
]
);
return (int)$firstShippingArticle['id'];
}
$shippingArticle = ['projekt' => $shop['projekt'], 'name_de' => 'Porto', 'proto' => 1];
$shippingArticle['nummer'] = $this->app->erp->GetNextArtikelnummer('', '1', $shop['projekt']);
$shippingArticleId = (int)$this->app->erp->InsertUpdateArtikel($shippingArticle);
if ($shippingArticleId <= 0) {
return null;
}
$this->db->perform(
'UPDATE `shopexport` SET `artikelporto` = :articleId WHERE `id` = :shopId ',
[
'articleId' => $shippingArticleId,
'shopId' => $shopId,
]
);
return $shippingArticleId;
}
/**
* @param int $shopId
*
* @return int|null
*/
private function createGiftWrapArticle($shopId): ?int
{
$shop = $this->db->fetchRow(
'SELECT `projekt`, `einstellungen_json` FROM `shopexport` WHERE `id` = :id AND `modulename` = :module_name',
[
'id' => $shopId,
'module_name' => 'shopimporter_amazon',
]
);
if (empty($shop)) {
return null;
}
$giftwrapArticle = ['projekt' => $shop['projekt'], 'name_de' => 'Geschenkverpackung', 'lagerartikel' => 1];
$giftwrapArticle['nummer'] = $this->app->erp->GetNextArtikelnummer('', '1', $shop['projekt']);
$giftwrapArticleId = (int)$this->app->erp->InsertUpdateArtikel($giftwrapArticle);
if ($giftwrapArticleId <= 0) {
return null;
}
$json = @json_decode($shop['einstellungen_json'], true);
if (!is_array($json)) {
$json = ['felder' => []];
}
if (!isset($json['felder'])) {
$json['felder'] = [];
}
$json['felder']['giftwrap'] = $giftwrapArticleId;
$this->db->perform(
'UPDATE `shopexport` SET `einstellungen_json` = :json WHERE `id` = :id',
[
'json' => json_encode($json),
'id' => $shopId,
]
);
return $giftwrapArticleId;
}
/**
* @param string $document
* @param int $positionId
* @param float $tax
*/
private function changePositionTax($document, $positionId, $tax): void
{
if (!is_numeric($tax) || empty($positionId) || !in_array($document, ['rechnung', 'gutschrift'])) {
return;
}
if ($document === 'rechnung') {
$this->db->perform(
'UPDATE `rechnung_position` SET `steuersatz` = :tax WHERE `id` = :positionId',
[
'tax' => (float)$tax,
'positionId' => (int)$positionId,
]
);
return;
}
if ($document === 'gutschrift') {
$this->db->perform(
'UPDATE `gutschrift_position` SET `steuersatz` = :tax WHERE `id` = :positionId',
[
'tax' => (float)$tax,
'positionId' => (int)$positionId,
]
);
return;
}
}
/**
* @param string $doctype
* @param int $doctypeId
* @param float|string $tax
* @param float $price
*
* @return int|null
*/
private function addDiscountPosition($doctype, $doctypeId, $tax, $price): ?int
{
$shopId = $this->getAmazonShopIdFromDocument($doctype, $doctypeId);
if ($shopId === null) {
return null;
}
$discountArticleId = $this->getDiscountArticleIdByShopId($shopId);
if ($discountArticleId === null) {
$discountArticleId = $this->createDiscountArticleByShopId($shopId);
if ($discountArticleId === null) {
return null;
}
}
$document = $this->getDocumentInfoForAddPosition($doctype, $doctypeId);
if ($document === null) {
return null;
}
$discountArticle = $this->getArticleInfoForAddPosition($document, $discountArticleId);
if ($discountArticle === null) {
return null;
}
$positionId = $this->app->erp->AddPositionManuellPreisNummer(
$doctype,
$doctypeId,
0,
$discountArticle['nummer'],
1,
$discountArticle['name'],
$price,
!empty($tax) && in_array($tax, ['normal', 'ermaessigt', 'befreit']) ? $tax : '',
0,
0,
$document['waehrung']
);
if (is_numeric($tax)) {
$this->changePositionTax($doctype, $positionId, $tax);
}
if (empty($positionId)) {
return null;
}
return (int)$positionId;
}
/**
* @param string $doctype
* @param int $doctypeId
* @param float|string $tax
* @param float $price
*
* @return int|null
*/
private function addShippingPosition($doctype, $doctypeId, $tax, $price): ?int
{
$shopId = $this->getAmazonShopIdFromDocument($doctype, $doctypeId);
if ($shopId === null) {
return null;
}
$shippingArticleId = $this->getShippingArticleIdByShopId($shopId);
if ($shippingArticleId === null) {
$shippingArticleId = $this->createShippingArticleByShopId($shopId);
if ($shippingArticleId === null) {
return null;
}
}
$document = $this->getDocumentInfoForAddPosition($doctype, $doctypeId);
if ($document === null) {
return null;
}
$shippingArticle = $this->getArticleInfoForAddPosition($document, $shippingArticleId);
if ($shippingArticle === null) {
return null;
}
$positionId = $this->app->erp->AddPositionManuellPreisNummer(
$doctype,
$doctypeId,
0,
$shippingArticle['nummer'],
1,
$shippingArticle['name'],
$price,
!empty($tax) && in_array($tax, ['normal', 'ermaessigt', 'befreit']) ? $tax : '',
0,
0,
$document['waehrung']
);
if (is_numeric($tax)) {
$this->changePositionTax($doctype, $positionId, $tax);
}
if (empty($positionId)) {
return null;
}
return (int)$positionId;
}
/**
* @param string $doctype
* @param int $doctypeId
*
* @return array|null
*/
private function getDocumentInfoForAddPosition($doctype, $doctypeId): ?array
{
if ($doctype === 'rechnung') {
$document = $this->db->fetchRow(
'SELECT `waehrung`, `sprache` FROM `rechnung` WHERE `id` = :id',
['id' => $doctypeId]
);
} elseif ($doctype === 'gutschrift') {
$document = $this->db->fetchRow(
'SELECT `waehrung`, `sprache` FROM `gutschrift` WHERE `id` = :id',
['id' => $doctypeId]
);
} else {
return null;
}
if (empty($document)) {
return null;
}
if (empty($document['waehrung'])) {
$document['waehrung'] = 'EUR';
}
return $document;
}
/**
* @param array $document
* @param int $articleId
*
* @return array|null
*/
private function getArticleInfoForAddPosition($document, $articleId): ?array
{
$article = $this->db->fetchRow(
'SELECT `nummer`, `name_de`, `name_en` FROM `artikel` WHERE `id` = :id ',
['id' => $articleId]
);
if (empty($article)) {
return null;
}
$name = $article['name_de'];
if (
!empty($article['name_en'])
&& !empty($document['sprache'])
&& !in_array($document['sprache'], ['deutsch', 'german', 'de', 'DE'])
) {
$name = $article['name_en'];
}
$article['name'] = $name;
return $article;
}
/**
* @param string $doctype
* @param int $doctypeId
* @param int $quantity
* @param float $price
* @param null|int $orderId
*
* @return int|null
*/
private function addGiftWrapPositon($doctype, $doctypeId, $quantity, $price, $orderId = null): ?int
{
if ($doctype !== 'rechnung') {
$createOrderPosition = false;
}
$shopId = $this->getAmazonShopIdFromDocument($doctype, $doctypeId);
if ($shopId === null) {
return null;
}
$giftWrapArticleId = $this->getGiftWrapArticleIdByShopId($shopId);
if ($giftWrapArticleId === null) {
$giftWrapArticleId = $this->createGiftWrapArticle($shopId);
if ($giftWrapArticleId === null) {
return null;
}
}
$document = $this->getDocumentInfoForAddPosition($doctype, $doctypeId);
if ($document === null) {
return null;
}
$giftWrapArticle = $this->getArticleInfoForAddPosition($document, $giftWrapArticleId);
if ($giftWrapArticle === null) {
return null;
}
$positionId = (int)$this->app->erp->AddPositionManuellPreisNummer(
$doctype,
$doctypeId,
0,
$giftWrapArticle['nummer'],
$quantity,
$giftWrapArticle['name'],
$price,
'',
0,
0,
$document['waehrung']
);
if (empty($positionId)) {
return null;
}
if ($createOrderPosition) {
$orderPositionId = (int)$this->app->erp->AddPositionManuellPreisNummer(
'auftrag',
$orderId,
0,
$giftWrapArticle['nummer'],
$quantity,
$giftWrapArticle['name'],
$price,
'',
0,
0,
$document['waehrung']
);
$this->db->perform(
'UPDATE `rechnung_position` SET `auftrag_position_id` = :orderPositionId WHERE `id` = :id',
[
'orderPositionId' => $orderPositionId,
'id' => $positionId,
]
);
}
return $positionId;
}
/**
* @param string $type
* @param int $documentId
* @param array $documentRows
* @param array $positions
* @param null|int $orderId
*/
private function addDiscountArticles($type, $documentId, $documentRows, $positions, $orderId = null): void
{
if (empty($documentId)
|| empty($documentRows)
|| empty($positions)
|| $documentId <= 0
|| !in_array($type, ['invoice', 'returnorder'])) {
return;
}
$doctype = $type === 'invoice' ? 'rechnung' : 'gutschrift';
foreach ($documentRows as $documentRow) {
if (empty($documentRow['itemdiscount_price'])) {
continue;
}
foreach ($documentRow['itemdiscount_price'] as $taxRate => $price) {
if ($price == 0) {
continue;
}
$positionId = (int)$this->addDiscountPosition($doctype, $documentId, $taxRate, $price);
if ($orderId !== null) {
$orderPositionId = (int)$this->addDiscountPosition('auftrag', $orderId, $taxRate, $price);
$this->db->perform(
'UPDATE `rechnung_position` SET `auftrag_position_id` = :orderPositionId WHERE `id` = :id',
[
'orderPositionId' => $orderPositionId,
'id' => $positionId,
]
);
}
}
}
}
/**
* @param string $type
* @param int $documentId
* @param array $documentRows
* @param array $positions
* @param null|int $orderId
*/
private function addShippingArticles($type, $documentId, $documentRows, $positions, $orderId = null): void
{
if (empty($documentId)
|| empty($documentRows)
|| empty($positions)
|| $documentId <= 0
|| !in_array($type, ['invoice', 'returnorder'])) {
return;
}
$doctype = $type === 'invoice' ? 'rechnung' : 'gutschrift';
foreach ($documentRows as $documentRow) {
if (empty($documentRow['shipping_price_with_discount'])) {
continue;
}
foreach ($documentRow['shipping_price_with_discount'] as $taxRate => $price) {
if ($price == 0) {
continue;
}
$positionId = (int)$this->addShippingPosition(
$doctype,
$documentId,
$taxRate,
$price / (1 + $taxRate / 100)
);
if ($orderId !== null) {
$orderPositionId = (int)$this->addShippingPosition(
'auftrag',
$orderId,
$taxRate,
$price / (1 + $taxRate / 100)
);
$this->db->perform(
'UPDATE `rechnung_position` SET `auftrag_position_id` = :orderPositionId WHERE `id` = :id',
[
'orderPositionId' => $orderPositionId,
'id' => $positionId,
]
);
}
}
}
}
/**
* @param string $sku
*
* @return int
*/
private function getShopIdFromExternalNumber(string $sku): int
{
return (int)$this->db->fetchValue(
"SELECT af.shopid
FROM `artikelnummer_fremdnummern` AS `af`
INNER JOIN `shopexport` AS `s` ON af.shopid = s.id AND s.aktiv = 1
AND s.modulename LIKE 'shopimporter_amazon%'
WHERE af.aktiv = 1 AND af.nummer = :nummer AND af.nummer <> ''
LIMIT 1",
['nummer' => trim($sku)]
);
}
/**
* @param string $type
* @param int $documentId
* @param array $positions
* @param null|int $orderId
*/
private function addPositions($type, $documentId, $positions, $orderId = null): void
{
if ($type === 'invoice') {
$this->db->perform(
'DELETE FROM `rechnung_position` WHERE `rechnung` = :invoice',
['invoice' => $documentId]
);
foreach ($positions as $key => $position) {
if ($position['quantity'] == 0) {
$position['quantity'] = 1;
}
$dataWithExternalNumber = null;
$shopId = $this->getShopIdFromExternalNumber((string)$position['sku']);
if ($shopId > 0) {
$dataWithExternalNumber = ['fremdnummer' => trim($position['sku'])];
}
$positionId = (int)$this->app->erp->AddPositionManuellPreisNummer(
'rechnung',
$documentId,
0,
$position['sku'],
$position['quantity'],
!isset($position['name']) ? $position['productname'] : $position['name'],
$position['taxrate'] > 0
? $position['itemprice'] / $position['quantity'] / (1 + $position['taxrate'] / 100) :
$position['itemprice_netto'] / $position['quantity'],
'',
0,
$shopId,
$position['currency'],
$dataWithExternalNumber
);
$this->db->perform(
'UPDATE `rechnung_position`
SET `steuersatz` = :taxRate, preis = :price
WHERE `id` = :id',
[
'taxRate' => $position['taxrate'],
'price' => $position['taxrate'] > 0
? $position['itemprice'] / $position['quantity'] / (1 + $position['taxrate'] / 100) :
$position['itemprice_netto'] / $position['quantity'],
'id' => $positionId,
]
);
if ($orderId !== null) {
$orderPositionId = (int)$this->app->erp->AddPositionManuellPreisNummer(
'auftrag',
$orderId,
0,
$position['sku'],
$position['quantity'],
!isset($position['name']) ? $position['productname'] : $position['name'],
$position['taxrate'] > 0
? $position['itemprice'] / $position['quantity'] / (1 + $position['taxrate'] / 100) :
$position['itemprice_netto'] / $position['quantity'],
'',
0,
$shopId,
$position['currency'],
$dataWithExternalNumber
);
$this->db->perform(
'UPDATE `auftrag_position`
SET `steuersatz` = :taxRate, preis = :price
WHERE `id` = :id',
[
'taxRate' => $position['taxrate'],
'price' => $position['taxrate'] > 0
? $position['itemprice'] / $position['quantity'] / (1 + $position['taxrate'] / 100) :
$position['itemprice_netto'] / $position['quantity'],
'id' => $orderPositionId,
]
);
$this->db->perform(
'UPDATE `rechnung_position`
SET `auftrag_position_id` = :orderPositionId
WHERE `id` = :id',
[
'orderPositionId' => $orderPositionId,
'id' => $positionId,
]
);
}
if (!empty($position['id'])) {
$this->db->perform(
'UPDATE `amazoninvoice_position`
SET `doctype_id` = :doctype_id, `doctype` = :doctype, `position_id` = :position_id
WHERE `id` = :id',
[
'doctype_id' => (int)$documentId,
'doctype' => 'rechnung',
'position_id' => (int)$positionId,
'id' => (int)$position['id'],
]
);
}
if (
!empty($position['giftwrap_price_net_with_discount'])
&& $position['giftwrap_price_net_with_discount'] != 0.0
) {
$this->addGiftWrapPositon(
'rechnung',
(int)$documentId,
$position['quantity'],
$position['giftwrap_price_net_with_discount'],
$orderId
);
}
}
} else {
$this->db->perform(
'DELETE FROM `gutschrift_position` WHERE `gutschrift` = :returnorder',
['returnorder' => $documentId]
);
foreach ($positions as $key => $position) {
if ($position['quantity'] == 0) {
$position['quantity'] = 1;
}
$dataWithExternalNumber = null;
$shopId = $this->getShopIdFromExternalNumber((string)$position['sku']);
if ($shopId > 0) {
$dataWithExternalNumber = ['fremdnummer' => trim($position['sku'])];
}
$positionId = $this->app->erp->AddPositionManuellPreisNummer(
'gutschrift',
$documentId,
0,
$position['sku'],
$position['quantity'],
$position['name'],
$position['price'],
'',
0,
$shopId,
$position['currency'],
$dataWithExternalNumber
);
$this->db->perform(
'UPDATE `gutschrift_position`
SET `steuersatz` = :taxRate, preis = :price
WHERE `id` = :id',
[
'taxRate' => $position['taxrate'],
'price' => $position['taxrate'] > 0
? $position['bruttototal'] / $position['quantity'] / (1 + $position['taxrate'] / 100) :
$position['nettototal'] / $position['quantity'],
'id' => $positionId,
]
);
if (!empty($position['id'])) {
$this->db->perform(
'UPDATE `amazoninvoice_position`
SET `doctype_id` = :doctype_id, `doctype` = :doctype, `position_id` = :position_id
WHERE `id` = :id',
[
'doctype_id' => (int)$documentId,
'doctype' => 'gutschrift',
'position_id' => (int)$positionId,
'id' => (int)$position['id'],
]
);
}
if (
!empty($position['giftwrap_price_net_with_discount'])
&& $position['giftwrap_price_net_with_discount'] != 0.0
) {
$this->addGiftWrapPositon(
'gutschrift',
(int)$documentId,
$position['quantity'],
$position['giftwrap_price_net_with_discount']
);
}
}
}
}
/**
* @param string $type
* @param int $documentId
* @param string $file
*/
private function archiveDocument($type, $documentId, $file): void
{
if ($type === 'invoice') {
$Brief = new RechnungPDF($this->app);
$table = 'rechnung';
} else {
$Brief = new GutschriftPDF($this->app);
$table = 'gutschrift';
}
$file = $this->app->erp->GetTMP() . $file;
if (!is_file($file)) {
throw new InvalidArgumentException(sprintf('file %s not found', $file));
}
$list = $Brief->getArchivedFiles($documentId, $table);
if (!empty($list)) {
foreach ($list as $pdfArchive) {
if (empty($pdfArchive['schreibschutz'])) {
continue;
}
$dir = $this->app->Conf->WFuserdata . '/pdfarchiv/' . $this->app->Conf->WFdbname . '/' . $table;
$pdfFile = Briefpapier::getPDFfolder($dir, $documentId, $pdfArchive['dateiname']);
if (@rename($file, $pdfFile)) {
$this->db->perform(
'UPDATE `pdfarchiv` SET `checksum` = :checksum WHERE `id` = :id',
['checksum' => md5_file($pdfFile), 'id' => $pdfArchive['id']]
);
return;
}
throw new InvalidArgumentException(sprintf('could not write file %s', $pdfFile));
}
}
}
}