Nop4.40.3

Da Webmobili Wiki.

Installare Nop 4.40.3

In questa guida saranno evidenziati in rosso tutti i file del core di Nop che verranno toccati.

Operazioni sul DB

  • Creare un dump del database di produzione (Nop 4.3)
  • Ripristinarlo
  • Per ripristinare l'utente wmuser è necessario disassociarlo dal catalogo fulltext
  • Da SQL Management Aprire Storage -> Fulltext Catalogs -> nopCommerceFullTextCatalog, nella tab General impostare come Owner => dbo
  • Eliminare l'utente wmuser
  • Ri-mappare l'utente wmuser sul database nuovo
  • Aprire di nuovo Storage -> Fulltext Catalogs -> nopCommerceFullTextCatalog, nella tab General inserire come Owner => wmuser
  • Aprire di nuovo Storage -> Fulltext Catalogs -> nopCommerceFullTextCatalog, nella tab Tables/Views, pannello Eligible columns impostare italian per tutti i campi

Configurazione della Solution

  • Aggiornare i file Presentation\Nop.Web\App_Data\dataSettings.json e Presentation\Nop.Web\App_Data\appsettings.json
  • Copiare i plugin di terze parti nella cartella Plugins\Nop.Plugin.Compiled
  • Aggiungere il seguente codice nei build events => post build event progetto Nop.Web
    xcopy /y /E $(SolutionDir)Plugins\Nop.Plugin.Compiled $(SolutionDir)Presentation\Nop.Web\Plugins
    per copiare i plugin compilati (7spikes & co) nel corretto folder durante il build.
  • Creare dal Configuration Manager una nuova Solution Configuration chiamata ReleaseTest
  • Tasto destro sul web.config e cliccare su Add Configs Transform per creare i web.Release.config e web.ReleaseTest.config
    • Nel web.config aggiungere la variabile d'ambiente ASPNETCORE_ENVIRONMENT con valore Development sotto la sezione aspNetCore
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Development" />
      </environmentVariables>
      
    • Nel web.ReleaseTest.config mettere il valore Testing
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Testing" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
      </environmentVariables>
      
    • nel web.Release.config mettere il valore Production
      <environmentVariables>
        <environmentVariable name="ASPNETCORE_ENVIRONMENT" value="Production" xdt:Transform="SetAttributes" xdt:Locator="Match(name)" />
      </environmentVariables>
      
  • Dalle proprietà del progetto Nop.Web andare sulla tab Build, selezionare la configurazione Release e aggiungere il simbolo condizionale OFFICIAL
  • Configuriamo l'applicazione in modo che cambi file di configurazione a seconda della Solution Configuration selezionata
    • In Libraries\Nop.Data\NopDataSettingsDefaults.cs cambiare l'assegnamento di FilePath con quanto segue
              public static string FilePath =>
      #if DEBUG
                  "~/App_Data/dataSettings.development.json";
      
      #elif !OFFICIAL
                  "~/App_Data/dataSettings.testing.json";
      
      #else
                  "~/App_Data/dataSettings.json";
      
      #endif
      
    • In Libraries\Nop.Services\Configuration\NopConfigurationDefaults.cs cambiare l'assegnamento di AppSettingsFilePath con quanto segue
              public static string AppSettingsFilePath =>
      #if DEBUG
                  "App_Data/appsettings.development.json";
      
      #elif !OFFICIAL
                  "App_Data/appsettings.testing.json";
      
      #else
                  "App_Data/appsettings.json";
      
      #endif
      
  • Addare alla Solution (cartella Libraries) i progetti GenericUtilites, WM4Search, WM_Core e USO
  • Runnando la Solution dovrebbe partire con tutti i plugin disabilitati. Una volta entrati in admin è possibile vederli dall'elenco e installarli.
  • Non ci saranno tutti i plugin, in tal caso cliccare su ricaricare la lista di plugin, la soluzione si chiuderà da sola, ma al successivo login la lista dovrebbe essere aggiornata.
  • Aggiornare tutti i pacchetti nuGet della Solution che abbiano un update minor (dalla seconda cifra in poi)
  • Creazione di IWMCoreModelFactory per le chiamate alla WMCore.
    • INTERFACCIA: creare Presentation\Nop.Web\Factories\IWMCoreModelFactory.cs così
      using GPC.WM_Core;
      
      namespace Nop.Web.Factories {
        public interface IWMCoreModelFactory {
          WMRetriever WMCore { get; }
        }
      }
      
    • IMPLEMENTAZIONE: creare Presentation\Nop.Web\Factories\IWMCoreModelFactory.cs così
      using GPC.WM_Core;
      using Microsoft.Extensions.Configuration;
      
      namespace Nop.Web.Factories {
        public class WMCoreModelFactory : IWMCoreModelFactory {
          public WMRetriever WMCore { get; } = null;
      
          public WMCoreModelFactory(IConfiguration configuration) {
            WMCore = new WMRetriever(
              configuration.GetSection("WMConnectionStrings")["Designbest"],
              configuration.GetSection("WMConnectionStrings")["Designbest"],
              configuration.GetSection("WMConnectionStrings")["Trovaprodotti"],
              configuration.GetSection("WMApplicationSettings")["ResourcesPath"],
              "Test_WM47");
          }
        }
      }
      
    • BINDING: comunicare la sua esistenza al framework modificando Presentation\Nop.Web\Startup.cs aggiungendo una riga a ConfigureServices() così
      public void ConfigureServices(IServiceCollection services)
      {
        // aggiunta di IWMCoreModelFactory
        services.AddSingleton<IWMCoreModelFactory, WMCoreModelFactory>();
        services.ConfigureApplicationServices(_configuration, _webHostEnvironment);
      }
      
  • Inserimento di UsoUtilitiesController uguale a quello precedente con la differenza che le chiamate a services sono diventate tutte ASYNC e perciò il trucco è aggiungere al fondo .Result per le variabili o .Wait() per i metodi come ad esempio
    Customer customer = _customerService.GetCustomerByGuidAsync(customerGuid).Result;
    _authenticationService.SignInAsync(customer, true).Wait();
    

