Project code maintenance and pr item attachment

This commit is contained in:
rowell_m_soriano 2026-02-12 10:41:44 +08:00
parent 33b839741f
commit 0612679648
69 changed files with 8366 additions and 680 deletions

View File

@ -2,6 +2,7 @@
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Models.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -21,11 +22,12 @@ namespace CPRNIMS.Domain.Contracts.Items
Task<List<ItemColor>> GetItemColor(ItemDto itemDto); Task<List<ItemColor>> GetItemColor(ItemDto itemDto);
Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto); Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto);
Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto); Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto);
Task<long> GetPRNo(); Task<(long, long)> GetPRNo();
Task<ItemCart> PostPurchRequest(ItemDto itemDto); Task<ResponseObject> PostPurchRequest(ItemDto itemDto);
Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto); Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto);
Task<Item> PutItemDetail(ItemDto itemDto); Task<Item> PutItemDetail(ItemDto itemDto);
Task<ItemCart> PostPutItemCart(ItemDto itemDto); Task<ItemCart> PostPutItemCart(ItemDto itemDto);
Task<ItemCart> PostPutItemPath(ItemDto itemDto); Task<ItemCart> PostPutItemPath(ItemDto itemDto);
Task PostPutAttachment(AttachmentRequest attach);
} }
} }

View File

@ -2,6 +2,7 @@
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.SMTP; using CPRNIMS.Infrastructure.Entities.SMTP;
using CPRNIMS.Infrastructure.Models.Common;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -28,6 +29,7 @@ namespace CPRNIMS.Domain.Contracts.PR
Task<List<AlternativeOfferDetails>> GetSupplierAlterOfferDetails(PRDto PRDto); Task<List<AlternativeOfferDetails>> GetSupplierAlterOfferDetails(PRDto PRDto);
Task<List<NotificationById>> GetNotificationById(PRDto PRDto); Task<List<NotificationById>> GetNotificationById(PRDto PRDto);
Task<List<PRDto>> GetApproverName(PRDto PRDto); Task<List<PRDto>> GetApproverName(PRDto PRDto);
Task<List<ProjectCodes>> GetProjectCodes(PRDto pRDto);
Task<MessageResponse> PRItemRemoval(PRDto pRDto); Task<MessageResponse> PRItemRemoval(PRDto pRDto);
Task<PRDetails> PostPRApproveReject(PRDto PRDto); Task<PRDetails> PostPRApproveReject(PRDto PRDto);
Task<PRDetails> PostPutReceiving(PRDto PRDto); Task<PRDetails> PostPutReceiving(PRDto PRDto);
@ -35,5 +37,6 @@ namespace CPRNIMS.Domain.Contracts.PR
Task<PRDetails> PutItemDetail(PRDto PRDto); Task<PRDetails> PutItemDetail(PRDto PRDto);
Task<PRDetails> PostPutDeniedItem(PRDto PRDto); Task<PRDetails> PostPutDeniedItem(PRDto PRDto);
Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto); Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto);
Task<ResponseObject> PostPutProjectCode(PRDto prDto);
} }
} }

View File

@ -0,0 +1,47 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.Services
{
public static class ContentTypeHelper
{
public static string GetContentType(string fileName)
{
var extension = Path.GetExtension(fileName).ToLowerInvariant();
return extension switch
{
".pdf" => "application/pdf",
".doc" => "application/msword",
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
".pptx" => "application/vnd.openxmlformats-officedocument.presentationml.presentation",
".xls" => "application/vnd.ms-excel",
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
".png" => "image/png",
".jpg" or ".jpeg" => "image/jpeg",
".gif" => "image/gif",
".txt" => "text/plain",
_ => "application/octet-stream"
};
}
public static string ValidateFile(string filePath, string uploadsPath)
{
var message = "";
// Security: Prevent directory traversal attacks
var fullPath = Path.GetFullPath(filePath);
if (!fullPath.StartsWith(Path.GetFullPath(uploadsPath)))
{
message = "Invalid file path";
}
if (!System.IO.File.Exists(filePath))
{
message = "File not found";
}
return message;
}
}
}

View File

