Das ShopBite Plugin bietet ein umfassendes Feiertagsmanagement-System, das speziell für Gastronomie- und Einzelhandelsbetriebe entwickelt wurde. Dieses Kapitel erklärt die detaillierte Konfiguration und Verwaltung von Feiertagen und Schließtagen.
Das Feiertagsmanagement-System ermöglicht:
CREATE TABLE `shopbite_holiday` (
`id` BINARY(16) NOT NULL,
`start` DATETIME(3) NOT NULL, -- Beginn der Schließung
`end` DATETIME(3) NOT NULL, -- Ende der Schließung
`sales_channel_id` BINARY(16) NOT NULL,
`name` VARCHAR(255) NULL, -- Name des Feiertags
`description` TEXT NULL, -- Beschreibung
`recurring` TINYINT(1) DEFAULT 0, -- Jährlich wiederholend
`created_at` DATETIME(3) NOT NULL,
`updated_at` DATETIME(3) NULL,
PRIMARY KEY (`id`),
KEY `fk.shopbite_holiday.sales_channel_id` (`sales_channel_id`),
CONSTRAINT `fk.shopbite_holiday.sales_channel_id`
FOREIGN KEY (`sales_channel_id`)
REFERENCES `sales_channel` (`id`)
ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
| Feld | Typ | Beschreibung | Beispiel |
|---|---|---|---|
| Name | Text | Name des Feiertags | "Weihnachten" |
| Startdatum | Datum/Zeit | Beginn der Schließung | 24.12.2024 18:00 |
| Enddatum | Datum/Zeit | Ende der Schließung | 26.12.2024 23:59 |
| Sales Channel | Dropdown | Vertriebskanal auswählen | "Mein Restaurant" |
| Jährlich wiederholen | Checkbox | Feiertag jährlich wiederholen | ✓ |
| Beschreibung | Textarea | Optional Beschreibung | "Weihnachtsferien - geschlossen" |
GET /store-api/shopbite/holiday
| Parameter | Typ | Beschreibung | Beispiel |
|---|---|---|---|
sales-channel-id | UUID | Filter nach Sales Channel | 019a36f224b0704fb6835914050392f4 |
from-date | Datum | Filter nach Startdatum | 2024-01-01 |
to-date | Datum | Filter nach Enddatum | 2024-12-31 |
include-recurring | Boolean | Wiederkehrende Feiertage einbeziehen | true |
curl -X GET "https://Ihre-Shopware-Domain.de/store-api/shopbite/holiday" \
-H "Authorization: Bearer IhrAPIToken" \
-H "sw-access-key: IhrAccessKey" \
-H "Accept: application/json"
{
"apiAlias": "shopbite_holiday",
"data": [
{
"id": "019a36f224b0704fb6835914050392f4",
"start": "2024-12-24T18:00:00+01:00",
"end": "2024-12-26T23:59:00+01:00",
"salesChannelId": "019a36f224b0704fb6835914050392f4",
"name": "Weihnachten",
"description": "Weihnachtsferien - geschlossen",
"recurring": false,
"createdAt": "2024-01-11T14:30:00+01:00",
"updatedAt": "2024-01-11T14:30:00+01:00",
"salesChannel": {
"id": "019a36f224b0704fb6835914050392f4",
"name": "Mein Restaurant",
"typeId": "019a36f224b0704fb6835914050392f4"
}
},
{
"id": "019a36f224b0704fb6835914050392f5",
"start": "2024-01-01T00:00:00+01:00",
"end": "2024-01-01T23:59:00+01:00",
"salesChannelId": "019a36f224b0704fb6835914050392f4",
"name": "Neujahr",
"description": "Geschlossen",
"recurring": true,
"createdAt": "2024-01-11T14:30:00+01:00",
"updatedAt": "2024-01-11T14:30:00+01:00",
"salesChannel": {
"id": "019a36f224b0704fb6835914050392f4",
"name": "Mein Restaurant",
"typeId": "019a36f224b0704fb6835914050392f4"
}
}
],
"total": 10
}
| Statuscode | Bedeutung | Lösung |
|---|---|---|
| 200 | Erfolg | Daten erfolgreich abgerufen |
| 401 | Unauthorized | API-Zugangsdaten prüfen |
| 403 | Forbidden | Berechtigungen prüfen |
| 404 | Not Found | Endpunkt oder Sales Channel nicht gefunden |
| 500 | Internal Server Error | Server-Logs prüfen |
Wiederkehrende Feiertage werden automatisch für jedes Jahr neu erstellt:
| Feld | Typ | Beschreibung | Beispiel |
|---|---|---|---|
| Name | Text | Name des Feiertags | "Weihnachten" |
| Monat | Dropdown | Monat auswählen | Dezember |
| Tag | Zahl | Tag im Monat | 25 |
| Startzeit | Zeit | Beginn der Schließung | 18:00 |
| Endzeit | Zeit | Ende der Schließung | 23:59 |
| Sales Channel | Dropdown | Vertriebskanal auswählen | "Mein Restaurant" |
| Beschreibung | Textarea | Optional Beschreibung | "Weihnachtsferien" |
curl -X GET "https://Ihre-Shopware-Domain.de/store-api/shopbite/holiday?include-recurring=true" \
-H "Authorization: Bearer IhrAPIToken" \
-H "sw-access-key: IhrAccessKey"
-- Indizes für bessere Performance
CREATE INDEX `idx_sales_channel` ON `shopbite_holiday` (`sales_channel_id`);
CREATE INDEX `idx_date_range` ON `shopbite_holiday` (`start`, `end`);
CREATE INDEX `idx_recurring` ON `shopbite_holiday` (`recurring`);
# In config/packages/cache.yaml
framework:
cache:
pools:
shopbite.holidays:
adapter: cache.adapter.redis
default_lifetime: 86400 # 24 Stunden Cache
Richten Sie Benachrichtigungen für anstehende Feiertage ein:
// In einem Cron-Job oder Event-Listener
$upcomingHolidays = $holidayRepository->getUpcomingHolidays(7); // Nächste 7 Tage
foreach ($upcomingHolidays as $holiday) {
$mailer->sendHolidayReminder($holiday);
}
// Feiertage abrufen
async function fetchHolidays(salesChannelId, fromDate, toDate) {
const params = new URLSearchParams({
'sales-channel-id': salesChannelId,
'from-date': fromDate,
'to-date': toDate
});
const response = await fetch(
`/store-api/shopbite/holiday?${params.toString()}`,
{
headers: {
'Authorization': `Bearer ${apiToken}`,
'sw-access-key': accessKey
}
}
);
if (!response.ok) {
throw new Error('Failed to fetch holidays');
}
return await response.json();
}
// Feiertage anzeigen
function displayHolidays(holidays) {
holidays.data.forEach(holiday => {
const start = new Date(holiday.start);
const end = new Date(holiday.end);
console.log(`${holiday.name}: ${start.toLocaleDateString()} - ${end.toLocaleDateString()}`);
console.log(`Beschreibung: ${holiday.description || 'Keine Beschreibung'}`);
});
}
// Beispielaufruf
const today = new Date().toISOString().split('T')[0];
const nextYear = new Date();
nextYear.setFullYear(nextYear.getFullYear() + 1);
const nextYearEnd = nextYear.toISOString().split('T')[0];
fetchHolidays('019a36f224b0704fb6835914050392f4', today, nextYearEnd)
.then(displayHolidays)
.catch(console.error);
<template>
<div class="holidays">
<h3>Feiertage und Schließtage</h3>
<div v-for="holiday in holidays" :key="holiday.id" class="holiday-item">
<div class="holiday-header">
<span class="holiday-name">{{ holiday.name }}</span>
<span v-if="holiday.recurring" class="badge recurring">Jährlich</span>
</div>
<div class="holiday-dates">
{{ formatDate(holiday.start) }} - {{ formatDate(holiday.end) }}
</div>
<div v-if="holiday.description" class="holiday-description">
{{ holiday.description }}
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
holidays: [],
loading: false,
error: null
};
},
async mounted() {
await this.fetchHolidays();
},
methods: {
formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString('de-DE', {
weekday: 'short',
day: 'numeric',
month: 'short',
year: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
},
async fetchHolidays() {
this.loading = true;
this.error = null;
try {
const response = await this.$axios.get('/store-api/shopbite/holiday');
this.holidays = response.data.data;
} catch (error) {
console.error('Failed to fetch holidays:', error);
this.error = 'Feiertage konnten nicht geladen werden.';
} finally {
this.loading = false;
}
}
}
};
</script>
<style scoped>
.holidays {
margin: 20px 0;
padding: 15px;
background: #fff5f5;
border-radius: 8px;
border: 1px solid #ffebee;
}
.holiday-item {
padding: 12px 0;
border-bottom: 1px solid #ffcdcd;
}
.holiday-item:last-child {
border-bottom: none;
}
.holiday-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 4px;
}
.holiday-name {
font-weight: bold;
color: #d32f2f;
}
.badge {
padding: 2px 6px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
}
.badge.recurring {
background: #ffeb3b;
color: #000;
}
.holiday-dates {
color: #b71c1c;
font-size: 14px;
margin-bottom: 4px;
}
.holiday-description {
color: #666;
font-size: 13px;
font-style: italic;
}
</style>
Symptome:
Lösungen:
# Feiertagsdaten prüfen
mysql -u shopware -p shopware -e "SELECT * FROM shopbite_holiday;"
# Zeitformat prüfen
bin/console database:check-timezone
# API-Abfrage testen
curl -X GET "https://Ihre-Domain.de/store-api/shopbite/holiday" -H "Authorization: Bearer IhrToken"
Symptome:
Lösungen:
# Cron-Job prüfen
crontab -l
# Manuell ausführen
bin/console shopbite:holidays:generate-recurring
# Logs prüfen
tail -n 50 /var/log/shopware/prod.log | grep holiday
Symptome:
Lösungen:
# Überlappungen prüfen
mysql -u shopware -p shopware -e "
SELECT * FROM shopbite_holiday
WHERE start < (SELECT end FROM shopbite_holiday WHERE id != shopbite_holiday.id)
AND end > (SELECT start FROM shopbite_holiday WHERE id != shopbite_holiday.id);"
# Validierung aktivieren
bin/console config:set ShopBitePlugin.config.validateHolidayOverlaps true