Updated Warehouse
This commit is contained in:
@@ -17,10 +17,8 @@
|
||||
}
|
||||
|
||||
.customer-details {
|
||||
vertical-align: bottom;
|
||||
vertical-align: top;
|
||||
font-size: 14px;
|
||||
padding-left: 30pt;
|
||||
width: 35%;
|
||||
}
|
||||
|
||||
.invoice-details {
|
||||
@@ -58,8 +56,8 @@
|
||||
|
||||
<table style="width: 100%; border-collapse: collapse;">
|
||||
<tr>
|
||||
<td class="customer-details" style="float: left">
|
||||
<h3>Lieferant</h3>
|
||||
<td class="customer-details">
|
||||
<h3>{{ addressLine_header }}</h3>
|
||||
<div>{{ addressLine_1 }}</div>
|
||||
<div>{{ addressLine_2 }}</div>
|
||||
<div>{{ addressLine_3 }}</div>
|
||||
@@ -67,8 +65,15 @@
|
||||
<div style="margin-bottom: 12pt"></div>
|
||||
<div>{{ externalReference }}</div>
|
||||
</td>
|
||||
<td class="customer-details" align="top">
|
||||
<h3>Rechnungsadresse</h3>
|
||||
<td class="customer-details">
|
||||
<h3>{{ shippingAddressLine_header }}</h3>
|
||||
<div>{{ shippingAddressLine_1 }}</div>
|
||||
<div>{{ shippingAddressLine_2 }}</div>
|
||||
<div>{{ shippingAddressLine_3 }}</div>
|
||||
<div>{{ shippingAddressLine_4 }}</div>
|
||||
</td>
|
||||
<td class="customer-details">
|
||||
<h3>{{ billingAddressLine_header }}</h3>
|
||||
<div>{{ billingAddressLine_1 }}</div>
|
||||
<div>{{ billingAddressLine_2 }}</div>
|
||||
<div>{{ billingAddressLine_3 }}</div>
|
||||
@@ -76,12 +81,6 @@
|
||||
<div>{{ billingAddressLine_5 }}</div>
|
||||
<div>{{ billingAddressLine_6 }}</div>
|
||||
</td>
|
||||
<td class="customer-details" style="float: right">
|
||||
<div>{{ shippingAddressLine_1 }}</div>
|
||||
<div>{{ shippingAddressLine_2 }}</div>
|
||||
<div>{{ shippingAddressLine_3 }}</div>
|
||||
<div>{{ shippingAddressLine_4 }}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
@@ -6,13 +6,51 @@
|
||||
* @var Array $textElements
|
||||
*/
|
||||
$this->setReturnValue(['filename' => $order["id"] . ".pdf"]);
|
||||
|
||||
|
||||
$texts = [
|
||||
'EN' => [
|
||||
'header' => 'XINON Supplier Order from ' . date("d.m.Y", $order["create"]),
|
||||
'sum' => 'Sum',
|
||||
'vat' => '20% VAT',
|
||||
'total' => 'Total',
|
||||
'taxFree' => 'Please provide tax-free delivery according to § 6a UStG (Austrian Sales tax law).<br>Our VAT ID number: ATU68711968. Delivery to Austria.',
|
||||
'orderConfirmation' => 'Please send the order confirmation to office@xinon.at',
|
||||
'table' => [
|
||||
'pos' => 'POS',
|
||||
'article' => 'Article',
|
||||
'articleNumber' => 'Dist. art. nr.',
|
||||
'amount' => 'Amount',
|
||||
'unitPrice' => 'Unit price',
|
||||
'totalPrice' => 'Total price'
|
||||
]
|
||||
],
|
||||
'DE' => [
|
||||
'header' => 'XINON Lieferantenbestellung vom ' . date("d.m.Y", $order["create"]),
|
||||
'sum' => 'Summe',
|
||||
'vat' => '20% MwSt',
|
||||
'total' => 'Gesamt',
|
||||
'taxFree' => 'Bitte um steuerfreie Lieferung gemäß § 6a UStG.<br> Unsere UID-Nr.: ATU68711968. Lieferung nach Österreich.',
|
||||
'orderConfirmation' => 'Wir bitten um Zusendung der Auftragsbestätigung für die Bestellung an office@xinon.at.',
|
||||
'table' => [
|
||||
'pos' => 'POS',
|
||||
'article' => 'Artikel',
|
||||
'articleNumber' => 'Art.-Nr. Lieferant',
|
||||
'amount' => 'Menge',
|
||||
'unitPrice' => 'Einzelpreis',
|
||||
'totalPrice' => 'Gesamtpreis'
|
||||
]
|
||||
]];
|
||||
|
||||
$text = $texts[in_array($distributorCountryText, ["Österreich", "Deutschland", "Schweiz"]) ? "DE" : "EN"];
|
||||
|
||||
?>
|
||||
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Bestellung</title>
|
||||
<meta charset="utf-8" />
|
||||
<title><?= $text['header'] ?></title>
|
||||
<meta charset="utf-8"/>
|
||||
<style>
|
||||
body {
|
||||
margin-top: 0;
|
||||
@@ -76,58 +114,78 @@ $this->setReturnValue(['filename' => $order["id"] . ".pdf"]);
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<!--
|
||||
TODO: enable option for showing prices
|
||||
vertauschen
|
||||
Die gelieferte Ware bleibt bis zur vollständigen Bezahlung in unserem Eigentum.
|
||||
-->
|
||||
<h2 style="text-align: center;color: #005384">XINON Lieferantenbestellung vom <?=date("d.m.Y", $order["create"])?></h2>
|
||||
<h2 style="text-align: center;color: #005384"><?= $text['header'] ?></h2>
|
||||
|
||||
<table style="border-collapse: collapse; width: 100%;" id="invoiceTable">
|
||||
<tr style="font-weight: bold; border-bottom: 1px solid black;" class="uneven">
|
||||
<th style="text-align: center;padding-right: 6pt">Position</th>
|
||||
<th style="text-align: center;padding-right: 6pt">Artikel</th>
|
||||
<th style="text-align: center;padding-right: 6pt">Art.-Nr. Lieferant</th>
|
||||
<th style="text-align: right">Menge</th>
|
||||
<th style="text-align: right">Einzelpreis</th>
|
||||
<th style="text-align: right;padding-right: 8pt">Gesamtpreis</th>
|
||||
<th style="text-align: center;padding-right: 6pt"><?= $text['table']['pos'] ?></th>
|
||||
<th style="text-align: center;padding-right: 6pt"><?= $text['table']['article'] ?></th>
|
||||
<th style="text-align: center;padding-right: 6pt"><?= $text['table']['articleNumber'] ?></th>
|
||||
<th style="text-align: right"><?= $text['table']['amount'] ?></th>
|
||||
<th style="text-align: right"><?= $text['table']['unitPrice'] ?></th>
|
||||
<th style="text-align: right;padding-right: 8pt"><?= $text['table']['totalPrice'] ?></th>
|
||||
</tr>
|
||||
<?php $i = 0; foreach($order['positions'] as $p):?>
|
||||
<?php $i = 0;
|
||||
foreach ($order['positions'] as $p): ?>
|
||||
|
||||
<tr class="position <?=($i%2 == 0) ? "even" : "uneven" ?>">
|
||||
<td style="text-align: center;"><?= $i + 1 ?></td>
|
||||
<td style="text-align: left;padding-right: 8pt"><?=$p["articleName"]?></td>
|
||||
<td style="text-align: center;padding-right: 8pt"><?=$p["distributorArticleNumber"]?></td>
|
||||
<td style="text-align: right"><?=$p["amount"]?></td>
|
||||
<td style="text-align: right"><?=number_format($p["buyPrice"], 2, ",", ".")?> €</td>
|
||||
<td style="text-align: right;padding-right: 8pt"><?=number_format($p["amount"] * $p["buyPrice"], 2, ",", ".")?> €</td>
|
||||
</tr>
|
||||
<?php $i++; endforeach;?>
|
||||
<!-- display a grey like header sum with top border to differentiate 2nd last td = Summe , last td is the calculated value both bold-->
|
||||
<tr class="position <?= ($i % 2 == 0) ? "even" : "uneven" ?>">
|
||||
<td style="text-align: center;"><?= $i + 1 ?></td>
|
||||
<td style="text-align: left;padding-right: 8pt"><?= $p["articleName"] ?></td>
|
||||
<td style="text-align: center;padding-right: 8pt"><?= $p["distributorArticleNumber"] ?></td>
|
||||
<td style="text-align: right"><?= $p["amount"] ?></td>
|
||||
<td style="text-align: right"><?= number_format($p["buyPrice"], 2, ",", ".") ?> €</td>
|
||||
<td style="text-align: right;padding-right: 8pt"><?= number_format($p["amount"] * $p["buyPrice"], 2, ",", ".") ?> €</td>
|
||||
</tr>
|
||||
|
||||
<tr class="<?= ($i % 2 == 0) ? "even" : "uneven" ?>">
|
||||
<td></td>
|
||||
<td style="text-align: left;max-width: 200px"><?= $p["articleDescription"] ?></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
|
||||
|
||||
<?php $i++; endforeach; ?>
|
||||
|
||||
<tr class="uneven">
|
||||
<?php
|
||||
$sum = 0;
|
||||
foreach($order['positions'] as $p){
|
||||
foreach ($order['positions'] as $p) {
|
||||
$sum += $p["amount"] * $p["buyPrice"];
|
||||
}
|
||||
?>
|
||||
<td colspan="5" style="text-align: right;border-top: 1px solid black;font-weight: bold
|
||||
;border-bottom: 1px solid black;
|
||||
">Summe</td>
|
||||
"><?= $text['sum'] ?>
|
||||
</td>
|
||||
<td style="text-align: right;border-top: 1px solid black;font-weight: bold
|
||||
;border-bottom: 1px solid black;
|
||||
"><?=number_format($sum, 2, ",", ".")?> €</td>
|
||||
"><?= number_format($sum, 2, ",", ".") ?> €
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php if ($distributorCountryText === "Österreich"): ?>
|
||||
<tr style="font-weight: bold; border-bottom: 1px solid black; background-color: #ebebeb;">
|
||||
<td colspan="5" style="text-align: right;font-weight: bold;">20% MwSt</td>
|
||||
<td style="text-align: right;font-weight: bold;"><?= number_format($sum * 0.2, 2, ",", ".") ?> €</td>
|
||||
</tr>
|
||||
<tr class="uneven" style="font-weight: bold; border-bottom: 3px double black; background-color: #ebebeb;">
|
||||
<td colspan="5" style="text-align: right;font-weight: bold;"><?= $text['total'] ?></td>
|
||||
<td style="text-align: right;font-weight: bold;"><?= number_format($sum * 1.2, 2, ",", ".") ?> €</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
|
||||
|
||||
</table>
|
||||
|
||||
<div>
|
||||
<h3>Anmerkungen</h3>
|
||||
<p>
|
||||
<?=$order["note"]?>
|
||||
</p>
|
||||
<?php if ($distributorCountryText !== "Österreich"): ?>
|
||||
<?= $text['taxFree'] ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?= $text['orderConfirmation'] ?>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -61,6 +61,8 @@
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<script src="https://cdn.jsdelivr.net/npm/sortablejs@1.14.0/Sortable.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/vue-draggable-next@2.1.0"></script>
|
||||
<script type="text/javascript">
|
||||
baseurl = '<?=self::getResourcePath()?>';
|
||||
</script>
|
||||
|
||||
@@ -30,6 +30,10 @@ class WarehouseOfferController extends TTCrud {
|
||||
['key' => 'sendOffer', 'title' => 'Angebot senden', 'class' => 'fas fa-paper-plane text-success']
|
||||
];
|
||||
|
||||
protected array $additionalJS = ['
|
||||
https://cdn.jsdelivr.net/npm/sortablejs@1.14.0/Sortable.min.js
|
||||
https://cdn.jsdelivr.net/npm/vue-draggable-next@2.1.0'];
|
||||
|
||||
protected array $infoMessages = [
|
||||
'create' => 'Angebot wurde erfolgreich erstellt.',
|
||||
'update' => 'Angebot wurde aktualisiert.',
|
||||
|
||||
@@ -9,18 +9,18 @@ class WarehouseOrderController extends TTCrud {
|
||||
protected array $columns = [
|
||||
['key' => 'id', 'text' => 'ID', 'modal' => false, 'table' => false],
|
||||
['key' => 'orderNumber', 'text' => 'Bestellnummer', 'required' => true, 'modal' => false],
|
||||
['key' => 'distributor', 'text' => 'Lieferant', 'required' => false, 'modal' => false, 'table' => ['filter' => false]],
|
||||
['key' => 'distributorId', 'text' => 'Lieferant', 'required' => false, 'modal' => ['type' => 'select', 'items' => []], 'table' => ['filter' => 'select']],
|
||||
['key' => 'delAddrCity', 'text' => 'Stadt', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'delAddrEMail', 'text' => 'E-Mail', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'delAddrLine', 'text' => 'Adresse', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'delAddrName', 'text' => 'Name', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'delAddrPLZ', 'text' => 'PLZ', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'editor', 'text' => 'Bearbeiter', 'required' => true, 'modal' => ['type' => 'select'], 'table' => ['filter' => 'select']],
|
||||
['key' => 'note', 'text' => 'Notiz', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'note', 'text' => 'Notiz', 'required' => false, 'modal' => false, 'table' => false],
|
||||
['key' => 'sum', 'text' => 'Summe', 'required' => false, 'modal' => false, 'table' => ['class' => 'text-right']],
|
||||
['key' => 'status', 'text' => 'Status', 'required' => false, 'modal' => ['type' => 'select', 'items' => []], 'table' => ['filter' => 'select']],
|
||||
['key' => 'positions', 'text' => 'Positionen', 'required' => true, 'modal' => false, 'table' => false],
|
||||
['key' => 'extReference', 'text' => 'Externe Referenz', 'required' => true, 'modal' => false],
|
||||
['key' => 'extReference', 'text' => 'Externe Referenz', 'required' => false, 'modal' => false],
|
||||
['key' => 'createBy', 'text' => 'Erstellt von', 'required' => true, 'modal' => ['type' => 'select'], 'table' => ['filter' => 'select']],
|
||||
['key' => 'create', 'text' => 'Erstellt', 'required' => true, 'modal' => false],
|
||||
['key' => 'actions', 'text' => 'Aktionen', 'required' => false, 'modal' => false, 'table' => ['filter' => false, 'sortable' => false, 'class' => 'text-center']],
|
||||
@@ -32,6 +32,8 @@ class WarehouseOrderController extends TTCrud {
|
||||
'delete' => 'Bestellung wurde gelöscht',
|
||||
'noChanges' => 'Keine Änderungen',];
|
||||
|
||||
protected array $additionalActions = [['key' => 'openpdf', 'title' => 'PDF öffnen', 'class' => 'fas fa-file-pdf', 'color' => 'primary']];
|
||||
|
||||
protected function prepareCrudConfig(): void {
|
||||
$editorColumnIndex = array_search('editor', array_column($this->columns, 'key'));
|
||||
$this->columns[$editorColumnIndex]['modal']['items'] = array_map(function ($user) {
|
||||
@@ -48,6 +50,11 @@ class WarehouseOrderController extends TTCrud {
|
||||
['value' => 'fullyDelivered', 'text' => 'Geliefert'],
|
||||
['value' => 'cancelled', 'text' => 'Storniert'],
|
||||
];
|
||||
|
||||
$distributorIndex = array_search('distributorId', array_column($this->columns, 'key'));
|
||||
$this->columns[$distributorIndex]['modal']['items'] = array_map(function ($distributor) {
|
||||
return ['value' => intval($distributor->id), 'text' => $distributor->name];
|
||||
}, WarehouseDistributorModel::getAll());
|
||||
}
|
||||
|
||||
protected function beforeCreate(): bool {
|
||||
@@ -91,40 +98,43 @@ class WarehouseOrderController extends TTCrud {
|
||||
// we need to get the article name and distributor name for the pdf
|
||||
$position['distributorName'] = WarehouseDistributorModel::get($position['distributorId'])->name;
|
||||
$position['articleName'] = WarehouseArticleModel::get($position['article'])->title;
|
||||
$position['articleDescription'] = WarehouseArticleModel::get($position['article'])->description;
|
||||
|
||||
$order['positions'][$key] = $position;
|
||||
}
|
||||
|
||||
$pdf_vars = ['order' => $order,
|
||||
'distributor' => WarehouseDistributorModel::get($distributorId),
|
||||
'distributorCountryText' => (new Country(WarehouseDistributorModel::get($distributorId)->countryId))->name,
|
||||
"bank_iban" => TT_INVOICE_BANK_IBAN,
|
||||
"bank_bic" => TT_INVOICE_BANK_BIC,
|
||||
"bank_bank" => TT_INVOICE_BANK_BANK,
|
||||
"bank_owner" => TT_INVOICE_BANK_OWNER];
|
||||
|
||||
|
||||
$countryText = CountryModel::search(['id' => WarehouseDistributorModel::get($distributorId)->countryId])[0]->name;
|
||||
$countryText = (new Country(WarehouseDistributorModel::get($distributorId)->countryId))->name;
|
||||
$shouldGenerateEnglisch = !in_array($countryText, ['Österreich', 'Deutschland', 'Schweiz']);
|
||||
|
||||
$headerHtml = file_get_contents(BASEDIR . "/Layout/default/WarehouseOrder/PDF_HEADER.html");
|
||||
$headerHtml = str_replace("{{ basedir }}", BASEDIR, $headerHtml);
|
||||
$headerHtml = str_replace("{{ externalReference }}","<strong>Ihre Referenz:</strong> ". $order['extReference'], $headerHtml);
|
||||
$headerHtml = str_replace("{{ externalReference }}", count($order['extReference']) > 0 ? "<strong>Ext. Ref.:</strong> ". $order['extReference'] : "", $headerHtml);
|
||||
|
||||
$headerHtml = str_replace("{{ addressLine_header }}", $shouldGenerateEnglisch ? "Supplier" : "Lieferant", $headerHtml);
|
||||
$headerHtml = str_replace("{{ addressLine_1 }}", WarehouseDistributorModel::get($distributorId)->name, $headerHtml);
|
||||
$headerHtml = str_replace("{{ addressLine_2 }}", WarehouseDistributorModel::get($distributorId)->address, $headerHtml);
|
||||
$headerHtml = str_replace("{{ addressLine_3 }}", WarehouseDistributorModel::get($distributorId)->plz . " " . WarehouseDistributorModel::get($distributorId)->city, $headerHtml);
|
||||
$headerHtml = str_replace("{{ addressLine_4 }}", $countryText, $headerHtml);
|
||||
|
||||
$headerHtml = str_replace("{{ billingAddressLine_header }}", $shouldGenerateEnglisch ? "Billing Address" : "Rechnungsadresse", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_1 }}", "Xinon GmbH", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_2 }}", "Fladnitz im Raabtal 150", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_3 }}", "8322 Studenzen", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_4 }}", "Österreich", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_5 }}", "einkauf@xinon.at", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_3 }}", "A-8322 Studenzen", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_4 }}", "UID: ATU68711968", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_5 }}", "EORI-Nr.: ATEOS1000085074", $headerHtml);
|
||||
$headerHtml = str_replace("{{ billingAddressLine_6 }}", "<strong>Referenz: ". $order["orderNumber"] . "</strong>", $headerHtml);
|
||||
|
||||
// if order dellAddrLine is Fladnitz im Raabtal 150 we need to set all template strings to empty
|
||||
|
||||
$chk = $order['delAddrLine'] == "Fladnitz im Raabtal 150";
|
||||
|
||||
$headerHtml = str_replace("{{ shippingAddressLine_header }}", $chk ? "" : ($shouldGenerateEnglisch ? "Shipping Address" : "Lieferadresse"), $headerHtml);
|
||||
$headerHtml = str_replace("{{ shippingAddressLine_1 }}", $chk ? "" : $order['delAddrName'], $headerHtml);
|
||||
$headerHtml = str_replace("{{ shippingAddressLine_2 }}", $chk ? "" : $order['delAddrLine'], $headerHtml);
|
||||
$headerHtml = str_replace("{{ shippingAddressLine_3 }}", $chk ? "" : $order['delAddrPLZ'] . " " . $order['delAddrCity'], $headerHtml);
|
||||
|
||||
@@ -15,24 +15,22 @@ Vue.component('warehouse-offer-modal', {
|
||||
sm
|
||||
row
|
||||
v-model="offer.editor"/>
|
||||
<tt-input label="Kundennummer" v-model="offer.customerNumber" sm row/>
|
||||
|
||||
<tt-autocomplete label="Kunde" v-model="offer.customerNumber" sm row :api-url="billAddrAutoCompleteUrl"/>
|
||||
<tt-input label="Kundenreferenz" v-model="offer.reference" sm row/>
|
||||
<tt-textarea label="Angebotszweck" v-model="offer.purpose" sm row/>
|
||||
<hr>
|
||||
<h4 class="text-center">Kundenadresse</h4>
|
||||
<div style="display: grid; grid-gap: 10px; grid-template-columns: 2fr 2fr 1fr 1fr 2fr;">
|
||||
<div style="display: grid; grid-gap: 10px; grid-template-columns: 2fr 1fr 2fr 1fr 1fr;">
|
||||
<tt-input label="Name" v-model="offer.customerName" sm/>
|
||||
<tt-input label="Kontakt" v-model="offer.contactPerson" sm/>
|
||||
<tt-input label="Straße" v-model="offer.customerStreet" sm/>
|
||||
<tt-input label="PLZ" v-model="offer.customerZip" sm/>
|
||||
<tt-input label="Ort" v-model="offer.customerCity" sm/>
|
||||
<tt-input label="UID" v-model="offer.customerVAT" sm/>
|
||||
</div>
|
||||
<hr>
|
||||
<h4 class="text-center">Positionen</h4>
|
||||
<tt-positions-manager ref="positionsManager" v-model="offer.positions" :config="positionsConfig" @updateField-article="fetchArticleData"/>
|
||||
<hr>
|
||||
<h4 class="text-center">Alternative Artikel</h4>
|
||||
<tt-positions-manager ref="alternativePositionsManager" v-model="offer.alternativePositions" :config="alternativePositionsConfig"/>
|
||||
<tt-positions-manager group-mode ref="positionsManager" v-model="offer.positions" :config="positionsConfig" @updateField-article="fetchArticleData"/>
|
||||
<hr>
|
||||
<tt-input label="Gesamtrabatt (%)" v-model="offer.totalDiscount" sm row type="number"/>
|
||||
<tt-select label="Zahlungskonditionen" :options="paymentTerms" sm row v-model="offer.paymentTerms"/>
|
||||
@@ -45,6 +43,7 @@ Vue.component('warehouse-offer-modal', {
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
billAddrAutoCompleteUrl: window.TT_CONFIG['BASE_PATH'] + '/Address/Api?do=findAddress&fibu_primary_account=1',
|
||||
window: window,
|
||||
positionsConfig: {
|
||||
fields: {
|
||||
@@ -57,6 +56,7 @@ Vue.component('warehouse-offer-modal', {
|
||||
amount: {type: 'input', label: 'Menge', inputType: 'number'},
|
||||
unit: {type: 'input', label: 'Einheit'},
|
||||
articleNumber: {type: 'input', label: 'Artikelnummer'},
|
||||
isAlternative: {type: 'checkbox', label: 'Alternativposition'},
|
||||
unitPrice: {type: 'input', label: 'Einzelpreis', inputType: 'number'},
|
||||
discount: {type: 'input', label: 'Rabatt (%)', inputType: 'number'},
|
||||
},
|
||||
@@ -71,12 +71,6 @@ Vue.component('warehouse-offer-modal', {
|
||||
return true;
|
||||
},
|
||||
},
|
||||
alternativePositionsConfig: {
|
||||
fields: {
|
||||
article: {type: 'input', label: 'Artikel'},
|
||||
description: {type: 'textarea', label: 'Beschreibung'},
|
||||
},
|
||||
},
|
||||
paymentTerms: [
|
||||
{value: 'net30', text: '30 Tage netto'},
|
||||
{value: 'net60', text: '60 Tage netto'},
|
||||
|
||||
@@ -218,19 +218,20 @@ Vue.component('warehouse-order', {
|
||||
<tt-card>
|
||||
<warehouse-order-modal v-if="orderModalId" :id="orderModalId" @close="closeOrderModal"/>
|
||||
<button @click="orderModalId = 'create'" class="btn btn-primary">Bestellung erstellen</button>
|
||||
<tt-table-crud emit-edit @edit="orderModalId = $event.id" ref="table">
|
||||
<tt-table-crud emit-edit
|
||||
@openpdf="window.open(window.TT_CONFIG['BASE_PATH'] + '/WarehouseOrder/createPDF?id=' + $event.id)"
|
||||
@edit="orderModalId = $event.id" ref="table">
|
||||
<template v-slot:expandedRow="{ row }">
|
||||
<warehouse-order-detail :id="row['id']"/>
|
||||
</template>
|
||||
|
||||
<template v-slot:sum="{ row }">{{ calculateSum(JSON.parse(row["positions"])).toFixed(2)}} €</template>
|
||||
<!-- TODO: think of a way here prob we add it to the database as field-->
|
||||
<template v-slot:distributor="{ row }">{{ row.id % 2 == 0 ? 'Triotronik' : 'Discomp' }}</template>
|
||||
</tt-table-crud>
|
||||
</tt-card>
|
||||
`,
|
||||
data() {
|
||||
return {
|
||||
window: window,
|
||||
orderModalId: null,
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,13 +1,42 @@
|
||||
Vue.component('tt-resolver', {
|
||||
props: {
|
||||
value: {type: Number, required: true},
|
||||
reference: {type: String, required: true},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
window: window,
|
||||
loading: true,
|
||||
text: '',
|
||||
}
|
||||
},
|
||||
template: `
|
||||
<div v-if="loading" class="d-flex justify-content-center align-items-center">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
<span v-else>{{ text }}</span>
|
||||
`,
|
||||
async created() {
|
||||
const entry = await axios.get(window.TT_CONFIG['BASE_PATH'] + '/' + this.reference + '/getById?id=' + this.value);
|
||||
this.text = entry.data.name ?? entry.data.title ?? entry.data.text ?? '[E] Key not found';
|
||||
this.loading = false;
|
||||
}
|
||||
})
|
||||
|
||||
Vue.component('tt-positions-manager', {
|
||||
props: {
|
||||
value: {type: Array, required: false},
|
||||
config: {type: Object, required: true},
|
||||
value: {type: Array, required: false},
|
||||
config: {type: Object, required: true},
|
||||
groupMode: {type: Boolean, default: false},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
window: window,
|
||||
positions: this.value,
|
||||
formData: {},
|
||||
groupName: '',
|
||||
selectedIndex: null,
|
||||
resolvingFields: {},
|
||||
}
|
||||
@@ -63,6 +92,12 @@ Vue.component('tt-positions-manager', {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-container" v-if="groupMode">
|
||||
<tt-input label="Gruppenname" v-model="groupName" sm/>
|
||||
<tt-button @click="addGroup" sm text="Gruppe hinzufügen" additional-class="btn-primary"/>
|
||||
</div>
|
||||
|
||||
<table class="table table-striped table-sm">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -71,24 +106,50 @@ Vue.component('tt-positions-manager', {
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(position, index) in positions" :key="index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<template v-if="resolvingFields[index + key] === true">
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
<template v-if="groupMode">
|
||||
<template v-for="(groupPositions, groupName) in groupedPositions">
|
||||
<tr>
|
||||
<td colspan="100%">
|
||||
<h4 style="text-align: center;">{{ groupName }}</h4>
|
||||
</td>
|
||||
<tr v-for="(position, index) in groupPositions" :key="groupName + index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<tt-resolver v-if="field.customFieldReference" :reference="field.customFieldReference" :value="position[key]"/>
|
||||
<span v-else>{{ formatFieldValue(position[key], field) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select v-model="position._group" @change="$set(position, '_group', $event.target.value)">
|
||||
<option v-for="group in allGroups" :value="group">{{ group }}</option>
|
||||
</select>
|
||||
<button @click="editEntry(index)" class="btn btn-sm btn-primary">Editieren</button>
|
||||
<button @click="deleteEntry(index)" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<tr v-for="(position, index) in positions" :key="index">
|
||||
<td v-for="(field, key) in config.fields">
|
||||
<template v-if="resolvingFields[index + key] === true">
|
||||
<div class="d-flex justify-content-center align-items-center">
|
||||
<div class="spinner-border spinner-border-sm text-primary" role="status">
|
||||
<span class="sr-only">Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<span v-else-if="resolvingFields[index + key]">{{ resolvingFields[index + key] }}</span>
|
||||
<span v-else>{{ formatFieldValue(position[key], field) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<button @click="editEntry(index)" class="btn btn-sm btn-primary">Editieren</button>
|
||||
<button @click="deleteEntry(index)" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
<span v-else-if="resolvingFields[index + key]">{{ resolvingFields[index + key] }}</span>
|
||||
<span v-else>{{ formatFieldValue(position[key], field) }}</span>
|
||||
</td>
|
||||
<td>
|
||||
<select v-model="position._group" @change="position._group = $event">
|
||||
<option v-for="group in allGroups" :value="group">{{ group }}</option>
|
||||
</select>
|
||||
<button @click="editEntry(index)" class="btn btn-sm btn-primary">Editieren</button>
|
||||
<button @click="deleteEntry(index)" class="btn btn-sm btn-danger">Löschen</button>
|
||||
</td>
|
||||
</tr>
|
||||
</template>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
@@ -110,6 +171,10 @@ Vue.component('tt-positions-manager', {
|
||||
this.$emit('input', this.positions);
|
||||
this.resetForm();
|
||||
},
|
||||
addGroup() {
|
||||
this.positions.push({_group: this.groupName});
|
||||
this.groupName = '';
|
||||
},
|
||||
editEntry(index) {
|
||||
this.selectedIndex = index;
|
||||
this.formData = {...this.positions[index]};
|
||||
@@ -133,7 +198,7 @@ Vue.component('tt-positions-manager', {
|
||||
this.$set(this.resolvingFields, i + key, true);
|
||||
const textValue = await this.config.fields[key].customFieldResolver(this.positions[i][key]);
|
||||
this.$set(this.resolvingFields, i + key, textValue);
|
||||
} else if (this.config.fields[key].customFieldReference) {
|
||||
} else if (this.config.fields[key].customFieldReference && this.positions[i][key]) {
|
||||
this.$set(this.resolvingFields, i + key, true);
|
||||
if (this.config.fields[key].customFieldReference) {
|
||||
const entry = await axios.get(window.TT_CONFIG['BASE_PATH'] +
|
||||
@@ -153,7 +218,21 @@ Vue.component('tt-positions-manager', {
|
||||
created() {
|
||||
if (this.config.customMethods) Object.assign(this, this.config.customMethods);
|
||||
},
|
||||
watch: {
|
||||
computed: {
|
||||
groupedPositions() {
|
||||
const groups = {};
|
||||
for (const position of this.positions) {
|
||||
const group = position._group ?? 'Keine Gruppe';
|
||||
if (!groups[group]) groups[group] = [];
|
||||
if (Object.keys(position).length !== 1) groups[group].push(position);
|
||||
}
|
||||
return groups;
|
||||
},
|
||||
allGroups() {
|
||||
return Object.keys(this.groupedPositions);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
positions: {
|
||||
handler() {
|
||||
this.resolveFields().then();
|
||||
|
||||
Reference in New Issue
Block a user