@ -1,16 +1,13 @@
using CPRNIMS.Domain.Contracts.Account; using CPRNIMS.Domain.Contracts.Items;
using CPRNIMS.Domain.Contracts.Items;
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Canvass; using CPRNIMS.Infrastructure.Dto.Canvass;
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Entities.Account; using CPRNIMS.Infrastructure.Entities.Account;
using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Models.Common;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data; using System.Data;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
@ -25,8 +22,6 @@ namespace CPRNIMS.Domain.Services.Items
_dbContext = dbContext; _dbContext = dbContext;
} }
public async Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto) public async Task<ItemCodeDto> PostPutItem(ItemCodeDto itemDto)
{
try
{ {
var messCodeParam = new SqlParameter("@MessCode", SqlDbType.TinyInt) var messCodeParam = new SqlParameter("@MessCode", SqlDbType.TinyInt)
{ {
@ -69,16 +64,8 @@ namespace CPRNIMS.Domain.Services.Items
UserId = itemDto.UserId UserId = itemDto.UserId
}; };
} }
catch (Exception ex)
{
// You could log ex.Message or rethrow with a custom message
throw new Exception("An error occurred while executing PostPutItem.", ex);
}
}
public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto) public async Task<Infrastructure.Entities.Items.Item> PutItemDetail(ItemDto itemDto)
{
try
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutItemDetail @ItemCodeId,@ItemLocalId,@ItemTypeId,@UOMId,@ItemColorId,@IsActive," + .ExecuteSqlRawAsync($"EXEC PutItemDetail @ItemCodeId,@ItemLocalId,@ItemTypeId,@UOMId,@ItemColorId,@IsActive," +
@ -106,15 +93,7 @@ namespace CPRNIMS.Domain.Services.Items
return new Infrastructure.Entities.Items.Item(); return new Infrastructure.Entities.Items.Item();
} }
catch (Exception ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto) public async Task<List<ItemLocalization>> GetItemLocalization(ItemDto itemDto)
{
try
{ {
var localizations = await _dbContext.ItemLocalizations var localizations = await _dbContext.ItemLocalizations
.Where(ic => ic.IsActive == true && .Where(ic => ic.IsActive == true &&
@ -124,17 +103,9 @@ namespace CPRNIMS.Domain.Services.Items
return localizations ?? new List<ItemLocalization>(); return localizations ?? new List<ItemLocalization>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto) public async Task<List<ItemCategory>> GetItemCateg(ItemDto itemDto)
{ {
try if (itemDto.ItemCategoryId == 0 || itemDto.ItemCategoryId == null)
{
if(itemDto.ItemCategoryId ==0 || itemDto.ItemCategoryId == null)
{ {
var categories = await _dbContext.ItemCategories var categories = await _dbContext.ItemCategories
.Where(ic => ic.IsActive == true) .Where(ic => ic.IsActive == true)
@ -148,18 +119,9 @@ namespace CPRNIMS.Domain.Services.Items
.ToListAsync(); .ToListAsync();
return categories ?? new List<ItemCategory>(); return categories ?? new List<ItemCategory>();
} }
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
} }
public async Task<List<Infrastructure.Entities.Items.Item>> GetItemDetail(ItemDto itemDto) public async Task<List<Infrastructure.Entities.Items.Item>> GetItemDetail(ItemDto itemDto)
{
try
{ {
var allItems = await _dbContext.Items var allItems = await _dbContext.Items
.FromSqlRaw($"EXEC GetItemDetail @ItemCodeId,@UserId", .FromSqlRaw($"EXEC GetItemDetail @ItemCodeId,@UserId",
@ -169,16 +131,8 @@ namespace CPRNIMS.Domain.Services.Items
return allItems ?? new List<Infrastructure.Entities.Items.Item>(); return allItems ?? new List<Infrastructure.Entities.Items.Item>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemList>> GetItemList(ItemCodeDto itemCode) public async Task<List<ItemList>> GetItemList(ItemCodeDto itemCode)
{
try
{ {
var allItems = await _dbContext.ItemList var allItems = await _dbContext.ItemList
.FromSqlRaw($"EXEC GetItemList @UserId = '{itemCode.UserId}'") .FromSqlRaw($"EXEC GetItemList @UserId = '{itemCode.UserId}'")
@ -186,16 +140,8 @@ namespace CPRNIMS.Domain.Services.Items
return allItems ?? new List<ItemList>(); return allItems ?? new List<ItemList>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemColor>> GetItemColor(ItemDto itemDto) public async Task<List<ItemColor>> GetItemColor(ItemDto itemDto)
{
try
{ {
var colors = await _dbContext.ItemColors var colors = await _dbContext.ItemColors
.Where(ic => EF.Functions.Like(ic.ItemColorName, $"%{itemDto.ItemColorName}%")) .Where(ic => EF.Functions.Like(ic.ItemColorName, $"%{itemDto.ItemColorName}%"))
@ -204,16 +150,8 @@ namespace CPRNIMS.Domain.Services.Items
return colors ?? new List<ItemColor>(); return colors ?? new List<ItemColor>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto) public async Task<List<UnitOfMessure>> GetItemUOM(ItemDto itemDto)
{
try
{ {
var uoms = await _dbContext.UnitOfMessures var uoms = await _dbContext.UnitOfMessures
.Where(ic => ic.IsActive == true && .Where(ic => ic.IsActive == true &&
@ -223,21 +161,13 @@ namespace CPRNIMS.Domain.Services.Items
return uoms ?? new List<UnitOfMessure>(); return uoms ?? new List<UnitOfMessure>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto) public async Task<ItemAttachement> PostPutItemPath(ItemDto itemDto)
{
try
{ {
var isExist = await _dbContext.ItemAttachements var isExist = await _dbContext.ItemAttachements
.FirstOrDefaultAsync(ia => ia.IsActive == true .FirstOrDefaultAsync(ia => ia.IsActive == true
&& ia.ItemNo == itemDto.ItemNo); && ia.ItemNo == itemDto.ItemNo);
if(isExist != null) if (isExist != null)
{ {
isExist.ItemAttachPath = itemDto.ItemAttachPath; isExist.ItemAttachPath = itemDto.ItemAttachPath;
await _dbContext.SaveChangesAsync(); await _dbContext.SaveChangesAsync();
@ -248,15 +178,7 @@ namespace CPRNIMS.Domain.Services.Items
return new ItemAttachement(); return new ItemAttachement();
} }
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<ItemCart> PostPutItemCart(ItemDto itemDto) public async Task<ItemCart> PostPutItemCart(ItemDto itemDto)
{
try
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutItemCart @ItemCartId,@ItemNo,@UserId,@UOMId,@ItemColorId,@ItemCategoryId,@PackagingTypeId,@ItemAttachId,@ItemLocalId", .ExecuteSqlRawAsync("EXEC PostPutItemCart @ItemCartId,@ItemNo,@UserId,@UOMId,@ItemColorId,@ItemCategoryId,@PackagingTypeId,@ItemAttachId,@ItemLocalId",
@ -271,16 +193,8 @@ namespace CPRNIMS.Domain.Services.Items
new SqlParameter("@ItemLocalId", itemDto.ItemLocalId)); new SqlParameter("@ItemLocalId", itemDto.ItemLocalId));
return new ItemCart(); return new ItemCart();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<List<ItemCart>> GetItemCart(ItemDto itemDto) public async Task<List<ItemCart>> GetItemCart(ItemDto itemDto)
{
try
{ {
var allItems = await _dbContext.ItemCarts var allItems = await _dbContext.ItemCarts
.FromSqlRaw($"EXEC GetItemCart @UserId,@RequestTypeId,@IsCount", .FromSqlRaw($"EXEC GetItemCart @UserId,@RequestTypeId,@IsCount",
@ -291,24 +205,19 @@ namespace CPRNIMS.Domain.Services.Items
return allItems ?? new List<ItemCart>(); return allItems ?? new List<ItemCart>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<ItemCart> PostPurchRequest(ItemDto itemDto) public async Task<ResponseObject> PostPurchRequest(ItemDto itemDto)
{ {
try var (messCode, message) = OutputParamMessage.CreateOutputParams();
{
if(itemDto.RequestTypeId == 1)//Internal if (itemDto.RequestTypeId == 1)//Internal
{ {
itemDto.Status = 2; itemDto.Status = 2;
itemDto.IsApproved = 2; itemDto.IsApproved = 2;
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId", .ExecuteSqlRawAsync("EXEC PostPutReqItems @UserId, @RequestItemId, @ItemNo, @QtyRequest,@Status,@IsApproved,@QtyReceived,@LotId," +
"@MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@ItemNo", itemDto.ItemNo), new SqlParameter("@ItemNo", itemDto.ItemNo),
new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L), new SqlParameter("@RequestItemId", itemDto.RequestItemId != null ? itemDto.RequestItemId : 0L),
@ -316,12 +225,14 @@ namespace CPRNIMS.Domain.Services.Items
new SqlParameter("@Status", itemDto.Status), new SqlParameter("@Status", itemDto.Status),
new SqlParameter("@IsApproved", itemDto.IsApproved), new SqlParameter("@IsApproved", itemDto.IsApproved),
new SqlParameter("@QtyReceived", itemDto.QtyReceived), new SqlParameter("@QtyReceived", itemDto.QtyReceived),
new SqlParameter("@LotId", itemDto.LotId)); new SqlParameter("@LotId", itemDto.LotId),
messCode,message);
} }
else else
{ {
await _dbContext.Database await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPurchRequest @ItemCartId, @IsActive, @UserId,@ItemCount,@PRNo,@DateNeeded,@Qty,@ChargeTo,@Remarks", .ExecuteSqlRawAsync("EXEC PostPurchRequest @ItemCartId, @IsActive, @UserId,@ItemCount," +
"@PRNo,@DateNeeded,@Qty,@ChargeTo,@Remarks,@ProjectCodeId,@MessCode OUTPUT, @Message OUTPUT",
new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L), new SqlParameter("@ItemCartId", itemDto.ItemCartId != null ? itemDto.ItemCartId : 0L),
new SqlParameter("@IsActive", 1), new SqlParameter("@IsActive", 1),
new SqlParameter("@UserId", itemDto.UserId), new SqlParameter("@UserId", itemDto.UserId),
@ -330,40 +241,57 @@ namespace CPRNIMS.Domain.Services.Items
new SqlParameter("@DateNeeded", itemDto.DateNeeded), new SqlParameter("@DateNeeded", itemDto.DateNeeded),
new SqlParameter("@Qty", itemDto.Qty), new SqlParameter("@Qty", itemDto.Qty),
new SqlParameter("@ChargeTo", itemDto.ChargeTo), new SqlParameter("@ChargeTo", itemDto.ChargeTo),
new SqlParameter("@Remarks", itemDto.Remarks)); new SqlParameter("@Remarks", itemDto.Remarks ?? "N/A"),
new SqlParameter("@ProjectCodeId", itemDto.ProjectCodeId),
messCode, message);
} }
return new ItemCart();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
public async Task<long> GetPRNo()
{
try
{
// Query the PRs table
var latestPR = await _dbContext.PRs
.OrderByDescending(ic => ic.PRNo) // Sort by PRNo in descending order
.FirstOrDefaultAsync(); // Retrieve the first record
if (latestPR != null) return new ResponseObject() {
messCode= (byte)messCode.Value,
message= message.Value.ToString()
};
}
public async Task PostPutAttachment(AttachmentRequest attach)
{ {
return latestPR.PRNo; var existing = await _dbContext.PRAttachments
.FirstOrDefaultAsync(a => a.PRId == attach.PRId);
if (existing == null)
{
var attchmnt = new PRAttachments()
{
FileName = attach.FileName,
OrigFileName = attach.OrigFileName,
PRId = attach.PRId
};
await _dbContext.PRAttachments.AddAsync(attchmnt);
} }
else else
{ {
return 0; // Example: Return 0 if no records found existing.OrigFileName = attach.OrigFileName;
existing.FileName = Guid.NewGuid().ToString();
} }
await _dbContext.SaveChangesAsync();
} }
catch (SqlException ex) public async Task<(long,long)> GetPRNo()
{ {
// Handle the exception (log, rethrow, etc.) try
ex.ToString(); {
var latestPR = await _dbContext.PRs
.Where(ic => ic.PRNo != null)
.OrderByDescending(ic => ic.PRNo)
.FirstOrDefaultAsync();
if (latestPR != null)
return (latestPR.PRNo + 1,latestPR.PRId + 1);
else
return (0,0);
}
catch (Exception ex)
{
throw; throw;
} }
} }
Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto) Task<ItemCart> IItem.PostPutItemPath(ItemDto itemDto)
{ {
@ -372,22 +300,11 @@ namespace CPRNIMS.Domain.Services.Items
public async Task <List<Departments>> GetDepartment(ItemCodeDto itemCode) public async Task <List<Departments>> GetDepartment(ItemCodeDto itemCode)
{ {
try return await _dbContext.Departments
{
var departments = await _dbContext.Departments
.Where(d => d.IsActive == true) .Where(d => d.IsActive == true)
.ToListAsync(); .ToListAsync();
return departments;
}
catch (Exception ex)
{
// Log the exception or handle it as needed
throw;
}
} }
public async Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto) public async Task<List<NotifUserKey>> GetNotifUserKey(ItemDto itemDto)
{
try
{ {
var allItems = await _dbContext.NotifUserKeys var allItems = await _dbContext.NotifUserKeys
.FromSqlRaw($"EXEC GetNotifUserKey @UserId,@Status,@PRDetailsId,@PRNo", .FromSqlRaw($"EXEC GetNotifUserKey @UserId,@Status,@PRDetailsId,@PRNo",
@ -399,11 +316,5 @@ namespace CPRNIMS.Domain.Services.Items
return allItems ?? new List<NotifUserKey>(); return allItems ?? new List<NotifUserKey>();
} }
catch (SqlException ex)
{
ex.ToString();
throw;
}
}
} }
} }

View File

@ -2,7 +2,6 @@
using CPRNIMS.Infrastructure.Database; using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.PR; using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Entities.Common; using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Entities.Purchasing; using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Entities.SMTP; using CPRNIMS.Infrastructure.Entities.SMTP;
using Microsoft.Data.SqlClient; using Microsoft.Data.SqlClient;
@ -14,6 +13,7 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using CPRNIMS.Infrastructure.Models.Common;
namespace CPRNIMS.Domain.Services.PR namespace CPRNIMS.Domain.Services.PR
{ {
@ -297,7 +297,10 @@ namespace CPRNIMS.Domain.Services.PR
return allItems ?? new List<NotificationById>(); return allItems ?? new List<NotificationById>();
} }
public async Task<List<ProjectCodes>> GetProjectCodes(PRDto pRDto)
{
return await _dbContext.ProjectCodes.ToListAsync();
}
public async Task<MessageResponse> PRItemRemoval(PRDto prDto) public async Task<MessageResponse> PRItemRemoval(PRDto prDto)
{ {
var (messCode, message) = CreateOutputParams(); var (messCode, message) = CreateOutputParams();
@ -318,6 +321,74 @@ namespace CPRNIMS.Domain.Services.PR
}; };
return response; return response;
} }
public async Task<ResponseObject> PostPutProjectCode(PRDto prDto)
{
if (prDto == null) throw new ArgumentNullException(nameof(prDto));
var existing = await _dbContext.ProjectCodes
.FirstOrDefaultAsync(p => p.ProjectCodeId == prDto.ProjectCodeId);
if (existing == null)
{
var project = new ProjectCodes
{
ProjectCode = prDto.ProjectCode,
ProjectName = prDto.ProjectName,
DeliveryAddress = prDto.DeliveryAddress,
MaxDays = prDto.MaxDays,
IsActive = prDto.IsActive
};
await _dbContext.ProjectCodes.AddAsync(project);
}
else
{
if (await IsUsingAsync(prDto.ProjectCodeId))
{
return new ResponseObject()
{
message = "Cannot update this project code because it is already being used in a Purchase Order (PO).",
messCode = 0,
success = false,
};
}
else
{
existing.ProjectCode = prDto.ProjectCode;
existing.ProjectName = prDto.ProjectName;
existing.DeliveryAddress = prDto.DeliveryAddress;
existing.MaxDays = prDto.MaxDays;
existing.IsActive = prDto.IsActive;
}
}
await _dbContext.SaveChangesAsync();
return new ResponseObject()
{
message = "Project code detail successfully updated",
messCode = 1,
success = true
};
}
private async Task<bool> IsUsingAsync(int projectCodeId)
{
try
{
return await (from pr in _dbContext.PRs
join pod in _dbContext.PODetails on pr.PRNo equals pod.PRNo
where pr.ProjectCodeId == projectCodeId
&& !pod.IsRemoved
&& pr.IsActive
select pr).AnyAsync();
}
catch (Exception ex)
{
ex.ToString();
throw;
}
}
#endregion #endregion
} }
} }

View File

@ -1,6 +1,4 @@
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.ViewModel.Items;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
@ -12,6 +10,7 @@ namespace CPRNIMS.Domain.UIContracts.PR
{ {
public interface IPRequest public interface IPRequest
{ {
#region Get
Task<List<PRVM>?> GetApproverName(User user, PRVM viewModels); Task<List<PRVM>?> GetApproverName(User user, PRVM viewModels);
Task<List<PRVM>> GetForReceiving(User user, PRVM viewModel); Task<List<PRVM>> GetForReceiving(User user, PRVM viewModel);
Task<List<PRVM>> GetItemDetailForReceiving(User user, PRVM viewModel); Task<List<PRVM>> GetItemDetailForReceiving(User user, PRVM viewModel);
@ -27,6 +26,9 @@ namespace CPRNIMS.Domain.UIContracts.PR
Task<List<PRVM>?> GetDetailedPRTracking(User user, PRVM viewModel); Task<List<PRVM>?> GetDetailedPRTracking(User user, PRVM viewModel);
Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel); Task<List<PRVM>?> GetSupplierAlternativeOffer(User user, PRVM viewModel);
Task<List<PRVM>?> GetSupplierAlterOfferDetails(User user, PRVM viewModel); Task<List<PRVM>?> GetSupplierAlterOfferDetails(User user, PRVM viewModel);
Task<List<PRVM>?> GetProjectCodes(User user, PRVM viewModels);
#endregion
#region Post Put
Task<PRVM> PostPRApproveReject(User user, PRVM viewModel); Task<PRVM> PostPRApproveReject(User user, PRVM viewModel);
Task<PRVM> PostPutItemReceiving(User user, PRVM viewModel); Task<PRVM> PostPutItemReceiving(User user, PRVM viewModel);
Task<PRVM> PutItemDetail(User user, PRVM viewModel); Task<PRVM> PutItemDetail(User user, PRVM viewModel);
@ -37,5 +39,7 @@ namespace CPRNIMS.Domain.UIContracts.PR
Task<PRVM> PutSupplierAlterOffer(User user, PRVM viewModel); Task<PRVM> PutSupplierAlterOffer(User user, PRVM viewModel);
Task<PRVM> PRItemRemoval(User user, PRVM viewModel); Task<PRVM> PRItemRemoval(User user, PRVM viewModel);
Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel); Task<PRVM> ApprovedSelectedPRItem(User user, PRVM viewModel);
Task<PRVM> PostPutProjectCode(User user, PRVM viewModel);
#endregion
} }
} }

View File

@ -116,6 +116,11 @@ namespace CPRNIMS.Domain.UIServices.PR
} }
#endregion #endregion
#region Get #region Get
public async Task<List<PRVM>?> GetProjectCodes(User user, PRVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:GetProjectCodes"]);
}
public async Task<List<PRVM>?> GetApproverName(User user, PRVM viewModel) public async Task<List<PRVM>?> GetApproverName(User user, PRVM viewModel)
{ {
return await SendGetApiRequest(user, viewModel, return await SendGetApiRequest(user, viewModel,
@ -253,6 +258,12 @@ namespace CPRNIMS.Domain.UIServices.PR
return await SendPostApiRequest(user, viewModel, return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:ApprovedSelectedPRItem"]); _configuration["LLI:NonInvent:PRMgmt:ApprovedSelectedPRItem"]);
} }
public async Task<PRVM> PostPutProjectCode(User user, PRVM viewModel)
{
return await SendPostApiRequest(user, viewModel,
_configuration["LLI:NonInvent:PRMgmt:PostPutProjectCode"]);
}
#endregion #endregion
} }
} }

View File

@ -47,6 +47,8 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<SMTPCredential> SMTPCredentials { get; set; } public virtual DbSet<SMTPCredential> SMTPCredentials { get; set; }
public virtual DbSet<PRDetails> PRDetails { get; set; } public virtual DbSet<PRDetails> PRDetails { get; set; }
public virtual DbSet<PRItemList> PRItemLists { get; set; } public virtual DbSet<PRItemList> PRItemLists { get; set; }
public DbSet<PRAttachments> PRAttachments { get; set; }
public DbSet<ProjectCodes> ProjectCodes { get; set; }
public virtual DbSet<NotificationById> NotificationByIds { get; set; } public virtual DbSet<NotificationById> NotificationByIds { get; set; }
public virtual DbSet<AlternativeOffer> AlternativeOffers { get; set; } public virtual DbSet<AlternativeOffer> AlternativeOffers { get; set; }
public virtual DbSet<AlternativeOfferDetails> AlternativeOfferDetails { get; set; } public virtual DbSet<AlternativeOfferDetails> AlternativeOfferDetails { get; set; }
@ -84,6 +86,7 @@ namespace CPRNIMS.Infrastructure.Database
public virtual DbSet<ApprovedPO> ApprovedPOs { get; set; } public virtual DbSet<ApprovedPO> ApprovedPOs { get; set; }
public virtual DbSet<PurchaseOrder> PurchaseOrders { get; set; } public virtual DbSet<PurchaseOrder> PurchaseOrders { get; set; }
public virtual DbSet<PO> POs { get; set; } public virtual DbSet<PO> POs { get; set; }
public DbSet<PODetails> PODetails { get; set; }
public virtual DbSet<PRPOSummaryCount> PRPOSummaryCounts { get; set; } public virtual DbSet<PRPOSummaryCount> PRPOSummaryCounts { get; set; }
public virtual DbSet<PRPOSummaryItem> PRPOSummaryItems { get; set; } public virtual DbSet<PRPOSummaryItem> PRPOSummaryItems { get; set; }
public virtual DbSet<POItemDetail> POItemDetails { get; set; } public virtual DbSet<POItemDetail> POItemDetails { get; set; }
@ -117,6 +120,7 @@ namespace CPRNIMS.Infrastructure.Database
#region Automation Part #region Automation Part
public virtual DbSet<AllForCanvass> AllForCanvasses { get; set; } public virtual DbSet<AllForCanvass> AllForCanvasses { get; set; }
public DbSet<ErrorLog> ErrorLogs { get; set; }
#endregion #endregion
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {

View File

@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Dto.Items
{
public class AttachmentRequest
{
public long PRId { get; set; }
public string? FileName { get; set; }
public string? OrigFileName { get; set; }
}
}

View File

@ -8,7 +8,8 @@ namespace CPRNIMS.Infrastructure.Dto.Items
{ {
public class ItemCartDto public class ItemCartDto
{ {
public List<long>? ItemCartIds { get; set; } public long ItemCartId { get; set; }
public List<int>? Qty { get; set; } public long ItemNo { get; set; }
public decimal Qty { get; set; }
} }
} }

View File

@ -20,6 +20,7 @@ namespace CPRNIMS.Infrastructure.Dto.Items
public string? ItemName { get; set; } public string? ItemName { get; set; }
public string? ItemDescription { get; set; } public string? ItemDescription { get; set; }
public string? UserId { get; set; } public string? UserId { get; set; }
public string? FileName { get; set; }
public short Status { get; set; } public short Status { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
} }

View File

@ -115,5 +115,9 @@ namespace CPRNIMS.Infrastructure.Dto.Items
public DateTime DateFrom { get; set; } public DateTime DateFrom { get; set; }
public DateTime DateTo { get; set; } public DateTime DateTo { get; set; }
public bool IsSorting { get; set; }=false; public bool IsSorting { get; set; }=false;
public int ProjectCodeId { get; set; }
public long PRId { get; set; }
public string? FileName { get; set; }
public string? OrigFileName { get; set; }
} }
} }

View File

@ -125,5 +125,14 @@ namespace CPRNIMS.Infrastructure.Dto.PR
public bool IsApproved { get; set; }=false; public bool IsApproved { get; set; }=false;
public int AlternativeOfferId { get; set; } public int AlternativeOfferId { get; set; }
public byte AppsModuleId { get; set; } public byte AppsModuleId { get; set; }
public int ProjectCodeId { get; set; }
public string? ProjectCode { get; set; }
public string? ProjectName { get; set; }
public int MaxDays { get; set; }
public string? DeliveryAddress { get; set; }
public int PRAttachmentId { get; set; }
public long PRId { get; set; }
public string? FileName { get; set; }
public string? OrigFileName { get; set; }
} }
} }

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Common
{
public class ErrorLog
{
public Guid Id { get; set; }
public string Path { get; set; } = default!;
public string HttpMethod { get; set; } = default!;
public string? QueryString { get; set; }
public int StatusCode { get; set; }
public string ExceptionType { get; set; } = default!;
public string Message { get; set; } = default!;
public string? StackTrace { get; set; }
public string? UserId { get; set; }
public string? IpAddress { get; set; }
public DateTime CreatedAt { get; set; }
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
[Table("PODetails")]
public class PODetails
{
[Key]
public long PODetailId { get; set; }
public long POId { get; set; }
public long PRNo { get; set; }
public bool IsRemoved { get; set; }
}
}

View File

@ -17,10 +17,9 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
public long PRId { get; set; } public long PRId { get; set; }
public long PRNo { get; set; } public long PRNo { get; set; }
public string? NewPRNo { get; set; } public string? NewPRNo { get; set; }
//public long ItemCodeId { get; set; } public int ProjectCodeId { get; set; }
public long ItemCartId { get; set; } public long ItemCartId { get; set; }
public string? UserId { get; set; } public string? UserId { get; set; }
public int ItemCount { get; set; }
public bool IsActive { get; set; } public bool IsActive { get; set; }
} }
} }

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Purchasing
{
[Table("PRAttachments")]
public class PRAttachments
{
[Key]
public int PRAttachmentId { get; set; }
public long PRId { get; set; }
public string? FileName { get; set; }
public string? OrigFileName { get; set; }
}
}

