Merge branch 'feature/warehouse-improvement' into 'master'
added confirmation email for eshop See merge request fronk/thetool!626
This commit is contained in:
@@ -27,6 +27,7 @@ class WarehouseEShopOrderController extends TTCrud {
|
|||||||
|
|
||||||
protected array $additionalActions = [
|
protected array $additionalActions = [
|
||||||
['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'],
|
['key' => 'openHistory', 'title' => 'Historie', 'class' => 'fas fa-history text-primary'],
|
||||||
|
['key' => 'openSingleOrderEmail', 'title' => 'Bestellbestätigung', 'class' => 'fas fa-envelope text-primary'],
|
||||||
];
|
];
|
||||||
|
|
||||||
protected array $infoMessages = [
|
protected array $infoMessages = [
|
||||||
@@ -48,6 +49,50 @@ class WarehouseEShopOrderController extends TTCrud {
|
|||||||
$this->columns[8]['modal']['items'] = $users;
|
$this->columns[8]['modal']['items'] = $users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function singleOrderEmailAction() {
|
||||||
|
// this has dryRun and id in get parameter create a E-Mail Body like the things below
|
||||||
|
$isDryRun = $this->request->dryRun ?? false;
|
||||||
|
$id = $this->request->id;
|
||||||
|
|
||||||
|
$order = WarehouseEShopOrderModel::get($id);
|
||||||
|
$orderItems = WarehouseEShopOrderItemModel::getAll(['orderId' => $id]);
|
||||||
|
$articles = WarehouseArticleModel::getAll();
|
||||||
|
$articlePackets = WarehouseArticlePacketModel::getAll();
|
||||||
|
|
||||||
|
$paddedId = str_pad($id, 3, '0', STR_PAD_LEFT);
|
||||||
|
$body = "Bestellung #$paddedId\n\n";
|
||||||
|
$body .= "Lieferadresse:\n";
|
||||||
|
$body .= $order->deliveryAddressName . "\n";
|
||||||
|
$body .= $order->deliveryAddressLine . "\n";
|
||||||
|
$body .= $order->deliveryAddressPLZ . ' ' . $order->deliveryAddressCity . "\n\n";
|
||||||
|
$body .= "Bestellte Artikel:\n";
|
||||||
|
foreach ($orderItems as $item) {
|
||||||
|
$article = $item->articleId ? array_search($item->articleId, array_column($articles, 'id')) : null;
|
||||||
|
$articlePacket = $item->articlePacketId ? array_search($item->articlePacketId, array_column($articlePackets, 'id')) : null;
|
||||||
|
|
||||||
|
$articleTitle = $item->articleId ? $articles[$article]->title : $articlePackets[$articlePacket]->title;
|
||||||
|
$quantity = $item->quantity;
|
||||||
|
$body .= "$quantity x $articleTitle\n";
|
||||||
|
}
|
||||||
|
$body .= "\n\n";
|
||||||
|
$body .= "CSV der Bestellung ist im Anhang.\n\n";
|
||||||
|
$body .= "XINON GmbH\nFladnitz im Raabtal 150\n8322 Studenzen\n";
|
||||||
|
|
||||||
|
if ($isDryRun) {
|
||||||
|
self::returnJson(['success' => true, 'message' => 'E-Mail Body wurde erstellt', 'body' => $body]);
|
||||||
|
} else {
|
||||||
|
$email = new Emailnotification();
|
||||||
|
$email->setSubject("Bestellbestätigung Bestellung #$paddedId");
|
||||||
|
$email->setBody($body);
|
||||||
|
$email->setFrom(TT_OUTGOING_EMAIL_2FA, TT_OUTGOING_EMAIL_2FA);
|
||||||
|
// $email->setTo('ftth-versand@triotronik.com');
|
||||||
|
$email->setTo('luca.haid@xinon.eu');
|
||||||
|
$csvContent = $this->CSVExportNewOrdersMarkAcceptedAction(true, [$id]);
|
||||||
|
$email->addAttachment(null, $csvContent, "Bestellung_$paddedId.csv", "text/csv");
|
||||||
|
self::returnJson(['success' => true, 'message' => 'E-Mail wurde versendet']);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected function getAllOrderItemsPerOrder(): array {
|
protected function getAllOrderItemsPerOrder(): array {
|
||||||
$items = WarehouseEShopOrderItemModel::getAll();
|
$items = WarehouseEShopOrderItemModel::getAll();
|
||||||
$articles = WarehouseArticleModel::getAll();
|
$articles = WarehouseArticleModel::getAll();
|
||||||
@@ -146,13 +191,14 @@ class WarehouseEShopOrderController extends TTCrud {
|
|||||||
|
|
||||||
$user = UserModel::getOne($json['createBy']);
|
$user = UserModel::getOne($json['createBy']);
|
||||||
|
|
||||||
|
foreach (["office@xinon.at", $user->email] as $emailAddr) {
|
||||||
$email = new Emailnotification();
|
$email = new Emailnotification();
|
||||||
$email->setSubject("Bestellbestätigung Bestellung #$subjectId");
|
$email->setSubject("Bestellbestätigung Bestellung #$subjectId");
|
||||||
$email->setBody($body);
|
$email->setBody($body);
|
||||||
$email->setFrom(TT_OUTGOING_EMAIL_2FA, TT_OUTGOING_EMAIL_2FA);
|
$email->setFrom(TT_OUTGOING_EMAIL_2FA, TT_OUTGOING_EMAIL_2FA);
|
||||||
$email->setTo($user->email);
|
$email->setTo($emailAddr);
|
||||||
$email->send();
|
$email->send();
|
||||||
|
}
|
||||||
|
|
||||||
self::returnJson(['success' => true,
|
self::returnJson(['success' => true,
|
||||||
'message' => $this->infoMessages['create'],
|
'message' => $this->infoMessages['create'],
|
||||||
@@ -162,12 +208,18 @@ class WarehouseEShopOrderController extends TTCrud {
|
|||||||
die(json_encode($json));
|
die(json_encode($json));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function CSVExportNewOrdersMarkAcceptedAction() {
|
protected function CSVExportNewOrdersMarkAcceptedAction($returnCSV = false, $orderIds = []) {
|
||||||
$orders = WarehouseEShopOrderModel::getAll(['status' => 'new']);
|
$orders = WarehouseEShopOrderModel::getAll(['status' => 'new']);
|
||||||
$orders = array_map(function($order) {
|
$orders = array_map(function($order) {
|
||||||
return (array) $order;
|
return (array) $order;
|
||||||
}, $orders);
|
}, $orders);
|
||||||
|
|
||||||
|
if (!empty($orderIds)) {
|
||||||
|
$orders = array_filter($orders, function($order) use ($orderIds) {
|
||||||
|
return in_array($order['id'], $orderIds);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
if (empty($orders)) {
|
if (empty($orders)) {
|
||||||
self::returnJson(['success' => false, 'message' => 'Keine neuen Bestellungen']);
|
self::returnJson(['success' => false, 'message' => 'Keine neuen Bestellungen']);
|
||||||
die();
|
die();
|
||||||
@@ -210,6 +262,10 @@ class WarehouseEShopOrderController extends TTCrud {
|
|||||||
WarehouseEShopOrderModel::update($order);
|
WarehouseEShopOrderModel::update($order);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($returnCSV) {
|
||||||
|
return Helper::arrayToCsv($rows);
|
||||||
|
}
|
||||||
|
|
||||||
self::returnJson($rows);
|
self::returnJson($rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,5 +135,26 @@ class Helper {
|
|||||||
$controller->layout()->setTemplate("VueViews/Vue");
|
$controller->layout()->setTemplate("VueViews/Vue");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts an array of objects to a CSV file.
|
||||||
|
* @param array $rows The array of objects to convert to CSV.
|
||||||
|
* @return string The CSV file content.
|
||||||
|
*/
|
||||||
|
public static function arrayToCsv(array $rows): string {
|
||||||
|
$output = fopen('php://temp', 'w');
|
||||||
|
|
||||||
|
// Add headers
|
||||||
|
fputcsv($output, array_keys((array) $rows[0]));
|
||||||
|
|
||||||
|
// Add rows
|
||||||
|
foreach ($rows as $row) {
|
||||||
|
fputcsv($output, (array) $row);
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind($output);
|
||||||
|
$csv = stream_get_contents($output);
|
||||||
|
fclose($output);
|
||||||
|
|
||||||
|
return $csv;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -103,10 +103,10 @@ Vue.component('warehouse-e-shop', {
|
|||||||
const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/createOrder`, {
|
const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/createOrder`, {
|
||||||
shoppingCart: this.shoppingCart,
|
shoppingCart: this.shoppingCart,
|
||||||
deliveryMode: this.createOrderDialogData.deliveryMode,
|
deliveryMode: this.createOrderDialogData.deliveryMode,
|
||||||
deliveryAddressName: this.createOrderDialogData.deliveryAddressName,
|
deliveryAddressName: this.createOrderDialogData.deliveryAddressName.trim(),
|
||||||
deliveryAddressLine: this.createOrderDialogData.deliveryAddressLine,
|
deliveryAddressLine: this.createOrderDialogData.deliveryAddressLine.trim(),
|
||||||
deliveryAddressPLZ: this.createOrderDialogData.deliveryAddressPLZ,
|
deliveryAddressPLZ: this.createOrderDialogData.deliveryAddressPLZ.trim(),
|
||||||
deliveryAddressCity: this.createOrderDialogData.deliveryAddressCity,
|
deliveryAddressCity: this.createOrderDialogData.deliveryAddressCity.trim(),
|
||||||
});
|
});
|
||||||
if (response.data.success) {
|
if (response.data.success) {
|
||||||
this.window.notify('success', response.data.message || 'Erfolgreich gespeichert');
|
this.window.notify('success', response.data.message || 'Erfolgreich gespeichert');
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ Vue.component('warehouse-e-shop-order', {
|
|||||||
//language=Vue
|
//language=Vue
|
||||||
template: `
|
template: `
|
||||||
<tt-card>
|
<tt-card>
|
||||||
<tt-table-crud @openHistory="historyModal = true; historyModalId = $event.id" ref="table">
|
<tt-table-crud @openHistory="historyModal = true; historyModalId = $event.id"
|
||||||
|
@openSingleOrderEmail="openSingleOrderEmailModal = true; singleOrderEmailModalId = $event.id"
|
||||||
|
ref="table">
|
||||||
|
|
||||||
<template v-slot:table-top-buttons>
|
<template v-slot:table-top-buttons>
|
||||||
<button @click="createCSVExportAndMarkAsAccepted" type="button" class="btn btn-outline-success">
|
<button @click="createCSVExportAndMarkAsAccepted" type="button" class="btn btn-outline-success">
|
||||||
@@ -28,10 +30,29 @@ Vue.component('warehouse-e-shop-order', {
|
|||||||
|
|
||||||
</tt-table-crud>
|
</tt-table-crud>
|
||||||
<warehouse-history-modal :show.sync="historyModal" :id="historyModalId"/>
|
<warehouse-history-modal :show.sync="historyModal" :id="historyModalId"/>
|
||||||
|
|
||||||
|
<!-- add a tt-modal which just shows some text from the api to show a email for a single order-->
|
||||||
|
<tt-modal :show.sync="openSingleOrderEmailModal"
|
||||||
|
:title="'Email für Bestellung ' + singleOrderEmailModalId"
|
||||||
|
@close="openSingleOrderEmailModal = false"
|
||||||
|
save-text="E-Mail senden"
|
||||||
|
@submit="sendSingleOrderEmail"
|
||||||
|
:delete="false"
|
||||||
|
>
|
||||||
|
<div v-if="singleOrderEmailModalId && singleOrderEmailModalText">
|
||||||
|
<p v-html="singleOrderEmailModalText.body.replaceAll('\\n', '<br>')"></p>
|
||||||
|
</div>
|
||||||
|
<!-- else show loader-->
|
||||||
|
<div v-else>
|
||||||
|
<tt-loader/>
|
||||||
|
</div>
|
||||||
|
</tt-modal>
|
||||||
|
|
||||||
|
|
||||||
</tt-card>
|
</tt-card>
|
||||||
`, data() {
|
`, data() {
|
||||||
return {
|
return {
|
||||||
window: window, historyModal: false, historyModalId: null, articleItems: null
|
window: window, historyModal: false, historyModalId: null, articleItems: null, openSingleOrderEmailModal: false, singleOrderEmailModalId: null, singleOrderEmailModalText: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@@ -40,11 +61,20 @@ Vue.component('warehouse-e-shop-order', {
|
|||||||
this.articleItems = response.data;
|
this.articleItems = response.data;
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async sendSingleOrderEmail() {
|
||||||
|
const response = await axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/singleOrderEmail?id=${this.singleOrderEmailModalId}`);
|
||||||
|
if (response.data.message) {
|
||||||
|
window.notify(response.data.success === true ? 'success' : 'error', response.data.message);
|
||||||
|
this.openSingleOrderEmailModal = false;
|
||||||
|
} else {
|
||||||
|
window.notify('error', 'Ein Fehler ist aufgetreten');
|
||||||
|
}
|
||||||
|
},
|
||||||
async createCSVExportAndMarkAsAccepted() {
|
async createCSVExportAndMarkAsAccepted() {
|
||||||
const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/CSVExportNewOrdersMarkAccepted`);
|
const response = await axios.post(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/CSVExportNewOrdersMarkAccepted`);
|
||||||
|
|
||||||
if (response.data.message) {
|
if (response.data.message) {
|
||||||
window.notify('info', response.data.message);
|
window.notify('success', response.data.message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,5 +107,16 @@ Vue.component('warehouse-e-shop-order', {
|
|||||||
|
|
||||||
await this.$refs.table.$refs.table.fetchData();
|
await this.$refs.table.$refs.table.fetchData();
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
singleOrderEmailModalId() {
|
||||||
|
this.openSingleOrderEmailModal = !!this.singleOrderEmailModalId;
|
||||||
|
this.singleOrderEmailModalText = null;
|
||||||
|
if (this.singleOrderEmailModalId) {
|
||||||
|
axios.get(`${window['TT_CONFIG']['BASE_PATH']}/WarehouseEShopOrder/singleOrderEmail?id=${this.singleOrderEmailModalId}&dryRun=true`)
|
||||||
|
.then(response => this.singleOrderEmailModalText = response.data)
|
||||||
|
.catch(error => window.notify('error', error.response?.data?.message || 'Ein Fehler ist aufgetreten'));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ Vue.component('tt-modal', {
|
|||||||
show: { type: Boolean, default: false },
|
show: { type: Boolean, default: false },
|
||||||
title: { type: String, default: 'Modal Title' },
|
title: { type: String, default: 'Modal Title' },
|
||||||
delete: { type: Boolean, default: true },
|
delete: { type: Boolean, default: true },
|
||||||
|
deleteText: { type: String, default: 'Delete' },
|
||||||
save: { type: Boolean, default: true },
|
save: { type: Boolean, default: true },
|
||||||
|
saveText: { type: String, default: 'Save' },
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
show(newVal) {
|
show(newVal) {
|
||||||
@@ -35,8 +37,8 @@ Vue.component('tt-modal', {
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<button v-if="save" class="btn btn-primary" @click="$emit('submit')">Save</button>
|
<button v-if="save" class="btn btn-primary" @click="$emit('submit')">{{saveText}}</button>
|
||||||
<button v-if="$props.delete" class="btn btn-danger" @click="$emit('delete')">Delete</button>
|
<button v-if="$props.delete" class="btn btn-danger" @click="$emit('delete')">{{deleteText}}</button>
|
||||||
<button class="btn btn-secondary" @click="$emit('update:show', false)">Close</button>
|
<button class="btn btn-secondary" @click="$emit('update:show', false)">Close</button>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user