Compare commits
No commits in common. "c0c2c59ea318805e9021d8bb8ceb5b7f91f93cb1" and "8a39714a25c230d2a9d927b07dc4b9611b210246" have entirely different histories.
c0c2c59ea3
...
8a39714a25
@ -20,9 +20,5 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers
|
|||||||
return View();
|
return View();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IActionResult OtSTatus()
|
|
||||||
{
|
|
||||||
return View();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
|
|
||||||
namespace PSTW_CentralSystem.Areas.OTcalculate.Models
|
|
||||||
{
|
|
||||||
[Table("otstatus")]
|
|
||||||
public class OtStatusModel
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
public int StatusId { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public int UserId { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public int Month { get; set; }
|
|
||||||
|
|
||||||
[Required]
|
|
||||||
public int Year { get; set; }
|
|
||||||
|
|
||||||
public DateTime SubmitDate { get; set; }
|
|
||||||
|
|
||||||
public string HodStatus { get; set; } = "Pending";
|
|
||||||
|
|
||||||
// JSON array of ApprovalUpdateLog
|
|
||||||
public string? HodUpdate { get; set; }
|
|
||||||
|
|
||||||
public string HrStatus { get; set; } = "Pending";
|
|
||||||
|
|
||||||
// JSON array of ApprovalUpdateLog
|
|
||||||
public string? HrUpdate { get; set; }
|
|
||||||
|
|
||||||
public string? FilePath { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -78,35 +78,30 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Services
|
|||||||
columns.RelativeColumn(2.7f); // Description
|
columns.RelativeColumn(2.7f); // Description
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Header Row
|
||||||
table.Header(header =>
|
table.Header(header =>
|
||||||
{
|
{
|
||||||
// Row 1 — grouped headers
|
void AddHeaderCell(string text, string bgColor)
|
||||||
header.Cell().RowSpan(2).Background("#d0ead2").Border(0.25f).Padding(5).Text("Date").FontSize(9).Bold().AlignCenter();
|
{
|
||||||
|
header.Cell().Background(bgColor).Border(0.25f).Padding(5).Text(text).FontSize(9).Bold().AlignCenter();
|
||||||
header.Cell().ColumnSpan(3).Background("#dceefb").Border(0.25f).Padding(5).Text("Office Hours\n(8:30 - 17:30)").FontSize(9).Bold().AlignCenter();
|
}
|
||||||
header.Cell().ColumnSpan(3).Background("#edf2f7").Border(0.25f).Padding(5).Text("After Office Hours\n(17:30 - 8:30)").FontSize(9).Bold().AlignCenter();
|
|
||||||
|
|
||||||
header.Cell().RowSpan(2).Background("#fdebd0").Border(0.25f).Padding(5).Text("Total OT\nHours").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().RowSpan(2).Background("#fdebd0").Border(0.25f).Padding(5).Text("Break Hours\n(min)").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().RowSpan(2).Background("#fdebd0").Border(0.25f).Padding(5).Text("Net OT Hours").FontSize(9).Bold().AlignCenter();
|
|
||||||
|
|
||||||
|
AddHeaderCell("Date", "#d0ead2");
|
||||||
|
AddHeaderCell("From\n(Office)", "#dceefb");
|
||||||
|
AddHeaderCell("To\n(Office)", "#dceefb");
|
||||||
|
AddHeaderCell("Break\n(Office)", "#dceefb");
|
||||||
|
AddHeaderCell("From\n(After)", "#edf2f7");
|
||||||
|
AddHeaderCell("To\n(After)", "#edf2f7");
|
||||||
|
AddHeaderCell("Break\n(After)", "#edf2f7");
|
||||||
|
AddHeaderCell("Total OT\nHours", "#fdebd0");
|
||||||
|
AddHeaderCell("Break Hours\n(min)", "#fdebd0");
|
||||||
|
AddHeaderCell("Net OT Hours", "#fdebd0");
|
||||||
if (departmentId == 2)
|
if (departmentId == 2)
|
||||||
header.Cell().RowSpan(2).Background("#d0f0ef").Border(0.25f).Padding(5).Text("Station").FontSize(9).Bold().AlignCenter();
|
AddHeaderCell("Station", "#d0f0ef");
|
||||||
|
AddHeaderCell("Days", "#e0f7da");
|
||||||
header.Cell().RowSpan(2).Background("#e0f7da").Border(0.25f).Padding(5).Text("Days").FontSize(9).Bold().AlignCenter();
|
AddHeaderCell("Description", "#e3f2fd");
|
||||||
header.Cell().RowSpan(2).Background("#e3f2fd").Border(0.25f).Padding(5).Text("Description").FontSize(9).Bold().AlignCenter();
|
|
||||||
|
|
||||||
// Row 2 — subheaders only for grouped columns
|
|
||||||
header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("From").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("To").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().Background("#dceefb").Border(0.25f).Padding(5).Text("Break").FontSize(9).Bold().AlignCenter();
|
|
||||||
|
|
||||||
header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("From").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("To").FontSize(9).Bold().AlignCenter();
|
|
||||||
header.Cell().Background("#edf2f7").Border(0.25f).Padding(5).Text("Break").FontSize(9).Bold().AlignCenter();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Data Rows
|
// Data Rows
|
||||||
double totalOTSum = 0;
|
double totalOTSum = 0;
|
||||||
int totalBreakSum = 0;
|
int totalBreakSum = 0;
|
||||||
|
|||||||
@ -1,4 +1,6 @@
|
|||||||
@{
|
|
||||||
|
|
||||||
|
@{
|
||||||
ViewData["Title"] = "Rate Update";
|
ViewData["Title"] = "Rate Update";
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
Layout = "~/Views/Shared/_Layout.cshtml";
|
||||||
}
|
}
|
||||||
|
|||||||
@ -104,7 +104,7 @@
|
|||||||
<th class="header-orange" rowspan="2" v-if="isPSTWAIR">Station</th>
|
<th class="header-orange" rowspan="2" v-if="isPSTWAIR">Station</th>
|
||||||
<th class="header-green" rowspan="2">Days</th>
|
<th class="header-green" rowspan="2">Days</th>
|
||||||
<th class="header-blue" rowspan="2">Description</th>
|
<th class="header-blue" rowspan="2">Description</th>
|
||||||
<th class="header-green" rowspan="2" v-if="!isAlreadySubmitted">Action</th>
|
<th class="header-green" rowspan="2">Action</th>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="header-blue">From</th>
|
<th class="header-blue">From</th>
|
||||||
@ -134,7 +134,7 @@
|
|||||||
{{ record.otDescription }}
|
{{ record.otDescription }}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td v-if="!isAlreadySubmitted">
|
<td>
|
||||||
<button class="btn btn-light border rounded-circle me-1" title="Edit Record" v-on:click="editRecord(index)">
|
<button class="btn btn-light border rounded-circle me-1" title="Edit Record" v-on:click="editRecord(index)">
|
||||||
<i class="bi bi-pencil-fill text-warning fs-5"></i>
|
<i class="bi bi-pencil-fill text-warning fs-5"></i>
|
||||||
</button>
|
</button>
|
||||||
@ -167,33 +167,10 @@
|
|||||||
<button class="btn btn-dark btn-sm" v-on:click="downloadPdf">
|
<button class="btn btn-dark btn-sm" v-on:click="downloadPdf">
|
||||||
<i class="bi bi-download"></i> Save
|
<i class="bi bi-download"></i> Save
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-success btn-sm"
|
<button class="btn btn-success btn-sm" v-on:click="submitRecords">
|
||||||
v-on:click="openSubmitModal"
|
<i class="bi bi-send"></i> Submit
|
||||||
:disabled="isSubmitting || isAlreadySubmitted">
|
|
||||||
<i class="bi bi-send"></i> {{ isAlreadySubmitted ? 'Submitted' : 'Submit' }}
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Submit Modal -->
|
|
||||||
<div v-if="showSubmitModal" class="modal show d-block" tabindex="-1">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content p-3">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Submit OT Records</h5>
|
|
||||||
<button type="button" class="btn-close" v-on:click="showSubmitModal = false"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
<input type="file" class="form-control" v-on:change="handleFileChange" accept=".pdf" />
|
|
||||||
</div>
|
|
||||||
<div class="modal-footer">
|
|
||||||
<button class="btn btn-success" v-on:click="submitToHod">Submit</button>
|
|
||||||
<button class="btn btn-secondary" v-on:click="showSubmitModal = false">Cancel</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@ -212,10 +189,7 @@
|
|||||||
selectedYear: currentYear,
|
selectedYear: currentYear,
|
||||||
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||||
years: Array.from({ length: 10 }, (_, i) => currentYear - 5 + i),
|
years: Array.from({ length: 10 }, (_, i) => currentYear - 5 + i),
|
||||||
expandedDescriptions: {},
|
expandedDescriptions: {}
|
||||||
showSubmitModal: false,
|
|
||||||
submitFile: null,
|
|
||||||
submittedStatus: {},
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -243,10 +217,6 @@
|
|||||||
hours: Math.floor(totalMinutes / 60),
|
hours: Math.floor(totalMinutes / 60),
|
||||||
minutes: Math.round(totalMinutes % 60)
|
minutes: Math.round(totalMinutes % 60)
|
||||||
};
|
};
|
||||||
},
|
|
||||||
isAlreadySubmitted() {
|
|
||||||
const key = `${this.selectedYear}-${String(this.selectedMonth).padStart(2, '0')}`;
|
|
||||||
return !!this.submittedStatus[key];
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async mounted() {
|
async mounted() {
|
||||||
@ -255,21 +225,8 @@
|
|||||||
methods: {
|
methods: {
|
||||||
async initUserAndRecords() {
|
async initUserAndRecords() {
|
||||||
await this.fetchUser();
|
await this.fetchUser();
|
||||||
if (this.userId) {
|
if (this.userId) await this.fetchOtRecords();
|
||||||
await this.fetchOtRecords();
|
|
||||||
await this.fetchSubmissionStatus();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
async fetchSubmissionStatus() {
|
|
||||||
try {
|
|
||||||
const res = await fetch(`/OvertimeAPI/GetSubmissionStatus/${this.userId}`);
|
|
||||||
const data = await res.json();
|
|
||||||
this.submittedStatus = data; // expect format like { '2025-04': true }
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Submission status fetch error:", err);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
async fetchUser() {
|
async fetchUser() {
|
||||||
try {
|
try {
|
||||||
const res = await fetch('/IdentityAPI/GetUserInformation', { method: 'POST' });
|
const res = await fetch('/IdentityAPI/GetUserInformation', { method: 'POST' });
|
||||||
@ -385,57 +342,43 @@
|
|||||||
alert("An error occurred while generating the PDF.");
|
alert("An error occurred while generating the PDF.");
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
openSubmitModal() {
|
async submitRecords() {
|
||||||
this.showSubmitModal = true;
|
try {
|
||||||
},
|
const recordsToSubmit = this.filteredRecords.map(record => ({
|
||||||
handleFileChange(event) {
|
overtimeId: record.overtimeId, // Make sure to include the ID for updates
|
||||||
const file = event.target.files[0];
|
otDate: record.otDate,
|
||||||
if (file && file.type !== 'application/pdf') {
|
officeFrom: record.officeFrom,
|
||||||
alert("Only PDF files are allowed.");
|
officeTo: record.officeTo,
|
||||||
return;
|
officeBreak: record.officeBreak,
|
||||||
}
|
afterFrom: record.afterFrom,
|
||||||
this.submitFile = file;
|
afterTo: record.afterTo,
|
||||||
},
|
afterBreak: record.afterBreak,
|
||||||
|
stationId: record.stationId,
|
||||||
|
otDescription: record.otDescription,
|
||||||
|
otDays: record.otDays,
|
||||||
|
filePath: record.filePath, // Include existing file path
|
||||||
|
userId: this.userId
|
||||||
|
// Add other relevant fields if necessary
|
||||||
|
}));
|
||||||
|
|
||||||
async submitToHod() {
|
const res = await fetch('/OvertimeAPI/SubmitOvertimeRecords', {
|
||||||
this.isSubmitting = true;
|
method: 'POST',
|
||||||
try {
|
headers: { 'Content-Type': 'application/json' },
|
||||||
if (!this.submitFile) {
|
body: JSON.stringify(recordsToSubmit)
|
||||||
alert("Please upload a PDF file.");
|
});
|
||||||
return;
|
if (res.ok) {
|
||||||
}
|
alert("Overtime records submitted for review.");
|
||||||
|
} else {
|
||||||
const formData = new FormData();
|
alert("Submission failed: " + await res.text());
|
||||||
formData.append("file", this.submitFile);
|
|
||||||
|
|
||||||
// Add month & year selection logic if needed
|
|
||||||
formData.append("month", new Date().getMonth() + 1);
|
|
||||||
formData.append("year", new Date().getFullYear());
|
|
||||||
|
|
||||||
try {
|
|
||||||
const response = await fetch("/OvertimeAPI/SubmitOvertimeRecords", {
|
|
||||||
method: "POST",
|
|
||||||
body: formData
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!response.ok) throw new Error("Submission failed");
|
|
||||||
alert("Submission successful!");
|
|
||||||
this.showSubmitModal = false;
|
|
||||||
|
|
||||||
const key = `${this.selectedYear}-${String(this.selectedMonth).padStart(2, '0')}`;
|
|
||||||
this.submittedStatus[key] = true;
|
|
||||||
this.showSubmitModal = false;
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
alert("Error: " + err.message);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.isSubmitting = false;
|
|
||||||
}
|
}
|
||||||
}
|
} catch (err) {
|
||||||
|
console.error("Submission error:", err);
|
||||||
|
alert("An error occurred during submission.");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
app.mount("#app");
|
app.mount("#app");
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
@ -1,123 +0,0 @@
|
|||||||
@{
|
|
||||||
ViewData["Title"] = "Overtime Status";
|
|
||||||
Layout = "~/Views/Shared/_Layout.cshtml";
|
|
||||||
}
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.hodstatus, .hrstatus {
|
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-mask {
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
background-color: rgba(0,0,0,0.6);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-container {
|
|
||||||
background: white;
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 8px;
|
|
||||||
width: 500px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="otStatusApp" class="container mt-4">
|
|
||||||
|
|
||||||
<table class="table table-bordered">
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Month</th>
|
|
||||||
<th>Year</th>
|
|
||||||
<th>Submitted On</th>
|
|
||||||
<th>HOD Status</th>
|
|
||||||
<th>HR Status</th>
|
|
||||||
<th>Details</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr v-for="status in statusList" :key="status.statusId">
|
|
||||||
<td>{{ getMonthName(status.month) }}</td>
|
|
||||||
<td>{{ status.year }}</td>
|
|
||||||
<td>{{ formatDate(status.submitDate) }}</td>
|
|
||||||
<td :class="status.hodStatus.toLowerCase()">{{ status.hodStatus }}</td>
|
|
||||||
<td :class="status.hrStatus.toLowerCase()">{{ status.hrStatus }}</td>
|
|
||||||
<td>
|
|
||||||
<button class="btn btn-sm btn-primary" v-on:click ="viewUpdates(status)">View Updates</button>
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
<!-- Modal -->
|
|
||||||
<div v-if="selectedStatus" class="modal-mask">
|
|
||||||
<div class="modal-container">
|
|
||||||
<h5>Status History</h5>
|
|
||||||
<p><strong>HOD Updates:</strong></p>
|
|
||||||
<ul>
|
|
||||||
<li v-for="update in parseJson(selectedStatus.hodUpdate)">
|
|
||||||
{{ formatUpdate(update) }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<p><strong>HR Updates:</strong></p>
|
|
||||||
<ul>
|
|
||||||
<li v-for="update in parseJson(selectedStatus.hrUpdate)">
|
|
||||||
{{ formatUpdate(update) }}
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
<button class="btn btn-secondary" v-on:click ="selectedStatus = null">Close</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
@section Scripts {
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.prod.js"></script>
|
|
||||||
<script>
|
|
||||||
const { createApp } = Vue;
|
|
||||||
|
|
||||||
createApp({
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
statusList: [],
|
|
||||||
selectedStatus: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
fetch('/OvertimeAPI/GetUserOtStatus')
|
|
||||||
.then(res => {
|
|
||||||
if (!res.ok) throw new Error(`HTTP error ${res.status}`);
|
|
||||||
return res.json();
|
|
||||||
})
|
|
||||||
.then(data => this.statusList = data)
|
|
||||||
.catch(err => console.error("Fetch error:", err));
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formatDate(dateStr) {
|
|
||||||
return new Date(dateStr).toLocaleDateString();
|
|
||||||
},
|
|
||||||
getMonthName(month) {
|
|
||||||
return new Date(2000, month - 1, 1).toLocaleString('default', { month: 'long' });
|
|
||||||
},
|
|
||||||
parseJson(jsonStr) {
|
|
||||||
try {
|
|
||||||
return jsonStr ? JSON.parse(jsonStr) : [];
|
|
||||||
} catch (e) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
},
|
|
||||||
formatUpdate(update) {
|
|
||||||
return `${update.timestamp} - ${update.updatedBy} changed ${update.field} from '${update.oldValue}' to '${update.newValue}'`;
|
|
||||||
},
|
|
||||||
viewUpdates(status) {
|
|
||||||
this.selectedStatus = status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).mount('#otStatusApp');
|
|
||||||
</script>
|
|
||||||
}
|
|
||||||
@ -554,87 +554,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
return File(stream, "application/pdf", $"OvertimeRecords_{year}_{month}.pdf");
|
return File(stream, "application/pdf", $"OvertimeRecords_{year}_{month}.pdf");
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("SubmitOvertimeRecords")]
|
|
||||||
public async Task<IActionResult> SubmitOvertimeRecords([FromForm] IFormFile file, [FromForm] int month, [FromForm] int year)
|
|
||||||
{
|
|
||||||
var userIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
if (string.IsNullOrEmpty(userIdStr) || !int.TryParse(userIdStr, out int userId))
|
|
||||||
return Unauthorized();
|
|
||||||
|
|
||||||
if (file == null || file.Length == 0)
|
|
||||||
return BadRequest("No file uploaded.");
|
|
||||||
|
|
||||||
var uploadsFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "Media", "Overtime");
|
|
||||||
|
|
||||||
if (!Directory.Exists(uploadsFolder))
|
|
||||||
Directory.CreateDirectory(uploadsFolder);
|
|
||||||
|
|
||||||
var fileName = $"OT_{userId}_{year}_{month}_{DateTime.Now.Ticks}.pdf";
|
|
||||||
var filePath = Path.Combine(uploadsFolder, fileName);
|
|
||||||
|
|
||||||
using (var stream = new FileStream(filePath, FileMode.Create))
|
|
||||||
{
|
|
||||||
await file.CopyToAsync(stream);
|
|
||||||
}
|
|
||||||
|
|
||||||
var statusRecord = new OtStatusModel
|
|
||||||
{
|
|
||||||
UserId = userId,
|
|
||||||
Month = month,
|
|
||||||
Year = year,
|
|
||||||
SubmitDate = DateTime.Now,
|
|
||||||
HodStatus = "Pending",
|
|
||||||
HrStatus = "Pending",
|
|
||||||
FilePath = $"/Media/Overtime/{fileName}"
|
|
||||||
};
|
|
||||||
|
|
||||||
_centralDbContext.OtStatus.Add(statusRecord);
|
|
||||||
await _centralDbContext.SaveChangesAsync();
|
|
||||||
|
|
||||||
return Ok(new { message = "Overtime records submitted successfully." });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("CheckSubmissionStatus")]
|
|
||||||
public IActionResult CheckSubmissionStatus(int month, int year)
|
|
||||||
{
|
|
||||||
var userIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
if (string.IsNullOrEmpty(userIdStr) || !int.TryParse(userIdStr, out int userId))
|
|
||||||
return Unauthorized();
|
|
||||||
|
|
||||||
var isSubmitted = _centralDbContext.OtStatus
|
|
||||||
.Any(s => s.UserId == userId && s.Month == month && s.Year == year);
|
|
||||||
|
|
||||||
return Ok(new { isSubmitted });
|
|
||||||
}
|
|
||||||
|
|
||||||
[HttpGet("GetSubmissionStatus/{userId}")]
|
|
||||||
public IActionResult GetSubmissionStatus(int userId)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var statuses = _centralDbContext.OtStatus
|
|
||||||
.Where(s => s.UserId == userId)
|
|
||||||
.OrderByDescending(s => s.SubmitDate)
|
|
||||||
.Select(s => new
|
|
||||||
{
|
|
||||||
s.UserId,
|
|
||||||
s.Month,
|
|
||||||
s.Year,
|
|
||||||
s.HodStatus,
|
|
||||||
s.HrStatus,
|
|
||||||
s.SubmitDate
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return Ok(statuses);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_logger.LogError(ex, "Failed to fetch submission statuses.");
|
|
||||||
return StatusCode(500, "Error retrieving submission statuses.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Ot Edit
|
#region Ot Edit
|
||||||
@ -696,23 +615,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region OtStatus
|
|
||||||
[HttpGet("GetUserOtStatus")]
|
|
||||||
public IActionResult GetUserOtStatus()
|
|
||||||
{
|
|
||||||
var userIdStr = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
|
|
||||||
if (string.IsNullOrEmpty(userIdStr) || !int.TryParse(userIdStr, out int userId))
|
|
||||||
return Unauthorized();
|
|
||||||
|
|
||||||
var records = _centralDbContext.OtStatus
|
|
||||||
.Where(s => s.UserId == userId)
|
|
||||||
.OrderByDescending(s => s.Year).ThenByDescending(s => s.Month)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
return Ok(records);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -104,7 +104,5 @@ namespace PSTW_CentralSystem.DBContext
|
|||||||
public DbSet<StateModel> States { get; set; }
|
public DbSet<StateModel> States { get; set; }
|
||||||
public DbSet<WeekendModel> Weekends { get; set; }
|
public DbSet<WeekendModel> Weekends { get; set; }
|
||||||
public DbSet<OtRegisterModel> Otregisters { get; set; }
|
public DbSet<OtRegisterModel> Otregisters { get; set; }
|
||||||
public DbSet<OtStatusModel> OtStatus { get; set; }
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -539,11 +539,6 @@
|
|||||||
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu">OT Records</span>
|
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu">OT Records</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="sidebar-item">
|
|
||||||
<a class="sidebar-link waves-effect waves-dark sidebar-link" asp-area="OTcalculate" asp-controller="Overtime" asp-action="OtStatus" aria-expanded="false">
|
|
||||||
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu">OT Status</span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user