Prodotto

  • Aggiunta metodi frmt() di utilità nelle viste per restituire decimali in Nop.Web\Extensions\HtmlExtensions.cs:
    /// Restituisce (come stringa) il numero decimale specificato inserendo il punto
    /// ogni tre cifre. I numeri decimali sono limitati a 2
    /// </summary>
    /// <param name="val">Un decimal</param>
    /// <returns>Il numero nella forma mmm.kkk.uuu,dd</returns>
    public static string frmt(this decimal val) {
      var ci = new CultureInfo("it-IT");
      ci.NumberFormat.NumberDecimalDigits = 2;
      return val.ToString("N", ci);
    }

    /// Restituisce (come stringa) il numero intero specificato inserendo il punto
    /// ogni tre cifre.
    /// </summary>
    /// <param name="val">Un decimal</param>
    /// <returns>Il numero nella forma mmm.kkk.uuu,dd</returns>
    public static string frmt(this int val) {
      var ci = new CultureInfo("it-IT");
      ci.NumberFormat.NumberDecimalDigits = 2;
      return val.ToString("N", ci);
    }
  • Nel modello del prodotto in Nop.Web\Models\Catalog\ProductDetailsModel.cs aggiungere:
 #region WEBMOBILI
    /// <summary>
    /// Nella nostra struttura c'è sempre un solo manufacturer per prodotto. Questa property lo restituisce.
    /// In caso di manufacturer non settato (errore di dati) restituisce un manu vuoto per evitare una NullPointerException
    /// </summary>
    public ManufacturerBriefInfoModel Manufacturer {
      get {
        if (ProductManufacturers.Count > 0) {
          return ProductManufacturers[0];
        }
        return new ManufacturerBriefInfoModel { Name = "", SeName = "", IsActive = false };
      }
    }

    public string ShopCity { get; set; }

    public decimal AdditionalShippingCharge { get; set; }

    #endregion
  • ProductController: al momento dichiarata l'istanza dell'interfaccia IWMCoreModelFactory, ma non utilizzata, i campi necessari sono stati aggiunti direttamente nel modello del prodotto, aggiungiamo quindi solo questa istruzione nel metodo ProductDetails(int productId, int updatecartitemid = 0):
#region WEBMOBILI
      model.AdditionalShippingCharge = product.AdditionalShippingCharge; // spese di spedizione da stampare in frontend
#endregion
  • Nella vista del prodotto, copiare la vista del tema base Nop.Web\Views\Product\_DeliveryInfo.cs in Nop.Web\Themes\Brooklyn\Views\Product\_DeliveryInfo.cs e modificarla così:
