diff --git a/zero.Core/Api/CountriesApi.cs b/zero.Core/Api/CountriesApi.cs index 0e6486bc..54ac100c 100644 --- a/zero.Core/Api/CountriesApi.cs +++ b/zero.Core/Api/CountriesApi.cs @@ -42,7 +42,7 @@ namespace zero.Core.Api { return await session.Query() .Scope(Scope) - .Where(x => x.LanguageId == languageId) + //.Where(x => x.LanguageId == languageId) .OrderByDescending(x => x.IsPreferred) .ThenBy(x => x.Name) .ToListAsync(); @@ -59,7 +59,7 @@ namespace zero.Core.Api { return await session.Query() .Scope(Scope) - .Where(x => x.LanguageId == languageId) + //.Where(x => x.LanguageId == languageId) .OrderByDescending(x => x.IsPreferred) .ThenBy(x => x.Name) .ToQueriedListAsync(query); diff --git a/zero.Core/Api/SetupApi.cs b/zero.Core/Api/SetupApi.cs index 7711c348..6057152c 100644 --- a/zero.Core/Api/SetupApi.cs +++ b/zero.Core/Api/SetupApi.cs @@ -211,7 +211,7 @@ namespace zero.Core.Api IsActive = true, AppId = Constants.Database.SharedAppId, Alias = Safenames.Alias(country.Value), - LanguageId = defaultLanguage.Id, + //LanguageId = defaultLanguage.Id, Code = country.Key.ToLowerInvariant(), Name = country.Value }).ToList()); diff --git a/zero.Core/Entities/Country.cs b/zero.Core/Entities/Country.cs index 49866f2b..e5d335be 100644 --- a/zero.Core/Entities/Country.cs +++ b/zero.Core/Entities/Country.cs @@ -12,14 +12,11 @@ namespace zero.Core.Entities /// public string Code { get; set; } - - /// - public string LanguageId { get; set; } } [Collection("Countries")] - public interface ICountry : IZeroEntity, IAppAwareShareableEntity, ILanguageAwareEntity, IZeroDbConventions + public interface ICountry : IZeroEntity, IAppAwareShareableEntity, IZeroDbConventions { /// /// Preferred countries are displayed on top in lists diff --git a/zero.Core/Entities/InheritAttribute.cs b/zero.Core/Entities/InheritAttribute.cs index b2ac527c..b5a06d26 100644 --- a/zero.Core/Entities/InheritAttribute.cs +++ b/zero.Core/Entities/InheritAttribute.cs @@ -2,7 +2,7 @@ namespace zero.Core.Entities { - internal class InheritAttribute : Attribute + public class OverwriteAttribute : Attribute { } } \ No newline at end of file diff --git a/zero.Core/Entities/Link.cs b/zero.Core/Entities/Link.cs deleted file mode 100644 index 14ba0869..00000000 --- a/zero.Core/Entities/Link.cs +++ /dev/null @@ -1,48 +0,0 @@ -using System.Collections.Generic; -using zero.Core.Attributes; - -namespace zero.Core.Entities -{ - public class Link : ZeroEntity, ILink - { - /// - public string AppId { get; set; } - - /// - public string OriginalId { get; set; } - - /// - public string Collection { get; set; } - - /// - public string Url { get; set; } - - /// - public Dictionary Params { get; set; } = new Dictionary(); - } - - - [Collection("Links")] - public interface ILink : IZeroEntity, IAppAwareEntity, IZeroDbConventions - { - /// - /// Id of the associated entity - /// - string OriginalId { get; set; } - - /// - /// Collection of the associated entity - /// - string Collection { get; set; } - - /// - /// Country code (ISO 3166-1) - /// - string Url { get; set; } - - /// - /// Optional parameters - /// - Dictionary Params { get; set; } - } -} diff --git a/zero.Core/Entities/ZeroEntity.cs b/zero.Core/Entities/ZeroEntity.cs index a8946680..cf89c157 100644 --- a/zero.Core/Entities/ZeroEntity.cs +++ b/zero.Core/Entities/ZeroEntity.cs @@ -29,6 +29,9 @@ namespace zero.Core.Entities /// public DateTimeOffset CreatedDate { get; set; } + + /// + public string OriginId { get; set; } } @@ -63,11 +66,18 @@ namespace zero.Core.Entities /// /// Backoffice user who created this content /// + [Overwrite] public string CreatedById { get; set; } /// /// Date of creation /// + [Overwrite] DateTimeOffset CreatedDate { get; set; } + + /// + /// Id of the original base entity (which this one inherits from) + /// + string OriginId { get; set; } } } diff --git a/zero.Core/Entities/ZeroEntityInterfaceBinder.cs b/zero.Core/Entities/ZeroEntityInterfaceBinder.cs deleted file mode 100644 index cdb0c28c..00000000 --- a/zero.Core/Entities/ZeroEntityInterfaceBinder.cs +++ /dev/null @@ -1,81 +0,0 @@ -//using Microsoft.AspNetCore.Mvc.ModelBinding; -//using Microsoft.AspNetCore.Mvc.ModelBinding.Binders; -//using System; -//using System.Collections.Generic; -//using System.Text; -//using System.Threading.Tasks; - -//namespace zero.Core.Entities -//{ -// public class ZeroEntityInterfaceBinderProvider : IModelBinderProvider -// { -// public IModelBinder GetBinder(ModelBinderProviderContext context) -// { -// if (context == null) -// { -// throw new ArgumentNullException(nameof(context)); -// } - -// if (context.Metadata.ModelType == typeof(IPage)) -// { -// return new BinderTypeModelBinder(typeof(ZeroEntityInterfaceBinder)); -// } - -// return null; -// } -// } - - -// public class ZeroEntityInterfaceBinder : IModelBinder -// { -// //private readonly AuthorContext _context; - -// //public ZeroEntityInterfaceBinder(AuthorContext context) -// //{ -// // _context = context; -// //} - -// public Task BindModelAsync(ModelBindingContext bindingContext) -// { -// if (bindingContext == null) -// { -// throw new ArgumentNullException(nameof(bindingContext)); -// } - -// var modelName = bindingContext.OriginalModelName; - -// // Try to fetch the value of the argument by name -// var valueProviderResult = bindingContext.ValueProvider.GetValue(modelName); - -// if (valueProviderResult == ValueProviderResult.None) -// { -// return Task.CompletedTask; -// } - -// bindingContext.ModelState.SetModelValue(modelName, valueProviderResult); - -// var value = valueProviderResult.FirstValue; - -// // Check if the argument value is null or empty -// //if (string.IsNullOrEmpty(value)) -// //{ -// // return Task.CompletedTask; -// //} - -// //if (!int.TryParse(value, out var id)) -// //{ -// // // Non-integer arguments result in model state errors -// // bindingContext.ModelState.TryAddModelError( -// // modelName, "Author Id must be an integer."); - -// // return Task.CompletedTask; -// //} - -// // Model will be null if not found, including for -// // out of range id values (0, -3, etc.) -// //var model = _context.Authors.Find(id); -// bindingContext.Result = ModelBindingResult.Success(new { name = "tobi" }); -// return Task.CompletedTask; -// } -// } -//} diff --git a/zero.Debug/Controllers/MigrationController.cs b/zero.Debug/Controllers/MigrationController.cs new file mode 100644 index 00000000..25b560b0 --- /dev/null +++ b/zero.Debug/Controllers/MigrationController.cs @@ -0,0 +1,158 @@ +using FluentValidation; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Infrastructure; +using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; +using Raven.Client.Documents; +using Raven.Client.Documents.Session; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using zero.Commerce.Api; +using zero.Commerce.Entities; +using zero.Core; +using zero.Core.Api; +using zero.Core.Attributes; +using zero.Core.Entities; +using zero.Core.Extensions; +using zero.Core.Utils; +using zero.Web.Filters; + +namespace zero.Debug.Controllers +{ + public class MigrationController : Controller + { + private IDocumentStore Raven { get; set; } + + public MigrationController(IDocumentStore raven) + { + Raven = raven; + } + + + [HttpGet] + public async Task SharedEntities() + { + async Task Handle() where T : IZeroIdEntity + { + return await SaveAll(); + } + + return Json(new + { + Applications = await Handle(), + Categories = await Handle(), + Channels = await Handle(), + Countries = await Handle(), + Currencies = await Handle(), + Customers = await Handle(), + Languages = await Handle(), + MailTemplates = await Handle(), + Manufacturers = await Handle(), + Media = await Handle(), + MediaFolders = await Handle(), + NumberTemplates = await Handle(), + OrderDetailStates = await Handle(), + Orders = await Handle(), + Pages = await Handle(), + ProductProperties = await Handle(), + Products = await Handle(), + RecycleBin = await Handle(), + ShippingOptions = await Handle(), + SpaceContents = await Handle(), + TaxRates = await Handle(), + Translations = await Handle(), + UserRoles = await Handle(), + Users = await Handle(), + }); + } + + + async Task> SaveAll() where T : IZeroIdEntity + { + HashSet changedIds = new HashSet(); + IList items; + + using (IAsyncDocumentSession session = Raven.OpenAsyncSession()) + { + items = await session.Query().ToListAsync(); + } + + foreach (T item in items) + { + if (await Save(item)) + { + changedIds.Add(item.Id); + } + } + + return changedIds; + } + + + async Task Save(T model) where T : IZeroIdEntity + { + IAppAwareEntity appAwareEntity = model as IAppAwareEntity; + IZeroEntity zeroEntity = model as IZeroEntity; + + bool hasChange = false; + + // set app id + if (appAwareEntity != null && appAwareEntity.AppId.IsNullOrEmpty()) + { + hasChange = true; + appAwareEntity.AppId = "shared"; + } + + // set unset Raven Ids + foreach (ObjectTraverser.Result item in ObjectTraverser.FindAttribute(model)) + { + string id = item.Property.GetValue(item.Parent, null) as string; + if (String.IsNullOrWhiteSpace(id)) + { + hasChange = true; + item.Property.SetValue(item.Parent, item.Item.Length.HasValue ? IdGenerator.Create(item.Item.Length.Value) : IdGenerator.Create()); + } + } + + string userId = HttpContext.User.Claims.FirstOrDefault(x => x.Type == Constants.Auth.Claims.UserId)?.Value; + + // set default properties + if (zeroEntity != null && zeroEntity.CreatedById == null) + { + hasChange = true; + zeroEntity.CreatedDate = zeroEntity.CreatedDate == default ? DateTimeOffset.Now : zeroEntity.CreatedDate; + zeroEntity.CreatedById = userId; + } + + if (zeroEntity != null && model is ITranslation) + { + zeroEntity.Name = ((ITranslation)model).Key; + } + + // update name alias and last modified + if (zeroEntity != null && zeroEntity.Alias.IsNullOrEmpty()) + { + hasChange = true; + zeroEntity.Alias = Safenames.Alias(zeroEntity.Name); + } + if (zeroEntity != null && zeroEntity.LastModifiedById == default) + { + hasChange = true; + zeroEntity.LastModifiedById = userId; + } + + if (!hasChange) + { + return false; + } + + using IAsyncDocumentSession session = Raven.OpenAsyncSession(); + await session.StoreAsync(model); + await session.SaveChangesAsync(); + return true; + } + } +} \ No newline at end of file diff --git a/zero.Web/Mapper/CountryMapperConfig.cs b/zero.Web/Mapper/CountryMapperConfig.cs index 45e429ce..bea476f7 100644 --- a/zero.Web/Mapper/CountryMapperConfig.cs +++ b/zero.Web/Mapper/CountryMapperConfig.cs @@ -17,7 +17,7 @@ namespace zero.Web.Mapper target.IsActive = source.IsActive; target.CreatedDate = source.CreatedDate; target.IsPreferred = source.IsPreferred; - target.LanguageId = source.LanguageId; + //target.LanguageId = source.LanguageId; target.Code = source.Code; }); @@ -28,7 +28,7 @@ namespace zero.Web.Mapper target.IsActive = source.IsActive; target.CreatedDate = source.CreatedDate; target.IsPreferred = source.IsPreferred; - target.LanguageId = source.LanguageId; + // target.LanguageId = source.LanguageId; target.Code = source.Code; });