View File

@ -37,5 +37,6 @@ namespace CPRNIMS.Infrastructure.Entities.Purchasing
public bool Queue { get; set; } public bool Queue { get; set; }
public string? AttestedBy { get; set; } public string? AttestedBy { get; set; }
public string? ApprovedBy { get; set; } public string? ApprovedBy { get; set; }
public string? ProjectCode { get; set; }
} }
} }

View File

@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.Purchasing
{
[Table("ProjectCodes")]
public class ProjectCodes
{
[Key]
public int ProjectCodeId { get; set; }
public string? ProjectCode { get; set; }
public string? ProjectName { get; set; }
public int MaxDays { get; set; }
public string? DeliveryAddress { get; set; }
public bool IsActive { get; set; }
}
}

View File

@ -44,6 +44,7 @@ namespace CPRNIMS.Infrastructure.ViewModel.Items
public string? ItemAttachPath { get; set; } public string? ItemAttachPath { get; set; }
public int CartItemCount { get; set; } public int CartItemCount { get; set; }
public int ItemCartId { get; set; } public int ItemCartId { get; set; }
public string? ItemCartIds { get; set; }
public long ItemAttachId { get; set; } public long ItemAttachId { get; set; }
public decimal QtyRequest { get; set; } public decimal QtyRequest { get; set; }
public byte IsApproved { get; set; } public byte IsApproved { get; set; }
@ -54,5 +55,10 @@ namespace CPRNIMS.Infrastructure.ViewModel.Items
public bool IsMDLD { get; set; } = false; public bool IsMDLD { get; set; } = false;
public bool CheckBox { get; set; } public bool CheckBox { get; set; }
public bool IsCount { get; set; } public bool IsCount { get; set; }
public int ProjectCodeId { get; set; }
public string? FileName { get; set; }
public long PRId { get; set; }
public string? ProjectCode { get; set; }
public string? OrigFileName { get; set; }
} }
} }

View File

@ -123,6 +123,15 @@ namespace CPRNIMS.Infrastructure.ViewModel.PR
public string? Description { get; set; } public string? Description { get; set; }
public int AlternativeOfferId { get; set; } public int AlternativeOfferId { get; set; }
public string? AggreDescription { get; set; } public string? AggreDescription { get; set; }
public string? ProjectCode { get; set; }
public int ProjectCodeId { get; set; }
public string? ProjectName { get; set; }
public int MaxDays { get; set; }
public string? DeliveryAddress { get; set; }
public int PRAttachmentId { get; set; }
public long PRId { get; set; }
public string? FileName { get; set; }
public string? OrigFileName { get; set; }
public ItemReceivingList? ItemList { get; set; } public ItemReceivingList? ItemList { get; set; }
public PRList? PRList { get; set; } public PRList? PRList { get; set; }
} }

View File

@ -146,4 +146,9 @@
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<Folder Include="Helper\" />
<Folder Include="wwwroot\Content\Uploads\PRAttachment\" />
</ItemGroup>
</Project> </Project>

View File

@ -31,13 +31,13 @@ namespace CPRNIMS.WebApi.Controllers.Account
private readonly UserClaimsManager _userClaimsManager; private readonly UserClaimsManager _userClaimsManager;
private readonly RoleManager<IdentityRole> _roleManager; private readonly RoleManager<IdentityRole> _roleManager;
public AccountController(ErrorMessageService errorMessageService, public AccountController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment,
IConfiguration configuration, IConfiguration configuration,
IAttachment attachment, IAccount account, IDepartment department, IControllerAccess controllerAccess, IAttachment attachment, IAccount account, IDepartment department, IControllerAccess controllerAccess,
UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager,
UserClaimsManager userClaimsManager, RoleManager<IdentityRole> roleManager UserClaimsManager userClaimsManager, RoleManager<IdentityRole> roleManager
) : ) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_errorMessageService = errorMessageService; _errorMessageService = errorMessageService;
_attachment = attachment; _attachment = attachment;

View File

@ -28,7 +28,7 @@ namespace CPRNIMS.WebApi.Controllers.Account
SignInManager<ApplicationUser> signInManager, SignInManager<ApplicationUser> signInManager,
UserManager<ApplicationUser> userManager UserManager<ApplicationUser> userManager
) )
: base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) : base(errorMessageService, webHostEnvironment, configuration)
{ {
_config = configuration; _config = configuration;
_smtpHelper = sMTPHelper; _smtpHelper = sMTPHelper;

View File

@ -13,11 +13,11 @@ namespace CPRNIMS.WebApi.Controllers.Base
[ApiController] [ApiController]
public class BaseController : ControllerBase public class BaseController : ControllerBase
{ {
private readonly IWebHostEnvironment _webHostEnvironment; public readonly IWebHostEnvironment _webHostEnvironment;
public readonly ErrorMessageService ErrorMessageService; public readonly ErrorMessageService ErrorMessageService;
public IConfiguration _configuration; public IConfiguration _configuration;
public BaseController(ErrorMessageService errorMessageService, public BaseController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, Infrastructure.Helper.SMTPHelper sMTPHelper, IConfiguration configuration) IWebHostEnvironment webHostEnvironment, IConfiguration configuration)
{ {
ErrorMessageService = errorMessageService; ErrorMessageService = errorMessageService;
_webHostEnvironment = webHostEnvironment; _webHostEnvironment = webHostEnvironment;

View File

@ -21,7 +21,7 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
public CanvassMgmtController(ErrorMessageService errorMessageService, public CanvassMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
IConfiguration configuration, ICanvass canvass) : IConfiguration configuration, ICanvass canvass) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_canvass = canvass; _canvass = canvass;
_config = configuration; _config = configuration;

View File

@ -17,9 +17,9 @@ namespace CPRNIMS.WebApi.Controllers.Finance
private readonly IRR _rr; private readonly IRR _rr;
public RRMgmtController(ErrorMessageService errorMessageService, public RRMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment,
IConfiguration configuration, SMTPHelper smptHelper, IRR rr) : IConfiguration configuration, IRR rr) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_rr = rr; _rr = rr;
} }

View File

@ -17,9 +17,9 @@ namespace CPRNIMS.WebApi.Controllers.Inventory
private readonly IInventory _inventory; private readonly IInventory _inventory;
public InventoryMgmtController(ErrorMessageService errorMessageService, public InventoryMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IConfiguration configuration, IWebHostEnvironment webHostEnvironment, IConfiguration configuration,
IInventory inventory) : IInventory inventory) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment,configuration)
{ {
_inventory = inventory; _inventory = inventory;
} }

View File

@ -2,6 +2,7 @@
using CPRNIMS.Domain.Contracts.SMTP; using CPRNIMS.Domain.Contracts.SMTP;
using CPRNIMS.Domain.Services; using CPRNIMS.Domain.Services;
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Common; using CPRNIMS.Infrastructure.Models.Common;
using CPRNIMS.Infrastructure.ViewModel.Common; using CPRNIMS.Infrastructure.ViewModel.Common;
@ -17,13 +18,15 @@ namespace CPRNIMS.WebApi.Controllers.Items
{ {
private readonly IItem _item; private readonly IItem _item;
private readonly IConfiguration _config; private readonly IConfiguration _config;
private readonly SMTPHelper _smtpHelper;
public ItemMgmtController(ErrorMessageService errorMessageService, public ItemMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment, SMTPHelper smtpHelper,
IConfiguration configuration, IItem item) : IConfiguration configuration, IItem item) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_config = configuration; _config = configuration;
_item= item; _item= item;
_smtpHelper = smtpHelper;
} }
[HttpPost("PostPutItemPath")] [HttpPost("PostPutItemPath")]
@ -54,44 +57,66 @@ namespace CPRNIMS.WebApi.Controllers.Items
[HttpPost("PostPurchRequest")] [HttpPost("PostPurchRequest")]
public async Task<IActionResult> PostPurchRequest([FromBody] ItemVM viewModel) public async Task<IActionResult> PostPurchRequest([FromBody] ItemVM viewModel)
{ {
try if (viewModel?.ItemCartVM == null)
{ return BadRequest("Invalid request.");
// Check if ItemCartId, Qty, and ItemNo are null or not of the same length
if (viewModel.ItemCartVM.ItemCartId == null ||
viewModel.ItemCartVM.Qty == null ||
viewModel.ItemCartVM.ItemNo == null)
{
throw new ArgumentNullException("One or more lists in ItemCartVM are null");
}
if (viewModel.ItemCartVM.ItemCartId.Count != viewModel.ItemCartVM.Qty.Count || if (viewModel.ItemCartVM.ItemCartId.Count != viewModel.ItemCartVM.Qty.Count ||
viewModel.ItemCartVM.ItemCartId.Count != viewModel.ItemCartVM.ItemNo.Count) viewModel.ItemCartVM.ItemCartId.Count != viewModel.ItemCartVM.ItemNo.Count)
{ {
throw new ArgumentException("The lengths of ItemCartId, Qty, and ItemNo must be the same"); return BadRequest("ItemCartId, Qty, and ItemNo length mismatch.");
} }
viewModel.ItemCount = viewModel.ItemCartVM.ItemCartId.Count; var result = await ProcessPurchaseRequest(viewModel);
long prNo = await _item.GetPRNo();
var itemDto = new ItemDto(); return Ok(new { success = result });
// Process each item in the ItemCartVM }
foreach (var itemCartId in viewModel.ItemCartVM.ItemCartId) private async Task<ItemDto> ProcessPurchaseRequest(ItemVM viewModel)
{ {
var index = viewModel.ItemCartVM.ItemCartId.IndexOf(itemCartId); var (prNo,prId) = await _item.GetPRNo();
bool IsSuccess = false;
int itemCount = viewModel.ItemCartVM.ItemCartId.Count;
var dto = new ItemDto();
for (int i = 0; i < itemCount; i++)
{
dto = new ItemDto
{
ItemCartId = viewModel.ItemCartVM.ItemCartId[i],
Qty = viewModel.ItemCartVM.Qty[i],
ItemNo = viewModel.ItemCartVM.ItemNo[i],
ItemCount = itemCount,
RequestTypeId = viewModel.RequestTypeId,
UserId = viewModel.UserId,
PRNo = prNo,
DateNeeded = viewModel.DateNeeded,
ChargeTo = viewModel.ChargeTo,
Remarks = viewModel.Remarks,
ProjectCodeId = viewModel.ProjectCodeId,
FileName=viewModel.FileName,
OrigFileName = viewModel.OrigFileName,
PRId= viewModel.PRId != null ? prId : 0L
};
itemDto.ItemCartId = itemCartId; var response = await _item.PostPurchRequest(dto);
itemDto.Qty = viewModel.ItemCartVM.Qty[index]; if (response.messCode == 1)
itemDto.ItemNo = viewModel.ItemCartVM.ItemNo[index]; IsSuccess = true;
itemDto.ItemCount = viewModel.ItemCount;
itemDto.RequestTypeId = viewModel.RequestTypeId;
itemDto.UserId = viewModel.UserId;
itemDto.PRNo = prNo + 1;
itemDto.DateNeeded = viewModel.DateNeeded;
itemDto.ChargeTo = viewModel.ChargeTo;
itemDto.Remarks = viewModel.Remarks;
await _item.PostPurchRequest(itemDto);
} }
if (IsSuccess)
{
var attachment = new AttachmentRequest()
{
FileName = dto.FileName,
OrigFileName = dto.OrigFileName,
PRId = dto.PRId
};
await _item.PostPutAttachment(attachment);
// await SendNotificationEmail(dto);
}
return dto;
}
private async Task SendNotificationEmail(ItemDto itemDto)
{
var getNotif = await _item.GetNotifUserKey(itemDto); var getNotif = await _item.GetNotifUserKey(itemDto);
var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "NewPR.cshtml"); var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "NewPR.cshtml");
@ -115,15 +140,8 @@ namespace CPRNIMS.WebApi.Controllers.Items
Server = _configuration["SMTP:Server"], Server = _configuration["SMTP:Server"],
UserName = _configuration["SMTP:UserName"], UserName = _configuration["SMTP:UserName"],
}; };
// await _smptHelper.SendEmailAsync(messageDetails);
return Ok(new { success = true }); await _smtpHelper.SendEmailAsync(messageDetails);
}
catch (Exception ex)
{
var message = ex.InnerException?.ToString() ?? ex.Message;
await PostErrorMessage(message, "WebApi");
return StatusCode(500, new { success = false, message });
}
} }
[HttpPost("PostPutItem")] [HttpPost("PostPutItem")]

View File

@ -24,7 +24,7 @@ namespace CPRNIMS.WebApi.Controllers.PO
public POMgmtController(ErrorMessageService errorMessageService, public POMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
IConfiguration configuration, ISMTP sMTP, IPurchaseOrder purchaseOrder) : IConfiguration configuration, ISMTP sMTP, IPurchaseOrder purchaseOrder) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_smtpHelper = sMTPHelper; _smtpHelper = sMTPHelper;
_sMTP= sMTP; _sMTP= sMTP;

View File

