Refactor stored procedure and update project structure
Playwright Tests / test (push) Has been cancelled

- Modified the stored procedure `fds__admin_getReportCatalog.sql` to use the correct schema for `all_objects`.
- Added new folders and projects for `eRechnungLib` in the solution file `Fuchs_Intranet.slnx`, including validation and test projects.
- Updated submodule reference for `OCORE`.
- Added new submodule `eRechnungLib` with initial commit.
This commit is contained in:
2026-07-06 00:01:35 +02:00
parent daac828c19
commit 4abf81cd7d
27 changed files with 1544 additions and 94 deletions
@@ -235,7 +235,7 @@ public partial class IntranetController
}
default:
return Ok();
return await JSONAsync(new { ok = true });
}
}
@@ -36,7 +36,7 @@ public partial class IntranetController
StdParamlist(SQL_VarChar("@Id", invoiceId)),
Security: DbSec, options: SqlOpt(fn, id, code));
if (!ok) _logger.LogError("setpyd: SQL failed for invoice {InvoiceId}, user={User}", invoiceId, UserAccountID);
return ok ? Ok() : StatusCode(500);
return ok ? await JSONAsync(new { ok = true }) : StatusCode(500);
}
case "setupd":
@@ -50,7 +50,7 @@ public partial class IntranetController
StdParamlist(SQL_VarChar("@Id", invoiceId)),
Security: DbSec, options: SqlOpt(fn, id, code));
if (!ok) _logger.LogError("setupd: SQL failed for invoice {InvoiceId}, user={User}", invoiceId, UserAccountID);
return ok ? Ok() : StatusCode(500);
return ok ? await JSONAsync(new { ok = true }) : StatusCode(500);
}
case "setvat":
@@ -72,7 +72,7 @@ public partial class IntranetController
_intranet.Intranet_SqlCon(), ref sqlEx, ref sqlCode, pl, Security: DbSec);
if (!string.IsNullOrEmpty(sqlEx))
_logger.LogError("setvat: SQL error for report {ReportId}: {SqlError}, user={User}", Form("id"), sqlEx, UserAccountID);
return string.IsNullOrEmpty(sqlEx) ? Ok() : StatusCode(500, new { error = sqlEx });
return string.IsNullOrEmpty(sqlEx) ? await JSONAsync(new { ok = true }) : StatusCode(500, new { error = sqlEx });
}
case "sis":
@@ -94,7 +94,7 @@ public partial class IntranetController
}
else
await _events.InvoiceMarkedSentAsync(invoiceId, invoiceId, UserAccountID);
return string.IsNullOrEmpty(dt2.Exception) ? Ok() : StatusCode(500);
return string.IsNullOrEmpty(dt2.Exception) ? await JSONAsync(new { ok = true }) : StatusCode(500);
}
case "pget":
@@ -156,11 +156,11 @@ public partial class IntranetController
using (var mfr = _mfrFactory.Create())
await mfr.Update__entitytable(EntityTypes.Invoice,
fds.FdsMfr.UpdateNeed.Reset, new[] { relId });
return Ok();
return await JSONAsync(new { ok = true });
default:
_logger.LogWarning("Do_Process_Invoices: unhandled action id={Id}, user={User}", id, UserAccountID);
return Ok();
return await JSONAsync(new { ok = true });
}
}
}
@@ -58,7 +58,7 @@ public partial class IntranetController
_logger.LogInformation("HandleInvoicePget reset complete for tgtid={TgtId} invoices={InvCount} serviceRequests={SrqCount} user={User}",
tgtid, invIds.Count, srqIds.Count, UserAccountID);
}
return Ok();
return await JSONAsync(new { ok = true });
}
private async Task<IActionResult> HandleInvoiceGet(string fn, string id, string code)
@@ -66,7 +66,7 @@ public partial class IntranetController
await _events.ReminderIssueAsync(
$"Mahnung {Form("id")} konnte nicht als versandt markiert werden.",
UserAccountID, Form("id"));
return string.IsNullOrEmpty(dt2.Exception) ? Ok() : StatusCode(500);
return string.IsNullOrEmpty(dt2.Exception) ? await JSONAsync(new { ok = true }) : StatusCode(500);
}
case "rdoc":
@@ -98,7 +98,7 @@ public partial class IntranetController
});
}
default: return Ok();
default: return await JSONAsync(new { ok = true });
}
}
@@ -160,7 +160,7 @@ public partial class IntranetController
$"Die Mahn-PDF {frdic.nz("DocumentName", "").ne($"Zahlungserinnerung_{remId}.pdf")} konnte nicht erstellt werden.",
UserAccountID, remId);
}
return Ok();
return await JSONAsync(new { ok = true });
}
return await ReminderIssueResult("Die Mahnung konnte aufgrund eines Fehlers nicht erstellt werden.");
}
@@ -223,7 +223,7 @@ public partial class IntranetController
UserAccountID, remId);
}
}
return Ok();
return await JSONAsync(new { ok = true });
}
return await ReminderIssueResult("Die Mahnung konnte aufgrund eines Fehlers nicht versandt werden.");
}
@@ -92,13 +92,13 @@ public partial class IntranetController
_intranet.Intranet__SQLConnectionString,
StdParamlist(SQL_VarChar("@Id", Form("id"))),
Security: DbSec, options: SqlOpt(fn, id, code));
return Ok();
return await JSONAsync(new { ok = true });
case "sconf": return await HandleRequestSconf(fn, id, code);
case "idoc": return await HandleRequestIdoc(fn, id, code);
case "resend": return await HandleRequestResend(fn, id, code);
default: return Ok();
default: return await JSONAsync(new { ok = true });
}
}
@@ -165,7 +165,13 @@ public partial class IntranetController
private async Task<IActionResult> HandleRequestPget(string fn, string id, string code)
{
if (!HasForm("id") || !long.TryParse(Form("id"), out long tgtid)) return BadRequest400();
if (!HasForm("id") || !long.TryParse(Form("id"), out long tgtid))
{
_logger.LogWarning("HandleRequestPget: missing/invalid 'id' value='{Value}' user={User}", Form("id"), UserAccountID);
return BadRequest400();
}
_logger.LogDebug("HandleRequestPget tgtid={TgtId} user={User}", tgtid, UserAccountID);
var dt = await getSQLDatatable_async(
"SELECT * FROM [dbo].[fds__getRequestTreeIds](@srqid);",
_intranet.Intranet__SQLConnectionString,
@@ -181,15 +187,19 @@ public partial class IntranetController
if (iid > 0 && !ids.Contains(iid)) ids.Add(iid);
}
}
_logger.LogDebug("HandleRequestPget tgtid={TgtId} resolved {Count} related ids: {Ids}", tgtid, ids.Count, string.Join(",", ids));
var schemaDic = new Dictionary<string, fds.FdsMfrClient.DatabaseSchema>
{
[EntityHelper.EntityName(EntityTypes.ServiceRequest)] =
new fds.FdsMfrClient.DatabaseSchema(EntityTypes.ServiceRequest)
};
using var mfr = _mfrFactory.Create();
await mfr.Update__entitytable(EntityTypes.ServiceRequest,
bool ok = await mfr.Update__entitytable(EntityTypes.ServiceRequest,
fds.FdsMfr.UpdateNeed.Reset, ids.ToArray(), schemaDic: schemaDic);
return Ok();
_logger.LogInformation("HandleRequestPget MFR update complete tgtid={TgtId} ids={Count} success={Success} user={User}",
tgtid, ids.Count, ok, UserAccountID);
return await JSONAsync(new { ok });
}
private async Task<IActionResult> HandleRequestGet(string fn, string id, string code)
@@ -321,7 +331,7 @@ public partial class IntranetController
$"Die Rechnungs-PDF {frdic.nz("DocumentName").ne($"Rechnung_{invId}.pdf")} konnte nicht erstellt werden.",
UserAccountID, invId);
}
return Ok();
return await JSONAsync(new { ok = true });
}
return await InvoiceIssueResult("Die Rechnung konnte aufgrund eines Fehlers nicht erstellt werden.");
}
@@ -381,7 +391,7 @@ public partial class IntranetController
UserAccountID, invId);
}
}
return Ok();
return await JSONAsync(new { ok = true });
}
return await InvoiceIssueResult("Die Rechnung konnte aufgrund eines Fehlers nicht versandt werden.");
}
+11 -11
View File
@@ -144,7 +144,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
{
IActionResult? result = fn.ToLower() switch
{
"ping" => Ok(),
"ping" => await JSONAsync(new { ok = true }),
"wdg" => await _widgets.GetWidgetAsync(id, UserAccountID, DbSec, Request),
"todos" => new PhysicalFileResult(
Path.Combine(Directory.GetCurrentDirectory(), "Data", "ProjectToDos.html"),
@@ -168,7 +168,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
_logger.LogWarning("No handler matched fn={Fn}", fn);
else
_logger.LogDebug("Do completed fn={Fn}/{Id} result={ResultType}", fn, id, result.GetType().Name);
return result ?? Ok();
return result ?? await JSONAsync(new { ok = true });
}
catch (Exception ex)
{
@@ -255,7 +255,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
UserAccountID, HttpContext.Connection.RemoteIpAddress);
await HttpContext.SignOutAsync(Fuchs_intranet.AuthScheme);
_logger.LogDebug("Logout sign-out complete for user={User}", UserAccountID);
return Ok();
return await JSONAsync(new { ok = true });
}
// ── Password helpers ──────────────────────────────────────────────────────
@@ -285,7 +285,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
{
_logger.LogDebug("HandleSendPasswordCode: no SMS sent for email={Email} (user not found, name mismatch, no mobile, or localhost)", email);
}
return Ok(); // always OK to prevent enumeration
return await JSONAsync(new { ok = true }); // always OK to prevent enumeration
}
private async Task<IActionResult> HandleSendPassword(string fn, string id, string code)
@@ -323,7 +323,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
{
_logger.LogWarning("HandleSendPassword: TOTP verification failed for email={Email}", email);
}
return Ok();
return await JSONAsync(new { ok = true });
}
private async Task<IActionResult> HandleAccount(string fn, string id, string code)
@@ -345,7 +345,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
{
_logger.LogDebug("HandleAccount sms: no SMS sent for user={User} (no mobile or localhost)", UserAccountID);
}
return Ok();
return await JSONAsync(new { ok = true });
case "changepassword":
string? npw = Request.Form["npw"];
@@ -400,10 +400,10 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
},
Security: DbSec, options: SqlOpt(fn, id, code));
_logger.LogDebug("Password changed successfully for user={User}", UserAccountID);
return Ok();
return await JSONAsync(new { ok = true });
}
_logger.LogWarning("HandleAccount unknown action={Action} user={User}", id, UserAccountID);
return Ok();
return await JSONAsync(new { ok = true });
}
private async Task<IActionResult> HandleMfr(string fn, string id, string code)
@@ -429,7 +429,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
}
_logger.LogWarning("HandleMfr access denied for user={User} authorization={Auth}",
UserAccountID, UserIdent.Authorization);
return Ok();
return await JSONAsync(new { ok = true });
}
private async Task<IActionResult> HandleMfrUpdate(string fn, string id, string code)
@@ -444,7 +444,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
using var mfrSingle = _mfrFactory.Create();
await mfrSingle.Update__entitytable(et, fds.FdsMfr.UpdateNeed.Short);
_logger.LogDebug("MfrUpdate Short completed for entity={EntityType}", et);
return Ok();
return await JSONAsync(new { ok = true });
}
if (et != EntityTypes.none && !string.IsNullOrEmpty(Request.Form["need"]))
{
@@ -453,7 +453,7 @@ public partial class IntranetController : Microsoft.AspNetCore.Mvc.Controller
using var mfr = _mfrFactory.Create();
await mfr.Update__entitytable(et, updateNeed: need, debugDetails: false);
_logger.LogDebug("MfrUpdate completed for entity={EntityType} need={Need}", et, need);
return Ok();
return await JSONAsync(new { ok = true });
}
_logger.LogWarning("HandleMfrUpdate bad request: unknown type={Type} user={User}", typeParam, UserAccountID);
return BadRequest400();