added new create from calendar feature

This commit is contained in:
2025-08-14 07:34:18 +02:00
parent 060a6300ed
commit 58b53f1404
2 changed files with 155 additions and 19 deletions

View File

@@ -671,6 +671,74 @@ class WarehouseShippingNoteController extends TTCrud {
}
}
protected function getRecentCalendarEventsAction()
{
$worker = UserModel::getOne($this->user->id);
if (!$worker || !empty($worker->name)) {
die($worker->name);
self::returnJson([]);
return;
}
$calendars = CalendarModel::getAll();
// loop through all calendars and find the one with user_id as the worker's id
$calendarId = null;
foreach ($calendars as $calendar) {
if ($calendar->user_id == $worker->id) {
$calendarId = $calendar->go_calendar_id;
break;
}
}
$eventsJson = CalendarModel::getCalendarEvents($this->user);
$allEvents = json_decode($eventsJson, true)['data'] ?? [];
if (!is_array($allEvents)) {
self::returnJson([]);
return;
}
$endDate = new DateTime();
$startDate = (new DateTime())->modify('-3 days');
$startTimestamp = $startDate->setTime(0, 0, 0)->getTimestamp();
$endTimestamp = $endDate->setTime(23, 59, 59)->getTimestamp();
$filteredEvents = array_filter($allEvents, function ($event) use ($startTimestamp, $endTimestamp, $calendarId) {
if (!isset($event['cstart']) && !isset($event['category']) || (intval($event['calendar_id']['calendar_id']) !== $calendarId)) {
return false;
}
$eventStartTimestamp = strtotime($event['cstart']['cstart'] ?? $event['cstart']);
if (empty($event['location']['location']) || empty($event['category']['category'])) {
return false;
}
if (date('H', $eventStartTimestamp) < 5 || date('H', $eventStartTimestamp) > 21) {
return false;
}
return $eventStartTimestamp >= $startTimestamp && $eventStartTimestamp <= $endTimestamp;
});
usort($filteredEvents, function ($a, $b) {
$timeA = strtotime($a['cstart']['cstart'] ?? $a['cstart']);
$timeB = strtotime($b['cstart']['cstart'] ?? $b['cstart']);
return $timeB <=> $timeA;
});
$limitedEvents = array_slice($filteredEvents, 0, 20);
$finalResponse = array_map(function ($event) {
$eventStart = $event['cstart']['cstart'] ?? $event['cstart'];
return [
'date' => date('Y-m-d H:i:s', strtotime($eventStart)),
'location' => $event['location']['location'] ?? '',
'category' => $event['category']['category'] ?? ''
];
}, $limitedEvents);
self::returnJson($finalResponse);
}
protected function createNewLogAction() {
$postData = json_decode(file_get_contents('php://input'), true);

View File

@@ -420,33 +420,53 @@ Vue.component('warehouse-shipping-note', {
@close="shippingNoteModalId = null;$refs.table.$refs.table.refreshTable()"
@open-article-modal="articleModalId = true;window.console.log($event)"
@open-signing-modal="signingShippingNoteId = $event"/>
<warehouse-article-modal
v-if="articleModalId"
:id="articleModalId"
<warehouse-article-modal
v-if="articleModalId"
:id="articleModalId"
@close="articleModalId = null"
@article-selected="$refs.modal.$refs.positionsManager.updateField('article', $event.id);"/>
<warehouse-history-modal :show.sync="historyModal" :id="historyModalId"/>
<warehouse-shipping-note-signature-pad v-if="signingShippingNoteId" :shipping-note-id="signingShippingNoteId"
@close="signingShippingNoteId = null;shippingNoteModalId = null;$refs.table.$refs.table.refreshTable()"/>
<add-log-modal-sn v-if="addLogModalId" :shipping-note-id="addLogModalId" @close="addLogModalId = null"/>
<button @click="shippingNoteModalId = 'create'" class="btn btn-primary">Lieferschein erstellen</button>
<div class="dropdown" style="display: inline-block; margin-left: 10px;"
v-if="window.TT_CONFIG['WAREHOUSE_ADMIN'] === '1'">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Durchschau-Modus
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" style="cursor: pointer;">
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'new'">Neue</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'in_progress'">In Bearbeitung</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'accepted'">Akzeptierte</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'on_hold'">On Hold</a>
<div class="mb-3">
<button @click="shippingNoteModalId = 'create'" class="btn btn-primary">Lieferschein erstellen</button>
<div class="dropdown" style="display: inline-block; margin-left: 10px;">
<button class="btn btn-info dropdown-toggle" type="button" @click.stop="showCalendarDropdown = !showCalendarDropdown">
Aus Kalendereintrag erstellen
</button>
<div class="dropdown-menu" :class="{'show': showCalendarDropdown}" style="cursor: pointer; max-height: 500px; overflow-y: auto;">
<a v-if="!calendarEvents.length" class="dropdown-item disabled">Lade Termine...</a>
<a v-for="event in calendarEvents" class="dropdown-item" @click="createFromEvent(event)">
<div style="white-space: normal;">
<strong>{{ event.category }}</strong><br>
<small>{{ event.location }}</small><br>
<small class="text-muted">{{ formatEventDate(event.date) }}</small>
</div>
</a>
</div>
</div>
<div class="dropdown" style="display: inline-block; margin-left: 10px;"
v-if="window.TT_CONFIG['WAREHOUSE_ADMIN'] === '1'">
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown"
aria-haspopup="true" aria-expanded="false">
Durchschau-Modus
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton" style="cursor: pointer;">
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'new'">Neue</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'in_progress'">In Bearbeitung</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'accepted'">Akzeptierte</a>
<a class="dropdown-item" @click="shippingNoteSeeThrough = 'on_hold'">On Hold</a>
</div>
</div>
</div>
<tt-table-crud emit-edit
@openHistory="historyModal = true; historyModalId = $event.id"
@print="window.open(window.TT_CONFIG['BASE_PATH'] + '/WarehouseShippingNote/createPDF?id=' + $event.id)"
@@ -468,7 +488,8 @@ Vue.component('warehouse-shipping-note', {
</tt-table-crud>
</tt-card>
`, data() {
`,
data() {
return {
window: window,
historyModal: false,
@@ -478,15 +499,62 @@ Vue.component('warehouse-shipping-note', {
addLogModalId: null,
shippingNoteSeeThrough: false,
articleModalId: null,
calendarEvents: [],
showCalendarDropdown: false,
}
},
mounted() {
// check if get parameter doAction = createNew is set, if so open the modal with 'create' as id
if (window.location.search.includes('doAction=createNew')) {
this.shippingNoteModalId = 'create';
}
this.fetchCalendarEvents();
document.addEventListener('click', this.closeDropdown);
},
beforeDestroy() {
document.removeEventListener('click', this.closeDropdown);
},
methods: {
async fetchCalendarEvents() {
try {
const response = await axios.get(window.TT_CONFIG.BASE_PATH + '/WarehouseShippingNote/getRecentCalendarEvents');
this.calendarEvents = response.data;
} catch (error) {
console.error("Could not fetch calendar events", error);
window.notify('error', 'Kalendereinträge konnten nicht geladen werden.');
}
},
formatEventDate(dateString) {
return window.moment(dateString).format('DD.MM.YYYY HH:mm');
},
async createFromEvent(event) {
this.showCalendarDropdown = false;
this.shippingNoteModalId = 'create';
await this.$nextTick(); // Wait for the modal component to be created
if (this.$refs.modal) {
// Parse address string
const locationParts = event.location.split(',');
const line = locationParts.slice(0, -1).join(',').trim();
const plzCityRaw = locationParts.slice(-1)[0].trim();
const plzMatch = plzCityRaw.match(/^(\d+)/);
const plz = plzMatch ? plzMatch[1] : '';
const city = plzCityRaw.replace(/^\d+\s*/, '').trim();
// Directly set the data in the modal's `shippingNote` object
const modalData = this.$refs.modal.shippingNote;
this.$set(modalData, 'deliveryAddressName', event.category);
this.$set(modalData, 'deliveryAddressLine', line);
this.$set(modalData, 'deliveryAddressPLZ', plz);
this.$set(modalData, 'deliveryAddressCity', city);
}
},
closeDropdown(event) {
if (!event.target.closest('.dropdown')) {
this.showCalendarDropdown = false;
}
},
async changeStatus(id, status) {
const response = await axios.post(window.TT_CONFIG.BASE_PATH + '/WarehouseShippingNote/changeStatus', {
id,