@ -1,10 +1,16 @@
using CPRNIMS.Domain.Contracts.PR; using CPRNIMS.Domain.Contracts.PR;
using CPRNIMS.Domain.Services; using CPRNIMS.Domain.Services;
using CPRNIMS.Infrastructure.Dto.PO;
using CPRNIMS.Infrastructure.Dto.PR; using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Entities.Purchasing;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Common;
using CPRNIMS.Infrastructure.ViewModel.Common; using CPRNIMS.Infrastructure.ViewModel.Common;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
using CPRNIMS.WebApi.Controllers.Base; using CPRNIMS.WebApi.Controllers.Base;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.HttpResults;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Text; using System.Text;
@ -21,7 +27,7 @@ namespace CPRNIMS.WebApi.Controllers.PR
public PRMgmtController(ErrorMessageService errorMessageService, public PRMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
IConfiguration configuration, IPRequest pRequest) : IConfiguration configuration, IPRequest pRequest) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_config = configuration; _config = configuration;
_smptHelper = sMTPHelper; _smptHelper = sMTPHelper;
@ -261,8 +267,23 @@ namespace CPRNIMS.WebApi.Controllers.PR
return Ok(new { success = false, messCode = 0, message = errorMessage }); return Ok(new { success = false, messCode = 0, message = errorMessage });
} }
} }
[HttpPost("PostPutProjectCode")]
public async Task<IActionResult> PostPutProjectCode([FromBody] PRDto prDto)
{
var results = await _pRequest.PostPutProjectCode(prDto);
return Ok( new { data = results, message =results.message, messCode=results.messCode });
}
#endregion #endregion
#region Get #region Get
[HttpPost("GetProjectCodes")]
public async Task<IActionResult> GetProjectCodes(PRDto PRDto)
{
return await ExecuteWithErrorHandling(
() => _pRequest.GetProjectCodes(PRDto),
nameof(GetProjectCodes), false
);
}
[HttpPost("GetApproverName")] [HttpPost("GetApproverName")]
public async Task<IActionResult> GetApproverName(PRDto PRDto) public async Task<IActionResult> GetApproverName(PRDto PRDto)
{ {

View File

@ -6,6 +6,7 @@ using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.Receiving; using CPRNIMS.Infrastructure.ViewModel.Receiving;
using CPRNIMS.WebApi.Controllers.Base; using CPRNIMS.WebApi.Controllers.Base;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Runtime.InteropServices;
using System.Text; using System.Text;
namespace CPRNIMS.WebApi.Controllers.Receiving namespace CPRNIMS.WebApi.Controllers.Receiving
@ -17,9 +18,9 @@ namespace CPRNIMS.WebApi.Controllers.Receiving
private readonly IItem _item; private readonly IItem _item;
public ReceivingController(ErrorMessageService errorMessageService, public ReceivingController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment,
IConfiguration configuration, IReceiving receiving, IItem item) : IConfiguration configuration, IReceiving receiving, IItem item) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_receiving = receiving; _receiving = receiving;
_item= item; _item= item;
@ -68,7 +69,7 @@ namespace CPRNIMS.WebApi.Controllers.Receiving
{ {
try try
{ {
long prNo = await _item.GetPRNo(); var (prNo,prId) = await _item.GetPRNo();
foreach (var items in viewModel.ItemList.PRDetailsId) foreach (var items in viewModel.ItemList.PRDetailsId)
{ {
var index = viewModel.ItemList.PRDetailsId.IndexOf(items); var index = viewModel.ItemList.PRDetailsId.IndexOf(items);

View File

@ -14,9 +14,9 @@ namespace CPRNIMS.WebApi.Controllers.SMTP
{ {
private readonly ISMTP _sMTP; private readonly ISMTP _sMTP;
public SMTPMgmtController(ErrorMessageService errorMessageService, public SMTPMgmtController(ErrorMessageService errorMessageService,
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper, IWebHostEnvironment webHostEnvironment,
IConfiguration configuration, ISMTP sMTP) : IConfiguration configuration, ISMTP sMTP) :
base(errorMessageService, webHostEnvironment, sMTPHelper, configuration) base(errorMessageService, webHostEnvironment, configuration)
{ {
_sMTP = sMTP; _sMTP = sMTP;
} }

View File

@ -0,0 +1,13 @@
namespace CPRNIMS.WebApi.Exceptions
{
public class AppException : Exception
{
public int StatusCode { get; }
public AppException(string message, int statusCode = StatusCodes.Status400BadRequest)
: base(message)
{
StatusCode = statusCode;
}
}
}

View File

@ -0,0 +1,89 @@
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.WebApi.Exceptions;
using System.Security.Claims;
using System.Text.Json;
namespace CPRNIMS.Middleware
{
public sealed class GlobalExceptionMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<GlobalExceptionMiddleware> _logger;
private readonly IWebHostEnvironment _env;
private readonly IServiceScopeFactory _scopeFactory;
public GlobalExceptionMiddleware(
RequestDelegate next,
ILogger<GlobalExceptionMiddleware> logger,
IWebHostEnvironment env,
IServiceScopeFactory scopeFactory)
{
_next = next;
_logger = logger;
_env = env;
_scopeFactory = scopeFactory;
}
public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(context);
}
catch (Exception ex)
{
_logger.LogError(ex, "Unhandled exception");
await LogToDatabaseAsync(context, ex);
await HandleResponseAsync(context, ex);
}
}
private async Task LogToDatabaseAsync(HttpContext context, Exception ex)
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<NonInventoryDbContext>();
var errorLog = new ErrorLog
{
Id = Guid.NewGuid(),
Path = context.Request.Path,
HttpMethod = context.Request.Method,
QueryString = context.Request.QueryString.Value,
StatusCode = context.Response.StatusCode,
ExceptionType = ex.GetType().FullName!,
Message = ex.Message,
StackTrace = ex.StackTrace,
UserId = context.User?.FindFirst(ClaimTypes.NameIdentifier)?.Value,
IpAddress = context.Connection.RemoteIpAddress?.ToString(),
CreatedAt = DateTime.UtcNow
};
db.ErrorLogs.Add(errorLog);
await db.SaveChangesAsync();
}
private async Task HandleResponseAsync(HttpContext context, Exception ex)
{
context.Response.ContentType = "application/json";
context.Response.StatusCode = ex switch
{
AppException app => app.StatusCode,
ArgumentException => StatusCodes.Status400BadRequest,
UnauthorizedAccessException => StatusCodes.Status401Unauthorized,
_ => StatusCodes.Status500InternalServerError
};
var response = new
{
success = false,
message = _env.IsDevelopment()
? ex.Message
: "An unexpected error occurred"
};
await context.Response.WriteAsync(JsonSerializer.Serialize(response));
}
}
}

View File

@ -1,3 +1,4 @@
using CPRNIMS.Middleware;
using CPRNIMS.WebApi.Common; using CPRNIMS.WebApi.Common;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -15,6 +16,7 @@ if (app.Environment.IsDevelopment())
c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); //originally "./swagger/v1/swagger.json" c.SwaggerEndpoint("./v2/swagger.json", "LLOYD API V2"); //originally "./swagger/v1/swagger.json"
}); });
} }
app.UseMiddleware<GlobalExceptionMiddleware>();
app.UseSwagger(); app.UseSwagger();
app.UseSwaggerUI(c => app.UseSwaggerUI(c =>
{ {

View File

@ -1,4 +1,22 @@
CREATE TABLE [dbo].[ControllerAccessDesc]( CREATE TABLE ProjectCodes(
ProjectCodeId INT PRIMARY KEY IDENTITY(1,1),
ProjectCode VARCHAR(50) NOT NULL,
ProjectName VARCHAR(200) NOT NULL,
MaxDays INT NOT NULL,
DeliveryAddress VARCHAR(300) NOT NULL,
IsActive BIT DEFAULT(1)
)
CREATE TABLE PRAttachments(
PRAttachmentId INT PRIMARY KEY IDENTITY(1,1),
PRId BIGINT,
OrigFileName VARCHAR(450),
FileName NVARCHAR(450),
FOREIGN KEY (PRId) REFERENCES PR (PRId)
);
ALTER TABLE PR
ADD ProjectCodeId INT DEFAULT 0;
CREATE TABLE [dbo].[ControllerAccessDesc](
[ContAccId] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL, [ContAccId] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL,
[Action] [varchar](150) NOT NULL, [Action] [varchar](150) NOT NULL,
[Controller] [varchar](150) NOT NULL, [Controller] [varchar](150) NOT NULL,

View File

@ -41,7 +41,7 @@
<Content Update="wwwroot\Content\Images\UserProfile\2e446d27-a03d-4024-832e-3f9c50f245f5.png"> <Content Update="wwwroot\Content\Images\UserProfile\2e446d27-a03d-4024-832e-3f9c50f245f5.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Update="wwwroot\css\Item\cart.css"> <Content Update="wwwroot\css\Item\cartV2.css">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content> </Content>
<Content Update="wwwroot\GoogleSecurity\credentials.json"> <Content Update="wwwroot\GoogleSecurity\credentials.json">
@ -60,6 +60,7 @@
<Folder Include="Common\Helper\" /> <Folder Include="Common\Helper\" />
<Folder Include="Properties\NewFolder\" /> <Folder Include="Properties\NewFolder\" />
<Folder Include="Views\Components\CanvassMgmt\" /> <Folder Include="Views\Components\CanvassMgmt\" />
<Folder Include="wwwroot\Content\Uploads\PRAttachment\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@ -13,7 +13,7 @@ namespace CPRNIMS.WebApps.Controllers.Account
List<UserRightsVM>? response; List<UserRightsVM>? response;
public AccountController(IWebHostEnvironment webHostEnvironment, public AccountController(IWebHostEnvironment webHostEnvironment,
IAccount account,ErrorLogHelper errorMessageService,TokenHelper tokenHelper IAccount account,ErrorLogHelper errorMessageService,TokenHelper tokenHelper
) : base(errorMessageService, webHostEnvironment,tokenHelper) ) : base(errorMessageService, webHostEnvironment,tokenHelper, account)
{ {
_account = account; _account = account;
} }

View File

@ -1,4 +1,5 @@
using CPRNIMS.Core.Facades; using CPRNIMS.Core.Facades;
using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Infrastructure.Constant; using CPRNIMS.Infrastructure.Constant;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel; using CPRNIMS.Infrastructure.ViewModel;
@ -12,17 +13,19 @@ namespace CPRNIMS.WebApps.Controllers.Base
public abstract class BaseMethod : BaseProperties public abstract class BaseMethod : BaseProperties
{ {
protected readonly ErrorLogHelper ErrorMessageService; protected readonly ErrorLogHelper ErrorMessageService;
protected readonly IWebHostEnvironment WebHostEnvironment; public readonly IWebHostEnvironment _webHostEnvironment;
protected readonly Infrastructure.Helper.TokenHelper TokenHelper; protected readonly Infrastructure.Helper.TokenHelper TokenHelper;
private readonly IAccount _account;
protected BaseMethod( protected BaseMethod(
ErrorLogHelper errorMessageService, ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment, IWebHostEnvironment webHostEnvironment,
Infrastructure.Helper.TokenHelper tokenHelper) Infrastructure.Helper.TokenHelper tokenHelper,
IAccount account)
{ {
ErrorMessageService = errorMessageService; ErrorMessageService = errorMessageService;
WebHostEnvironment = webHostEnvironment; _webHostEnvironment = webHostEnvironment;
TokenHelper = tokenHelper; TokenHelper = tokenHelper;
_account = account;
} }
protected Infrastructure.Models.Account.User GetUser() protected Infrastructure.Models.Account.User GetUser()
@ -74,9 +77,34 @@ namespace CPRNIMS.WebApps.Controllers.Base
return RedirectToAction("Index", "Home"); return RedirectToAction("Index", "Home");
PopulateViewBagFromClaims(); PopulateViewBagFromClaims();
if(!await PopulateSidebarAsync())
{
return RedirectToAction("Logout", "Home");
}
return View(); return View();
} }
private async Task<bool> PopulateSidebarAsync()
{
try
{
if (!string.IsNullOrEmpty(ViewBag.UserRoles))
{
var myControllerAccess = await _account.GetLandingPageByUserId(GetUser());
// Group by menu name
ViewBag.TempDataElements = myControllerAccess
.GroupBy(e => e.ElementMenuName)
.ToList();
}
return true;
}
catch (Exception)
{
return false;
}
}
protected void PopulateViewBagFromClaims() protected void PopulateViewBagFromClaims()
{ {
if (!User.Identity?.IsAuthenticated ?? true) if (!User.Identity?.IsAuthenticated ?? true)
@ -90,7 +118,6 @@ namespace CPRNIMS.WebApps.Controllers.Base
User.FindAll(ClaimTypes.Role).Select(c => c.Value)); User.FindAll(ClaimTypes.Role).Select(c => c.Value));
ViewBag.URLAttachment = User.FindFirst("URLAttachment")?.Value ?? "Content/Images/UserProfile/404userImage.jpg"; ViewBag.URLAttachment = User.FindFirst("URLAttachment")?.Value ?? "Content/Images/UserProfile/404userImage.jpg";
} }
protected IActionResult GetResponse<T>(T response) protected IActionResult GetResponse<T>(T response)
{ {
return Json(new return Json(new
@ -142,12 +169,12 @@ namespace CPRNIMS.WebApps.Controllers.Base
var fileName = $"{Guid.NewGuid()}.{imageFormat.Name.ToLower()}"; var fileName = $"{Guid.NewGuid()}.{imageFormat.Name.ToLower()}";
var filePath = Path.Combine( var filePath = Path.Combine(
WebHostEnvironment.WebRootPath, _webHostEnvironment.WebRootPath,
FileExtensionPath.GetExtensionPath(imageFormat.Name.ToLower()), FileExtensionPath.GetExtensionPath(imageFormat.Name.ToLower()),
fileName); fileName);
var relativePath = var relativePath =
Path.GetRelativePath(WebHostEnvironment.WebRootPath, filePath); Path.GetRelativePath(_webHostEnvironment.WebRootPath, filePath);
return facadeAttachment.SaveAttachment( return facadeAttachment.SaveAttachment(
contentBytes, contentBytes,

View File

@ -1,4 +1,5 @@
using CPRNIMS.Domain.UIContracts.Canvass; using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.Canvass;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.Canvass; using CPRNIMS.Infrastructure.ViewModel.Canvass;
using CPRNIMS.WebApps.Controllers.Base; using CPRNIMS.WebApps.Controllers.Base;
@ -12,9 +13,9 @@ namespace CPRNIMS.WebApps.Controllers.Canvass
private readonly ICanvass _canvass; private readonly ICanvass _canvass;
public CanvassMgmtController(TokenHelper tokenHelper, ErrorLogHelper errorMessageService, public CanvassMgmtController(TokenHelper tokenHelper, ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment IWebHostEnvironment webHostEnvironment
, ICanvass canvass , ICanvass canvass,IAccount account
) )
: base(errorMessageService, webHostEnvironment, tokenHelper) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{ {
_canvass = canvass; _canvass = canvass;
} }

View File

@ -1,4 +1,5 @@
using CPRNIMS.Domain.UIContracts.Finance; using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.Finance;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.Finance; using CPRNIMS.Infrastructure.ViewModel.Finance;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
@ -13,8 +14,8 @@ namespace CPRNIMS.WebApps.Controllers.Finance
private readonly IRR _rr; private readonly IRR _rr;
public RRMgmtController(ErrorLogHelper errorMessageService, public RRMgmtController(ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper
, IRR pRequest) , IRR pRequest,IAccount account)
: base(errorMessageService, webHostEnvironment, tokenHelper) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{ {
_rr = pRequest; _rr = pRequest;
} }
@ -82,8 +83,7 @@ namespace CPRNIMS.WebApps.Controllers.Finance
#region Views #region Views
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
await IsAuthenTicated(); return await IsAuthenTicated();
return View();
} }
#endregion #endregion
} }

View File

@ -29,7 +29,7 @@ namespace CPRNIMS.WebApps.Controllers
IWebHostEnvironment webHostEnvironment, IWebHostEnvironment webHostEnvironment,
IAttachment attachment, IAccount account, IAttachment attachment, IAccount account,
ICaptchaService captchaService) : ICaptchaService captchaService) :
base(errorMessageService, webHostEnvironment,tokenHelper) base(errorMessageService, webHostEnvironment,tokenHelper,account)
{ {
_account = account; _account = account;
_attachment = attachment; _attachment = attachment;

View File

@ -1,4 +1,5 @@
using CPRNIMS.Domain.UIContracts.Inventory; using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.Inventory;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.Account; using CPRNIMS.Infrastructure.ViewModel.Account;
using CPRNIMS.Infrastructure.ViewModel.Finance; using CPRNIMS.Infrastructure.ViewModel.Finance;
@ -16,8 +17,8 @@ namespace CPRNIMS.WebApps.Controllers.Inventory
private readonly IInventory _inventory; private readonly IInventory _inventory;
public InventoryMgmtController(ErrorLogHelper errorMessageService, public InventoryMgmtController(ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper
, IInventory inventory) , IInventory inventory,IAccount account)
: base(errorMessageService, webHostEnvironment, tokenHelper) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{ {
_inventory = inventory; _inventory = inventory;
} }
@ -180,18 +181,15 @@ namespace CPRNIMS.WebApps.Controllers.Inventory
#region Views #region Views
public async Task<IActionResult> Inventory() public async Task<IActionResult> Inventory()
{ {
await IsAuthenTicated(); return await IsAuthenTicated();
return View();
} }
public async Task<IActionResult> Lot() public async Task<IActionResult> Lot()
{ {
await IsAuthenTicated(); return await IsAuthenTicated();
return View();
} }
public async Task<IActionResult> RequestItem() public async Task<IActionResult> RequestItem()
{ {
await IsAuthenTicated(); return await IsAuthenTicated();
return View();
} }
#endregion #endregion
} }

View File

@ -1,21 +1,16 @@
using Azure; using Azure;
using CPRNIMS.Domain.Services; using CPRNIMS.Domain.Services;
using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.Items; using CPRNIMS.Domain.UIContracts.Items;
using CPRNIMS.Domain.UIServices.Updater; using CPRNIMS.Domain.UIServices.Updater;
using CPRNIMS.Infrastructure.Dto.Items; using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Models.Account;
using CPRNIMS.Infrastructure.ViewModel.Account;
using CPRNIMS.Infrastructure.ViewModel.Items; using CPRNIMS.Infrastructure.ViewModel.Items;
using CPRNIMS.WebApps.Controllers.Base; using CPRNIMS.WebApps.Controllers.Base;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v3;
using Google.Apis.Drive.v3.Data;
using Google.Apis.Services;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using System.Collections.Generic; using System.Text.Json;
namespace CPRNIMS.WebApps.Controllers.Items namespace CPRNIMS.WebApps.Controllers.Items
{ {
@ -28,8 +23,8 @@ namespace CPRNIMS.WebApps.Controllers.Items
private readonly IHubContext<CartHub> _hubContext; private readonly IHubContext<CartHub> _hubContext;
public ItemMgmtController(ErrorLogHelper errorMessageService, public ItemMgmtController(ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment, IConfiguration config, TokenHelper tokenHelper, IWebHostEnvironment webHostEnvironment, IConfiguration config, TokenHelper tokenHelper,
IItem item, IHubContext<CartHub> hubContext) IItem item, IHubContext<CartHub> hubContext,IAccount account)
: base(errorMessageService, webHostEnvironment,tokenHelper) : base(errorMessageService, webHostEnvironment,tokenHelper, account)
{ {
_item = item; _item = item;
_config = config; _config = config;
@ -134,32 +129,127 @@ namespace CPRNIMS.WebApps.Controllers.Items
throw; throw;
} }
} }
private async Task<string?> SaveAttachmentAsync(IFormFile? file, string? oldFileName)
{
var uploadsPath = Path.Combine(
_webHostEnvironment.WebRootPath,
"Content", "Uploads", "PRAttachment");
Directory.CreateDirectory(uploadsPath);
// If no new file uploaded, return old filename
if (file == null)
return oldFileName;
// Delete old file if exists
if (!string.IsNullOrWhiteSpace(oldFileName))
{
await DeleteAttachmentAsync(oldFileName);
}
// Validate file extension
var allowedExtensions = new[] { ".csv", ".xlsx", ".xls", ".pdf" };
var fileExtension = Path.GetExtension(file.FileName).ToLowerInvariant();
if (!allowedExtensions.Contains(fileExtension))
{
throw new InvalidOperationException("Invalid file type. Only CSV, Excel, and PDF files are allowed.");
}
// Validate file size (5MB max)
if (file.Length > 5 * 1024 * 1024)
{
throw new InvalidOperationException("File size exceeds 5MB limit.");
}
// Generate new unique filename with original extension
var newFileName = $"{Guid.NewGuid()}{fileExtension}";
var newFilePath = Path.Combine(uploadsPath, newFileName);
// Save new file
await using var stream = new FileStream(newFilePath, FileMode.Create);
await file.CopyToAsync(stream);
// Return only filename (NOT full path)
return newFileName;
}
private async Task DeleteAttachmentAsync(string fileName)
{
if (string.IsNullOrWhiteSpace(fileName))
return;
var uploadsPath = Path.Combine(
_webHostEnvironment.WebRootPath,
"Content", "Uploads", "PRAttachment");
var filePath = Path.Combine(uploadsPath, fileName);
if (System.IO.File.Exists(filePath))
{
await Task.Run(() => System.IO.File.Delete(filePath));
}
}
[HttpPost] [HttpPost]
public async Task<IActionResult> PostPurchRequest(ItemVM viewModel,List<ItemCartVM> ItemCartIds) public async Task<IActionResult> PostPurchRequest([FromForm] string ItemCartIds,
[FromForm] DateTime DateNeeded,
[FromForm] byte RequestTypeId,
[FromForm] int ChargeTo,
[FromForm] string? Remarks,
[FromForm] string? ProjectCode,
IFormFile? file)
{ {
try try
{ {
viewModel.ItemCartVM = new ItemCartVM // Deserialize the ItemCartIds JSON string
{ var itemCartList = JsonSerializer.Deserialize<List<ItemCartDto>>(ItemCartIds);
ItemCartId = ItemCartIds.SelectMany(ic => ic.ItemCartId).ToList(),
Qty = ItemCartIds.SelectMany(ic => ic.Qty).ToList(),
ItemNo = ItemCartIds.SelectMany(ic => ic.ItemNo).ToList()
};
var postPutItem = await _item.PostPurchRequest(GetUser(), viewModel);
if (postPutItem.statusResponse != "Error") if (itemCartList == null || !itemCartList.Any())
{ {
return Json(new { success = true }); return Json(new { success = false, response = "No items selected" });
} }
return Json(new { success = false, Response = postPutItem.message }); var viewModel = new ItemVM
{
DateNeeded = DateNeeded,
RequestTypeId = RequestTypeId,
ChargeTo = ChargeTo,
Remarks = Remarks,
ProjectCode = ProjectCode,
ItemCartVM = new ItemCartVM
{
ItemCartId = itemCartList.Select(ic => ic.ItemCartId).ToList(),
Qty = itemCartList.Select(ic => ic.Qty).ToList(),
ItemNo = itemCartList.Select(ic => ic.ItemNo).ToList()
}
};
// Save attachment if provided
string? savedFileName = await SaveAttachmentAsync(file, null);
viewModel.FileName = savedFileName;
viewModel.OrigFileName = file.FileName;
var postPutItem = await _item.PostPurchRequest(GetUser(), viewModel);
if (postPutItem.messCode != 0)
{
return Json(new { success = true, message = "Purchase request created successfully" });
}
// Delete uploaded file if request failed
if (!string.IsNullOrWhiteSpace(savedFileName))
{
await DeleteAttachmentAsync(savedFileName);
}
return Json(new { success = false, response = postPutItem.message });
} }
catch (Exception ex) catch (Exception ex)
{ {
var message = ex.InnerException?.ToString() ?? ex.Message.ToString(); var message = ex.InnerException?.Message ?? ex.Message;
return Json(new { success = false, response = "An error occurred while processing your request" });
throw;
} }
} }
#endregion #endregion
@ -349,17 +439,14 @@ namespace CPRNIMS.WebApps.Controllers.Items
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
var viewModels = new ItemVM(); var viewModels = new ItemVM();
await IsAuthenTicated();
await UpdateCart(viewModels); await UpdateCart(viewModels);
return View(); return await IsAuthenTicated();
} }
public async Task<IActionResult> ItemCart(byte TypeOfRequest) public async Task<IActionResult> ItemCart(byte TypeOfRequest)
{ {
var viewModels = new ItemVM();
await IsAuthenTicated();
ViewBag.TypeOfRequest = TypeOfRequest; ViewBag.TypeOfRequest = TypeOfRequest;
return View(); return await IsAuthenTicated();
} }
#endregion #endregion
#region Common #region Common

View File

@ -1,4 +1,5 @@
using CPRNIMS.Domain.UIContracts.PO; using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.PO;
using CPRNIMS.Infrastructure.Entities.PO; using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.PO; using CPRNIMS.Infrastructure.ViewModel.PO;
@ -16,8 +17,8 @@ namespace CPRNIMS.WebApps.Controllers.PO
private readonly IPurchaseOrder _purchaseOrder; private readonly IPurchaseOrder _purchaseOrder;
public POMgmtController( public POMgmtController(
ErrorLogHelper errorMessageService, IWebHostEnvironment webHostEnvironment ErrorLogHelper errorMessageService, IWebHostEnvironment webHostEnvironment
, IPurchaseOrder purchaseOrder, TokenHelper tokenHelper , IPurchaseOrder purchaseOrder, TokenHelper tokenHelper,IAccount account
) : base(errorMessageService, webHostEnvironment, tokenHelper) ) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{ {
_purchaseOrder = purchaseOrder; _purchaseOrder = purchaseOrder;
} }

View File

@ -1,4 +1,6 @@
using CPRNIMS.Domain.UIContracts.PR; using CPRNIMS.Domain.Services;
using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.PR;
using CPRNIMS.Infrastructure.Dto.PR; using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
@ -13,12 +15,43 @@ namespace CPRNIMS.WebApps.Controllers.PR
private readonly IPRequest _pRequest; private readonly IPRequest _pRequest;
public PRMgmtController(TokenHelper tokenHelper, ErrorLogHelper errorMessageService, public PRMgmtController(TokenHelper tokenHelper, ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment IWebHostEnvironment webHostEnvironment
, IPRequest pRequest, IConfiguration configuration) , IPRequest pRequest, IConfiguration configuration,IAccount account)
: base(errorMessageService, webHostEnvironment, tokenHelper) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{ {
_pRequest = pRequest; _pRequest = pRequest;
} }
#region Get #region Get
private async Task<IActionResult> GetProductFile(string fileName)
{
try
{
// Validate filename
if (string.IsNullOrWhiteSpace(fileName) || fileName.Contains(".."))
{
return BadRequest("Invalid file name");
}
var uploadsPath = Path.Combine(_webHostEnvironment.WebRootPath, "Content/Uploads", "PRAttachment");
var filePath = Path.Combine(uploadsPath, fileName);
ContentTypeHelper.ValidateFile(filePath, uploadsPath);
// Stream the file instead of loading entirely into memory
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read);
var contentType = ContentTypeHelper.GetContentType(fileName);
return File(fileStream, contentType, fileName, enableRangeProcessing: true);
}
catch (Exception ex)
{
return StatusCode(500, "Error retrieving file");
}
}
public async Task<IActionResult> GetProjectCodes(PRVM viewModels)
{
response = await _pRequest.GetProjectCodes(GetUser(), viewModels);
return GetResponse(response);
}
public async Task<IActionResult> GetApproverName(PRVM viewModels) public async Task<IActionResult> GetApproverName(PRVM viewModels)
{ {
response = await _pRequest.GetApproverName(GetUser(), viewModels); response = await _pRequest.GetApproverName(GetUser(), viewModels);
@ -117,6 +150,16 @@ namespace CPRNIMS.WebApps.Controllers.PR
} }
#endregion #endregion
#region POST PUT #region POST PUT
public async Task<IActionResult> PostPutProjectCode([FromBody] PRVM viewModel)
{
var postPutItem = await _pRequest.PostPutProjectCode(GetUser(), viewModel);
if (postPutItem.messCode != 0)
{
return Json(new { success = true, Response = postPutItem.Message });
}
return Json(new { success = false, Response = postPutItem.Message });
}
public async Task<IActionResult> ApprovedSelectedPRItem(PRVM viewModel, public async Task<IActionResult> ApprovedSelectedPRItem(PRVM viewModel,
List<PRList> PRList) List<PRList> PRList)
{ {
@ -223,6 +266,10 @@ namespace CPRNIMS.WebApps.Controllers.PR
{ {
return await IsAuthenTicated(); return await IsAuthenTicated();
} }
public async Task<IActionResult> ProjectCode()
{
return await IsAuthenTicated();
}
#endregion #endregion
} }
} }

View File

@ -1,4 +1,5 @@
using CPRNIMS.Domain.UIContracts.Receiving; using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.Receiving;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.PR; using CPRNIMS.Infrastructure.ViewModel.PR;
using CPRNIMS.Infrastructure.ViewModel.Receiving; using CPRNIMS.Infrastructure.ViewModel.Receiving;
@ -14,8 +15,8 @@ namespace CPRNIMS.WebApps.Controllers.Receiving
private readonly IConfiguration _configuration; private readonly IConfiguration _configuration;
public ReceivingController(ErrorLogHelper errorMessageService, public ReceivingController(ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment,TokenHelper tokenHelper IWebHostEnvironment webHostEnvironment,TokenHelper tokenHelper
, IReceiving receiving, IConfiguration configuration) , IReceiving receiving, IConfiguration configuration,IAccount account)
: base(errorMessageService, webHostEnvironment,tokenHelper) : base(errorMessageService, webHostEnvironment,tokenHelper, account)
{ {
_receiving = receiving; _receiving = receiving;
_configuration = configuration; _configuration = configuration;

View File

@ -1,4 +1,5 @@
using Azure; using Azure;
using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.SMTP; using CPRNIMS.Domain.UIContracts.SMTP;
using CPRNIMS.Infrastructure.Entities.Items; using CPRNIMS.Infrastructure.Entities.Items;
using CPRNIMS.Infrastructure.Helper; using CPRNIMS.Infrastructure.Helper;
@ -17,16 +18,15 @@ namespace CPRNIMS.WebApps.Controllers.SMTP
private readonly ISMTP _sMTP; private readonly ISMTP _sMTP;
public SMTPMgmtController(ErrorLogHelper errorMessageService, public SMTPMgmtController(ErrorLogHelper errorMessageService,
IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper IWebHostEnvironment webHostEnvironment, TokenHelper tokenHelper
, ISMTP sMTP , ISMTP sMTP,IAccount account
) )
: base(errorMessageService, webHostEnvironment,tokenHelper) : base(errorMessageService, webHostEnvironment,tokenHelper, account)
{ {
_sMTP = sMTP; _sMTP = sMTP;
} }
public async Task<IActionResult> Index() public async Task<IActionResult> Index()
{ {
await IsAuthenTicated(); return await IsAuthenTicated();
return View();
} }
#region Get #region Get
public async Task<IActionResult> GetAllSmtp() public async Task<IActionResult> GetAllSmtp()

View File

@ -2,7 +2,7 @@
<div class="container-fluid"> <div class="container-fluid">
<div class="table-container shadow-lg p-3 mb-5 bg-white rounded"> <div class="table-container shadow-lg p-3 mb-5 bg-white rounded">
<div class="header-container"> <div class="header-container">
<h2 style="display: flex; flex-direction: column; align-items: center;">Requestor Page</h2> <h2 style="display: flex; flex-direction: column; align-items: center;">Item Management</h2>
</div> </div>
<br /> <br />
<button id="btnAddNewLayout" type="button" class="btn btn-success" <button id="btnAddNewLayout" type="button" class="btn btn-success"
@ -237,7 +237,7 @@
</div> </div>
</div> </div>
</div> </div>
<script src="~/JsFunctions/Items/ItemManagementV6.js"></script> <script src="~/JsFunctions/Items/ItemManagementV7.js"></script>
@await Html.PartialAsync("PagesView/Item/_Scripts") @await Html.PartialAsync("PagesView/Item/_Scripts")
</div> </div>

View File

@ -15,9 +15,10 @@
<table id="ItemCartTable" class="row-border" cellspacing="0" width="100%"> <table id="ItemCartTable" class="row-border" cellspacing="0" width="100%">
<thead> <thead>
<tr> <tr>
<th> <th style="text-align:left;width:4%;">
All All
<input id="selectAllHeaderCheckbox" type="checkbox" class="selectAllCheckbox" style="margin-left:10px;" /> <input id="selectAllCheckboxItem" type="checkbox"
class="selectAllCheckboxItem" />
</th> </th>
<th>ItemNo</th> <th>ItemNo</th>
<th>ItemName</th> <th>ItemName</th>
@ -25,64 +26,122 @@
<th>PRTypeId</th> <th>PRTypeId</th>
<th>Qty</th> <th>Qty</th>
<th>Action</th> <th>Action</th>
<th hidden></th>
<th hidden></th>
<th hidden></th>
<th hidden></th>
<th hidden></th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
</tbody> </tbody>
</table> </table>
<div style="margin-top:20px;" class="d-flex justify-content-end"> <div style="margin-top:20px;" class="d-flex justify-content-end">
<a class="btn btn-primary" asp-area="" asp-controller="ItemMgmt" asp-action="Index" style="margin-bottom:20px; margin-right:10px;"> <a class="btn btn-outline-secondary px-4" asp-area="" asp-controller="ItemMgmt" asp-action="Index" style="margin-bottom:20px; margin-right:10px;">
Back <i class="bi bi-x-circle me-2"></i>Back
</a> </a>
<button id="btnSubmitItem" type="button" class="btn btn-success" onclick="showModal();" style="margin-bottom:20px; margin-right:10px;"> <button id="btnSubmitItem" type="button" class="btn btn-success" onclick="showModal();" style="margin-bottom:20px; margin-right:10px;">
Submit <i class="bi bi-check-circle me-2"></i> Submit
</button> </button>
</div> </div>
</div> </div>
<!-- Modal addDateNeeded --> <!-- Modal -->
<div class="modal fade custom-modal-backdrop" id="addDateNeeded" <div class="modal fade custom-modal-backdrop" id="addDateNeeded"
tabindex="-1" aria-labelledby="addDateNeededLabel" aria-hidden="true" data-bs-backdrop="static"> tabindex="-1" aria-labelledby="addDateNeededLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog"> <div class="modal-dialog modal-dialog-centered">
<div class="modal-content"> <div class="modal-content border-0 shadow-lg">
<div class="modal-header"> <div class="modal-header">
<h5 id="addDateNeededLabel" class="modal-title fw-semibold">
<h5 id="addDateNeededLabel" class="modal-title"> <i class="bi bi-clipboard-check me-2"></i>Purchase Request Details
Fill all fields below, before to proceed
</h5> </h5>
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
</div> </div>
<div class="modal-body"> <div class="modal-body p-4">
<div class="form-group">
<label id="labelDateNeeded" for="dateNeeded" style="margin-bottom: 5px;">Date Needed</label> <!-- Date Needed -->
<input type="date" class="form-control" <div class="mb-3">
style="width: 100%;margin-bottom:10px;" id="dateNeeded" name="dateNeeded" /> <label id="labelDateNeeded" for="dateNeeded" class="form-label fw-light">
Date Needed <span class="text-danger">*</span>
</label>
<input type="date" class="form-control form-control"
id="dateNeeded" name="dateNeeded" required />
</div> </div>
<div class="form-group">
<label for="requestorRemarks">Remarks</label> <!-- Project Code Autocomplete -->
<div class="mb-3">
<label for="projectCode" class="form-label fw-semibold">
Project Code <small class="text-muted">(Optional)</small>
</label>
<input type="text" class="form-control form-control"
id="projectCode" name="projectCode"
placeholder="Start typing here..."
autocomplete="off"
list="projectCodeList" />
<datalist id="projectCodeList">
<!-- Options will be populated dynamically via JavaScript -->
</datalist>
<div class="form-text">
<i class="bi bi-info-circle me-1"></i>Search and select the appropriate project code
</div>
</div>
<!-- File Attachment -->
<div class="mb-3">
<label for="fileAttachment" class="form-label fw-semibold">
Attachment <small class="text-muted">(Optional)</small>
</label>
<input type="file" class="form-control"
id="fileAttachment" name="fileAttachment"
accept=".csv,.xlsx,.xls,.pdf" />
<div class="form-text">
<i class="bi bi-paperclip me-1"></i>Accepted formats: CSV, Excel (.xlsx, .xls), PDF (Max 5MB)
</div>
<!-- File preview area -->
<div id="filePreview" class="mt-2 d-none">
<div class="alert alert-success alert-dismissible fade show py-2" role="alert">
<i class="bi bi-file-earmark-check me-2"></i>
<span id="fileName"></span>
<small class="text-muted ms-2">(<span id="fileSize"></span>)</small>
<button type="button" class="btn-close py-2" onclick="clearFileAttachment()"></button>
</div>
</div>
</div>
<!-- Remarks -->
<div class="mb-3">
<label for="requestorRemarks" class="form-label fw-semibold">
Remarks <small class="text-muted">(Optional)</small>
</label>
<textarea id="requestorRemarks" class="form-control" <textarea id="requestorRemarks" class="form-control"
style="width: 100%; height: 100px;margin-bottom:10px;"></textarea> rows="4"
placeholder="Add any additional notes or comments here..."></textarea>
<div class="form-text">
<span id="charCount">0</span>/500 characters
</div> </div>
<div class="form-group"> </div>
<label id="labelChargeTo" for="chargeTo">Charge To</label>
<select id="chargeTo" class="form-control" style="margin-bottom:10px;" name="chargeTo"> <!-- Charge To -->
<div class="mb-3">
<label id="labelChargeTo" for="chargeTo" class="form-label fw-semibold">
Charge To <span class="text-danger">*</span>
</label>
<select id="chargeTo" class="form-select form-select-lg" name="chargeTo" required>
<option value="" selected disabled>-- Select Department --</option>
<!-- Options populated dynamically -->
</select> </select>
<input type="hidden" id="departmentId" name="departmentId" /> <input type="hidden" id="departmentId" name="departmentId" />
</div> </div>
</div> </div>
<div class="modal-footer bg-light border-0 p-3">
<div class="modal-footer"> <button type="button" class="btn btn-outline-secondary px-4" data-bs-dismiss="modal">
<button type="button" class="btn btn-warning" data-bs-dismiss="modal">Cancel</button> <i class="bi bi-x-circle me-2"></i>Cancel
<button type="button" id="btnConfirmUpdate" onclick="postPutPurchase()" class="btn btn-success">Submit</button> </button>
<button type="button" id="btnConfirmUpdate" onclick="postPutPurchase()" class="btn btn-success px-4">
<i class="bi bi-check-circle me-2"></i>Submit Request
</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<link href="~/css/item/cartv2.css" rel="stylesheet" />
@await Html.PartialAsync("PagesView/Item/_Scripts") @await Html.PartialAsync("PagesView/Item/_Scripts")
<script src="~/JsFunctions/Items/ItemCartV2.js"></script> <script src="~/JsFunctions/Items/ItemCartV3.js"></script>
</body> </body>

View File

@ -0,0 +1,105 @@
<body>
<div class="container-fluid">
<div class="table-container shadow-lg p-3 mb-5 bg-white rounded">
<div class="header-container">
<h2>Project Code Management</h2>
</div>
<br />
<button id="btnAddNew" type="button" class="btn btn-success" data-mode="add"
onclick="showProjectCode({},true)" style="margin-bottom:20px;margin-left:10px;">
Add new
</button>
<br />
<table id="ProjectCodeTable" class="row-border" cellspacing="0" width="100%">
<thead>
<tr>
<th style="width:15%">ProjectCode</th>
<th style="width:25%">ProjectName</th>
<th style="width:32%">DeliveryAddress</th>
<th style="width:10%">MaxDays</th>
<th style="width:11%">Status</th>
<th style="width:7%">Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
</div>
<!-- Modal addNewItem -->
<div class="modal fade custom-modal-backdrop" id="showProjectCode" tabindex="-1"
aria-labelledby="ModalLabel" aria-hidden="true" data-bs-backdrop="static">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" style="text-align: center; margin-left: auto; margin-right: auto;"
id="headerNew">
Add new item
</h5>
<h5 class="modal-title" style="text-align: center; margin-left: auto; margin-right: auto;"
id="headerUpdate">
Update item
</h5>
</div>
<br />
<div class="modal-body">
<form id="itemPostPutForm">
<div class="form-floating mb-3">
<input id="projectCodeId" hidden />
<input id="projectCode" class="form-control"
placeholder=" Describe proejct code...">
<label for="projectCode">Project Code</label>
</div>
<div class="form-floating mb-3">
<textarea id="projectName" class="form-control"
placeholder=" Describe projectName..."></textarea>
<label for="projectName">Project Name</label>
</div>
<div class="form-floating mb-3">
<textarea id="deliveryAddress" class="form-control"
placeholder=" Describe deliveryAddress..."></textarea>
<label for="deliveryAddress">Delivery Address</label>
</div>
<div class="row g-3 mb-3">
<div class="col-md-6">
<div class="form-floating">
<input id="maxDays"
type="number"
min="1"
class="form-control"
placeholder="Max days">
<label for="maxDays">Max Days</label>
</div>
</div>
<div class="col-md-6 d-flex align-items-center">
<div class="form-check form-switch">
<input class="form-check-input"
type="checkbox"
id="statusSwitch"
checked>
<label class="form-check-label" for="statusSwitch">
Active
</label>
</div>
</div>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-cancel" data-bs-dismiss="modal">Cancel</button>
<button type="button" id="btnAddUpdate" onclick="postPutProjectCode(1);" class="btn btn-success"></button>
</div>
</div>
</div>
</div>
<script src="~/JsFunctions/PR/ProjectCode.js"></script>
@await Html.PartialAsync("PagesView/PR/_PRScripts")
</body>

View File

@ -5,8 +5,11 @@
<link href="~/lib/bootstrap/dist/fonts/boostrap-icons.css" rel="stylesheet" /> <link href="~/lib/bootstrap/dist/fonts/boostrap-icons.css" rel="stylesheet" />
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" /> <link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
<script src="~/jsfunctions/items/itemvar.js"></script> <script src="~/jsfunctions/items/itemvar.js"></script>
<script src="~/jsfunctions/items/ItemViewV5.js"></script> <script src="~/jsfunctions/items/ItemViewV6.js"></script>
<script src="~/jsfunctions/items/PostPutItemV2.js"></script> <script src="~/jsfunctions/items/PostPutItemV3.js"></script>
<script src="~/microsoft-signalr/signalr.min.js"></script> <script src="~/microsoft-signalr/signalr.min.js"></script>
<script src="~/jsfunctions/updater/CartUpdater.js"></script> <script src="~/jsfunctions/updater/CartUpdater.js"></script>
<script src="~/jsfunctions/utilities/NewStyle.js"></script>
<script src="~/jsfunctions/utilities/utilsV3.js"></script> <script src="~/jsfunctions/utilities/utilsV3.js"></script>
<script src="~/jsfunctions/utilities/StylesV3.js"></script>

View File

@ -2,12 +2,12 @@
<div id="loader" class="loader"></div> <div id="loader" class="loader"></div>
</div> </div>
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" /> <link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
<script src="~/jsfunctions/pr/PRColumnV6.js"></script> <script src="~/jsfunctions/pr/PRColumnV7.js"></script>
<script src="~/jsfunctions/pr/PRViewV4.js"></script> <script src="~/jsfunctions/pr/PRViewV5.js"></script>
<script src="~/jsfunctions/pr/PRPutPostV9.js"></script> <script src="~/jsfunctions/pr/PRPutPost.js"></script>
<script src="~/jsfunctions/pr/PRButtonv2.js"></script> <script src="~/jsfunctions/pr/PRButtonv3.js"></script>
<script src="~/jsfunctions/pr/PRVarV3.js"></script> <script src="~/jsfunctions/pr/PRVarV3.js"></script>
<script src="~/jsfunctions/pr/Configv4.js"></script> <script src="~/jsfunctions/pr/Configv5.js"></script>
<script src="~/jsfunctions/pr/populatedropdown.js"></script> <script src="~/jsfunctions/pr/populatedropdown.js"></script>
<script src="~/jsfunctions/pr/prRowCallbackV3.js"></script> <script src="~/jsfunctions/pr/prRowCallbackV3.js"></script>
<script src="~/jsfunctions/utilities/columnstyle.js"></script> <script src="~/jsfunctions/utilities/columnstyle.js"></script>

View File

@ -341,20 +341,24 @@
<div class="p-2 mb-3 rounded border shadow-sm bg-light pr-info-section"> <div class="p-2 mb-3 rounded border shadow-sm bg-light pr-info-section">
<div class="row mb-2"> <div class="row mb-2">
<!-- PR No --> <!-- PR No -->
<div class="col-md-4"> <div class="col-md-5">
<small class="text-muted">P.R. No</small> <small class="text-muted">P.R. No</small>
<div id="label-pr-prNo" class="fw-bold text-dark"></div> <div id="label-pr-prNo" class="fw-bold text-dark"></div>
</div> </div>
<!-- PR By --> <!-- PR By -->
<div class="col-md-4"> <div class="col-md-5">
<small class="text-muted">P.R. By</small> <small class="text-muted">P.R. By</small>
<div id="label-prby" class="fw-bold text-dark"></div> <div id="label-prby" class="fw-bold text-dark"></div>
</div> </div>
<!-- Department --> <!-- Department -->
<div class="col-md-4"> <div class="col-md-5">
<small class="text-muted">Department</small> <small class="text-muted">Department</small>
<div id="label-pr-Department" class="fw-bold text-dark"></div> <div id="label-pr-Department" class="fw-bold text-dark"></div>
</div> </div>
<div class="col-md-5">
<small class="text-muted">Project Code</small>
<div id="label-pr-ProjectCode" class="fw-bold text-dark"></div>
</div>
</div> </div>
<div class="row mb-2"> <div class="row mb-2">

View File

@ -1,32 +1,7 @@
@using CPRNIMS.Infrastructure.ViewModel; @using CPRNIMS.Infrastructure.ViewModel;
@using CPRNIMS.Infrastructure.ViewModel.Account; @using CPRNIMS.Infrastructure.ViewModel.Account;
@using CPRNIMS.Infrastructure.ViewModel.Common; @using CPRNIMS.Infrastructure.ViewModel.Common;
@inject CPRNIMS.Domain.UIContracts.Account.IAccount _account;
@model CPRNIMS.Infrastructure.Dto.Attachement.AttachResponseDto
@{
if (!String.IsNullOrEmpty(ViewBag.UserRoles))
{
try
{
string allowedRoles = ViewBag.UserRoles;
var userCred = new CPRNIMS.Infrastructure.Models.Account.User();
userCred.UserName = ViewBag.UserName;
userCred.UserId = ViewBag.UserId;
var myControllerAccess = await _account.GetLandingPageByUserId(userCred);
var groupedElements = myControllerAccess.GroupBy(e => e.ElementMenuName).ToList();
ViewBag.TempDataElements = groupedElements;
}
catch (Exception)
{
// Console.WriteLine(ex.Message.ToString() ?? ex.InnerException?.ToString());
throw;
}
}
}
<div class="sidebar"> <div class="sidebar">
<div class="logo-details"> <div class="logo-details">
<i class="bx bxl-c-plus-plus icon"></i> <i class="bx bxl-c-plus-plus icon"></i>
@ -68,6 +43,3 @@
@await Html.PartialAsync("PartialView/MenuNav/UserProfile/_UpdateUserProfile") @await Html.PartialAsync("PartialView/MenuNav/UserProfile/_UpdateUserProfile")
</ul> </ul>
</div> </div>

View File

@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<link href="~/css/item/cart.css" rel="stylesheet" /> <link href="~/css/item/cartV2.css" rel="stylesheet" />
} }
</header> </header>

