AI-Driven Supplier Search & Tagging
This commit is contained in:
parent
ee0f853a85
commit
3825a986f6
@ -7,6 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper" Version="16.1.1" />
|
||||
<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" />
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass;
|
||||
using CPRNIMS.Domain.Services.ICanvass;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using CPRNIMS.Infrastructure.Entities.Canvass;
|
||||
using CPRNIMS.Infrastructure.Entities.Purchasing;
|
||||
using System;
|
||||
@ -9,46 +12,46 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Domain.Contracts.Canvass
|
||||
{
|
||||
public interface ICanvass
|
||||
public interface ICanvass : ISupplier
|
||||
{
|
||||
#region Post Put
|
||||
Task<RFQ> PostPerSupplierToken(CanvassDto CanvassDto);
|
||||
Task<ForCanvassFollowUp> PutSupplierCanvass(long canvassSupplierId);
|
||||
Task<PRDetails> PostCanvass(CanvassDto CanvassDto);
|
||||
Task<Suppliers> PostPutSupplier(CanvassDto CanvassDto);
|
||||
Task<Suppliers> PostTaggingSupplier(CanvassDto CanvassDto);
|
||||
Task<Suppliers> PostApprovedSupp(CanvassDto CanvassDto);
|
||||
Task<PRCanvassDetail> PostCanvass(CanvassDto CanvassDto);
|
||||
Task<SupplierResponse> PostPutSupplier(CanvassDto CanvassDto);
|
||||
Task<SupplierResponse> PostTaggingSupplier(CanvassDto CanvassDto);
|
||||
Task<SupplierResponse> PostApprovedSupp(CanvassDto CanvassDto);
|
||||
Task<CanvassDetail> PostSuggestedSupp(CanvassDto CanvassDto);
|
||||
Task<CanvassDetail> PutSuppUnitPrice(CanvassDto CanvassDto);
|
||||
Task<CanvassDetail> PutSuppBidDetails(CanvassDto canvassDto);
|
||||
Task<Suppliers> PostPutMySupplier(CanvassDto canvassDto);
|
||||
Task<Suppliers> PostPutItemTagging(CanvassDto canvassDto);
|
||||
Task<SupplierResponse> PostPutMySupplier(CanvassDto canvassDto);
|
||||
Task<SupplierResponse> PostPutItemTagging(CanvassDto canvassDto);
|
||||
Task<CanvassSupplier> UnlockFormLink(CanvassDto canvassDto);
|
||||
#endregion
|
||||
#region Get
|
||||
Task<List<PRDetails>> GetCanvassById(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetCanvassById(CanvassDto CanvassDto);
|
||||
Task<List<WOResponse>> GetCanvassWOResponse(CanvassDto CanvassDto);
|
||||
Task<List<WOResponseById>> GetWOResponseBySuppId(CanvassDto CanvassDto);
|
||||
Task<List<Suppliers>> GetSupplierById(CanvassDto CanvassDto);
|
||||
Task<List<SupplierResponse>> GetSupplierById(CanvassDto CanvassDto);
|
||||
Task<List<RFQReference>> GetRFQ(CanvassDto CanvassDto);
|
||||
Task<List<BiddingItem>> GetSupplierBid(CanvassDto CanvassDto);
|
||||
Task<List<RFQPerSupplier>> GetSupplierBidByItem(CanvassDto CanvassDto);
|
||||
Task<List<SupplierBidById>> GetSupplierBidById(CanvassDto CanvassDto);
|
||||
Task<List<PerSupplier>> GetCanvassPerSupplier(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetCanvassPerSupplierId(CanvassDto itemCodeDto);
|
||||
Task<List<PRCanvassDetail>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetCanvassPerSupplierId(CanvassDto itemCodeDto);
|
||||
Task<List<ItemListWOEmail>> GetItemSupplierWOEmail(CanvassDto CanvassDto);
|
||||
Task<List<Suppliers>> GetSupplierItemWOEmail(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetCanvassByPRNo(CanvassDto CanvassDto);
|
||||
Task<List<SupplierResponse>> GetSupplierItemWOEmail(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetCanvassByPRNo(CanvassDto CanvassDto);
|
||||
Task<List<CanvassGroupByPRNo>> GetCanvassGroupByPRNo(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetCanvassByItemNo(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetPRItemList(CanvassDto CanvassDto);
|
||||
Task<List<PRDetails>> GetPRItem(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetCanvassByItemNo(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetPRItemList(CanvassDto CanvassDto);
|
||||
Task<List<PRCanvassDetail>> GetPRItem(CanvassDto CanvassDto);
|
||||
Task<List<Infrastructure.Entities.Canvass.PRList>> GetPRListByPRNo(CanvassDto canvassDto);
|
||||
Task<List<ForCanvass>> GetForCanvassPerItem(CanvassDto CanvassDto);
|
||||
Task<int> GetCanvassNo();
|
||||
Task<List<ForCanvassFollowUp>> GetCanvassForFollowUp(CanvassDto itemDto);
|
||||
Task<List<Suppliers>> GetMySuppliers(CanvassDto CanvassDto);
|
||||
Task<List<SupplierResponse>> GetMySuppliers(CanvassDto CanvassDto);
|
||||
Task<List<MyPRWOCanvass>> GetMyPRWOCanvass(CanvassDto itemDto);
|
||||
Task<List<AlternativeOfferDetails>> GetAlternativeOfferByPRDetailId(CanvassDto itemDto);
|
||||
Task<List<AllForCanvass>> GetAllForCanvass();
|
||||
|
||||
19
CPRNIMS.Domain/Contracts/Canvass/ISupplier.cs
Normal file
19
CPRNIMS.Domain/Contracts/Canvass/ISupplier.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using CPRNIMS.Infrastructure.Entities.Purchasing;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Domain.Services.ICanvass
|
||||
{
|
||||
public interface ISupplier
|
||||
{
|
||||
Task<List<ItemWithoutSupplier>> GetItemWithoutSupplier();
|
||||
Task<Result<SupplierResponse>> PostSupplierAsync(SupplierRequest request, CancellationToken ct);
|
||||
Task SendRFQ(SupplierEmailRequest supplierEmailRequest);
|
||||
Task<bool> SearchingUpdate(long pRDetailsId);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,6 @@
|
||||
using CPRNIMS.Infrastructure.Dto.Items;
|
||||
using CPRNIMS.Infrastructure.Dto.PR;
|
||||
using CPRNIMS.Infrastructure.Dto.PR.Response;
|
||||
using CPRNIMS.Infrastructure.Entities.Common;
|
||||
using CPRNIMS.Infrastructure.Entities.Purchasing;
|
||||
using CPRNIMS.Infrastructure.Entities.SMTP;
|
||||
@ -36,11 +37,11 @@ namespace CPRNIMS.Domain.Contracts.PR
|
||||
Task<PagedResult<DeletedPR>> GetDeletedPR(PRDto pRDto);
|
||||
Task<PagedResult<ApprovedPR>> GetApprovedPR(PRDto pRDto);
|
||||
Task<MessageResponse> PRItemRemoval(PRDto pRDto);
|
||||
Task<PRDetails> PostPRApproveReject(PRDto PRDto);
|
||||
Task<PRDetails> PostPutReceiving(PRDto PRDto);
|
||||
Task<PRDetails> PutPOClose(PRDto PRDto);
|
||||
Task<PRDetails> PutItemDetail(PRDto PRDto);
|
||||
Task<PRDetails> PostPutDeniedItem(PRDto PRDto);
|
||||
Task<PRResponse> PostPRApproveReject(PRDto PRDto);
|
||||
Task<PRResponse> PostPutReceiving(PRDto PRDto);
|
||||
Task<PRResponse> PutPOClose(PRDto PRDto);
|
||||
Task<PRResponse> PutItemDetail(PRDto PRDto);
|
||||
Task<PRResponse> PostPutDeniedItem(PRDto PRDto);
|
||||
Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto);
|
||||
Task<ResponseObject> PostPutProjectCode(PRDto prDto);
|
||||
Task<ResponseObject> PostItemInPR(PRDto dto);
|
||||
|
||||
28
CPRNIMS.Domain/Profile/Canvass/SupplierRequestProfile.cs
Normal file
28
CPRNIMS.Domain/Profile/Canvass/SupplierRequestProfile.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using AutoMapper;
|
||||
using CPRNIMS.Infrastructure.ViewModel.Common;
|
||||
using CPRNIMS.Infrastructure.Entities.Canvass;
|
||||
|
||||
namespace CPRNIMS.Domain.Profile.Canvass
|
||||
{
|
||||
public class SupplierRequestProfile : AutoMapper.Profile
|
||||
{
|
||||
public SupplierRequestProfile()
|
||||
{
|
||||
// 1. THIS IS THE MISSING LINK: Request -> Entity
|
||||
CreateMap<SupplierRequest, Suppliers>();
|
||||
|
||||
// 2. Entity -> Response
|
||||
CreateMap<Suppliers, SupplierResponse>();
|
||||
|
||||
// 3. Response <-> Request (Use ReverseMap to handle both directions automatically)
|
||||
CreateMap<SupplierResponse, SupplierRequest>().ReverseMap();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,29 +1,37 @@
|
||||
using CPRNIMS.Domain.Contracts.Canvass;
|
||||
using AutoMapper;
|
||||
using Azure.Core;
|
||||
using CPRNIMS.Domain.Services.ICanvass;
|
||||
using CPRNIMS.Infrastructure.Database;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using CPRNIMS.Infrastructure.Entities.Canvass;
|
||||
using CPRNIMS.Infrastructure.Entities.Purchasing;
|
||||
using CPRNIMS.Infrastructure.Helper;
|
||||
using CPRNIMS.Infrastructure.ViewModel.Common;
|
||||
using Microsoft.Data.SqlClient;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System.Data;
|
||||
using static CPRNIMS.Domain.Services.OutputParamMessage;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using static CPRNIMS.Domain.Services.OutputParamMessage;
|
||||
|
||||
namespace CPRNIMS.Domain.Services.Canvass
|
||||
{
|
||||
public class Canvass : ICanvass
|
||||
public class Canvass : Contracts.Canvass.ICanvass
|
||||
{
|
||||
private readonly NonInventoryDbContext _dbContext;
|
||||
public Canvass(NonInventoryDbContext dbContext)
|
||||
private readonly SMTPHelper _smptHelper;
|
||||
private readonly IMapper _mapper;
|
||||
public Canvass(NonInventoryDbContext dbContext, SMTPHelper smptHelper,IMapper mapper)
|
||||
{
|
||||
_dbContext = dbContext;
|
||||
_smptHelper = smptHelper;
|
||||
_mapper = mapper;
|
||||
}
|
||||
#region Get
|
||||
public async Task<List<ItemListWOEmail>> GetItemSupplierWOEmail(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.ItemListWOEmails
|
||||
.FromSqlRaw($"EXEC GetItemSupplierWOEmail @PRNo = '{CanvassDto.PRNo}'")
|
||||
@ -31,12 +39,6 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<ItemListWOEmail>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<BiddingItem>> GetSupplierBid(CanvassDto CanvassDto)
|
||||
{
|
||||
var allItems = await _dbContext.BiddingItems
|
||||
@ -48,8 +50,6 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
return allItems ?? new List<BiddingItem>();
|
||||
}
|
||||
public async Task<List<PerSupplier>> GetCanvassPerSupplier(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.PerSuppliers
|
||||
.FromSqlRaw($"EXEC GetCanvassPerSupplier @UserId",
|
||||
@ -58,12 +58,6 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<PerSupplier>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<RFQPerSupplier>> GetSupplierBidByItem(CanvassDto CanvassDto)
|
||||
{
|
||||
var allItems = await _dbContext.RFQPerSuppliers
|
||||
@ -78,34 +72,34 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<RFQPerSupplier>();
|
||||
}
|
||||
public async Task<List<PRDetails>> GetCanvassById(CanvassDto CanvassDto)
|
||||
public async Task<List<PRCanvassDetail>> GetCanvassById(CanvassDto CanvassDto)
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw("EXEC GetCanvassById @UserId",
|
||||
new SqlParameter("@UserId", CanvassDto.UserId))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
public async Task<List<PRDetails>> GetCanvassByItemNo(CanvassDto CanvassDto)
|
||||
public async Task<List<PRCanvassDetail>> GetCanvassByItemNo(CanvassDto CanvassDto)
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw($"EXEC GetCanvassByItemNo @UserId, @ItemNo",
|
||||
new SqlParameter("@UserId", CanvassDto.UserId),
|
||||
new SqlParameter("@ItemNo", CanvassDto.ItemNo))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
public async Task<List<PRDetails>> GetCanvassByPRNo(CanvassDto CanvassDto)
|
||||
public async Task<List<PRCanvassDetail>> GetCanvassByPRNo(CanvassDto CanvassDto)
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw("EXEC GetCanvassByPRNo @UserId, @PRNo",
|
||||
new SqlParameter("@UserId", CanvassDto.UserId),
|
||||
new SqlParameter("@PRNo", CanvassDto.PRNo))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
public async Task<List<CanvassGroupByPRNo>> GetCanvassGroupByPRNo(CanvassDto CanvassDto)
|
||||
{
|
||||
@ -119,42 +113,29 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<CanvassGroupByPRNo>();
|
||||
}
|
||||
public async Task<List<Suppliers>> GetSupplierItemWOEmail(CanvassDto CanvassDto)
|
||||
public async Task<List<SupplierResponse>> GetSupplierItemWOEmail(CanvassDto canvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.Suppliers
|
||||
.FromSqlRaw($"EXEC GetSupplierItemWOEmail @ItemNo = '{CanvassDto.ItemNo}'")
|
||||
// 1. Use Interpolated string to prevent SQL injection and pass the parameter safely
|
||||
var suppliers = await _dbContext.Suppliers
|
||||
.FromSqlInterpolated($"EXEC GetSupplierItemWOEmail @ItemNo = {canvassDto.ItemNo}")
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<Suppliers>();
|
||||
// 2. Map the List of entities to a List of Response objects
|
||||
// AutoMapper handles collections automatically if the types are configured
|
||||
return _mapper.Map<List<SupplierResponse>>(suppliers);
|
||||
}
|
||||
catch (SqlException ex)
|
||||
|
||||
public async Task<List<SupplierResponse>> GetSupplierById(CanvassDto CanvassDto)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<Suppliers>> GetSupplierById(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.Suppliers
|
||||
var item = await _dbContext.Suppliers
|
||||
.FromSqlRaw($"EXEC GetSupplierById @SupplierId",
|
||||
new SqlParameter("@SupplierId", CanvassDto.SupplierId))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<Suppliers>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
// 2. Map the List of entities to a List of Response objects
|
||||
// AutoMapper handles collections automatically if the types are configured
|
||||
return _mapper.Map<List<SupplierResponse>>(item);
|
||||
}
|
||||
public async Task<List<RFQReference>> GetRFQ(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.RFQReferences
|
||||
.FromSqlRaw($"EXEC GetRFQPerSupplier @SupplierId,@UserId",
|
||||
@ -164,63 +145,31 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<RFQReference>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
public async Task<List<PRCanvassDetail>> GetPRItemList(CanvassDto CanvassDto)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<PRDetails>> GetPRItemList(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw($"EXEC GetPRItemList @UserId = '{CanvassDto.UserId}'")
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
public async Task<List<PRCanvassDetail>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<PRDetails>> GetCanvassPerSupplierEmail(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw($"EXEC GetCanvassPerSupplierEmail @UserId = '{CanvassDto.UserId}', @EmailAddress = '{CanvassDto.EmailAddress}'")
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
public async Task<List<PRCanvassDetail>> GetPRItem(CanvassDto CanvassDto)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<PRDetails>> GetPRItem(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw($"EXEC GetPRItem @UserId = '{CanvassDto.UserId}', @ItemNo = {CanvassDto.ItemNo}")
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
public async Task<List<WOResponse>> GetCanvassWOResponse(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.WOResponses
|
||||
.FromSqlRaw($"EXEC GetCanvassWOResponse @UserId = '{CanvassDto.UserId}'")
|
||||
@ -228,15 +177,7 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<WOResponse>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<int> GetCanvassNo()
|
||||
{
|
||||
try
|
||||
{
|
||||
var latestCanvassNo = await _dbContext.Canvasses
|
||||
.OrderByDescending(ic => ic.CanvassNo)
|
||||
@ -251,15 +192,15 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
catch (SqlException ex)
|
||||
public async Task<List<ItemWithoutSupplier>> GetItemWithoutSupplier()
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
var allItems = await _dbContext.ItemWithoutSuppliers
|
||||
.FromSqlRaw("EXEC GetItemWithoutSupplier")
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<ItemWithoutSupplier>();
|
||||
}
|
||||
public async Task<List<WOResponseById>> GetWOResponseBySuppId(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.WOResponseByIds
|
||||
.FromSqlRaw($"EXEC GetWOResponseBySuppId @UserId = '{CanvassDto.UserId}',@SupplierId = '{CanvassDto.SupplierId}'")
|
||||
@ -267,15 +208,7 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<WOResponseById>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<RFQ> PostPerSupplierToken(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostPerSupplierToken @UserId,@SupplierId,@PRNo,@ItemNo,@CanvassNo,@PRDetailsId",
|
||||
@ -288,15 +221,7 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return new RFQ();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<SupplierBidById>> GetSupplierBidById(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.SupplierBidByIds
|
||||
.FromSqlRaw($"EXEC GetSupplierBidById @CanvassDetailId",
|
||||
@ -305,29 +230,15 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
|
||||
return allItems ?? new List<SupplierBidById>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
public async Task<List<SupplierResponse>> GetMySuppliers(CanvassDto CanvassDto)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<Suppliers>> GetMySuppliers(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.Suppliers
|
||||
var items = await _dbContext.Suppliers
|
||||
.FromSqlRaw($"EXEC GetMySuppliers @UserId,@SupplierId",
|
||||
new SqlParameter("@UserId", CanvassDto.UserId),
|
||||
new SqlParameter("@SupplierId", CanvassDto.SupplierId))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<Suppliers>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
return _mapper.Map<List<SupplierResponse>>(items);
|
||||
}
|
||||
public async Task<List<MyPRWOCanvass>> GetMyPRWOCanvass(CanvassDto itemDto)
|
||||
{
|
||||
@ -352,15 +263,15 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
return allItems ?? new List<Infrastructure.Entities.Canvass.PRList>();
|
||||
}
|
||||
|
||||
public async Task<List<PRDetails>> GetCanvassPerSupplierId(CanvassDto itemCodeDto)
|
||||
public async Task<List<PRCanvassDetail>> GetCanvassPerSupplierId(CanvassDto itemCodeDto)
|
||||
{
|
||||
var allItems = await _dbContext.PRDetails
|
||||
var allItems = await _dbContext.PRCanvassDetails
|
||||
.FromSqlRaw($"EXEC GetCanvassPerSupplierId @UserId,@SupplierId",
|
||||
new SqlParameter("@UserId", itemCodeDto.UserId),
|
||||
new SqlParameter("@SupplierId", itemCodeDto.SupplierId))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<PRDetails>();
|
||||
return allItems ?? new List<PRCanvassDetail>();
|
||||
}
|
||||
|
||||
public async Task<List<AlternativeOfferDetails>>
|
||||
@ -400,9 +311,60 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
}
|
||||
#endregion
|
||||
#region Post Put
|
||||
public async Task<Suppliers> PostApprovedSupp(CanvassDto CanvassDto)
|
||||
public async Task<Result<SupplierResponse>> PostSupplierAsync(SupplierRequest request, CancellationToken ct)
|
||||
{
|
||||
var strategy = _dbContext.Database.CreateExecutionStrategy();
|
||||
|
||||
return await strategy.ExecuteAsync(async () =>
|
||||
{
|
||||
await using var transaction = await _dbContext.Database.BeginTransactionAsync(ct);
|
||||
|
||||
try
|
||||
{
|
||||
var supplier = await _dbContext.Suppliers
|
||||
.FirstOrDefaultAsync(s => s.SupplierName == request.SupplierName, ct);
|
||||
|
||||
if (supplier == null)
|
||||
{
|
||||
supplier = _mapper.Map<Suppliers>(request);
|
||||
await _dbContext.AddAsync(supplier, ct);
|
||||
await _dbContext.SaveChangesAsync(ct);
|
||||
}
|
||||
|
||||
await PostSupplierItems(supplier.SupplierId, request.ItemNo, ct);
|
||||
|
||||
await _dbContext.SaveChangesAsync(ct);
|
||||
|
||||
await transaction.CommitAsync(ct);
|
||||
|
||||
return Result<SupplierResponse>.Success(_mapper.Map<SupplierResponse>(supplier));
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
await transaction.RollbackAsync(ct);
|
||||
|
||||
// handle unique constraint violation here if needed
|
||||
throw;
|
||||
}
|
||||
});
|
||||
}
|
||||
private async Task PostSupplierItems(int supplierId, long itemNo, CancellationToken ct)
|
||||
{
|
||||
var exists = await _dbContext.SupplierItems.AnyAsync(
|
||||
s => s.SupplierId == supplierId && s.ItemNo == itemNo && s.IsActive,
|
||||
ct);
|
||||
|
||||
if (!exists)
|
||||
{
|
||||
await _dbContext.SupplierItems.AddAsync(new SupplierItems
|
||||
{
|
||||
SupplierId = supplierId,
|
||||
ItemNo = itemNo,
|
||||
IsActive = true
|
||||
}, ct);
|
||||
}
|
||||
}
|
||||
public async Task<SupplierResponse> PostApprovedSupp(CanvassDto CanvassDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostApprovedSupp @UserId,@CanvassId,@ItemNo",
|
||||
@ -410,16 +372,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
new SqlParameter("@CanvassId", CanvassDto.CanvassId != null ? CanvassDto.CanvassId : 0L),
|
||||
new SqlParameter("@ItemNo", CanvassDto.ItemNo != null ? CanvassDto.ItemNo : 0L));
|
||||
|
||||
return new Suppliers();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return new SupplierResponse();
|
||||
}
|
||||
public async Task<CanvassDetail> PostSuggestedSupp(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostSuggestedSupp @UserId,@CanvassDetailId,@ItemNo,@SupplierId,@CanvassId",
|
||||
@ -430,14 +385,7 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
new SqlParameter("@CanvassId", CanvassDto.CanvassId));
|
||||
return new CanvassDetail();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<PRDetails> PostCanvass(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
public async Task<PRCanvassDetail> PostCanvass(CanvassDto CanvassDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostCanvass @UserId, @SupplierId, @Status,@Remarks",
|
||||
@ -445,17 +393,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
new SqlParameter("@UserId", CanvassDto.UserId),
|
||||
new SqlParameter("@Status", CanvassDto.Status),
|
||||
new SqlParameter("@Remarks", CanvassDto.Remarks ?? "N/A"));
|
||||
return new PRDetails();
|
||||
return new PRCanvassDetail();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<Suppliers> PostTaggingSupplier(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
public async Task<SupplierResponse> PostTaggingSupplier(CanvassDto CanvassDto)
|
||||
{
|
||||
var (messCode, message) = CreateOutputParams();
|
||||
|
||||
@ -479,16 +419,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
{
|
||||
throw new Exception(message.Value.ToString());
|
||||
}
|
||||
return new Suppliers();
|
||||
return new SupplierResponse();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<Suppliers> PostPutItemTagging(CanvassDto canvassDto)
|
||||
{
|
||||
try
|
||||
public async Task<SupplierResponse> PostPutItemTagging(CanvassDto canvassDto)
|
||||
{
|
||||
var (messCode, message) = CreateOutputParams();
|
||||
|
||||
@ -506,16 +439,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
{
|
||||
throw new Exception(message.Value.ToString());
|
||||
}
|
||||
return new Suppliers();
|
||||
return new SupplierResponse();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<Suppliers> PostPutSupplier(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
public async Task<SupplierResponse> PostPutSupplier(CanvassDto CanvassDto)
|
||||
{
|
||||
var messCode = new SqlParameter("@MessCode", SqlDbType.TinyInt) { Direction = ParameterDirection.Output };
|
||||
var message = new SqlParameter("@Message", SqlDbType.VarChar, 8000) { Direction = ParameterDirection.Output };
|
||||
@ -541,16 +467,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
throw new Exception(message.Value.ToString());
|
||||
}
|
||||
|
||||
return new Suppliers();
|
||||
return new SupplierResponse();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<Suppliers> PostPutMySupplier(CanvassDto canvassDto)
|
||||
{
|
||||
try
|
||||
public async Task<SupplierResponse> PostPutMySupplier(CanvassDto canvassDto)
|
||||
{
|
||||
var messCode = new SqlParameter("@MessCode", SqlDbType.TinyInt) { Direction = ParameterDirection.Output };
|
||||
var message = new SqlParameter("@Message", SqlDbType.VarChar, 8000) { Direction = ParameterDirection.Output };
|
||||
@ -581,16 +500,9 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
throw new Exception(message.Value.ToString());
|
||||
}
|
||||
|
||||
return new Suppliers();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
return new SupplierResponse();
|
||||
}
|
||||
public async Task<CanvassDetail> PutSuppUnitPrice(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync($"EXEC PutSuppUnitPrice @UserId, @CanvassDetailId, @UnitPrice",
|
||||
@ -599,27 +511,13 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
new SqlParameter("@UnitPrice", CanvassDto.UnitPrice));
|
||||
return new CanvassDetail();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<ForCanvassFollowUp> PutSupplierCanvass(long canvassSupplierId)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PutCanvassForFollowUp @CanvassSupplierId",
|
||||
new SqlParameter("@CanvassSupplierId", canvassSupplierId));
|
||||
return new ForCanvassFollowUp();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<CanvassDetail> PutSuppBidDetails(CanvassDto canvassDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
@ -649,6 +547,61 @@ namespace CPRNIMS.Domain.Services.Canvass
|
||||
new SqlParameter("@CanvassSupplierId", canvassDto.CanvassSupplierId));
|
||||
return new CanvassSupplier();
|
||||
}
|
||||
|
||||
public async Task SendRFQ(SupplierEmailRequest supplierEmailRequest)
|
||||
{
|
||||
var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "SendToSupplier.cshtml");
|
||||
|
||||
var message = new StringBuilder(baseTemplate);
|
||||
|
||||
message.Replace("@ViewBag.FormLink", Convert.ToString(supplierEmailRequest.FormLink + supplierEmailRequest.Token));
|
||||
message.Replace("@ViewBag.Supplier", supplierEmailRequest.SupplierName);
|
||||
message.Replace("@ViewBag.Signature", supplierEmailRequest.Purchaser);
|
||||
|
||||
var messageDetails = new EmailMessageDetailsVM
|
||||
{
|
||||
Recipient = supplierEmailRequest.Recipient,
|
||||
Message = message.ToString(),
|
||||
Subject = supplierEmailRequest.Subject,
|
||||
CC = supplierEmailRequest.CC,
|
||||
IsSuccess = supplierEmailRequest.IsSuccess,
|
||||
SenderEmail = supplierEmailRequest.UserName,
|
||||
DisplayName = "llipurchasing.com",
|
||||
NewPassword = supplierEmailRequest.Password,
|
||||
OutGoingPort = supplierEmailRequest.OutGoingPort,
|
||||
Server = supplierEmailRequest.Server,
|
||||
UserName = supplierEmailRequest.UserName,
|
||||
IsCanvass= supplierEmailRequest.IsCanvass,
|
||||
AttachPath=supplierEmailRequest.AttachPath
|
||||
};
|
||||
|
||||
await _smptHelper.SendEmailAsync(messageDetails);
|
||||
}
|
||||
public string EMailTemplate(string relativePath, string 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";
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> SearchingUpdate(long pRDetailsId)
|
||||
{
|
||||
var rowsAffected = await _dbContext.PRDetails
|
||||
.Where(p => p.PRDetailsId == pRDetailsId)
|
||||
.ExecuteUpdateAsync(s => s.SetProperty(p => p.IsSearched, true));
|
||||
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
231
CPRNIMS.Domain/Services/Canvass/SupplierSearchService.cs
Normal file
231
CPRNIMS.Domain/Services/Canvass/SupplierSearchService.cs
Normal file
@ -0,0 +1,231 @@
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Result;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Domain.Services.Canvass
|
||||
{
|
||||
public class SupplierSearchService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
// Common contact page suffixes to try
|
||||
private static readonly string[] ContactPaths =
|
||||
{ "/contact", "/contact-us", "/pages/contact-us", "/about/contact", "/about" };
|
||||
|
||||
public SupplierSearchService(HttpClient httpClient, IConfiguration config)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_config = config;
|
||||
}
|
||||
|
||||
public async Task<List<SupplierResponse>> SearchAndFilterSuppliersAsync(
|
||||
string itemName, string itemDescription)
|
||||
{
|
||||
// Step 1: Tavily — get supplier URLs
|
||||
var (searchContent, supplierUrls) = await SearchTavilyAsync(itemName, itemDescription);
|
||||
|
||||
// Step 2: Fetch contact pages from discovered URLs
|
||||
var contactContent = await FetchContactPagesAsync(supplierUrls);
|
||||
|
||||
// Step 3: Combine search + contact content, send to Groq
|
||||
var combined = searchContent + " CONTACT_PAGES_DATA: " + contactContent;
|
||||
var suppliers = await FilterWithGroqAsync(itemName, itemDescription, combined);
|
||||
|
||||
return suppliers;
|
||||
}
|
||||
|
||||
// ── Tavily ──────────────────────────────────────────────────────────────
|
||||
private async Task<(string content, List<string> urls)> SearchTavilyAsync(
|
||||
string itemName, string itemDescription)
|
||||
{
|
||||
var query = $"{itemName} {itemDescription} suppliers Philippines budget price contact email phone";
|
||||
|
||||
var payload = new
|
||||
{
|
||||
query,
|
||||
max_results = 10,
|
||||
search_depth = "advanced",
|
||||
include_answer = false
|
||||
};
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, _config["Tavily:SearchUrl"]);
|
||||
request.Headers.Add("Authorization", $"Bearer {_config["Tavily:ApiKey"]}");
|
||||
request.Content = new StringContent(
|
||||
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var result = JsonSerializer.Deserialize<TavilySearchResult>(body,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
var sb = new StringBuilder();
|
||||
var urls = new List<string>();
|
||||
int i = 1;
|
||||
|
||||
foreach (var r in result?.Results ?? new())
|
||||
{
|
||||
// Clean text
|
||||
var clean = Regex.Replace(r.Content ?? "", @"[^\x20-\x7E]", " ");
|
||||
clean = Regex.Replace(clean, @"\s{3,}", " ");
|
||||
if (clean.Length > 300) clean = clean[..300];
|
||||
sb.Append($"{i}. Title:{r.Title}|URL:{r.Url}|Content:{clean}|");
|
||||
|
||||
// Collect base domain URLs for contact page fetching
|
||||
try
|
||||
{
|
||||
var uri = new Uri(r.Url);
|
||||
var baseUrl = $"{uri.Scheme}://{uri.Host}";
|
||||
if (!urls.Contains(baseUrl)) urls.Add(baseUrl);
|
||||
}
|
||||
catch { }
|
||||
i++;
|
||||
}
|
||||
|
||||
var fullText = sb.ToString();
|
||||
if (fullText.Length > 2000) fullText = fullText[..2000];
|
||||
|
||||
return (fullText, urls);
|
||||
}
|
||||
|
||||
// ── Fetch Contact Pages ──────────────────────────────────────────────────
|
||||
private async Task<string> FetchContactPagesAsync(List<string> baseUrls)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
// Limit to top 5 domains to avoid timeout
|
||||
foreach (var baseUrl in baseUrls.Take(5))
|
||||
{
|
||||
foreach (var path in ContactPaths)
|
||||
{
|
||||
try
|
||||
{
|
||||
var url = baseUrl + path;
|
||||
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
|
||||
var resp = await _httpClient.GetAsync(url, cts.Token);
|
||||
|
||||
if (!resp.IsSuccessStatusCode) continue;
|
||||
|
||||
var html = await resp.Content.ReadAsStringAsync();
|
||||
|
||||
// Strip HTML tags
|
||||
var text = Regex.Replace(html, @"<[^>]+>", " ");
|
||||
text = Regex.Replace(text, @"[^\x20-\x7E]", " ");
|
||||
text = Regex.Replace(text, @"\s{3,}", " ");
|
||||
|
||||
// Extract only lines with contact signals
|
||||
var contactLines = text.Split(' ', StringSplitOptions.RemoveEmptyEntries)
|
||||
.Where(w => w.Contains("@")
|
||||
|| Regex.IsMatch(w, @"\+?[\d\-\(\)]{7,}")
|
||||
|| w.Contains("email")
|
||||
|| w.Contains("phone")
|
||||
|| w.Contains("contact")
|
||||
|| w.Contains("mobile")
|
||||
|| w.Contains("tel"))
|
||||
.Take(50);
|
||||
|
||||
var contactText = string.Join(" ", contactLines);
|
||||
if (!string.IsNullOrWhiteSpace(contactText))
|
||||
{
|
||||
sb.Append($"[{baseUrl}]: {contactText} | ");
|
||||
break; // Found contact page for this domain, move to next
|
||||
}
|
||||
}
|
||||
catch { /* timeout or unreachable — skip */ }
|
||||
}
|
||||
}
|
||||
|
||||
return sb.Length > 2000 ? sb.ToString()[..2000] : sb.ToString();
|
||||
}
|
||||
|
||||
// ── Groq ─────────────────────────────────────────────────────────────────
|
||||
private async Task<List<SupplierResponse>> FilterWithGroqAsync(
|
||||
string itemName, string itemDescription, string searchContent)
|
||||
{
|
||||
var prompt = $"Extract top 10 unique suppliers for: {itemName} {itemDescription}. " +
|
||||
"Prioritize Philippines suppliers first. " +
|
||||
"IMPORTANT: Look carefully in CONTACT_PAGES_DATA section for real phone numbers and emails. " +
|
||||
"Extract exact email addresses and phone numbers found. " +
|
||||
"For domains without contact data found, infer email as sales@domain or info@domain. " +
|
||||
"Prefer budget-friendly suppliers. No duplicates. " +
|
||||
"Return ONLY a raw JSON array: company_name, country, phone_number, contact_email, website, estimated_price_usd, item_specifications. " +
|
||||
$"Null for missing. JSON array only. Data: {searchContent}";
|
||||
|
||||
var payload = new
|
||||
{
|
||||
model = _config["Groq:Model"] ?? "llama-3.1-8b-instant",
|
||||
stream = false,
|
||||
max_tokens = 2048,
|
||||
temperature = 0.1,
|
||||
messages = new[]
|
||||
{
|
||||
new { role = "system", content = "You are a supplier data extractor. Extract real contact details from provided content. Return ONLY a valid JSON array, no markdown, no explanation." },
|
||||
new { role = "user", content = prompt }
|
||||
}
|
||||
};
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, _config["Groq:ApiUrl"]);
|
||||
request.Headers.Add("Authorization", $"Bearer {_config["Groq:ApiKey"]}");
|
||||
request.Content = new StringContent(
|
||||
JsonSerializer.Serialize(payload), Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _httpClient.SendAsync(request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var body = await response.Content.ReadAsStringAsync();
|
||||
var groqResp = JsonSerializer.Deserialize<GroqResponse>(body,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
|
||||
|
||||
var rawText = groqResp?.Choices?[0]?.Message?.Content ?? string.Empty;
|
||||
|
||||
var match = Regex.Match(rawText, @"\[[\s\S]*\]");
|
||||
if (!match.Success) return new List<SupplierResponse>();
|
||||
|
||||
var groqList = JsonSerializer.Deserialize<List<GroqSupplierResult>>(match.Value,
|
||||
new JsonSerializerOptions { PropertyNameCaseInsensitive = true })
|
||||
?? new List<GroqSupplierResult>();
|
||||
|
||||
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
var suppliers = new List<SupplierResponse>();
|
||||
|
||||
foreach (var s in groqList)
|
||||
{
|
||||
var key = (s.CompanyName ?? "").Trim().ToLower();
|
||||
if (string.IsNullOrEmpty(key) || seen.Contains(key)) continue;
|
||||
seen.Add(key);
|
||||
|
||||
if (string.IsNullOrEmpty(s.ContactEmail)) continue;
|
||||
|
||||
suppliers.Add(new SupplierResponse
|
||||
{
|
||||
SupplierName = s.CompanyName,
|
||||
EmailAddress = s.ContactEmail,
|
||||
ContactNo = s.PhoneNumber ?? string.Empty,
|
||||
Address = s.Country ?? string.Empty,
|
||||
IsActive = true,
|
||||
VatInc = false,
|
||||
Currency = "PHP",
|
||||
CurrencyId = 1,
|
||||
PaymentTermsId = 1,
|
||||
PaymentTerms = "30 Days",
|
||||
LeadTime = "7-14 Days",
|
||||
TinNo = string.Empty,
|
||||
ContactPerson = string.Empty,
|
||||
Website =s.Website ?? string.Empty,
|
||||
});
|
||||
|
||||
if (suppliers.Count >= 10) break;
|
||||
}
|
||||
|
||||
return suppliers;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
using CPRNIMS.Infrastructure.Database;
|
||||
using CPRNIMS.Infrastructure.Dto.Items;
|
||||
using CPRNIMS.Infrastructure.Dto.PR;
|
||||
using CPRNIMS.Infrastructure.Dto.PR.Response;
|
||||
using CPRNIMS.Infrastructure.Entities.Common;
|
||||
using CPRNIMS.Infrastructure.Entities.Purchasing;
|
||||
using CPRNIMS.Infrastructure.Entities.SMTP;
|
||||
@ -309,7 +310,7 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
PRNo = reader["PRNo"] as long? ?? 0,
|
||||
NewPRNo = reader["NewPRNo"]?.ToString(),
|
||||
AggreItemName = reader["AggreItemName"]?.ToString(),
|
||||
CreatedDate = reader["NewPRNo"] as DateTime? ?? DateTime.UtcNow,
|
||||
CreatedDate = reader["CreatedDate"] as DateTime? ?? DateTime.UtcNow,
|
||||
DateNeeded = reader["DateNeeded"] as DateTime? ?? DateTime.UtcNow,
|
||||
CreatedBy = reader["CreatedBy"]?.ToString(),
|
||||
Department = reader["Department"]?.ToString(),
|
||||
@ -545,7 +546,7 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
}
|
||||
#endregion
|
||||
#region Post Put
|
||||
public async Task<PRDetails> PostPRApproveReject(PRDto PRDto)
|
||||
public async Task<PRResponse> PostPRApproveReject(PRDto PRDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostPRApproveReject @UserId, @ItemNo, @Status, @PRDetailsId, @Remarks",
|
||||
@ -554,9 +555,9 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
new SqlParameter("@Status", PRDto.Status),
|
||||
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
|
||||
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
|
||||
return new PRDetails();
|
||||
return new PRResponse();
|
||||
}
|
||||
public async Task<PRDetails> PutItemDetail(PRDto PRDto)
|
||||
public async Task<PRResponse> PutItemDetail(PRDto PRDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync($"EXEC PutPRItemDetail @UserId, @ItemLocalId, @UOMId, @ItemColorId," +
|
||||
@ -571,18 +572,18 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
new SqlParameter("@Remarks", PRDto.Remarks),
|
||||
new SqlParameter("@ItemName", PRDto.ItemName),
|
||||
new SqlParameter("@ItemDescription", PRDto.ItemDescription));
|
||||
return new PRDetails();
|
||||
return new PRResponse();
|
||||
}
|
||||
public async Task<PRDetails> PostPutDeniedItem(PRDto PRDto)
|
||||
public async Task<PRResponse> PostPutDeniedItem(PRDto PRDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PostPutDeniedItem @UserId,@PRDetailsId,@Remarks",
|
||||
new SqlParameter("@UserId", PRDto.UserId),
|
||||
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
|
||||
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
|
||||
return new PRDetails();
|
||||
return new PRResponse();
|
||||
}
|
||||
public async Task<PRDetails> PostPutReceiving(PRDto PRDto)
|
||||
public async Task<PRResponse> PostPutReceiving(PRDto PRDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync($"EXEC PostPutReceiving @UserId, @PONo, @POTypeId, @EmailAddress, @DRNo, @DocTypeId, @QuantityReceived,@RRNo,@PRDetailsId,@Remarks,@ReceivedDate,@IsCompleted",
|
||||
@ -598,9 +599,9 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"),
|
||||
new SqlParameter("@ReceivedDate", PRDto.ReceivedDate),
|
||||
new SqlParameter("@IsCompleted", PRDto.IsCompleted));
|
||||
return new PRDetails();
|
||||
return new PRResponse();
|
||||
}
|
||||
public async Task<PRDetails> PutPOClose(PRDto PRDto)
|
||||
public async Task<PRResponse> PutPOClose(PRDto PRDto)
|
||||
{
|
||||
await _dbContext.Database
|
||||
.ExecuteSqlRawAsync("EXEC PutPOClose @UserId, @PONo, @POTypeId, @EmailAddress,@PRDetailsId,@DocTypeId,@PRNo,@Remarks",
|
||||
@ -612,7 +613,7 @@ namespace CPRNIMS.Domain.Services.PR
|
||||
new SqlParameter("@PRDetailsId", PRDto.PRDetailsId),
|
||||
new SqlParameter("@PRNo", PRDto.PRNo),
|
||||
new SqlParameter("@Remarks", PRDto.Remarks ?? "N/A"));
|
||||
return new PRDetails();
|
||||
return new PRResponse();
|
||||
}
|
||||
public async Task<AlternativeOfferDetails> PutSupplierAlterOffer(PRDto pRDto)
|
||||
{
|
||||
|
||||
@ -22,8 +22,6 @@ namespace CPRNIMS.Domain.Services.Receiving
|
||||
}
|
||||
#region Get
|
||||
public async Task<List<Infrastructure.Entities.Receiving.RRReport>> GetRRReport(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!itemDto.IsSorting)
|
||||
{
|
||||
@ -40,15 +38,7 @@ namespace CPRNIMS.Domain.Services.Receiving
|
||||
|
||||
return allItems ?? new List<Infrastructure.Entities.Receiving.RRReport>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<ForReceiving>> GetForReceiving(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.ForReceivings
|
||||
.FromSqlRaw($"EXEC GetForReceiving @UserId,@IsDenied",
|
||||
@ -58,15 +48,7 @@ namespace CPRNIMS.Domain.Services.Receiving
|
||||
|
||||
return allItems ?? new List<ForReceiving>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<RR>> GetRR(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.RRs
|
||||
.FromSqlRaw($"EXEC GetRR @UserId",
|
||||
@ -75,28 +57,12 @@ namespace CPRNIMS.Domain.Services.Receiving
|
||||
|
||||
return allItems ?? new List<RR>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<RRSeries>> GetLatestRRNo(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _dbContext.RRSeries.FromSqlRaw("EXEC GetLatestRRNo @UserId",
|
||||
new SqlParameter("@UserId", itemDto.UserId)).ToListAsync();
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<ReceivingDetail>> GetRRDetailByPO(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.ReceivingDetails
|
||||
.FromSqlRaw($"EXEC GetRRDetailByPO @PONo,@POTypeId,@UserId",
|
||||
@ -107,30 +73,16 @@ namespace CPRNIMS.Domain.Services.Receiving
|
||||
|
||||
return allItems ?? new List<ReceivingDetail>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<List<RRDetail>> GetRRDetail(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var allItems = await _dbContext.RRDetailss
|
||||
.FromSqlRaw($"EXEC GetRRDetail @RRNo,@UserId",
|
||||
.FromSqlRaw("EXEC GetRRDetail @RRNo,@UserId",
|
||||
new SqlParameter("@RRNo", itemDto.RRNo),
|
||||
new SqlParameter("@UserId", itemDto.UserId))
|
||||
.ToListAsync();
|
||||
|
||||
return allItems ?? new List<RRDetail>();
|
||||
}
|
||||
catch (SqlException ex)
|
||||
{
|
||||
ex.ToString();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Post Put
|
||||
public async Task<PRDetails> PostPutReceiving(ItemDto itemDto)
|
||||
|
||||
25
CPRNIMS.Domain/Services/Result.cs
Normal file
25
CPRNIMS.Domain/Services/Result.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Domain.Services
|
||||
{
|
||||
public class Result<T>
|
||||
{
|
||||
public bool IsSuccess { get; set; }
|
||||
public string? Error { get; set; }
|
||||
public T? Value { get; set; }
|
||||
private Result(bool isSuccess, T? value, string? error)
|
||||
{
|
||||
IsSuccess = isSuccess;
|
||||
Error = error;
|
||||
Value = value;
|
||||
}
|
||||
public static Result<T> Success(T value)
|
||||
=> new Result<T>(true, value, null);
|
||||
public static Result<T> Failure(string? error)
|
||||
=> new Result<T>(false, default, error);
|
||||
}
|
||||
}
|
||||
@ -23,4 +23,8 @@
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="Dto\PR\Request\" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@ -65,6 +65,7 @@ namespace CPRNIMS.Infrastructure.Database
|
||||
public virtual DbSet<ForRR> ForRRs { get; set; }
|
||||
public virtual DbSet<RR> RRs { get; set; }
|
||||
public virtual DbSet<Canvass> Canvasses { get; set; }
|
||||
public DbSet<SupplierItems> SupplierItems { get; set; }
|
||||
public virtual DbSet<ForCanvassFollowUp> ForCanvassFollowUps { get; set; }
|
||||
public virtual DbSet<WOResponse> WOResponses { get; set; }
|
||||
public virtual DbSet<WOResponseById> WOResponseByIds { get; set; }
|
||||
@ -78,6 +79,7 @@ namespace CPRNIMS.Infrastructure.Database
|
||||
public virtual DbSet<CanvassSupplier> CanvassSuppliers { get; set; }
|
||||
public virtual DbSet<RFQReference> RFQReferences { get; set; }
|
||||
public virtual DbSet<CanvassDetail> CanvassDetails { get; set; }
|
||||
public virtual DbSet<PRCanvassDetail> PRCanvassDetails { get; set; }
|
||||
public virtual DbSet<CanvassGroupByPRNo> CanvassGroupByPRNos { get; set; }
|
||||
public virtual DbSet<ForCanvass> ForCanvasses { get; set; }
|
||||
public virtual DbSet<ForPO> ForPOs { get; set; }
|
||||
@ -122,6 +124,7 @@ namespace CPRNIMS.Infrastructure.Database
|
||||
|
||||
#region Automation Part
|
||||
public virtual DbSet<AllForCanvass> AllForCanvasses { get; set; }
|
||||
public DbSet<ItemWithoutSupplier> ItemWithoutSuppliers { get; set; }
|
||||
public DbSet<ErrorLog> ErrorLogs { get; set; }
|
||||
#endregion
|
||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||
@ -150,6 +153,11 @@ namespace CPRNIMS.Infrastructure.Database
|
||||
b.ToTable("PRPOSummaryItem");
|
||||
b.HasNoKey();
|
||||
});
|
||||
modelBuilder.Entity<RR>(b =>
|
||||
{
|
||||
b.ToTable("RR");
|
||||
b.HasNoKey();
|
||||
});
|
||||
modelBuilder.Entity<ApplicationUser>(b =>
|
||||
{
|
||||
b.ToTable("Users");
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
|
||||
{
|
||||
public class SearchSupplierRequest
|
||||
{
|
||||
public long PRDetailsId { get; set; }
|
||||
public long PRNo { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public string ItemName { get; set; } = string.Empty;
|
||||
public string ItemDescription { get; set; } = string.Empty;
|
||||
public string FullName { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
|
||||
{
|
||||
public class SupplierEmailRequest
|
||||
{
|
||||
public string Subject { get; set; } = string.Empty;
|
||||
public string SenderEmail { get; set; } = string.Empty;
|
||||
public string Recipient { get; set; } = string.Empty;
|
||||
public string DisplayName { get; set; } = string.Empty;
|
||||
public int OutGoingPort { get; set; } = 587;
|
||||
public string Password { get; set; } = string.Empty;
|
||||
public string Token { get; set; } = string.Empty;
|
||||
public string Server { get; set; } = string.Empty;
|
||||
public string CC { get; set; } = string.Empty;
|
||||
public bool IsCanvass { get; set; }
|
||||
public string Purchaser { get; set; }=string.Empty;
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string FormLink { get; set; } = string.Empty;
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
public string SupplierName { get; set; } = string.Empty;
|
||||
public bool IsSuccess { get; set; }
|
||||
public string AttachPath { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Request
|
||||
{
|
||||
public class SupplierRequest
|
||||
{
|
||||
public string SupplierName { get; set; } = string.Empty;
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string ContactNo { get; set; } = string.Empty;
|
||||
public string ContactPerson { get; set; } = string.Empty;
|
||||
public string LeadTime { get; set; } = string.Empty;
|
||||
public bool IsVatable { get; set; } = false;
|
||||
public byte PaymentTermsId { get; set; } = 1;
|
||||
public byte CurrencyId { get; set; } = 1;
|
||||
public string TinNo { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public long ItemNo { get; set; } = 0;
|
||||
public string Website { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
|
||||
{
|
||||
public class SearchSupplierResponse
|
||||
{
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Response
|
||||
{
|
||||
public class SupplierResponse
|
||||
{
|
||||
public int SupplierId { get; set; }
|
||||
public string SupplierName { get; set; } = string.Empty;
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string ContactNo { get; set; } = string.Empty;
|
||||
public string ContactPerson { get; set; } = string.Empty;
|
||||
public string LeadTime { get; set; } = string.Empty;
|
||||
public bool VatInc { get; set; } = false;
|
||||
public string Currency { get; set; } = string.Empty;
|
||||
public string PaymentTerms { get; set; } = string.Empty;
|
||||
public byte PaymentTermsId { get; set; } = 1;
|
||||
public byte CurrencyId { get; set; } = 1;
|
||||
public string TinNo { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string Website { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,64 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.Canvass.Result
|
||||
{
|
||||
public class GroqSupplierResult
|
||||
{
|
||||
[JsonPropertyName("company_name")]
|
||||
public string CompanyName { get; set; } = string.Empty;
|
||||
|
||||
[JsonPropertyName("country")]
|
||||
public string? Country { get; set; }
|
||||
|
||||
[JsonPropertyName("phone_number")]
|
||||
public string? PhoneNumber { get; set; }
|
||||
|
||||
[JsonPropertyName("contact_email")]
|
||||
public string? ContactEmail { get; set; }
|
||||
|
||||
[JsonPropertyName("website")]
|
||||
public string? Website { get; set; }
|
||||
|
||||
[JsonPropertyName("source")]
|
||||
public string? Source { get; set; }
|
||||
|
||||
[JsonPropertyName("estimated_price_usd")]
|
||||
public decimal? EstimatedPriceUsd { get; set; }
|
||||
|
||||
[JsonPropertyName("item_specifications")]
|
||||
public JsonElement? ItemSpecifications { get; set; }
|
||||
}
|
||||
public class TavilySearchResult
|
||||
{
|
||||
public List<TavilyResult> Results { get; set; } = new();
|
||||
}
|
||||
|
||||
public class TavilyResult
|
||||
{
|
||||
public string Title { get; set; } = string.Empty;
|
||||
public string Url { get; set; } = string.Empty;
|
||||
public string Content { get; set; } = string.Empty;
|
||||
public double Score { get; set; }
|
||||
}
|
||||
|
||||
public class GroqResponse
|
||||
{
|
||||
public List<GroqChoice> Choices { get; set; } = new();
|
||||
}
|
||||
|
||||
public class GroqChoice
|
||||
{
|
||||
public GroqMessage Message { get; set; } = new();
|
||||
}
|
||||
|
||||
public class GroqMessage
|
||||
{
|
||||
public string Content { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
37
CPRNIMS.Infrastructure/Dto/PR/Response/PRResponse.cs
Normal file
37
CPRNIMS.Infrastructure/Dto/PR/Response/PRResponse.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Dto.PR.Response
|
||||
{
|
||||
public class PRResponse
|
||||
{
|
||||
[Key]
|
||||
public long PRDetailsId { get; set; }
|
||||
public long ItemCodeId { get; set; }
|
||||
public short ItemClassId { get; set; }
|
||||
public string? Department { get; set; }
|
||||
public string? ItemCategoryName { get; set; }
|
||||
public string? UserId { get; set; }
|
||||
public string? ItemName { get; set; }
|
||||
public decimal TotalAmount { get; set; }
|
||||
public string? ItemDescription { get; set; }
|
||||
public short Status { get; set; }
|
||||
public string? StatusName { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public string? ItemLocalName { get; set; }
|
||||
public decimal Qty { get; set; }
|
||||
public string? NewPRNo { get; set; }
|
||||
public string? ItemClassName { get; set; }
|
||||
public string? UOMName { get; set; }
|
||||
public string? ItemColorName { get; set; }
|
||||
public string? ItemAttachPath { get; set; }
|
||||
public long PRNo { get; set; }
|
||||
public string? Remarks { get; set; }
|
||||
public DateTime DateNeeded { get; set; }
|
||||
}
|
||||
}
|
||||
38
CPRNIMS.Infrastructure/Entities/Canvass/PRCanvassDetail.cs
Normal file
38
CPRNIMS.Infrastructure/Entities/Canvass/PRCanvassDetail.cs
Normal file
@ -0,0 +1,38 @@
|
||||
using CPRNIMS.Infrastructure.Entities.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Entities.Canvass
|
||||
{
|
||||
public class PRCanvassDetail : CommonProperties
|
||||
{
|
||||
[Key]
|
||||
public long PRDetailsId { get; set; }
|
||||
public long ItemCodeId { get; set; }
|
||||
public short ItemClassId { get; set; }
|
||||
public string? Department { get; set; }
|
||||
public string? ItemCategoryName { get; set; }
|
||||
public string? UserId { get; set; }
|
||||
public string? ItemName { get; set; }
|
||||
public decimal TotalAmount { get; set; }
|
||||
public string? ItemDescription { get; set; }
|
||||
public short Status { get; set; }
|
||||
public string? StatusName { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public string? ItemLocalName { get; set; }
|
||||
public decimal Qty { get; set; }
|
||||
public string? NewPRNo { get; set; }
|
||||
public string? ItemClassName { get; set; }
|
||||
public string? UOMName { get; set; }
|
||||
public string? ItemColorName { get; set; }
|
||||
public string? ItemAttachPath { get; set; }
|
||||
public long PRNo { get; set; }
|
||||
public string? Remarks { get; set; }
|
||||
public DateTime DateNeeded { get; set; }
|
||||
}
|
||||
}
|
||||
21
CPRNIMS.Infrastructure/Entities/Canvass/SupplierItems.cs
Normal file
21
CPRNIMS.Infrastructure/Entities/Canvass/SupplierItems.cs
Normal file
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Entities.Canvass
|
||||
{
|
||||
[Table("SupplierItems")]
|
||||
public class SupplierItems
|
||||
{
|
||||
[Key]
|
||||
public long SupplierItemId { get; set; }
|
||||
public int SupplierId { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@ -13,18 +13,17 @@ namespace CPRNIMS.Infrastructure.Entities.Canvass
|
||||
{
|
||||
[Key]
|
||||
public int SupplierId { get; set; }
|
||||
public string? SupplierName { get; set; }
|
||||
public string? EmailAddress { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public string? ContactNo { get; set; }
|
||||
public string? ContactPerson { get; set; }
|
||||
public string? LeadTime { get; set; }
|
||||
public bool VatInc { get; set; }
|
||||
public string? Currency { get; set; }
|
||||
public string? PaymentTerms { get; set; }
|
||||
public byte PaymentTermsId { get; set; }
|
||||
public byte CurrencyId { get; set; }
|
||||
public string? TinNo { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public string SupplierName { get; set; } = string.Empty;
|
||||
public string EmailAddress { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; } = true;
|
||||
public string ContactNo { get; set; } = string.Empty;
|
||||
public string ContactPerson { get; set; } = string.Empty;
|
||||
public string LeadTime { get; set; } = string.Empty;
|
||||
public bool IsVatable { get; set; }=false;
|
||||
public byte PaymentTermsId { get; set; } = 1;
|
||||
public byte CurrencyId { get; set; } = 1;
|
||||
public string TinNo { get; set; } = string.Empty;
|
||||
public string Address { get; set; } = string.Empty;
|
||||
public string Website { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
||||
{
|
||||
public class ItemWithoutSupplier
|
||||
{
|
||||
[Key]
|
||||
public long PRDetailsId { get; set; }
|
||||
public long PRNo { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public string UserId { get; set; } = string.Empty;
|
||||
public string ItemName { get; set; }=string.Empty;
|
||||
public string ItemDescription { get; set; } = string.Empty;
|
||||
public string FullName { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -3,38 +3,24 @@ using CPRNIMS.Infrastructure.ViewModel.Items;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
||||
{
|
||||
public class PRDetails : CommonProperties
|
||||
[Table("PRDetails")]
|
||||
public class PRDetails
|
||||
{
|
||||
[Key]
|
||||
public long PRDetailsId { get; set; }
|
||||
public long ItemCodeId { get; set; }
|
||||
public short ItemClassId { get; set; }
|
||||
public string? Department { get; set; }
|
||||
public string? ItemCategoryName { get; set; }
|
||||
public string? UserId { get; set; }
|
||||
public string? ItemName { get; set; }
|
||||
public decimal TotalAmount { get; set; }
|
||||
public string? ItemDescription { get; set; }
|
||||
public string ItemName { get; set; }=string.Empty;
|
||||
public string ItemDescription { get; set; } = string.Empty;
|
||||
public short Status { get; set; }
|
||||
public string? StatusName { get; set; }
|
||||
public bool IsActive { get; set; }
|
||||
public long ItemNo { get; set; }
|
||||
public string? ItemLocalName { get; set; }
|
||||
public decimal Qty { get; set; }
|
||||
public string? NewPRNo { get; set; }
|
||||
public string? ItemClassName { get; set; }
|
||||
public string? UOMName { get; set; }
|
||||
public string? ItemColorName { get; set; }
|
||||
public string? ItemAttachPath { get; set; }
|
||||
public long PRNo { get; set; }
|
||||
public string? Remarks { get; set; }
|
||||
public DateTime DateNeeded { get; set; }
|
||||
public bool Queue { get; set; }
|
||||
public bool IsSearched { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Linq;
|
||||
@ -7,9 +8,10 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace CPRNIMS.Infrastructure.Entities.Purchasing
|
||||
{
|
||||
[Keyless]
|
||||
public class RR
|
||||
{
|
||||
[Key]
|
||||
public long RRId { get; set; }
|
||||
public long RRNo { get; set; }
|
||||
public long POId { get; set; }
|
||||
public string? PONo { get; set; }
|
||||
|
||||
@ -43,8 +43,6 @@ namespace CPRNIMS.Infrastructure.Helper
|
||||
return otp;
|
||||
}
|
||||
public async Task<bool> SendEmailAsync(EmailMessageDetailsVM emailMessageBody)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(emailMessageBody?.Recipient))
|
||||
{
|
||||
@ -52,7 +50,7 @@ namespace CPRNIMS.Infrastructure.Helper
|
||||
return false;
|
||||
}
|
||||
|
||||
// 👇 Reads live from appsettings.json every time — picks up changes without restart
|
||||
// Reads live from appsettings.json every time — picks up changes without restart
|
||||
var excludedEmails = new HashSet<string>(
|
||||
_configuration.GetSection("Canvass:EmailSettings:ExcludedEmails")
|
||||
.Get<List<string>>() ?? new List<string>(),
|
||||
@ -155,13 +153,5 @@ namespace CPRNIMS.Infrastructure.Helper
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
IsAuthError = true;
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message;
|
||||
Console.WriteLine($"Error in SendEmailAsync: {message}");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,28 +1,29 @@
|
||||
using CPRNIMS.Infrastructure.Database;
|
||||
using CPRNIMS.Domain.Contracts.Account;
|
||||
using CPRNIMS.Domain.Contracts.Canvass;
|
||||
using CPRNIMS.Domain.Contracts.Finance;
|
||||
using CPRNIMS.Domain.Contracts.Inventory;
|
||||
using CPRNIMS.Domain.Contracts.Items;
|
||||
using CPRNIMS.Domain.Contracts.PO;
|
||||
using CPRNIMS.Domain.Contracts.PR;
|
||||
using CPRNIMS.Domain.Contracts.Receiving;
|
||||
using CPRNIMS.Domain.Contracts.SMTP;
|
||||
using CPRNIMS.Domain.Services;
|
||||
using CPRNIMS.Domain.Services.Account;
|
||||
using CPRNIMS.Domain.Services.Canvass;
|
||||
using CPRNIMS.Domain.Services.Finance;
|
||||
using CPRNIMS.Domain.Services.Inventory;
|
||||
using CPRNIMS.Domain.Services.PO;
|
||||
using CPRNIMS.Domain.Services.Receiving;
|
||||
using CPRNIMS.Domain.Services.SMTP;
|
||||
using CPRNIMS.Infrastructure.Database;
|
||||
using CPRNIMS.Infrastructure.Entities.Account;
|
||||
using CPRNIMS.Infrastructure.Helper;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Microsoft.OpenApi.Models;
|
||||
using System.Text;
|
||||
using CPRNIMS.Domain.Services.Account;
|
||||
using CPRNIMS.Domain.Contracts.Account;
|
||||
using CPRNIMS.Domain.Services;
|
||||
using CPRNIMS.Domain.Contracts.Items;
|
||||
using CPRNIMS.Domain.Contracts.PR;
|
||||
using CPRNIMS.Domain.Contracts.Canvass;
|
||||
using CPRNIMS.Domain.Contracts.SMTP;
|
||||
using CPRNIMS.Domain.Services.SMTP;
|
||||
using CPRNIMS.Infrastructure.Helper;
|
||||
using CPRNIMS.Domain.Contracts.PO;
|
||||
using CPRNIMS.Domain.Services.PO;
|
||||
using CPRNIMS.Domain.Contracts.Finance;
|
||||
using CPRNIMS.Domain.Services.Finance;
|
||||
using CPRNIMS.Domain.Contracts.Inventory;
|
||||
using CPRNIMS.Domain.Services.Inventory;
|
||||
using CPRNIMS.Domain.Contracts.Receiving;
|
||||
using CPRNIMS.Domain.Services.Receiving;
|
||||
|
||||
|
||||
namespace CPRNIMS.WebApi.Common
|
||||
@ -150,7 +151,12 @@ namespace CPRNIMS.WebApi.Common
|
||||
services.AddScoped<IAttachment, Domain.Services.Account.Attachment>();
|
||||
services.AddScoped<IItem, Domain.Services.Items.Item>();
|
||||
services.AddScoped<IPRequest, Domain.Services.PR.PRequest>();
|
||||
services.AddScoped<ICanvass, Domain.Services.Canvass.Canvass>();
|
||||
services.AddScoped<ICanvass, Canvass>();
|
||||
|
||||
#region Automation using LLM
|
||||
services.AddHttpClient<SupplierSearchService>();
|
||||
#endregion
|
||||
|
||||
services.AddScoped<IRR, RR>();
|
||||
services.AddScoped<IReceiving, Receiving>();
|
||||
services.AddScoped <ISMTP, SMTP>();
|
||||
|
||||
@ -55,17 +55,10 @@ namespace CPRNIMS.WebApi.Controllers.Base
|
||||
[AllowAnonymous]
|
||||
[HttpPost("{GetRelativePath}")]
|
||||
public string GetRelativePath(string relativePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
string templateFolderPath = Path.Combine(_webHostEnvironment.ContentRootPath, relativePath);
|
||||
return templateFolderPath;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[NonAction]
|
||||
[HttpPost("{ErrMessage}")]
|
||||
public async Task PostErrorMessage(string errMessage, string appName)
|
||||
|
||||
@ -1,8 +1,10 @@
|
||||
using CPRNIMS.Domain.Contracts.Canvass;
|
||||
using CPRNIMS.Domain.Contracts.SMTP;
|
||||
using AutoMapper;
|
||||
using CPRNIMS.Domain.Contracts.Canvass;
|
||||
using CPRNIMS.Domain.Services;
|
||||
using CPRNIMS.Domain.Services.Canvass;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass;
|
||||
using CPRNIMS.Infrastructure.Entities.Canvass;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Request;
|
||||
using CPRNIMS.Infrastructure.Dto.Canvass.Response;
|
||||
using CPRNIMS.Infrastructure.Helper;
|
||||
using CPRNIMS.Infrastructure.ViewModel.Canvass;
|
||||
using CPRNIMS.Infrastructure.ViewModel.Common;
|
||||
@ -17,15 +19,19 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
|
||||
private readonly SMTPHelper _smtpHelper;
|
||||
private readonly ICanvass _canvass;
|
||||
private readonly IConfiguration _config;
|
||||
|
||||
private readonly SupplierSearchService _supplierSearchService;
|
||||
private readonly IMapper _mapper;
|
||||
public CanvassMgmtController(ErrorMessageService errorMessageService,
|
||||
IWebHostEnvironment webHostEnvironment, SMTPHelper sMTPHelper,
|
||||
IConfiguration configuration, ICanvass canvass) :
|
||||
IConfiguration configuration, ICanvass canvass, SupplierSearchService supplierSearchService,
|
||||
IMapper mapper) :
|
||||
base(errorMessageService, webHostEnvironment, configuration)
|
||||
{
|
||||
_canvass = canvass;
|
||||
_config = configuration;
|
||||
_smtpHelper = sMTPHelper;
|
||||
_supplierSearchService= supplierSearchService;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
#region Get
|
||||
@ -350,9 +356,7 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
|
||||
[HttpPost("PostTaggingSupplier")]
|
||||
public async Task<IActionResult> PostTaggingSupplier([FromBody] CanvassVM canvassVM)
|
||||
{
|
||||
try
|
||||
{
|
||||
var supplier = new Suppliers();
|
||||
var supplier = new SupplierResponse();
|
||||
foreach (var items in canvassVM.SupplierList.SupplierId)
|
||||
{
|
||||
var index = canvassVM.SupplierList.SupplierId.IndexOf(items);
|
||||
@ -375,18 +379,10 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
|
||||
}
|
||||
return Ok(supplier);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.Message ?? ex.Message;
|
||||
return BadRequest(new { ErrMessage = message, ErrCode = 0 });
|
||||
}
|
||||
}
|
||||
[HttpPost("PostPutItemTagging")]
|
||||
public async Task<IActionResult> PostPutItemTagging([FromBody] CanvassVM canvassVM)
|
||||
{
|
||||
try
|
||||
{
|
||||
var supplier = new Suppliers();
|
||||
var supplier = new SupplierResponse();
|
||||
foreach (var items in canvassVM.ItemList.ItemNo)
|
||||
{
|
||||
var index = canvassVM.ItemList.ItemNo.IndexOf(items);
|
||||
@ -403,20 +399,10 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
|
||||
}
|
||||
return Ok(supplier);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.Message ?? ex.Message;
|
||||
return BadRequest(new { ErrMessage = message, ErrCode = 0 });
|
||||
}
|
||||
}
|
||||
[HttpPost("PostCanvass")]
|
||||
public async Task<IActionResult> PostCanvass([FromBody] CanvassVM canvassVM)
|
||||
{
|
||||
try
|
||||
{
|
||||
var baseTemplate = "n/a";
|
||||
|
||||
baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "SendToSupplier.cshtml");
|
||||
var baseTemplate = EMailTemplate("Content\\SMTPEmailContent", "SendToSupplier.cshtml");
|
||||
|
||||
var CanvassDto = new CanvassDto();
|
||||
int canvassNo = await _canvass.GetCanvassNo();
|
||||
@ -464,29 +450,202 @@ namespace CPRNIMS.WebApi.Controllers.Canvass
|
||||
|
||||
return Ok(pR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
[HttpPost("PostSearchSupplierAndSend")]
|
||||
public async Task<IActionResult> PostSearchSupplierAndSend(CancellationToken ct)
|
||||
{
|
||||
var errorMessage = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(errorMessage + " PostCanvass", "WebApi");
|
||||
throw;
|
||||
// #1 Get top 10 items without suppliers — must process all
|
||||
var response = await _canvass.GetItemWithoutSupplier();
|
||||
if (response == null || !response.Any()) return BadRequest("No items found.");
|
||||
|
||||
var supplierResults = new List<object>();
|
||||
|
||||
foreach (var item in response) // ✅ FIX #1: use loop variable, not response[0]
|
||||
{
|
||||
// #2 Search Tavily + Filter with Groq
|
||||
var suppliers = await _supplierSearchService
|
||||
.SearchAndFilterSuppliersAsync(item.ItemName, item.ItemDescription);
|
||||
|
||||
if (!suppliers.Any())
|
||||
{
|
||||
await _canvass.SearchingUpdate(item.PRDetailsId);
|
||||
continue;
|
||||
}
|
||||
|
||||
// #3 & #4 Loop each found supplier
|
||||
foreach (var supplier in suppliers)
|
||||
{
|
||||
int canvassNo = await _canvass.GetCanvassNo();
|
||||
|
||||
var supplierRequest = _mapper.Map<SupplierRequest>(supplier);
|
||||
supplierRequest.ItemNo = item.ItemNo;
|
||||
|
||||
var result = await _canvass.PostSupplierAsync(supplierRequest, ct);
|
||||
if (result?.Value == null) continue;
|
||||
|
||||
var canvassDto = new CanvassDto
|
||||
{
|
||||
PRDetailsId = item.PRDetailsId,
|
||||
PRNo = item.PRNo,
|
||||
ItemNo = item.ItemNo,
|
||||
SupplierId = result.Value.SupplierId,
|
||||
UserId = item.UserId,
|
||||
FullName = item.FullName,
|
||||
CanvassNo = ++canvassNo,
|
||||
};
|
||||
|
||||
await _canvass.PostPerSupplierToken(canvassDto);
|
||||
|
||||
var rfq = await _canvass.GetRFQ(canvassDto);
|
||||
if (rfq == null || !rfq.Any()) continue;
|
||||
|
||||
var supplierEmailRequest = new SupplierEmailRequest
|
||||
{
|
||||
AttachPath = GetRelativePath(@"Content\\Documents\\Pdf\\Offer_Submission_Procedure.pdf"),
|
||||
Recipient = "rmsoriano@lloydlab.com",//rfq[0].EmailAddress, // this will be implemented later
|
||||
Subject = $"CLMS - Request For Quotation #PRNo: {rfq[0].AggrePRNo}",
|
||||
CC = Convert.ToString(_configuration["Canvass:CC"] ?? ""),
|
||||
SenderEmail = _config["SMTP:SenderEmail"],
|
||||
DisplayName = "lloydlabinc.com",
|
||||
Password = _config["SMTP:Password"],
|
||||
OutGoingPort = 587,
|
||||
Server = _config["SMTP:Server"],
|
||||
UserName = _config["SMTP:UserName"],
|
||||
FormLink = Convert.ToString(_configuration["WebEndPoint:SupplierForm"] ?? ""),
|
||||
Token = rfq[0].Token,
|
||||
SupplierName = result.Value.SupplierName,
|
||||
Purchaser = item.FullName,
|
||||
IsSuccess = false,
|
||||
IsCanvass = true,
|
||||
};
|
||||
|
||||
await _canvass.SearchingUpdate(item.PRDetailsId);
|
||||
await _canvass.SendRFQ(supplierEmailRequest);
|
||||
|
||||
supplierResults.Add(new
|
||||
{
|
||||
item = item.ItemName,
|
||||
supplier = supplier.SupplierName,
|
||||
email = supplier.EmailAddress,
|
||||
canvassNo = canvassDto.CanvassNo
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
totalProcessed = supplierResults.Count,
|
||||
suppliers = supplierResults
|
||||
});
|
||||
}
|
||||
/* [HttpPost("PostSearchSupplierAndSend")]
|
||||
public async Task<IActionResult> PostSearchSupplierAndSend(CancellationToken ct)
|
||||
{
|
||||
// #1 Get top 10 item without suppliers must be process all
|
||||
var response = await _canvass.GetItemWithoutSupplier();
|
||||
if (response == null || !response.Any()) return BadRequest("No items found.");
|
||||
|
||||
var supplierResults = new List<object>();
|
||||
|
||||
foreach (var supplierList in response)
|
||||
{
|
||||
|
||||
var item = response[0];
|
||||
|
||||
// #2 Search Tavily + Filter with Groq
|
||||
var suppliers = await _supplierSearchService
|
||||
.SearchAndFilterSuppliersAsync(item.ItemName, item.ItemDescription);
|
||||
|
||||
if (!suppliers.Any())
|
||||
{
|
||||
await _canvass.SearchingUpdate(supplierList.PRDetailsId);
|
||||
continue;
|
||||
}
|
||||
|
||||
var results = new List<object>();
|
||||
|
||||
// #3 & #4 Loop each found supplier
|
||||
foreach (var supplier in suppliers)
|
||||
{
|
||||
int canvassNo = await _canvass.GetCanvassNo();
|
||||
|
||||
// Map SupplierResponse → SupplierRequest before saving
|
||||
var supplierRequest = _mapper.Map<SupplierRequest>(supplier);
|
||||
|
||||
supplierRequest.ItemNo=item.ItemNo;
|
||||
|
||||
var result = await _canvass.PostSupplierAsync(supplierRequest, ct);
|
||||
|
||||
if (result?.Value == null) continue;
|
||||
|
||||
var canvassDto = new CanvassDto
|
||||
{
|
||||
PRDetailsId = item.PRDetailsId,
|
||||
PRNo = item.PRNo,
|
||||
ItemNo = item.ItemNo,
|
||||
SupplierId = result.Value.SupplierId,
|
||||
UserId = item.UserId,
|
||||
FullName = item.FullName,
|
||||
CanvassNo = ++canvassNo,
|
||||
};
|
||||
|
||||
// Generate token for supplier form link
|
||||
await _canvass.PostPerSupplierToken(canvassDto);
|
||||
|
||||
// Get RFQ details
|
||||
var rfq = await _canvass.GetRFQ(canvassDto);
|
||||
|
||||
if (rfq == null || !rfq.Any()) continue;
|
||||
|
||||
// Send RFQ email
|
||||
var email = rfq[0].EmailAddress;
|
||||
var supplierEmailRequest = new SupplierEmailRequest
|
||||
{
|
||||
AttachPath = GetRelativePath(@"Content\\Documents\\Pdf\\Offer_Submission_Procedure.pdf"),
|
||||
Recipient = "rmsoriano@lloydlab.com",//rfq[0].EmailAddress, // this will be implemented later
|
||||
Subject = $"CLMS - Request For Quotation #PRNo: {rfq[0].AggrePRNo}",
|
||||
CC = Convert.ToString(_configuration["Canvass:CC"] ?? ""),
|
||||
SenderEmail = _config["SMTP:SenderEmail"],
|
||||
DisplayName = "lloydlabinc.com",
|
||||
Password = _config["SMTP:Password"],
|
||||
OutGoingPort = 587,
|
||||
Server = _config["SMTP:Server"],
|
||||
UserName = _config["SMTP:UserName"],
|
||||
FormLink= Convert.ToString(_configuration["WebEndPoint:SupplierForm"] ?? ""),
|
||||
Token = rfq[0].Token,
|
||||
SupplierName= result.Value.SupplierName,
|
||||
Purchaser= item.FullName,
|
||||
IsSuccess = false,
|
||||
IsCanvass = true,
|
||||
};
|
||||
await _canvass.SearchingUpdate(supplierList.PRDetailsId);
|
||||
|
||||
await _canvass.SendRFQ(supplierEmailRequest);
|
||||
|
||||
results.Add(new
|
||||
{
|
||||
supplier = supplier.SupplierName,
|
||||
email = supplier.EmailAddress,
|
||||
canvassNo = canvassDto.CanvassNo
|
||||
});
|
||||
}
|
||||
|
||||
return Ok(new
|
||||
{
|
||||
item = item.ItemName,
|
||||
processed = results.Count,
|
||||
suppliers = results
|
||||
});
|
||||
}
|
||||
return Ok();
|
||||
}*/
|
||||
|
||||
[HttpPost("PostSuggestedSupp")]
|
||||
public async Task<IActionResult> PostSuggestedSupp(CanvassDto CanvassDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pR = await _canvass.PostSuggestedSupp(CanvassDto);
|
||||
|
||||
return Ok(pR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message + " PostSuggestedSupp", "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost("PostApprovedSupp")]
|
||||
public async Task<IActionResult> PostApprovedSupp(CanvassDto CanvassDto)
|
||||
{
|
||||
|
||||
@ -123,84 +123,39 @@ namespace CPRNIMS.WebApi.Controllers.Receiving
|
||||
}
|
||||
[HttpPost("GetForReceiving")]
|
||||
public async Task<IActionResult> GetForReceiving(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var myPR = await _receiving.GetForReceiving(itemDto);
|
||||
|
||||
return Ok(myPR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message, "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost("GetRR")]
|
||||
public async Task<IActionResult> GetRR(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var myPR = await _receiving.GetRR(itemDto);
|
||||
|
||||
return Ok(myPR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message, "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost("GetRRDetailByPO")]
|
||||
public async Task<IActionResult> GetRRDetailByPO(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var myPR = await _receiving.GetRRDetailByPO(itemDto);
|
||||
|
||||
return Ok(myPR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message + "GetPRByRRId", "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost("GetRRDetail")]
|
||||
public async Task<IActionResult> GetRRDetail(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var myPR = await _receiving.GetRRDetail(itemDto);
|
||||
|
||||
return Ok(myPR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message + "GetRRDetail", "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
[HttpPost("GetLatestRRNo")]
|
||||
public async Task<IActionResult> GetLatestRRNo(ItemDto itemDto)
|
||||
{
|
||||
try
|
||||
{
|
||||
var myPR = await _receiving.GetLatestRRNo(itemDto);
|
||||
|
||||
return Ok(myPR);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var message = ex.InnerException?.ToString() ?? ex.Message.ToString();
|
||||
await PostErrorMessage(message + "GetLatestRRNo", "WebApi");
|
||||
throw;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
using CPRNIMS.Domain.Profile.Canvass;
|
||||
using CPRNIMS.Middleware;
|
||||
using CPRNIMS.WebApi.Common;
|
||||
|
||||
@ -5,6 +6,8 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddApplicationServices(builder);
|
||||
|
||||
builder.Services.AddAutoMapper(cfg => { }, typeof(SupplierRequestProfile));
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
<!-- Client field (positioned where CLIENT field is on form) -->
|
||||
<div style="position: absolute; top:120px !important; left: 35px;">
|
||||
<span id="client" >LLOD LABORATORIES INC.</span>
|
||||
<span id="client" >LLOYD LABORATORIES INC.</span>
|
||||
</div>
|
||||
|
||||
<!-- Date field (positioned where DATE field is on form) -->
|
||||
|
||||
Loading…
Reference in New Issue
Block a user