Feature: Belegbuchung verbessert, Metadaten bereinigt (Migrationen 024–026)
- Verbindlichkeiten in Kategorie-Auswahl bei Belegbuchung ergänzt - Direkte Kontonummer-Eingabe über Suchfeld (ohne Dropdown-Auswahl) - Auto-Select im Konto-Suchfeld nur noch bei exaktem Kontonummer-Treffer - Flash-Messages bleiben 20 Sekunden sichtbar - Bewirtungsfelder (Grund, Teilnehmerliste) am Beleg statt an Buchung gespeichert (Migration 024) - Bewirtungssplit für Konto 4652→4657 analog zu 4650→4654; USt 0% für 4652/4657 automatisch - Bewirtungshinweis als persistentes Flash (verschwindet nicht automatisch) - Eingangsdatum aus Belegen entfernt (Migration 025) - Bruttobetrag am Beleg wird aus Buchungszeilen berechnet, keine manuelle Eingabe mehr - Kontenrahmen von Produktion übernommen (Migration 026)
This commit is contained in:
parent
092ea1f02f
commit
262454e038
14 changed files with 264 additions and 85 deletions
10
migrations/024_bewirtung_zu_beleg.sql
Normal file
10
migrations/024_bewirtung_zu_beleg.sql
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
-- Migration 024: Bewirtungsfelder von bookings nach belege verschieben
|
||||||
|
-- Bestehende Daten werden nicht migriert (können gelöscht werden).
|
||||||
|
|
||||||
|
ALTER TABLE belege
|
||||||
|
ADD COLUMN bewirtungsgrund TEXT NULL AFTER notes,
|
||||||
|
ADD COLUMN teilnehmerliste TEXT NULL AFTER bewirtungsgrund;
|
||||||
|
|
||||||
|
ALTER TABLE bookings
|
||||||
|
DROP COLUMN bewirtungsgrund,
|
||||||
|
DROP COLUMN teilnehmerliste;
|
||||||
2
migrations/025_remove_eingangs_datum.sql
Normal file
2
migrations/025_remove_eingangs_datum.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
-- Migration 025: Eingangsdatum aus belege entfernen
|
||||||
|
ALTER TABLE belege DROP COLUMN eingangs_datum;
|
||||||
159
migrations/026_kontenrahmen_prod.sql
Normal file
159
migrations/026_kontenrahmen_prod.sql
Normal file
|
|
@ -0,0 +1,159 @@
|
||||||
|
-- Migration 026: Kontenrahmen-Abgleich von Produktion (2026-04-11)
|
||||||
|
|
||||||
|
INSERT INTO accounts (kontonummer, bezeichnung, kontenart, steuercode, ustva_kz, euer_zeile, is_system, aktiv) VALUES
|
||||||
|
('0027', 'EDV-Software', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0030', 'Lizenzen an gewerblichen Schutzrechten', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0210', 'Maschinen', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0320', 'Pkw', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0350', 'Lkw', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0400', 'Betriebsausstattung', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0410', 'Geschäftsausstattung', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0420', 'Büroeinrichtung', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0440', 'Werkzeuge', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('0480', 'Geringwertige Wirtschaftsgüter', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1000', 'Kasse', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1010', 'Nebenkasse 1', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1200', 'Bank 1 - Comdirekt', 'Zahlungskonto', '', '', NULL, 1, 1),
|
||||||
|
('1210', 'Bank 2 - Sonstige Banken und Kasse', 'Zahlungskonto', '', '', NULL, 1, 1),
|
||||||
|
('1220', 'Bank 3', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1230', 'Bank 4', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1240', 'Bank 5', 'Zahlungskonto', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1390', 'Verrechnungskonto Ist-Versteuerung', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1770', 'Umsatzsteuer', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1771', 'Umsatzsteuer 7 %', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1776', 'Umsatzsteuer 19 %', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1780', 'Umsatzsteuer-Vorauszahlungen lfd. Jahr', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1781', 'Umsatzsteuer-Vorauszahlungen 1/11', 'Verbindlichkeit', '', '', NULL, 1, 1),
|
||||||
|
('1800', 'Privatentnahmen', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1810', 'Privatsteuern', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1820', 'Sonderausgaben beschränkt abzugsfähig', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1830', 'Sonderausgaben unbeschränkt abzugsfähig', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1840', 'Zuwendungen, Spenden', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('1890', 'Privateinlagen', 'Privat', NULL, NULL, NULL, 1, 1),
|
||||||
|
('3106', 'Fremdleistungen 19 % Vorsteuer', 'Betriebsausgabe', 'VSt19', '61', '29', 1, 1),
|
||||||
|
('3108', 'Fremdleistungen 7 % Vorsteuer', 'Betriebsausgabe', 'VSt7', '62', '29', 1, 1),
|
||||||
|
('3109', 'Fremdleistungen ohne Vorsteuer', 'Betriebsausgabe', NULL, NULL, '29', 1, 1),
|
||||||
|
('3300', 'Wareneingang 7 % Vorsteuer', 'Betriebsausgabe', 'VSt7', '62', '28', 1, 1),
|
||||||
|
('3349', 'Wareneingang ohne Vorsteuerabzug', 'Betriebsausgabe', NULL, NULL, '26', 1, 1),
|
||||||
|
('3400', 'Wareneingang 19 % Vorsteuer', 'Betriebsausgabe', 'VSt19', '61', '27', 1, 1),
|
||||||
|
('4100', 'Löhne und Gehälter', 'Betriebsausgabe', NULL, NULL, '30', 1, 1),
|
||||||
|
('4110', 'Löhne', 'Betriebsausgabe', NULL, NULL, '30', 1, 1),
|
||||||
|
('4120', 'Gehälter', 'Betriebsausgabe', NULL, NULL, '30', 1, 1),
|
||||||
|
('4130', 'Gesetzliche soziale Aufwendungen', 'Betriebsausgabe', NULL, NULL, '31', 1, 1),
|
||||||
|
('4138', 'Beiträge zur Berufsgenossenschaft', 'Betriebsausgabe', NULL, NULL, '31', 1, 1),
|
||||||
|
('4140', 'Freiwillige soziale Aufwendungen, lohnsteuerfrei', 'Betriebsausgabe', NULL, NULL, '32', 1, 1),
|
||||||
|
('4145', 'Freiwillige soziale Aufwendungen, lohnsteuerpflichtig', 'Betriebsausgabe', NULL, NULL, '32', 1, 1),
|
||||||
|
('4180', 'Aushilfslöhne', 'Betriebsausgabe', NULL, NULL, '30', 1, 1),
|
||||||
|
('4190', 'Aushilfslöhne Minijobs', 'Betriebsausgabe', NULL, NULL, '30', 1, 1),
|
||||||
|
('4210', 'Miete (unbewegliche Wirtschaftsgüter)', 'Betriebsausgabe', NULL, NULL, '33', 1, 1),
|
||||||
|
('4211', 'Miete/Pacht unbewegliche WG (gewerbesteuerl. hinzuzur.)', 'Betriebsausgabe', NULL, NULL, '33', 1, 1),
|
||||||
|
('4220', 'Pacht (unbewegliche Wirtschaftsgüter)', 'Betriebsausgabe', NULL, NULL, '33', 1, 1),
|
||||||
|
('4230', 'Heizung', 'Betriebsausgabe', 'VSt19', '61', '34', 1, 1),
|
||||||
|
('4240', 'Gas, Strom, Wasser', 'Betriebsausgabe', 'VSt19', '61', '34', 1, 1),
|
||||||
|
('4250', 'Reinigung', 'Betriebsausgabe', 'VSt19', '61', '37', 1, 1),
|
||||||
|
('4260', 'Instandhaltung betrieblicher Räume', 'Betriebsausgabe', 'VSt19', '61', '37', 1, 1),
|
||||||
|
('4280', 'Sonstige Raumkosten', 'Betriebsausgabe', 'VSt19', '61', '33', 1, 1),
|
||||||
|
('4287', 'Tagespauschale für Tätigkeit in der häuslichen Wohnung', 'Betriebsausgabe', NULL, NULL, '66', 1, 1),
|
||||||
|
('4288', 'Häusliches Arbeitszimmer (abziehbarer Anteil)', 'Betriebsausgabe', NULL, NULL, '65', 1, 1),
|
||||||
|
('4289', 'Häusliches Arbeitszimmer (nicht abziehbarer Anteil)', 'Betriebsausgabe', NULL, NULL, '51', 1, 1),
|
||||||
|
('4300', 'Nicht abziehbare Vorsteuer', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4301', 'Nicht abziehbare Vorsteuer 7 %', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4306', 'Nicht abziehbare Vorsteuer 19 %', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4320', 'Gewerbesteuer', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4340', 'Sonstige Betriebssteuern', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4350', 'Verbrauchsteuer (sonstige Steuern)', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4360', 'Versicherungen', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4366', 'Versicherungen für Gebäude', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4380', 'Beiträge', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4390', 'Sonstige Abgaben', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4500', 'Fahrzeugkosten (allgemein)', 'Betriebsausgabe', NULL, NULL, '40', 1, 1),
|
||||||
|
('4510', 'Kfz-Steuer', 'Betriebsausgabe', NULL, NULL, '40', 1, 1),
|
||||||
|
('4520', 'Fahrzeug-Versicherungen', 'Betriebsausgabe', NULL, NULL, '40', 1, 1),
|
||||||
|
('4530', 'Laufende Fahrzeug-Betriebskosten', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4540', 'Fahrzeug-Reparaturen', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4550', 'Garagenmiete', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4560', 'Mautgebühren', 'Betriebsausgabe', NULL, NULL, '40', 1, 1),
|
||||||
|
('4570', 'Mietleasing Kfz', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4575', 'Mietleasing Elektrofahrzeuge/Fahrräder (gewerbesteuerl. hinzuzurechnen)', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4580', 'Sonstige Fahrzeugkosten', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4590', 'Fremdfahrzeugkosten', 'Betriebsausgabe', 'VSt19', '61', '40', 1, 1),
|
||||||
|
('4600', 'Werbekosten', 'Betriebsausgabe', 'VSt19', '61', '41', 1, 1),
|
||||||
|
('4605', 'Streuartikel', 'Betriebsausgabe', 'VSt19', '61', '41', 1, 1),
|
||||||
|
('4630', 'Geschenke abzugsfähig ohne § 37b EStG', 'Betriebsausgabe', 'VSt19', '61', '41', 1, 1),
|
||||||
|
('4631', 'Geschenke abzugsfähig mit § 37b EStG (§ 37b-Steuer)', 'Betriebsausgabe', 'VSt19', '61', '41', 1, 1),
|
||||||
|
('4635', 'Geschenke nicht abzugsfähig ohne § 37b EStG', 'Betriebsausgabe', 'VSt19', '61', '51', 1, 1),
|
||||||
|
('4636', 'Geschenke nicht abzugsfähig mit § 37b EStG', 'Betriebsausgabe', 'VSt19', '61', '51', 1, 1),
|
||||||
|
('4650', 'Bewirtungskosten (70 % abzugsfähig) VSt. 19%', 'Betriebsausgabe', 'VSt19', '61', '44', 1, 1),
|
||||||
|
('4651', 'Bewirtungskosten (70 % abzugsfähig) VSt. 7%', 'Betriebsausgabe', 'VSt7', '62', '44', 1, 1),
|
||||||
|
('4652', 'Bewirtungskosten (70 % abzugsfähig) VSt. 0%', 'Betriebsausgabe', '', '', NULL, 0, 1),
|
||||||
|
('4654', 'Nicht abzugsfähige Bewirtungskosten VSt. 19%', 'Betriebsausgabe', 'VSt19', '61', '51', 1, 1),
|
||||||
|
('4656', 'nicht abzugsfähige Bewirtungskosten VSt. 7%', 'Betriebsausgabe', 'VSt7', '62', '51', 1, 1),
|
||||||
|
('4657', 'nicht abzugsfähige Bewirtungskosten VSt. 0%', 'Betriebsausgabe', '', '', NULL, 0, 1),
|
||||||
|
('4660', 'Reisekosten Arbeitnehmer', 'Betriebsausgabe', NULL, NULL, '42', 1, 1),
|
||||||
|
('4663', 'Reisekosten Arbeitnehmer Fahrtkosten', 'Betriebsausgabe', NULL, NULL, '42', 1, 1),
|
||||||
|
('4664', 'Reisekosten Arbeitnehmer Verpflegungsmehraufwand', 'Betriebsausgabe', NULL, NULL, '42', 1, 1),
|
||||||
|
('4666', 'Reisekosten Arbeitnehmer Übernachtungsaufwand', 'Betriebsausgabe', 'VSt19', '61', '42', 1, 1),
|
||||||
|
('4668', 'Kilometergelderstattung Arbeitnehmer', 'Betriebsausgabe', NULL, NULL, '42', 1, 1),
|
||||||
|
('4670', 'Reisekosten Unternehmer', 'Betriebsausgabe', NULL, NULL, '43', 1, 1),
|
||||||
|
('4672', 'Reisekosten Unternehmer (nicht abziehbarer Anteil)', 'Betriebsausgabe', NULL, NULL, '51', 1, 1),
|
||||||
|
('4673', 'Reisekosten Unternehmer Fahrtkosten', 'Betriebsausgabe', NULL, NULL, '43', 1, 1),
|
||||||
|
('4674', 'Reisekosten Unternehmer Verpflegungsmehraufwand', 'Betriebsausgabe', NULL, NULL, '43', 1, 1),
|
||||||
|
('4676', 'Reisekosten Unternehmer Übernachtungsaufwand', 'Betriebsausgabe', 'VSt19', '61', '43', 1, 1),
|
||||||
|
('4780', 'Fremdarbeiten', 'Betriebsausgabe', 'VSt19', '61', '29', 1, 1),
|
||||||
|
('4800', 'Reparaturen und Instandhaltungen (Maschinen, techn. Anlagen)', 'Betriebsausgabe', 'VSt19', '61', '38', 1, 1),
|
||||||
|
('4801', 'Reparaturen und Instandhaltung von Bauten', 'Betriebsausgabe', 'VSt19', '61', '37', 1, 1),
|
||||||
|
('4805', 'Reparaturen und Instandhaltungen (andere Anlagen, BGA)', 'Betriebsausgabe', 'VSt19', '61', '38', 1, 1),
|
||||||
|
('4806', 'Wartungskosten Hard- und Software', 'Betriebsausgabe', 'VSt19', '61', '38', 1, 1),
|
||||||
|
('4809', 'Sonstige Reparaturen und Instandhaltungen', 'Betriebsausgabe', 'VSt19', '61', '38', 1, 1),
|
||||||
|
('4822', 'Abschreibungen auf immaterielle Vermögensgegenstände', 'Betriebsausgabe', NULL, NULL, '49', 1, 1),
|
||||||
|
('4830', 'Abschreibungen auf Sachanlagen (ohne AfA Fzg./Gebäude)', 'Betriebsausgabe', NULL, NULL, '49', 1, 1),
|
||||||
|
('4831', 'Abschreibungen auf Gebäude', 'Betriebsausgabe', NULL, NULL, '49', 1, 1),
|
||||||
|
('4832', 'Abschreibungen auf Fahrzeuge', 'Betriebsausgabe', NULL, NULL, '49', 1, 1),
|
||||||
|
('4855', 'Sofortabschreibung geringwertiger Wirtschaftsgüter', 'Betriebsausgabe', NULL, NULL, '50', 1, 1),
|
||||||
|
('4856', 'Sonderabschreibungen nach § 7b EStG (Mietwohnungsneubau)', 'Betriebsausgabe', NULL, NULL, '37', 1, 1),
|
||||||
|
('4900', 'Sonstige betriebliche Aufwendungen', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('4909', 'Fremdleistungen / Fremdarbeiten', 'Betriebsausgabe', 'VSt19', '61', '29', 1, 1),
|
||||||
|
('4910', 'Porto', 'Betriebsausgabe', NULL, NULL, '47', 1, 1),
|
||||||
|
('4920', 'Telefon', 'Betriebsausgabe', 'VSt19', '61', '47', 1, 1),
|
||||||
|
('4925', 'Internetkosten', 'Betriebsausgabe', 'VSt19', '61', '47', 1, 1),
|
||||||
|
('4930', 'Bürobedarf', 'Betriebsausgabe', 'VSt19', '61', '47', 1, 1),
|
||||||
|
('4940', 'Zeitschriften, Bücher, digitale Medien (Fachliteratur)', 'Betriebsausgabe', 'VSt7', '62', '47', 1, 1),
|
||||||
|
('4945', 'Fortbildungskosten', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('4950', 'Rechts- und Beratungskosten', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('4955', 'Buchführungskosten', 'Betriebsausgabe', 'VSt19', '61', '46', 1, 1),
|
||||||
|
('4957', 'Abschluss- und Prüfungskosten', 'Betriebsausgabe', 'VSt19', '61', '46', 1, 1),
|
||||||
|
('4960', 'Mieten für Einrichtungen (bewegliche Wirtschaftsgüter)', 'Betriebsausgabe', 'VSt19', '61', '48', 1, 1),
|
||||||
|
('4964', 'Zeitlich befristete Überlassung von Rechten (Lizenzen)', 'Betriebsausgabe', 'VSt19', '61', '48', 1, 1),
|
||||||
|
('4965', 'Mietleasing (bewegliche WG / Geschäftsausstattung)', 'Betriebsausgabe', 'VSt19', '61', '48', 1, 1),
|
||||||
|
('4969', 'Abraum- und Abfallbeseitigung', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('4970', 'Nebenkosten des Geldverkehrs (Bankgebühren, Zinsen)', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4971', 'Verwahrentgelt', 'Betriebsausgabe', NULL, NULL, '52', 1, 1),
|
||||||
|
('4980', 'Sonstiger Betriebsbedarf', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('4985', 'Werkzeuge und Kleingeräte', 'Betriebsausgabe', 'VSt19', '61', '52', 1, 1),
|
||||||
|
('8100', 'Steuerfreie Umsätze § 4 Nr. 8 ff. UStG', 'Betriebseinnahme', NULL, '48', '17', 1, 1),
|
||||||
|
('8105', 'Steuerfreie Umsätze § 4 Nr. 12 UStG (Vermietung/Verpachtung)', 'Betriebseinnahme', NULL, '48', '17', 1, 1),
|
||||||
|
('8110', 'Sonstige steuerfreie Umsätze Inland', 'Betriebseinnahme', NULL, '48', '17', 1, 1),
|
||||||
|
('8120', 'Steuerfreie Umsätze § 4 Nr. 1a UStG', 'Betriebseinnahme', NULL, '43', '18', 1, 1),
|
||||||
|
('8125', 'Steuerfreie innergemeinschaftliche Lieferungen § 4 Nr. 1b UStG', 'Betriebseinnahme', NULL, '41', '18', 1, 1),
|
||||||
|
('8300', 'Erlöse 7 % USt', 'Betriebseinnahme', 'USt7', '86', '15', 1, 1),
|
||||||
|
('8400', 'Erlöse 19 % USt', 'Betriebseinnahme', 'USt19', '81', '16', 1, 1),
|
||||||
|
('8570', 'Sonstige Erträge aus Provisionen, Lizenzen und Patenten', 'Betriebseinnahme', 'USt19', '81', '16', 1, 1),
|
||||||
|
('8710', 'Erlösschmälerungen 7 % USt', 'Betriebseinnahme', 'USt7', '86', '15', 1, 1),
|
||||||
|
('8720', 'Erlösschmälerungen 19 % USt', 'Betriebseinnahme', 'USt19', '81', '16', 1, 1),
|
||||||
|
('8800', 'Erlöse aus Verkäufen Sachanlagevermögen (bei Buchverlust)', 'Betriebseinnahme', NULL, NULL, '22', 1, 1),
|
||||||
|
('8801', 'Erlöse aus Verkäufen Sachanlagevermögen 19 % USt (bei Buchverlust)', 'Betriebseinnahme', 'USt19', '81', '22', 1, 1),
|
||||||
|
('8820', 'Erlöse aus Verkäufen Sachanlagevermögen 19 % USt (bei Buchgewinn)', 'Betriebseinnahme', 'USt19', '81', '22', 1, 1),
|
||||||
|
('8900', 'Sonstige betriebliche Erträge', 'Betriebseinnahme', NULL, NULL, '23', 1, 1),
|
||||||
|
('8910', 'Sonstige betriebliche Erträge (steuerfrei)', 'Betriebseinnahme', NULL, NULL, '23', 1, 1),
|
||||||
|
('8920', 'Verwendung von Gegenständen für Zwecke außerhalb des Unternehmens', 'Betriebseinnahme', NULL, NULL, '22', 1, 1),
|
||||||
|
('8921', 'Verwendung von Gegenständen für Zwecke außerhalb des Unternehmens 7 % USt', 'Betriebseinnahme', 'USt7', '86', '22', 1, 1),
|
||||||
|
('8922', 'Verwendung von Gegenständen für Zwecke außerhalb des Unternehmens 19 % USt', 'Betriebseinnahme', 'USt19', '81', '22', 1, 1),
|
||||||
|
('8950', 'Nicht steuerbare Umsätze (Innenenumsätze)', 'Betriebseinnahme', NULL, NULL, '21', 1, 1)
|
||||||
|
ON DUPLICATE KEY UPDATE
|
||||||
|
bezeichnung=VALUES(bezeichnung),
|
||||||
|
kontenart=VALUES(kontenart),
|
||||||
|
steuercode=VALUES(steuercode),
|
||||||
|
ustva_kz=VALUES(ustva_kz),
|
||||||
|
euer_zeile=VALUES(euer_zeile),
|
||||||
|
is_system=VALUES(is_system),
|
||||||
|
aktiv=VALUES(aktiv);
|
||||||
|
|
@ -33,11 +33,14 @@ document.addEventListener('input', (e) => {
|
||||||
if (opt.value === '') { opt.hidden = false; continue; }
|
if (opt.value === '') { opt.hidden = false; continue; }
|
||||||
opt.hidden = !opt.dataset.search.toLowerCase().includes(q);
|
opt.hidden = !opt.dataset.search.toLowerCase().includes(q);
|
||||||
}
|
}
|
||||||
// Auto-select first visible match
|
// Auto-select nur bei exaktem Kontonummer-Treffer; sonst Select leeren
|
||||||
|
// (verhindert, dass direkte Kontonummer-Eingabe durch einen Partial-Match überschrieben wird)
|
||||||
if (q.length > 0) {
|
if (q.length > 0) {
|
||||||
for (const opt of select.options) {
|
const exact = [...select.options].find(
|
||||||
if (!opt.hidden && opt.value !== '') { select.value = opt.value; break; }
|
opt => opt.value !== '' && opt.dataset.search && opt.dataset.search.split(' ')[0] === q
|
||||||
}
|
);
|
||||||
|
select.value = exact ? exact.value : '';
|
||||||
|
select.dispatchEvent(new Event('change'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -364,10 +367,11 @@ document.addEventListener('keydown', (e) => {
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
document.querySelectorAll('.flash').forEach(el => {
|
document.querySelectorAll('.flash').forEach(el => {
|
||||||
if (el.closest('#ki-badge')) return; // KI-Badge nie auto-dismissen
|
if (el.closest('#ki-badge')) return; // KI-Badge nie auto-dismissen
|
||||||
|
if (el.classList.contains('flash-persistent')) return; // z.B. Bewirtungshinweis
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
el.style.transition = 'opacity .4s';
|
el.style.transition = 'opacity .4s';
|
||||||
el.style.opacity = '0';
|
el.style.opacity = '0';
|
||||||
setTimeout(() => el.remove(), 400);
|
setTimeout(() => el.remove(), 400);
|
||||||
}, 4000);
|
}, 20000);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -126,9 +126,8 @@ class BelegController
|
||||||
'mime_type' => $mime,
|
'mime_type' => $mime,
|
||||||
'file_hash' => $hash,
|
'file_hash' => $hash,
|
||||||
'beleg_datum' => $_POST['beleg_datum'] ?? null,
|
'beleg_datum' => $_POST['beleg_datum'] ?? null,
|
||||||
'eingangs_datum'=> $_POST['eingangs_datum'] ?? date('Y-m-d'),
|
|
||||||
'rechnungs_nr' => $filenameWithoutExt,
|
'rechnungs_nr' => $filenameWithoutExt,
|
||||||
'betrag_brutto' => ($_POST['betrag_brutto'] ?? '') !== '' ? $_POST['betrag_brutto'] : null,
|
'betrag_brutto' => null,
|
||||||
'belegtyp' => $_POST['belegtyp'] ?? 'Eingangsrechnung',
|
'belegtyp' => $_POST['belegtyp'] ?? 'Eingangsrechnung',
|
||||||
'notes' => $_POST['notes'] ?? null,
|
'notes' => $_POST['notes'] ?? null,
|
||||||
]);
|
]);
|
||||||
|
|
@ -214,7 +213,6 @@ class BelegController
|
||||||
'rechnungs_nr' => trim($_POST['rechnungs_nr'] ?? ''),
|
'rechnungs_nr' => trim($_POST['rechnungs_nr'] ?? ''),
|
||||||
'belegtyp' => $_POST['belegtyp'] ?? $beleg['belegtyp'],
|
'belegtyp' => $_POST['belegtyp'] ?? $beleg['belegtyp'],
|
||||||
'beleg_datum' => $_POST['beleg_datum'] ?: null,
|
'beleg_datum' => $_POST['beleg_datum'] ?: null,
|
||||||
'betrag_brutto' => ($_POST['betrag_brutto'] ?? '') !== '' ? $_POST['betrag_brutto'] : null,
|
|
||||||
'supplier_id' => $supplierId,
|
'supplier_id' => $supplierId,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,27 @@ class BookingController
|
||||||
$data = $_POST;
|
$data = $_POST;
|
||||||
$errors = [];
|
$errors = [];
|
||||||
|
|
||||||
|
// Direkte Kontonummer-Eingabe: nur auflösen wenn nichts per Select gewählt
|
||||||
|
foreach ([
|
||||||
|
'kategorie_kontonummer' => 'kategorie_konto_id',
|
||||||
|
'zahlungs_kontonummer' => 'zahlungskonto_id',
|
||||||
|
] as $field => $idField) {
|
||||||
|
if (!empty($data[$idField])) continue; // Select-Auswahl hat Vorrang
|
||||||
|
$nr = trim($data[$field] ?? '');
|
||||||
|
if ($nr !== '') {
|
||||||
|
$acc = \Steuerkram\Database::fetchOne('SELECT id FROM accounts WHERE kontonummer = ?', [$nr]);
|
||||||
|
if (!$acc) {
|
||||||
|
$errors[$idField] = "Kontonummer '$nr' nicht gefunden.";
|
||||||
|
} else {
|
||||||
|
$data[$idField] = $acc['id'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate
|
// Validate
|
||||||
if (empty($data['buchungstyp'])) $errors['buchungstyp'] = 'Pflichtfeld';
|
if (empty($data['buchungstyp'])) $errors['buchungstyp'] = 'Pflichtfeld';
|
||||||
if (empty($data['kategorie_konto_id'])) $errors['kategorie_konto_id'] = 'Pflichtfeld';
|
if (empty($data['kategorie_konto_id']) && !isset($errors['kategorie_konto_id'])) $errors['kategorie_konto_id'] = 'Pflichtfeld';
|
||||||
if (empty($data['zahlungskonto_id'])) $errors['zahlungskonto_id'] = 'Pflichtfeld';
|
if (empty($data['zahlungskonto_id']) && !isset($errors['zahlungskonto_id'])) $errors['zahlungskonto_id'] = 'Pflichtfeld';
|
||||||
if (empty($data['buchungs_datum'])) $errors['buchungs_datum'] = 'Pflichtfeld';
|
if (empty($data['buchungs_datum'])) $errors['buchungs_datum'] = 'Pflichtfeld';
|
||||||
if (!isset($data['betrag_netto']) || $data['betrag_netto'] === '')
|
if (!isset($data['betrag_netto']) || $data['betrag_netto'] === '')
|
||||||
$errors['betrag_netto'] = 'Pflichtfeld';
|
$errors['betrag_netto'] = 'Pflichtfeld';
|
||||||
|
|
@ -110,14 +127,24 @@ class BookingController
|
||||||
try {
|
try {
|
||||||
$data['beleg_id'] = $belegId;
|
$data['beleg_id'] = $belegId;
|
||||||
|
|
||||||
// Bewirtungskonto-Split: 4650→4654, 4651→4656
|
// Bewirtungsfelder am Beleg speichern (gehören zum Beleg, nicht zur Buchung)
|
||||||
|
\Steuerkram\Database::execute(
|
||||||
|
'UPDATE belege SET bewirtungsgrund=?, teilnehmerliste=?, updated_at=NOW() WHERE id=?',
|
||||||
|
[
|
||||||
|
!empty($data['bewirtungsgrund']) ? $data['bewirtungsgrund'] : null,
|
||||||
|
!empty($data['teilnehmerliste']) ? $data['teilnehmerliste'] : null,
|
||||||
|
$belegId,
|
||||||
|
]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bewirtungskonto-Split: 4650→4654, 4651→4656, 4652→4657
|
||||||
$konto = \Steuerkram\Database::fetchOne(
|
$konto = \Steuerkram\Database::fetchOne(
|
||||||
'SELECT kontonummer FROM accounts WHERE id = ?',
|
'SELECT kontonummer FROM accounts WHERE id = ?',
|
||||||
[(int)$data['kategorie_konto_id']]
|
[(int)$data['kategorie_konto_id']]
|
||||||
);
|
);
|
||||||
$kontonummer = $konto['kontonummer'] ?? '';
|
$kontonummer = $konto['kontonummer'] ?? '';
|
||||||
|
|
||||||
if ($kontonummer === '4650' || $kontonummer === '4651') {
|
if (in_array($kontonummer, ['4650', '4651', '4652'], true)) {
|
||||||
$this->bucheBewirtungssplit($data, $kontonummer);
|
$this->bucheBewirtungssplit($data, $kontonummer);
|
||||||
} else {
|
} else {
|
||||||
Booking::create($data);
|
Booking::create($data);
|
||||||
|
|
@ -171,7 +198,7 @@ class BookingController
|
||||||
private function bucheBewirtungssplit(array $data, string $kontonummer): void
|
private function bucheBewirtungssplit(array $data, string $kontonummer): void
|
||||||
{
|
{
|
||||||
// Abzugskonto ermitteln
|
// Abzugskonto ermitteln
|
||||||
$abzugskontonummer = $kontonummer === '4650' ? '4654' : '4656';
|
$abzugskontonummer = match($kontonummer) { '4650' => '4654', '4652' => '4657', default => '4656' };
|
||||||
$abzugskonto = \Steuerkram\Database::fetchOne(
|
$abzugskonto = \Steuerkram\Database::fetchOne(
|
||||||
'SELECT id FROM accounts WHERE kontonummer = ?',
|
'SELECT id FROM accounts WHERE kontonummer = ?',
|
||||||
[$abzugskontonummer]
|
[$abzugskontonummer]
|
||||||
|
|
@ -189,16 +216,12 @@ class BookingController
|
||||||
// Buchung 1: 70 % auf Bewirtungskonto (abzugsfähig)
|
// Buchung 1: 70 % auf Bewirtungskonto (abzugsfähig)
|
||||||
Booking::create(array_merge($data, [
|
Booking::create(array_merge($data, [
|
||||||
'betrag_netto' => $netto70,
|
'betrag_netto' => $netto70,
|
||||||
'bewirtungsgrund' => $data['bewirtungsgrund'] ?? null,
|
|
||||||
'teilnehmerliste' => $data['teilnehmerliste'] ?? null,
|
|
||||||
]));
|
]));
|
||||||
|
|
||||||
// Buchung 2: 30 % auf Abzugskonto (nicht abzugsfähig, § 4 Abs. 5 EStG)
|
// Buchung 2: 30 % auf Abzugskonto (nicht abzugsfähig, § 4 Abs. 5 EStG)
|
||||||
Booking::create(array_merge($data, [
|
Booking::create(array_merge($data, [
|
||||||
'kategorie_konto_id' => $abzugskonto['id'],
|
'kategorie_konto_id' => $abzugskonto['id'],
|
||||||
'betrag_netto' => $netto30,
|
'betrag_netto' => $netto30,
|
||||||
'bewirtungsgrund' => $data['bewirtungsgrund'] ?? null,
|
|
||||||
'teilnehmerliste' => $data['teilnehmerliste'] ?? null,
|
|
||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,6 @@ class InvoiceController
|
||||||
'mime_type' => 'application/pdf',
|
'mime_type' => 'application/pdf',
|
||||||
'file_hash' => hash('sha256', $invoice['rechnungs_nr']),
|
'file_hash' => hash('sha256', $invoice['rechnungs_nr']),
|
||||||
'beleg_datum' => $invoice['rechnungs_datum'],
|
'beleg_datum' => $invoice['rechnungs_datum'],
|
||||||
'eingangs_datum' => $invoice['rechnungs_datum'],
|
|
||||||
'rechnungs_nr' => $invoice['rechnungs_nr'],
|
'rechnungs_nr' => $invoice['rechnungs_nr'],
|
||||||
'betrag_brutto' => $invoice['betrag_brutto'],
|
'betrag_brutto' => $invoice['betrag_brutto'],
|
||||||
'belegtyp' => 'Ausgangsrechnung',
|
'belegtyp' => 'Ausgangsrechnung',
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,8 @@ class Beleg
|
||||||
|
|
||||||
$offset = ($page - 1) * $perPage;
|
$offset = ($page - 1) * $perPage;
|
||||||
$sql = 'SELECT b.*,
|
$sql = 'SELECT b.*,
|
||||||
COALESCE(b.betrag_brutto,
|
|
||||||
(SELECT SUM(bk.betrag_brutto) FROM bookings bk
|
(SELECT SUM(bk.betrag_brutto) FROM bookings bk
|
||||||
WHERE bk.beleg_id = b.id AND bk.is_reversal = 0)
|
WHERE bk.beleg_id = b.id AND bk.is_reversal = 0
|
||||||
) AS betrag_brutto,
|
) AS betrag_brutto,
|
||||||
fy.year as fiscal_year_nr,
|
fy.year as fiscal_year_nr,
|
||||||
s.name as supplier_name,
|
s.name as supplier_name,
|
||||||
|
|
@ -51,7 +50,7 @@ class Beleg
|
||||||
LEFT JOIN fiscal_years fy ON b.fiscal_year_id = fy.id
|
LEFT JOIN fiscal_years fy ON b.fiscal_year_id = fy.id
|
||||||
LEFT JOIN suppliers s ON b.supplier_id = s.id
|
LEFT JOIN suppliers s ON b.supplier_id = s.id
|
||||||
WHERE ' . implode(' AND ', $where) . '
|
WHERE ' . implode(' AND ', $where) . '
|
||||||
ORDER BY b.eingangs_datum DESC, b.id DESC
|
ORDER BY b.created_at DESC, b.id DESC
|
||||||
LIMIT ? OFFSET ?';
|
LIMIT ? OFFSET ?';
|
||||||
|
|
||||||
$params[] = $perPage;
|
$params[] = $perPage;
|
||||||
|
|
@ -71,9 +70,8 @@ class Beleg
|
||||||
{
|
{
|
||||||
return Database::fetchOne(
|
return Database::fetchOne(
|
||||||
'SELECT b.*,
|
'SELECT b.*,
|
||||||
COALESCE(b.betrag_brutto,
|
|
||||||
(SELECT SUM(bk.betrag_brutto) FROM bookings bk
|
(SELECT SUM(bk.betrag_brutto) FROM bookings bk
|
||||||
WHERE bk.beleg_id = b.id AND bk.is_reversal = 0)
|
WHERE bk.beleg_id = b.id AND bk.is_reversal = 0
|
||||||
) AS betrag_brutto,
|
) AS betrag_brutto,
|
||||||
fy.year as fiscal_year_nr,
|
fy.year as fiscal_year_nr,
|
||||||
s.name as supplier_name,
|
s.name as supplier_name,
|
||||||
|
|
@ -98,8 +96,8 @@ class Beleg
|
||||||
|
|
||||||
Database::execute(
|
Database::execute(
|
||||||
'INSERT INTO belege (beleg_nr, filename, storage_path, mime_type, file_hash,
|
'INSERT INTO belege (beleg_nr, filename, storage_path, mime_type, file_hash,
|
||||||
beleg_datum, eingangs_datum, rechnungs_nr, betrag_brutto, belegtyp, notes, fiscal_year_id)
|
beleg_datum, rechnungs_nr, betrag_brutto, belegtyp, notes, fiscal_year_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
[
|
[
|
||||||
$data['beleg_nr'],
|
$data['beleg_nr'],
|
||||||
$data['filename'],
|
$data['filename'],
|
||||||
|
|
@ -107,7 +105,6 @@ class Beleg
|
||||||
$data['mime_type'],
|
$data['mime_type'],
|
||||||
$data['file_hash'],
|
$data['file_hash'],
|
||||||
$data['beleg_datum'] ?: null,
|
$data['beleg_datum'] ?: null,
|
||||||
$data['eingangs_datum'],
|
|
||||||
$data['rechnungs_nr'] ?? null,
|
$data['rechnungs_nr'] ?? null,
|
||||||
$data['betrag_brutto'] ?? null,
|
$data['betrag_brutto'] ?? null,
|
||||||
$data['belegtyp'] ?? 'Eingangsrechnung',
|
$data['belegtyp'] ?? 'Eingangsrechnung',
|
||||||
|
|
@ -134,13 +131,12 @@ class Beleg
|
||||||
}
|
}
|
||||||
|
|
||||||
Database::execute(
|
Database::execute(
|
||||||
'UPDATE belege SET beleg_datum=?, rechnungs_nr=?, betrag_brutto=?, belegtyp=?, notes=?,
|
'UPDATE belege SET beleg_datum=?, rechnungs_nr=?, belegtyp=?, notes=?,
|
||||||
fiscal_year_id=?, updated_at=NOW()
|
fiscal_year_id=?, updated_at=NOW()
|
||||||
WHERE id=? AND locked=0',
|
WHERE id=? AND locked=0',
|
||||||
[
|
[
|
||||||
$data['beleg_datum'] ?: null,
|
$data['beleg_datum'] ?: null,
|
||||||
$data['rechnungs_nr'] ?? null,
|
$data['rechnungs_nr'] ?? null,
|
||||||
$data['betrag_brutto'] ?? null,
|
|
||||||
$data['belegtyp'] ?? 'Eingangsrechnung',
|
$data['belegtyp'] ?? 'Eingangsrechnung',
|
||||||
$data['notes'] ?? null,
|
$data['notes'] ?? null,
|
||||||
$fyId,
|
$fyId,
|
||||||
|
|
@ -163,7 +159,6 @@ class Beleg
|
||||||
rechnungs_nr = ?,
|
rechnungs_nr = ?,
|
||||||
belegtyp = ?,
|
belegtyp = ?,
|
||||||
beleg_datum = ?,
|
beleg_datum = ?,
|
||||||
betrag_brutto = ?,
|
|
||||||
supplier_id = ?,
|
supplier_id = ?,
|
||||||
fiscal_year_id = COALESCE(?, fiscal_year_id),
|
fiscal_year_id = COALESCE(?, fiscal_year_id),
|
||||||
updated_at = NOW()
|
updated_at = NOW()
|
||||||
|
|
@ -172,7 +167,6 @@ class Beleg
|
||||||
$data['rechnungs_nr'] ?: null,
|
$data['rechnungs_nr'] ?: null,
|
||||||
$data['belegtyp'],
|
$data['belegtyp'],
|
||||||
$data['beleg_datum'] ?: null,
|
$data['beleg_datum'] ?: null,
|
||||||
$data['betrag_brutto'] !== null && $data['betrag_brutto'] !== '' ? (float)$data['betrag_brutto'] : null,
|
|
||||||
isset($data['supplier_id']) && $data['supplier_id'] !== '' ? (int)$data['supplier_id'] : null,
|
isset($data['supplier_id']) && $data['supplier_id'] !== '' ? (int)$data['supplier_id'] : null,
|
||||||
$fyId,
|
$fyId,
|
||||||
$id,
|
$id,
|
||||||
|
|
|
||||||
|
|
@ -105,8 +105,8 @@ class Booking
|
||||||
'INSERT INTO bookings (buchungs_nr, beleg_id, buchungs_datum, buchungstyp,
|
'INSERT INTO bookings (buchungs_nr, beleg_id, buchungs_datum, buchungstyp,
|
||||||
kategorie_konto_id, zahlungskonto_id,
|
kategorie_konto_id, zahlungskonto_id,
|
||||||
betrag_netto, ust_satz, steuerart, betrag_ust, betrag_brutto,
|
betrag_netto, ust_satz, steuerart, betrag_ust, betrag_brutto,
|
||||||
buchungstext, bewirtungsgrund, teilnehmerliste, fiscal_year_id)
|
buchungstext, fiscal_year_id)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||||
[
|
[
|
||||||
$nr,
|
$nr,
|
||||||
(int)$data['beleg_id'],
|
(int)$data['beleg_id'],
|
||||||
|
|
@ -120,8 +120,6 @@ class Booking
|
||||||
$ust,
|
$ust,
|
||||||
$brutto,
|
$brutto,
|
||||||
$data['buchungstext'],
|
$data['buchungstext'],
|
||||||
$data['bewirtungsgrund'] ?? null,
|
|
||||||
$data['teilnehmerliste'] ?? null,
|
|
||||||
$fy['id'],
|
$fy['id'],
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -269,7 +269,6 @@ class NextcloudImportService
|
||||||
'mime_type' => $contentType,
|
'mime_type' => $contentType,
|
||||||
'file_hash' => $hash,
|
'file_hash' => $hash,
|
||||||
'beleg_datum' => null,
|
'beleg_datum' => null,
|
||||||
'eingangs_datum' => $today,
|
|
||||||
'rechnungs_nr' => null,
|
'rechnungs_nr' => null,
|
||||||
'betrag_brutto' => null,
|
'betrag_brutto' => null,
|
||||||
'belegtyp' => 'Eingangsrechnung',
|
'belegtyp' => 'Eingangsrechnung',
|
||||||
|
|
|
||||||
|
|
@ -57,10 +57,7 @@ $suppliers = $suppliers ?? [];
|
||||||
<?= View::formatDate($beleg['beleg_datum']) ?>
|
<?= View::formatDate($beleg['beleg_datum']) ?>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
|
||||||
<span class="text-muted text-sm">Eingangsdatum</span><br>
|
|
||||||
<?= View::formatDate($beleg['eingangs_datum']) ?>
|
|
||||||
</div>
|
|
||||||
<div>
|
<div>
|
||||||
<span class="text-muted text-sm">Rechnungsnr.<?= !$beleg['locked'] ? ' <span style="opacity:.4;font-size:.7rem">✎</span>' : '' ?></span><br>
|
<span class="text-muted text-sm">Rechnungsnr.<?= !$beleg['locked'] ? ' <span style="opacity:.4;font-size:.7rem">✎</span>' : '' ?></span><br>
|
||||||
<?php if (!$beleg['locked']): ?>
|
<?php if (!$beleg['locked']): ?>
|
||||||
|
|
@ -75,7 +72,7 @@ $suppliers = $suppliers ?? [];
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<span class="text-muted text-sm">Brutto lt. Beleg</span><br>
|
<span class="text-muted text-sm">Brutto (Buchungen)</span><br>
|
||||||
<?= $beleg['betrag_brutto'] ? '<strong>' . $fmt($beleg['betrag_brutto']) . '</strong>' : '<span class="text-muted">–</span>' ?>
|
<?= $beleg['betrag_brutto'] ? '<strong>' . $fmt($beleg['betrag_brutto']) . '</strong>' : '<span class="text-muted">–</span>' ?>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -86,6 +83,17 @@ $suppliers = $suppliers ?? [];
|
||||||
<span class="badge badge-red">⚠ Prüfsumme abweichend</span>
|
<span class="badge badge-red">⚠ Prüfsumme abweichend</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</div>
|
</div>
|
||||||
|
<?php if (!empty($beleg['bewirtungsgrund']) || !empty($beleg['teilnehmerliste'])): ?>
|
||||||
|
<div>
|
||||||
|
<span class="text-muted text-sm">Bewirtung</span><br>
|
||||||
|
<?php if (!empty($beleg['bewirtungsgrund'])): ?>
|
||||||
|
<span><?= $h($beleg['bewirtungsgrund']) ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if (!empty($beleg['teilnehmerliste'])): ?>
|
||||||
|
<span class="text-muted" style="font-size:.85em"> · <?= $h($beleg['teilnehmerliste']) ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<div style="margin-left:auto;display:flex;gap:.5rem">
|
<div style="margin-left:auto;display:flex;gap:.5rem">
|
||||||
<a href="/belege/<?= $h($beleg['id']) ?>/file" target="_blank" class="btn btn-secondary btn-sm">Datei öffnen</a>
|
<a href="/belege/<?= $h($beleg['id']) ?>/file" target="_blank" class="btn btn-secondary btn-sm">Datei öffnen</a>
|
||||||
<?php if (!$beleg['locked'] && in_array($beleg['mime_type'], ['image/jpeg', 'image/png'])): ?>
|
<?php if (!$beleg['locked'] && in_array($beleg['mime_type'], ['image/jpeg', 'image/png'])): ?>
|
||||||
|
|
@ -127,11 +135,7 @@ $suppliers = $suppliers ?? [];
|
||||||
<label style="font-size:.8rem">Belegdatum</label>
|
<label style="font-size:.8rem">Belegdatum</label>
|
||||||
<input type="date" name="beleg_datum" value="<?= $h($beleg['beleg_datum'] ?? '') ?>">
|
<input type="date" name="beleg_datum" value="<?= $h($beleg['beleg_datum'] ?? '') ?>">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="margin:0;min-width:120px">
|
|
||||||
<label style="font-size:.8rem">Brutto lt. Beleg (€)</label>
|
|
||||||
<input type="number" name="betrag_brutto" step="0.01" min="0"
|
|
||||||
value="<?= $h($beleg['betrag_brutto'] ?? '') ?>" placeholder="0.00">
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin:0;min-width:180px">
|
<div class="form-group" style="margin:0;min-width:180px">
|
||||||
<label style="font-size:.8rem">Lieferant</label>
|
<label style="font-size:.8rem">Lieferant</label>
|
||||||
<input type="text" name="supplier_name" id="supplier_name_input"
|
<input type="text" name="supplier_name" id="supplier_name_input"
|
||||||
|
|
@ -217,12 +221,6 @@ $suppliers = $suppliers ?? [];
|
||||||
<?php elseif ($isReversed): ?>
|
<?php elseif ($isReversed): ?>
|
||||||
<span class="badge badge-red">Storniert</span>
|
<span class="badge badge-red">Storniert</span>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
<?php if (!empty($bk['bewirtungsgrund'])): ?>
|
|
||||||
<br><span class="td-muted" style="font-size:.8em">Grund: <?= $h($bk['bewirtungsgrund']) ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
<?php if (!empty($bk['teilnehmerliste'])): ?>
|
|
||||||
<br><span class="td-muted" style="font-size:.8em">Teilnehmer: <?= $h($bk['teilnehmerliste']) ?></span>
|
|
||||||
<?php endif; ?>
|
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<?php if (!$bk['locked'] && !$isReversal && !$isReversed): ?>
|
<?php if (!$bk['locked'] && !$isReversal && !$isReversed): ?>
|
||||||
|
|
@ -378,12 +376,13 @@ $suppliers = $suppliers ?? [];
|
||||||
<label for="kategorie_konto_id">Kategorie *
|
<label for="kategorie_konto_id">Kategorie *
|
||||||
<span id="kategorie_konto_art" class="badge badge-gray" style="margin-left:.5rem;font-size:.7rem"></span>
|
<span id="kategorie_konto_art" class="badge badge-gray" style="margin-left:.5rem;font-size:.7rem"></span>
|
||||||
</label>
|
</label>
|
||||||
<input type="search" placeholder="Kontonr. oder Bezeichnung filtern…" class="konto-filter"
|
<input type="search" name="kategorie_kontonummer" placeholder="Kontonr. oder Bezeichnung filtern – oder direkt eingeben" class="konto-filter"
|
||||||
data-target="kategorie_konto_id" autocomplete="off" style="margin-bottom:.3rem">
|
data-target="kategorie_konto_id" autocomplete="off" style="margin-bottom:.3rem"
|
||||||
<select id="kategorie_konto_id" name="kategorie_konto_id" required size="6"
|
value="<?= $h($formData['kategorie_kontonummer'] ?? '') ?>">
|
||||||
|
<select id="kategorie_konto_id" name="kategorie_konto_id" size="6"
|
||||||
onchange="showKontoArt('kategorie_konto_id','kategorie_konto_art',this);updateEigenanteilState();updateBewirtungsState();updateAutoUst()">
|
onchange="showKontoArt('kategorie_konto_id','kategorie_konto_art',this);updateEigenanteilState();updateBewirtungsState();updateAutoUst()">
|
||||||
<option value="">– Konto wählen –</option>
|
<option value="">– Konto wählen –</option>
|
||||||
<?php foreach (['Betriebsausgabe', 'Betriebseinnahme', 'Privat'] as $art): ?>
|
<?php foreach (['Betriebsausgabe', 'Betriebseinnahme', 'Privat', 'Verbindlichkeit'] as $art): ?>
|
||||||
<?php if (empty($kontenGruppen[$art])) continue; ?>
|
<?php if (empty($kontenGruppen[$art])) continue; ?>
|
||||||
<optgroup label="── <?= $h($art) ?> ──" data-kontenart="<?= $h($art) ?>">
|
<optgroup label="── <?= $h($art) ?> ──" data-kontenart="<?= $h($art) ?>">
|
||||||
<?php foreach ($kontenGruppen[$art] as $acc): ?>
|
<?php foreach ($kontenGruppen[$art] as $acc): ?>
|
||||||
|
|
@ -405,9 +404,10 @@ $suppliers = $suppliers ?? [];
|
||||||
<label for="zahlungskonto_id">Zahlungskonto *
|
<label for="zahlungskonto_id">Zahlungskonto *
|
||||||
<span id="zahlungskonto_art" class="badge badge-gray" style="margin-left:.5rem;font-size:.7rem"></span>
|
<span id="zahlungskonto_art" class="badge badge-gray" style="margin-left:.5rem;font-size:.7rem"></span>
|
||||||
</label>
|
</label>
|
||||||
<input type="search" placeholder="Kontonr. oder Bezeichnung filtern…" class="konto-filter"
|
<input type="search" name="zahlungs_kontonummer" placeholder="Kontonr. oder Bezeichnung filtern – oder direkt eingeben" class="konto-filter"
|
||||||
data-target="zahlungskonto_id" autocomplete="off" style="margin-bottom:.3rem">
|
data-target="zahlungskonto_id" autocomplete="off" style="margin-bottom:.3rem"
|
||||||
<select id="zahlungskonto_id" name="zahlungskonto_id" required size="4"
|
value="<?= $h($formData['zahlungs_kontonummer'] ?? '') ?>">
|
||||||
|
<select id="zahlungskonto_id" name="zahlungskonto_id" size="4"
|
||||||
onchange="showKontoArt('zahlungskonto_id','zahlungskonto_art',this)">
|
onchange="showKontoArt('zahlungskonto_id','zahlungskonto_art',this)">
|
||||||
<option value="">– Konto wählen –</option>
|
<option value="">– Konto wählen –</option>
|
||||||
<?php foreach (['Zahlungskonto', 'Verbindlichkeit'] as $art): ?>
|
<?php foreach (['Zahlungskonto', 'Verbindlichkeit'] as $art): ?>
|
||||||
|
|
@ -451,7 +451,7 @@ $suppliers = $suppliers ?? [];
|
||||||
|
|
||||||
<!-- Bewirtungsfelder (nur bei Konto 4650/4651) -->
|
<!-- Bewirtungsfelder (nur bei Konto 4650/4651) -->
|
||||||
<div id="bewirtungsfelder" style="display:none">
|
<div id="bewirtungsfelder" style="display:none">
|
||||||
<div class="flash flash-info" style="margin-bottom:.75rem;padding:.5rem .75rem;font-size:.85rem">
|
<div class="flash flash-info flash-persistent" style="margin-bottom:.75rem;padding:.5rem .75rem;font-size:.85rem">
|
||||||
<strong>Bewirtungsausgabe:</strong> 70 % werden auf das gewählte Konto gebucht, 30 % automatisch auf das Abzugskonto. Die Vorsteuer wird vollständig berücksichtigt.
|
<strong>Bewirtungsausgabe:</strong> 70 % werden auf das gewählte Konto gebucht, 30 % automatisch auf das Abzugskonto. Die Vorsteuer wird vollständig berücksichtigt.
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
|
@ -459,13 +459,13 @@ $suppliers = $suppliers ?? [];
|
||||||
<textarea name="bewirtungsgrund" id="bewirtungsgrund_input"
|
<textarea name="bewirtungsgrund" id="bewirtungsgrund_input"
|
||||||
style="height:2.4em;resize:none;overflow:hidden"
|
style="height:2.4em;resize:none;overflow:hidden"
|
||||||
oninput="this.style.height='auto';this.style.height=this.scrollHeight+'px'"
|
oninput="this.style.height='auto';this.style.height=this.scrollHeight+'px'"
|
||||||
placeholder="Anlass/Grund der Bewirtung"><?= $h($formData['bewirtungsgrund'] ?? '') ?></textarea>
|
placeholder="Anlass/Grund der Bewirtung"><?= $h($formData['bewirtungsgrund'] ?? $beleg['bewirtungsgrund'] ?? '') ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="teilnehmerliste_input">Teilnehmerliste *</label>
|
<label for="teilnehmerliste_input">Teilnehmerliste *</label>
|
||||||
<textarea name="teilnehmerliste" id="teilnehmerliste_input"
|
<textarea name="teilnehmerliste" id="teilnehmerliste_input"
|
||||||
style="height:5.4em;resize:vertical"
|
style="height:5.4em;resize:vertical"
|
||||||
placeholder="Namen der Teilnehmer"><?= $h($formData['teilnehmerliste'] ?? '') ?></textarea>
|
placeholder="Namen der Teilnehmer"><?= $h($formData['teilnehmerliste'] ?? $beleg['teilnehmerliste'] ?? '') ?></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -497,8 +497,8 @@ function filterKategorieKonten(buchungstyp) {
|
||||||
groups.forEach(function(g) {
|
groups.forEach(function(g) {
|
||||||
const art = g.getAttribute('data-kontenart');
|
const art = g.getAttribute('data-kontenart');
|
||||||
if (!art) return;
|
if (!art) return;
|
||||||
// Privat immer anzeigen, Kategorie nach Typ filtern
|
// Privat und Verbindlichkeit immer anzeigen, Kategorie nach Typ filtern
|
||||||
g.style.display = (art === zielArt || art === 'Privat') ? '' : 'none';
|
g.style.display = (art === zielArt || art === 'Privat' || art === 'Verbindlichkeit') ? '' : 'none';
|
||||||
});
|
});
|
||||||
|
|
||||||
// Auswahl zurücksetzen wenn aktuell gewähltes Konto nicht mehr sichtbar
|
// Auswahl zurücksetzen wenn aktuell gewähltes Konto nicht mehr sichtbar
|
||||||
|
|
@ -518,8 +518,10 @@ function updateAutoUst() {
|
||||||
const selectedOpt = kategorieEl.options[kategorieEl.selectedIndex];
|
const selectedOpt = kategorieEl.options[kategorieEl.selectedIndex];
|
||||||
const steuercode = selectedOpt ? (selectedOpt.getAttribute('data-steuercode') || '') : '';
|
const steuercode = selectedOpt ? (selectedOpt.getAttribute('data-steuercode') || '') : '';
|
||||||
|
|
||||||
|
const kontonummer = selectedOpt ? (selectedOpt.getAttribute('data-kontonummer') || '') : '';
|
||||||
const ustMap = { 'VSt19': '19', 'USt19': '19', 'VSt7': '7', 'USt7': '7' };
|
const ustMap = { 'VSt19': '19', 'USt19': '19', 'VSt7': '7', 'USt7': '7' };
|
||||||
const autoUst = ustMap[steuercode] || null;
|
// 4652/4657 immer 0 % (keine Vorsteuer bei pauschalen Bewirtungskosten ohne USt-Ausweis)
|
||||||
|
const autoUst = (['4652','4657'].includes(kontonummer)) ? '0' : (ustMap[steuercode] || null);
|
||||||
|
|
||||||
const hiddenEl = document.getElementById('ust_satz_hidden');
|
const hiddenEl = document.getElementById('ust_satz_hidden');
|
||||||
if (autoUst !== null) {
|
if (autoUst !== null) {
|
||||||
|
|
@ -543,7 +545,7 @@ function updateBewirtungsState() {
|
||||||
|
|
||||||
const selectedOpt = kategorieEl.options[kategorieEl.selectedIndex];
|
const selectedOpt = kategorieEl.options[kategorieEl.selectedIndex];
|
||||||
const kontonummer = selectedOpt ? (selectedOpt.getAttribute('data-kontonummer') || '') : '';
|
const kontonummer = selectedOpt ? (selectedOpt.getAttribute('data-kontonummer') || '') : '';
|
||||||
const istBewirtung = kontonummer === '4650' || kontonummer === '4651';
|
const istBewirtung = ['4650','4651','4652'].includes(kontonummer);
|
||||||
|
|
||||||
felder.style.display = istBewirtung ? '' : 'none';
|
felder.style.display = istBewirtung ? '' : 'none';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,7 @@
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('beleg_file', file);
|
fd.append('beleg_file', file);
|
||||||
fd.append('belegtyp', 'Eingangsrechnung');
|
fd.append('belegtyp', 'Eingangsrechnung');
|
||||||
fd.append('eingangs_datum', new Date().toISOString().slice(0,10));
|
|
||||||
fd.append('beleg_datum', new Date().toISOString().slice(0,10));
|
fd.append('beleg_datum', new Date().toISOString().slice(0,10));
|
||||||
|
|
||||||
fetch('/belege/upload', {
|
fetch('/belege/upload', {
|
||||||
|
|
@ -132,7 +132,7 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Belegnr.</th>
|
<th>Belegnr.</th>
|
||||||
<th>Eingangsdatum</th>
|
|
||||||
<th>Belegdatum</th>
|
<th>Belegdatum</th>
|
||||||
<th>Lieferant</th>
|
<th>Lieferant</th>
|
||||||
<th>Rechnungsnr.</th>
|
<th>Rechnungsnr.</th>
|
||||||
|
|
@ -146,7 +146,7 @@
|
||||||
<?php foreach ($rows as $b): ?>
|
<?php foreach ($rows as $b): ?>
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="/belege/<?= $h($b['id']) ?>" class="font-mono"><?= $h($b['beleg_nr']) ?></a></td>
|
<td><a href="/belege/<?= $h($b['id']) ?>" class="font-mono"><?= $h($b['beleg_nr']) ?></a></td>
|
||||||
<td class="td-muted"><?= View::formatDate($b['eingangs_datum']) ?></td>
|
|
||||||
<td class="td-muted"><?= View::formatDate($b['beleg_datum']) ?></td>
|
<td class="td-muted"><?= View::formatDate($b['beleg_datum']) ?></td>
|
||||||
<td class="td-muted"><?= $h($b['supplier_name'] ?? '–') ?></td>
|
<td class="td-muted"><?= $h($b['supplier_name'] ?? '–') ?></td>
|
||||||
<td class="td-muted"><?= $h($b['rechnungs_nr'] ?? '–') ?></td>
|
<td class="td-muted"><?= $h($b['rechnungs_nr'] ?? '–') ?></td>
|
||||||
|
|
|
||||||
|
|
@ -25,11 +25,7 @@
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="eingangs_datum">Eingangsdatum *</label>
|
|
||||||
<input type="date" id="eingangs_datum" name="eingangs_datum"
|
|
||||||
value="<?= $h($old['eingangs_datum'] ?? date('Y-m-d')) ?>" required>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-grid form-grid-2">
|
<div class="form-grid form-grid-2">
|
||||||
|
|
@ -46,12 +42,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="betrag_brutto">Bruttobetrag (€)</label>
|
|
||||||
<input type="number" id="betrag_brutto" name="betrag_brutto"
|
|
||||||
value="<?= $h($old['betrag_brutto'] ?? '') ?>"
|
|
||||||
step="0.01" min="0" placeholder="0.00">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="notes">Notizen</label>
|
<label for="notes">Notizen</label>
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ $fmt = fn($v) => View::formatMoney($v);
|
||||||
const fd = new FormData();
|
const fd = new FormData();
|
||||||
fd.append('beleg_file', file);
|
fd.append('beleg_file', file);
|
||||||
fd.append('belegtyp', 'Eingangsrechnung');
|
fd.append('belegtyp', 'Eingangsrechnung');
|
||||||
fd.append('eingangs_datum', new Date().toISOString().slice(0,10));
|
|
||||||
fd.append('beleg_datum', new Date().toISOString().slice(0,10));
|
fd.append('beleg_datum', new Date().toISOString().slice(0,10));
|
||||||
|
|
||||||
fetch('/belege/upload', {
|
fetch('/belege/upload', {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue