Partial for custom PO

This commit is contained in:
rowell_m_soriano 2026-02-19 17:23:28 +08:00
parent 11646fec68
commit da0af6a64e
44 changed files with 1411 additions and 606 deletions

View File

@ -8,6 +8,7 @@
<ItemGroup>
<PackageReference Include="CaptchaGen.NetCore" Version="1.1.2" />
<PackageReference Include="Dapper" Version="2.1.66" />
<PackageReference Include="Google.Apis.Drive.v3" Version="1.67.0.3373" />
<PackageReference Include="Microsoft.AspNet.Identity.Core" Version="2.2.4" />
<PackageReference Include="Microsoft.AspNetCore.SignalR.Core" Version="1.2.0" />

View File

@ -15,6 +15,8 @@ namespace CPRNIMS.Domain.Contracts.PO
public interface IPurchaseOrder
{
#region Get
Task<POFormData> GetPOFormDataAsync(long? poId);
Task<List<Infrastructure.Entities.PO.PO>> GetPOListByTerm(PODto itemDto);
Task<List<IncomingShipmentDto>> GetIncomingShipment(PODto itemDto);
Task<List<IndexCard>> GetIndexCard(PODto poDto);
Task<List<PurchaseOrder>> GetForPOApprovalByPRNo(PODto PODto);

View File

@ -1,8 +1,6 @@
using CPRNIMS.Domain.Contracts.PO;
using CPRNIMS.Infrastructure.Database;
using CPRNIMS.Infrastructure.Dto.Items;
using CPRNIMS.Infrastructure.Dto.PO;
using CPRNIMS.Infrastructure.Dto.PR;
using CPRNIMS.Infrastructure.Entities.Canvass;
using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.Entities.LocalDb.NonInvent;
@ -10,6 +8,7 @@ using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.Common;
using CPRNIMS.Infrastructure.ViewModel.PO;
using Dapper;
using Microsoft.Data.SqlClient;
using Microsoft.EntityFrameworkCore;
using System.Data;
@ -30,6 +29,32 @@ namespace CPRNIMS.Domain.Services.PO
_smptHelper = smptHelper;
}
#region Get
public async Task<POFormData> GetPOFormDataAsync(long? poId)
{
// Reuse the connection from your existing DbContext
var conn = _dbContext.Database.GetDbConnection();
var param = new DynamicParameters();
param.Add("@POId", poId, DbType.Int64);
// Open only if not already open (EF Core may have it open already)
if (conn.State != ConnectionState.Open)
await conn.OpenAsync();
using var multi = await conn.QueryMultipleAsync(
"GetExistingPOFormData",
param,
commandType: CommandType.StoredProcedure
);
return new POFormData
{
Header = await multi.ReadFirstOrDefaultAsync<POHeader>(),
LineItems = (await multi.ReadAsync<POLineItem>()).ToList(),
Charges = (await multi.ReadAsync<POCharges>()).ToList(),
DocsRequired = (await multi.ReadAsync<DocRequired>()).ToList()
};
}
public async Task<List<Incoterm>> GetIncoterms(PODto itemDto)
{
return await _dbContext.Incoterms.ToListAsync();
@ -41,21 +66,13 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<List<Suppliers>> GetSuppliers(PODto itemDto)
{
try
{
var allItems = await _dbContext.Suppliers
.FromSqlRaw($"EXEC GetSuppliers @UserId,@SupplierName",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@SupplierName", itemDto.SupplierName))
.ToListAsync();
var allItems = await _dbContext.Suppliers
.FromSqlRaw($"EXEC GetSuppliers @UserId,@SupplierName",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@SupplierName", itemDto.SupplierName))
.ToListAsync();
return allItems ?? new List<Suppliers>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<Suppliers>();
}
public async Task<List<PRWOCanvass>> GetPRWOCanvass(PODto itemDto)
{
@ -69,55 +86,31 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<List<CreatedPO>> GetCreatedPO(PODto pODto)
{
try
{
var createdPOs = await _dbContext.CreatedPOs
.FromSqlRaw($"EXEC GetCreatedPO @UserId",
new SqlParameter("@UserId", pODto.UserId))
.ToListAsync();
var createdPOs = await _dbContext.CreatedPOs
.FromSqlRaw($"EXEC GetCreatedPO @UserId",
new SqlParameter("@UserId", pODto.UserId))
.ToListAsync();
return createdPOs ?? new List<CreatedPO>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return createdPOs ?? new List<CreatedPO>();
}
public async Task<List<CreatedPO>> GetMyCreatedPO(PODto pODto)
{
try
{
var createdPOs = await _dbContext.CreatedPOs
.FromSqlRaw($"EXEC GetMyCreatedPO @UserId",
new SqlParameter("@UserId", pODto.UserId))
.ToListAsync();
var createdPOs = await _dbContext.CreatedPOs
.FromSqlRaw($"EXEC GetMyCreatedPO @UserId",
new SqlParameter("@UserId", pODto.UserId))
.ToListAsync();
return createdPOs ?? new List<CreatedPO>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return createdPOs ?? new List<CreatedPO>();
}
public async Task<List<ApprovedPO>> GetApprovedPO(PODto PODto)
{
try
{
var allItems = await _dbContext.ApprovedPOs
.FromSqlRaw($"EXEC GetApprovedPO @UserId ,@IsArchived",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@IsArchived", PODto.IsArchived))
.ToListAsync();
var allItems = await _dbContext.ApprovedPOs
.FromSqlRaw($"EXEC GetApprovedPO @UserId ,@IsArchived",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@IsArchived", PODto.IsArchived))
.ToListAsync();
return allItems ?? new List<ApprovedPO>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<ApprovedPO>();
}
public async Task<List<ItemListForPO>> GetApprovedPOPerEmail(PODto PODto)
{
@ -134,24 +127,16 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<List<CreatedPOPerSupId>> GetCreatedPOPerSupId(PODto pODto)
{
try
{
var allItems = await _dbContext.CreatedPOPerSupIds
.FromSqlRaw("EXEC GetCreatedPOPerSupId @UserId,@SupplierId,@POTypeId,@PONo,@IsManual",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@SupplierId", pODto.SupplierId),
new SqlParameter("@POTypeId", pODto.POTypeId),
new SqlParameter("@PONo", pODto.PONo),
new SqlParameter("@IsManual", pODto.IsManual))
.ToListAsync();
var allItems = await _dbContext.CreatedPOPerSupIds
.FromSqlRaw("EXEC GetCreatedPOPerSupId @UserId,@SupplierId,@POTypeId,@PONo,@IsManual",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@SupplierId", pODto.SupplierId),
new SqlParameter("@POTypeId", pODto.POTypeId),
new SqlParameter("@PONo", pODto.PONo),
new SqlParameter("@IsManual", pODto.IsManual))
.ToListAsync();
return allItems ?? new List<CreatedPOPerSupId>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<CreatedPOPerSupId>();
}
public async Task<List<DocRequired>> GetDocRequired(PODto pODto)
{
@ -160,103 +145,54 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<List<BiddingApproval>> GetForBiddingApproval(PODto PODto)
{
try
{
var allItems = await _dbContext.BiddingApprovals
var allItems = await _dbContext.BiddingApprovals
.FromSqlRaw($"EXEC GetForBiddingApproval @UserId",
new SqlParameter("@UserId", PODto.UserId))
.ToListAsync();
return allItems ?? new List<BiddingApproval>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<BiddingApproval>();
}
public async Task<List<ForPO>> GetForPO(PODto PODto)
{
try
{
var allItems = await _dbContext.ForPOs
var allItems = await _dbContext.ForPOs
.FromSqlRaw($"EXEC GetForPO @UserId",
new SqlParameter("@UserId", PODto.UserId))
.ToListAsync();
return allItems ?? new List<ForPO>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<ForPO>();
}
public async Task<List<ForPOApproval>> GetForPOApproval(PODto PODto)
{
try
{
var allItems = await _dbContext.ForPOApprovals
var allItems = await _dbContext.ForPOApprovals
.FromSqlRaw($"EXEC GetForPOApproval @UserId = '{PODto.UserId}'")
.ToListAsync();
return allItems ?? new List<ForPOApproval>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<ForPOApproval>();
}
public async Task<List<Infrastructure.Entities.PO.PurchaseOrder>>
GetForPOApprovalByPRNo(PODto PODto)
{
try
{
var allItems = await _dbContext.PurchaseOrders
.FromSqlRaw($"EXEC GetForPOApprovalByPRNo @UserId = '{PODto.UserId}',@PRNo = '{PODto.PRNo}'")
.ToListAsync();
var allItems = await _dbContext.PurchaseOrders
.FromSqlRaw($"EXEC GetForPOApprovalByPRNo @UserId = '{PODto.UserId}',@PRNo = '{PODto.PRNo}'")
.ToListAsync();
return allItems ?? new List<Infrastructure.Entities.PO.PurchaseOrder>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<Infrastructure.Entities.PO.PurchaseOrder>();
}
public async Task<List<ItemListForPO>> GetForPOPerSuppEmail(PODto PODto)
{
try
{
var allItems = await _dbContext.ItemListForPOs
var allItems = await _dbContext.ItemListForPOs
.FromSqlRaw($"EXEC GetForPOPerSuppEmail @UserId = '{PODto.UserId}',@EmailAddress = '{PODto.EmailAddress}',@POTypeId = '{PODto.POTypeId}',@PONo = '{PODto.PONo}',@IsArchived = '{PODto.IsArchived}'")
.ToListAsync();
return allItems ?? new List<ItemListForPO>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<ItemListForPO>();
}
public async Task<List<CentralPONo>> GetLatestPO(PODto pODto)
{
try
{
var allItems = await _dbContext.CentralPONos
var allItems = await _dbContext.CentralPONos
.FromSqlRaw($"EXEC GetLatestPO")
.ToListAsync();
return allItems ?? new List<CentralPONo>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<CentralPONo>();
}
public async Task<List<SystemSettings>> GetLatestPO2(PODto pODto)
{
@ -345,25 +281,15 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<List<RFQPerSupplier>> GetSupplierBidById(PODto itemDto)
{
try
{
var allItems = await _dbContext.RFQPerSuppliers
.FromSqlRaw($"EXEC GetSupplierBidById @CanvassDetailId = '{itemDto.CanvassDetailId}'")
.ToListAsync();
var allItems = await _dbContext.RFQPerSuppliers
.FromSqlRaw($"EXEC GetSupplierBidById @CanvassDetailId = '{itemDto.CanvassDetailId}'")
.ToListAsync();
return allItems ?? new List<RFQPerSupplier>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<RFQPerSupplier>();
}
public async Task<List<RFQPerSupplier>> GetSupplierBidByItem(PODto itemDto)
{
try
{
var allItems = await _dbContext.RFQPerSuppliers
var allItems = await _dbContext.RFQPerSuppliers
.FromSqlRaw($"EXEC GetSupplierBidByItem @UserId,@Status,@ItemNo,@CanvassId,@IsHistory,@PRDetailsId",
new SqlParameter("@UserId", itemDto.UserId),
new SqlParameter("@Status", itemDto.Status),
@ -373,13 +299,7 @@ namespace CPRNIMS.Domain.Services.PO
new SqlParameter("@PRDetailsId", itemDto.PRDetailsId))
.ToListAsync();
return allItems ?? new List<RFQPerSupplier>();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return allItems ?? new List<RFQPerSupplier>();
}
public async Task<List<PRPOSummaryCount>> GetPRPOSummaryReport(PODto itemDto)
{
@ -420,170 +340,130 @@ namespace CPRNIMS.Domain.Services.PO
return allItems ?? new List<IncomingShipmentDto>();
}
public async Task<List<Infrastructure.Entities.PO.PO>> GetPOListByTerm(PODto itemDto)
{
return await _dbContext.POs
.Where(p => !p.IsCancel && !p.IsPOClosed &&
p.IsActive && p.PONo.StartsWith(itemDto.PONo ?? "N/A"))
.Take(50)
.AsNoTracking()
.ToListAsync();
}
#endregion
#region PostPut
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PostApprovedPO(PODto PODto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostApprovedPO @UserId, @PONo",
new SqlParameter("@PONo", PODto.PONo != null ? PODto.PONo : 0L),
new SqlParameter("@UserId", PODto.UserId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostApprovedPO @UserId, @PONo",
new SqlParameter("@PONo", PODto.PONo != null ? PODto.PONo : 0L),
new SqlParameter("@UserId", PODto.UserId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PostApprovedSuggested(PODto PODto)
{
try
{
await _dbContext.Database
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostSuggestedSupp @UserId, @CanvassDetailId, @ItemNo, @SupplierId,@CanvassId",
new SqlParameter("@CanvassDetailId", PODto.CanvassDetailId != null ? PODto.CanvassDetailId : 0L),
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@ItemNo", PODto.ItemNo != null ? PODto.ItemNo : 0L),
new SqlParameter("@SupplierId", PODto.SupplierId),
new SqlParameter("@CanvassId", PODto.CanvassId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<Suppliers> PostApprovedSupplier(PODto PODto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostApprovedSupplier @UserId, @CanvassDetailId, @ItemNo",
{ await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostApprovedSupplier @UserId, @CanvassDetailId, @ItemNo",
new SqlParameter("@CanvassDetailId", PODto.CanvassDetailId != null ? PODto.CanvassDetailId : 0L),
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@ItemNo", PODto.ItemNo));
return new Suppliers();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return new Suppliers();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PostPOToSupplier(PODto PODto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPOToSupplier @UserId, @POTypeId, @EmailAddress,@PONumber",
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@EmailAddress", PODto.EmailAddress),
new SqlParameter("@PONumber", PODto.PONo));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostPOToSupplier @UserId, @POTypeId, @EmailAddress,@PONumber",
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@EmailAddress", PODto.EmailAddress),
new SqlParameter("@PONumber", PODto.PONo));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PostPutPO(PODto PODto)
{
try
if (PODto.UserId == "89da2977-c70f-4df9-94d4-9a610aa999ea" ||
PODto.UserId == "ac95500c-4b73-4df8-bdcb-965f9fafec30")
{
if (PODto.UserId == "89da2977-c70f-4df9-94d4-9a610aa999ea" ||
PODto.UserId == "ac95500c-4b73-4df8-bdcb-965f9fafec30")
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PostPutPO @UserId,@POTypeId,@SupplierId,@PONumber,@PORemarks,@IncoTermsId,@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@DeliverTo",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@SupplierId", PODto.SupplierId),
new SqlParameter("@PONumber", PODto.PONo),
new SqlParameter("@PORemarks", PODto.PORemarks ?? "N/A"),
new SqlParameter("@IncoTermsId", 1),
new SqlParameter("@PODId", 1),
new SqlParameter("@ProfInvoiceNo", PODto.ProfInvoiceNo ?? "N/A"),
new SqlParameter("@ProfInvoiceDate", DateTime.Now),
new SqlParameter("@PaymentTermsId", 1),
new SqlParameter("@ShippingInstructionId", 1),
new SqlParameter("@DeliverTo", PODto.DeliverTo));
}
else
{
if (!isUpdated)
{
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PostPutPO @UserId,@POTypeId,@SupplierId,@PONumber,@PORemarks,@IncoTermsId,@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@DeliverTo",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@SupplierId", PODto.SupplierId),
new SqlParameter("@PONumber", PODto.PONo),
new SqlParameter("@PORemarks", PODto.PORemarks ?? "N/A"),
new SqlParameter("@IncoTermsId", 1),
new SqlParameter("@PODId", 1),
new SqlParameter("@ProfInvoiceNo", PODto.ProfInvoiceNo ?? "N/A"),
new SqlParameter("@ProfInvoiceDate", DateTime.Now),
new SqlParameter("@PaymentTermsId", 1),
new SqlParameter("@ShippingInstructionId", 1),
new SqlParameter("@DeliverTo", PODto.DeliverTo));
PODto.PONo = await GetLatestPOById(PODto);//Retrieve and Update SystemSettings
}
else
{
if (!isUpdated)
{
PODto.PONo = await GetLatestPOById(PODto);//Retrieve and Update SystemSettings
}
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PostPutPO @UserId,@POTypeId,@SupplierId,@PONumber,@PORemarks,@IncoTermsId,@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@DeliverTo",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@SupplierId", PODto.SupplierId),
new SqlParameter("@PONumber", formattedPONumber),
new SqlParameter("@PORemarks", PODto.PORemarks ?? "N/A"),
new SqlParameter("@IncoTermsId", 1),
new SqlParameter("@PODId", 1),
new SqlParameter("@ProfInvoiceNo", PODto.ProfInvoiceNo ?? "N/A"),
new SqlParameter("@ProfInvoiceDate", DateTime.Now),
new SqlParameter("@PaymentTermsId", 1),
new SqlParameter("@ShippingInstructionId", 1),
new SqlParameter("@DeliverTo", PODto.DeliverTo));
}
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PostPutPO @UserId,@POTypeId,@SupplierId,@PONumber,@PORemarks,@IncoTermsId,@PODId,@ProfInvoiceNo,@ProfInvoiceDate,@PaymentTermsId,@ShippingInstructionId,@DeliverTo",
new SqlParameter("@UserId", PODto.UserId),
new SqlParameter("@POTypeId", PODto.POTypeId),
new SqlParameter("@SupplierId", PODto.SupplierId),
new SqlParameter("@PONumber", formattedPONumber),
new SqlParameter("@PORemarks", PODto.PORemarks ?? "N/A"),
new SqlParameter("@IncoTermsId", 1),
new SqlParameter("@PODId", 1),
new SqlParameter("@ProfInvoiceNo", PODto.ProfInvoiceNo ?? "N/A"),
new SqlParameter("@ProfInvoiceDate", DateTime.Now),
new SqlParameter("@PaymentTermsId", 1),
new SqlParameter("@ShippingInstructionId", 1),
new SqlParameter("@DeliverTo", PODto.DeliverTo));
}
return new Infrastructure.Entities.PO.PurchaseOrder();
}
private void PutLocalCentralPo(PODto PODto)
{
try
string columnName;
string updatedPONo = "";
// Determine the column to update based on POTypeId
switch (PODto.POTypeId)
{
string columnName;
string updatedPONo = "";
// Determine the column to update based on POTypeId
switch (PODto.POTypeId)
{
case 1: // SI
// Remove the first two characters from PONo
updatedPONo = PODto.PONo;
columnName = "PONoVatInc";
break;
case 2: // DR
updatedPONo = PODto.PONo;
columnName = "PONoVatEx";
break;
case 3: // IMPORT
updatedPONo = PODto.PONo;
columnName = "IPONoVatInc";
break;
default:
throw new ArgumentException("Invalid POTypeId.");
}
case 1: // SI
// Remove the first two characters from PONo
updatedPONo = PODto.PONo;
columnName = "PONoVatInc";
break;
case 2: // DR
updatedPONo = PODto.PONo;
columnName = "PONoVatEx";
break;
case 3: // IMPORT
updatedPONo = PODto.PONo;
columnName = "IPONoVatInc";
break;
default:
throw new ArgumentException("Invalid POTypeId.");
}
// Build the SQL query
string query = $@"
// Build the SQL query
string query = $@"
UPDATE [dbo].[SystemSettings]
SET {columnName} = @UpdatedPONo
WHERE {columnName} IS NOT NULL";
// Execute the raw SQL query
_dbLocalContext.Database.ExecuteSqlRaw(query, new SqlParameter("@UpdatedPONo", updatedPONo));
}
catch (Exception ex)
{
ex.ToString();
throw;
}
// Execute the raw SQL query
_dbLocalContext.Database.ExecuteSqlRaw(query, new SqlParameter("@UpdatedPONo", updatedPONo));
}
public async Task<CustomPO> PostPutCustomPO(PODto pODto)
{
@ -693,107 +573,68 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<DocRequired> PostSuppDocRequirements(PODto poDto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostSuppDocRequirements @UserId,@DocRequirementId,@PONumber",
new SqlParameter("@DocRequirementId", poDto.DocRequirementId),
new SqlParameter("@UserId", poDto.UserId),
new SqlParameter("@PONumber", formattedPONumber));
return new DocRequired();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostSuppDocRequirements @UserId,@DocRequirementId,@PONumber",
new SqlParameter("@DocRequirementId", poDto.DocRequirementId),
new SqlParameter("@UserId", poDto.UserId),
new SqlParameter("@PONumber", formattedPONumber));
return new DocRequired();
}
public async Task<OtherCharges> PostSuppCharges(PODto poDto)
{
try
{
await _dbContext.Database
await _dbContext.Database
.ExecuteSqlRawAsync("EXEC PostSuppCharges @UserId,@PONo,@OtherChargesId,@POTypeId,@Amount",
new SqlParameter("@UserId", poDto.UserId),
new SqlParameter("@PONo", formattedPONumber),
new SqlParameter("@OtherChargesId", poDto.OtherChargesId),
new SqlParameter("@POTypeId", poDto.POTypeId),
new SqlParameter("@Amount", poDto.Amount));
return new OtherCharges();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
return new OtherCharges();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PutPRItemDetails(PODto pODto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutPRItemDetails @UserId,@ItemName,@Specification,@Qty,@UOMId,@PRDetailsId",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@ItemName", pODto.ItemName),
new SqlParameter("@Specification", pODto.Specification),
new SqlParameter("@Qty", pODto.Qty),
new SqlParameter("@UOMId", pODto.UOMId),
new SqlParameter("@PRDetailsId", pODto.PRDetailsId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutPRItemDetails @UserId,@ItemName,@Specification,@Qty,@UOMId,@PRDetailsId",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@ItemName", pODto.ItemName),
new SqlParameter("@Specification", pODto.Specification),
new SqlParameter("@Qty", pODto.Qty),
new SqlParameter("@UOMId", pODto.UOMId),
new SqlParameter("@PRDetailsId", pODto.PRDetailsId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PutPOItemDetail(PODto pODto)
{
try
{
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutPOItemDetail @UserId,@UOMId,@Qty,@PRDetailsId,@Remarks,@ItemDescription,@Specification,@PONo,@UnitPrice,@PaymentTermsId,@PODId",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@UOMId", pODto.UOMId),
new SqlParameter("@Qty", pODto.Qty),
new SqlParameter("@PRDetailsId", pODto.PRDetailsId),
new SqlParameter("@Remarks", pODto.PORemarks),
new SqlParameter("@ItemDescription", pODto.ItemDescription),
new SqlParameter("@Specification", pODto.Specification),
new SqlParameter("@PONo", pODto.PONo),
new SqlParameter("@UnitPrice", pODto.UnitPrice),
new SqlParameter("@PaymentTermsId", pODto.PaymentTermsId),
new SqlParameter("@PODId", pODto.PODId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException ex)
{
ex.ToString();
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutPOItemDetail @UserId,@UOMId,@Qty,@PRDetailsId,@Remarks,@ItemDescription,@Specification,@PONo,@UnitPrice,@PaymentTermsId,@PODId",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@UOMId", pODto.UOMId),
new SqlParameter("@Qty", pODto.Qty),
new SqlParameter("@PRDetailsId", pODto.PRDetailsId),
new SqlParameter("@Remarks", pODto.PORemarks),
new SqlParameter("@ItemDescription", pODto.ItemDescription),
new SqlParameter("@Specification", pODto.Specification),
new SqlParameter("@PONo", pODto.PONo),
new SqlParameter("@UnitPrice", pODto.UnitPrice),
new SqlParameter("@PaymentTermsId", pODto.PaymentTermsId),
new SqlParameter("@PODId", pODto.PODId));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<Infrastructure.Entities.PO.PurchaseOrder> PutMyPONo(PODto pODto)
{
try
string oldPONo = pODto.PONo;
if (!isUpdated)
{
string oldPONo = pODto.PONo;
if (!isUpdated)
{
await GetLatestPOById(pODto);
}
await GetLatestPOById(pODto);
}
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutMyPONo @UserId,@OldPONo,@NewPONo,@PORemarks",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@OldPONo", oldPONo),
new SqlParameter("@NewPONo", formattedPONumber),
new SqlParameter("@PORemarks", pODto.PORemarks));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
catch (SqlException)
{
throw;
}
await _dbContext.Database
.ExecuteSqlRawAsync($"EXEC PutMyPONo @UserId,@OldPONo,@NewPONo,@PORemarks",
new SqlParameter("@UserId", pODto.UserId),
new SqlParameter("@OldPONo", oldPONo),
new SqlParameter("@NewPONo", formattedPONumber),
new SqlParameter("@PORemarks", pODto.PORemarks));
return new Infrastructure.Entities.PO.PurchaseOrder();
}
public async Task<List<POItemDetail>> GetPOItemDetail(PODto pODto)
{
@ -909,103 +750,71 @@ namespace CPRNIMS.Domain.Services.PO
}
public async Task<bool> DeleteIncShip(PODto poDto)
{
try
{
var inc = await _dbContext.IncomingShipments
.FirstOrDefaultAsync(i => i.POId == poDto.POId);
var inc = await _dbContext.IncomingShipments
.FirstOrDefaultAsync(i => i.POId == poDto.POId);
if (inc != null)
{
inc.IsActive = false;
_dbContext.SaveChanges();
}
return true;
}
catch (Exception ex)
if (inc != null)
{
return false;
inc.IsActive = false;
_dbContext.SaveChanges();
}
return true;
}
public string EMailTemplate(string relativePath, string emailTemplate)
{
try
{
string basePath = AppContext.BaseDirectory;
string templateFolderPath = Path.Combine(basePath, relativePath);
string templateFilePath = Path.Combine(templateFolderPath, emailTemplate);
string basePath = AppContext.BaseDirectory;
string templateFolderPath = Path.Combine(basePath, relativePath);
string templateFilePath = Path.Combine(templateFolderPath, emailTemplate);
if (System.IO.File.Exists(templateFilePath))
{
return System.IO.File.ReadAllText(templateFilePath);
}
else
{
Console.WriteLine($"File not found: {templateFilePath}");
return "Template file not found";
}
}
catch (Exception ex)
if (System.IO.File.Exists(templateFilePath))
{
var errorMessage = ex.ToString();
throw new Exception($"Error loading email template: {errorMessage}", ex);
return System.IO.File.ReadAllText(templateFilePath);
}
else
{
Console.WriteLine($"File not found: {templateFilePath}");
return "Template file not found";
}
}
public async Task PostIncShipFollowUp(PODto itemDto, List<IncomingShipmentDto> shipFollowUp)
{
try
{
var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "IncShipFollowUp.cshtml");
var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "IncShipFollowUp.cshtml");
// Use the passed data instead of re-querying
foreach (var incShip in shipFollowUp)
// Use the passed data instead of re-querying
foreach (var incShip in shipFollowUp)
{
var message = new StringBuilder(baseTemplate);
message.Replace("@ViewBag.PONo", Convert.ToString(incShip.PONo));
message.Replace("@ViewBag.ProfInvoiceNo", Convert.ToString(incShip.ProfInvoiceNo));
message.Replace("@ViewBag.DeliveryDate", Convert.ToString(incShip.DeliveryDate));
message.Replace("@ViewBag.Supplier", Convert.ToString(incShip.SupplierName));
message.Replace("@ViewBag.Signature", Convert.ToString(incShip.Signature));
var messageDetails = new EmailMessageDetailsVM
{
var message = new StringBuilder(baseTemplate);
message.Replace("@ViewBag.PONo", Convert.ToString(incShip.PONo));
message.Replace("@ViewBag.ProfInvoiceNo", Convert.ToString(incShip.ProfInvoiceNo));
message.Replace("@ViewBag.DeliveryDate", Convert.ToString(incShip.DeliveryDate));
message.Replace("@ViewBag.Supplier", Convert.ToString(incShip.SupplierName));
message.Replace("@ViewBag.Signature", Convert.ToString(incShip.Signature));
Recipient = incShip.EmailAddress,
Message = message.ToString(),
Subject = incShip.Subject,
CC = incShip.CC,
IsSuccess = false,
SenderEmail = incShip.UserName,
DisplayName = "llipurchasing.com",
NewPassword = incShip.Password,
OutGoingPort = 587,
Server = incShip.Server,
UserName = incShip.UserName
};
var messageDetails = new EmailMessageDetailsVM
{
Recipient = incShip.EmailAddress,
Message = message.ToString(),
Subject = incShip.Subject,
CC = incShip.CC,
IsSuccess = false,
SenderEmail = incShip.UserName,
DisplayName = "llipurchasing.com",
NewPassword = incShip.Password,
OutGoingPort = 587,
Server = incShip.Server,
UserName = incShip.UserName
};
await _smptHelper.SendEmailAsync(messageDetails);
}
}
catch (Exception ex)
{
var errorMessage = ex.InnerException?.ToString() ?? ex.Message.ToString();
// Log the error properly
throw;
await _smptHelper.SendEmailAsync(messageDetails);
}
}
public async Task<bool> PostIncShipFollowUp(PODto itemDto)
{
try
{
var shipFollowUp = await GetIncomingShipment(itemDto);
await PostIncShipFollowUp(itemDto, shipFollowUp);
return true;
}
catch (Exception ex)
{
ex.ToString();
return false;
}
var shipFollowUp = await GetIncomingShipment(itemDto);
await PostIncShipFollowUp(itemDto, shipFollowUp);
return true;
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
using CPRNIMS.Infrastructure.Entities.PO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.PO
{
public interface ICustomPOService
{
Task<POFormData> GetPOFormDataAsync(long? poId = null);
}
}

View File

@ -8,7 +8,7 @@ using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIContracts.PO
{
public interface IPurchaseOrder
public interface IPurchaseOrder
{
#region Get
Task<List<POVM>> GetSupplierBidById(User user, POVM viewModel);
@ -40,6 +40,7 @@ namespace CPRNIMS.Domain.UIContracts.PO
Task<List<POVM>?> GetIndexCard(User user, POVM viewModel);
Task<List<POVM>?> GetPortOfDischarge(User user, POVM viewModels);
Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModels);
Task<List<POVM>?> GetPOListByTerm(User user, POVM viewModels);
#endregion
#region Post Put
Task<POVM> PostApprovedSupplier(User user, POVM viewModel);

View File

@ -0,0 +1,76 @@
using CPRNIMS.Domain.UIContracts.PO;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Helper;
using Google.Apis.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace CPRNIMS.Domain.UIServices.PO
{
public class CustomPOService : ICustomPOService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly TokenHelper _tokenHelper;
private readonly IConfiguration _configuration;
private readonly ILogger<CustomPOService> _logger;
public CustomPOService(
IHttpClientFactory httpClientFactory,
TokenHelper tokenHelper,
IConfiguration configuration,
ILogger<CustomPOService> logger)
{
_httpClientFactory = httpClientFactory;
_tokenHelper = tokenHelper;
_configuration = configuration;
_logger = logger;
}
public async Task<POFormData> GetPOFormDataAsync(long? poId = null)
{
try
{
var token = await _tokenHelper.GetValidTokenAsync();
if (string.IsNullOrEmpty(token))
throw new UnauthorizedAccessException("No valid token available.");
var httpClient = _httpClientFactory.CreateClient("AuthApi");
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
var url = _configuration["LLI:NonInvent:POMgmt:GetPOFormData"];
if (poId.HasValue)
url += $"?poId={poId}";
var response = await httpClient.GetAsync(url);
if (!response.IsSuccessStatusCode)
{
_logger.LogError("GetPOFormData failed: {StatusCode}", response.StatusCode);
return new POFormData(); // return empty rather than throw
}
var json = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<POFormData>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
});
return result ?? new POFormData();
}
catch (Exception ex)
{
_logger.LogError(ex, "Error in GetPOFormDataAsync");
return new POFormData();
}
}
}
}

View File

@ -126,6 +126,12 @@ namespace CPRNIMS.Domain.UIServices.PO
#endregion
#region Get
public async Task<List<POVM>?> GetPOListByTerm(User user, POVM viewModel)
{
return await SendGetApiRequest(user, viewModel,
_configuration["LLI:NonInvent:POMgmt:GetPOListByTerm"]);
}
public async Task<List<POVM>?> GetIncomingShipment(User user, POVM viewModel)
{
return await SendGetApiRequest(user, viewModel,

View File

@ -13,12 +13,15 @@ namespace CPRNIMS.Infrastructure.Entities.PO
{
[Key]
public long POId { get; set; }
public long PONo { get; set; }
public bool Submit { get; set; }
public string PONo { get; set; }
public bool IsActive { get; set; }
public bool IsPOClosed { get; set; }
public bool IsCancel { get; set; }
public string? UserId { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime UpdatedDate { get; set; }
public byte Status { get; set; }
public byte PaymentTermsId { get; set; }
public byte PODId { get; set; }
public byte POTypeId { get; set; }
public DateTime? UpdatedDate { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
public class POCharges
{
[Key]
public int OtherChargesId { get; set; }
public string? OtherChargesName { get; set; }
public decimal Amount { get; set; }
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
public class POFormData
{
public POHeader? Header { get; set; }
public List<POLineItem>? LineItems { get; set; }
public List<POCharges>? Charges { get; set; }
public List<DocRequired>? DocsRequired { get; set; }
}
}

View File

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
public class POHeader
{
[Key]
public long POId { get; set; }
public string? PONo { get; set; }
public int SupplierId { get; set; }
public string? SupplierName { get; set; }
public DateTime DeliveryDate { get; set; }
public DateTime? ProfInvoiceDate { get; set; }
public string? ProfInvoiceNo { get; set; }
public string? CurrencyName { get; set; }
public string? PaymentTerms { get; set; }
public string? Remarks { get; set; }
public decimal Discount { get; set; }
public decimal GrossAmountUSD { get; set; }
public decimal FinalAmountUSD { get; set; }
public decimal GrossAmountPHP { get; set; }
public decimal FinalAmountPHP { get; set; }
public string? POTypeName { get; set; }
public string? UserId { get; set; }
public byte Status { get; set; }
public byte PaymentTermsId { get; set; }
public byte PODId { get; set; }
public byte POTypeId { get; set; }
public byte IncoTermsId { get; set; }
}
}

View File

@ -0,0 +1,24 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPRNIMS.Infrastructure.Entities.PO
{
public class POLineItem
{
[Key]
public long PODetailId { get; set; }
public long PRNo { get; set; }
public decimal Qty { get; set; }
public decimal UnitPrice { get; set; }
public decimal TotalAmount { get; set; }
public string? UOMName { get; set; }
public long ItemNo { get; set; }
public string? ItemName { get; set; }
public string? Specification { get; set; }
}
}

View File

@ -256,7 +256,6 @@ namespace CPRNIMS.Infrastructure.Helper
return ExtractClaimsFromToken(tokenClaim.Value);
}
// Rest of your existing methods...
public HttpClient CreateHttpClientWithDefaultHeaders(string token)
{
string BaseUrl = _configuration["CommonEndpoints:ApiDefaultHeaders:BaseUrl"];
@ -281,24 +280,6 @@ namespace CPRNIMS.Infrastructure.Helper
return httpClient;
}
public Dictionary<string, string> DefaultHeaders
{
get
{
var headersSection = _configuration.GetSection(
"CommonEndpoints:ApiDefaultHeaders");
var headers = new Dictionary<string, string>();
foreach (var childSection in headersSection.GetChildren())
{
headers[childSection.Key] = childSection.Value;
}
return headers;
}
}
public Dictionary<string, string> CustomHeaders
{
get

View File

@ -147,7 +147,6 @@
</ItemGroup>
<ItemGroup>
<Folder Include="Helper\" />
<Folder Include="wwwroot\Content\Uploads\PRAttachment\" />
</ItemGroup>

View File

@ -9,6 +9,7 @@ using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.Entities.Common;
using CPRNIMS.Infrastructure.ViewModel.Common;
using CPRNIMS.Infrastructure.Dto.Account;
using System.Threading.Tasks;
namespace CPRNIMS.WebApi.Controllers.Account
{
@ -36,7 +37,6 @@ namespace CPRNIMS.WebApi.Controllers.Account
_userManager = userManager;
_signInManager = signInManager;
}
[AllowAnonymous]
[HttpPost("Login")]
public async Task<IActionResult> Login([FromBody] LoginRequest model,

View File

@ -279,6 +279,20 @@ namespace CPRNIMS.WebApi.Controllers.PO
}
#endregion
#region Get
[HttpGet("GetPOFormData")]
public async Task<IActionResult> GetPOFormData(int? poId = null)
{
var data = await _purchaseOrder.GetPOFormDataAsync(poId);
return Ok(data);
}
[HttpPost("GetPOListByTerm")]
public async Task<IActionResult> GetPOListByTerm(PODto itemDto)
{
return await ExecuteWithErrorHandling(
() => _purchaseOrder.GetPOListByTerm(itemDto),
nameof(GetPOListByTerm), false
);
}
[HttpPost("GetIncomingShipment")]
public async Task<IActionResult> GetIncomingShipment(PODto itemDto)
{

View File

@ -81,7 +81,8 @@ namespace CPRNIMS.WebApps.Common
builder.Services.AddTransient<IReceiving, Receiving>();
builder.Services.AddTransient<ISMTP, SMTP>();
builder.Services.AddTransient<IInventory, Inventory>();
builder.Services.AddTransient<IPurchaseOrder, PurchaseOrder>();
builder.Services.AddTransient<IPurchaseOrder, PurchaseOrder>();
builder.Services.AddTransient<ICustomPOService, CustomPOService>();
builder.Services.AddTransient<Domain.UIContracts.Attachment.IAttachment, Domain.UIServices.Attachment.Attachment>();
builder.Services.AddTransient<IAccount, Account>();
builder.Services.AddTransient<ICaptchaService, CaptchaService>();

View File

@ -1,6 +1,5 @@
using CPRNIMS.Domain.UIContracts.Account;
using CPRNIMS.Domain.UIContracts.PO;
using CPRNIMS.Infrastructure.Entities.PO;
using CPRNIMS.Infrastructure.Helper;
using CPRNIMS.Infrastructure.ViewModel.PO;
using CPRNIMS.WebApps.Controllers.Base;
@ -15,12 +14,14 @@ namespace CPRNIMS.WebApps.Controllers.PO
POVM postPutItem;
private readonly IPurchaseOrder _purchaseOrder;
private readonly ICustomPOService _customPOService;
public POMgmtController(
ErrorLogHelper errorMessageService, IWebHostEnvironment webHostEnvironment
, IPurchaseOrder purchaseOrder, TokenHelper tokenHelper,IAccount account
, IPurchaseOrder purchaseOrder, TokenHelper tokenHelper,IAccount account, ICustomPOService customPOService
) : base(errorMessageService, webHostEnvironment, tokenHelper, account)
{
_purchaseOrder = purchaseOrder;
_customPOService = customPOService;
}
#endregion
#region POST PUT
@ -207,7 +208,7 @@ namespace CPRNIMS.WebApps.Controllers.PO
return Json(new { success = false, Response = postPutItem.Message });
}
#endregion
#region Get
#region Mapper
private POList MapToPONoList(IEnumerable<POList> poList)
{
if (poList == null || !poList.Any())
@ -267,6 +268,15 @@ namespace CPRNIMS.WebApps.Controllers.PO
Specification = itemList.SelectMany(ic => ic.Specification).ToList()
};
}
#endregion
#region Get
[HttpGet]
public async Task<IActionResult> GetPOFormData(long? poId = null)
{
var data = await _customPOService.GetPOFormDataAsync(poId);
return Ok(data);
}
public async Task<IActionResult> GetIncomingShipment(POVM viewModels)
{
response = await _purchaseOrder.GetIncomingShipment(GetUser(), viewModels);
@ -304,7 +314,7 @@ namespace CPRNIMS.WebApps.Controllers.PO
var viewModels = new POVM();
response = await _purchaseOrder.GetForPO(GetUser(), viewModels);
return GetResponse(response);
}
}
public async Task<IActionResult> GetForPOPerSuppEmail(POVM viewModels)
{
response = await _purchaseOrder.GetForPOPerSuppEmail(GetUser(), viewModels);
@ -352,6 +362,24 @@ namespace CPRNIMS.WebApps.Controllers.PO
return Json(new { success = true, data = formattedData });
}
public async Task<IActionResult> GetPOListByTerm(string query)
{
var viewModels = new POVM();
viewModels.PONo = query;
response = await _purchaseOrder.GetPOListByTerm(GetUser(), viewModels);
if (response == null)
{
response = new List<POVM>();
}
var formattedData = response.Select(item => new
{
label = item.PONo,
value = item.POId,
value2 = item.POTypeId
});
return Json(new { success = true, data = formattedData });
}
public async Task<IActionResult> GetPaymentTerms(string query)
{
var viewModels = new POVM();

View File

@ -12,7 +12,8 @@ namespace CPRNIMS.WebApps.ViewComponents.POMgmt
{
1 => "~/Views/Components/POMgmt/CustomPO/SIElem.cshtml",
2 => "~/Views/Components/POMgmt/CustomPO/DRElem.cshtml",
_ => "~/Views/Components/POMgmt/CustomPO/ImportElem.cshtml"
3 => "~/Views/Components/POMgmt/CustomPO/ImportElem.cshtml",
_ => "~/Views/Components/POMgmt/CustomPO/PODetailModification.cshtml"
};
return View(viewName);

View File

@ -216,5 +216,3 @@
@await Html.PartialAsync("PagesView/PO/_DocRequired")
<input hidden id="dr-ImportPoNo" />
<input hidden id="si-ImportPoNo" />

View File

@ -0,0 +1,28 @@
<div class="container mt-4 mb-4">
<!-- WARNING BANNER -->
<div class="alert alert-danger shadow-sm border-3 border-danger">
<div class="d-flex align-items-center">
<div class="me-3 fs-1">
</div>
<div>
<h4 class="mb-1 fw-bold text-danger">
You Are Modifying an Existing Purchase Order
</h4>
<p class="mb-0">
Any changes made here will directly affect supplier commitments, and financial reports.
Please review all details carefully before saving.
</p>
</div>
</div>
</div>
<!-- SECONDARY NOTICE -->
<div class="alert alert-warning shadow-sm">
<strong>Important:</strong>
Ensure that all quantities, prices, delivery dates, and supplier details are accurate.
Any incorrect modifications may result in discrepancies and processing issues.
</div>
</div>

View File

@ -24,6 +24,7 @@
UserRights = document.getElementById("roleRights").value;
const reportTitle = `All Purchase Request - as of ${getFormattedDateTime()}`;
prTable = $('#PRTable').DataTable({
ajax: {
url: '/PRMgmt/GetAllPR',
@ -42,7 +43,59 @@
}
}
},
initComplete: initCompleteCallback,
dom: 'lBfrtip',
buttons: [
{
extend: 'csv',
title: reportTitle
},
{
extend: 'excel',
title: reportTitle
},
{
extend: 'pdf',
title: reportTitle
}
],
initComplete: function () {
initializeColumnSearch({
tableId: '#PRTable',
dataTable: prTable,
searchableColumns: [
{
columnIndex: 0,
columnName: 'PR No',
placeholder: 'Enter PR Number...',
searchType: 'text',
searchMode: 'exact',
width: '150px'
},
{
columnIndex: 2,
columnName: 'Item Name',
placeholder: 'Enter Item Name...',
searchType: 'text',
searchMode: 'contains',
width: '200px'
},
{
columnIndex: 6,
columnName: 'Department',
placeholder: 'Select Department...',
searchType: 'select',
searchMode: 'exact',
width: '150px'
}
]
});
const uniqueSearchClass = 'column-search-input-PRTable';
populateSelectOptions(prTable, 6, '.' + uniqueSearchClass + '[data-column="6"]');
restoreSearchFromURL(uniqueSearchClass, '#PRTable');
},
columns: colOnPRTable,
order: [[3, 'asc']],
rowCallback: rowStatusColorCallback,

View File

@ -24,8 +24,8 @@
<script>
$(document).ready(function() {
// Initialize DataTable for Approved PR
const reportTitle = `Approved Purchase Request (No PO) - as of ${getFormattedDateTime()}`;
var approvedPRTable = $('#ApprovedPRTable').DataTable({
ajax: {
url: '/PRMgmt/GetApprovedPR',
@ -44,11 +44,26 @@
}
}
},
dom: 'lBfrtip',
buttons: [
{
extend: 'csv',
title: reportTitle
},
{
extend: 'excel',
title: reportTitle
},
{
extend: 'pdf',
title: reportTitle
}
],
initComplete: function () {
initializeColumnSearch({
tableId: '#ApprovedPRTable',
dataTable: approvedPRTable,
searchableColumns: [
initializeColumnSearch({
tableId: '#ApprovedPRTable',
dataTable: approvedPRTable,
searchableColumns: [
{
columnIndex: 0,
columnName: 'Status',
@ -92,12 +107,12 @@
]
});
const uniqueSearchClass = 'column-search-input-ApprovedPRTable';
const uniqueSearchClass = 'column-search-input-ApprovedPRTable';
populateSelectOptions(approvedPRTable, 0, '.' + uniqueSearchClass + '[data-column="0"]');
populateSelectOptions(approvedPRTable, 12, '.' + uniqueSearchClass + '[data-column="12"]');
populateSelectOptions(approvedPRTable, 0, '.' + uniqueSearchClass + '[data-column="0"]');
populateSelectOptions(approvedPRTable, 12, '.' + uniqueSearchClass + '[data-column="12"]');
restoreSearchFromURL(uniqueSearchClass, '#ApprovedPRTable');
restoreSearchFromURL(uniqueSearchClass, '#ApprovedPRTable');
},
columns: [
{ data: 'statusName' },

View File

@ -23,8 +23,8 @@
<script>
$(document).ready(function() {
// Initialize DataTable for Approved PR
const reportTitle = `Deleted Purchase Request - as of ${getFormattedDateTime()}`;
var removedPRTable = $('#RemovedPRTable').DataTable({
ajax: {
url: '/PRMgmt/GetApprovedPR',
@ -43,8 +43,23 @@
}
}
},
dom: 'lBfrtip',
buttons: [
{
extend: 'csv',
title: reportTitle
},
{
extend: 'excel',
title: reportTitle
},
{
extend: 'pdf',
title: reportTitle
}
],
initComplete: function () {
initializeColumnSearch({
initializeColumnSearch({
tableId: '#RemovedPRTable',
dataTable: removedPRTable,
searchableColumns: [
@ -83,12 +98,12 @@
]
});
const uniqueSearchClass = 'column-search-input-RemovedPRTable';
const uniqueSearchClass = 'column-search-input-RemovedPRTable';
populateSelectOptions(removedPRTable, 10, '.' + uniqueSearchClass + '[data-column="10"]');
populateSelectOptions(removedPRTable, 10, '.' + uniqueSearchClass + '[data-column="10"]');
restoreSearchFromURL(uniqueSearchClass, '#RemovedPRTable');
},
restoreSearchFromURL(uniqueSearchClass, '#RemovedPRTable');
},
columns: [
{ data: 'prNo' },
{ data: 'itemNo' },

View File

@ -17,7 +17,7 @@
<div class="toast-container" id="toast-container"></div>
</main>
</div>
<script src="~/JsFunctions/Account/loginV3.js"></script>
<script src="~/JsFunctions/Account/loginV4.js"></script>
<script src="~/jsfunctions/utilities/utilsV3.js"></script>
<script src="~/js/toast-notifications.js"></script>
<script src="~/jsfunctions/account/accountvar.js"></script>

View File

@ -2,21 +2,25 @@
<div class="container-fluid">
<div class="row table-container shadow-lg p-2 mb-3 bg-white rounded">
<div class="header-container">
<h2>Custom P.O. Creation</h2>
<h2 id="customPOHeading">Custom P.O. Creation</h2>
</div>
<div class="row">
<!-- Left side (half of the row) -->
<div class="col-6">
<div class="row">
<div class="col-4">
<div class="form-group">
<label for="poNo">PO No#</label>
<input readonly id="poNo" class="form-control">
</div>
<div class="form-group">
<label for="poNo">PO No.</label>
<i class="bx bx-pencil"
style="color: orange; font-size: 1.2rem; cursor: pointer;"
onclick="enablePONoAutocomplete()"> </i>
<input type="search" readonly id="poNo" class="form-control">
<input type="hidden" id="poId" class="form-control" name="poId" />
</div>
</div>
<div class="col-4">
<div class="form-group">
<label for="poNoFinal">Final PO No#</label>
<label for="poNoFinal">Final PO No.</label>
<input readonly id="poNoFinal" class="form-control">
</div>
</div>

View File

@ -159,7 +159,7 @@
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="ModalLabel">PR Item Details</h5>
<h5 class="modal-title" id="ModalLabel">PO Item Details</h5>
</div>
<div class="modal-body">
<div class="row">

View File

@ -11,7 +11,7 @@
Approved PR
</button>
<button class="pr-tab-btn" data-tab="pr-removed" data-endpoint="/PRMgmt/GetRemovedPR">
Removed PR
Deleted PR
</button>
</div>
</div>
@ -76,7 +76,7 @@
<link href="~/css/pr/ButtonStyleV2.css" rel="stylesheet" />
<link href="~/css/pr/PRTabs.css" rel="stylesheet" />
@await Html.PartialAsync("PagesView/PR/_PRTracking")
<script src="~/JsFunctions/PR/PRV7.js"></script>
<script src="~/JsFunctions/PR/PRV8.js"></script>
<script src="~/JsFunctions/PR/PRTabs.js"></script>
@await Html.PartialAsync("PagesView/PR/_PRScripts")
</body>

View File

@ -45,6 +45,6 @@
</div>
</div>
<link href="~/css/pr/trackingdetail.css" rel="stylesheet" />
<script src="~/jsfunctions/pr/DetailedPRTrackingV6.js"></script>
<script src="~/jsfunctions/pr/DetailedPRTrackingV7.js"></script>
@await Html.PartialAsync("PagesView/PR/_PRScripts")
</body>

View File

@ -22,4 +22,4 @@
style="color: green; font-size: 1.5rem; cursor: pointer;" onclick="viewCharges()"></i>
</div>
</div>
</div>
</div>

View File

@ -3,7 +3,7 @@
</div>
<link href="~/css/common/rowhighlighter.css" rel="stylesheet" />
<script src="~/jsfunctions/pr/PRColumnV7.js"></script>
<script src="~/jsfunctions/pr/PRColumnV8.js"></script>
<script src="~/jsfunctions/pr/PRViewV7.js"></script>
<script src="~/jsfunctions/pr/PRPutPost.js"></script>
<script src="~/jsfunctions/pr/PRButtonv3.js"></script>

View File

@ -138,10 +138,6 @@ function validateOTP() {
}
});
}
function enableHideShowButton() {
//Enable the 'btnSendOTP' if success
//Read only input element id="email"
}
function refreshCaptcha() {
const captchaImage = document.getElementById('captchaImage');
captchaImage.src = `/Home/GetCaptcha?ts=${new Date().getTime()}`; // Cache-busting query
@ -302,14 +298,30 @@ function login() {
loader.hide();
},
success: function (response) {
let parsedMessage = null;
if (response && response.responseMessage) {
try {
parsedMessage = JSON.parse(response.responseMessage);
} catch (e) {
console.error("Failed to parse responseMessage", e);
}
}
if (response && response.success === true) {
window.location.href = '/' + response.responseController + '/' + response.responseAction;
} else if (response && response.success === false) {
showToast('error', response.responseMessage, 'Login failed!', 4000);
}
else if (response && response.success === false) {
const errorMessage = parsedMessage?.message || "Login failed.";
showToast('error', errorMessage, 'Login failed!', 4000);
// Highlight inputs if credential-related error
if (errorMessage.toLowerCase().includes('username') ||
errorMessage.toLowerCase().includes('credential')) {
// If login failed due to invalid credentials, highlight username and password
if (response.responseMessage.toLowerCase().includes('username') ||
response.responseMessage.toLowerCase().includes('credential')) {
addErrorClass(userNameInput);
addErrorClass(passwordInput);
}

View File

@ -36,7 +36,7 @@
return;
}
}
console.log('ProjectCodeId', ProjectCodeId);
showConfirmation({
title: 'Purchasing Requisition',
message: 'Are you sure you want to proceed? This action cannot be undone.',

View File

@ -15,6 +15,7 @@
GetForBiddingApproval: "/POMgmt/GetForBiddingApproval",
GetSupplierBidById: "/POMgmt/GetSupplierBidById",
GetPortOfDischarge: "/POMgmt/GetPortOfDischarge",
GetPOListByTerm: "/POMgmt/GetPOListByTerm",
PutPOCancel: "/POMgmt/PutPOCancel",
PutPOItemDetail: "/POMgmt/PutPOItemDetail",

View File

@ -25,36 +25,52 @@ function poTableComponent(id, loader) {
}
});
}
function customFormPOElemComponent(id) {
async function customFormPOElemComponent(id) {
document.getElementById("poNo").readOnly = true;
document.getElementById('customPOHeading').innerHTML = 'Custom P.O. Creation';
populateIncoterms();
populatePOElem(id);
$('#poTypeId').val(id);
$("#supplierName").on('keyup', function () {
$("#supplierName").off('keyup').on('keyup', function () {
populateSupplier();
});
if (!id) {
console.warn("No PO Type selected.");
return;
}
$.ajax({
url: '/POMgmt/GetCustomFormPOElem',
type: 'GET',
data: { id: id },
success: function (response) {
$('#CustomFormPOElemContainer').html(response);
$("#C-paymentTerms").on('keyup', function () {
populateTerms();
});
},
error: function (xhr, status, error) {
console.error("Error loading component:", error);
}
// 1. Load the custom form container FIRST
await new Promise(function (resolve, reject) {
$.ajax({
url: '/POMgmt/GetCustomFormPOElem',
type: 'GET',
data: { id: id },
success: function (response) {
$('#CustomFormPOElemContainer').html(response);
$("#C-paymentTerms").off('keyup').on('keyup', function () {
populateTerms();
});
resolve();
},
error: function (xhr, status, error) {
console.error("Error loading component:", error);
reject(error);
}
});
});
// 2. NOW the hidden inputs exist in DOM — safe to populate
await populatePOElem(id);
// 3. NOW read from those inputs
getPONoType(id);
getPOType(id);
}
function poNoComponent(id) {
/*function poNoComponent(id) {
populatePONoElem(id);
$('#poTypeId').val(id);
}
}*/
function poReportComponent(id) {
return $.ajax({
url: '/POMgmt/GetPOReportTable',

View File

@ -21,6 +21,109 @@
}
});
});
async function fetchAndPopulatePOFormData(poType, poId = null) {
loader = $('#overlay, #loader').css('z-index', 1060);
return new Promise((resolve, reject) => {
$.ajax({
url: '/POMgmt/GetPOFormData',
type: 'GET',
data: { poId: poId },
beforeSend: function () {
loader.show();
},
complete: function () {
loader.hide();
},
success: function (response) {
const d = response;
document.getElementById("poType").value = poType;
$('#poNoFinal').val($('#poNo').val());
// --- Header Fields ---
if (d.header) {
document.getElementById("supplierName").value = d.header.supplierName || '';
$('#supplierId').val(d.header.supplierId || 0);
console.log(d.header.supplierId);
console.log(d.header.supplierName);
$('#deliveryDate').val(d.header.deliveryDate || '');
$('#piDate').val(d.header.profInvoiceDate || '');
$('#piNo').val(d.header.profInvoiceNo || '');
$('#currencyCER').val(d.header.currencyCER || '59.00');
$('#podId').val(d.header.podId || 0);
$('#shippingInstructionId').val(1 || 0);
$('#incotermsName').val(d.header.incoTermsId || 0);
$('#incoTermsId').val(d.header.incoTermsId || 0);
$('#C-paymentTerms').val(d.header.paymentTerms || '');
$('#C-paymentTermsId').val(d.header.paymentTermsId || 0);
$('#remarks').val(d.header.remarks || '');
$('#grossAmountUSD').val(d.header.grossAmountUSD || 0);
$('#finalAmountUSD').val(d.header.finalAmountUSD || 0);
$('#grossAmountPHP').val(d.header.grossAmountPHP || 0);
$('#finalAmountPHP').val(d.header.finalAmountPHP || 0);
}
// --- DataTable: Line Items ---
if (poDataTable) {
poDataTable.clear();
if (d.lineItems && d.lineItems.length > 0) {
poDataTable.rows.add(d.lineItems).draw();
}
}
// --- DataTable: Charges ---
if (d.charges && d.charges.length > 0) {
const $tbody = $('#DestChargesTable tbody');
$tbody.empty(); // clear existing rows first
d.charges.forEach(function (charge) {
var newRow = '<tr>' +
'<td style="display: none;">' + charge.otherChargesId + '</td>' +
'<td>' + charge.otherChargesName + '</td>' +
'<td>' + charge.amount + '</td>' +
'<td><button class="btn btn-default" onclick="removeRow(this)" data-otherChargesId="' + charge.otherChargesId + '">' +
'<i class="fa-solid fa-trash fa-xl" style="color: #ff0000;" aria-hidden="true"></i>' +
'</button></td>' +
'</tr>';
$tbody.append(newRow);
});
// Recalculate after populating charges
calculateFinalPesoAmount($('#poTypeId').val());
calculateFinalUsdAmount();
lessDiscount();
}
// --- Docs Required ---
if (d.docsRequired && d.docsRequired.length > 0) {
$('#docRequiredId').val(
d.docsRequired.map(x => x.docName).join('\n')
);
}
resolve();
},
error: function (xhr, status, error) {
console.error("Error loading PO form data:", error);
reject(error);
}
});
});
}
function enablePONoAutocomplete() {
document.getElementById('customPOHeading').innerHTML = 'Custom P.O. Modification';
customFormPOElemComponent(4);
document.getElementById("poNo").removeAttribute("readonly");
document.getElementById("poNo").value ='';
document.getElementById("poNo").focus();
document.getElementById("poType").value = "0";
popPONo();
}
function lessDiscount() {
let amount = parseFloat($('#finalAmount').val()) || 0;
let discount = parseFloat($('#discount').val()) || 0;

View File

@ -641,18 +641,19 @@ function toggleShippingInstructions() {
}
}
function getPONoType(poType) {
var poNo = '';
if (poType == 1) {
poNo = $('#si-poNo').val();
} else if (poType == 2) {
poNo = $('#dr-poNo').val();
} else {
poNo = $('#si-ImportPoNo').val();
}
$('#c-poNo').val(poNo);
let poTypeNo = '';
if (poType == 1)
poTypeNo = $('#si-poNo').val();
else if (poType == 2)
poTypeNo = $('#dr-poNo').val();
else
poTypeNo = $('#si-ImportPoNo').val();
$('#c-poNo').val(poTypeNo);
}
function getPOType(poType) {
var poNo = '';
if (poType == 1) {
poNo = $('#si-poNo').val();
calculateTotalPesoAmount(1);
@ -665,6 +666,7 @@ function getPOType(poType) {
poNo = $('#si-ImportPoNo').val();
calculateTotalUsdAmount();
}
$('#remarks').val('');
$('#deliveryDate').val('');
$('#poNo').val(poNo);

View File

@ -1,42 +1,123 @@
function populatePONoElem(id) {
loader = $('#overlay, #loader').css('z-index', 1060);
$.ajax($.extend({
url: endpoint.GetLatestPO2,
type: 'POST',
success: function (data) {
if (data && data.data && data.data.length > 0) {
var item = data.data[0];
$('#si-poNo').val('00' + (parseFloat(item.poNoVatInc) + 1));
$('#dr-poNo').val(parseFloat(item.poNoVatEx) + 1);
$('#si-ImportPoNo').val('10-' + (parseFloat(item.ipoNoVatInc) + 1));
$('#dr-ImportPoNo').val(item.ipoNoVatEx);
getPONoType(id);
} else {
console.log('Data is null or undefined');
}
function popPONo() {
$("#poNo").autocomplete({
source: function (request, response) {
$.ajax({
url: endpoint.GetPOListByTerm,
data: { query: request.term },
success: function (result) {
if (result && result.success && Array.isArray(result.data)) {
var formattedData = result.data.map(item => ({
label: item.label || '',
value: item.value !== undefined && item.value !== null ? item.value : 0,
value2: item.value2 !== undefined && item.value2 !== null ? item.value2 : 0
}));
response(formattedData);
} else {
console.error('Invalid data format received:', result);
response([]);
}
}
});
},
error: errorHandler
}, beforeComplete(loader)));
minLength: 2,
select: function (event, ui) {
if (!ui.item || !ui.item.value) {
return false;
}
$('#poNo').val(ui.item.label);
$('#poId').val(ui.item.value);
$('#poTypeId').val(ui.item.value2);
console.log("Selected PO ID:", ui.item.value);
//#1
populatePOModificationForm(ui.item.value2);
fetchAndPopulatePOFormData(ui.item.value2,ui.item.value);
return false;
},
focus: function (event, ui) {
event.preventDefault();
},
open: function () {
var dropdown = $(".ui-autocomplete");
dropdown.css({
"max-height": "200px",
"overflow-y": "auto"
});
},
messages: {
noResults: '',
results: function (count) {
return count + (count > 1 ? ' results' : ' result');
}
}
});
}
async function populatePOModificationForm(id) {
populateIncoterms();
$("#supplierName").off('keyup').on('keyup', function () {
populateSupplier();
});
if (!id) {
console.warn("No PO Type selected.");
return;
}
// 1. Load the custom form container FIRST
await new Promise(function (resolve, reject) {
$.ajax({
url: '/POMgmt/GetCustomFormPOElem',
type: 'GET',
data: { id: id },
success: function (response) {
$('#CustomFormPOElemContainer').html(response);
$("#C-paymentTerms").off('keyup').on('keyup', function () {
populateTerms();
});
resolve();
},
error: function (xhr, status, error) {
console.error("Error loading component:", error);
reject(error);
}
});
});
}
function populatePOElem(id) {
loader = $('#overlay, #loader').css('z-index', 1060);
$.ajax($.extend({
url: endpoint.GetLatestPO2,
type: 'POST',
success: function (data) {
if (data && data.data && data.data.length > 0) {
var item = data.data[0];
$('#si-poNo').val('00' + (parseFloat(item.poNoVatInc) + 1));
$('#dr-poNo').val(parseFloat(item.poNoVatEx) + 1);
$('#si-ImportPoNo').val('10-' + (parseFloat(item.ipoNoVatInc) + 1));
$('#dr-ImportPoNo').val(item.ipoNoVatEx);
getPOType(id);
} else {
console.log('Data is null or undefined');
return new Promise(function (resolve, reject) {
$.ajax($.extend(
beforeComplete(loader),
{
url: endpoint.GetLatestPO2,
type: 'POST',
success: function (data) {
if (data && data.data && data.data.length > 0) {
var item = data.data[0];
$('#si-poNo').val('00' + (parseFloat(item.poNoVatInc) + 1));
$('#dr-poNo').val(parseFloat(item.poNoVatEx) + 1);
$('#si-ImportPoNo').val('10-' + (parseFloat(item.ipoNoVatInc) + 1));
$('#dr-ImportPoNo').val(item.ipoNoVatEx);
resolve(id);
} else {
console.log('Data is null or undefined');
resolve(id);
}
},
error: function (xhr, status, error) {
errorHandler(xhr, status, error);
reject(error);
}
}
},
error: errorHandler
}, beforeComplete(loader)));
));
});
}
function populateIncoterms() {
$.ajax({

View File

@ -17,6 +17,14 @@
tableId: '#PRTable',
dataTable: prTable,
searchableColumns: [
{
columnIndex: 0,
columnName: 'Status',
placeholder: 'Select Status...',
searchType: 'select',
searchMode: 'exact',
width: '150px'
},
{
columnIndex: 1,
columnName: 'PR No',
@ -52,6 +60,7 @@
]
});
const uniqueSearchClass = 'column-search-input-PRTable';
populateSelectOptions(prTable, 0, '.' + uniqueSearchClass + '[data-column="0"]');
populateSelectOptions(prTable, 13, '.' + uniqueSearchClass + '[data-column="13"]');
restoreSearchFromURL(uniqueSearchClass, '#PRTable');
},

View File

@ -96,10 +96,7 @@ var colOnPRTable = [
render: function (data, type, row) {
return renderPRbtns(data, row);
}
},
{ data: 'status', visible: false },
{ data: 'itemCodeId', visible: false },
{ data: 'createdDate', visible: false },
}
];
var colOnAlterOfferTable = [
{ data: 'prNo' },

View File

@ -0,0 +1,176 @@
(function () {
'use strict';
// Tab configuration with table IDs for view components
const tabConfig = {
'pr-list': {
title: 'All Purchase Requests',
tableId: 1,
endpoint: '/PRMgmt/GetTabbedById'
},
'pr-approved': {
title: 'Approved Purchase Requests (No PO)',
tableId: 2,
endpoint: '/PRMgmt/GetTabbedById'
},
'pr-removed': {
title: 'Deleted Purchase Requests',
tableId: 3,
endpoint: '/PRMgmt/GetTabbedById'
}
};
let currentTab = 'pr-list';
let isSwitching = false;
function init() {
const tabs = document.querySelectorAll('.pr-tab-btn');
tabs.forEach(tab => {
tab.addEventListener('click', handleTabClick);
});
// Load initial tab content
loadTabContent('pr-list');
}
function handleTabClick(e) {
if (isSwitching) return;
const btn = e.currentTarget;
const tabId = btn.getAttribute('data-tab');
if (tabId === currentTab) return;
switchTab(tabId, btn);
}
function switchTab(tabId, btn) {
if (!tabConfig[tabId]) {
console.error('Invalid tab ID:', tabId);
return;
}
isSwitching = true;
// Update active states
document.querySelectorAll('.pr-tab-btn').forEach(b => {
b.classList.remove('active');
});
btn.classList.add('active');
// Update title
updateTitle(tabConfig[tabId].title);
// Load view component
loadTabContent(tabId, btn);
currentTab = tabId;
}
function updateTitle(title) {
const titleEl = document.getElementById('pageTitle');
if (!titleEl) return;
// Fade out with slide
titleEl.classList.add('updating');
setTimeout(() => {
titleEl.textContent = title;
// Trigger reflow
void titleEl.offsetWidth;
// Fade in
titleEl.classList.remove('updating');
}, 250);
}
function loadTabContent(tabId, btn = null) {
const config = tabConfig[tabId];
if (!config) {
console.error('Tab config not found:', tabId);
isSwitching = false;
return;
}
// Show loading state
if (btn) {
btn.classList.add('loading');
}
showContainerLoading(true);
// Call your existing function
prTabbedComponent(config.tableId, config.endpoint, function (success) {
// Hide loading state
if (btn) {
btn.classList.remove('loading');
}
showContainerLoading(false);
isSwitching = false;
if (!success) {
console.error('Failed to load tab content');
}
});
}
function showContainerLoading(isLoading) {
const container = document.getElementById('TabbedContainer');
if (!container) return;
if (isLoading) {
container.style.opacity = '0.5';
container.style.pointerEvents = 'none';
} else {
container.style.opacity = '1';
container.style.pointerEvents = 'auto';
}
}
// Initialize on DOM ready
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
// Public API
window.PRTabs = {
switchTo: function (tabId) {
const btn = document.querySelector(`.pr-tab-btn[data-tab="${tabId}"]`);
if (btn && !isSwitching) {
switchTab(tabId, btn);
}
},
reload: function () {
loadTabContent(currentTab);
},
getCurrent: function () {
return currentTab;
},
addTab: function (tabId, config) {
// Dynamically add new tab configuration
tabConfig[tabId] = config;
}
};
})();
// Updated prTabbedComponent to work with callback
function prTabbedComponent(id, endpoint, callback) {
$.ajax({
url: endpoint,
type: 'GET',
data: { TableId: id }, // Note: capital T to match your controller parameter
success: function (response) {
$('#TabbedContainer').html(response);
if (callback) callback(true);
},
error: function (xhr, status, error) {
console.error("Error loading component:", error);
$('#TabbedContainer').html('<div class="alert alert-danger">Failed to load content. Please try again.</div>');
if (callback) callback(false);
}
});
}

View File

@ -18,7 +18,7 @@
data: { ItemNo: ItemNo, Status: Status, PRDetailsId: PRDetailsId, Remarks: Remarks },
success: function (response) {
if (response.success) {
getApproverName(PRDetailsId);
getApproverName(PRDetailsId,0);
prDataTable.ajax.reload(null, false);
isApproval = true;
@ -46,14 +46,14 @@
});
}
$(document).ready(function () {
/*$(document).ready(function () {
loader = $('#overlay, #loader');
UserRights = document.getElementById("roleRights").value;
prTable = $('#PRTable').DataTable({
ajax: {
url: '/PRMgmt/GetAllPR',
url: '/PRMgmt/GetAllPR', // Initial endpoint
type: 'GET',
beforeSend: function () {
// Show the loader before making the AJAX request
@ -61,19 +61,49 @@ $(document).ready(function () {
},
complete: function () {
loader.hide();
},
error: function (xhr, error, thrown) {
loader.hide();
console.error('Error loading data:', error);
// Optional: Show error notification
if (typeof toastr !== 'undefined') {
toastr.error('Failed to load data. Please try again.');
}
}
},
initComplete: initCompleteCallback,
columns: colOnPRTable,
order: [10, 'asc'],
order: [[10, 'asc']],
rowCallback: rowStatusColorCallback,
responsive: true,
language: {
emptyTable: "No record available"
emptyTable: "No record available",
loadingRecords: "Loading data...",
processing: "Processing..."
},
error: errorHandler
});
})
// Initialize tabs after DataTable is ready
// The PRTabs.js script will handle tab switching and DataTable reloading
});*/
// Optional: Add helper function to refresh current tab
function refreshCurrentTab() {
if (typeof PRTabs !== 'undefined') {
PRTabs.reload();
} else if (prTable) {
prTable.ajax.reload();
}
}
// Optional: Add helper to switch tabs programmatically
function switchToPRTab(tabName) {
if (typeof PRTabs !== 'undefined') {
PRTabs.switchToTab(tabName);
}
}
function submitItem() {
loader = $('#overlay, #loader');
@ -269,4 +299,14 @@ function checkExistingAttachment() {
} else {
existingAttachment = false;
}
}
function getFormattedDateTime() {
const now = new Date();
const yyyy = now.getFullYear();
const mm = String(now.getMonth() + 1).padStart(2, '0');
const dd = String(now.getDate()).padStart(2, '0');
const hh = String(now.getHours()).padStart(2, '0');
const min = String(now.getMinutes()).padStart(2, '0');
const ss = String(now.getSeconds()).padStart(2, '0');
return `${yyyy}-${mm}-${dd}_${hh}${min}${ss}`;
}

View File

@ -55,29 +55,30 @@
modal.modal('show');
}
function getApproverName(prDetailsId) {
PRDetailsId = prDetailsId;
function getApproverName(prDetailsId, prNo) {
const endPoint = (prNo === 0 || prNo === undefined) ? '/PRMgmt/GetApproverName'
: '/PRMgmt/GetApproverNameByPRNo';
$.ajax({
url: '/PRMgmt/GetApproverName',
url: endPoint,
type: 'POST',
data: { PRDetailsId },
success: function (data) {
if (data && data.data && data.data.length > 0) {
var item = data.data[0];
data: { prDetailsId, prNo },
success: function (response) {
if (response && response.data && response.data.length > 0) {
const item = response.data[0];
const attestedBy = document.getElementById('label-pr-attestedBy');
const approveBy = document.getElementById('label-pr-approvedBy');
if (attestedBy) {
attestedBy.innerHTML = item.attestedBy;
}
if (approveBy) {
approveBy.innerHTML = item.approvedBy;
}
// Security: Use textContent to prevent XSS
if (attestedBy) attestedBy.textContent = item.attestedBy || '';
if (approveBy) approveBy.textContent = item.approvedBy || '';
}
},
error: errorHandler
});
}
function printPRItem() {
const iframe = document.createElement('iframe');
iframe.style.position = 'fixed';
@ -506,7 +507,7 @@ function viewPRStatusById(data) {
} else {
var imageUrl = item.url + itemPicturePath;
//console.log('imageUrl', imageUrl);
$('#t-itemPictureImage').attr('src', imageUrl);
}
@ -684,8 +685,8 @@ function enableDisableInput(isDenied, dynamicBtn) {
document.getElementById('itemLocalName'),
document.getElementById('itemClassId'),
document.getElementById('prTypeId'),
document.getElementById('itemQty'),//btnUpdateItem
/* document.getElementById('btnUpdateItem'),*/
document.getElementById('itemQty'),
];
inputs.forEach(function (input) {
if (input) {
@ -711,9 +712,19 @@ function viewPRDetails(data) {
tableDestroy(tableElement);
var PRNo = data.prNo;
getApproverName(0, PRNo);
$('#prId').val(data.prId);
// Populate PR header details
const allowedRoles = ['Approver1', 'Approver2', 'POApprover'];
if (allowedRoles.includes(UserRights)) {
document.getElementById('btnSubmitItem').style.display = 'block';
} else {
document.getElementById('btnSubmitItem').style.display = 'none';
}
populatePRHeader(data);
prDataTable = tableElement.DataTable({
@ -789,14 +800,12 @@ function toggleAttachment(rowWithFile) {
function downloadPRAttachment() {
let fileName = $('#fileName').val();
// Append parameters to URL for GET requests
const params = new URLSearchParams({ fileName: fileName });
const url = `/PRMgmt/GetPRAttachment?${params.toString()}`;
fetch(url, { method: 'GET' })
.then(response => {
if (!response.ok) {
// If backend returns 500 or 400, it won't be a blob
throw new Error("Failed to download file");
}
return response.blob();

View File

@ -0,0 +1,217 @@
/* Tab Header Container */
.pr-tabs-header {
background: teal;
border-bottom: 1px solid #00695c;
margin: -1rem -1rem 0 -1rem;
padding: 0;
border-radius: 15px 10px 0 0;
}
/* Tab Navigation */
.pr-tabs-nav {
display: flex;
gap: 0;
align-items: stretch;
padding: 0;
}
/* Individual Tab Button */
.pr-tab-btn {
flex: 0 0 auto;
padding: 14px 32px;
background: transparent;
border: none;
border-bottom: 3px solid transparent;
color: white;
font-size: 15px;
font-weight: 500;
border-radius: 15px 0px 0 0;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
position: relative;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
letter-spacing: 0.3px;
}
/* Tab Hover State */
.pr-tab-btn:hover {
background: rgba(255, 255, 255, 0.15);
color: white;
}
/* Active Tab */
.pr-tab-btn.active {
background: white;
color: teal;
font-weight: 600;
border-bottom-color: white;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}
/* Active Tab Accent Line */
.pr-tab-btn.active::before {
content: '';
position: absolute;
bottom: -3px;
left: 0;
right: 0;
height: 3px;
background: white;
}
/* Loading State */
.pr-tab-btn.loading {
pointer-events: none;
opacity: 0.6;
}
.pr-tab-btn.loading::after {
content: '';
position: absolute;
right: 12px;
top: 50%;
transform: translateY(-50%);
width: 12px;
height: 12px;
border: 2px solid currentColor;
border-top-color: transparent;
border-radius: 50%;
animation: spin 0.7s linear infinite;
}
@keyframes spin {
to {
transform: translateY(-50%) rotate(360deg);
}
}
.page-header-section {
padding: 24px 0 16px 0;
}
.page-heading {
margin: 0;
font-size: 28px;
font-weight: 600;
color: teal;
text-align: left;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
letter-spacing: -0.5px;
position: relative;
padding-bottom: 12px;
}
/* Subtle Accent Line Under Heading */
.page-heading::after {
content: '';
position: absolute;
bottom: 0;
left: 0;
width: 60px;
height: 3px;
background: teal;
border-radius: 2px;
}
/* Title Transition Animation */
.page-heading {
transition: opacity 0.25s ease, transform 0.25s ease;
}
.page-heading.updating {
opacity: 0;
transform: translateX(-10px);
}
/* Table Container Adjustments */
.table-container {
margin-top: -15px !important;
overflow: hidden;
}
/* Ensure table container has proper border radius */
.table-container.rounded {
border-radius: 5px !important;
}
/* Responsive Design */
@media (max-width: 768px) {
.pr-tabs-nav {
overflow-x: auto;
-webkit-overflow-scrolling: touch;
}
.pr-tab-btn {
padding: 12px 24px;
font-size: 14px;
white-space: nowrap;
}
.page-heading {
font-size: 24px;
}
.page-header-section {
padding: 20px 0 12px 0;
}
}
@media (max-width: 576px) {
.pr-tab-btn {
padding: 10px 20px;
font-size: 13px;
}
.page-heading {
font-size: 22px;
}
.page-header-section {
padding: 16px 0 10px 0;
}
}
/* Smooth scrollbar for mobile tabs */
.pr-tabs-nav::-webkit-scrollbar {
height: 3px;
}
.pr-tabs-nav::-webkit-scrollbar-track {
background: #e0f2f1;
}
.pr-tabs-nav::-webkit-scrollbar-thumb {
background: #80cbc4;
border-radius: 10px;
}
.pr-tabs-nav::-webkit-scrollbar-thumb:hover {
background: #4db6ac;
}
/* Enhanced Table Styling */
#PRTable {
margin-top: 0 !important;
}
/* Focus States for Accessibility */
.pr-tab-btn:focus {
outline: 2px solid white;
outline-offset: -2px;
}
.pr-tab-btn:focus:not(:focus-visible) {
outline: none;
}
/* Print Styles */
@media print {
.pr-tabs-header {
display: none;
}
.page-heading::after {
display: none;
}
}