@model ProductDetailsModel
@if (Model.FreeShippingNotificationEnabled && Model.IsFreeShipping@*|| !string.IsNullOrWhiteSpace(Model.DeliveryDate)*@) {
<div class="delivery">
  <script asp-location="Footer">
    $(document).on("product_attributes_changed", function (data) {
      if (data.changedData.isFreeShipping) {
        $("#free-shipping-" + data.changedData.productId).removeClass("invisible");
      } else {
        $("#free-shipping-" + data.changedData.productId).addClass("invisible");
      }
    });
  </script>
  @if (Model.FreeShippingNotificationEnabled && Model.IsFreeShipping) {
    <div id="free-shipping-@Model.Id" class="free-shipping">@T("Products.FreeShipping")</div>
  }
  @if (!string.IsNullOrWhiteSpace(Model.DeliveryDate)) {
    <div class="delivery-date">
      <span class="label">@T("Products.DeliveryDate"):</span>
      <span class="value">@Model.DeliveryDate</span>
    </div>
  }
</div>
}
else {
<div class="delivery">
  @if (Model.IsShipEnabled) {
    <div class="free-shipping">
      <span class="label">SPEDIZIONE STANDARD ITALIA  @Model.AdditionalShippingCharge.frmt() <span class="testo-minuscolo">(cad.)</span></span>
    </div>
    @if (!string.IsNullOrWhiteSpace(Model.DeliveryDate)) {
      <div class="delivery-date">
        <span class="label">@T("Products.DeliveryDate"):</span>
        <span class="value">@Model.DeliveryDate</span>
      </div>
    }
  }
  else {
    <div class="free-shipping">
      <span class="label">SPEDIZIONE PERSONALIZZATA A PREVENTIVO</span>
    </div>
  }
</div>
}

LATO ADMIN

Home - Vendor

  • Nascondere il pulsante Visualizza nei best seller(un Vendor non deve entrare nella pagina di modifica del prodotto lato NOP), bisogna commentare l'ultima ColumnProperty in queste 2 viste:

Nop.Web\Areas\Admin\Views\Home\_BestsellersBriefReportByAmount.cshtml Nop.Web\Areas\Admin\Views\Home\_BestsellersBriefReportByQuantity.cshtml

Vendite - Ordini del Cliente

  • Nascondere il filtro Magazzino (aggiungere la classe d-none), altrimenti un vendor potrebbe vedere le vendite degli altri vendor.
<div class="form-group row d-none" @(Model.AvailableWarehouses.SelectionIsNotPossible() ? Html.Raw("style=\"display:none\"") : null)>
   <div class="col-md-4">
     <nop-label asp-for="WarehouseId" />
   </div>
   <div class="col-md-8">
      <nop-select asp-for="WarehouseId" asp-items="Model.AvailableWarehouses" />
   </div>
</div>

Ordine - dettaglio

  • Modificare il modello Nop.Web\Areas\Admin\Models\Orders\OrderItemModel.cs aggiungendo public string ProductSeoName { get; set; }
  • Factory Nop.Web\Areas\Admin\Factories\OrderModelFactory.cs valorizzare il campo ProductSeoName usando la WMCore, nel metodo PrepareOrderItemModelsAsync
ProductSeoName = _wmcore.WMCore.GetNopProductSeoName(orderItem.ProductId),
  • Nel box dove sono elencati i prodotti, il link del prodotti rimanderà alla scheda del prodotto nel frontend, mentre solo se siamo Admin entreremo nell'edit del prodotto di NOP

File:Esempio.jpg modificare in Nop.Web\Areas\Admin\Views\Order\_OrderDetails.Products.cshtml

    • Dobbiamo recuperare il VendorID del dropship di Webmobili:
@inject Nop.Services.Catalog.IProductService prodService;
@inject Microsoft.Extensions.Configuration.IConfiguration configuration;
@{
  int vendorWMDropship = 0;
  int.TryParse(configuration.GetSection("WMApplicationSettings")["DropshipVendorID"], out vendorWMDropship);
}
    • Controllo se l'utente è un Vendor o Admin
<em>
@if (!Model.IsLoggedInAsVendor) {
  <a asp-controller="Product" asp-action="Edit" asp-route-id="@item.ProductId">@item.ProductName</a>
}else {
  <a href="@Url.RouteUrl("Product", new { SeName = item.ProductSeoName })" target="_blank">@item.ProductName</a>
}</em>
    • Se il vendorID è quello di Webmobili-dropship mostro il pulsante CLONA e ASSEGNA a RIVENDITORE.

Attenzione il metodo è cambiato da prodService.GetProductById(item.ProductId).VendorId a GetProductByIdAsync:

@{
	var productById = await prodService.GetProductByIdAsync(item.ProductId);
 }
@if (productById != null) {
 if (productById.VendorId == vendorWMDropship) {
  <button type="button" id="setProductToVendor" name="setProductToVendor" class="btn bg-olive" onclick="apriModaleAssegnazione(@item.ProductId,@item.Id,'@item.ProductName','@item.PictureThumbnailUrl');" data-toggle="modal" data-target="#setProductToVendor-window"><i class="fa fa-clone"></i>
CLONA e ASSEGNA a RIVENDITORE</button>
 }
}
    • Il pulsante CLONA e ASSEGNA a RIVENDITORE apre un modale in cui selezionare il rivenditore, innanzitutto dobbiamo creare la vista/componente del modale ProductToVendorModal