Add fis_wdg_* table functions for dashboard widgets and wire them into FuchsDatabase.sqlproj; update the invoice list procs accordingly. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,11 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_balance_net_thismonth' (Umsatz diesen Monat).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_balance_net_thismonth](@authuser)
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_balance_net_thismonth](@authuser varchar(100))
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = FORMAT(GETDATE(), 'MMMM yy', 'de'), [value] = [dbo].[fds__r_getBalanceThisMonth](@authuser)
|
||||
);
|
||||
@@ -0,0 +1,16 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_bankingupload' (Bank-Buchungen).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_bankingupload]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_bankingupload]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT TOP (1) [label] = N'Letzte Übertragung der Bankdaten am ' + FORMAT(CAST([value] as date), 'dd.MM.', 'de')
|
||||
, [value] = FORMAT(DATEDIFF(DAY, CAST([value] as date), CAST(GETDATE() as date)), '0', 'de') + ' d'
|
||||
, [status] = IIF(DATEDIFF(DAY, CAST([value] as date), CAST(GETDATE() as date)) > 6, 'neg', 'pos')
|
||||
FROM [dbo].[fds__admin_settings]
|
||||
WHERE [type] = 'log' AND [key] = 'bankingtransaction_merge'
|
||||
ORDER BY TRY_CAST([value] as date) DESC
|
||||
);
|
||||
@@ -0,0 +1,14 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_overdue' (Unbezahlte Rechungen Überfällig).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_overdue]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_overdue]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = N'überfällige Rechnungen (10wd)', [value] = COUNT(*)
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]()
|
||||
WHERE [dbo].[fds__fn_invoiceDate]([DateFinalized], NULL) >= DATEFROMPARTS(2026, 1, 1)
|
||||
AND [dbo].[date_addcustom]([dbo].[fds__fn_invoiceDate]([DateFinalized], NULL), '10wd') < CAST(GETDATE() as date)
|
||||
);
|
||||
@@ -0,0 +1,15 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_overdue_sum' (Summe überfällige Rechnungen).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_overdue_sum]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_overdue_sum]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = N'Summe überfällige Rechnungen (10wd, Teilzahlungen ab ' + FORMAT((SELECT MIN([valuedate]) FROM [dbo].[fds__bankingtransactions]), 'dd.MM.yy', 'de') + ' berücksichtigt) '
|
||||
, [value] = FORMAT(0.001 * SUM([OpenAmount]), '#0', 'de') + N'k€'
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]()
|
||||
WHERE [dbo].[fds__fn_invoiceDate]([DateFinalized], NULL) >= DATEFROMPARTS(2026, 1, 1)
|
||||
AND [dbo].[date_addcustom]([dbo].[fds__fn_invoiceDate]([DateFinalized], NULL), '10wd') < CAST(GETDATE() as date)
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_reminded_fds' (Überfällige, angemahnte Rechnungen (Intranet)).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_reminded_fds]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_reminded_fds]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
WITH rem AS (SELECT [invid], [rem#] = COUNT(*) FROM [dbo].[fds__reminder] AS r GROUP BY [invid])
|
||||
SELECT [label] = N'angemahnte, überfällige Rechnungen (10wd, nur Intranet)', [value] = COUNT(*)
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]() AS i
|
||||
LEFT JOIN rem ON i.[id] = rem.[InvId]
|
||||
WHERE i.[fds] = 1
|
||||
AND [dbo].[fds__fn_invoiceDate](i.[DateFinalized], NULL) >= DATEFROMPARTS(2026, 1, 1)
|
||||
AND [dbo].[date_addcustom]([dbo].[fds__fn_invoiceDate](i.[DateFinalized], NULL), '10wd') < CAST(GETDATE() as date)
|
||||
AND ISNULL(rem.[rem#], 0) > 0
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_today' (Rechnungen Heute).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_today]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_today]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = N'Rechnungen heute erstellt'
|
||||
, [value] = FORMAT((SELECT COUNT(*) FROM [dbo].[fds__invoices] WHERE CAST([DateFinalized] as date) = CAST(GETDATE() as date)), '#0')
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_unpaid' (Unbezahlte Rechnungen).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_unpaid]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_unpaid]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = N'unbez. Rechnungen', [value] = COUNT(*)
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]()
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_unreminded_fds' (Überfällige, ungemahnte Rechnungen (Intranet)).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_unreminded_fds]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_unreminded_fds]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
WITH rem AS (SELECT [invid], [rem#] = COUNT(*) FROM [dbo].[fds__reminder] AS r GROUP BY [invid])
|
||||
SELECT [label] = N'UNgemahnte, überfällige Rechnungen (10wd, nur Intranet)', [value] = COUNT(*)
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]() AS i
|
||||
LEFT JOIN rem ON i.[id] = rem.[InvId]
|
||||
WHERE i.[fds] = 1
|
||||
AND [dbo].[fds__fn_invoiceDate](i.[DateFinalized], NULL) >= DATEFROMPARTS(2026, 1, 1)
|
||||
AND [dbo].[date_addcustom]([dbo].[fds__fn_invoiceDate](i.[DateFinalized], NULL), '10wd') < CAST(GETDATE() as date)
|
||||
AND ISNULL(rem.[rem#], 0) = 0
|
||||
);
|
||||
@@ -0,0 +1,12 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_invoices_yesterday' (Rechnung des letzten Werktags).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_invoices_yesterday]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_invoices_yesterday]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [label] = N'Rechnungen erstellt am ' + FORMAT(CAST([dbo].[date_add](GETDATE(), '-1wd', 0) as date), 'dd.MM.yy', 'de')
|
||||
, [value] = FORMAT((SELECT COUNT(*) FROM [dbo].[fds__invoices] WHERE CAST([DateFinalized] as date) = CAST([dbo].[date_add](GETDATE(), '-1wd', 0) as date)), '#0')
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_reminder_open10wd' (Offene Mahnungen, älter 10wd).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_reminder_open10wd]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_reminder_open10wd]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
WITH rem AS (SELECT [invid], [rem#] = COUNT(*), [last] = MAX([DateFinalized]) FROM [dbo].[fds__reminder] AS r GROUP BY [invid])
|
||||
SELECT [label] = N'ALTE offene Mahnungen (10wd, nur Intranet)', [value] = COUNT(*)
|
||||
FROM [dbo].[fds__fn_unpaidInvoices]() AS i
|
||||
LEFT JOIN rem ON i.[id] = rem.[InvId]
|
||||
WHERE i.[fds] = 1
|
||||
AND [dbo].[fds__fn_invoiceDate](i.[DateFinalized], NULL) >= DATEFROMPARTS(2026, 1, 1)
|
||||
AND [dbo].[date_addcustom]([dbo].[fds__fn_invoiceDate](rem.[last], NULL), '10wd') < CAST(GETDATE() as date)
|
||||
AND ISNULL(rem.[rem#], 0) > 0
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_requests_today' (Aufträge terminiert für heute).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_requests_today]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_requests_today]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
WITH osrq AS (
|
||||
SELECT s.[id], s.[name], s.[externalid], s.[customerId]
|
||||
, [last_appointment] = MAX(CAST(a.[startdatetime] as date)), [#a] = COUNT(*)
|
||||
FROM [dbo].[mfr__servicerequests] AS s
|
||||
JOIN [dbo].[mfr__appointments] AS a ON s.[id] = a.[ServiceRequestId]
|
||||
WHERE s.[state] IN ('Scheduled', 'Released', 'InProgress')
|
||||
GROUP BY s.[id], s.[name], s.[externalid], s.[customerId])
|
||||
SELECT [Nummer] = [externalid], [Auftrag] = [name], [Kunde] = [dbo].[fds__getCompanyName]([customerId])
|
||||
FROM osrq
|
||||
WHERE [last_appointment] = CAST(GETDATE() as date)
|
||||
);
|
||||
@@ -0,0 +1,18 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_requestsforinvoice' (Aufträge zur Rechnungsstellung).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_requestsforinvoice]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_requestsforinvoice]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT rfi.[Id]
|
||||
, [Nummer] = rfi.[ExternalId]
|
||||
, [Auftrag] = rfi.[Name]
|
||||
, [Arbeit erledigt am] = FORMAT(rfi.[workdoneat], 'dd.MM.', 'de')
|
||||
, [Freigegeben am] = FORMAT(rfi.[ReleasedAt], 'dd.MM.', 'de')
|
||||
, [Kunde] = c.[name]
|
||||
FROM [dbo].[fds__fn_requestsforinvoice]() AS rfi
|
||||
LEFT JOIN [dbo].[mfr__companies] AS c ON c.[id] = rfi.[CustomerId]
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
-- =============================================
|
||||
-- Description: Dashboard widget 'wdg_unbez_akonto' (Unbezahlte Akontos älter als 5 Arbeitstage (ohne MFR !)).
|
||||
-- Called from [dbo].[fis_widgets].[sql] as: SELECT * FROM [dbo].[fis_wdg_unbez_akonto]()
|
||||
-- =============================================
|
||||
CREATE FUNCTION [dbo].[fis_wdg_unbez_akonto]()
|
||||
RETURNS TABLE
|
||||
AS
|
||||
RETURN
|
||||
(
|
||||
SELECT [Rechnung] = i.[invoiceId]
|
||||
, [Name] = i.[InvoiceTitle] + CHAR(10) + ' (' + (SELECT TOP (1) c.[name] FROM [dbo].[mfr__companies] AS c WHERE i.[customerid] = c.[id]) + ')'
|
||||
, [Betrag (net)] = FORMAT(i.[invoicebalance], N'#0.00€', 'de')
|
||||
, [Datum] = FORMAT(i.[DateFinalized], 'dd.MM.yy', 'de')
|
||||
, [Zahlungen] = FORMAT(ISNULL(pay.[Amount], 0.0), N'#0.00€', 'de')
|
||||
, [order] = ROW_NUMBER() OVER (ORDER BY i.[DateFinalized], i.[DateSent])
|
||||
FROM [dbo].[fds__invoices] AS i
|
||||
LEFT JOIN [dbo].[fds__fn_InvoicePaymentAmounts]() AS pay ON pay.[InvId] = i.[id]
|
||||
WHERE i.[InvoiceType] = 'i' AND i.[IsPayed] = 0 AND i.[iscanceled] = 0
|
||||
AND i.[DateFinalized] < [dbo].[date_add](GETDATE(), '-5wd', 0)
|
||||
);
|
||||
@@ -1,12 +1,25 @@
|
||||
|
||||
CREATE FUNCTION [dbo].[strings_encodeHTML](@inputText NVARCHAR(MAX))
|
||||
CREATE FUNCTION [dbo].[strings_encodeHTML](@inputText NVARCHAR(MAX))
|
||||
RETURNS NVARCHAR(MAX)
|
||||
AS
|
||||
BEGIN
|
||||
DECLARE @encodedText NVARCHAR(MAX);
|
||||
DECLARE @encodedText NVARCHAR(MAX) = N'';
|
||||
|
||||
-- Use FOR XML PATH to escape special characters
|
||||
SET @encodedText = CAST((SELECT @inputText AS [p] FOR XML PATH(''), TYPE) as nvarchar(max));
|
||||
IF DATALENGTH(@inputText) > 0
|
||||
BEGIN
|
||||
/* 1) Escape reserved HTML characters (& < >); FOR XML also entitizes CR as 
 */
|
||||
SET @encodedText = CAST((SELECT @inputText AS [p] FOR XML PATH(''), TYPE) AS NVARCHAR(MAX));
|
||||
|
||||
RETURN IIF(LEN(@encodedText) < 7, '', dbo.strings_replaceSpecialCharsInHTML(SUBSTRING(@encodedText, 4, LEN(@encodedText) -7)));
|
||||
END;
|
||||
/* 2) Remove the leading <p> and trailing </p> that FOR XML adds */
|
||||
SET @encodedText = SUBSTRING(@encodedText, 4, LEN(@encodedText) - 7);
|
||||
|
||||
/* 3) Line breaks (CRLF, LF, lone CR) -> <br>; NBSP -> */
|
||||
SET @encodedText = REPLACE(@encodedText, N'
' + NCHAR(10), N'<br>');
|
||||
SET @encodedText = REPLACE(@encodedText, NCHAR(13) + NCHAR(10), N'<br>');
|
||||
SET @encodedText = REPLACE(@encodedText, NCHAR(10), N'<br>');
|
||||
SET @encodedText = REPLACE(@encodedText, N'
', N'<br>');
|
||||
SET @encodedText = REPLACE(@encodedText, NCHAR(13), N'<br>');
|
||||
SET @encodedText = REPLACE(@encodedText, NCHAR(160), N' ');
|
||||
END
|
||||
|
||||
RETURN @encodedText;
|
||||
END;
|
||||
|
||||
Reference in New Issue
Block a user