32 Commits

Author SHA1 Message Date
468f8b51f6 Merge pull request 'dev' (#257) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 59s
Build and Release FEDEO / build-and-release (push) Successful in 6m52s
Reviewed-on: #257
2026-11-04 10:35:20 +00:00
d4c4a2b9c1 Merge pull request 'dev' (#255) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m4s
Build and Release FEDEO / build-and-release (push) Successful in 6m36s
Reviewed-on: #255
2026-10-29 17:20:58 +00:00
1b617c7910 Merge pull request 'dev' (#252) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m1s
Build and Release FEDEO / build-and-release (push) Successful in 6m34s
Reviewed-on: #252
2026-10-27 20:39:01 +00:00
9676a270da Merge pull request 'dev' (#251) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m7s
Build and Release FEDEO / build-and-release (push) Successful in 6m36s
Reviewed-on: #251
2026-10-25 13:17:14 +00:00
f3b4fac4c0 Merge pull request 'dev' (#247) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m2s
Build and Release FEDEO / build-and-release (push) Successful in 6m25s
Reviewed-on: #247
2026-10-15 16:47:32 +00:00
a8c6c2625c Merge pull request 'dev' (#242) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m6s
Build and Release FEDEO / build-and-release (push) Successful in 6m31s
Reviewed-on: #242
2026-10-13 16:18:53 +00:00
a2a1151ccb Merge pull request 'dev' (#241) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m5s
Build and Release FEDEO / build-and-release (push) Successful in 6m29s
Reviewed-on: #241
2026-10-07 17:11:45 +00:00
daaed01d02 Merge pull request 'dev' (#240) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 59s
Build and Release FEDEO / build-and-release (push) Successful in 6m16s
Reviewed-on: #240
2026-10-02 16:30:02 +00:00
e7d6c482ad Merge pull request 'dev' (#239) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 58s
Build and Release FEDEO / build-and-release (push) Successful in 6m13s
Reviewed-on: #239
2026-10-02 15:17:16 +00:00
ed305f656c Merge pull request 'dev' (#238) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 57s
Build and Release FEDEO / build-and-release (push) Successful in 6m14s
Reviewed-on: #238
2026-10-02 14:18:01 +00:00
30e932a874 Merge pull request 'dev' (#237) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 58s
Build and Release FEDEO / build-and-release (push) Successful in 6m16s
Reviewed-on: #237
2026-10-02 12:51:46 +00:00
0a74e07288 Merge pull request 'fix(scanner): accept Epson empty write probes' (#234) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 58s
Build and Release FEDEO / build-and-release (push) Successful in 6m8s
Reviewed-on: #234
2026-10-01 15:36:56 +00:00
4c3de8c942 Merge pull request 'dev' (#233) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 58s
Build and Release FEDEO / build-and-release (push) Successful in 6m11s
Reviewed-on: #233
2026-09-30 17:23:15 +00:00
49d44d9701 Merge pull request 'dev' (#232) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 1m1s
Build and Release FEDEO / build-and-release (push) Successful in 6m18s
Reviewed-on: #232
2026-09-30 15:43:45 +00:00
96a7acff33 Merge pull request 'feat(selfhost): show sanitized update logs in admin UI' (#231) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 47s
Build and Release FEDEO / build-and-release (push) Successful in 6m7s
Reviewed-on: #231
2026-09-25 17:22:30 +00:00
65588686c7 Merge pull request 'fix(documents): normalize units when selecting and loading rows' (#230) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 48s
Build and Release FEDEO / build-and-release (push) Successful in 6m3s
Reviewed-on: #230
2026-09-25 09:54:08 +00:00
fcf9cc3fc9 Merge pull request 'dev' (#229) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 49s
Build and Release FEDEO / build-and-release (push) Successful in 6m6s
Reviewed-on: #229
2026-09-25 09:24:39 +00:00
20091143d2 Merge pull request 'dev' (#228) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 45s
Build and Release FEDEO / build-and-release (push) Successful in 6m5s
Reviewed-on: #228
2026-09-23 17:20:58 +00:00
f708d0a2b2 Merge pull request 'dev' (#227) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 44s
Build and Release FEDEO / build-and-release (push) Successful in 6m7s
Reviewed-on: #227
2026-09-23 16:15:44 +00:00
7e9f4409f6 Merge pull request 'dev' (#226) from dev into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 33s
Build and Release FEDEO / build-and-release (push) Successful in 6m10s
Reviewed-on: #226
2026-09-23 14:57:40 +00:00
2e63af1aa2 Merge pull request 'fix(release): stream large migration checksums from git' (#225) from flfeders/codex/release-migration-checksums into main
All checks were successful
Build and Release FEDEO / verify (push) Successful in 25s
Build and Release FEDEO / build-and-release (push) Successful in 5m59s
Reviewed-on: #225
2026-09-23 14:09:57 +00:00
5ebd2d508c Merge pull request 'fix(release): exclude legacy main history from commit checks' (#224) from dev into main
Some checks failed
Build and Release FEDEO / verify (push) Successful in 23s
Build and Release FEDEO / build-and-release (push) Failing after 5m57s
Reviewed-on: #224
2026-09-23 13:03:36 +00:00
9128fbb165 Merge pull request 'fix(ci): build dev images without repository write access' (#221) from dev into main
Some checks failed
Build and Release FEDEO / verify (push) Failing after 26s
Build and Release FEDEO / build-and-release (push) Has been skipped
Reviewed-on: #221
2026-09-20 16:25:38 +00:00
8473221c13 Merge pull request '3.0.0' (#220) from dev into main
Some checks failed
Build and Release FEDEO / verify (push) Failing after 22s
Build and Release FEDEO / build-and-release (push) Has been skipped
Reviewed-on: #220
2026-09-20 16:10:46 +00:00
e7554fa2cc .gitea/ISSUE_TEMPLATE/feature_request.md aktualisiert
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 16s
Build and Push Docker Images / build-frontend (push) Successful in 16s
2026-01-22 17:42:28 +00:00
7c1fabf58a .gitea/ISSUE_TEMPLATE/bug_report.md aktualisiert
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 17s
Build and Push Docker Images / build-frontend (push) Successful in 16s
2026-01-22 17:40:58 +00:00
1203b6cbd1 .gitea/ISSUE_TEMPLATE/bug_report.md aktualisiert
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 16s
Build and Push Docker Images / build-frontend (push) Successful in 16s
2026-01-15 11:39:03 +00:00
525f2906fb .gitea/ISSUE_TEMPLATE/feature_request.md aktualisiert
Some checks failed
Build and Push Docker Images / build-frontend (push) Has been cancelled
Build and Push Docker Images / build-backend (push) Has been cancelled
2026-01-15 11:38:50 +00:00
b105382abf .gitea/ISSUE_TEMPLATE/bug_report.md aktualisiert
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 16s
Build and Push Docker Images / build-frontend (push) Successful in 15s
2026-01-15 11:38:00 +00:00
b1cdec7d17 Merge pull request 'Added feature request template' (#62) from dev into main
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 17s
Build and Push Docker Images / build-frontend (push) Successful in 16s
Reviewed-on: #62
2026-01-15 11:31:57 +00:00
f1d512b2e5 Merge pull request 'dev' (#61) from dev into main
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 17s
Build and Push Docker Images / build-frontend (push) Successful in 16s
Reviewed-on: #61
2026-01-15 11:29:15 +00:00
db21b43120 Merge pull request 'dev' (#40) from dev into main
All checks were successful
Build and Push Docker Images / build-backend (push) Successful in 18s
Build and Push Docker Images / build-frontend (push) Successful in 16s
Reviewed-on: #40
2026-01-08 22:21:06 +00:00
7 changed files with 8 additions and 109 deletions

View File

@@ -2,37 +2,18 @@
name: 🐛 Bug Report
about: Erstelle einen Bericht, um uns zu helfen, das Projekt zu verbessern.
title: '[BUG] '
labels: bug
labels: Problem
assignees: ''
---
**Beschreibung**
Eine klare und prägnante Beschreibung des Fehlers.
**Reproduktion**
Schritte, um den Fehler zu reproduzieren:
Entweder:
1. Gehe zu '...'
2. Klicke auf '...'
3. Scrolle runter zu '...'
4. Siehe Fehler
Oder Link zur Seite
**Erwartetes Verhalten**
Eine klare Beschreibung dessen, was du erwartet hast.
**Screenshots**
Falls zutreffend, füge hier Screenshots oder Gifs hinzu, um das Problem zu verdeutlichen.
**Achtung: Achte bitte auf Datenschutz deiner Daten sowie der Daten deiner Kunden. Sollten ein Screenshot nur mit Daten möglich sein, schwärze diese bitte vor dem Upload.**
**Umgebung:**
- Betriebssystem: [z.B. Windows, macOS, Linux]
- Browser / Version (falls relevant): [z.B. Chrome 120]
- Projekt-Version: [z.B. v1.0.2]
**Zusätzlicher Kontext**
Füge hier alle anderen Informationen zum Problem hinzu.

View File

@@ -2,19 +2,16 @@
name: ✨ Feature Request
about: Schlage eine Idee für dieses Projekt vor.
title: '[FEATURE] '
labels: enhancement
labels: Funktionswunsch
assignees: ''
---
**Ist dein Feature-Wunsch mit einem Problem verbunden?**
Eine klare Beschreibung des Problems (z.B. "Ich bin immer genervt, wenn...").
**Lösungsvorschlag**
Eine klare Beschreibung dessen, was du dir wünschst und wie es funktionieren soll.
**Alternativen**
Hast du über alternative Lösungen oder Workarounds nachgedacht?
**Zusätzlicher Kontext**
Hier ist Platz für weitere Informationen, Skizzen oder Beispiele von anderen Tools.

View File

@@ -9,7 +9,7 @@
"fill": "ts-node src/webdav/fill-file-sizes.ts",
"dev:dav": "tsx watch src/webdav/server.ts",
"build": "tsc",
"test:einvoice": "tsx --test tests/einvoice.test.ts tests/zugferdInvoice.test.ts tests/outgoingEInvoiceSettings.test.ts",
"test:einvoice": "tsx --test tests/einvoice.test.ts tests/zugferdInvoice.test.ts",
"start": "node dist/src/index.js",
"schema:index": "ts-node scripts/generate-schema-index.ts",
"bankcodes:update": "tsx scripts/generate-de-bank-codes.ts",

View File

@@ -30,18 +30,9 @@ export class EInvoiceRequirementsError extends Error {
export const breakingIssues = (issues: ZugferdIssue[]) => issues.filter((issue) => issue.type === "breaking")
/** Ausgangs-E-Rechnungen sind pro Mandant ausdrücklich zu aktivieren. */
async function outgoingEInvoiceEnabled(server: FastifyInstance, tenantId: number) {
const [tenant] = await server.db.select({ businessInfo: tenants.businessInfo }).from(tenants)
.where(eq(tenants.id, tenantId)).limit(1)
if (!tenant) throw new Error("Mandant nicht gefunden")
return (tenant.businessInfo as any)?.outgoingEInvoiceEnabled === true
}
/** Prüft die Pflichtangaben eines (auch ungespeicherten) Belegs. Andere Belegarten liefern keine Hinweise. */
export async function checkOutgoingEInvoice(server: FastifyInstance, tenantId: number, document: any, options: { requireNumber?: boolean } = {}) {
if (!document || !isZugferdDocumentType(document.type)) return [] as ZugferdIssue[]
if (!await outgoingEInvoiceEnabled(server, tenantId)) return [] as ZugferdIssue[]
const context = await loadZugferdContext(server, tenantId, document)
return checkZugferdRequirements(document, context, options)
}
@@ -101,12 +92,11 @@ export async function loadZugferdContext(server: FastifyInstance, tenantId: numb
}
/**
* Bei aktivierter Ausgangs-E-Rechnung wird die PDF zur ZUGFeRD-Rechnung. Fehlende Pflichtangaben führen zu
* Macht aus der gerenderten Rechnungs-PDF eine ZUGFeRD-Rechnung. Fehlende Pflichtangaben führen zu
* EInvoiceRequirementsError, damit keine Rechnung ohne gültige E-Rechnung abgelegt wird.
*/
export async function attachZugferdToPdf(server: FastifyInstance, tenantId: number, document: any, pdf: Buffer) {
if (!isZugferdDocument(document)) return { pdf, issues: [] as ZugferdIssue[], einvoice: false }
if (!await outgoingEInvoiceEnabled(server, tenantId)) return { pdf, issues: [] as ZugferdIssue[], einvoice: false }
const context = await loadZugferdContext(server, tenantId, document)
const { xml, issues } = buildZugferdInvoiceXml(document, context)
const blocking = breakingIssues(issues)

View File

@@ -278,11 +278,6 @@ export default async function tenantRoutes(server: FastifyInstance) {
if (!data) return reply.code(400).send({ error: "data required" })
if (data.businessInfo && Object.prototype.hasOwnProperty.call(data.businessInfo, "outgoingEInvoiceEnabled")
&& typeof data.businessInfo.outgoingEInvoiceEnabled !== "boolean") {
return reply.code(400).send({ error: "Die Einstellung für Ausgangs-E-Rechnungen muss ein Wahrheitswert sein." })
}
if (Object.prototype.hasOwnProperty.call(data, "portalConfig")) {
const config = data.portalConfig
if (!config || typeof config !== "object" || Array.isArray(config)

View File

@@ -1,56 +0,0 @@
import assert from "node:assert/strict"
import test from "node:test"
import { tenants } from "../db/schema"
import { PgDialect } from "drizzle-orm/pg-core"
import { assertOutgoingEInvoiceRequirements, attachZugferdToPdf, checkOutgoingEInvoice, EInvoiceRequirementsError } from "../src/modules/einvoice/outgoingZugferd.service"
const invoice = { type: "invoices", documentNumber: "RE-1", payment_type: "sepa", rows: [] }
function serverFor(businessInfo: any) {
const tenantIds: number[] = []
let otherReads = 0
const server = { db: { select: () => ({ from: (table: any) => {
const rows = table === tenants ? [{ businessInfo }] : []
if (table !== tenants) otherReads++
const query: any = {
where: (condition: any) => {
if (table === tenants) tenantIds.push(new PgDialect().sqlToQuery(condition).params[0] as number)
return query
},
limit: async () => rows,
then: (resolve: any, reject: any) => Promise.resolve(rows).then(resolve, reject),
}
return query
} }) } } as any
return { server, tenantIds, otherReads: () => otherReads }
}
for (const businessInfo of [undefined, {}, { outgoingEInvoiceEnabled: false }, { outgoingEInvoiceEnabled: "true" }]) {
test(`disabled/legacy tenant skips e-invoice requirements: ${JSON.stringify(businessInfo)}`, async () => {
const { server, tenantIds, otherReads } = serverFor(businessInfo)
assert.deepEqual(await checkOutgoingEInvoice(server, 8, invoice), [])
await assertOutgoingEInvoiceRequirements(server, 8, invoice)
const pdf = Buffer.from("original PDF bytes")
const result = await attachZugferdToPdf(server, 8, invoice, pdf)
assert.equal(result.pdf, pdf)
assert.equal(result.einvoice, false)
assert.deepEqual(result.issues, [])
assert.deepEqual(tenantIds, [8, 8, 8])
assert.equal(otherReads(), 0)
})
}
test("enabled tenant still blocks incomplete invoices before finalization and embedding", async () => {
const { server, tenantIds } = serverFor({ outgoingEInvoiceEnabled: true })
const issues = await checkOutgoingEInvoice(server, 9, invoice)
assert.ok(issues.some(issue => issue.type === "breaking"))
await assert.rejects(assertOutgoingEInvoiceRequirements(server, 9, invoice), EInvoiceRequirementsError)
await assert.rejects(attachZugferdToPdf(server, 9, invoice, Buffer.from("pdf")), EInvoiceRequirementsError)
assert.ok(tenantIds.every(id => id === 9))
})
test("document payload cannot disable the tenant setting", async () => {
const { server } = serverFor({ outgoingEInvoiceEnabled: true })
await assert.rejects(assertOutgoingEInvoiceRequirements(server, 8, {
...invoice, businessInfo: { outgoingEInvoiceEnabled: false }, outgoingEInvoiceEnabled: false,
}), EInvoiceRequirementsError)
})

View File

@@ -233,7 +233,6 @@ const activeTelephonyTargetOptions = computed(() => {
return telephonyExtensionOptions.value.users || []
})
const defaultBusinessInfo = {
outgoingEInvoiceEnabled: false,
name: "",
street: "",
zip: "",
@@ -753,13 +752,6 @@ onMounted(() => {
>
<UInput v-model="businessInfo.bic"/>
</UFormField>
<UFormField
label="Ausgangs-E-Rechnungen"
description="Optional für diesen Mandanten: Bei Aktivierung werden Rechnungs-PDFs mit ZUGFeRD-Daten erstellt und die erforderlichen Angaben geprüft. Deaktiviert werden normale PDFs ohne E-Rechnungsprüfung erstellt. Gilt auch für Serienrechnungen. Bereits gespeicherte Belege und der Empfang von E-Rechnungen bleiben unverändert."
class="mt-6"
>
<USwitch v-model="businessInfo.outgoingEInvoiceEnabled" label="E-Rechnungen erstellen" />
</UFormField>
<UButton
class="mt-3"
@click="updateTenant({businessInfo: businessInfo})"