bug fixes and item management improvements

This commit is contained in:
Dennis Eichhorn 2023-05-24 18:11:37 +00:00
parent 397f8fcb33
commit 9a9aecd785
13 changed files with 163 additions and 203 deletions

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
use Modules\Billing\Models\NullBill; use Modules\Billing\Models\NullBill;
use phpOMS\Localization\ISO3166NameEnum; use phpOMS\Localization\ISO3166NameEnum;
use phpOMS\Localization\ISO3166TwoEnum;
use phpOMS\Localization\Money; use phpOMS\Localization\Money;
/** @var \phpOMS\Views\View $this */ /** @var \phpOMS\Views\View $this */
@ -70,11 +71,14 @@ $billTypeName = \strtoupper($bill->type->getL11n());
// @todo: depending on amount of lines, there is a solution (html, or use backtracking of tcpdf) // @todo: depending on amount of lines, there is a solution (html, or use backtracking of tcpdf)
// Address // Address
$pdf->setY(55); $pdf->setY(50);
$pdf->setFont('helvetica', '', 8); $pdf->setFont('helvetica', '', 10);
$countries = ISO3166NameEnum::getConstants(); $countries = ISO3166NameEnum::getConstants();
$toCountry = isset($countries[$bill->billCountry]) ? $countries[$bill->billCountry] : ''; $countryEnumName = ISO3166TwoEnum::getName($bill->billCountry);
$toCountry = \is_string($countryEnumName) && ($country = ISO3166NameEnum::getByName($countryEnumName)) !== null
? $country
: '';
$addressString = \trim( $addressString = \trim(
$bill->billTo . "\n" $bill->billTo . "\n"
@ -96,11 +100,11 @@ $pdf->Write(
$lineHeight = ($lineHeight - $pdf->getY()) / $addressLineCount; $lineHeight = ($lineHeight - $pdf->getY()) / $addressLineCount;
// Bill head // Bill head
$pdf->setFont('helvetica', 'B', 20); $pdf->setFont('helvetica', 'B', 16);
$titleWidth = $pdf->getStringWidth($billTypeName, 'helvetica', 'B', 20); $titleWidth = $pdf->getStringWidth($billTypeName, 'helvetica', 'B', 16);
$pdf->setXY( $pdf->setXY(
$rightPos = ($pdf->getPageWidth() - $titleWidth - ($titleWidth < 55 ? 55 : 35) + 15), $rightPos = ($pdf->getPageWidth() - $titleWidth - \max(60 - $titleWidth, 0) - 15 - 2),
$topPos + 50 + $lineHeight * $addressLineCount - 38, $topPos + 50 + $lineHeight * $addressLineCount - 38,
true true
); );
@ -109,12 +113,12 @@ $pdf->setTextColor(255, 255, 255);
$pdf->setFillColor(255, 162, 7); $pdf->setFillColor(255, 162, 7);
$pdf->Cell($pdf->getPageWidth() - $rightPos - 15, 0, $billTypeName, 0, 0, 'L', true); $pdf->Cell($pdf->getPageWidth() - $rightPos - 15, 0, $billTypeName, 0, 0, 'L', true);
$pdf->setFont('helvetica', '', 8); $pdf->setFont('helvetica', '', 10);
$pdf->setTextColor(255, 162, 7); $pdf->setTextColor(255, 162, 7);
$pdf->setXY($rightPos, $tempY = $pdf->getY() + 10, true); $pdf->setXY($rightPos, $tempY = $pdf->getY() + 10, true);
$pdf->MultiCell( $pdf->MultiCell(
23, 30, 26, 30,
$lang[$pdf->language]['InvoiceNo'] . "\n" $lang[$pdf->language]['InvoiceNo'] . "\n"
. $lang[$pdf->language]['InvoiceDate'] . "\n" . $lang[$pdf->language]['InvoiceDate'] . "\n"
. $lang[$pdf->language]['ServiceDate'] . "\n" . $lang[$pdf->language]['ServiceDate'] . "\n"
@ -124,10 +128,10 @@ $pdf->MultiCell(
0, 'L' 0, 'L'
); );
$pdf->setFont('helvetica', '', 8); $pdf->setFont('helvetica', '', 10);
$pdf->setTextColor(0, 0, 0); $pdf->setTextColor(0, 0, 0);
$pdf->setXY($rightPos + 23 + 2, $tempY, true); $pdf->setXY($rightPos + 26 + 2, $tempY, true);
$pdf->MultiCell( $pdf->MultiCell(
25, 30, 25, 30,
$bill->number . "\n" $bill->number . "\n"
@ -151,7 +155,7 @@ $pdf->writeHTMLCell(
$pdf->Ln(); $pdf->Ln();
*/ */
$pdf->setY($pdf->getY() + 5); $pdf->setY($pdf->getY() + 10);
$header = [ $header = [
$lang[$pdf->language]['Item'], $lang[$pdf->language]['Item'],
@ -180,7 +184,7 @@ foreach($lines as $line) {
$pdf->setTextColor(255); $pdf->setTextColor(255);
$pdf->setDrawColor(255, 162, 7); $pdf->setDrawColor(255, 162, 7);
//$pdf->SetLineWidth(0.3); //$pdf->SetLineWidth(0.3);
$pdf->setFont('helvetica', 'B', 8); $pdf->setFont('helvetica', 'B', 10);
if (!$first/* || $row === null*/) { if (!$first/* || $row === null*/) {
$pdf->AddPage(); $pdf->AddPage();
@ -194,7 +198,7 @@ foreach($lines as $line) {
$pdf->Ln(); $pdf->Ln();
$pdf->setFillColor(245, 245, 245); $pdf->setFillColor(245, 245, 245);
$pdf->setTextColor(0); $pdf->setTextColor(0);
$pdf->setFont('helvetica', '', 8); $pdf->setFont('helvetica', '', 10);
$first = false; $first = false;
} }
@ -230,7 +234,7 @@ if ($pdf->getY() > $pdf->getPageHeight() - 40) {
$pdf->setFillColor(240, 240, 240); $pdf->setFillColor(240, 240, 240);
$pdf->setTextColor(0); $pdf->setTextColor(0);
$pdf->setDrawColor(240, 240, 240); $pdf->setDrawColor(240, 240, 240);
$pdf->setFont('helvetica', 'B', 8); $pdf->setFont('helvetica', 'B', 10);
$tempY = $pdf->getY(); $tempY = $pdf->getY();
@ -255,7 +259,7 @@ foreach ($taxes as $rate => $tax) {
$pdf->setFillColor(255, 162, 7); $pdf->setFillColor(255, 162, 7);
$pdf->setTextColor(255); $pdf->setTextColor(255);
$pdf->setDrawColor(255, 162, 7); $pdf->setDrawColor(255, 162, 7);
$pdf->setFont('helvetica', 'B', 8); $pdf->setFont('helvetica', 'B', 10);
$grossSales = Money::fromFloatInt($bill->grossSales); $grossSales = Money::fromFloatInt($bill->grossSales);
@ -279,6 +283,11 @@ $pdf->Ln();
// @todo: fix terms // @todo: fix terms
$pdf->setFont('helvetica', 'B', 8); $pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['Terms'] . ': https://jingga.app/terms', '', 0, 'L', false, 0, false, false, 0); $pdf->Write(0, $lang[$pdf->language]['Terms'] . ': https://jingga.app/terms', '', 0, 'L', false, 0, false, false, 0);
$pdf->Ln();
$pdf->setFont('helvetica', 'B', 8);
$pdf->Write(0, $lang[$pdf->language]['Currency'] . ': ' . $bill->currency, '', 0, 'L', false, 0, false, false, 0);
$pdf->Ln();
$pdf->setFont('helvetica', '', 8); $pdf->setFont('helvetica', '', 8);
$pdf->Write(0, $bill->termsText, '', 0, 'L', false, 0, false, false, 0); $pdf->Write(0, $bill->termsText, '', 0, 'L', false, 0, false, false, 0);

View File

@ -23,6 +23,7 @@ return [
'PO' => 'PO', 'PO' => 'PO',
'DueDate' => 'Due Date', 'DueDate' => 'Due Date',
'Item' => 'Item', 'Item' => 'Item',
'Currency' => 'Currency',
'Quantity' => 'Quantity', 'Quantity' => 'Quantity',
'UnitPrice' => 'Unit Price', 'UnitPrice' => 'Unit Price',
'Total' => 'Total', 'Total' => 'Total',
@ -41,6 +42,7 @@ return [
'PO' => 'Kundenreferenz', 'PO' => 'Kundenreferenz',
'DueDate' => 'Fälligkeitsdatum', 'DueDate' => 'Fälligkeitsdatum',
'Item' => 'Artikel', 'Item' => 'Artikel',
'Currency' => 'Währung',
'Quantity' => 'Menge', 'Quantity' => 'Menge',
'UnitPrice' => 'Einzelpreis', 'UnitPrice' => 'Einzelpreis',
'Total' => 'Gesamt', 'Total' => 'Gesamt',

View File

@ -18,7 +18,7 @@
"isTemplate": false, "isTemplate": false,
"l11n": { "l11n": {
"en": "Order Confirmation", "en": "Order Confirmation",
"de": "Auftragsbestaetigung" "de": "Auftragsbestätigung"
} }
}, },
{ {
@ -95,7 +95,7 @@
"isTemplate": false, "isTemplate": false,
"l11n": { "l11n": {
"en": "Order Confirmation", "en": "Order Confirmation",
"de": "Auftragsbestaetigung" "de": "Auftragsbestätigung"
} }
}, },
{ {

View File

@ -20,7 +20,7 @@ use phpOMS\Router\RouteVerb;
return [ return [
'^.*/bill/render.*$' => [ '^.*/bill/render.*$' => [
[ [
'dest' => '\Modules\Billing\Controller\ApiController:apiPreviewRender', 'dest' => '\Modules\Billing\Controller\ApiBillController:apiMediaRender',
'verb' => RouteVerb::GET, 'verb' => RouteVerb::GET,
'permission' => [ 'permission' => [
'module' => BackendController::NAME, 'module' => BackendController::NAME,

View File

@ -36,6 +36,7 @@ use Modules\Media\Models\PathSettings;
use Modules\Media\Models\UploadStatus; use Modules\Media\Models\UploadStatus;
use Modules\Messages\Models\EmailMapper; use Modules\Messages\Models\EmailMapper;
use Modules\SupplierManagement\Models\NullSupplier; use Modules\SupplierManagement\Models\NullSupplier;
use Modules\SupplierManagement\Models\Supplier;
use Modules\SupplierManagement\Models\SupplierMapper; use Modules\SupplierManagement\Models\SupplierMapper;
use phpOMS\Autoloader; use phpOMS\Autoloader;
use phpOMS\Localization\ISO3166TwoEnum; use phpOMS\Localization\ISO3166TwoEnum;
@ -85,9 +86,9 @@ final class ApiBillController extends Controller
/** @var \Modules\Billing\Models\Bill $old */ /** @var \Modules\Billing\Models\Bill $old */
$old = BillMapper::get()->where('id', (int) $request->getData('bill')); $old = BillMapper::get()->where('id', (int) $request->getData('bill'));
$new = $this->updateBillFromRequest($request, $response, $data); $new = $this->updateBillFromRequest($request, $response, $data);
$this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill', $request->getOrigin());
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill', 'Bill successfully created.', $new); $this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill', $request->getOrigin());
$this->createStandardUpdateResponse($request, $response, $new);
} }
/** /**
@ -153,7 +154,7 @@ final class ApiBillController extends Controller
$bill = $this->createBillFromRequest($request, $response, $data); $bill = $this->createBillFromRequest($request, $response, $data);
$this->createBillDatabaseEntry($bill, $request); $this->createBillDatabaseEntry($bill, $request);
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill', 'Bill successfully created.', $bill); $this->createStandardCreateResponse($request, $response, $bill);
} }
/** /**
@ -200,16 +201,16 @@ final class ApiBillController extends Controller
* *
* @since 1.0.0 * @since 1.0.0
*/ */
public function createBaseBill(Client $client, RequestAbstract $request) : Bill public function createBaseBill(Client | Supplier $account, RequestAbstract $request) : Bill
{ {
// @todo: validate vat before creation // @todo: validate vat before creation for clients
$bill = new Bill(); $bill = new Bill();
$bill->createdBy = new NullAccount($request->header->account); $bill->createdBy = new NullAccount($request->header->account);
$bill->unit = $client->unit ?? $this->app->unitId; $bill->unit = $account->unit ?? $this->app->unitId;
$bill->billDate = new \DateTime('now'); // @todo: Date of payment $bill->billDate = new \DateTime('now'); // @todo: Date of payment
$bill->performanceDate = new \DateTime('now'); // @todo: Date of payment $bill->performanceDate = $request->getDataDateTime('performancedate') ?? new \DateTime('now'); // @todo: Date of payment
$bill->accountNumber = $client->number; $bill->accountNumber = $account->number;
$bill->setStatus(BillStatus::DRAFT); $bill->setStatus($request->getDataInt('status') ?? BillStatus::DRAFT);
$bill->shipping = 0; $bill->shipping = 0;
$bill->shippingText = ''; $bill->shippingText = '';
@ -217,17 +218,18 @@ final class ApiBillController extends Controller
$bill->payment = 0; $bill->payment = 0;
$bill->paymentText = ''; $bill->paymentText = '';
$bill->type = BillTypeMapper::get() if ($account instanceof Client) {
->where('name', 'sales_invoice') $bill->client = $account;
->execute(); } else {
$bill->supplier = $account;
}
// @todo: use bill and shipping address instead of main address if available // @todo: use bill and shipping address instead of main address if available
$bill->client = $client; $bill->billTo = $request->getDataString('billto') ?? $account->account->name1;
$bill->billTo = $client->account->name1; $bill->billAddress = $request->getDataString('billaddress') ?? $account->mainAddress->address;
$bill->billAddress = $client->mainAddress->address; $bill->billCity = $request->getDataString('billtocity') ?? $account->mainAddress->city;
$bill->billCity = $client->mainAddress->city; $bill->billZip = $request->getDataString('billtopostal') ?? $account->mainAddress->postal;
$bill->billZip = $client->mainAddress->postal; $bill->billCountry = $request->getDataString('billtocountry') ?? $account->mainAddress->getCountry();
$bill->billCountry = $client->mainAddress->getCountry();
$bill->setCurrency(ISO4217CharEnum::_EUR); $bill->setCurrency(ISO4217CharEnum::_EUR);
@ -248,7 +250,7 @@ final class ApiBillController extends Controller
} }
$validLanguages = []; $validLanguages = [];
if (!empty($settings)) { if (!empty($settings) && !empty($settings->content)) {
$validLanguages = \json_decode($settings->content, true); $validLanguages = \json_decode($settings->content, true);
} else { } else {
$validLanguages = [ $validLanguages = [
@ -258,20 +260,33 @@ final class ApiBillController extends Controller
$billLanguage = $validLanguages[0] ?? ISO639x1Enum::_EN; $billLanguage = $validLanguages[0] ?? ISO639x1Enum::_EN;
$clientBillLanguage = $client->getAttribute('bill_language')->value->valueStr; $accountBillLanguage = $account->getAttribute('bill_language')->value->valueStr;
if (!empty($clientBillLanguage) && \in_array($clientBillLanguage, $validLanguages)) { if (!empty($accountBillLanguage) && \in_array($accountBillLanguage, $validLanguages)) {
$billLanguage = $clientBillLanguage; $billLanguage = $accountBillLanguage;
} else { } else {
$clientLanguages = ISO639x1Enum::languageFromCountry($client->mainAddress->getCountry()); $accountLanguages = ISO639x1Enum::languageFromCountry($account->mainAddress->getCountry());
$clientLanguage = !empty($clientLanguages) ? $clientLanguages[0] : ''; $accountLanguage = !empty($accountLanguages) ? $accountLanguages[0] : '';
if (\in_array($clientLanguage, $validLanguages)) { if (\in_array($accountLanguage, $validLanguages)) {
$billLanguage = $clientLanguage; $billLanguage = $accountLanguage;
} }
} }
$bill->setLanguage($billLanguage); $bill->setLanguage($billLanguage);
$typeMapper = BillTypeMapper::get()
->with('l11n')
->where('l11n/langauge', $billLanguage)
->limit(1);
if ($request->hasData('type')) {
$typeMapper->where('id', $request->getDataInt('type'));
} else {
$typeMapper->where('name', 'sales_invoice');
}
$bill->type = $typeMapper->execute();
return $bill; return $bill;
} }
@ -335,31 +350,7 @@ final class ApiBillController extends Controller
->execute(); ->execute();
} }
/** @var \Modules\Billing\Models\BillType $billType */ $bill = $this->createBaseBill($account, $request);
$billType = BillTypeMapper::get()
->where('id', $request->getDataInt('type') ?? 1)
->execute();
// @todo: use defaultInvoiceAddress or mainAddress. also consider to use billto1, billto2, billto3 (for multiple lines e.g. name2, fao etc.)
/** @var \Modules\SupplierManagement\Models\Supplier|\Modules\ClientManagement\Models\Client $account */
$bill = new Bill();
$bill->unit = $account->unit ?? $this->app->unitId;
$bill->createdBy = new NullAccount($request->header->account);
$bill->type = $billType;
$bill->billTo = $request->getDataString('billto') ?? (
$account->account->name1 . (!empty($account->account->name2)
? ', ' . $account->account->name2
: ''
));
$bill->billAddress = (string) ($request->getDataString('billaddress') ?? $account->mainAddress->address);
$bill->billZip = (string) ($request->getDataString('billtopostal') ?? $account->mainAddress->postal);
$bill->billCity = (string) ($request->getDataString('billtocity') ?? $account->mainAddress->city);
$bill->billCountry = $request->getDataString('billtocountry') ?? (
($country = $account->mainAddress->getCountry()) === ISO3166TwoEnum::_XXX ? '' : $country);
$bill->client = !$request->hasData('client') ? null : $account;
$bill->supplier = !$request->hasData('supplier') ? null : $account;
$bill->performanceDate = $request->getDataDateTime('performancedate') ?? new \DateTime('now');
$bill->setStatus($request->getDataInt('status') ?? BillStatus::ACTIVE);
return $bill; return $bill;
} }
@ -435,7 +426,7 @@ final class ApiBillController extends Controller
$bill->id, $bill->id,
$media->id, $media->id,
BillMapper::class, BillMapper::class,
'media', 'files',
'', '',
$request->getOrigin() $request->getOrigin()
); );
@ -483,7 +474,7 @@ final class ApiBillController extends Controller
$bill->id, $bill->id,
(int) $media, (int) $media,
BillMapper::class, BillMapper::class,
'media', 'files',
'', '',
$request->getOrigin() $request->getOrigin()
); );
@ -570,9 +561,9 @@ final class ApiBillController extends Controller
$new = clone $old; $new = clone $old;
$new->addElement($element); $new->addElement($element);
$this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill_element', $request->getOrigin());
$this->fillJsonResponse($request, $response, NotificationLevel::OK, 'Bill element', 'Bill element successfully created.', $element); $this->updateModel($request->header->account, $old, $new, BillMapper::class, 'bill_element', $request->getOrigin());
$this->createStandardCreateResponse($request, $response, $element);
} }
/** /**
@ -631,6 +622,12 @@ final class ApiBillController extends Controller
return []; return [];
} }
public function apiMediaRender(RequestAbstract $request, ResponseAbstract $response, mixed $data = null) : void
{
// @todo: check if has permission
$this->app->moduleManager->get('Media', 'Api')->apiMediaExport($request, $response, ['ignorePermission' => true]);
}
/** /**
* Api method to create a bill preview * Api method to create a bill preview
* *
@ -789,24 +786,29 @@ final class ApiBillController extends Controller
{ {
Autoloader::addPath(__DIR__ . '/../../../Resources/'); Autoloader::addPath(__DIR__ . '/../../../Resources/');
/** @var \Modules\Billing\Models\Bill $bill */
$bill = BillMapper::get()
->where('id', $request->getDataInt('bill') ?? 0)
->execute();
// @todo: This is stupid to do twice but I need to get the langauge.
// For the future it should just be a join on the bill langauge!!!
// The problem is the where here is a model where and not a query
// builder where meaning it is always considered a value and not a column.
/** @var \Modules\Billing\Models\Bill $bill */ /** @var \Modules\Billing\Models\Bill $bill */
$bill = BillMapper::get() $bill = BillMapper::get()
->with('type') ->with('type')
->with('type/l11n') ->with('type/l11n')
->with('type/defaultTemplate')
->with('elements') ->with('elements')
->where('id', $request->getDataInt('bill') ?? 0) ->where('id', $request->getDataInt('bill') ?? 0)
->where('type/l11n/language', $bill->getLanguage())
->execute(); ->execute();
$templateId = $request->getDataInt('bill_template'); $templateId = $request->getDataInt('bill_template');
if ($templateId === null) { if ($templateId === null) {
$billTypeId = $bill->type->id; $templateId = $bill->type->defaultTemplate?->id;
/** @var \Modules\Billing\Models\BillType $billType */
$billType = BillTypeMapper::get()
->where('id', $billTypeId)
->execute();
$templateId = $billType->defaultTemplate?->id;
} }
/** @var \Modules\Media\Models\Collection $template */ /** @var \Modules\Media\Models\Collection $template */
@ -920,24 +922,34 @@ final class ApiBillController extends Controller
$this->sendBillEmail($media, $email, $response->getLanguage()); $this->sendBillEmail($media, $email, $response->getLanguage());
} }
// Add type to media
$originalType = $this->app->appSettings->get(
names: SettingsEnum::ORIGINAL_MEDIA_TYPE,
module: self::NAME
);
$this->createModelRelation(
$request->header->account,
$media->id,
(int) $originalType->content,
MediaMapper::class,
'types',
'',
$request->getOrigin()
);
// Add media to bill
$this->createModelRelation( $this->createModelRelation(
$request->header->account, $request->header->account,
$bill->id, $bill->id,
$media->id, $media->id,
BillMapper::class, BillMapper::class,
'media', 'files',
'', '',
$request->getOrigin() $request->getOrigin()
); );
$this->fillJsonResponse( $this->createStandardCreateResponse($request, $response, $media);
$request,
$response,
NotificationLevel::OK,
'PDF',
'Bill Pdf successfully created.',
$media
);
} }
public function sendBillEmail(Media $media, string $email, string $language = 'en') : void public function sendBillEmail(Media $media, string $email, string $language = 'en') : void

View File

@ -68,6 +68,7 @@ final class BackendController extends Controller
->with('type/l11n') ->with('type/l11n')
->with('client') ->with('client')
->where('type/transferType', BillTransferType::SALES) ->where('type/transferType', BillTransferType::SALES)
->where('type/l11n/language', $response->getLanguage())
->sort('id', OrderType::DESC) ->sort('id', OrderType::DESC)
->limit(25); ->limit(25);
@ -76,21 +77,18 @@ final class BackendController extends Controller
$mapperQuery $mapperQuery
->where('id', $request->getDataInt('id') ?? 0, '<') ->where('id', $request->getDataInt('id') ?? 0, '<')
->where('client', null, '!=') ->where('client', null, '!=')
->where('type/l11n/language', $response->getLanguage())
->execute() ->execute()
); );
} elseif ($request->getData('ptype') === 'n') { } elseif ($request->getData('ptype') === 'n') {
$view->setData('bills', $view->setData('bills',
$mapperQuery->where('id', $request->getDataInt('id') ?? 0, '>') $mapperQuery->where('id', $request->getDataInt('id') ?? 0, '>')
->where('client', null, '!=') ->where('client', null, '!=')
->where('type/l11n/language', $response->getLanguage())
->execute() ->execute()
); );
} else { } else {
$view->setData('bills', $view->setData('bills',
$mapperQuery->where('id', 0, '>') $mapperQuery->where('id', 0, '>')
->where('client', null, '!=') ->where('client', null, '!=')
->where('type/l11n/language', $response->getLanguage())
->execute() ->execute()
); );
} }
@ -119,7 +117,8 @@ final class BackendController extends Controller
/** @var \Modules\Billing\Models\Bill $bill */ /** @var \Modules\Billing\Models\Bill $bill */
$bill = SalesBillMapper::get() $bill = SalesBillMapper::get()
->with('elements') ->with('elements')
->with('media') ->with('files')
->with('files/types')
->with('notes') ->with('notes')
->where('id', (int) $request->getData('id')) ->where('id', (int) $request->getData('id'))
->execute(); ->execute();
@ -298,8 +297,8 @@ final class BackendController extends Controller
$bill = PurchaseBillMapper::get() $bill = PurchaseBillMapper::get()
->with('elements') ->with('elements')
->with('media') ->with('files')
->with('media/types') ->with('files/types')
->with('notes') ->with('notes')
->where('id', (int) $request->getData('id')) ->where('id', (int) $request->getData('id'))
->execute(); ->execute();
@ -806,8 +805,8 @@ final class BackendController extends Controller
$bill = PurchaseBillMapper::get() $bill = PurchaseBillMapper::get()
->with('elements') ->with('elements')
->with('media') ->with('files')
->with('media/types') ->with('files/types')
->with('notes') ->with('notes')
->where('id', (int) $request->getData('id')) ->where('id', (int) $request->getData('id'))
->execute(); ->execute();

View File

@ -339,7 +339,7 @@ class Bill implements \JsonSerializable
* @var string * @var string
* @since 1.0.0 * @since 1.0.0
*/ */
private string $currency = ISO4217CharEnum::_EUR; public string $currency = ISO4217CharEnum::_EUR;
/** /**
* Info text. * Info text.
@ -445,14 +445,6 @@ class Bill implements \JsonSerializable
*/ */
public int $reference = 0; public int $reference = 0;
/**
* Media files
*
* @var array
* @since 1.0.0
*/
protected array $media = [];
/** /**
* Attributes. * Attributes.
* *
@ -761,77 +753,6 @@ class Bill implements \JsonSerializable
return $this->notes; return $this->notes;
} }
/**
* Get all media
*
* @return Media[]
*
* @since 1.0.0
*/
public function getMedia() : array
{
return $this->media;
}
/**
* Add media
*
* @param Media $media Media to add
*
* @return void
*
* @since 1.0.0
*/
public function addMedia(Media $media) : void
{
$this->media[] = $media;
}
/**
* Get media file by type
*
* @param null|int $type Media type
*
* @return array
*
* @since 1.0.0
*/
public function getMediaByType(int $type = null) : array
{
if ($type === null) {
return $this->media;
}
$files = [];
foreach ($this->media as $file) {
if ($file->type !== null && $file->type->id === $type) {
$files[] = $file;
}
}
return $files;
}
/**
* Get media file by type
*
* @param int $type Media type
*
* @return Media
*
* @since 1.0.0
*/
public function getFileByType(int $type) : Media
{
foreach ($this->media as $file) {
if ($file->hasMediaTypeId($type)) {
return $file;
}
}
return new NullMedia();
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -865,4 +786,5 @@ class Bill implements \JsonSerializable
} }
use \Modules\Attribute\Models\AttributeHolderTrait; use \Modules\Attribute\Models\AttributeHolderTrait;
use \Modules\Media\Models\MediaListTrait;
} }

