diff --git a/CPRNIMS.Domain/CPRNIMS.Domain.csproj b/CPRNIMS.Domain/CPRNIMS.Domain.csproj index cb1b764..ae1b559 100644 --- a/CPRNIMS.Domain/CPRNIMS.Domain.csproj +++ b/CPRNIMS.Domain/CPRNIMS.Domain.csproj @@ -8,6 +8,7 @@ + diff --git a/CPRNIMS.Domain/Contracts/PO/IPurchaseOrder.cs b/CPRNIMS.Domain/Contracts/PO/IPurchaseOrder.cs index 6474bfd..fb65b5c 100644 --- a/CPRNIMS.Domain/Contracts/PO/IPurchaseOrder.cs +++ b/CPRNIMS.Domain/Contracts/PO/IPurchaseOrder.cs @@ -15,6 +15,8 @@ namespace CPRNIMS.Domain.Contracts.PO public interface IPurchaseOrder { #region Get + Task GetPOFormDataAsync(long? poId); + Task> GetPOListByTerm(PODto itemDto); Task> GetIncomingShipment(PODto itemDto); Task> GetIndexCard(PODto poDto); Task> GetForPOApprovalByPRNo(PODto PODto); diff --git a/CPRNIMS.Domain/Services/PO/PurchaseOrder.cs b/CPRNIMS.Domain/Services/PO/PurchaseOrder.cs index a098b7e..2dc2b9a 100644 --- a/CPRNIMS.Domain/Services/PO/PurchaseOrder.cs +++ b/CPRNIMS.Domain/Services/PO/PurchaseOrder.cs @@ -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 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(), + LineItems = (await multi.ReadAsync()).ToList(), + Charges = (await multi.ReadAsync()).ToList(), + DocsRequired = (await multi.ReadAsync()).ToList() + }; + } public async Task> GetIncoterms(PODto itemDto) { return await _dbContext.Incoterms.ToListAsync(); @@ -41,21 +66,13 @@ namespace CPRNIMS.Domain.Services.PO } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetPRWOCanvass(PODto itemDto) { @@ -69,55 +86,31 @@ namespace CPRNIMS.Domain.Services.PO } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return createdPOs ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return createdPOs ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetApprovedPOPerEmail(PODto PODto) { @@ -134,24 +127,16 @@ namespace CPRNIMS.Domain.Services.PO } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetDocRequired(PODto pODto) { @@ -160,103 +145,54 @@ namespace CPRNIMS.Domain.Services.PO } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetLatestPO(PODto pODto) { - try - { - var allItems = await _dbContext.CentralPONos + var allItems = await _dbContext.CentralPONos .FromSqlRaw($"EXEC GetLatestPO") .ToListAsync(); - return allItems ?? new List(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetLatestPO2(PODto pODto) { @@ -345,25 +281,15 @@ namespace CPRNIMS.Domain.Services.PO } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> 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(); - } - catch (SqlException ex) - { - ex.ToString(); - throw; - } + return allItems ?? new List(); } public async Task> GetPRPOSummaryReport(PODto itemDto) { @@ -420,170 +340,130 @@ namespace CPRNIMS.Domain.Services.PO return allItems ?? new List(); } + public async Task> 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 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 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 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 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 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 PostPutCustomPO(PODto pODto) { @@ -693,107 +573,68 @@ namespace CPRNIMS.Domain.Services.PO } public async Task 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 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 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 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 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> GetPOItemDetail(PODto pODto) { @@ -909,103 +750,71 @@ namespace CPRNIMS.Domain.Services.PO } public async Task 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 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 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 } } diff --git a/CPRNIMS.Domain/UIContracts/PO/ICustomPOService.cs b/CPRNIMS.Domain/UIContracts/PO/ICustomPOService.cs new file mode 100644 index 0000000..f1bf3fc --- /dev/null +++ b/CPRNIMS.Domain/UIContracts/PO/ICustomPOService.cs @@ -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 GetPOFormDataAsync(long? poId = null); + } +} diff --git a/CPRNIMS.Domain/UIContracts/PO/IPurchaseOrder.cs b/CPRNIMS.Domain/UIContracts/PO/IPurchaseOrder.cs index 6517421..fc84e34 100644 --- a/CPRNIMS.Domain/UIContracts/PO/IPurchaseOrder.cs +++ b/CPRNIMS.Domain/UIContracts/PO/IPurchaseOrder.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace CPRNIMS.Domain.UIContracts.PO { - public interface IPurchaseOrder + public interface IPurchaseOrder { #region Get Task> GetSupplierBidById(User user, POVM viewModel); @@ -40,6 +40,7 @@ namespace CPRNIMS.Domain.UIContracts.PO Task?> GetIndexCard(User user, POVM viewModel); Task?> GetPortOfDischarge(User user, POVM viewModels); Task?> GetIncomingShipment(User user, POVM viewModels); + Task?> GetPOListByTerm(User user, POVM viewModels); #endregion #region Post Put Task PostApprovedSupplier(User user, POVM viewModel); diff --git a/CPRNIMS.Domain/UIServices/PO/CustomPOService.cs b/CPRNIMS.Domain/UIServices/PO/CustomPOService.cs new file mode 100644 index 0000000..7a9c563 --- /dev/null +++ b/CPRNIMS.Domain/UIServices/PO/CustomPOService.cs @@ -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 _logger; + + public CustomPOService( + IHttpClientFactory httpClientFactory, + TokenHelper tokenHelper, + IConfiguration configuration, + ILogger logger) + { + _httpClientFactory = httpClientFactory; + _tokenHelper = tokenHelper; + _configuration = configuration; + _logger = logger; + } + + public async Task 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(json, new JsonSerializerOptions + { + PropertyNameCaseInsensitive = true + }); + + return result ?? new POFormData(); + } + catch (Exception ex) + { + _logger.LogError(ex, "Error in GetPOFormDataAsync"); + return new POFormData(); + } + } + } +} diff --git a/CPRNIMS.Domain/UIServices/PO/PurchaseOrder.cs b/CPRNIMS.Domain/UIServices/PO/PurchaseOrder.cs index b59320a..8ba3416 100644 --- a/CPRNIMS.Domain/UIServices/PO/PurchaseOrder.cs +++ b/CPRNIMS.Domain/UIServices/PO/PurchaseOrder.cs @@ -126,6 +126,12 @@ namespace CPRNIMS.Domain.UIServices.PO #endregion #region Get + + public async Task?> GetPOListByTerm(User user, POVM viewModel) + { + return await SendGetApiRequest(user, viewModel, + _configuration["LLI:NonInvent:POMgmt:GetPOListByTerm"]); + } public async Task?> GetIncomingShipment(User user, POVM viewModel) { return await SendGetApiRequest(user, viewModel, diff --git a/CPRNIMS.Infrastructure/Entities/PO/PO.cs b/CPRNIMS.Infrastructure/Entities/PO/PO.cs index e018523..c352178 100644 --- a/CPRNIMS.Infrastructure/Entities/PO/PO.cs +++ b/CPRNIMS.Infrastructure/Entities/PO/PO.cs @@ -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; } } } diff --git a/CPRNIMS.Infrastructure/Entities/PO/POCharges.cs b/CPRNIMS.Infrastructure/Entities/PO/POCharges.cs new file mode 100644 index 0000000..2ec1c6b --- /dev/null +++ b/CPRNIMS.Infrastructure/Entities/PO/POCharges.cs @@ -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; } + } +} diff --git a/CPRNIMS.Infrastructure/Entities/PO/POFormData.cs b/CPRNIMS.Infrastructure/Entities/PO/POFormData.cs new file mode 100644 index 0000000..7489be6 --- /dev/null +++ b/CPRNIMS.Infrastructure/Entities/PO/POFormData.cs @@ -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? LineItems { get; set; } + public List? Charges { get; set; } + public List? DocsRequired { get; set; } + } +} diff --git a/CPRNIMS.Infrastructure/Entities/PO/POHeader.cs b/CPRNIMS.Infrastructure/Entities/PO/POHeader.cs new file mode 100644 index 0000000..ef5ab22 --- /dev/null +++ b/CPRNIMS.Infrastructure/Entities/PO/POHeader.cs @@ -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; } + } +} diff --git a/CPRNIMS.Infrastructure/Entities/PO/POLineItem.cs b/CPRNIMS.Infrastructure/Entities/PO/POLineItem.cs new file mode 100644 index 0000000..a75b3ff --- /dev/null +++ b/CPRNIMS.Infrastructure/Entities/PO/POLineItem.cs @@ -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; } + + } +} diff --git a/CPRNIMS.Infrastructure/Helper/TokenHelper.cs b/CPRNIMS.Infrastructure/Helper/TokenHelper.cs index 70f9fa5..594c216 100644 --- a/CPRNIMS.Infrastructure/Helper/TokenHelper.cs +++ b/CPRNIMS.Infrastructure/Helper/TokenHelper.cs @@ -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 DefaultHeaders - { - get - { - var headersSection = _configuration.GetSection( - "CommonEndpoints:ApiDefaultHeaders"); - var headers = new Dictionary(); - - foreach (var childSection in headersSection.GetChildren()) - { - headers[childSection.Key] = childSection.Value; - } - - return headers; - } - } - public Dictionary CustomHeaders { get diff --git a/CPRNIMS.WebApi/CPRNIMS.WebApi.csproj b/CPRNIMS.WebApi/CPRNIMS.WebApi.csproj index 6ceb148..753cb2d 100644 --- a/CPRNIMS.WebApi/CPRNIMS.WebApi.csproj +++ b/CPRNIMS.WebApi/CPRNIMS.WebApi.csproj @@ -147,7 +147,6 @@ - diff --git a/CPRNIMS.WebApi/Controllers/Account/AnonController.cs b/CPRNIMS.WebApi/Controllers/Account/AnonController.cs index 3efef2e..2d8ef74 100644 --- a/CPRNIMS.WebApi/Controllers/Account/AnonController.cs +++ b/CPRNIMS.WebApi/Controllers/Account/AnonController.cs @@ -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 Login([FromBody] LoginRequest model, diff --git a/CPRNIMS.WebApi/Controllers/PO/POMgmtController.cs b/CPRNIMS.WebApi/Controllers/PO/POMgmtController.cs index 32196fd..3484ced 100644 --- a/CPRNIMS.WebApi/Controllers/PO/POMgmtController.cs +++ b/CPRNIMS.WebApi/Controllers/PO/POMgmtController.cs @@ -279,6 +279,20 @@ namespace CPRNIMS.WebApi.Controllers.PO } #endregion #region Get + [HttpGet("GetPOFormData")] + public async Task GetPOFormData(int? poId = null) + { + var data = await _purchaseOrder.GetPOFormDataAsync(poId); + return Ok(data); + } + [HttpPost("GetPOListByTerm")] + public async Task GetPOListByTerm(PODto itemDto) + { + return await ExecuteWithErrorHandling( + () => _purchaseOrder.GetPOListByTerm(itemDto), + nameof(GetPOListByTerm), false + ); + } [HttpPost("GetIncomingShipment")] public async Task GetIncomingShipment(PODto itemDto) { diff --git a/CPRNIMS.WebApps/Common/ServiceExtensions.cs b/CPRNIMS.WebApps/Common/ServiceExtensions.cs index 9fb20c3..3d5257f 100644 --- a/CPRNIMS.WebApps/Common/ServiceExtensions.cs +++ b/CPRNIMS.WebApps/Common/ServiceExtensions.cs @@ -81,7 +81,8 @@ namespace CPRNIMS.WebApps.Common builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); - builder.Services.AddTransient(); + builder.Services.AddTransient(); + builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); builder.Services.AddTransient(); diff --git a/CPRNIMS.WebApps/Controllers/PO/POMgmtController.cs b/CPRNIMS.WebApps/Controllers/PO/POMgmtController.cs index d7dff48..454c8e8 100644 --- a/CPRNIMS.WebApps/Controllers/PO/POMgmtController.cs +++ b/CPRNIMS.WebApps/Controllers/PO/POMgmtController.cs @@ -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) { 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 GetPOFormData(long? poId = null) + { + var data = await _customPOService.GetPOFormDataAsync(poId); + return Ok(data); + } public async Task 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 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 GetPOListByTerm(string query) + { + var viewModels = new POVM(); + viewModels.PONo = query; + response = await _purchaseOrder.GetPOListByTerm(GetUser(), viewModels); + if (response == null) + { + response = new List(); + } + 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 GetPaymentTerms(string query) { var viewModels = new POVM(); diff --git a/CPRNIMS.WebApps/ViewComponents/POMgmt/CustomFormPOElemVC.cs b/CPRNIMS.WebApps/ViewComponents/POMgmt/CustomFormPOElemVC.cs index ca7ce7a..cdcdd96 100644 --- a/CPRNIMS.WebApps/ViewComponents/POMgmt/CustomFormPOElemVC.cs +++ b/CPRNIMS.WebApps/ViewComponents/POMgmt/CustomFormPOElemVC.cs @@ -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); diff --git a/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/ImportElem.cshtml b/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/ImportElem.cshtml index c76aa8d..eb1e801 100644 --- a/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/ImportElem.cshtml +++ b/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/ImportElem.cshtml @@ -216,5 +216,3 @@ @await Html.PartialAsync("PagesView/PO/_DocRequired") - - diff --git a/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/PODetailModification.cshtml b/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/PODetailModification.cshtml new file mode 100644 index 0000000..18758ea --- /dev/null +++ b/CPRNIMS.WebApps/Views/Components/POMgmt/CustomPO/PODetailModification.cshtml @@ -0,0 +1,28 @@ +
+ + +
+
+
+ ⚠ +
+
+

+ You Are Modifying an Existing Purchase Order +

+

+ Any changes made here will directly affect supplier commitments, and financial reports. + Please review all details carefully before saving. +

+
+
+
+ + +
+ Important: + Ensure that all quantities, prices, delivery dates, and supplier details are accurate. + Any incorrect modifications may result in discrepancies and processing issues. +
+ +
\ No newline at end of file diff --git a/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/AllPR.cshtml b/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/AllPR.cshtml index 12584b9..53decbd 100644 --- a/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/AllPR.cshtml +++ b/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/AllPR.cshtml @@ -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, diff --git a/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/ApprovedPR.cshtml b/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/ApprovedPR.cshtml index d91d38d..671c8f1 100644 --- a/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/ApprovedPR.cshtml +++ b/CPRNIMS.WebApps/Views/Components/PRMgmt/PRTabbedTable/ApprovedPR.cshtml @@ -24,8 +24,8 @@ + diff --git a/CPRNIMS.WebApps/Views/POMgmt/CustomPO.cshtml b/CPRNIMS.WebApps/Views/POMgmt/CustomPO.cshtml index 7ed1a1c..d8165c5 100644 --- a/CPRNIMS.WebApps/Views/POMgmt/CustomPO.cshtml +++ b/CPRNIMS.WebApps/Views/POMgmt/CustomPO.cshtml @@ -2,21 +2,25 @@
-

Custom P.O. Creation

+

Custom P.O. Creation

-
- - -
+
+ + + + +
- +
diff --git a/CPRNIMS.WebApps/Views/POMgmt/PutPONo.cshtml b/CPRNIMS.WebApps/Views/POMgmt/PutPONo.cshtml index c34c983..520f60d 100644 --- a/CPRNIMS.WebApps/Views/POMgmt/PutPONo.cshtml +++ b/CPRNIMS.WebApps/Views/POMgmt/PutPONo.cshtml @@ -159,7 +159,7 @@ - + @await Html.PartialAsync("PagesView/PR/_PRScripts") \ No newline at end of file diff --git a/CPRNIMS.WebApps/Views/Shared/PagesView/PO/_OtherCharges.cshtml b/CPRNIMS.WebApps/Views/Shared/PagesView/PO/_OtherCharges.cshtml index f4bf03b..62c36bc 100644 --- a/CPRNIMS.WebApps/Views/Shared/PagesView/PO/_OtherCharges.cshtml +++ b/CPRNIMS.WebApps/Views/Shared/PagesView/PO/_OtherCharges.cshtml @@ -22,4 +22,4 @@ style="color: green; font-size: 1.5rem; cursor: pointer;" onclick="viewCharges()">
-
+
\ No newline at end of file diff --git a/CPRNIMS.WebApps/Views/Shared/PagesView/PR/_PRScripts.cshtml b/CPRNIMS.WebApps/Views/Shared/PagesView/PR/_PRScripts.cshtml index 6c419a6..7485d0d 100644 --- a/CPRNIMS.WebApps/Views/Shared/PagesView/PR/_PRScripts.cshtml +++ b/CPRNIMS.WebApps/Views/Shared/PagesView/PR/_PRScripts.cshtml @@ -3,7 +3,7 @@
- + diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV3.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV4.js similarity index 94% rename from CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV3.js rename to CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV4.js index 0257814..29ad721 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV3.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/Account/loginV4.js @@ -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); } diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/Items/PostPutItemV4.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/Items/PostPutItemV4.js index 911952a..149b529 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/Items/PostPutItemV4.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/Items/PostPutItemV4.js @@ -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.', diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ApiV3.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ApiV3.js index 2007202..63a7305 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ApiV3.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ApiV3.js @@ -15,6 +15,7 @@ GetForBiddingApproval: "/POMgmt/GetForBiddingApproval", GetSupplierBidById: "/POMgmt/GetSupplierBidById", GetPortOfDischarge: "/POMgmt/GetPortOfDischarge", + GetPOListByTerm: "/POMgmt/GetPOListByTerm", PutPOCancel: "/POMgmt/PutPOCancel", PutPOItemDetail: "/POMgmt/PutPOItemDetail", diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ComponentsV2.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ComponentsV2.js index bcf6d72..7e73bf1 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ComponentsV2.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/ComponentsV2.js @@ -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', diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/CustomPOV5.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/CustomPOV5.js index 7211282..2b0f82c 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/CustomPOV5.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/CustomPOV5.js @@ -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 = '' + + '' + charge.otherChargesId + '' + + '' + charge.otherChargesName + '' + + '' + charge.amount + '' + + '' + + ''; + $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; diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/POViewV4.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/POViewV4.js index 6f7abe7..41e85fb 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/POViewV4.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/POViewV4.js @@ -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); diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/PopulateDopdownV2.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/PopulateDopdownV2.js index 8069c23..ff3dfc1 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/PopulateDopdownV2.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PO/PopulateDopdownV2.js @@ -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({ diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV6.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV7.js similarity index 89% rename from CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV6.js rename to CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV7.js index 4b49948..2e55f13 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV6.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/DetailedPRTrackingV7.js @@ -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'); }, diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV7.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV8.js similarity index 97% rename from CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV7.js rename to CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV8.js index e86aca6..f87e789 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV7.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRColumnV8.js @@ -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' }, diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRTabs.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRTabs.js new file mode 100644 index 0000000..3d55e70 --- /dev/null +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRTabs.js @@ -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('
Failed to load content. Please try again.
'); + if (callback) callback(false); + } + }); +} \ No newline at end of file diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV6.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV8.js similarity index 84% rename from CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV6.js rename to CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV8.js index 51100d9..123b68f 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV6.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRV8.js @@ -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}`; } \ No newline at end of file diff --git a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV6.js b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV7.js similarity index 96% rename from CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV6.js rename to CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV7.js index b534b5a..15a9d28 100644 --- a/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV6.js +++ b/CPRNIMS.WebApps/wwwroot/JsFunctions/PR/PRViewV7.js @@ -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(); diff --git a/CPRNIMS.WebApps/wwwroot/css/PR/PRTabs.css b/CPRNIMS.WebApps/wwwroot/css/PR/PRTabs.css new file mode 100644 index 0000000..28c3801 --- /dev/null +++ b/CPRNIMS.WebApps/wwwroot/css/PR/PRTabs.css @@ -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; + } +} \ No newline at end of file