diff --git a/frontend/app.vue b/frontend/app.vue
index 2a84181..4a28cd3 100644
--- a/frontend/app.vue
+++ b/frontend/app.vue
@@ -1,5 +1,6 @@
-
+
diff --git a/frontend/components/EntityModalButtons.vue b/frontend/components/EntityModalButtons.vue
index b754b05..726cd04 100644
--- a/frontend/components/EntityModalButtons.vue
+++ b/frontend/components/EntityModalButtons.vue
@@ -39,7 +39,9 @@ const modal = useModal()
-
\ No newline at end of file
+
diff --git a/frontend/components/EntityShowSubCreatedDocuments.vue b/frontend/components/EntityShowSubCreatedDocuments.vue
index ff8c53d..6593399 100644
--- a/frontend/components/EntityShowSubCreatedDocuments.vue
+++ b/frontend/components/EntityShowSubCreatedDocuments.vue
@@ -255,9 +255,14 @@ const selectItem = (item) => {
class="w-full"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
:on-select="(row) => selectItem(row.original)"
- :empty="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Belege anzuzeigen' }"
style="height: 70vh"
>
+
+
+
+ Keine Belege anzuzeigen
+
+
{{ dataStore.documentTypesForCreation[row.original.type].labelSingle }}
diff --git a/frontend/components/EntityShowSubOwnAccountsStatements.vue b/frontend/components/EntityShowSubOwnAccountsStatements.vue
index 62657a9..00b4d66 100644
--- a/frontend/components/EntityShowSubOwnAccountsStatements.vue
+++ b/frontend/components/EntityShowSubOwnAccountsStatements.vue
@@ -1,7 +1,7 @@
-
-
- {{useCurrency(row.original.amount)}}
- {{useCurrency(row.original.amount)}}
- {{useCurrency(row.original.amount)}}
-
-
- {{row.original.date ? dayjs(row.original.date).format('DD.MM.YYYY') : ''}}
-
-
- {{row.original.description ? row.original.description : ''}}
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Einnahmen
+ {{ currency(totals.income) }}
+
+
+
+ Ausgaben
+ {{ currency(totals.expenses) }}
+
+
+
+ Saldo
+ {{ currency(totals.balance) }}
+
+
+
+
+
+
+
+
+
Keine Buchungen im ausgewaehlten Zeitraum
+
+
+
+
+ {{ useCurrency(row.original.amount) }}
+ {{ useCurrency(row.original.amount) }}
+ {{ useCurrency(row.original.amount) }}
+
+
+
+ {{ row.original.bankstatement.date && dayjs(row.original.bankstatement.date).isValid() ? dayjs(row.original.bankstatement.date).format('DD.MM.YYYY') : '-' }}
+
+
+
+ {{ hasContent(row.original.partner) ? row.original.partner : '-' }}
+
+
+
+
+ {{ hasContent(row.original.description) ? row.original.description : '-' }}
+
+
+
+
+
+
+
-
-
-
diff --git a/frontend/components/EntityShowSubTimes.vue b/frontend/components/EntityShowSubTimes.vue
index 112250b..f0834d2 100644
--- a/frontend/components/EntityShowSubTimes.vue
+++ b/frontend/components/EntityShowSubTimes.vue
@@ -69,8 +69,13 @@ const columns = [
class="mt-3"
:columns="normalizeTableColumns(columns)"
:data="props.item.times"
- :empty="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Noch keine Einträge' }"
>
+
+
+
+ Noch keine Einträge
+
+
{
:icon="labelPrinter.connected ? 'i-heroicons-printer' : 'i-heroicons-printer'"
:color="labelPrinter.connected ? 'green' : ''"
variant="soft"
- class="w-full justify-start"
+ class="w-full justify-start rounded-lg px-2.5 py-2 transition-colors hover:bg-gray-100 dark:hover:bg-gray-800"
:loading="labelPrinter.connectLoading"
@click="handleClick"
>
diff --git a/frontend/components/MainNav.vue b/frontend/components/MainNav.vue
index 295f518..bfd5f6e 100644
--- a/frontend/components/MainNav.vue
+++ b/frontend/components/MainNav.vue
@@ -141,6 +141,11 @@ const links = computed(() => {
to: "/accounting/tax",
icon: "i-heroicons-calculator",
} : null,
+ (featureEnabled("createDocument") || featureEnabled("incomingInvoices") || featureEnabled("accounts") || featureEnabled("ownaccounts")) ? {
+ label: "BWA",
+ to: "/accounting/bwa",
+ icon: "i-heroicons-chart-bar-square",
+ } : null,
featureEnabled("costcentres") ? {
label: "Kostenstellen",
to: "/standardEntity/costcentres",
diff --git a/frontend/components/UCalendar.vue b/frontend/components/UCalendar.vue
new file mode 100644
index 0000000..8f0cd53
--- /dev/null
+++ b/frontend/components/UCalendar.vue
@@ -0,0 +1,166 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ headingValue }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ day }}
+
+
+
+
+
+
+
+
+
+
+ {{ weekDate.day }}
+
+
+
+
+
+
+
+
+
diff --git a/frontend/components/UDashboardNavbar.vue b/frontend/components/UDashboardNavbar.vue
new file mode 100644
index 0000000..9944daa
--- /dev/null
+++ b/frontend/components/UDashboardNavbar.vue
@@ -0,0 +1,94 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ title }}
+
+ {{ badge }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/components/UserDropdown.vue b/frontend/components/UserDropdown.vue
index c5e7aac..9472a84 100644
--- a/frontend/components/UserDropdown.vue
+++ b/frontend/components/UserDropdown.vue
@@ -28,16 +28,16 @@ const userItems = computed(() => [[
-
+
+
{{ auth.user.email }}
-
-
-
+
+
diff --git a/frontend/components/costcentreDisplay.vue b/frontend/components/costcentreDisplay.vue
index d3adf6d..5c8beec 100644
--- a/frontend/components/costcentreDisplay.vue
+++ b/frontend/components/costcentreDisplay.vue
@@ -1,26 +1,205 @@
- {{props.item}}
- {{incomingInvoices}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Netto gesamt
+ {{ currency(totals.net) }}
+
+
+
+ Steuer gesamt
+ {{ currency(totals.tax) }}
+
+
+
+ Brutto gesamt
+ {{ currency(totals.gross) }}
+
+
+
+
+
+ {{ row.original.reference }}
+
+
+
+ {{ row.original.date ? dayjs(row.original.date).format("DD.MM.YYYY") : "-" }}
+
+
+
+ {{ row.original.vendorName }}
+
+
+
+ {{ row.original.accountLabel }}
+
+
+
+
+ {{ row.original.description }}
+
+
+
+
+ {{ currency(row.original.amountNet) }}
+
+
+
+ {{ currency(row.original.amountTax) }}
+
+
+
+ {{ currency(row.original.amountGross) }}
+
+
+
+
+
-
-
diff --git a/frontend/components/materialComposing.vue b/frontend/components/materialComposing.vue
index 46662bc..55ec12a 100644
--- a/frontend/components/materialComposing.vue
+++ b/frontend/components/materialComposing.vue
@@ -72,18 +72,26 @@ const setRowData = (row) => {
+ Artikel
-
-
- | Artikel |
- Menge |
- Einheit |
- Verkaufspreis |
-
-
-
+
+
+
+
+ | Artikel |
+ Menge |
+ Einheit |
+ Verkaufspreis |
+ |
+
+
+
+
+ |
{
:filter-fields="['name']"
v-model="product.product"
:color="product.product ? 'primary' : 'error'"
- @change="setRowData(product)"
+ @update:model-value="setRowData(product)"
>
- {{products.find(i => i.id === product.product) ? products.find(i => i.id === product.product).name : 'Kein Artikel ausgewählt'}}
+ {{ products.find(i => i.id === product.product)?.name || 'Kein Artikel ausgewählt' }}
|
-
+ |
|
-
+ |
+ >
+
+ {{ units.find(i => i.id === product.unit)?.name || 'Einheit wählen' }}
+
+
|
-
+ |
|
-
+ |
{
color="error"
/>
|
-
-
+ |
+
+
+
diff --git a/frontend/components/personalComposing.vue b/frontend/components/personalComposing.vue
index 28398dc..fe725de 100644
--- a/frontend/components/personalComposing.vue
+++ b/frontend/components/personalComposing.vue
@@ -73,19 +73,27 @@ const setRowData = (row) => {
+ Stundensatz
-
-
- | Name |
- Menge |
- Einheit |
- Einkaufpreis |
- Verkaufspreis |
-
-
-
+
+
+
+
+ | Name |
+ Menge |
+ Einheit |
+ Einkaufspreis |
+ Verkaufspreis |
+ |
+
+
+
+
+ |
{
:filter-fields="['name']"
v-model="row.hourrate"
:color="row.hourrate ? 'primary' : 'error'"
- @change="setRowData(row)"
+ @update:model-value="setRowData(row)"
>
-
+
+ {{ hourrates.find(i => i.id === row.hourrate)?.name || 'Kein Stundensatz ausgewählt' }}
+
|
-
+ |
|
-
+ |
+ >
+
+ {{ units.find(i => i.id === row.unit)?.name || 'Einheit' }}
+
+
|
-
+ |
|
-
+ |
|
-
+ |
{
color="error"
/>
|
-
-
+ |
+
+
+
diff --git a/frontend/layouts/default.vue b/frontend/layouts/default.vue
index 6281786..1f354af 100644
--- a/frontend/layouts/default.vue
+++ b/frontend/layouts/default.vue
@@ -270,7 +270,7 @@ onMounted(() => {
-
+
@@ -284,7 +284,7 @@ onMounted(() => {
:key="item.label"
color="gray"
variant="ghost"
- class="w-full"
+ class="w-full min-w-0 justify-start rounded-lg px-2.5 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-800"
:icon="item.icon"
@click="item.click ? item.click() : null"
>
@@ -305,10 +305,10 @@ onMounted(() => {
-
+
-
+
diff --git a/frontend/pages/accounting/bwa.vue b/frontend/pages/accounting/bwa.vue
new file mode 100644
index 0000000..e5637d4
--- /dev/null
+++ b/frontend/pages/accounting/bwa.vue
@@ -0,0 +1,545 @@
+
+
+
+
+
+
+ Aktualisieren
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Einnahmen netto
+ {{ useCurrency(incomeTotal) }}
+
+ {{ filteredDocuments.length }} gebuchte Ausgangsbelege
+
+
+
+
+ Ausgaben netto
+ {{ useCurrency(expenseNetTotal) }}
+
+ Brutto: {{ useCurrency(expenseGrossTotal) }}
+
+
+
+
+ Betriebsergebnis
+
+ {{ useCurrency(operatingResult) }}
+
+
+ Einnahmen minus Ausgaben netto
+
+
+
+
+ USt-Saldo
+
+ {{ useCurrency(taxSummary.balance) }}
+
+
+ USt {{ useCurrency(taxSummary.outputTax) }} | Vorsteuer {{ useCurrency(taxSummary.inputTax) }}
+
+
+
+
+
+
+
+ USt-Details
+
+
+
+
+ Netto 19% Ausgangsbelege
+ {{ useCurrency(taxSummary.output.net19) }}
+
+
+ USt 19%
+ {{ useCurrency(taxSummary.output.tax19) }}
+
+
+ Netto 7% Ausgangsbelege
+ {{ useCurrency(taxSummary.output.net7) }}
+
+
+ USt 7%
+ {{ useCurrency(taxSummary.output.tax7) }}
+
+
+ Steuerfrei
+ {{ useCurrency(taxSummary.output.net0 + taxSummary.input.net0) }}
+
+
+
+
+
+
+ Vorsteuer-Details
+
+
+
+
+ Netto 19% Eingangsbelege
+ {{ useCurrency(taxSummary.input.net19) }}
+
+
+ Vorsteuer 19%
+ {{ useCurrency(taxSummary.input.tax19) }}
+
+
+ Netto 7% Eingangsbelege
+ {{ useCurrency(taxSummary.input.net7) }}
+
+
+ Vorsteuer 7%
+ {{ useCurrency(taxSummary.input.tax7) }}
+
+
+ Steuerfrei
+ {{ useCurrency(taxSummary.input.net0) }}
+
+
+
+
+
+
+
+
+
+ Buchungskonten
+ {{ accountRows.length }}
+
+
+
+
+
+
+
+
+
Keine Buchungskonten im ausgewaehlten Zeitraum
+
+
+
+
+ {{ row.original.label }}
+
+
+
+ {{ row.original.bookings }}
+
+
+
+ {{ useCurrency(row.original.net) }}
+
+
+
+ {{ useCurrency(row.original.tax) }}
+
+
+
+ {{ useCurrency(row.original.gross) }}
+
+
+
+
+
+
+
+
+ Eigene Buchungskonten
+ {{ ownAccountRows.length }}
+
+
+
+
+
+
+
+
+
Keine eigenen Buchungen im ausgewaehlten Zeitraum
+
+
+
+
+ {{ row.original.label }}
+
+
+
+ {{ row.original.bookings }}
+
+
+
+ {{ useCurrency(row.original.income) }}
+
+
+
+ {{ useCurrency(row.original.expenses) }}
+
+
+
+
+ {{ useCurrency(row.original.balance) }}
+
+
+
+
+
+
+
+
diff --git a/frontend/pages/accounts/index.vue b/frontend/pages/accounts/index.vue
index 52ec3ef..030297f 100644
--- a/frontend/pages/accounts/index.vue
+++ b/frontend/pages/accounts/index.vue
@@ -198,7 +198,7 @@ setupPage()
:columns="normalizeTableColumns(columns)"
class="w-full"
:ui="{ divide: 'divide-gray-200 dark:divide-gray-800' }"
- :on-select="(i) => router.push(`/accounts/show/${i.id}`)"
+ :on-select="(row) => router.push(`/accounts/show/${row.original.id}`)"
:empty="{ icon: 'i-heroicons-circle-stack-20-solid', label: 'Keine Buchungen anzuzeigen' }"
>
diff --git a/frontend/pages/accounts/show/[id].vue b/frontend/pages/accounts/show/[id].vue
index ea113b6..36ce142 100644
--- a/frontend/pages/accounts/show/[id].vue
+++ b/frontend/pages/accounts/show/[id].vue
@@ -1,62 +1,44 @@
@@ -29,60 +38,42 @@ const doLogin = async (data:any) => {
dark="/Logo_Dark.png"
/>
-
-
- Passwort vergessen?
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+ Passwort vergessen?
+
+
+
+
+
+ Weiter
+
+
+
+
+
diff --git a/frontend/pages/password-change.vue b/frontend/pages/password-change.vue
index 099b2c5..e2ae4b0 100644
--- a/frontend/pages/password-change.vue
+++ b/frontend/pages/password-change.vue
@@ -1,4 +1,6 @@
@@ -37,26 +45,39 @@ const doChange = async (data:any) => {
dark="/Logo_Dark.png"
/>
-
-
+
+
+
Passwort ändern
+
+ Geben Sie Ihr aktuelles und Ihr neues Passwort ein.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Ändern
+
+
+
-
\ No newline at end of file
+
diff --git a/frontend/pages/password-reset.vue b/frontend/pages/password-reset.vue
index 93db7f7..b1584f1 100644
--- a/frontend/pages/password-reset.vue
+++ b/frontend/pages/password-reset.vue
@@ -1,28 +1,34 @@
@@ -35,21 +41,29 @@ const doReset = async (data:any) => {
dark="/Logo_Dark.png"
/>
-
-
+
+
+
Passwort zurücksetzen
+
+ Geben Sie Ihre E-Mail ein um ein neues Passwort per E-Mail zu erhalten.
+
+
+
+
+
+
+
+
+
+ Zurücksetzen
+
+
+
-
\ No newline at end of file
+
diff --git a/frontend/pages/settings/tenant.vue b/frontend/pages/settings/tenant.vue
index 72e9545..850eba8 100644
--- a/frontend/pages/settings/tenant.vue
+++ b/frontend/pages/settings/tenant.vue
@@ -173,6 +173,8 @@ setupPage()
Die Dokubox ist eine E-Mail Inbox um deine Anhänge direkt als Dokumente zu importieren. Leite Deine E-Mails einfach an die folgende E-Mail Adresse weiter, diese ist für dein Unternehmen einzigartig. Die E-Mails werden dann alle 5 min abgerufen.
diff --git a/frontend/pages/standardEntity/[type]/index.vue b/frontend/pages/standardEntity/[type]/index.vue
index 6b43d78..f2d46ef 100644
--- a/frontend/pages/standardEntity/[type]/index.vue
+++ b/frontend/pages/standardEntity/[type]/index.vue
@@ -313,6 +313,20 @@ const truncateValue = (value, maxLength) => {
return `${stringValue.substring(0, maxLength)}...`
}
+const getDistinctFilterItems = (columnKey) => {
+ return (itemsMeta.value?.distinctValues?.[columnKey] || []).map((value) => ({
+ label: String(value),
+ value
+ }))
+}
+
+const isDistinctFilterActive = (columnKey) => {
+ const available = itemsMeta.value?.distinctValues?.[columnKey] || []
+ const selected = columnsToFilter.value[columnKey] || []
+
+ return selected.length > 0 && selected.length !== available.length
+}
+
@@ -371,7 +385,7 @@ const truncateValue = (value, maxLength) => {
v-model="pageLimit"
value-key="value"
label-key="value"
- @change="setupPage"
+ @update:model-value="setupPage"
/>
{
by="key"
:color="selectedColumns.length !== dataType.templateColumns.filter(i => !i.disabledInTable).length ? 'primary' : 'white'"
:content="{ width: 'min-w-max' }"
- @change="tempStore.modifyColumns(type,selectedColumns)"
+ @update:model-value="tempStore.modifyColumns(type, selectedColumns)"
>
Spalten
@@ -442,32 +456,26 @@ const truncateValue = (value, maxLength) => {
:text="!columnsToFilter[column.key]?.length > 0 ? `Keine Einträge für ${column.label} verfügbar` : `${column.label} Spalte nach Einträgen filtern`"
>
Keine Einträge in der Spalte {{column.label}}
-
+
{{ column.label }}
-
-
-
+
-
-
{