View File

@ -109,7 +109,7 @@ class BillMapper extends DataMapperFactory
'self' => 'billing_bill_element_bill', 'self' => 'billing_bill_element_bill',
'external' => null, 'external' => null,
], ],
'media' => [ 'files' => [
'mapper' => MediaMapper::class, 'mapper' => MediaMapper::class,
'table' => 'billing_bill_media', 'table' => 'billing_bill_media',
'external' => 'billing_bill_media_dst', 'external' => 'billing_bill_media_dst',

View File

@ -28,7 +28,7 @@ abstract class SettingsEnum extends Enum
{ {
public const PREVIEW_MEDIA_TYPE = '1005100001'; // internally generated preview public const PREVIEW_MEDIA_TYPE = '1005100001'; // internally generated preview
public const ORIGINAL_MEDIA_TYPE = '1005100002'; // original document (mostly supplier invoice/delivery note) public const ORIGINAL_MEDIA_TYPE = '1005100002'; // original document (client = invoice sent to client, supplier = invoice from supplier)
public const VALID_BILL_LANGUAGES = '1005100003'; // List of valid languages for bills public const VALID_BILL_LANGUAGES = '1005100003'; // List of valid languages for bills

View File

@ -14,6 +14,7 @@ declare(strict_types=1);
return ['Billing' => [ return ['Billing' => [
'Amount' => 'Amount', 'Amount' => 'Amount',
'Archive' => 'Archive',
'Address' => 'Address', 'Address' => 'Address',
'Addresses' => 'Addresses', 'Addresses' => 'Addresses',
'Africa' => 'Africa', 'Africa' => 'Africa',

View File

@ -36,6 +36,8 @@ $elements = $bill->getElements();
$billTypes = $this->getData('billtypes') ?? []; $billTypes = $this->getData('billtypes') ?? [];
$archive = $bill->getFileByTypeName('original');
/** @var \Modules\Auditor\Models\Audit */ /** @var \Modules\Auditor\Models\Audit */
$logs = $this->getData('logs') ?? []; $logs = $this->getData('logs') ?? [];
@ -49,10 +51,11 @@ echo $this->getData('nav')->render(); ?>
<ul class="tab-links"> <ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Invoice'); ?></label></li> <li><label for="c-tab-1"><?= $this->getHtml('Invoice'); ?></label></li>
<li><label for="c-tab-2"><?= $this->getHtml('Items'); ?></label></li> <li><label for="c-tab-2"><?= $this->getHtml('Items'); ?></label></li>
<li><label for="c-tab-3">Preview</label></li> <li><label for="c-tab-3"><?= $this->getHtml('Preview'); ?></label></li>
<li><label for="c-tab-4"><?= $this->getHtml('Payment'); ?></label></li> <li><label for="c-tab-4"><?= $this->getHtml('Archive'); ?></label></li>
<li><label for="c-tab-5"><?= $this->getHtml('Media'); ?></label></li> <li><label for="c-tab-5"><?= $this->getHtml('Payment'); ?></label></li>
<li><label for="c-tab-6"><?= $this->getHtml('Logs'); ?></label></li> <li><label for="c-tab-6"><?= $this->getHtml('Media'); ?></label></li>
<li><label for="c-tab-7"><?= $this->getHtml('Logs'); ?></label></li>
</ul> </ul>
</div> </div>
<div class="tab-content col-simple"> <div class="tab-content col-simple">
@ -355,13 +358,25 @@ echo $this->getData('nav')->render(); ?>
<div class="col-xs-12 col-simple"> <div class="col-xs-12 col-simple">
<section id="mediaFile" class="portlet col-simple"> <section id="mediaFile" class="portlet col-simple">
<div class="portlet-body col-simple"> <div class="portlet-body col-simple">
<iframe class="col-simple" id="iHelperFrame" src="Resources/mozilla/Pdf/web/viewer.html?file=<?= \urlencode('http://127.0.0.1/en/api/bill/render?bill_type='); ?>{#iBillPreviewType}" loading="lazy" allowfullscreen></iframe> <iframe class="col-simple" id="iHelperFrame" src="" loading="lazy" allowfullscreen></iframe>
</div> </div>
</section> </section>
</div> </div>
</div> </div>
</div> </div>
<input type="radio" id="c-tab-4" name="tabular-2"> <input type="radio" id="c-tab-4" name="tabular-2">
<div class="tab col-simple">
<div class="col-simple">
<div class="col-xs-12 col-simple">
<section id="mediaFile" class="portlet col-simple">
<div class="portlet-body col-simple">
<iframe class="col-simple" id="iHelperFrame" src="Resources/mozilla/Pdf/web/viewer.html?file=<?= \urlencode(UriFactory::build('{/api}bill/render?id=' . $archive->id)); ?>" loading="lazy" allowfullscreen></iframe>
</div>
</section>
</div>
</div>
</div>
<input type="radio" id="c-tab-5" name="tabular-2">
<div class="tab"> <div class="tab">
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-6 col-lg-4"> <div class="col-xs-12 col-md-6 col-lg-4">
@ -459,7 +474,7 @@ echo $this->getData('nav')->render(); ?>
</div> </div>
</div> </div>
</div> </div>
<input type="radio" id="c-tab-5" name="tabular-2"> <input type="radio" id="c-tab-6" name="tabular-2">
<div class="tab"> <div class="tab">
<div class="row"> <div class="row">
<div class="col-xs-12 col-md-6 col-lg-4"> <div class="col-xs-12 col-md-6 col-lg-4">
@ -489,7 +504,7 @@ echo $this->getData('nav')->render(); ?>
</div> </div>
</div> </div>
</div> </div>
<input type="radio" id="c-tab-6" name="tabular-2"> <input type="radio" id="c-tab-7" name="tabular-2">
<div class="tab"> <div class="tab">
<?php <?php
$footerView = new \phpOMS\Views\PaginationView($this->l11nManager, $this->request, $this->response); $footerView = new \phpOMS\Views\PaginationView($this->l11nManager, $this->request, $this->response);

View File

@ -170,7 +170,7 @@ echo $this->getData('nav')->render(); ?>
<td><a href="<?= $url; ?>"><?= $value->billZip; ?></a> <td><a href="<?= $url; ?>"><?= $value->billZip; ?></a>
<td><a href="<?= $url; ?>"><?= $value->billCity; ?></a> <td><a href="<?= $url; ?>"><?= $value->billCity; ?></a>
<td><a href="<?= $url; ?>"><?= $value->billCountry; ?></a> <td><a href="<?= $url; ?>"><?= $value->billCountry; ?></a>
<td><a href="<?= $url; ?>"><?= $value->netSales->getCurrency(); ?></a> <td><a href="<?= $url; ?>"><?= $this->getCurrency($value->netSales); ?></a>
<td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a> <td><a href="<?= $url; ?>"><?= $value->createdAt->format('Y-m-d'); ?></a>
<?php endforeach; ?> <?php endforeach; ?>
<?php if ($count === 0) : ?> <?php if ($count === 0) : ?>

View File

@ -34,7 +34,7 @@ $media = $bill->getMedia();
echo $this->getData('nav')->render(); ?> echo $this->getData('nav')->render(); ?>
<div class="tabview tab-2"> <div class="tabview tab-2 col-simple">
<div class="box"> <div class="box">
<ul class="tab-links"> <ul class="tab-links">
<li><label for="c-tab-1"><?= $this->getHtml('Invoice'); ?></label></li> <li><label for="c-tab-1"><?= $this->getHtml('Invoice'); ?></label></li>
@ -46,7 +46,7 @@ echo $this->getData('nav')->render(); ?>
<li><label for="c-tab-7"><?= $this->getHtml('Logs'); ?></label></li> <li><label for="c-tab-7"><?= $this->getHtml('Logs'); ?></label></li>
</ul> </ul>
</div> </div>
<div class="tab-content"> <div class="tab-content col-simple">
<input type="radio" id="c-tab-1" name="tabular-2" checked> <input type="radio" id="c-tab-1" name="tabular-2" checked>
<div class="tab"> <div class="tab">
<div class="row"> <div class="row">
@ -200,13 +200,13 @@ echo $this->getData('nav')->render(); ?>
</div> </div>
</div> </div>
<input type="radio" id="c-tab-3" name="tabular-2"> <input type="radio" id="c-tab-3" name="tabular-2">
<div class="tab"> <div class="tab col-simple">
<div class="row"> <div class="row col-simple">
<div class="col-xs-12"> <div class="col-xs-12 col-simple">
<section id="mediaFile" class="portlet"> <section id="mediaFile" class="portlet col-simple">
<div class="portlet-body"> <div class="portlet-body col-simple">
<?php if ($billPdf->id > 0) : ?> <?php if ($billPdf->id > 0) : ?>
<iframe style="min-height: 600px;" data-form="iUiSettings" data-name="iframeHelper" id="iHelperFrame" src="<?= UriFactory::build('{/backend}Resources/mozilla/Pdf/web/viewer.html{?}&file=' . \urlencode(($billPdf->isAbsolute ? '' : '/../../../../') . $billPdf->getPath())); ?>" allowfullscreen></iframe> <iframe class="col-simple" data-form="iUiSettings" data-name="iframeHelper" id="iHelperFrame" src="<?= UriFactory::build('Resources/mozilla/Pdf/web/viewer.html{?}&file=' . \urlencode(($billPdf->isAbsolute ? '' : '/../../../../') . $billPdf->getPath())); ?>" allowfullscreen></iframe>
<?php endif; ?> <?php endif; ?>
</div> </div>
</section> </section>
@ -214,13 +214,13 @@ echo $this->getData('nav')->render(); ?>
</div> </div>
</div> </div>
<input type="radio" id="c-tab-4" name="tabular-2"> <input type="radio" id="c-tab-4" name="tabular-2">
<div class="tab"> <div class="tab col-simple">
<div class="row"> <div class="row col-simple">
<div class="col-xs-12"> <div class="col-xs-12 col-simple">
<section id="mediaFile" class="portlet"> <section id="mediaFile" class="portlet col-simple">
<div class="portlet-body"> <div class="portlet-body col-simple">
<?php if ($original->id > 0) : ?> <?php if ($original->id > 0) : ?>
<iframe style="min-height: 600px;" data-form="iUiSettings" data-name="iframeHelper" id="iHelperFrame" src="<?= UriFactory::build('{/backend}Resources/mozilla/Pdf/web/viewer.html{?}&file=' . \urlencode(($original->isAbsolute ? '' : '/../../../../') . $original->getPath())); ?>" allowfullscreen></iframe> <iframe class="col-simple" data-form="iUiSettings" data-name="iframeHelper" id="iHelperFrame" src="<?= UriFactory::build('Resources/mozilla/Pdf/web/viewer.html{?}&file=' . \urlencode(($original->isAbsolute ? '' : '/../../../../') . $original->getPath())); ?>" allowfullscreen></iframe>
<?php endif; ?> <?php endif; ?>
</div> </div>
</section> </section>