View File

@ -54,18 +54,27 @@ function showHideLabelButtons() {
$(document).ready(function () { $(document).ready(function () {
loader = $('#overlay, #loader'); loader = $('#overlay, #loader');
var submitButton = $('#btnSubmitItem'); var submitButton = $('#btnSubmitItem');
var totalSelectedLabel = $('#totalSelected');
tableName = '#ItemCartTable';
totalSelectedLabel = $('#totalSelected');
clearTableSelection(tableName, selectedProductsMap, () => {
totalSelectedLabel.text(0);
}, 'selected-row', '.select-all-item-checkbox');
tableElement = $(tableName);
tableDestroy(tableElement);
UserRights = document.getElementById("roleRights").value; UserRights = document.getElementById("roleRights").value;
RequestTypeId = document.getElementById("requestTypeId").value; RequestTypeId = document.getElementById("requestTypeId").value;
showHideLabelButtons(); showHideLabelButtons();
itemTable = $('#ItemCartTable').DataTable({ itemTable = $(tableName).DataTable({
ajax: { ajax: {
url: '/ItemMgmt/GetItemCart', url: '/ItemMgmt/GetItemCart',
type: 'GET', type: 'GET',
data: { RequestTypeId }, data: { RequestTypeId },
beforeSend: function () { beforeSend: function () {
// Show the loader before making the AJAX request
loader.show(); loader.show();
}, },
complete: function () { complete: function () {
@ -73,6 +82,19 @@ $(document).ready(function () {
} }
}, },
initComplete: function () { initComplete: function () {
initializeTableSelection({
tableName: tableName,
dataTable: itemTable,
selectedItemsMap: selectedProductsMap,
idKey: 'itemCartId',
idKey2: 'itemNo',
checkboxClass: '.select-item-checkbox',
selectAllClass: '.select-all-item-checkbox',
selectedRowClass: 'selected-row',
updateCountCallback: function () {
totalSelectedLabel.text(getSelectedCount(selectedProductsMap));
}
});
var api = this.api(); var api = this.api();
var data = api.ajax.json(); var data = api.ajax.json();
@ -85,9 +107,12 @@ $(document).ready(function () {
columns: [ columns: [
{ {
data: 'itemCartId', data: 'itemCartId',
title: '<input type="checkbox" class="select-all-item-checkbox" />',
render: function () { render: function () {
return '<input type="checkbox" class="selectedItem-checkbox" />'; return '<input type="checkbox" class="select-item-checkbox"/>';
} },
orderable: false,
searchable: false
}, },
{ data: 'itemNo' }, { data: 'itemNo' },
{ data: 'itemName' }, { data: 'itemName' },
@ -99,12 +124,7 @@ $(document).ready(function () {
render: function (data, type, row) { render: function (data, type, row) {
return renderItembtns(data, row); return renderItembtns(data, row);
} }
}, }
{ data: 'isActive', visible: false },
{ data: 'itemCartId', visible: false },
{ data: 'cartItemCount', visible: false },
{ data: 'createdDate', visible: false },
{ data: 'requestTypeId', visible: false },
], ],
"columnDefs": [ "columnDefs": [
@ -139,7 +159,7 @@ $(document).ready(function () {
} }
}, },
//responsive: true, //responsive: true,
order: [[10, 'desc']], order: [[0, 'desc']],
language: { language: {
emptyTable: "No record available" emptyTable: "No record available"
}, },
@ -157,37 +177,6 @@ $(document).ready(function () {
// Toggle the visibility of the submit button based on whether the table is empty or not // Toggle the visibility of the submit button based on whether the table is empty or not
submitButton.toggle(!isEmpty); submitButton.toggle(!isEmpty);
} }
// Event handler for individual checkbox change
$('#ItemCartTable').on('change', '.selectedItem-checkbox', function () {
var row = $(this).closest('tr'); // Get the closest row for the checkbox
if ($(this).prop('checked')) {
row.addClass('selected-row'); // Add highlight class if checked
} else {
row.removeClass('selected-row'); // Remove highlight class if unchecked
}
updateTotalSelectedCount(); // Update the total selected count
});
// Event handler for "Select All" checkbox change in the header
$('#selectAllHeaderCheckbox').on('change', function () {
var isChecked = $(this).prop('checked'); // Check if "Select All" checkbox is checked
// Check or uncheck all checkboxes in the table based on the state of "Select All" checkbox
$('.selectedItem-checkbox').prop('checked', isChecked);
// Highlight or unhighlight all rows based on "Select All" checkbox state
if (isChecked) {
$('#ItemCartTable tbody tr').addClass('selected-row');
} else {
$('#ItemCartTable tbody tr').removeClass('selected-row');
}
updateTotalSelectedCount(); // Update the total selected count
});
function updateTotalSelectedCount() {
var totalSelected = $('.selectedItem-checkbox:checked').length; // Count the checked checkboxes
totalSelectedLabel.text(totalSelected); // Update the label with the count
}
}) })
function deleteCartItemById(data) { function deleteCartItemById(data) {
loader = $('#overlay, #loader'); loader = $('#overlay, #loader');
@ -228,3 +217,72 @@ function deleteCartItemById(data) {
} }
}); });
} }
document.getElementById('fileAttachment').addEventListener('change', function (e) {
const file = e.target.files[0];
const filePreview = document.getElementById('filePreview');
const fileName = document.getElementById('fileName');
const fileSize = document.getElementById('fileSize');
if (file) {
// Validate file size (5MB max)
const maxSize = 5 * 1024 * 1024; // 5MB in bytes
if (file.size > maxSize) {
showToast('warning', 'File size exceeds 5MB. Please choose a smaller file.', 'File Upload', 4000);
e.target.value = '';
return;
}
// Validate file type
const allowedExtensions = ['csv', 'xlsx', 'xls', 'pdf'];
const fileExtension = file.name.split('.').pop().toLowerCase();
if (!allowedExtensions.includes(fileExtension)) {
showToast('warning', 'Invalid file type. Please upload CSV, Excel, or PDF files only.', 'File Upload', 4000);
e.target.value = '';
return;
}
// Show file preview
fileName.textContent = file.name;
fileSize.textContent = formatFileSize(file.size);
filePreview.classList.remove('d-none');
}
});
function clearFormData() {
document.getElementById('dateNeeded').value = '';
document.getElementById('projectCode').value = '';
document.getElementById('requestorRemarks').value = '';
document.getElementById('fileAttachment').value = '';
document.getElementById('chargeTo').value = '';
clearFileAttachment();
document.getElementById('charCount').textContent = '0';
}
function clearFileAttachment() {
document.getElementById('fileAttachment').value = '';
document.getElementById('filePreview').classList.add('d-none');
}
document.getElementById('requestorRemarks').addEventListener('input', function (e) {
const charCount = document.getElementById('charCount');
const currentLength = e.target.value.length;
const maxLength = 500;
charCount.textContent = currentLength;
if (currentLength > maxLength) {
e.target.value = e.target.value.substring(0, maxLength);
charCount.textContent = maxLength;
}
// Change color when approaching limit
if (currentLength > maxLength * 0.9) {
charCount.classList.add('text-danger');
} else {
charCount.classList.remove('text-danger');
}
});
function formatFileSize(bytes) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const sizes = ['Bytes', 'KB', 'MB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
}

View File

@ -40,11 +40,10 @@ function isFullFilled() {
} }
$(document).ready(function () { $(document).ready(function () {
var loader = $('#overlay, #loader'); loader = $('#overlay, #loader');
let fetchedData = []; let fetchedData = [];
let hasFetched = false; // ensures only one fetch per page load let hasFetched = false; // ensures only one fetch per page load
let fetchInProgress = false; // prevents multiple calls before first finishes let fetchInProgress = false; // prevents multiple calls before first finishes
let itemTable;
let cartItemCount = $('#cartItemCount').val(); let cartItemCount = $('#cartItemCount').val();
$('#cartCount').text(cartItemCount); $('#cartCount').text(cartItemCount);

View File

@ -1,4 +1,35 @@
function populateItemCategSelect() { async function setupProjectCodeAutocomplete() {
const input = document.getElementById('projectCode');
let debounceTimer;
input.addEventListener('input', function (e) {
clearTimeout(debounceTimer);
const searchTerm = e.target.value;
if (searchTerm.length < 2) return;
debounceTimer = setTimeout(async () => {
try {
// Replace with your actual API endpoint
const response = await fetch(`/api/projects/search?term=${encodeURIComponent(searchTerm)}`);
const projects = await response.json();
const datalist = document.getElementById('projectCodeList');
datalist.innerHTML = '';
projects.forEach(project => {
const option = document.createElement('option');
option.value = project.code;
option.textContent = `${project.code} - ${project.name}`;
datalist.appendChild(option);
});
} catch (error) {
console.error('Error fetching project codes:', error);
}
}, 300);
});
}
function populateItemCategSelect() {
$.ajax({ $.ajax({
url: "/ItemMgmt/GetItemCateg", url: "/ItemMgmt/GetItemCateg",
success: function (response) { success: function (response) {

View File

@ -1,4 +1,106 @@
function putItemDetails() { function postPutPurchase() {
loader = $('#overlay, #loader').css('z-index', 1060);
isValid = true;
var Remarks = document.getElementById('requestorRemarks').value;
var ProjectCode = document.getElementById('projectCode').value;
const selectedItems = Object.values(selectedProductsMap);
if (selectedItems.length === 0) {
showToast('warning', 'Please select items first!', 'Approval failed', 4000);
return;
}
const requestData = selectedItems.map(item => {
return {
ItemCartId: item.itemCartId,
ItemNo: item.itemNo,
Qty: item.qty
};
});
console.log(requestData);
var DateNeeded = document.getElementById('dateNeeded').value;
if (!DateNeeded) {
showToast('warning', 'Please choose date needed!', 'P.R. submission failed', 4000);
confirmUpdateListener = false;
return;
}
if (RequestTypeId == 3) {
updateDepartmentId();
var ChargeTo = document.getElementById('departmentId').value;
if (!ChargeTo) {
showToast('warning', 'Please choose a department to be in charge of!', 'P.R. submission failed', 4000);
confirmUpdateListener = false;
return;
}
}
showConfirmation({
title: 'Purchasing Requisition',
message: 'Are you sure you want to proceed? This action cannot be undone.',
type: 'warning',
confirmText: 'Yes',
cancelText: 'No'
}).then((confirmed) => {
if (confirmed) {
// Create FormData to handle file upload
var formData = new FormData();
// Append file if exists
var fileInput = document.getElementById('fileAttachment');
if (fileInput.files.length > 0) {
formData.append('file', fileInput.files[0]);
}
// Append other data
formData.append('DateNeeded', DateNeeded);
formData.append('RequestTypeId', RequestTypeId);
formData.append('ChargeTo', ChargeTo || '');
formData.append('Remarks', Remarks || '');
formData.append('ProjectCode', ProjectCode || '');
// Append array data - serialize as JSON
formData.append('ItemCartIds', JSON.stringify(requestData));
$.ajax({
url: '/ItemMgmt/PostPurchRequest',
type: 'POST',
data: formData,
processData: false, // Important: Don't process the data
contentType: false, // Important: Don't set content type
success: function (response) {
if (response.success) {
itemTable.ajax.reload();
$('#addDateNeeded').modal('hide');
showToast('success', 'P.R. Successfully Created!', 'Success', 4000);
var totalSelectedLabel = $('#totalSelected');
totalSelectedLabel.text('');
// Clear form after successful submission
clearFormData();
} else {
itemTable.ajax.reload();
showToast('error', response.response, 'P.R. submission failed', 4000);
}
},
error: errorHandler,
beforeSend: function () {
loader.show();
},
complete: function () {
loader.hide();
}
});
}
});
}
function putItemDetails() {
loader = $('#overlay, #loader'); loader = $('#overlay, #loader');
const itemPictureImageInput = document.getElementById("itemPictureImageInput"); const itemPictureImageInput = document.getElementById("itemPictureImageInput");
@ -132,91 +234,91 @@ function sendUpdateRequest(data, loader) {
} }
}); });
} }
function postPutPurchase() { //function postPutPurchase() {
loader = $('#overlay, #loader').css('z-index', 1060); // loader = $('#overlay, #loader').css('z-index', 1060);
isValid = true; // isValid = true;
var Remarks = document.getElementById('requestorRemarks').value; // var Remarks = document.getElementById('requestorRemarks').value;
var selectedCheckboxes = $('.selectedItem-checkbox:checked'); // var selectedCheckboxes = $('.selectedItem-checkbox:checked');
var requestData = []; // var requestData = [];
selectedCheckboxes.each(function () { // selectedCheckboxes.each(function () {
var $row = $(this).closest('tr'); // var $row = $(this).closest('tr');
var rowIndex = itemTable.row($row).index(); // var rowIndex = itemTable.row($row).index();
var rowData = itemTable.row(rowIndex).data(); // var rowData = itemTable.row(rowIndex).data();
var itemCartId = rowData.itemCartId; // var itemCartId = rowData.itemCartId;
var itemNo = rowData.itemNo; // var itemNo = rowData.itemNo;
var qty = $row.find('.editable-qty').val() || rowData.qty; // var qty = $row.find('.editable-qty').val() || rowData.qty;
if (parseFloat(qty) === 0 || isNaN(parseFloat(qty))) { // if (parseFloat(qty) === 0 || isNaN(parseFloat(qty))) {
isValid = false; // isValid = false;
showToast('warning', "Please input a valid qty for ItemNo# " + itemNo + "!", ' warning', 4000); // showToast('warning', "Please input a valid qty for ItemNo# " + itemNo + "!", ' warning', 4000);
$(modalId).modal('hide'); // $(modalId).modal('hide');
return false; // return false;
} // }
var itemData = { // var itemData = {
itemCartId: itemCartId, // itemCartId: itemCartId,
ItemNo: itemNo, // ItemNo: itemNo,
qty: qty // qty: qty
}; // };
requestData.push(itemData); // requestData.push(itemData);
}); // });
if (selectedCheckboxes.length <= 0) { // if (selectedCheckboxes.length <= 0) {
showToast('warning', 'No selected item!', 'Item cart failed', 4000); // showToast('warning', 'No selected item!', 'Item cart failed', 4000);
return; // return;
} else { // } else {
var DateNeeded = document.getElementById('dateNeeded').value; // var DateNeeded = document.getElementById('dateNeeded').value;
if (!DateNeeded) { // if (!DateNeeded) {
showToast('warning', 'Please choose date needed!', 'P.R. submission failed', 4000); // showToast('warning', 'Please choose date needed!', 'P.R. submission failed', 4000);
confirmUpdateListener = false; // confirmUpdateListener = false;
return; // return;
} // }
if (RequestTypeId == 3) { // if (RequestTypeId == 3) {
updateDepartmentId(); // updateDepartmentId();
var ChargeTo = document.getElementById('departmentId').value; // var ChargeTo = document.getElementById('departmentId').value;
if (!ChargeTo) { // if (!ChargeTo) {
showToast('warning', 'Please choose a department to be in charge of!', 'P.R. submission failed', 4000); // showToast('warning', 'Please choose a department to be in charge of!', 'P.R. submission failed', 4000);
confirmUpdateListener = false; // confirmUpdateListener = false;
return; // return;
} // }
} // }
} // }
showConfirmation({ // showConfirmation({
title: 'Purchasing Requisition', // title: 'Purchasing Requisition',
message: 'Are you sure you want to proceed? This action cannot be undone.', // message: 'Are you sure you want to proceed? This action cannot be undone.',
type: 'warning', // type: 'warning',
confirmText: 'Yes', // confirmText: 'Yes',
cancelText: 'No' // cancelText: 'No'
}).then((confirmed) => { // }).then((confirmed) => {
if (confirmed) { // if (confirmed) {
$.ajax({ // $.ajax({
url: '/ItemMgmt/PostPurchRequest', // url: '/ItemMgmt/PostPurchRequest',
type: 'POST', // type: 'POST',
data: { ItemCartIds: requestData, DateNeeded: DateNeeded, RequestTypeId: RequestTypeId, ChargeTo: ChargeTo, Remarks: Remarks }, // data: { ItemCartIds: requestData, DateNeeded: DateNeeded, RequestTypeId: RequestTypeId, ChargeTo: ChargeTo, Remarks: Remarks },
success: function (response) { // success: function (response) {
if (response.success) { // if (response.success) {
itemTable.ajax.reload(); // itemTable.ajax.reload();
$('#addDateNeeded').modal('hide'); // $('#addDateNeeded').modal('hide');
showToast('success', 'P.R. Successfully Created!', 'Success', 4000); // showToast('success', 'P.R. Successfully Created!', 'Success', 4000);
var totalSelectedLabel = $('#totalSelected'); // var totalSelectedLabel = $('#totalSelected');
totalSelectedLabel.text(''); // totalSelectedLabel.text('');
} else { // } else {
itemTable.ajax.reload(); // itemTable.ajax.reload();
showToast('error', response.response, title + ' failed', 4000); // showToast('error', response.response, title + ' failed', 4000);
} // }
}, // },
beforeSend: function () { // beforeSend: function () {
loader.show(); // loader.show();
}, // },
complete: function () { // complete: function () {
loader.hide(); // loader.hide();
} // }
}); // });
} // }
}); // });
} //}
function AddToCart(isUpdated) { function AddToCart(isUpdated) {
var loader = $('#overlay, #loader'); var loader = $('#overlay, #loader');
var ItemNo = $('#itemNo').val(); var ItemNo = $('#itemNo').val();

View File

@ -3,10 +3,13 @@
GetItemColor: '/ItemMgmt/GetItemColor', GetItemColor: '/ItemMgmt/GetItemColor',
GetItemLocalization: '/ItemMgmt/GetItemLocalization', GetItemLocalization: '/ItemMgmt/GetItemLocalization',
GetItemUOM: '/ItemMgmt/GetItemUOM', GetItemUOM: '/ItemMgmt/GetItemUOM',
GetProjectCodes: '/PRMgmt/GetProjectCodes',
GetSupplierAlternativeOffer: '/PRMgmt/GetSupplierAlternativeOffer', GetSupplierAlternativeOffer: '/PRMgmt/GetSupplierAlternativeOffer',
GetSupplierAlterOfferDetails: '/PRMgmt/GetSupplierAlterOfferDetails', GetSupplierAlterOfferDetails: '/PRMgmt/GetSupplierAlterOfferDetails',
PutSupplierAlterOffer: '/PRMgmt/PutSupplierAlterOffer', PutSupplierAlterOffer: '/PRMgmt/PutSupplierAlterOffer',
PostPutProjectCode: '/PRMgmt/PostPutProjectCode',
PRItemRemoval: '/PRMgmt/PRItemRemoval', PRItemRemoval: '/PRMgmt/PRItemRemoval',
PutItemDetail: '/PRMgmt/PutItemDetail', PutItemDetail: '/PRMgmt/PutItemDetail',
ApprovedSelectedPRItem: '/PRMgmt/ApprovedSelectedPRItem', ApprovedSelectedPRItem: '/PRMgmt/ApprovedSelectedPRItem',

View File

@ -30,3 +30,10 @@ function renderAlterOfferbtns(data, row) {
'</button > '; '</button > ';
return buttonsHtml; return buttonsHtml;
} }
function renderProjectCodebtns(data, row) {
var jsonData = JSON.stringify(row).replace(/"/g, "&quot;");
return '<button onclick="showProjectCode(' + jsonData + ',' + false + ')" class="btn btn-default">' +
'<i class="fa-solid fa-pen-to-square fa-xl" style="color: #FFA500;" aria-hidden="true"></i>' +
'</button > ';;
}

View File

@ -62,7 +62,6 @@ var colOnPRtracking = [
{ data: 'acknowledgeBy' }, { data: 'acknowledgeBy' },
{ data: 'acknowledgeDate' }, { data: 'acknowledgeDate' },
]; ];
var colOnPRTable = [ var colOnPRTable = [
{ data: 'prNo' }, { data: 'prNo' },
{ data: 'newPRNo' }, { data: 'newPRNo' },
@ -126,7 +125,6 @@ var colAlterOfferTable = [
}, },
{ data: 'description' }, { data: 'description' },
]; ];
var colRRFinance = [ var colRRFinance = [
{ data: 'prNo' }, { data: 'prNo' },
{ data: 'itemNo' }, { data: 'itemNo' },
@ -161,7 +159,6 @@ var colRRFinance = [
{ data: 'emailAddress', visible: false }, { data: 'emailAddress', visible: false },
{ data: 'supplierName', visible: false }, { data: 'supplierName', visible: false },
]; ];
var colItemList = [ var colItemList = [
{ {
data: 'prDetailsId', data: 'prDetailsId',
@ -184,3 +181,22 @@ var colItemList = [
} }
} }
]; ];
var colOnProjectCode = [
{ data: 'projectCode' },
{ data: 'projectName' },
{ data: 'deliveryAddress' },
{ data: 'maxDays' },
{
data: 'isActive',
render: function (data) {
return data ? 'Active' : 'Inactive';
}
},
{
data: null,
render: function (data, type, row) {
return renderProjectCodebtns(data, row);
}
}
];

View File

@ -1,4 +1,64 @@
function approvedSelectedPRItem() { function postPutProjectCode() {
loader = $('#overlay, #loader').css('z-index', 1070);
const modal = $('#showProjectCode');
const mode = modal.attr('data-mode');
const id = modal.attr('data-id');
const payload = {
ProjectCodeId: Number($('#projectCodeId').val()) || 0,
ProjectCode: $('#projectCode').val().trim(),
ProjectName: $('#projectName').val().trim(),
DeliveryAddress: $('#deliveryAddress').val().trim(),
MaxDays: parseInt($('#maxDays').val(), 10),
IsActive: $('#statusSwitch').is(':checked')
};
if (!payload.ProjectCode || !payload.ProjectName || !payload.DeliveryAddress
|| !Number.isInteger(payload.MaxDays) || payload.MaxDays <= 0) {
showToast('error', 'Please complete all required fields.', 'Submission failed', 4000);
return;
}
const isAdd = mode === 'add';
let message = isAdd
? 'Are you sure you want to add new project code? This action cannot be undone.'
: 'Are you sure you want to update this project code? This action cannot be undone.';
showConfirmation({
title: 'Project Code',
message: message,
type: 'warning',
confirmText: 'Yes',
cancelText: 'No'
}).then((confirmed) => {
if (confirmed) {
$.ajax({
url: endpoint.PostPutProjectCode,
type: 'POST',
contentType: 'application/json',
data: JSON.stringify(payload),
...beforeComplete(loader),
success: function (response) {
if (response.success) {
// Refresh table
prTable.ajax.reload(null, false);
// Close modal
modal.modal('hide');
showToast('success', isAdd ? 'Project added successfully!' : 'Project updated successfully!', 'Success', 4000);
} else {
showToast('error', response.response, 'Approval failed', 4000);
}
},
error: errorHandler
});
}
});
}
function approvedSelectedPRItem() {
const loader = $('#overlay, #loader').css('z-index', 1070); const loader = $('#overlay, #loader').css('z-index', 1070);
const selectedItems = Object.values(selectedProductsMap); const selectedItems = Object.values(selectedProductsMap);

View File

@ -1,4 +1,62 @@
function getApproverName(prDetailsId) { function showProjectCode(data = {}, isNew = true) {
const modal = $('#showProjectCode');
if (isNew) {
// Mode
modal.attr('data-mode', 'add');
modal.attr('data-id', '');
// Header & button
$('#headerNew').show();
$('#headerUpdate').hide();
$('#btnAddUpdate')
.text('Add Project')
.removeClass('btn-warning')
.addClass('btn-success');
// Clear fields
$('#itemPostPutForm')[0].reset();
$('#status').val('true');
} else {
modal.attr('data-mode', 'update');
modal.attr('data-id', data.id);
$('#headerNew').hide();
$('#headerUpdate').show();
$('#btnAddUpdate')
.text('Update Project')
.removeClass('btn-success')
.addClass('btn-warning');
// Fill fields
$('#projectCodeId').val(data.projectCodeId);
$('#projectCode').val(data.projectCode);
$('#projectName').val(data.projectName);
$('#deliveryAddress').val(data.deliveryAddress);
$('#maxDays').val(data.maxDays);
$('#statusSwitch').prop('checked', data.isActive);
$('label[for="statusSwitch"]').text(data.isActive ? 'Active' : 'Inactive');
}
$('#maxDays').on('input', function () {
const value = Number(this.value);
$('#btnAddUpdate').prop('disabled', value <= 0);
});
$('#statusSwitch').on('change', function () {
$('label[for="statusSwitch"]').text(
this.checked ? 'Active' : 'Inactive'
);
});
modal.modal('show');
}
function getApproverName(prDetailsId) {
PRDetailsId = prDetailsId; PRDetailsId = prDetailsId;
$.ajax({ $.ajax({
url: '/PRMgmt/GetApproverName', url: '/PRMgmt/GetApproverName',
@ -636,6 +694,9 @@ function viewPRDetails(data) {
document.getElementById('label-pr-remarks').innerHTML = data.remarks; document.getElementById('label-pr-remarks').innerHTML = data.remarks;
document.getElementById('label-pr-attestedBy').innerHTML = data.attestedBy; document.getElementById('label-pr-attestedBy').innerHTML = data.attestedBy;
document.getElementById('label-pr-approvedBy').innerHTML = data.approvedBy; document.getElementById('label-pr-approvedBy').innerHTML = data.approvedBy;
document.getElementById('label-pr-ProjectCode').innerHTML = data.projectCode;
console.log('data.projectCode', data.projectCode);
document.getElementById('label-pr-dateNeeded').innerHTML = formatDate(data.dateNeeded); document.getElementById('label-pr-dateNeeded').innerHTML = formatDate(data.dateNeeded);

View File

@ -0,0 +1,22 @@
$(document).ready(function () {
loader = $('#overlay, #loader');
prTable = $('#ProjectCodeTable').DataTable({
ajax: {
url: endpoint.GetProjectCodes,
type: 'GET',
beforeSend: function () {
loader.show();
},
complete: function () {
loader.hide();
}
},
initComplete: initCompleteCallback,
columns: colOnProjectCode,
responsive: true,
language: {
emptyTable: "No record available"
},
error: errorHandler
});
})

View File

@ -29,3 +29,8 @@
align-self: flex-end; align-self: flex-end;
margin-right: 20px; margin-right: 20px;
} }
#filePreview .alert {
border-left: 4px solid #198754;
}