submit proker tested, approve/decline revised, untested

This commit is contained in:
nugroho 2025-06-26 05:22:31 +07:00
parent 0bb5595122
commit 3f2db5deb0
2 changed files with 81 additions and 26 deletions

View File

@ -1,3 +1,4 @@
using System.Security.Cryptography.Pkcs;
using System.Text.Json; using System.Text.Json;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@ -350,7 +351,7 @@ public static partial class APIHandler
{ {
if (!await runner.RequestValidated(3) || !Auth.TryGetUser(runner, out SafeUser CurrUser)) return; if (!await runner.RequestValidated(3) || !Auth.TryGetUser(runner, out SafeUser CurrUser)) return;
List<ProkerJournal> Journals = []; List<ProkerJournal> Journals = [];
using SqlDataReader Prokers = await RunReaderAsync(CS, "SELECT * FROM [AllJournal] WHERE [ownerid] = @oi OR @oi IS NULL ORDER BY [ownerid] ASC, [kegiatan] ASC, [prokerid] ASC, [prokerjid] DESC", Query => using SqlDataReader Prokers = await RunReaderAsync(CS, "SELECT * FROM [AllJournal] WHERE [ownerid] = @oi OR @oi IS NULL ORDER BY [ownerid] ASC, [year] DESC, [kegiatan] ASC, [prokerid] ASC, [prokerjid] DESC", Query =>
{ {
Query.Parameters.AddWithValue("@oi", CurrUser.Level < 3 ? DBNull.Value : CurrUser.AgentID); Query.Parameters.AddWithValue("@oi", CurrUser.Level < 3 ? DBNull.Value : CurrUser.AgentID);
}, CTS.Token); }, CTS.Token);
@ -367,6 +368,7 @@ public static partial class APIHandler
(string)J["enttarget"], (string)J["enttarget"],
(string)J["indicators"], (string)J["indicators"],
(string)J["actions"], (string)J["actions"],
(string)J["prokerjid"],
(string)J["submitter"], (string)J["submitter"],
(string)J["notes"], (string)J["notes"],
(byte)J["status"], (byte)J["status"],
@ -482,29 +484,59 @@ public static partial class APIHandler
{ {
proker.Run(async runner => proker.Run(async runner =>
{ {
if (!await runner.RequestValidated(2, "POST", true) || !Auth.TryGetUser(runner, out SafeUser CurrUser) || if (!await runner.RequestValidated(2, "POST", true) || !Auth.TryGetUser(runner, out SafeUser CurrUser) ||
await runner.TryGetBodyJsonAsync(["agentid", "year", "newstatus", "notes"], CTS.Token) is not Dictionary<string, JsonElement> InElement) return; await runner.TryGetBodyJsonAsync(["agentid", "year", "newstatus", "notes"], CTS.Token) is not Dictionary<string, JsonElement> InElement) return;
if (CurrUser.Level != 2)
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "Only Level 2 Users may process Proker submission.");
return;
}
if ( if (
InElement["agentid"].GetString() is not string AgentID || AgentID.Equals(string.Empty) || InElement["agentid"].GetString() is not string AgentID || AgentID.Equals(string.Empty) ||
InElement["year"].GetInt16() is short Year && Year < 2020 || InElement["year"].GetInt16() is short Year && Year < 2020 ||
InElement["newstatus"].GetByte() is byte Status && Status != 1 && Status != 3 || InElement["newstatus"].GetByte() is byte Status && Status != 1 && Status != 3 ||
InElement["notes"].GetString() is not string Notes || Notes.Equals(string.Empty) InElement["notes"].GetString() is not string Notes || Notes.Equals(string.Empty)
) )
{ {
await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Required property is of invalid format."); await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Required property is of invalid format.");
return; return;
} }
await RunNonQueryAsync(CS, "INSERT INTO [proker_journal] SELECT @pjid, [prokerid], @agid, @st, @nots, null, @tstp FROM [LatestJournal] WHERE [ownerid] = @oi AND [year] = @yr AND [status] = 2 ORDER BY [kegiatan]", Query => await RunTransactionAsync(CS, async(Conn, Trans) =>
{ {
DateTime Now = DateTime.Now; List<string> PKIDList = [];
Query.Parameters.AddWithValue("@pjid", GenerateUuidV7(Now)); using (SqlCommand PKIDFetch = Conn.CreateCommand())
Query.Parameters.AddWithValue("@agid", CurrUser.AgentID); {
Query.Parameters.AddWithValue("@st", Status); PKIDFetch.Transaction = Trans;
Query.Parameters.AddWithValue("@nots", Notes); PKIDFetch.CommandText = "SELECT [prokerid] FROM [LatestJournal] WHERE [ownerid] = @oi AND [year] = @yr AND [status] = 2 ORDER BY [kegiatan]";
Query.Parameters.AddWithValue("@tstp", Now); PKIDFetch.Parameters.AddWithValue("@oi", AgentID);
Query.Parameters.AddWithValue("@oi", AgentID); PKIDFetch.Parameters.AddWithValue("@yr", Year);
Query.Parameters.AddWithValue("@yr", Year); PKIDList = await (await PKIDFetch.ExecuteReaderAsync(CTS.Token)).ToListAsync(PKID => (string)PKID["prokerid"], CTS.Token);
}
foreach (string PKID in PKIDList)
{
DateTime Now = DateTime.Now;
using SqlCommand PJUpdate = Conn.CreateCommand();
PJUpdate.Transaction = Trans;
PJUpdate.CommandText = "INSERT INTO [proker_journal] VALUES(@pjid, @pkid, @agid, @st, @nots, null, @tstp)";
PJUpdate.Parameters.AddWithValue("@pjid", GenerateUuidV7(Now));
PJUpdate.Parameters.AddWithValue("@pkid", PKID);
PJUpdate.Parameters.AddWithValue("@agid", CurrUser.AgentID);
PJUpdate.Parameters.AddWithValue("@st", Status);
PJUpdate.Parameters.AddWithValue("@nots", Notes);
PJUpdate.Parameters.AddWithValue("@tstp", Now);
}
}, CTS.Token); }, CTS.Token);
// await RunNonQueryAsync(CS, "INSERT INTO [proker_journal] SELECT @pjid, [prokerid], @agid, @st, @nots, null, @tstp FROM [LatestJournal] WHERE [ownerid] = @oi AND [year] = @yr AND [status] = 2 ORDER BY [kegiatan]", Query =>
// {
// DateTime Now = DateTime.Now;
// Query.Parameters.AddWithValue("@pjid", GenerateUuidV7(Now));
// Query.Parameters.AddWithValue("@agid", CurrUser.AgentID);
// Query.Parameters.AddWithValue("@st", Status);
// Query.Parameters.AddWithValue("@nots", Notes);
// Query.Parameters.AddWithValue("@tstp", Now);
// Query.Parameters.AddWithValue("@oi", AgentID);
// Query.Parameters.AddWithValue("@yr", Year);
// }, CTS.Token);
await runner.WriteJsonResponse(StatusCodes.Status202Accepted, "Proker submission processed."); await runner.WriteJsonResponse(StatusCodes.Status202Accepted, "Proker submission processed.");
}); });
}) })
@ -513,23 +545,46 @@ public static partial class APIHandler
proker.Run(async runner => proker.Run(async runner =>
{ {
if (!await runner.RequestValidated(3, "POST", true) || !Auth.TryGetUser(runner, out SafeUser CurrUser) || if (!await runner.RequestValidated(3, "POST", true) || !Auth.TryGetUser(runner, out SafeUser CurrUser) ||
await runner.TryGetBodyJsonAsync(["year"], CTS.Token) is not Dictionary<string, JsonElement> InElement) return; await runner.TryGetBodyJsonAsync(["agentid","year"], CTS.Token) is not Dictionary<string, JsonElement> InElement) return;
if (CurrUser.Level != 3)
{
await runner.WriteJsonResponse(StatusCodes.Status401Unauthorized, "Only Level 3 Users may submit their own Prokers.");
return;
}
if ( if (
InElement["agentid"].GetString() is not string AgentID || AgentID.Equals(string.Empty) ||
InElement["year"].GetInt16() is short Year && Year < 2020 InElement["year"].GetInt16() is short Year && Year < 2020
) )
{ {
await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Required property is of invalid format."); await runner.WriteJsonResponse(StatusCodes.Status400BadRequest, "Required property values is invalid or out of allowed range.");
return; return;
} }
await RunNonQueryAsync(CS, "INSERT INTO [proker_journal] SELECT @pjid, [prokerid], @oi, @st, @nots, null, @tstp FROM [LatestJournal] WHERE [ownerid] = @oi AND [year] = @yr AND [status] = 0 OR [status] = 1 ORDER BY [kegiatan]", Query => List<string> PKIDList = [];
await RunTransactionAsync(CS, async(Conn, Trans) =>
{ {
DateTime Now = DateTime.Now; using (SqlCommand PKIDFetch = Conn.CreateCommand())
Query.Parameters.AddWithValue("@pjid", GenerateUuidV7(Now)); {
Query.Parameters.AddWithValue("@tstp", Now); PKIDFetch.Transaction = Trans;
Query.Parameters.AddWithValue("@oi", CurrUser.AgentID); PKIDFetch.CommandText = "SELECT [prokerid] FROM [LatestJournal] WHERE [ownerid] = @oi AND [year] = @yr AND [status] = 0 OR [status] = 1 ORDER BY [kegiatan]";
Query.Parameters.AddWithValue("@yr", Year); PKIDFetch.Parameters.AddWithValue("@oi", AgentID);
PKIDFetch.Parameters.AddWithValue("@yr", Year);
using SqlDataReader PKRd = await PKIDFetch.ExecuteReaderAsync(CTS.Token);
PKIDList = await PKRd.ToListAsync(PKID => (string)PKID["prokerid"], CTS.Token);
}
foreach (string PKID in PKIDList)
{
DateTime Now = DateTime.Now;
using SqlCommand PJUpdate = Conn.CreateCommand();
PJUpdate.Transaction = Trans;
PJUpdate.CommandText = "INSERT INTO [proker_journal] VALUES(@pjid, @pkid, @oi, 2, 'Pengajuan Program Kerja', null, @tstp)";
PJUpdate.Parameters.AddWithValue("@pjid", GenerateUuidV7(Now));
PJUpdate.Parameters.AddWithValue("@pkid", PKID);
PJUpdate.Parameters.AddWithValue("@oi", AgentID);
PJUpdate.Parameters.AddWithValue("@tstp", Now);
_ = await PJUpdate.ExecuteNonQueryAsync(CTS.Token);
}
}, CTS.Token); }, CTS.Token);
await runner.WriteJsonResponse(StatusCodes.Status202Accepted, "Proker draft submitted."); await runner.WriteJsonResponse(StatusCodes.Status202Accepted, "Proker draft submitted.", PKIDList);
}); });
}) })
.Map("/pushproker", proker => .Map("/pushproker", proker =>

View File

@ -20,7 +20,7 @@ internal partial record Proker(string ProkerID, string AgentID, byte Kegiatan, s
byte StartMonth, short Year, byte TimeTarget, bool IsInMonth, string EntityTarget, string Indicators, string Actions); byte StartMonth, short Year, byte TimeTarget, bool IsInMonth, string EntityTarget, string Indicators, string Actions);
internal partial record ProkerJournal(string ProkerID, string OwnerID, byte Kegiatan, string Sasaran, byte? StartDay, internal partial record ProkerJournal(string ProkerID, string OwnerID, byte Kegiatan, string Sasaran, byte? StartDay,
byte StartMonth, short Year, byte TimeTarget, bool IsInMonth, string EntityTarget, string Indicators, string Actions, byte StartMonth, short Year, byte TimeTarget, bool IsInMonth, string EntityTarget, string Indicators, string Actions,
string SubmitterID, string Notes, byte Status, string? Document, DateTime TimeStamp); string JournalID, string SubmitterID, string Notes, byte Status, string? Document, DateTime TimeStamp);
internal partial record User(string Username, string AgentID, string Password, byte Level, bool Active); internal partial record User(string Username, string AgentID, string Password, byte Level, bool Active);
[JsonSerializable(typeof(Agent))] [JsonSerializable(typeof(Agent))]
[JsonSerializable(typeof(ApiResponse))] [JsonSerializable(typeof(ApiResponse))]