Merge branch '4.80' of https://git.aycode.com/Adam/Mango.Nop.Plugins into 4.80
This commit is contained in:
commit
015f42bef9
|
|
@ -52,11 +52,12 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
private readonly IProductService _productService;
|
||||
private readonly IStoreContext _storeContext;
|
||||
private readonly IWorkContext _workContext;
|
||||
private readonly IPriceCalculationService _priceCalculationService;
|
||||
// ... other dependencies
|
||||
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public CustomOrderController(FruitBankDbContext fruitBankDbContext, IOrderService orderService, IOrderModelFactory orderModelFactory, ICustomOrderSignalREndpointServer customOrderSignalREndpoint, IPermissionService permissionService, IGenericAttributeService genericAttributeService, INotificationService notificationService, ICustomerService customerService, IProductService productService, IEnumerable<IAcLogWriterBase> logWriters, IStoreContext storeContext, IWorkContext workContext)
|
||||
public CustomOrderController(FruitBankDbContext fruitBankDbContext, IOrderService orderService,IPriceCalculationService priceCalculationService, IOrderModelFactory orderModelFactory, ICustomOrderSignalREndpointServer customOrderSignalREndpoint, IPermissionService permissionService, IGenericAttributeService genericAttributeService, INotificationService notificationService, ICustomerService customerService, IProductService productService, IEnumerable<IAcLogWriterBase> logWriters, IStoreContext storeContext, IWorkContext workContext)
|
||||
{
|
||||
_logger = new Logger<CustomOrderController>(logWriters.ToArray());
|
||||
|
||||
|
|
@ -71,6 +72,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
_productService = productService;
|
||||
_storeContext = storeContext;
|
||||
_workContext = workContext;
|
||||
_priceCalculationService = priceCalculationService;
|
||||
// ... initialize other deps
|
||||
}
|
||||
|
||||
|
|
@ -78,6 +80,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
[NonAction] public Task<List<OrderDto>> GetAllOrderDtos() => _customOrderSignalREndpoint.GetAllOrderDtos();
|
||||
[NonAction]public Task<OrderDto> GetOrderDtoById(int orderId) => _customOrderSignalREndpoint.GetOrderDtoById(orderId);
|
||||
[NonAction]public Task<List<OrderDto>> GetPendingOrderDtos() => _customOrderSignalREndpoint.GetPendingOrderDtos();
|
||||
[NonAction]public Task<List<OrderDto>> GetPendingOrderDtosForMeasuring() => _customOrderSignalREndpoint.GetPendingOrderDtosForMeasuring();
|
||||
[NonAction] public Task<OrderDto> StartMeasuring(int orderId, int userId) => _customOrderSignalREndpoint.StartMeasuring(orderId, userId);
|
||||
[NonAction]public Task<OrderDto> SetOrderStatusToComplete(int orderId, int revisorId) => _customOrderSignalREndpoint.SetOrderStatusToComplete(orderId, revisorId);
|
||||
[NonAction] public Task<List<OrderDto>> GetAllOrderDtoByIds(int[] orderIds) => _customOrderSignalREndpoint.GetAllOrderDtoByIds(orderIds);
|
||||
|
|
@ -116,10 +119,10 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
//return _customOrderService.
|
||||
var orderListModel = await _orderModelFactory.PrepareOrderListModelExtendedAsync(searchModel);
|
||||
|
||||
_logger.Debug($"Total: {orderListModel.RecordsTotal}, Data Count: {orderListModel.Data.Count()}");
|
||||
_logger.Detail($"Total: {orderListModel.RecordsTotal}, Data Count: {orderListModel.Data.Count()}");
|
||||
foreach (var item in orderListModel.Data.Take(3))
|
||||
{
|
||||
_logger.Debug($"Order: {item.Id}, {item.CustomOrderNumber}");
|
||||
_logger.Detail($"Order: {item.Id}, {item.CustomOrderNumber}");
|
||||
}
|
||||
|
||||
return orderListModel;
|
||||
|
|
@ -222,7 +225,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
};
|
||||
|
||||
//var productDtosById = await _dbContext.ProductDtos.GetAllByIds(orderProducts.Select(op => op.Id)).ToDictionaryAsync(p => p.Id, prodDto => prodDto);
|
||||
|
||||
var store = _storeContext.GetCurrentStore();
|
||||
var transactionSuccess = await _dbContext.TransactionSafeAsync(async _ =>
|
||||
{
|
||||
await _orderService.InsertOrderAsync(order);
|
||||
|
|
@ -232,6 +235,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
foreach (var item in orderProducts)
|
||||
{
|
||||
var product = await _productService.GetProductByIdAsync(item.Id);
|
||||
|
||||
if (product == null || product.StockQuantity - item.Quantity < 0)
|
||||
{
|
||||
var errorText = $"product == null || product.StockQuantity - item.Quantity < 0; productId: {product?.Id}; product?.StockQuantity - item.Quantity: {product?.StockQuantity - item.Quantity}";
|
||||
|
|
@ -240,6 +244,16 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
throw new Exception($"{errorText}");
|
||||
}
|
||||
|
||||
//var (_, finalUnitPrice, _, _) = await _priceCalculationService.GetFinalPriceAsync(product, customer, store, item.Price, 0, true, item.Quantity, null, null);
|
||||
|
||||
//var (presetPriceInclTax, _) = await _taxService.GetProductPriceAsync(product, finalPrice, true, customer);
|
||||
//var (presetPriceExclTax, _) = await _taxService.GetProductPriceAsync(product, finalPrice, false, customer);
|
||||
//model.UnitPriceExclTax = presetPriceExclTax;
|
||||
//model.UnitPriceInclTax = presetPriceInclTax;
|
||||
//model.Quantity = item.Quantity;
|
||||
//model.SubTotalExclTax = presetPriceExclTax;
|
||||
//model.SubTotalInclTax = presetPriceInclTax;
|
||||
|
||||
//if (productDtosById.TryGetValue(item.Id, out var productDto))
|
||||
{
|
||||
var orderItem = new OrderItem
|
||||
|
|
@ -452,7 +466,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Controllers
|
|||
{
|
||||
result.Add(new
|
||||
{
|
||||
label = $"{product.Name} [KÉSZLET: {product.StockQuantity}]",
|
||||
label = $"{product.Name} [KÉSZLET: {product.StockQuantity}] [ÁR: {product.Price}]",
|
||||
value = product.Id,
|
||||
sku = product.Sku,
|
||||
price = product.Price,
|
||||
|
|
|
|||
|
|
@ -35,6 +35,12 @@ public class CustomOrderSignalREndpoint(FruitBankDbContext ctx, IWorkContext wor
|
|||
return await ctx.OrderDtos.GetAllByOrderStatus(OrderStatus.Pending).ToListAsync();
|
||||
}
|
||||
|
||||
[SignalR(SignalRTags.GetPendingOrderDtosForMeasuring)]
|
||||
public async Task<List<OrderDto>> GetPendingOrderDtosForMeasuring()
|
||||
{
|
||||
return await ctx.OrderDtos.GetAllForMeasuring().ToListAsync();
|
||||
}
|
||||
|
||||
[SignalR(SignalRTags.GetAllOrderDtoByIds)]
|
||||
public async Task<List<OrderDto>> GetAllOrderDtoByIds(int[] orderIds)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -0,0 +1,82 @@
|
|||
@model OrderModel
|
||||
|
||||
|
||||
@{
|
||||
//page title
|
||||
ViewBag.PageTitle = T("Admin.Orders.EditOrderDetails").Text + "ANYÁD";
|
||||
//active menu item (system name)
|
||||
NopHtml.SetActiveMenuItemSystemName("Orders");
|
||||
}
|
||||
|
||||
@{
|
||||
const string hideInfoBlockAttributeName = "OrderPage.HideInfoBlock";
|
||||
var customer = await workContext.GetCurrentCustomerAsync();
|
||||
var hideInfoBlock = await genericAttributeService.GetAttributeAsync<bool>(customer, hideInfoBlockAttributeName);
|
||||
|
||||
const string hideBillingAndShippingBlockAttributeName = "OrderPage.HideBillingAndShippingBlock";
|
||||
var hideBillingAndShippingBlock = await genericAttributeService.GetAttributeAsync<bool>(customer, hideBillingAndShippingBlockAttributeName);
|
||||
|
||||
const string hideProductsBlockAttributeName = "OrderPage.HideProductsBlock";
|
||||
var hideProductsBlock = await genericAttributeService.GetAttributeAsync<bool>(customer, hideProductsBlockAttributeName);
|
||||
|
||||
const string hideNotesBlockAttributeName = "OrderPage.HideNotesBlock";
|
||||
var hideNotesBlock = await genericAttributeService.GetAttributeAsync<bool>(customer, hideNotesBlockAttributeName);
|
||||
}
|
||||
|
||||
<form asp-controller="Order" asp-action="Edit" method="post" id="order-form">
|
||||
<div class="content-header clearfix">
|
||||
<h1 class="float-left">
|
||||
@T("Admin.Orders.EditOrderDetails") - @Model.CustomOrderNumber
|
||||
<small>
|
||||
<i class="fas fa-arrow-circle-left"></i>
|
||||
<a asp-action="List">@T("Admin.Orders.BackToList")</a>
|
||||
</small>
|
||||
</h1>
|
||||
<div class="float-right">
|
||||
<a asp-action="PdfInvoice" asp-route-orderId="@Model.Id" class="btn btn-info">
|
||||
<i class="far fa-file-pdf"></i>
|
||||
@T("Admin.Orders.PdfInvoice")
|
||||
</a>
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<span id="order-delete" class="btn btn-danger">
|
||||
<i class="far fa-trash-can"></i>
|
||||
@T("Admin.Common.Delete")
|
||||
</span>
|
||||
}
|
||||
<button type="submit" id="btnRefreshPage" style="display: none"></button>
|
||||
<script>
|
||||
$(function() {
|
||||
$('#btnRefreshPage').click(function () {
|
||||
//refresh pageed
|
||||
location.reload();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
@await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderDetailsButtons, additionalData = Model })
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div asp-validation-summary="All"></div>
|
||||
|
||||
<section class="content">
|
||||
<div class="container-fluid">
|
||||
<div class="form-horizontal">
|
||||
|
||||
<nop-cards id="order-cards">
|
||||
@await Component.InvokeAsync(typeof(AdminWidgetViewComponent), new { widgetZone = AdminWidgetZones.OrderDetailsBlock, additionalData = Model })
|
||||
<nop-card asp-name="order-info" asp-icon="fas fa-info" asp-title="@T("Admin.Orders.Info")" asp-hide-block-attribute-name="@hideInfoBlockAttributeName" asp-hide="@hideInfoBlock" asp-advanced="false">@await Html.PartialAsync("_OrderDetails.Info", Model)</nop-card>
|
||||
<nop-card asp-name="order-billing-shipping" asp-icon="fas fa-truck" asp-title="@T("Admin.Orders.BillingShippingInfo")" asp-hide-block-attribute-name="@hideBillingAndShippingBlockAttributeName" asp-hide="@hideBillingAndShippingBlock" asp-advanced="false">@await Html.PartialAsync("_OrderDetails.BillingShipping", Model)</nop-card>
|
||||
<nop-card asp-name="order-products" asp-icon="fas fa-table-list" asp-title="@T("Admin.Orders.Products")" asp-hide-block-attribute-name="@hideProductsBlockAttributeName" asp-hide="@hideProductsBlock" asp-advanced="true">@await Html.PartialAsync("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Order/_CustomOrderDetails.Products.cshtml", Model)</nop-card>
|
||||
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<nop-card asp-name="order-notes" asp-icon="far fa-sticky-note" asp-title="@T("Admin.Orders.OrderNotes")" asp-hide-block-attribute-name="@hideNotesBlockAttributeName" asp-hide="@hideNotesBlock" asp-advanced="true">@await Html.PartialAsync("_OrderDetails.Notes", Model)</nop-card>
|
||||
}
|
||||
|
||||
</nop-cards>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
<nop-delete-confirmation asp-model-id="@Model.Id" asp-button-id="order-delete" />
|
||||
|
|
@ -752,8 +752,8 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th style="width: 100px;">Quantity</th>
|
||||
<th style="width: 120px;">Price</th>
|
||||
<th style="width: 100px;">Mennyisség</th>
|
||||
<th style="width: 120px;">Egységár</th>
|
||||
<th style="width: 50px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,399 @@
|
|||
@model OrderModel
|
||||
|
||||
@using Nop.Core.Domain.Tax;
|
||||
@using Nop.Core.Domain.Catalog;
|
||||
|
||||
<div class="card-body">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12" style="overflow-x: auto;">ANYÁD!!!!!
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<script>
|
||||
$(function() {
|
||||
toggleOrderItemEdit@(item.Id)(false);
|
||||
// Attach event listeners for automatic calculation
|
||||
setupAutoCalculation@(item.Id)();
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// Function to automatically calculate and update total price
|
||||
function calculateTotal@(item.Id)() {
|
||||
// Get values
|
||||
var unitPriceInclTax = parseFloat($('#pvUnitPriceInclTax@(item.Id)').val()) || 0;
|
||||
var unitPriceExclTax = parseFloat($('#pvUnitPriceExclTax@(item.Id)').val()) || 0;
|
||||
var quantity = parseFloat($('#pvQuantity@(item.Id)').val()) || 0;
|
||||
var discountInclTax = parseFloat($('#pvDiscountInclTax@(item.Id)').val()) || 0;
|
||||
var discountExclTax = parseFloat($('#pvDiscountExclTax@(item.Id)').val()) || 0;
|
||||
|
||||
// Calculate totals
|
||||
var totalInclTax = (unitPriceInclTax * quantity) - discountInclTax;
|
||||
var totalExclTax = (unitPriceExclTax * quantity) - discountExclTax;
|
||||
|
||||
// Update total price fields
|
||||
$('#pvPriceInclTax@(item.Id)').val(totalInclTax.toFixed(0));
|
||||
$('#pvPriceExclTax@(item.Id)').val(totalExclTax.toFixed(0));
|
||||
}
|
||||
|
||||
// Function to setup event listeners for automatic calculation
|
||||
function setupAutoCalculation@(item.Id)() {
|
||||
// Attach change and input events to all relevant fields
|
||||
$('#pvUnitPriceInclTax@(item.Id), #pvUnitPriceExclTax@(item.Id), #pvQuantity@(item.Id), #pvDiscountInclTax@(item.Id), #pvDiscountExclTax@(item.Id)').on('input change', function() {
|
||||
calculateTotal@(item.Id)();
|
||||
});
|
||||
}
|
||||
|
||||
function toggleOrderItemEdit@(item.Id)(editMode) {
|
||||
if (editMode) {
|
||||
$('#pnlEditPvUnitPrice@(item.Id)').showElement();
|
||||
$('#pnlEditPvQuantity@(item.Id)').showElement();
|
||||
$('#pnlEditPvDiscount@(item.Id)').showElement();
|
||||
$('#pnlEditPvPrice@(item.Id)').showElement();
|
||||
$('#btnSaveOrderItem@(item.Id)').showElement();
|
||||
$('#btnCancelOrderItem@(item.Id)').showElement();
|
||||
|
||||
$('#pvUnitPriceInclTax@(item.Id)').prop("disabled", false);
|
||||
$('#pvUnitPriceExclTax@(item.Id)').prop("disabled", false);
|
||||
$('#pvQuantity@(item.Id)').prop("disabled", false);
|
||||
$('#pvDiscountInclTax@(item.Id)').prop("disabled", false);
|
||||
$('#pvDiscountExclTax@(item.Id)').prop("disabled", false);
|
||||
$('#pvPriceInclTax@(item.Id)').prop("disabled", false);
|
||||
$('#pvPriceExclTax@(item.Id)').prop("disabled", false);
|
||||
|
||||
$('#btnEditOrderItem@(item.Id)').hideElement();
|
||||
$('#btnDeleteOrderItem@(item.Id)').hideElement();
|
||||
} else {
|
||||
$('#pnlEditPvUnitPrice@(item.Id)').hideElement();
|
||||
$('#pnlEditPvQuantity@(item.Id)').hideElement();
|
||||
$('#pnlEditPvDiscount@(item.Id)').hideElement();
|
||||
$('#pnlEditPvPrice@(item.Id)').hideElement();
|
||||
$('#btnSaveOrderItem@(item.Id)').hideElement();
|
||||
$('#btnCancelOrderItem@(item.Id)').hideElement();
|
||||
|
||||
$('#pvUnitPriceInclTax@(item.Id)').prop("disabled", true);
|
||||
$('#pvUnitPriceExclTax@(item.Id)').prop("disabled", true);
|
||||
$('#pvQuantity@(item.Id)').prop("disabled", true);
|
||||
$('#pvDiscountInclTax@(item.Id)').prop("disabled", true);
|
||||
$('#pvDiscountExclTax@(item.Id)').prop("disabled", true);
|
||||
$('#pvPriceInclTax@(item.Id)').prop("disabled", true);
|
||||
$('#pvPriceExclTax@(item.Id)').prop("disabled", true);
|
||||
|
||||
$('#btnEditOrderItem@(item.Id)').showElement();
|
||||
$('#btnDeleteOrderItem@(item.Id)').showElement();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
}
|
||||
|
||||
<table class="table table-hover table-bordered">
|
||||
<col />
|
||||
<col />
|
||||
@if (Model.HasDownloadableProducts)
|
||||
{
|
||||
<col />
|
||||
}
|
||||
<col />
|
||||
<col />
|
||||
<col />
|
||||
<col />
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<col />
|
||||
}
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Picture")
|
||||
</th>
|
||||
<th>
|
||||
@T("Admin.Orders.Products.ProductName")
|
||||
</th>
|
||||
@if (Model.HasDownloadableProducts)
|
||||
{
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Download")
|
||||
</th>
|
||||
}
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Price")
|
||||
</th>
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Quantity")
|
||||
</th>
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Discount")
|
||||
</th>
|
||||
<th>
|
||||
@T("Admin.Orders.Products.Total")
|
||||
</th>
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<th>
|
||||
@T("Admin.Common.Edit")
|
||||
</th>
|
||||
}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach (var item in Model.Items)
|
||||
{
|
||||
<tr>
|
||||
<td class="text-center preview">
|
||||
<img src="@item.PictureThumbnailUrl" alt="" title="" />
|
||||
</td>
|
||||
<td style="width: 25%;" class="text-left">
|
||||
<em><a asp-controller="Product" asp-action="Edit" asp-route-id="@item.ProductId">@item.ProductName</a></em>
|
||||
@if (!string.IsNullOrEmpty(item.AttributeInfo))
|
||||
{
|
||||
<p>
|
||||
@Html.Raw(item.AttributeInfo)
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.RecurringInfo))
|
||||
{
|
||||
<p>
|
||||
@Html.Raw(item.RecurringInfo)
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.RentalInfo))
|
||||
{
|
||||
<p>
|
||||
@Html.Raw(item.RentalInfo)
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.Sku))
|
||||
{
|
||||
<p>
|
||||
<strong>@T("Admin.Orders.Products.SKU")</strong><text>:</text>
|
||||
@item.Sku
|
||||
</p>
|
||||
}
|
||||
@if (!string.IsNullOrEmpty(item.VendorName))
|
||||
{
|
||||
<p>
|
||||
<strong>@T("Admin.Orders.Products.Vendor")</strong><text>:</text>
|
||||
@item.VendorName
|
||||
</p>
|
||||
}
|
||||
@if (item.ReturnRequests.Count > 0)
|
||||
{
|
||||
<p>
|
||||
@T("Admin.Orders.Products.ReturnRequests")<text>:</text>
|
||||
@for (var i = 0; i < item.ReturnRequests.Count; i++)
|
||||
{
|
||||
var returnRequest = item.ReturnRequests[i];
|
||||
<a asp-controller="ReturnRequest" asp-action="Edit" asp-route-id="@returnRequest.Id">@returnRequest.CustomNumber</a>
|
||||
if (i != item.ReturnRequests.Count - 1)
|
||||
{
|
||||
<text>, </text>
|
||||
}
|
||||
}
|
||||
</p>
|
||||
}
|
||||
</td>
|
||||
@if (Model.HasDownloadableProducts)
|
||||
{
|
||||
<td style="width: 15%;" class="text-center">
|
||||
@if (item.IsDownload)
|
||||
{
|
||||
<a asp-controller="Download" asp-action="DownloadFile" asp-route-orderItemId="@item.Id">
|
||||
@T("Admin.Orders.Products.Download.Download")
|
||||
</a>
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@T("Admin.Orders.Products.Download.NotAvailable")
|
||||
}
|
||||
</td>
|
||||
}
|
||||
<td style="width: 15%;" class="text-center">
|
||||
@if (Model.AllowCustomersToSelectTaxDisplayType)
|
||||
{
|
||||
<div>@Html.Raw(item.UnitPriceInclTax)</div>
|
||||
<div>@Html.Raw(item.UnitPriceExclTax)</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Model.TaxDisplayType)
|
||||
{
|
||||
case TaxDisplayType.ExcludingTax:
|
||||
{
|
||||
@Html.Raw(item.UnitPriceExclTax)
|
||||
}
|
||||
break;
|
||||
case TaxDisplayType.IncludingTax:
|
||||
{
|
||||
@Html.Raw(item.UnitPriceInclTax)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
<div id="pnlEditPvUnitPrice@(item.Id)">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.InclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvUnitPriceInclTax@(item.Id)" type="text" value="@item.UnitPriceInclTaxValue" id="pvUnitPriceInclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.ExclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvUnitPriceExclTax@(item.Id)" type="text" value="@item.UnitPriceExclTaxValue" id="pvUnitPriceExclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="width: 10%;" class="text-center">
|
||||
<div>@item.Quantity</div>
|
||||
<div id="pnlEditPvQuantity@(item.Id)">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-8 offset-md-2">
|
||||
<input name="pvQuantity@(item.Id)" type="text" value="@item.Quantity" id="pvQuantity@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="width: 15%;" class="text-center">
|
||||
@if (Model.AllowCustomersToSelectTaxDisplayType)
|
||||
{
|
||||
<div>@Html.Raw(item.DiscountInclTax)</div>
|
||||
<div>@Html.Raw(item.DiscountExclTax)</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Model.TaxDisplayType)
|
||||
{
|
||||
case TaxDisplayType.ExcludingTax:
|
||||
{
|
||||
@Html.Raw(item.DiscountExclTax)
|
||||
}
|
||||
break;
|
||||
case TaxDisplayType.IncludingTax:
|
||||
{
|
||||
@Html.Raw(item.DiscountInclTax)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
<div id="pnlEditPvDiscount@(item.Id)">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.InclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvDiscountInclTax@(item.Id)" type="text" value="@item.DiscountInclTaxValue" id="pvDiscountInclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.ExclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvDiscountExclTax@(item.Id)" type="text" value="@item.DiscountExclTaxValue" id="pvDiscountExclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td style="width: 15%;" class="text-center">
|
||||
@if (Model.AllowCustomersToSelectTaxDisplayType)
|
||||
{
|
||||
<div>@Html.Raw(item.SubTotalInclTax)</div>
|
||||
<div>@Html.Raw(item.SubTotalExclTax)</div>
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (Model.TaxDisplayType)
|
||||
{
|
||||
case TaxDisplayType.ExcludingTax:
|
||||
{
|
||||
@Html.Raw(item.SubTotalExclTax)
|
||||
}
|
||||
break;
|
||||
case TaxDisplayType.IncludingTax:
|
||||
{
|
||||
@Html.Raw(item.SubTotalInclTax)
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
<div id="pnlEditPvPrice@(item.Id)">
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.InclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvPriceInclTax@(item.Id)" type="text" value="@item.SubTotalInclTaxValue" id="pvPriceInclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group row">
|
||||
<div class="col-md-5">
|
||||
@T("Admin.Orders.Products.Edit.ExclTax")
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<input name="pvPriceExclTax@(item.Id)" type="text" value="@item.SubTotalExclTaxValue" id="pvPriceExclTax@(item.Id)" class="form-control input-sm" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<td style="width: 15%;" class="text-center">
|
||||
<button type="submit" class="btn btn-default" name="btnEditOrderItem@(item.Id)" onclick="toggleOrderItemEdit@(item.Id)(true);return false;" id="btnEditOrderItem@(item.Id)">
|
||||
<i class="fas fa-pencil"></i>
|
||||
@T("Admin.Common.Edit")
|
||||
</button>
|
||||
|
||||
<button type="submit" class="btn btn-default" name="btnDeleteOrderItem@(item.Id)" id="btnDeleteOrderItem@(item.Id)">
|
||||
<i class="far fa-trash-can"></i>
|
||||
@T("Admin.Common.Delete")
|
||||
</button>
|
||||
<nop-action-confirmation asp-button-id="@("btnDeleteOrderItem" + item.Id)" />
|
||||
|
||||
<button type="submit" class="btn btn-default" name="btnSaveOrderItem@(item.Id)" id="btnSaveOrderItem@(item.Id)">
|
||||
<i class="far fa-floppy-disk"></i>
|
||||
@T("Admin.Common.Save")
|
||||
</button>
|
||||
<nop-action-confirmation asp-button-id="@("btnSaveOrderItem" + item.Id)" />
|
||||
|
||||
<button type="submit" class="btn btn-default" name="btnCancelOrderItem@(item.Id)" onclick="toggleOrderItemEdit@(item.Id)(false);return false;" id="btnCancelOrderItem@(item.Id)">
|
||||
<i class="fas fa-times"></i>
|
||||
@T("Admin.Common.Cancel")
|
||||
</button>
|
||||
</td>
|
||||
}
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
@if (!string.IsNullOrEmpty(Model.CheckoutAttributeInfo) && !Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
@Html.Raw(Model.CheckoutAttributeInfo)
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@if (!Model.IsLoggedInAsVendor)
|
||||
{
|
||||
<div class="form-group row">
|
||||
<div class="col-md-12">
|
||||
<button type="submit" id="btnAddNewProduct" name="btnAddNewProduct" onclick="javascript:setLocation('@(Url.Action("AddProductToOrder", "Order", new { orderId = Model.Id }))'); return false;" class="btn btn-primary">
|
||||
@T("Admin.Orders.Products.AddNew")
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
|
|
@ -74,4 +74,5 @@
|
|||
@using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin
|
||||
|
||||
@* @using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Components *@
|
||||
@using DevExtreme.AspNet.Mvc
|
||||
@using DevExtreme.AspNet.Mvc
|
||||
@using Nop.Web.Areas.Admin.Models.Orders;
|
||||
|
|
@ -2,22 +2,24 @@
|
|||
using AyCode.Core.Extensions;
|
||||
using AyCode.Core.Loggers;
|
||||
using AyCode.Utils.Extensions;
|
||||
using FruitBank.Common.Dtos;
|
||||
using FruitBank.Common.Entities;
|
||||
using FruitBank.Common.Interfaces;
|
||||
using FruitBank.Common.Models;
|
||||
using Mango.Nop.Core.Extensions;
|
||||
using Mango.Nop.Core.Loggers;
|
||||
using Mango.Nop.Core.Repositories;
|
||||
using Nop.Core;
|
||||
using Nop.Core.Caching;
|
||||
using Nop.Core.Domain.Catalog;
|
||||
using Nop.Core.Domain.Customers;
|
||||
using Nop.Core.Domain.Orders;
|
||||
using Nop.Core.Events;
|
||||
using Nop.Data;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer.Interfaces;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||
using Nop.Services.Catalog;
|
||||
using FruitBank.Common.Dtos;
|
||||
using Mango.Nop.Core.Extensions;
|
||||
using Mango.Nop.Core.Loggers;
|
||||
using Nop.Core.Domain.Orders;
|
||||
using Nop.Services.Security;
|
||||
using WebMarkupMin.Core.Loggers;
|
||||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
||||
|
|
@ -38,6 +40,7 @@ public class FruitBankDbContext : MgDbContextBase,
|
|||
private readonly IStoreContext _storeContext;
|
||||
private readonly IProductService _productService;
|
||||
private readonly IStaticCacheManager _staticCacheManager;
|
||||
protected readonly IEventPublisher _eventPublisher;
|
||||
|
||||
public ProductDtoDbTable ProductDtos { get; set; }
|
||||
|
||||
|
|
@ -55,7 +58,6 @@ public class FruitBankDbContext : MgDbContextBase,
|
|||
public FilesDbTable Files { get; set; }
|
||||
public ShippingDocumentToFilesDbTable ShippingDocumentToFiles { get; set; }
|
||||
|
||||
public IRepository<Product> Products { get; set; }
|
||||
public IRepository<Customer> Customers { get; set; }
|
||||
public IRepository<CustomerRole> CustomerRoles { get; set; }
|
||||
public IRepository<CustomerCustomerRoleMapping> CustomerRoleMappings { get; set; }
|
||||
|
|
@ -65,12 +67,15 @@ public class FruitBankDbContext : MgDbContextBase,
|
|||
ShippingItemPalletDbTable shippingItemPalletDbTable, FilesDbTable filesDbTable, ShippingDocumentToFilesDbTable shippingDocumentToFilesDbTable,
|
||||
ProductDtoDbTable productDtoDbTable, OrderDtoDbTable orderDtoDbTable, OrderItemDtoDbTable orderItemDtoDbTable, OrderItemPalletDbTable orderItemPalletDbTable,
|
||||
IProductService productService, IStaticCacheManager staticCacheManager,
|
||||
IRepository<Order> orderRepository,
|
||||
IRepository<OrderItem> orderItemRepository,
|
||||
IRepository<Product> productRepository,
|
||||
IRepository<Customer> customerRepository,
|
||||
IRepository<CustomerCustomerRoleMapping> customerCustomerRoleMappingRepository,
|
||||
IRepository<CustomerRole> customerRoleRepository,
|
||||
IEnumerable<IAcLogWriterBase> logWriters) : base(dataProvider, lockService, new Logger<FruitBankDbContext>(logWriters.ToArray()))
|
||||
IRepository<CustomerRole> customerRoleRepository,IEventPublisher eventPublisher,
|
||||
IEnumerable<IAcLogWriterBase> logWriters) : base(productRepository, orderRepository, orderItemRepository, dataProvider, lockService, new Logger<FruitBankDbContext>(logWriters.ToArray()))
|
||||
{
|
||||
_eventPublisher = eventPublisher;
|
||||
_storeContext = storeContext;
|
||||
_productService = productService;
|
||||
_staticCacheManager = staticCacheManager;
|
||||
|
|
@ -411,6 +416,8 @@ public class FruitBankDbContext : MgDbContextBase,
|
|||
if (orderDto == null) return null;
|
||||
|
||||
if (!orderDto.IsMeasuredAndValid() || orderDto.OrderStatus == OrderStatus.Complete) return null; //throw new Exception($"SetOrderDtoToComplete; orderDto.IsMeasured == false; {orderDto}");
|
||||
|
||||
var prevOrderStatus = orderDto.OrderStatus;
|
||||
orderDto.OrderStatus = OrderStatus.Complete;
|
||||
|
||||
await OrderDtos.UpdateAsync(orderDto);
|
||||
|
|
@ -435,6 +442,9 @@ public class FruitBankDbContext : MgDbContextBase,
|
|||
(orderItemDto.ProductId, -(orderItemDto.NetWeight-gaNetWeight), orderItemDto.IsMeasurable, true);
|
||||
}
|
||||
|
||||
var order = Orders.GetById(orderDto.Id);
|
||||
await _eventPublisher.PublishAsync(new OrderStatusChangedEvent(order, prevOrderStatus));
|
||||
|
||||
return orderDto;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,5 +33,8 @@ public class OrderDtoDbTable : MgDtoDbTableBase<OrderDto, Order>
|
|||
public IQueryable<OrderDto> GetAllByOrderStatus(OrderStatus orderStatus, bool loadRelations = true)
|
||||
=> GetAll(loadRelations).Where(o => o.OrderStatusId == (int)orderStatus);
|
||||
|
||||
public IQueryable<OrderDto> GetAllForMeasuring(bool loadRelations = true)
|
||||
=> GetAllByOrderStatus(OrderStatus.Pending, loadRelations).Where(o => o.DateOfReceipt != null);
|
||||
|
||||
public IQueryable<OrderDto> GetAllByIds(IEnumerable<int> orderIds, bool loadRelations = true) => GetAll(loadRelations).Where(o => orderIds.Contains(o.Id));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,11 +10,12 @@ using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
|||
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||
using Nop.Services.Events;
|
||||
using Mango.Nop.Core.Extensions;
|
||||
using Nop.Core.Domain.Orders;
|
||||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains.EventConsumers;
|
||||
|
||||
public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBankDbContext ctx, FruitBankAttributeService fruitBankAttributeService, IEnumerable<IAcLogWriterBase> logWriters) :
|
||||
MgEventConsumer(httpContextAcc, logWriters),
|
||||
MgEventConsumerBase(ctx, httpContextAcc, logWriters),
|
||||
IConsumer<EntityDeletedEvent<Shipping>>,
|
||||
IConsumer<EntityInsertedEvent<ShippingItem>>,
|
||||
IConsumer<EntityUpdatedEvent<ShippingItem>>,
|
||||
|
|
@ -24,13 +25,16 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
IConsumer<EntityDeletedEvent<ShippingDocument>>,
|
||||
IConsumer<EntityInsertedEvent<ShippingItemPallet>>,
|
||||
IConsumer<EntityUpdatedEvent<ShippingItemPallet>>,
|
||||
IConsumer<EntityDeletedEvent<ShippingItemPallet>>
|
||||
IConsumer<EntityDeletedEvent<ShippingItemPallet>>,
|
||||
|
||||
IConsumer<EntityInsertedEvent<OrderItem>>,
|
||||
IConsumer<EntityUpdatedEvent<OrderItem>>
|
||||
{
|
||||
public override async Task HandleEventAsync(EntityUpdatedEvent<Product> eventMessage)
|
||||
{
|
||||
var product = eventMessage.Entity;
|
||||
var product = await CheckAndUpdateProductManageInventoryMethodToManageStock(eventMessage.Entity);
|
||||
|
||||
var saveProductCustomAttributesResult = await SaveProductCustomAttributesAsync(eventMessage.Entity);
|
||||
var saveProductCustomAttributesResult = await SaveProductCustomAttributesAsync(product);
|
||||
|
||||
//var isMeasurableProduct = await fruitBankAttributeService.IsMeasurableEntityAsync<Product>(product.Id);
|
||||
|
||||
|
|
@ -52,7 +56,9 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
|
||||
public override async Task HandleEventAsync(EntityInsertedEvent<Product> eventMessage)
|
||||
{
|
||||
await SaveProductCustomAttributesAsync(eventMessage.Entity); //TODO: ez ide miért kell? - J.
|
||||
var product = await CheckAndUpdateProductManageInventoryMethodToManageStock(eventMessage.Entity);
|
||||
|
||||
await SaveProductCustomAttributesAsync(product); //TODO: ez ide miért kell? - J.
|
||||
await base.HandleEventAsync(eventMessage);
|
||||
}
|
||||
|
||||
|
|
@ -124,7 +130,7 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
{
|
||||
return;
|
||||
|
||||
Logger.Info($"HandleEventAsync EntityInsertedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityInsertedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
await UpdateShippingItemMeasuringValuesAsync(eventMessage.Entity);
|
||||
}
|
||||
|
||||
|
|
@ -132,13 +138,13 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
{
|
||||
return;
|
||||
|
||||
Logger.Info($"HandleEventAsync EntityUpdatedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityUpdatedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
await UpdateShippingItemMeasuringValuesAsync(eventMessage.Entity);
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityDeletedEvent<ShippingItemPallet> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityDeletedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityDeletedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await UpdateShippingItemMeasuringValuesAsync(eventMessage.Entity);
|
||||
}
|
||||
|
|
@ -151,7 +157,7 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
|
||||
public async Task HandleEventAsync(EntityInsertedEvent<ShippingItem> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityInsertedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityInsertedEvent<ShippingItemPallet>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await UpdateShippingDocumentIsAllMeasuredAsync(eventMessage.Entity);
|
||||
}
|
||||
|
|
@ -160,7 +166,7 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
|
||||
public async Task HandleEventAsync(EntityUpdatedEvent<ShippingItem> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityUpdatedEvent<ShippingItem>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityUpdatedEvent<ShippingItem>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
var shippingItem = eventMessage.Entity;
|
||||
//var isMeasured = shippingItem.IsValidMeasuringValues();
|
||||
|
|
@ -189,14 +195,14 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
|
||||
public async Task HandleEventAsync(EntityInsertedEvent<ShippingDocument> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityInsertedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityInsertedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await UpdateShippingIsAllMeasuredAsync(eventMessage.Entity);
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityUpdatedEvent<ShippingDocument> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityUpdatedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityUpdatedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await UpdateShippingIsAllMeasuredAsync(eventMessage.Entity);
|
||||
}
|
||||
|
|
@ -219,24 +225,48 @@ public class FruitBankEventConsumer(IHttpContextAccessor httpContextAcc, FruitBa
|
|||
|
||||
public async Task HandleEventAsync(EntityDeletedEvent<Shipping> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityDeletedEvent<Shipping>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityDeletedEvent<Shipping>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await ctx.ShippingDocuments.DeleteAsync(sd => sd.ShippingId == eventMessage.Entity.Id, true);
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityDeletedEvent<ShippingDocument> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityDeletedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityDeletedEvent<ShippingDocument>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await ctx.ShippingItems.DeleteAsync(si => si.ShippingDocumentId == eventMessage.Entity.Id, true);
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityDeletedEvent<ShippingItem> eventMessage)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync EntityDeletedEvent<ShippingItem>; id: {eventMessage.Entity.Id}");
|
||||
Logger.Info($"HandleEventAsync->EntityDeletedEvent<ShippingItem>; id: {eventMessage.Entity.Id}");
|
||||
|
||||
await ctx.ShippingItemPallets.DeleteAsync(sp => sp.ShippingItemId == eventMessage.Entity.Id, false);
|
||||
}
|
||||
|
||||
public async Task HandleEventAsync(EntityUpdatedEvent<OrderItem> eventMessage) => await CheckAndUpdateOrderItemFinalPrices(eventMessage.Entity);
|
||||
|
||||
public async Task HandleEventAsync(EntityInsertedEvent<OrderItem> eventMessage) => await CheckAndUpdateOrderItemFinalPrices(eventMessage.Entity);
|
||||
|
||||
private async Task CheckAndUpdateOrderItemFinalPrices(OrderItem orderItem)
|
||||
{
|
||||
Logger.Info($"HandleEventAsync->CheckAndUpdateOrderItemFinalPrices; orderItem.Id: {orderItem.Id}");
|
||||
|
||||
var finalPriceInclTax = decimal.Round(orderItem.UnitPriceInclTax * orderItem.Quantity, 0);
|
||||
var finalPriceExclTax = decimal.Round(orderItem.UnitPriceExclTax * orderItem.Quantity, 0);
|
||||
|
||||
if (orderItem.PriceInclTax != finalPriceInclTax || orderItem.PriceExclTax != finalPriceExclTax)
|
||||
{
|
||||
Logger.Error($"HandleEventAsync->CheckAndUpdateOrderItemFinalPrices; " +
|
||||
$"orderItem.PriceInclTax({orderItem.PriceInclTax}) != finalPriceInclTax({finalPriceInclTax}) || " +
|
||||
$"orderItem.PriceExclTax({orderItem.PriceExclTax}) != finalPriceExclTax({finalPriceExclTax})");
|
||||
|
||||
orderItem.PriceInclTax = finalPriceInclTax;
|
||||
orderItem.PriceExclTax = finalPriceExclTax;
|
||||
|
||||
await ctx.OrderItems.UpdateAsync(orderItem, false);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Delete
|
||||
}
|
||||
|
|
@ -176,7 +176,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Factories
|
|||
//orderModelExtended.IsMeasurable = await ShouldMarkAsNeedsMeasurementAsync(orderModel);
|
||||
//orderModelExtended.DateOfReceipt = await GetPickupDateTimeAsync(orderModel);
|
||||
|
||||
Console.WriteLine(orderModelExtended.Id);
|
||||
//Console.WriteLine(orderModelExtended.Id);
|
||||
});
|
||||
|
||||
return orderListModelExtended;
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Areas\Admin\Views\Order\Edit.cshtml" />
|
||||
<None Remove="logo.jpg" />
|
||||
<None Remove="plugin.json" />
|
||||
<None Remove="Views\_ViewImports.cshtml" />
|
||||
|
|
@ -40,6 +41,16 @@
|
|||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Areas\Admin\Views\Order\Edit.cshtml">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Areas\Admin\Views\Order\_CustomOrderDetails.Products.cshtml">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Areas\Admin\Views\Product\List.cshtml">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
|
|
|
|||
|
|
@ -21,9 +21,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
var store = await _storeContext.GetCurrentStoreAsync();
|
||||
var storeName = store.Name;
|
||||
var storeCompanyName = store.CompanyName;
|
||||
string systemMessage = $"You are a helpful assistant of a webshop called {storeName}, of the company {storeCompanyName}, you work in the administration area, with the ADMIN user. The ADMIN user is {customer.FirstName}. Date and time is {DateTime.Now} When the user greets you, answer with a warm HUNGARIAN welcome message, incorporating some reference of the time, and maybe the weather too, making it pleasant for the ADMIN user to start working with the shop system. Assure the user that AI connection is established and you are ready to assist them.";
|
||||
var systemMessage = $"You are a helpful assistant of a webshop called {storeName}, of the company {storeCompanyName}, you work in the administration area, with the ADMIN user. The ADMIN user is {customer.FirstName}. Date and time is {DateTime.Now} When the user greets you, answer with a warm HUNGARIAN welcome message, incorporating some reference of the time, and maybe the weather too, making it pleasant for the ADMIN user to start working with the shop system. Assure the user that AI connection is established and you are ready to assist them.";
|
||||
|
||||
string userMessage = "Hello";
|
||||
const string userMessage = "Hello";
|
||||
|
||||
var response = await _openAIApiService.GetSimpleResponseAsync(systemMessage, userMessage) ?? string.Empty;
|
||||
return response;
|
||||
|
|
@ -31,7 +31,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
public async Task<string> GetOpenAIPDFAnalysisFromText(string pdfText, string userQuestion)
|
||||
{
|
||||
string systemMessage = $"You are a pdf analyzis assistant, the user is asking you questions about a PDF document, that you have access to. The content of the PDF document is the following: {pdfText}";
|
||||
var systemMessage = $"You are a pdf analyzis assistant, the user is asking you questions about a PDF document, that you have access to. The content of the PDF document is the following: {pdfText}";
|
||||
var response = await _openAIApiService.GetSimpleResponseAsync(systemMessage, userQuestion);
|
||||
|
||||
if (response == null) return string.Empty;
|
||||
|
|
|
|||
|
|
@ -1,14 +1,18 @@
|
|||
using System.Text.Json;
|
||||
using System.Text;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using AyCode.Core.Loggers;
|
||||
using Mango.Nop.Core.Loggers;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Domains.DataLayer;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||
using Nop.Services.Configuration;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
#nullable enable
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||
{
|
||||
public class CerebrasAPIService : IAIAPIService
|
||||
{
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
private readonly ISettingService _settingService;
|
||||
private readonly FruitBankSettings _fruitBankSettings;
|
||||
private readonly HttpClient _httpClient;
|
||||
|
|
@ -18,23 +22,20 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
private const string CerebrasEndpoint = "https://api.cerebras.ai/v1/chat/completions";
|
||||
|
||||
public CerebrasAPIService(ISettingService settingService, HttpClient httpClient)
|
||||
public CerebrasAPIService(ISettingService settingService, HttpClient httpClient, IEnumerable<IAcLogWriterBase> logWriters)
|
||||
{
|
||||
_logger = new Logger<CerebrasAPIService>(logWriters.ToArray());
|
||||
|
||||
_settingService = settingService;
|
||||
_fruitBankSettings = _settingService.LoadSetting<FruitBankSettings>();
|
||||
|
||||
_httpClient = httpClient;
|
||||
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {GetApiKey()}");
|
||||
}
|
||||
|
||||
public string GetApiKey() =>
|
||||
_fruitBankSettings.ApiKey;
|
||||
//_configuration?.GetSection("Cerebras")?.GetValue<string>("ApiKey") ?? string.Empty;
|
||||
public string GetApiKey() => _fruitBankSettings.ApiKey; //_configuration?.GetSection("Cerebras")?.GetValue<string>("ApiKey") ?? string.Empty;
|
||||
|
||||
|
||||
|
||||
public string GetModelName() =>
|
||||
_fruitBankSettings.ModelName;
|
||||
//_configuration?.GetSection("Cerebras")?.GetValue<string>("Model") ?? string.Empty;
|
||||
public string GetModelName() => _fruitBankSettings.ModelName; //_configuration?.GetSection("Cerebras")?.GetValue<string>("Model") ?? string.Empty;
|
||||
|
||||
public void RegisterCallback(Action<string, string> callback, Action<string> onCompleteCallback, Action<string, string> onErrorCallback)
|
||||
{
|
||||
|
|
@ -44,27 +45,26 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
}
|
||||
|
||||
|
||||
public async Task<string> GetSimpleResponseAsync(string systemMessage, string userMessage, string? assistantMessage = null)
|
||||
{
|
||||
|
||||
string modelName = GetModelName();
|
||||
public async Task<string?> GetSimpleResponseAsync(string systemMessage, string userMessage, string? assistantMessage = null)
|
||||
{
|
||||
var modelName = GetModelName();
|
||||
|
||||
var requestBody = new CerebrasAIChatRequest
|
||||
{
|
||||
Model = modelName,
|
||||
Temperature = 0.2,
|
||||
Messages = assistantMessage == null || assistantMessage == string.Empty
|
||||
? new[]
|
||||
{
|
||||
Messages = string.IsNullOrEmpty(assistantMessage)
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
Stream = false
|
||||
};
|
||||
|
||||
|
|
@ -78,12 +78,13 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
using var response = await _httpClient.PostAsync(CerebrasEndpoint, requestContent);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
using var responseStream = await response.Content.ReadAsStreamAsync();
|
||||
await using var responseStream = await response.Content.ReadAsStreamAsync();
|
||||
using var document = await JsonDocument.ParseAsync(responseStream);
|
||||
var inputTokens = document.RootElement.GetProperty("usage").GetProperty("prompt_tokens").GetInt32();
|
||||
var outputTokens = document.RootElement.GetProperty("usage").GetProperty("completion_tokens").GetInt32();
|
||||
var sum = inputTokens + outputTokens;
|
||||
Console.WriteLine($"USAGE STATS - Tokens: {inputTokens.ToString()} + {outputTokens.ToString()} = {sum.ToString()}");
|
||||
|
||||
_logger.Info($"USAGE STATS - Tokens: {inputTokens.ToString()} + {outputTokens.ToString()} = {sum.ToString()}");
|
||||
|
||||
return document.RootElement
|
||||
.GetProperty("choices")[0]
|
||||
|
|
@ -95,24 +96,24 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
public async Task<string> GetStreamedResponseAsync(string sessionId, string systemMessage, string userMessage, string? assistantMessage = null)
|
||||
{
|
||||
string modelName = GetModelName();
|
||||
var modelName = GetModelName();
|
||||
|
||||
var requestBody = new CerebrasAIChatRequest
|
||||
{
|
||||
Model = modelName,
|
||||
Temperature = 0.2,
|
||||
Messages = assistantMessage == null
|
||||
? new[]
|
||||
{
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
Stream = true
|
||||
};
|
||||
|
||||
|
|
@ -122,16 +123,14 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
});
|
||||
|
||||
var requestContent = new StringContent(requestJson, Encoding.UTF8, "application/json");
|
||||
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, CerebrasEndpoint)
|
||||
{
|
||||
Content = requestContent
|
||||
};
|
||||
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, CerebrasEndpoint);
|
||||
httpRequest.Content = requestContent;
|
||||
|
||||
using var response = await _httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
||||
var stringBuilder = new StringBuilder();
|
||||
using var responseStream = await response.Content.ReadAsStreamAsync();
|
||||
await using var responseStream = await response.Content.ReadAsStreamAsync();
|
||||
using var reader = new StreamReader(responseStream);
|
||||
|
||||
try
|
||||
|
|
|
|||
|
|
@ -53,8 +53,6 @@ public class CustomPriceCalculationService : PriceCalculationService
|
|||
}
|
||||
|
||||
|
||||
//decimal? overriddenProductPrice = null
|
||||
|
||||
public override async Task<(decimal priceWithoutDiscounts, decimal finalPrice, decimal appliedDiscountAmount, List<Discount> appliedDiscounts)> GetFinalPriceAsync(
|
||||
Product product, Customer customer, Store store, decimal? overriddenProductPrice, decimal additionalCharge = 0, bool includeDiscounts = true,
|
||||
int quantity = 1, DateTime? rentalStartDate = null, DateTime? rentalEndDate = null)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||
|
||||
public class LockService : MgLockService, ILockService
|
||||
public class LockService : MgLockServiceBase, ILockService
|
||||
{
|
||||
public LockService() : this(new SemaphoreSlim(1))
|
||||
{}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
using Microsoft.Extensions.Configuration;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Services;
|
||||
using Nop.Plugin.Misc.FruitBankPlugin.Models;
|
||||
using Nop.Services.Configuration;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using AyCode.Utils.Extensions;
|
||||
|
||||
#nullable enable
|
||||
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
||||
{
|
||||
public class OpenAIApiService : IAIAPIService
|
||||
|
|
@ -45,29 +44,30 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
}
|
||||
|
||||
#region === CHAT (TEXT INPUT) ===
|
||||
|
||||
public async Task<string?> GetSimpleResponseAsync(string systemMessage, string userMessage, string? assistantMessage = null)
|
||||
{
|
||||
string modelName = GetModelName();
|
||||
StringContent requestContent = new("");
|
||||
var modelName = GetModelName();
|
||||
StringContent requestContent;
|
||||
|
||||
if (modelName == "gpt-4.1-mini" || modelName == "gpt-4o-mini" || modelName == "gpt-4.1-nano" || modelName == "gpt-5-nano")
|
||||
if (modelName is "gpt-4.1-mini" or "gpt-4o-mini" or "gpt-4.1-nano" or "gpt-5-nano")
|
||||
{
|
||||
var requestBody = new OpenAIGpt4MiniAIChatRequest
|
||||
{
|
||||
Model = modelName,
|
||||
Temperature = 0.2,
|
||||
Messages = assistantMessage == null || assistantMessage == string.Empty
|
||||
? new[]
|
||||
{
|
||||
Messages = string.IsNullOrEmpty(assistantMessage)
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
Stream = false
|
||||
};
|
||||
|
||||
|
|
@ -84,18 +84,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
{
|
||||
Model = modelName,
|
||||
Temperature = 1,
|
||||
Messages = assistantMessage == null || assistantMessage == string.Empty
|
||||
? new[]
|
||||
{
|
||||
Messages = string.IsNullOrEmpty(assistantMessage)
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
ReasoningEffort = "minimal",
|
||||
Verbosity = "high",
|
||||
Stream = false
|
||||
|
|
@ -134,12 +134,14 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region === CHAT (STREAMING) ===
|
||||
|
||||
public async Task<string> GetStreamedResponseAsync(string sessionId, string systemMessage, string userMessage, string? assistantMessage = null)
|
||||
{
|
||||
string modelName = GetModelName();
|
||||
var modelName = GetModelName();
|
||||
StringContent requestContent = new("");
|
||||
|
||||
if (modelName == "gpt-4.1-mini" || modelName == "gpt-4o-mini" || modelName == "gpt-4.1-nano" || modelName == "gpt-5-nano")
|
||||
|
|
@ -148,18 +150,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
{
|
||||
Model = modelName,
|
||||
Temperature = 0.2,
|
||||
Messages = assistantMessage == null || assistantMessage == string.Empty
|
||||
? new[]
|
||||
{
|
||||
Messages = string.IsNullOrEmpty(assistantMessage)
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
Stream = true
|
||||
};
|
||||
|
||||
|
|
@ -176,18 +178,18 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
{
|
||||
Model = modelName,
|
||||
Temperature = 1,
|
||||
Messages = assistantMessage == null || assistantMessage == string.Empty
|
||||
? new[]
|
||||
{
|
||||
Messages = string.IsNullOrEmpty(assistantMessage)
|
||||
?
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
}
|
||||
: new[]
|
||||
{
|
||||
]
|
||||
:
|
||||
[
|
||||
new AIChatMessage { Role = "system", Content = systemMessage },
|
||||
new AIChatMessage { Role = "assistant", Content = assistantMessage },
|
||||
new AIChatMessage { Role = "user", Content = userMessage }
|
||||
},
|
||||
],
|
||||
Stream = true
|
||||
};
|
||||
|
||||
|
|
@ -200,7 +202,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
}
|
||||
|
||||
using var httpRequest = new HttpRequestMessage(HttpMethod.Post, OpenAiEndpoint);
|
||||
httpRequest.Content = requestContent;
|
||||
httpRequest.Content = new StringContent("");
|
||||
|
||||
using var response = await _httpClient.SendAsync(httpRequest, HttpCompletionOption.ResponseHeadersRead);
|
||||
response.EnsureSuccessStatusCode();
|
||||
|
|
@ -216,7 +218,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
var line = await reader.ReadLineAsync();
|
||||
if (string.IsNullOrWhiteSpace(line) || !line.StartsWith("data: ")) continue;
|
||||
|
||||
var jsonResponse = line.Substring(6);
|
||||
var jsonResponse = line[6..];
|
||||
|
||||
if (jsonResponse == "[DONE]")
|
||||
{
|
||||
|
|
@ -259,9 +261,11 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
return stringBuilder.ToString();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region === IMAGE GENERATION ===
|
||||
|
||||
public async Task<string?> GenerateImageAsync(string prompt)
|
||||
{
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, OpenAiImageEndpoint);
|
||||
|
|
@ -294,6 +298,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
return $"data:image/png;base64,{base64Image}";
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region === PDF ANALYSIS (NEW) ===
|
||||
|
|
@ -301,16 +306,10 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
private async Task EnsureAssistantAndVectorStoreAsync()
|
||||
{
|
||||
// Find or create vector store
|
||||
if (_vectorStoreId == null)
|
||||
{
|
||||
_vectorStoreId = await FindOrCreateVectorStoreAsync("pdf-analysis-store");
|
||||
}
|
||||
_vectorStoreId ??= await FindOrCreateVectorStoreAsync("pdf-analysis-store");
|
||||
|
||||
// Find or create assistant
|
||||
if (_assistantId == null)
|
||||
{
|
||||
_assistantId = await FindOrCreateAssistantAsync("PDF and Image Analyzer Assistant");
|
||||
}
|
||||
_assistantId ??= await FindOrCreateAssistantAsync("PDF and Image Analyzer Assistant");
|
||||
}
|
||||
|
||||
//TEMPORARY: Cleanup all assistants (for testing purposes) - A.
|
||||
|
|
@ -348,7 +347,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
|
||||
public async Task<string?> AnalyzePdfAsync(Stream file, string fileName, string userPrompt)
|
||||
{
|
||||
|
||||
|
||||
await EnsureAssistantAndVectorStoreAsync();
|
||||
var fileId = await UploadFileAsync(file, fileName);
|
||||
var isImage = IsImageFile(fileName);
|
||||
|
|
@ -361,7 +360,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
var threadId = await CreateThreadAsync();
|
||||
|
||||
if (isImage)
|
||||
{
|
||||
{
|
||||
await AddUserMessageWithImageAsync(threadId, userPrompt, fileId);
|
||||
}
|
||||
else
|
||||
|
|
@ -375,7 +374,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
return await GetAssistantResponseAsync(threadId);
|
||||
}
|
||||
|
||||
private bool IsImageFile(string fileName)
|
||||
private static bool IsImageFile(string fileName)
|
||||
{
|
||||
var extension = Path.GetExtension(fileName).ToLowerInvariant();
|
||||
return extension == ".jpg" || extension == ".jpeg" || extension == ".png" || extension == ".gif" || extension == ".webp";
|
||||
|
|
@ -461,8 +460,8 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
role = "user",
|
||||
content = new object[]
|
||||
{
|
||||
new { type = "text", text = userPrompt },
|
||||
new { type = "image_file", image_file = new { file_id = fileId } }
|
||||
new { type = "text", text = userPrompt },
|
||||
new { type = "image_file", image_file = new { file_id = fileId } }
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -507,7 +506,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
{
|
||||
const int pollIntervalMs = 1000;
|
||||
const int maxAttempts = 60; // 1 minute timeout
|
||||
int attempts = 0;
|
||||
var attempts = 0;
|
||||
|
||||
while (attempts < maxAttempts)
|
||||
{
|
||||
|
|
@ -560,7 +559,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
return firstMessage ?? "No response";
|
||||
}
|
||||
|
||||
private HttpRequestMessage CreateAssistantRequest(HttpMethod method, string url, object? body = null)
|
||||
private static HttpRequestMessage CreateAssistantRequest(HttpMethod method, string url, object? body = null)
|
||||
{
|
||||
var request = new HttpRequestMessage(method, url);
|
||||
request.Headers.Add("OpenAI-Beta", "assistants=v2");
|
||||
|
|
@ -577,7 +576,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
return request;
|
||||
}
|
||||
|
||||
private async Task EnsureSuccessAsync(HttpResponseMessage response, string operation)
|
||||
private static async Task EnsureSuccessAsync(HttpResponseMessage response, string operation)
|
||||
{
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
|
|
@ -588,8 +587,6 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private async Task<string> FindOrCreateVectorStoreAsync(string name)
|
||||
{
|
||||
// List existing vector stores
|
||||
|
|
@ -602,12 +599,12 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
using var json = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
|
||||
var stores = json.RootElement.GetProperty("data");
|
||||
|
||||
foreach (var store in stores.EnumerateArray())
|
||||
//var getString = stores.EnumerateArray().FirstOrDefault(store => store.GetProperty("name").GetString() == name)?.GetProperty("id").GetString();
|
||||
//if (!getString.IsNullOrWhiteSpace()) return getString;
|
||||
|
||||
foreach (var store in stores.EnumerateArray().Where(store => store.GetProperty("name").GetString() == name))
|
||||
{
|
||||
if (store.GetProperty("name").GetString() == name)
|
||||
{
|
||||
return store.GetProperty("id").GetString()!;
|
||||
}
|
||||
return store.GetProperty("id").GetString()!;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -633,12 +630,9 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
using var json = await JsonDocument.ParseAsync(await response.Content.ReadAsStreamAsync());
|
||||
var assistants = json.RootElement.GetProperty("data");
|
||||
|
||||
foreach (var assistant in assistants.EnumerateArray())
|
||||
foreach (var assistant in assistants.EnumerateArray().Where(assistant => assistant.GetProperty("name").GetString() == name))
|
||||
{
|
||||
if (assistant.GetProperty("name").GetString() == name)
|
||||
{
|
||||
return assistant.GetProperty("id").GetString()!;
|
||||
}
|
||||
return assistant.GetProperty("id").GetString()!;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -659,9 +653,7 @@ namespace Nop.Plugin.Misc.FruitBankPlugin.Services
|
|||
return createJson.RootElement.GetProperty("id").GetString()!;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue