FruitBank plugin

This commit is contained in:
Adam 2025-08-31 01:25:22 +02:00
parent e03a9cf6db
commit 566ff1ea5f
27 changed files with 403 additions and 51 deletions

View File

@ -1,21 +1,21 @@
using Microsoft.AspNetCore.Mvc;
using Nop.Plugin.Misc.AIPlugin.Areas.Admin.Models;
using Nop.Plugin.Misc.AIPlugin;
//using Nop.Plugin.Misc.AIPlugin;
using Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models;
using Nop.Plugin.Misc.FruitBankPlugin;
//using Nop.Plugin.Misc.FruitBankPlugin;
using Nop.Services.Configuration;
using Nop.Web.Framework.Controllers;
using Nop.Services.Messages;
namespace Nop.Plugin.Misc.AIPlugin.Controllers
namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers
{
[Area("Admin")]
public class AIPluginAdminController : BasePluginController
public class FruitBankPluginAdminController : BasePluginController
{
private readonly INotificationService _notificationService;
private readonly ISettingService _settingService;
private readonly OpenAiSettings _settings;
public AIPluginAdminController(INotificationService notificationService, ISettingService settingService, OpenAiSettings settings)
public FruitBankPluginAdminController(INotificationService notificationService, ISettingService settingService, OpenAiSettings settings)
{
_notificationService = notificationService;
_settingService = settingService;
@ -29,7 +29,7 @@ namespace Nop.Plugin.Misc.AIPlugin.Controllers
{
ApiKey = _settings.ApiKey
};
return View("~/Plugins/Misc.AIPlugin/Views/Configure/Configure.cshtml", model);
return View("~/Plugins/Misc.FruitBankPlugin/Areas/Admin/Views/Configure/Configure.cshtml", model);
}
[HttpPost]

View File

@ -5,11 +5,11 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.AIPlugin.Areas.Admin.Models
namespace Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models
{
public record ConfigureModel
{
[NopResourceDisplayName("Plugins.AIPlugin.Fields.ApiKey")]
[NopResourceDisplayName("Plugins.FruitBankPlugin.Fields.ApiKey")]
public string ApiKey { get; set; }
}
}

View File

@ -1,8 +1,8 @@
@model Nop.Plugin.Misc.AIPlugin.Models.ConfigureModel
@model Nop.Plugin.Misc.FruitBankPlugin.Areas.Admin.Models.ConfigureModel
@{
Layout = "_AdminLayout";
Html.SetActiveMenuItemSystemName("AiAssistant.Configure");
NopHtml.SetActiveMenuItemSystemName("AiAssistant.Configure");
}
<div class="card">

View File

@ -2,6 +2,8 @@
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
@addTagHelper *, Nop.Web.Framework
@inject INopHtmlHelper NopHtml
@using Microsoft.AspNetCore.Mvc.ViewFeatures
@using Nop.Web.Framework.UI
@using Nop.Web.Framework.Extensions

View File

@ -1,7 +1,7 @@
using Microsoft.AspNetCore.Mvc;
using Nop.Web.Framework.Components;
namespace Nop.Plugin.Misc.AIPlugin.Components;
namespace Nop.Plugin.Misc.FruitBankPlugin.Components;
[ViewComponent(Name = "Custom")]
public class CustomViewComponent : NopViewComponent

View File

@ -6,7 +6,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.AIPlugin.Components
namespace Nop.Plugin.Misc.FruitBankPlugin.Components
{
[ViewComponent(Name = "ProductAIWidget")]
@ -20,7 +20,7 @@ namespace Nop.Plugin.Misc.AIPlugin.Components
if (product == null)
return Content(""); // ne rendereljen semmit, ha nincs product
return View("~/Plugins/Misc.AIPlugin/Views/ProductAIListWidget.cshtml", product);
return View("~/Plugins/Misc.FruitBankPlugin/Views/ProductAIListWidget.cshtml", product);
}
else if (additionalData is Nop.Web.Models.Catalog.ProductDetailsModel)
{
@ -28,7 +28,7 @@ namespace Nop.Plugin.Misc.AIPlugin.Components
if (product == null)
return Content(""); // ne rendereljen semmit, ha nincs product
return View("~/Plugins/Misc.AIPlugin/Views/ProductAIWidget.cshtml", product);
return View("~/Plugins/Misc.FruitBankPlugin/Views/ProductAIWidget.cshtml", product);
}
else {
return Content(""); // ne rendereljen semmit, ha nem productDetailModel vagy productOverviewModel

View File

@ -0,0 +1,16 @@
using Microsoft.AspNetCore.Mvc;
namespace Nop.Plugin.Misc.FruitBankPlugin.Controllers
{
[Area("Admin")] // ha admin oldalra, de a frontendre ne legyen
public class CheckoutController : Controller
{
[Route("checkout/pending-measurement")]
public IActionResult PendingMeasurementWarning()
{
// visszaadja a view-t
return View("~/Plugins/Misc.FruitBankPlugin/Views/Checkout/PendingMeasurementWarning.cshtml");
}
}
}

View File

@ -1,6 +1,6 @@
using Nop.Core;
namespace Nop.Plugin.Misc.AIPlugin.Domains;
namespace Nop.Plugin.Misc.FruitBankPlugin.Domains;
public partial class CustomTable : BaseEntity
{

View File

@ -0,0 +1,55 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Nop.Core.Domain.Orders;
using Nop.Services.Orders;
using Nop.Services.Common;
using System.Threading.Tasks;
using Nop.Core;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
namespace Nop.Plugin.Misc.FruitBankPlugin.Filters
{
public class PendingMeasurementCheckoutFilter : IAsyncActionFilter
{
private readonly IWorkContext _workContext;
private readonly IOrderService _orderService;
private readonly IOrderMeasurementService _orderMeasurementService;
public PendingMeasurementCheckoutFilter(
IWorkContext workContext,
IOrderService orderService,
IOrderMeasurementService orderMeasurementService)
{
_workContext = workContext;
_orderService = orderService;
_orderMeasurementService = orderMeasurementService;
}
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
{
// csak a ConfirmOrder action-nál kell ellenőrizni
var actionName = context.ActionDescriptor.RouteValues["action"];
var controllerName = context.ActionDescriptor.RouteValues["controller"];
if (controllerName == "Checkout" && actionName == "ConfirmOrder")
{
// lekérjük a user aktuális kosarát
var customer = await _workContext.GetCurrentCustomerAsync();
var order = await _orderService.GetOrderByIdAsync((int)context.ActionArguments["orderId"]); // ha van orderId param
if (order != null && await _orderMeasurementService.IsPendingMeasurementAsync(order))
{
context.Result = new RedirectToRouteResult(new
{
controller = "Checkout",
action = "PendingMeasurementWarning"
});
return; // itt kilépünk, a fizetés nem engedélyezett
}
}
await next(); // mehet a többi pipeline
}
}
}

View File

@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.FruitBankPlugin
{
public static class FruitBankConsts
{
public const string RequiresMeasurementAttr = "PriceByMeasurement.RequiresMeasurement";
}
}

View File

@ -2,7 +2,7 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.Routing;
using Nop.Plugin.Misc.AIPlugin.Components;
using Nop.Plugin.Misc.FruitBankPlugin.Components;
using Nop.Services.Cms;
using Nop.Services.Configuration;
using Nop.Services.Localization;
@ -12,12 +12,12 @@ using Nop.Web.Framework.Infrastructure;
using Nop.Web.Framework.Menu;
namespace Nop.Plugin.Misc.AIPlugin
namespace Nop.Plugin.Misc.FruitBankPlugin
{
/// <summary>
/// Main plugin class
/// </summary>
public class AIPlugin : BasePlugin, IWidgetPlugin
public class FruitBankPlugin : BasePlugin, IWidgetPlugin
{
protected readonly IActionContextAccessor _actionContextAccessor;
private readonly ISettingService _settingService;
@ -30,7 +30,7 @@ namespace Nop.Plugin.Misc.AIPlugin
//handle AdminMenuCreatedEvent
public AIPlugin(IActionContextAccessor actionContextAccessor,
public FruitBankPlugin(IActionContextAccessor actionContextAccessor,
ISettingService settingService,
//IWebHelper webHelper,
ILocalizationService localizationService,
@ -50,6 +50,9 @@ namespace Nop.Plugin.Misc.AIPlugin
// --- INSTALL ---
public override async Task InstallAsync()
{
// TODO: Add "NeedsToBeMeasured" product attribute if not exists
// Default settings
var settings = new OpenAiSettings
{
@ -88,9 +91,9 @@ namespace Nop.Plugin.Misc.AIPlugin
// var pluginNode = new AdminMenuItem
// {
// SystemName = "AIPlugin.Configure",
// SystemName = "FruitBankPlugin.Configure",
// Title = "AI Assistant",
// Url = $"{_webHelper.GetStoreLocation()}Admin/AIPluginAdmin/Configure",
// Url = $"{_webHelper.GetStoreLocation()}Admin/FruitBankPluginAdmin/Configure",
// Visible = true
// };
// rootNode.ChildNodes.Add(pluginNode);
@ -128,15 +131,15 @@ namespace Nop.Plugin.Misc.AIPlugin
{
new()
{
// SystemName = "AIPlugin.Configure",
// SystemName = "FruitBankPlugin.Configure",
// Title = "AI Assistant",
// Url = $"{_webHelper.GetStoreLocation()}Admin/AIPluginAdmin/Configure",
// Url = $"{_webHelper.GetStoreLocation()}Admin/FruitBankPluginAdmin/Configure",
// Visible = true
Visible = true,
SystemName = PluginDescriptor.SystemName,
Title = PluginDescriptor.FriendlyName,
IconClass = "far fa-circle",
Url = _adminMenu.GetMenuItemUrl("AIPlugin", "Configure"),
Url = _adminMenu.GetMenuItemUrl("FruitBankPlugin", "Configure"),
//Url = "Admin/SignalRApi/Configure",
//ControllerName = "SignalRApi",
//ActionName = "Configure",
@ -148,7 +151,7 @@ namespace Nop.Plugin.Misc.AIPlugin
public override string GetConfigurationPageUrl()
{
return _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext).RouteUrl("Plugin.Misc.AIPlugin.Configure");
return _urlHelperFactory.GetUrlHelper(_actionContextAccessor.ActionContext).RouteUrl("Plugin.Misc.FruitBankPlugin.Configure");
}
public Type GetWidgetViewComponent(string widgetZone)

View File

@ -1,10 +1,14 @@
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Nop.Core.Infrastructure;
using Nop.Plugin.Misc.FruitBankPlugin.Filters;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Services.Catalog;
namespace Nop.Plugin.Misc.AIPlugin.Infrastructure;
namespace Nop.Plugin.Misc.FruitBankPlugin.Infrastructure;
public class PluginNopStartup : INopStartup
{
@ -20,8 +24,26 @@ public class PluginNopStartup : INopStartup
options.ViewLocationExpanders.Add(new ViewLocationExpander());
});
services.AddCors(feature =>
feature.AddPolicy(
"AllowBlazorClient",
apiPolicy => apiPolicy
.WithOrigins("https://localhost:7144")
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()
));
services.AddSignalR();
//register services and interfaces
//services.AddScoped<CustomModelFactory, ICustomerModelFactory>();
services.AddScoped<IPriceCalculationService, CustomPriceCalculationService>();
services.AddScoped<PendingMeasurementCheckoutFilter>();
services.AddControllersWithViews(options =>
{
options.Filters.AddService<PendingMeasurementCheckoutFilter>();
});
}
/// <summary>
@ -30,10 +52,24 @@ public class PluginNopStartup : INopStartup
/// <param name="application">Builder for configuring an application's request pipeline</param>
public void Configure(IApplicationBuilder application)
{
application.UseWhen(context => context.Request.Path.StartsWithSegments("/fbhub"), app =>
{
app.UseCors("AllowBlazorClient");
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHub<FruitBankHub>("/fbhub");
});
});
}
/// <summary>
/// Gets order of this startup configuration implementation
/// </summary>
public int Order => 3000;
public int Order => 100;
}

View File

@ -1,7 +1,10 @@
using Microsoft.AspNetCore.Routing;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Routing;
using Nop.Plugin.Misc.FruitBankPlugin.Services;
using Nop.Web.Framework;
using Nop.Web.Framework.Mvc.Routing;
namespace Nop.Plugin.Misc.AIPlugin.Infrastructure;
namespace Nop.Plugin.Misc.FruitBankPlugin.Infrastructure;
/// <summary>
/// Represents plugin route provider
@ -14,7 +17,11 @@ public class RouteProvider : IRouteProvider
/// <param name="endpointRouteBuilder">Route builder</param>
public void RegisterRoutes(IEndpointRouteBuilder endpointRouteBuilder)
{
endpointRouteBuilder.MapControllerRoute(name: "Plugin.Misc.FruitBankPlugin.Configure",
pattern: "Admin/FruitBankPlugin/Configure",
defaults: new { controller = "FruitBankPluginAdmin", action = "Configure", area = AreaNames.ADMIN });
//endpointRouteBuilder.MapHub<FruitBankHub>("/fbhub");//.RequireCors("AllowBlazorClient");
}
/// <summary>

View File

@ -1,6 +1,6 @@
using Microsoft.AspNetCore.Mvc.Razor;
namespace Nop.Plugin.Misc.AIPlugin.Infrastructure;
namespace Nop.Plugin.Misc.FruitBankPlugin.Infrastructure;
public class ViewLocationExpander : IViewLocationExpander
{
@ -26,11 +26,11 @@ public class ViewLocationExpander : IViewLocationExpander
{
if (context.AreaName == "Admin")
{
viewLocations = new[] { $"/Plugins/Nop.Plugin.Misc.AIPlugin/Areas/Admin/Views/{context.ControllerName}/{context.ViewName}.cshtml" }.Concat(viewLocations);
viewLocations = new[] { $"/Plugins/Nop.Plugin.Misc.FruitBankPlugin/Areas/Admin/Views/{context.ControllerName}/{context.ViewName}.cshtml" }.Concat(viewLocations);
}
else
{
viewLocations = new[] { $"/Plugins/Nop.Plugin.Misc.AIPlugin/Views/{context.ControllerName}/{context.ViewName}.cshtml" }.Concat(viewLocations);
viewLocations = new[] { $"/Plugins/Nop.Plugin.Misc.FruitBankPlugin/Views/{context.ControllerName}/{context.ViewName}.cshtml" }.Concat(viewLocations);
}
return viewLocations;

View File

@ -1,8 +1,8 @@
using FluentMigrator.Builders.Create.Table;
using Nop.Data.Mapping.Builders;
using Nop.Plugin.Misc.AIPlugin.Domains;
using Nop.Plugin.Misc.FruitBankPlugin.Domains;
namespace Nop.Plugin.Misc.AIPlugin.Mapping.Builders;
namespace Nop.Plugin.Misc.FruitBankPlugin.Mapping.Builders;
public class PluginBuilder : NopEntityBuilder<CustomTable>
{

View File

@ -1,6 +1,6 @@
using Nop.Data.Mapping;
namespace Nop.Plugin.Misc.AIPlugin.Mapping;
namespace Nop.Plugin.Misc.FruitBankPlugin.Mapping;
public partial class NameCompatibility : INameCompatibility
{

View File

@ -1,12 +1,12 @@
using FluentMigrator;
using Nop.Data.Extensions;
using Nop.Data.Migrations;
using Nop.Plugin.Misc.AIPlugin.Domains;
using Nop.Plugin.Misc.FruitBankPlugin.Domains;
namespace Nop.Plugin.Misc.AIPlugin.Migrations;
namespace Nop.Plugin.Misc.FruitBankPlugin.Migrations;
//2024-10-31
[NopMigration("2025-08-29 12:07:22", "Nop.Plugin.Misc.AIPlugin schema", MigrationProcessType.Installation)]
[NopMigration("2025-08-29 12:07:22", "Nop.Plugin.Misc.FruitBankPlugin schema", MigrationProcessType.Installation)]
public class SchemaMigration : AutoReversingMigration
{
/// <summary>

View File

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<OutputPath>$(SolutionDir)\Presentation\Nop.Web\Plugins\Misc.AIPlugin</OutputPath>
<OutputPath>$(SolutionDir)\Presentation\Nop.Web\Plugins\Misc.FruitBankPlugin</OutputPath>
<OutDir>$(OutputPath)</OutDir>
<!--Set this parameter to true to get the dlls copied from the NuGet cache to the output of your project.
You need to set this parameter to true if your plugin has a nuget package
@ -49,7 +49,6 @@
<Folder Include="Areas\Admin\Extensions\" />
<Folder Include="Areas\Admin\Factories\" />
<Folder Include="Areas\Admin\Validators\" />
<Folder Include="Controllers\" />
<Folder Include="Extensions\" />
<Folder Include="Factories\" />
<Folder Include="Models\" />
@ -57,6 +56,12 @@
</ItemGroup>
<ItemGroup>
<None Update="Areas\Admin\Views\Configure\Configure.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Views\Checkout\PendingMeasurementWarning.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="Views\ProductAIListWidget.cshtml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>

View File

@ -1,7 +1,7 @@
using global::Nop.Core.Configuration;
namespace Nop.Plugin.Misc.AIPlugin
namespace Nop.Plugin.Misc.FruitBankPlugin
{
public class OpenAiSettings : ISettings
{

View File

@ -0,0 +1,81 @@
using Nop.Core.Caching;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Customers;
using Nop.Core;
using Nop.Data;
using Nop.Services.Catalog;
using Nop.Services.Customers;
using Nop.Services.Discounts;
using Nop.Services.Localization;
using Nop.Services.Logging;
using Nop.Core.Domain.Directory;
using Nop.Services.Directory;
using Nop.Core.Domain.Discounts;
using Nop.Core.Domain.Stores;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services;
public class CustomPriceCalculationService : PriceCalculationService
{
private readonly IRepository<Product> _productRepository;
private readonly IProductAttributeService _productAttributeService;
private readonly ILocalizationService _localizationService;
private readonly IProductService _productService;
public CustomPriceCalculationService(
IRepository<Product> productRepository,
// inject all base deps
CatalogSettings catalogSettings,
CurrencySettings currencySettings,
ICategoryService categoryService,
ICurrencyService currencyService,
IManufacturerService manufacturerService,
IProductAttributeParser productAttributeParser,
IProductAttributeService productAttributeService,
IProductService productService,
ICustomerService customerService,
IDiscountService discountService,
IDiscountPluginManager discountPluginManager,
ILocalizationService localizationService,
IStaticCacheManager cacheManager,
IWorkContext workContext,
ILogger logger)
: base(catalogSettings, currencySettings, categoryService, currencyService, customerService, discountService, manufacturerService,
productAttributeParser, productService,
cacheManager)
{
_productRepository = productRepository;
// assign all base deps to local private vars if needed
_productAttributeService = productAttributeService;
_localizationService = localizationService;
_productService = productService;
}
//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)
{
var productAttributeMappings = await _productAttributeService.GetProductAttributeMappingsByProductIdAsync(product.Id);
//Product Attributes
foreach (var pam in productAttributeMappings)
{
var attributes = await _productAttributeService.GetProductAttributeValuesAsync(pam.Id);
foreach (var attr in attributes)
{
// you can check for specific attribute by its name or id
if (attr.Name == "NeedsToBeMeasured" && attr.IsPreSelected)
{
return (0m, 0m, 0m, new List<Discount>());
}
}
}
return await base.GetFinalPriceAsync(product, customer, store, 0, additionalCharge, includeDiscounts, quantity, rentalStartDate, rentalEndDate);
}
}

View File

@ -0,0 +1,71 @@
using System.Linq;
using Nop.Core.Domain.Catalog;
using Nop.Core.Domain.Orders;
using Nop.Services.Catalog;
using Nop.Services.Common;
using Nop.Services.Events;
using Nop.Services.Orders;
namespace Nop.Plugin.YourCompany.Measurement.Services
{
public class OrderPlacedConsumer : IConsumer<OrderPlacedEvent>
{
private readonly IGenericAttributeService _genericAttributeService;
private readonly IProductService _productService;
private readonly IOrderService _orderService;
private readonly IProductAttributeService _productAttributeService;
public OrderPlacedConsumer(
IGenericAttributeService genericAttributeService,
IProductService productService,
IOrderService orderService,
IProductAttributeService productAttributeService)
{
_genericAttributeService = genericAttributeService;
_productService = productService;
_orderService = orderService;
_productAttributeService = productAttributeService;
}
public async Task HandleEventAsync(OrderPlacedEvent eventMessage)
{
var order = eventMessage.Order;
var orderItems = await _orderService.GetOrderItemsAsync(order.Id);
bool requiresMeasurement = false;
foreach (var item in orderItems)
{
var product = await _productService.GetProductByIdAsync(item.ProductId);
// itt pl. egy custom flag a producton, ami jelzi, hogy mérés kell hozzá
// akár egy product attribute is lehet, vagy egy saját extension metódus
if (product != null)
{
var productAttributeMappings = await _productAttributeService.GetProductAttributeMappingsByProductIdAsync(product.Id);
//Product Attributes
foreach (var pam in productAttributeMappings)
{
var attributes = await _productAttributeService.GetProductAttributeValuesAsync(pam.Id);
foreach (var attr in attributes)
{
// you can check for specific attribute by its name or id
if (attr.Name == "NeedsToBeMeasured" && attr.IsPreSelected)
{
requiresMeasurement = true;
break;
}
}
}
}
}
if (requiresMeasurement)
{
// itt adjuk hozzá a GenericAttribute flag-et az orderhez
await _genericAttributeService.SaveAttributeAsync(order,
"PendingMeasurement", true);
}
}
}
}

View File

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
{
class FruitBankHub : Hub
{
public async Task SendMessage(string user, string message)
{
await Clients.All.SendAsync("ReceiveMessage", user, message);
}
}
}

View File

@ -1,4 +1,4 @@
using Nop.Plugin.Misc.AIPlugin;
using Nop.Plugin.Misc.FruitBankPlugin;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
@ -6,7 +6,7 @@ using System.Text.Json;
using System.Threading.Tasks;
using Nop.Services.Configuration;
namespace Nop.Plugin.Misc.AIPlugin.Services
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
{
public class OpenAiService

View File

@ -0,0 +1,29 @@
using Nop.Core.Domain.Orders;
using Nop.Services.Common;
namespace Nop.Plugin.Misc.FruitBankPlugin.Services
{
public interface IOrderMeasurementService
{
Task<bool> IsPendingMeasurementAsync(Order order);
}
public class OrderMeasurementService : IOrderMeasurementService
{
private readonly IGenericAttributeService _genericAttributeService;
public OrderMeasurementService(IGenericAttributeService genericAttributeService)
{
_genericAttributeService = genericAttributeService;
}
public async Task<bool> IsPendingMeasurementAsync(Order order)
{
if (order == null)
return false;
return await _genericAttributeService.GetAttributeAsync<bool>(
order, "PendingMeasurement", order.StoreId);
}
}
}

View File

@ -0,0 +1,15 @@
@{
Layout = "_RootLayout"; // a front-endhez használt layout
}
<h3>Rendelés mérés alatt</h3>
<p>
Ez a rendelés még mérés alatt áll, az ár még nem végleges.
Értesítést fog kapni, amikor a fizetés lehetséges.
</p>
<a href="@Url.Action("Index", "ShoppingCart")" class="btn btn-secondary">
Vissza a kosárhoz
</a>

View File

@ -9,7 +9,7 @@
@using Nop.Services.Events
@using Nop.Web.Framework.Events
@using Nop.Web.Framework.Infrastructure
@using Nop.Plugin.Misc.AIPlugin
@* @using Nop.Plugin.Misc.AIPlugin.Models *@
@using Nop.Plugin.Misc.AIPlugin.Services
@* @using Nop.Plugin.Misc.AIPlugin.Hubs *@
@using Nop.Plugin.Misc.FruitBankPlugin
@* @using Nop.Plugin.Misc.FruitBankPlugin.Models *@
@using Nop.Plugin.Misc.FruitBankPlugin.Services
@* @using Nop.Plugin.Misc.FruitBankPlugin.Hubs *@

View File

@ -1,13 +1,13 @@
{
"Group": "Misc",
"FriendlyName": "AIPlugin",
"SystemName": "Misc.AIPlugin",
"FriendlyName": "FruitBankPlugin",
"SystemName": "Misc.FruitBankPlugin",
"Version": "1.00",
"SupportedVersions": [
"4.80"
],
"Author": "Adam Gelencser",
"DisplayOrder": 1,
"FileName": "Nop.Plugin.Misc.AIPlugin.dll",
"FileName": "Nop.Plugin.Misc.FruitBankPlugin.dll",
"Description": ""
}