Added API to get plan List and add subscription to specific tenant
This commit is contained in:
parent
001bb6447d
commit
53a2c5d87c
53
Marco.Pms.CacheHelper/FeatureDetailsHelper.cs
Normal file
53
Marco.Pms.CacheHelper/FeatureDetailsHelper.cs
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using MongoDB.Driver;
|
||||||
|
|
||||||
|
namespace Marco.Pms.CacheHelper
|
||||||
|
{
|
||||||
|
public class FeatureDetailsHelper
|
||||||
|
{
|
||||||
|
private readonly IMongoCollection<FeatureDetails> _collection;
|
||||||
|
private readonly ILogger<FeatureDetailsHelper> _logger;
|
||||||
|
public FeatureDetailsHelper(IConfiguration configuration, ILogger<FeatureDetailsHelper> logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
var connectionString = configuration["MongoDB:ModificationConnectionString"];
|
||||||
|
var mongoUrl = new MongoUrl(connectionString);
|
||||||
|
var client = new MongoClient(mongoUrl); // Your MongoDB connection string
|
||||||
|
var mongoDB = client.GetDatabase(mongoUrl.DatabaseName); // Your MongoDB Database name
|
||||||
|
_collection = mongoDB.GetCollection<FeatureDetails>("FeatureDetails");
|
||||||
|
}
|
||||||
|
public async Task<FeatureDetails?> GetFeatureDetails(Guid Id)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var filter = Builders<FeatureDetails>.Filter.Eq(e => e.Id, Id);
|
||||||
|
|
||||||
|
var result = await _collection
|
||||||
|
.Find(filter)
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occured while fetchig features for subscription plan");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task<bool> AddFeatureDetails(FeatureDetails featureDetails)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _collection.InsertOneAsync(featureDetails);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occured while fetchig features for subscription plan");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ using Marco.Pms.Model.Master;
|
|||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Roles;
|
using Marco.Pms.Model.Roles;
|
||||||
using Marco.Pms.Model.TenantModel;
|
using Marco.Pms.Model.TenantModel;
|
||||||
|
using Marco.Pms.Model.TenantModels;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Identity;
|
using Microsoft.AspNetCore.Identity;
|
||||||
@ -32,7 +33,10 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
|
|
||||||
public DbSet<RefreshToken> RefreshTokens { get; set; }
|
public DbSet<RefreshToken> RefreshTokens { get; set; }
|
||||||
public DbSet<TenantStatus> TenantStatus { get; set; }
|
public DbSet<TenantStatus> TenantStatus { get; set; }
|
||||||
|
public DbSet<SubscriptionStatus> SubscriptionStatus { get; set; }
|
||||||
public DbSet<Tenant> Tenants { get; set; }
|
public DbSet<Tenant> Tenants { get; set; }
|
||||||
|
public DbSet<SubscriptionPlan> SubscriptionPlans { get; set; }
|
||||||
|
public DbSet<TenantSubscriptions> TenantSubscriptions { get; set; }
|
||||||
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
|
public DbSet<ApplicationUser> ApplicationUsers { get; set; }
|
||||||
public DbSet<ActivityMaster> ActivityMasters { get; set; }
|
public DbSet<ActivityMaster> ActivityMasters { get; set; }
|
||||||
public DbSet<Project> Projects { get; set; }
|
public DbSet<Project> Projects { get; set; }
|
||||||
@ -54,6 +58,7 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
public DbSet<Module> Modules { get; set; }
|
public DbSet<Module> Modules { get; set; }
|
||||||
public DbSet<Feature> Features { get; set; }
|
public DbSet<Feature> Features { get; set; }
|
||||||
public DbSet<FeaturePermission> FeaturePermissions { get; set; }
|
public DbSet<FeaturePermission> FeaturePermissions { get; set; }
|
||||||
|
public DbSet<CurrencyMaster> CurrencyMaster { get; set; }
|
||||||
public DbSet<ApplicationRole> ApplicationRoles { get; set; }
|
public DbSet<ApplicationRole> ApplicationRoles { get; set; }
|
||||||
public DbSet<JobRole> JobRoles { get; set; }
|
public DbSet<JobRole> JobRoles { get; set; }
|
||||||
public DbSet<RolePermissionMappings> RolePermissionMappings { get; set; }
|
public DbSet<RolePermissionMappings> RolePermissionMappings { get; set; }
|
||||||
@ -191,79 +196,11 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"),
|
ProjectStatusId = new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"),
|
||||||
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
||||||
}
|
}
|
||||||
//, new Project
|
|
||||||
//{
|
|
||||||
// Id = new Guid("3ef56a12-f5e5-4193-87d6-9e110ed10b86"),
|
|
||||||
// Name = "Project 2",
|
|
||||||
// ProjectAddress = "Project 2 Address",
|
|
||||||
// ContactPerson = "Project 2 Contact Person",
|
|
||||||
// StartDate = DateTime.ParseExact("2025-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture),
|
|
||||||
// EndDate = DateTime.ParseExact("2026-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture),
|
|
||||||
// ProjectStatusId = new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
//}, new Project
|
|
||||||
//{
|
|
||||||
// Id = new Guid("54d013e3-0a2b-48be-85c7-5ef03492a18c"),
|
|
||||||
// Name = "Project 3",
|
|
||||||
// ProjectAddress = "Project 3 Address",
|
|
||||||
// ContactPerson = "Project 3 Contact Person",
|
|
||||||
// StartDate = DateTime.ParseExact("2025-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture),
|
|
||||||
// EndDate = DateTime.ParseExact("2026-04-20 10:11:17.588000", "yyyy-MM-dd HH:mm:ss.ffffff", CultureInfo.InvariantCulture),
|
|
||||||
// ProjectStatusId = new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
//}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var tenantId = _httpContextAccessor.HttpContext?.Items["TenantId"]?.ToString();
|
var tenantId = _httpContextAccessor.HttpContext?.Items["TenantId"]?.ToString();
|
||||||
|
|
||||||
//modelBuilder.Entity<ActivityMaster>()
|
|
||||||
// .HasData(
|
|
||||||
// new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("4117b7de-ef6c-461f-a2c2-64eaac5f9a11"),
|
|
||||||
// ActivityName = "Core Cutting",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Number.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("1714f64d-7591-4419-bee5-118d21bb2855"),
|
|
||||||
// ActivityName = "Fabrication",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Meter.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("b3f51a93-dde6-45f9-8b22-f1bf017a640b"),
|
|
||||||
// ActivityName = "Welding",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Meter.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("53eedf44-4076-445f-be93-fedef17117e7"),
|
|
||||||
// ActivityName = "MS Support Fabrication",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Number.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("715b9ddb-d9e2-4afa-8987-d9918905cea4"),
|
|
||||||
// ActivityName = "MS Support Hanging",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Number.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("a3d191a7-a5aa-4dd8-a525-12c99263bbd6"),
|
|
||||||
// ActivityName = "Hydrant Volve",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Number.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }, new ActivityMaster
|
|
||||||
// {
|
|
||||||
// Id = new Guid("c138a7de-713a-4bd4-8292-b0b265be77a3"),
|
|
||||||
// ActivityName = "Sprinkler Installation",
|
|
||||||
// UnitOfMeasurement = UnitOfMeasurement.Number.ToString(),
|
|
||||||
// TenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26")
|
|
||||||
// }
|
|
||||||
// );
|
|
||||||
|
|
||||||
modelBuilder.Entity<Industry>().HasData(
|
modelBuilder.Entity<Industry>().HasData(
|
||||||
new Industry { Id = Guid.Parse("15436ee3-a650-469e-bfc2-59993f7514bb"), Name = "Information Technology (IT) Services" },
|
new Industry { Id = Guid.Parse("15436ee3-a650-469e-bfc2-59993f7514bb"), Name = "Information Technology (IT) Services" },
|
||||||
new Industry { Id = Guid.Parse("0a63e657-2c5f-49b5-854b-42c978293154"), Name = "Manufacturing & Production" },
|
new Industry { Id = Guid.Parse("0a63e657-2c5f-49b5-854b-42c978293154"), Name = "Manufacturing & Production" },
|
||||||
@ -483,34 +420,52 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
modelBuilder.Entity<Module>().HasData(new Module
|
modelBuilder.Entity<SubscriptionStatus>().HasData(
|
||||||
{
|
new SubscriptionStatus
|
||||||
Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"),
|
{
|
||||||
Name = "Project",
|
Id = Guid.Parse("cd3a68ea-41fd-42f0-bd0c-c871c7337727"),
|
||||||
Description = "Project Module",
|
Name = "Active"
|
||||||
Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02"
|
},
|
||||||
},
|
new SubscriptionStatus
|
||||||
new Module
|
{
|
||||||
{
|
Id = Guid.Parse("4ed487b1-af22-4e25-aecd-b63fd850cf2d"),
|
||||||
Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"),
|
Name = "InActive"
|
||||||
Name = "Employee",
|
},
|
||||||
Description = "Employee Module",
|
new SubscriptionStatus
|
||||||
Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637"
|
{
|
||||||
},
|
Id = Guid.Parse("1c0e422e-01b6-412f-b72a-1db004cc8a7f"),
|
||||||
new Module
|
Name = "Suspended"
|
||||||
{
|
}
|
||||||
Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"),
|
);
|
||||||
Name = "Masters",
|
modelBuilder.Entity<Module>().HasData(
|
||||||
Description = "Masters Module",
|
new Module
|
||||||
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
|
{
|
||||||
},
|
Id = new Guid("bf59fd88-b57a-4d67-bf01-3780f385896b"),
|
||||||
new Module
|
Name = "Project",
|
||||||
{
|
Description = "Project Module",
|
||||||
Id = new Guid("f482a079-4dec-4f2d-9867-6baf2a4f23d9"),
|
Key = "b04da7e9-0406-409c-ac7f-b97256e6ea02"
|
||||||
Name = "Tenant",
|
},
|
||||||
Description = "Tenant Module",
|
new Module
|
||||||
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
|
{
|
||||||
});
|
Id = new Guid("2a231490-bcb1-4bdd-91f1-f25fb7f25b23"),
|
||||||
|
Name = "Employee",
|
||||||
|
Description = "Employee Module",
|
||||||
|
Key = "0971c7fb-6ce1-458a-ae3f-8d3205893637"
|
||||||
|
},
|
||||||
|
new Module
|
||||||
|
{
|
||||||
|
Id = new Guid("c43db8c7-ab73-47f4-9d3b-f83e81357924"),
|
||||||
|
Name = "Masters",
|
||||||
|
Description = "Masters Module",
|
||||||
|
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
|
||||||
|
},
|
||||||
|
new Module
|
||||||
|
{
|
||||||
|
Id = new Guid("f482a079-4dec-4f2d-9867-6baf2a4f23d9"),
|
||||||
|
Name = "Tenant",
|
||||||
|
Description = "Tenant Module",
|
||||||
|
Key = "504ec132-e6a9-422f-8f85-050602cfce05"
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -565,6 +520,65 @@ namespace Marco.Pms.DataAccess.Data
|
|||||||
//new FeaturePermission { Id = new Guid("6b1a6d97-a951-4de5-9b19-709bac7c4f18"), FeatureId = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), IsEnabled = true, Name = "Manage Masters", Description = "" }
|
//new FeaturePermission { Id = new Guid("6b1a6d97-a951-4de5-9b19-709bac7c4f18"), FeatureId = new Guid("660131a4-788c-4739-a082-cbbf7879cbf2"), IsEnabled = true, Name = "Manage Masters", Description = "" }
|
||||||
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
modelBuilder.Entity<CurrencyMaster>().HasData(
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"),
|
||||||
|
CurrencyCode = "INR",
|
||||||
|
CurrencyName = "Indian Rupee",
|
||||||
|
Symbol = "₹",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("2f672568-a67b-4961-acb2-a8c7834e1762"),
|
||||||
|
CurrencyCode = "USD",
|
||||||
|
CurrencyName = "US Dollar",
|
||||||
|
Symbol = "$",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("4d1155bb-1448-4d97-a732-96c92eb99c45"),
|
||||||
|
CurrencyCode = "EUR",
|
||||||
|
CurrencyName = "Euro",
|
||||||
|
Symbol = "€",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("3e456237-ef06-4ea1-a261-188c9b0c6df6"),
|
||||||
|
CurrencyCode = "GBP",
|
||||||
|
CurrencyName = "Pound Sterling",
|
||||||
|
Symbol = "£",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("297e237a-56d3-48f6-b39d-ec3991dea8bf"),
|
||||||
|
CurrencyCode = "JPY",
|
||||||
|
CurrencyName = "Japanese Yen",
|
||||||
|
Symbol = "¥",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"),
|
||||||
|
CurrencyCode = "RUB",
|
||||||
|
CurrencyName = "Russian Ruble",
|
||||||
|
Symbol = "₽",
|
||||||
|
IsActive = true
|
||||||
|
},
|
||||||
|
new CurrencyMaster
|
||||||
|
{
|
||||||
|
Id = Guid.Parse("b960166a-f7e9-49e3-bb4b-28511f126c08"),
|
||||||
|
CurrencyCode = "CNY",
|
||||||
|
CurrencyName = "Chinese Yuan (Renminbi)",
|
||||||
|
Symbol = "¥",
|
||||||
|
IsActive = true
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
3872
Marco.Pms.DataAccess/Migrations/20250804061007_Added_Subscription_Related_Tables.Designer.cs
generated
Normal file
3872
Marco.Pms.DataAccess/Migrations/20250804061007_Added_Subscription_Related_Tables.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,243 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Added_Subscription_Related_Tables : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "CurrencyMaster",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
CurrencyCode = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
CurrencyName = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Symbol = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_CurrencyMaster", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SubscriptionStatus",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
Name = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SubscriptionStatus", x => x.Id);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "SubscriptionPlans",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
PlanName = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
Description = table.Column<string>(type: "longtext", nullable: false)
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4"),
|
||||||
|
PriceQuarterly = table.Column<double>(type: "double", nullable: false),
|
||||||
|
PriceMonthly = table.Column<double>(type: "double", nullable: false),
|
||||||
|
PriceHalfMonthly = table.Column<double>(type: "double", nullable: false),
|
||||||
|
PriceYearly = table.Column<double>(type: "double", nullable: false),
|
||||||
|
TrialDays = table.Column<int>(type: "int", nullable: false),
|
||||||
|
MaxUser = table.Column<double>(type: "double", nullable: false),
|
||||||
|
MaxStorage = table.Column<double>(type: "double", nullable: false),
|
||||||
|
FeaturesId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
CreateAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
UpdateAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||||
|
CurrencyId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||||
|
IsActive = table.Column<bool>(type: "tinyint(1)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_SubscriptionPlans", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_SubscriptionPlans_CurrencyMaster_CurrencyId",
|
||||||
|
column: x => x.CurrencyId,
|
||||||
|
principalTable: "CurrencyMaster",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_SubscriptionPlans_Employees_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_SubscriptionPlans_Employees_UpdatedById",
|
||||||
|
column: x => x.UpdatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "TenantSubscriptions",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
PlanId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
StartDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
EndDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
IsTrial = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
StatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
CurrencyId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
NextBillingDate = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
CancellationDate = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||||
|
AutoRemew = table.Column<bool>(type: "tinyint(1)", nullable: false),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
|
||||||
|
UpdateAt = table.Column<DateTime>(type: "datetime(6)", nullable: true),
|
||||||
|
CreatedById = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||||
|
UpdatedById = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
|
||||||
|
TenantId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_TenantSubscriptions", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_CurrencyMaster_CurrencyId",
|
||||||
|
column: x => x.CurrencyId,
|
||||||
|
principalTable: "CurrencyMaster",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_Employees_CreatedById",
|
||||||
|
column: x => x.CreatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_Employees_UpdatedById",
|
||||||
|
column: x => x.UpdatedById,
|
||||||
|
principalTable: "Employees",
|
||||||
|
principalColumn: "Id");
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_SubscriptionPlans_PlanId",
|
||||||
|
column: x => x.PlanId,
|
||||||
|
principalTable: "SubscriptionPlans",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_SubscriptionStatus_StatusId",
|
||||||
|
column: x => x.StatusId,
|
||||||
|
principalTable: "SubscriptionStatus",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TenantSubscriptions_Tenants_TenantId",
|
||||||
|
column: x => x.TenantId,
|
||||||
|
principalTable: "Tenants",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
})
|
||||||
|
.Annotation("MySql:CharSet", "utf8mb4");
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "CurrencyMaster",
|
||||||
|
columns: new[] { "Id", "CurrencyCode", "CurrencyName", "IsActive", "Symbol" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"), "JPY", "Japanese Yen", true, "¥" },
|
||||||
|
{ new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"), "USD", "US Dollar", true, "$" },
|
||||||
|
{ new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"), "GBP", "Pound Sterling", true, "£" },
|
||||||
|
{ new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"), "EUR", "Euro", true, "€" },
|
||||||
|
{ new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"), "INR", "Indian Rupee", true, "₹" },
|
||||||
|
{ new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"), "CNY", "Chinese Yuan (Renminbi)", true, "¥" },
|
||||||
|
{ new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"), "RUB", "Russian Ruble", true, "₽" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.InsertData(
|
||||||
|
table: "SubscriptionStatus",
|
||||||
|
columns: new[] { "Id", "Name" },
|
||||||
|
values: new object[,]
|
||||||
|
{
|
||||||
|
{ new Guid("1c0e422e-01b6-412f-b72a-1db004cc8a7f"), "Suspended" },
|
||||||
|
{ new Guid("4ed487b1-af22-4e25-aecd-b63fd850cf2d"), "InActive" },
|
||||||
|
{ new Guid("cd3a68ea-41fd-42f0-bd0c-c871c7337727"), "Active" }
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_SubscriptionPlans_CreatedById",
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_SubscriptionPlans_CurrencyId",
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
column: "CurrencyId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_SubscriptionPlans_UpdatedById",
|
||||||
|
table: "SubscriptionPlans",
|
||||||
|
column: "UpdatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_CreatedById",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "CreatedById");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_CurrencyId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "CurrencyId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_PlanId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "PlanId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_StatusId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "StatusId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_TenantId",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "TenantId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TenantSubscriptions_UpdatedById",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
column: "UpdatedById");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "TenantSubscriptions");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SubscriptionPlans");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "SubscriptionStatus");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "CurrencyMaster");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3872
Marco.Pms.DataAccess/Migrations/20250804063600_Corrected_Typo_In_Subscription_Table.Designer.cs
generated
Normal file
3872
Marco.Pms.DataAccess/Migrations/20250804063600_Corrected_Typo_In_Subscription_Table.Designer.cs
generated
Normal file
File diff suppressed because one or more lines are too long
@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Marco.Pms.DataAccess.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class Corrected_Typo_In_Subscription_Table : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "AutoRemew",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
newName: "AutoRenew");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "AutoRenew",
|
||||||
|
table: "TenantSubscriptions",
|
||||||
|
newName: "AutoRemew");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1469,6 +1469,90 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
b.ToTable("ActivityMasters");
|
b.ToTable("ActivityMasters");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.Master.CurrencyMaster", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyCode")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<string>("CurrencyName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<string>("Symbol")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CurrencyMaster");
|
||||||
|
|
||||||
|
b.HasData(
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("78e96e4a-7ce0-4164-ae3a-c833ad45ec2c"),
|
||||||
|
CurrencyCode = "INR",
|
||||||
|
CurrencyName = "Indian Rupee",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "₹"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("2f672568-a67b-4961-acb2-a8c7834e1762"),
|
||||||
|
CurrencyCode = "USD",
|
||||||
|
CurrencyName = "US Dollar",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "$"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("4d1155bb-1448-4d97-a732-96c92eb99c45"),
|
||||||
|
CurrencyCode = "EUR",
|
||||||
|
CurrencyName = "Euro",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "€"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("3e456237-ef06-4ea1-a261-188c9b0c6df6"),
|
||||||
|
CurrencyCode = "GBP",
|
||||||
|
CurrencyName = "Pound Sterling",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "£"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("297e237a-56d3-48f6-b39d-ec3991dea8bf"),
|
||||||
|
CurrencyCode = "JPY",
|
||||||
|
CurrencyName = "Japanese Yen",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "¥"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("efe9b4f6-64d6-446e-a42d-1c7aaf6dd70d"),
|
||||||
|
CurrencyCode = "RUB",
|
||||||
|
CurrencyName = "Russian Ruble",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "₽"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("b960166a-f7e9-49e3-bb4b-28511f126c08"),
|
||||||
|
CurrencyCode = "CNY",
|
||||||
|
CurrencyName = "Chinese Yuan (Renminbi)",
|
||||||
|
IsActive = true,
|
||||||
|
Symbol = "¥"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b =>
|
modelBuilder.Entity("Marco.Pms.Model.Master.Feature", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
@ -1716,6 +1800,38 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.Master.SubscriptionStatus", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("SubscriptionStatus");
|
||||||
|
|
||||||
|
b.HasData(
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("cd3a68ea-41fd-42f0-bd0c-c871c7337727"),
|
||||||
|
Name = "Active"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("4ed487b1-af22-4e25-aecd-b63fd850cf2d"),
|
||||||
|
Name = "InActive"
|
||||||
|
},
|
||||||
|
new
|
||||||
|
{
|
||||||
|
Id = new Guid("1c0e422e-01b6-412f-b72a-1db004cc8a7f"),
|
||||||
|
Name = "Suspended"
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Marco.Pms.Model.Master.TenantStatus", b =>
|
modelBuilder.Entity("Marco.Pms.Model.Master.TenantStatus", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
@ -2400,6 +2516,138 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.TenantModels.SubscriptionPlan", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreateAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedById")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid>("CurrencyId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<Guid>("FeaturesId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<double>("MaxStorage")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<double>("MaxUser")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<string>("PlanName")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("longtext");
|
||||||
|
|
||||||
|
b.Property<double>("PriceHalfMonthly")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<double>("PriceMonthly")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<double>("PriceQuarterly")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<double>("PriceYearly")
|
||||||
|
.HasColumnType("double");
|
||||||
|
|
||||||
|
b.Property<int>("TrialDays")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdateAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UpdatedById")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedById");
|
||||||
|
|
||||||
|
b.HasIndex("CurrencyId");
|
||||||
|
|
||||||
|
b.HasIndex("UpdatedById");
|
||||||
|
|
||||||
|
b.ToTable("SubscriptionPlans");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.TenantModels.TenantSubscriptions", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<bool>("AutoRenew")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("CancellationDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid>("CreatedById")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid>("CurrencyId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("EndDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsTrial")
|
||||||
|
.HasColumnType("tinyint(1)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("NextBillingDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid>("PlanId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("StartDate")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid>("StatusId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<Guid>("TenantId")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("UpdateAt")
|
||||||
|
.HasColumnType("datetime(6)");
|
||||||
|
|
||||||
|
b.Property<Guid?>("UpdatedById")
|
||||||
|
.HasColumnType("char(36)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("CreatedById");
|
||||||
|
|
||||||
|
b.HasIndex("CurrencyId");
|
||||||
|
|
||||||
|
b.HasIndex("PlanId");
|
||||||
|
|
||||||
|
b.HasIndex("StatusId");
|
||||||
|
|
||||||
|
b.HasIndex("TenantId");
|
||||||
|
|
||||||
|
b.HasIndex("UpdatedById");
|
||||||
|
|
||||||
|
b.ToTable("TenantSubscriptions");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b =>
|
modelBuilder.Entity("Marco.Pms.Model.Utilities.Inquiries", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
@ -3481,6 +3729,80 @@ namespace Marco.Pms.DataAccess.Migrations
|
|||||||
b.Navigation("TenantStatus");
|
b.Navigation("TenantStatus");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.TenantModels.SubscriptionPlan", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatedById")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.Master.CurrencyMaster", "Currency")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrencyId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UpdatedById");
|
||||||
|
|
||||||
|
b.Navigation("CreatedBy");
|
||||||
|
|
||||||
|
b.Navigation("Currency");
|
||||||
|
|
||||||
|
b.Navigation("UpdatedBy");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Marco.Pms.Model.TenantModels.TenantSubscriptions", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Marco.Pms.Model.Employees.Employee", "CreatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CreatedById")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.Master.CurrencyMaster", "Currency")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CurrencyId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.TenantModels.SubscriptionPlan", "Plan")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("PlanId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.Master.SubscriptionStatus", "Status")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("StatusId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.TenantModel.Tenant", "Tenant")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("TenantId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Marco.Pms.Model.Employees.Employee", "UpdatedBy")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("UpdatedById");
|
||||||
|
|
||||||
|
b.Navigation("CreatedBy");
|
||||||
|
|
||||||
|
b.Navigation("Currency");
|
||||||
|
|
||||||
|
b.Navigation("Plan");
|
||||||
|
|
||||||
|
b.Navigation("Status");
|
||||||
|
|
||||||
|
b.Navigation("Tenant");
|
||||||
|
|
||||||
|
b.Navigation("UpdatedBy");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim<string>", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null)
|
||||||
|
15
Marco.Pms.Model/Dtos/Tenant/AddSubscriptionDto.cs
Normal file
15
Marco.Pms.Model/Dtos/Tenant/AddSubscriptionDto.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Marco.Pms.Model.TenantModels;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class AddSubscriptionDto
|
||||||
|
{
|
||||||
|
public Guid TenantId { get; set; }
|
||||||
|
public Guid PlanId { get; set; }
|
||||||
|
public Guid CurrencyId { get; set; }
|
||||||
|
public int MaxUsers { get; set; }
|
||||||
|
public PLAN_FREQUENCY Frequency { get; set; }
|
||||||
|
public bool IsTrial { get; set; } = false;
|
||||||
|
public bool AutoRenew { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
10
Marco.Pms.Model/Dtos/Tenant/AttendanceDetailsDto.cs
Normal file
10
Marco.Pms.Model/Dtos/Tenant/AttendanceDetailsDto.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class AttendanceDetailsDto
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public bool ManualEntry { get; set; } = true;
|
||||||
|
public bool LocationTracking { get; set; } = true;
|
||||||
|
public bool ShiftManagement { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
9
Marco.Pms.Model/Dtos/Tenant/DirectoryDetailsDto.cs
Normal file
9
Marco.Pms.Model/Dtos/Tenant/DirectoryDetailsDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class DirectoryDetailsDto
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public int BucketLimit { get; set; } = 25;
|
||||||
|
public bool OrganizationChart { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
7
Marco.Pms.Model/Dtos/Tenant/ExpenseModuleDetailsDto.cs
Normal file
7
Marco.Pms.Model/Dtos/Tenant/ExpenseModuleDetailsDto.cs
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class ExpenseModuleDetailsDto
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
10
Marco.Pms.Model/Dtos/Tenant/FeatureDetailsDto.cs
Normal file
10
Marco.Pms.Model/Dtos/Tenant/FeatureDetailsDto.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class FeatureDetailsDto
|
||||||
|
{
|
||||||
|
public ModulesDetailsDto? Modules { get; set; }
|
||||||
|
public ReportDetailsDto? Reports { get; set; }
|
||||||
|
public SupportDetailsDto? Supports { get; set; }
|
||||||
|
public List<SubscriptionCheckListDto> SubscriptionCheckList { get; set; } = new List<SubscriptionCheckListDto>();
|
||||||
|
}
|
||||||
|
}
|
10
Marco.Pms.Model/Dtos/Tenant/ModulesDetailsDto.cs
Normal file
10
Marco.Pms.Model/Dtos/Tenant/ModulesDetailsDto.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class ModulesDetailsDto
|
||||||
|
{
|
||||||
|
public ProjectManagementDetailsDto? ProjectManagement { get; set; }
|
||||||
|
public AttendanceDetailsDto? Attendance { get; set; }
|
||||||
|
public DirectoryDetailsDto? Directory { get; set; }
|
||||||
|
public ExpenseModuleDetailsDto? Expense { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
Marco.Pms.Model/Dtos/Tenant/ProjectManagementDetailsDto.cs
Normal file
11
Marco.Pms.Model/Dtos/Tenant/ProjectManagementDetailsDto.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class ProjectManagementDetailsDto
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public int MaxProject { get; set; } = 10;
|
||||||
|
public double MaxTaskPerProject { get; set; } = 100000000;
|
||||||
|
public bool GanttChart { get; set; } = false;
|
||||||
|
public bool ResourceAllocation { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
9
Marco.Pms.Model/Dtos/Tenant/ReportDetailsDto.cs
Normal file
9
Marco.Pms.Model/Dtos/Tenant/ReportDetailsDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class ReportDetailsDto
|
||||||
|
{
|
||||||
|
public bool BasicReports { get; set; } = true;
|
||||||
|
public bool CustomReports { get; set; } = false;
|
||||||
|
public List<string> ExportData { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
8
Marco.Pms.Model/Dtos/Tenant/SubscriptionCheckListDto.cs
Normal file
8
Marco.Pms.Model/Dtos/Tenant/SubscriptionCheckListDto.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class SubscriptionCheckListDto
|
||||||
|
{
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
19
Marco.Pms.Model/Dtos/Tenant/SubscriptionPlanDto.cs
Normal file
19
Marco.Pms.Model/Dtos/Tenant/SubscriptionPlanDto.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class SubscriptionPlanDto
|
||||||
|
{
|
||||||
|
public Guid? Id { get; set; }
|
||||||
|
public required string PlanName { get; set; }
|
||||||
|
public required string Description { get; set; }
|
||||||
|
public double PriceQuarterly { get; set; }
|
||||||
|
public double PriceMonthly { get; set; }
|
||||||
|
public double PriceHalfMonthly { get; set; }
|
||||||
|
public double PriceYearly { get; set; }
|
||||||
|
public required int TrialDays { get; set; }
|
||||||
|
public required double MaxUser { get; set; }
|
||||||
|
public double MaxStorage { get; set; }
|
||||||
|
public required FeatureDetailsDto Features { get; set; }
|
||||||
|
public Guid CurrencyId { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
9
Marco.Pms.Model/Dtos/Tenant/SupportDetailsDto.cs
Normal file
9
Marco.Pms.Model/Dtos/Tenant/SupportDetailsDto.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Marco.Pms.Model.Dtos.Tenant
|
||||||
|
{
|
||||||
|
public class SupportDetailsDto
|
||||||
|
{
|
||||||
|
public bool EmailSupport { get; set; } = true;
|
||||||
|
public bool PhoneSupport { get; set; } = false;
|
||||||
|
public bool PrioritySupport { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
11
Marco.Pms.Model/Master/CurrencyMaster.cs
Normal file
11
Marco.Pms.Model/Master/CurrencyMaster.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace Marco.Pms.Model.Master
|
||||||
|
{
|
||||||
|
public class CurrencyMaster
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string CurrencyCode { get; set; } = string.Empty;
|
||||||
|
public string CurrencyName { get; set; } = string.Empty;
|
||||||
|
public string Symbol { get; set; } = string.Empty;
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
8
Marco.Pms.Model/Master/SubscriptionStatus.cs
Normal file
8
Marco.Pms.Model/Master/SubscriptionStatus.cs
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
namespace Marco.Pms.Model.Master
|
||||||
|
{
|
||||||
|
public class SubscriptionStatus
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class AttendanceDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public bool ManualEntry { get; set; } = true;
|
||||||
|
public bool LocationTracking { get; set; } = true;
|
||||||
|
public bool ShiftManagement { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class DirectoryDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public int BucketLimit { get; set; } = 25;
|
||||||
|
public bool OrganizationChart { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,13 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class ExpenseModuleDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
18
Marco.Pms.Model/TenantModels/MongoDBModel/FeatureDetails.cs
Normal file
18
Marco.Pms.Model/TenantModels/MongoDBModel/FeatureDetails.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class FeatureDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public ModulesDetails? Modules { get; set; }
|
||||||
|
public ReportDetails? Reports { get; set; }
|
||||||
|
public SupportDetails? Supports { get; set; }
|
||||||
|
public List<SubscriptionCheckList> SubscriptionCheckList { get; set; } = new List<SubscriptionCheckList>();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
16
Marco.Pms.Model/TenantModels/MongoDBModel/ModulesDetails.cs
Normal file
16
Marco.Pms.Model/TenantModels/MongoDBModel/ModulesDetails.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class ModulesDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public ProjectManagementDetails? ProjectManagement { get; set; }
|
||||||
|
public AttendanceDetails? Attendance { get; set; }
|
||||||
|
public DirectoryDetails? Directory { get; set; }
|
||||||
|
public ExpenseModuleDetails? Expense { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class ProjectManagementDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool Enabled { get; set; } = false;
|
||||||
|
public int MaxProject { get; set; } = 10;
|
||||||
|
public double MaxTaskPerProject { get; set; } = 100000000;
|
||||||
|
public bool GanttChart { get; set; } = false;
|
||||||
|
public bool ResourceAllocation { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
15
Marco.Pms.Model/TenantModels/MongoDBModel/ReportDetails.cs
Normal file
15
Marco.Pms.Model/TenantModels/MongoDBModel/ReportDetails.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class ReportDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool BasicReports { get; set; } = true;
|
||||||
|
public bool CustomReports { get; set; } = false;
|
||||||
|
public List<string> ExportData { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,14 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class SubscriptionCheckList
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public string Name { get; set; } = string.Empty;
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
}
|
15
Marco.Pms.Model/TenantModels/MongoDBModel/SupportDetails.cs
Normal file
15
Marco.Pms.Model/TenantModels/MongoDBModel/SupportDetails.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using MongoDB.Bson;
|
||||||
|
using MongoDB.Bson.Serialization.Attributes;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels.MongoDBModel
|
||||||
|
{
|
||||||
|
public class SupportDetails
|
||||||
|
{
|
||||||
|
[BsonId]
|
||||||
|
[BsonRepresentation(BsonType.String)]
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
public bool EmailSupport { get; set; } = true;
|
||||||
|
public bool PhoneSupport { get; set; } = false;
|
||||||
|
public bool PrioritySupport { get; set; } = false;
|
||||||
|
}
|
||||||
|
}
|
45
Marco.Pms.Model/TenantModels/SubscriptionPlan.cs
Normal file
45
Marco.Pms.Model/TenantModels/SubscriptionPlan.cs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
using Marco.Pms.Model.Employees;
|
||||||
|
using Marco.Pms.Model.Master;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels
|
||||||
|
{
|
||||||
|
public class SubscriptionPlan
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string PlanName { get; set; } = string.Empty;
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public double PriceQuarterly { get; set; }
|
||||||
|
public double PriceMonthly { get; set; }
|
||||||
|
public double PriceHalfMonthly { get; set; }
|
||||||
|
public double PriceYearly { get; set; }
|
||||||
|
public int TrialDays { get; set; } = 30;
|
||||||
|
public double MaxUser { get; set; } = 10;
|
||||||
|
public double MaxStorage { get; set; }
|
||||||
|
public Guid FeaturesId { get; set; }
|
||||||
|
public DateTime CreateAt { get; set; }
|
||||||
|
public DateTime? UpdateAt { get; set; }
|
||||||
|
public Guid CurrencyId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("CurrencyId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public CurrencyMaster? Currency { get; set; }
|
||||||
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("CreatedById")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Employee? CreatedBy { get; set; }
|
||||||
|
public Guid? UpdatedById { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("UpdatedById")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Employee? UpdatedBy { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum PLAN_FREQUENCY
|
||||||
|
{
|
||||||
|
MONTHLY = 0, QUARTERLY = 1, HALF_MONTHLY = 2, YEARLY = 3
|
||||||
|
}
|
||||||
|
}
|
46
Marco.Pms.Model/TenantModels/TenantSubscriptions.cs
Normal file
46
Marco.Pms.Model/TenantModels/TenantSubscriptions.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using Marco.Pms.Model.Employees;
|
||||||
|
using Marco.Pms.Model.Master;
|
||||||
|
using Marco.Pms.Model.Utilities;
|
||||||
|
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.TenantModels
|
||||||
|
{
|
||||||
|
public class TenantSubscriptions : TenantRelation
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public Guid PlanId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("PlanId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public SubscriptionPlan? Plan { get; set; }
|
||||||
|
public DateTime StartDate { get; set; }
|
||||||
|
public DateTime EndDate { get; set; }
|
||||||
|
public bool IsTrial { get; set; }
|
||||||
|
public Guid StatusId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("StatusId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public SubscriptionStatus? Status { get; set; }
|
||||||
|
public Guid CurrencyId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("CurrencyId")]
|
||||||
|
[ValidateNever]
|
||||||
|
public CurrencyMaster? Currency { get; set; }
|
||||||
|
public DateTime NextBillingDate { get; set; }
|
||||||
|
public DateTime? CancellationDate { get; set; }
|
||||||
|
public bool AutoRenew { get; set; } = true;
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime? UpdateAt { get; set; }
|
||||||
|
public Guid CreatedById { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("CreatedById")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Employee? CreatedBy { get; set; }
|
||||||
|
public Guid? UpdatedById { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("UpdatedById")]
|
||||||
|
[ValidateNever]
|
||||||
|
public Employee? UpdatedBy { get; set; }
|
||||||
|
}
|
||||||
|
}
|
18
Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanVM.cs
Normal file
18
Marco.Pms.Model/ViewModels/Tenant/SubscriptionPlanVM.cs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
using Marco.Pms.Model.Master;
|
||||||
|
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||||
|
|
||||||
|
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||||
|
{
|
||||||
|
public class SubscriptionPlanVM
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string? PlanName { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public double? Price { get; set; }
|
||||||
|
public int TrialDays { get; set; }
|
||||||
|
public double MaxUser { get; set; }
|
||||||
|
public double MaxStorage { get; set; }
|
||||||
|
public FeatureDetails? Features { get; set; }
|
||||||
|
public CurrencyMaster? Currency { get; set; }
|
||||||
|
}
|
||||||
|
}
|
@ -11,7 +11,7 @@ namespace Marco.Pms.Model.ViewModels.Tenant
|
|||||||
public string ContactName { get; set; } = string.Empty;
|
public string ContactName { get; set; } = string.Empty;
|
||||||
public string ContactNumber { get; set; } = string.Empty;
|
public string ContactNumber { get; set; } = string.Empty;
|
||||||
public string? logoImage { get; set; } // Base64
|
public string? logoImage { get; set; } // Base64
|
||||||
public string? OragnizationSize { get; set; }
|
public string? OrganizationSize { get; set; }
|
||||||
public Industry? Industry { get; set; }
|
public Industry? Industry { get; set; }
|
||||||
public TenantStatus? TenantStatus { get; set; }
|
public TenantStatus? TenantStatus { get; set; }
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using Marco.Pms.CacheHelper;
|
||||||
using Marco.Pms.DataAccess.Data;
|
using Marco.Pms.DataAccess.Data;
|
||||||
using Marco.Pms.Model.Dtos.Tenant;
|
using Marco.Pms.Model.Dtos.Tenant;
|
||||||
using Marco.Pms.Model.Employees;
|
using Marco.Pms.Model.Employees;
|
||||||
@ -6,6 +7,8 @@ using Marco.Pms.Model.Entitlements;
|
|||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.Roles;
|
using Marco.Pms.Model.Roles;
|
||||||
using Marco.Pms.Model.TenantModel;
|
using Marco.Pms.Model.TenantModel;
|
||||||
|
using Marco.Pms.Model.TenantModels;
|
||||||
|
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||||
using Marco.Pms.Model.Utilities;
|
using Marco.Pms.Model.Utilities;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
using Marco.Pms.Model.ViewModels.Tenant;
|
using Marco.Pms.Model.ViewModels.Tenant;
|
||||||
@ -34,14 +37,18 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
private readonly UserManager<ApplicationUser> _userManager;
|
private readonly UserManager<ApplicationUser> _userManager;
|
||||||
private readonly IMapper _mapper;
|
private readonly IMapper _mapper;
|
||||||
private readonly UserHelper _userHelper;
|
private readonly UserHelper _userHelper;
|
||||||
|
private readonly FeatureDetailsHelper _featureDetailsHelper;
|
||||||
|
|
||||||
private readonly static Guid activeStatus = Guid.Parse("62b05792-5115-4f99-8ff5-e8374859b191");
|
private readonly static Guid activeStatus = Guid.Parse("62b05792-5115-4f99-8ff5-e8374859b191");
|
||||||
|
private readonly static Guid activePlanStatus = Guid.Parse("cd3a68ea-41fd-42f0-bd0c-c871c7337727");
|
||||||
private readonly static string AdminRoleName = "Admin";
|
private readonly static string AdminRoleName = "Admin";
|
||||||
public TenantController(IDbContextFactory<ApplicationDbContext> dbContextFactory,
|
public TenantController(IDbContextFactory<ApplicationDbContext> dbContextFactory,
|
||||||
IServiceScopeFactory serviceScopeFactory,
|
IServiceScopeFactory serviceScopeFactory,
|
||||||
ILoggingService logger,
|
ILoggingService logger,
|
||||||
UserManager<ApplicationUser> userManager,
|
UserManager<ApplicationUser> userManager,
|
||||||
IMapper mapper,
|
IMapper mapper,
|
||||||
UserHelper userHelper)
|
UserHelper userHelper,
|
||||||
|
FeatureDetailsHelper featureDetailsHelper)
|
||||||
{
|
{
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContextFactory = dbContextFactory;
|
||||||
_serviceScopeFactory = serviceScopeFactory;
|
_serviceScopeFactory = serviceScopeFactory;
|
||||||
@ -49,6 +56,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
_userManager = userManager;
|
_userManager = userManager;
|
||||||
_mapper = mapper;
|
_mapper = mapper;
|
||||||
_userHelper = userHelper;
|
_userHelper = userHelper;
|
||||||
|
_featureDetailsHelper = featureDetailsHelper;
|
||||||
}
|
}
|
||||||
#region =================================================================== Tenant APIs ===================================================================
|
#region =================================================================== Tenant APIs ===================================================================
|
||||||
|
|
||||||
@ -85,7 +93,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||||
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
||||||
|
|
||||||
if (!hasPermission && !isRootUser)
|
if (!hasPermission || !isRootUser)
|
||||||
{
|
{
|
||||||
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to list tenants without 'ManageTenants' permission or root access.", loggedInEmployee.Id);
|
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to list tenants without 'ManageTenants' permission or root access.", loggedInEmployee.Id);
|
||||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
||||||
@ -336,6 +344,7 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
LastName = model.LastName,
|
LastName = model.LastName,
|
||||||
Email = model.Email,
|
Email = model.Email,
|
||||||
PhoneNumber = model.ContactNumber,
|
PhoneNumber = model.ContactNumber,
|
||||||
|
JoiningDate = model.OnBoardingDate,
|
||||||
ApplicationUserId = applicationUser.Id,
|
ApplicationUserId = applicationUser.Id,
|
||||||
JobRole = adminJobRole, // Link to the newly created role
|
JobRole = adminJobRole, // Link to the newly created role
|
||||||
CurrentAddress = model.BillingAddress,
|
CurrentAddress = model.BillingAddress,
|
||||||
@ -387,9 +396,11 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
// Create a default project for the new tenant
|
// Create a default project for the new tenant
|
||||||
var project = new Project
|
var project = new Project
|
||||||
{
|
{
|
||||||
Name = $"{model.OrganizationName} - Default Project",
|
Name = "Default Project",
|
||||||
ProjectStatusId = Guid.Parse("b74da4c2-d07e-46f2-9919-e75e49b12731"), // Consider using a constant for this GUID
|
ProjectStatusId = Guid.Parse("b74da4c2-d07e-46f2-9919-e75e49b12731"), // Consider using a constant for this GUID
|
||||||
ProjectAddress = model.BillingAddress,
|
ProjectAddress = model.BillingAddress,
|
||||||
|
StartDate = model.OnBoardingDate,
|
||||||
|
EndDate = DateTime.MaxValue,
|
||||||
ContactPerson = tenant.ContactName,
|
ContactPerson = tenant.ContactName,
|
||||||
TenantId = tenant.Id
|
TenantId = tenant.Id
|
||||||
};
|
};
|
||||||
@ -449,10 +460,156 @@ namespace Marco.Pms.Services.Controllers
|
|||||||
|
|
||||||
#region =================================================================== Subscription APIs ===================================================================
|
#region =================================================================== Subscription APIs ===================================================================
|
||||||
|
|
||||||
|
[HttpPost("add-subscription")]
|
||||||
|
public async Task<IActionResult> AddSubscription(AddSubscriptionDto model)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
|
||||||
|
var _permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
|
||||||
|
// A root user should have access regardless of the specific permission.
|
||||||
|
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||||
|
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
if (!hasPermission || !isRootUser)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to list tenants without 'ManageTenants' permission or root access.", loggedInEmployee.Id);
|
||||||
|
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
||||||
|
}
|
||||||
|
|
||||||
|
var tenantSubscription = new TenantSubscriptions
|
||||||
|
{
|
||||||
|
TenantId = model.TenantId,
|
||||||
|
PlanId = model.PlanId,
|
||||||
|
StatusId = activePlanStatus,
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
CreatedById = loggedInEmployee.Id,
|
||||||
|
CurrencyId = model.CurrencyId,
|
||||||
|
IsTrial = model.IsTrial,
|
||||||
|
StartDate = DateTime.UtcNow,
|
||||||
|
AutoRenew = model.AutoRenew
|
||||||
|
};
|
||||||
|
switch (model.Frequency)
|
||||||
|
{
|
||||||
|
case PLAN_FREQUENCY.MONTHLY:
|
||||||
|
tenantSubscription.EndDate = DateTime.UtcNow.AddMonths(1);
|
||||||
|
tenantSubscription.NextBillingDate = DateTime.UtcNow.AddMonths(1);
|
||||||
|
break;
|
||||||
|
case PLAN_FREQUENCY.QUARTERLY:
|
||||||
|
tenantSubscription.EndDate = DateTime.UtcNow.AddMonths(3);
|
||||||
|
tenantSubscription.NextBillingDate = DateTime.UtcNow.AddMonths(3);
|
||||||
|
break;
|
||||||
|
case PLAN_FREQUENCY.HALF_MONTHLY:
|
||||||
|
tenantSubscription.EndDate = DateTime.UtcNow.AddMonths(6);
|
||||||
|
tenantSubscription.NextBillingDate = DateTime.UtcNow.AddMonths(6);
|
||||||
|
break;
|
||||||
|
case PLAN_FREQUENCY.YEARLY:
|
||||||
|
tenantSubscription.EndDate = DateTime.UtcNow.AddMonths(12);
|
||||||
|
tenantSubscription.NextBillingDate = DateTime.UtcNow.AddMonths(12);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_context.TenantSubscriptions.Add(tenantSubscription);
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(tenantSubscription, "Tenant Subscription Successfully", 200));
|
||||||
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Subscription Plan APIs ===================================================================
|
#region =================================================================== Subscription Plan APIs ===================================================================
|
||||||
|
|
||||||
|
[HttpGet("list/subscription-plan")]
|
||||||
|
public async Task<IActionResult> GetSubscriptionPlanList([FromQuery] int frequency)
|
||||||
|
{
|
||||||
|
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
var plans = await _context.SubscriptionPlans.Include(s => s.Currency).ToListAsync();
|
||||||
|
|
||||||
|
var vm = await Task.WhenAll(plans.Select(async p =>
|
||||||
|
{
|
||||||
|
var response = _mapper.Map<SubscriptionPlanVM>(p);
|
||||||
|
switch (frequency)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
response.Price = p.PriceMonthly;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
response.Price = p.PriceMonthly;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
response.Price = p.PriceHalfMonthly;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
response.Price = p.PriceYearly;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
response.Features = await _featureDetailsHelper.GetFeatureDetails(p.FeaturesId);
|
||||||
|
return response;
|
||||||
|
}).ToList());
|
||||||
|
|
||||||
|
return Ok(ApiResponse<object>.SuccessResponse(vm, "List of plans fetched successfully", 200));
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("create/subscription-plan")]
|
||||||
|
public async Task<IActionResult> CreateSubscriptionPlan([FromBody] SubscriptionPlanDto model)
|
||||||
|
{
|
||||||
|
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||||
|
await using var _context = await _dbContextFactory.CreateDbContextAsync();
|
||||||
|
using var scope = _serviceScopeFactory.CreateScope();
|
||||||
|
|
||||||
|
var _permissionService = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||||
|
|
||||||
|
// A root user should have access regardless of the specific permission.
|
||||||
|
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||||
|
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
||||||
|
|
||||||
|
if (!hasPermission || !isRootUser)
|
||||||
|
{
|
||||||
|
_logger.LogWarning("Permission denied: User {EmployeeId} attempted to list tenants without 'ManageTenants' permission or root access.", loggedInEmployee.Id);
|
||||||
|
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access denied", "User does not have the required permissions for this action.", 403));
|
||||||
|
}
|
||||||
|
|
||||||
|
var currencyMaster = await _context.CurrencyMaster.AsNoTracking().FirstOrDefaultAsync(c => c.Id == model.CurrencyId);
|
||||||
|
if (currencyMaster == null)
|
||||||
|
{
|
||||||
|
return NotFound(ApiResponse<object>.ErrorResponse("Currency not found", "Currency not found", 404));
|
||||||
|
}
|
||||||
|
|
||||||
|
var plan = _mapper.Map<SubscriptionPlan>(model);
|
||||||
|
var features = _mapper.Map<FeatureDetails>(model.Features);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _featureDetailsHelper.AddFeatureDetails(features);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Exception occured while saving feature in mongoDB");
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(ex), 500));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
plan.FeaturesId = features.Id;
|
||||||
|
plan.CreatedById = loggedInEmployee.Id;
|
||||||
|
plan.CreateAt = DateTime.UtcNow;
|
||||||
|
|
||||||
|
_context.SubscriptionPlans.Add(plan);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _context.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
catch (DbUpdateException dbEx)
|
||||||
|
{
|
||||||
|
_logger.LogError(dbEx, "Database Exception occured while saving subscription plan");
|
||||||
|
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Error occured", ExceptionMapper(dbEx), 500));
|
||||||
|
}
|
||||||
|
|
||||||
|
var response = _mapper.Map<SubscriptionPlanVM>(plan);
|
||||||
|
response.Features = features;
|
||||||
|
response.Currency = currencyMaster;
|
||||||
|
|
||||||
|
return StatusCode(201, ApiResponse<object>.SuccessResponse(response, "Plan Created Successfully", 201));
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region =================================================================== Helper Functions ===================================================================
|
#region =================================================================== Helper Functions ===================================================================
|
||||||
|
@ -6,6 +6,8 @@ using Marco.Pms.Model.Master;
|
|||||||
using Marco.Pms.Model.MongoDBModels;
|
using Marco.Pms.Model.MongoDBModels;
|
||||||
using Marco.Pms.Model.Projects;
|
using Marco.Pms.Model.Projects;
|
||||||
using Marco.Pms.Model.TenantModel;
|
using Marco.Pms.Model.TenantModel;
|
||||||
|
using Marco.Pms.Model.TenantModels;
|
||||||
|
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||||
using Marco.Pms.Model.ViewModels.Activities;
|
using Marco.Pms.Model.ViewModels.Activities;
|
||||||
using Marco.Pms.Model.ViewModels.Employee;
|
using Marco.Pms.Model.ViewModels.Employee;
|
||||||
using Marco.Pms.Model.ViewModels.Projects;
|
using Marco.Pms.Model.ViewModels.Projects;
|
||||||
@ -29,6 +31,19 @@ namespace Marco.Pms.Services.MappingProfiles
|
|||||||
dest => dest.Name,
|
dest => dest.Name,
|
||||||
opt => opt.MapFrom(src => src.OrganizationName)
|
opt => opt.MapFrom(src => src.OrganizationName)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CreateMap<SubscriptionPlan, SubscriptionPlanVM>();
|
||||||
|
CreateMap<SubscriptionPlanDto, SubscriptionPlan>();
|
||||||
|
CreateMap<FeatureDetailsDto, FeatureDetails>();
|
||||||
|
CreateMap<SubscriptionCheckListDto, SubscriptionCheckList>();
|
||||||
|
CreateMap<SupportDetailsDto, SupportDetails>();
|
||||||
|
CreateMap<ReportDetailsDto, ReportDetails>();
|
||||||
|
CreateMap<ModulesDetailsDto, ModulesDetails>();
|
||||||
|
CreateMap<ProjectManagementDetailsDto, ProjectManagementDetails>();
|
||||||
|
CreateMap<AttendanceDetailsDto, AttendanceDetails>();
|
||||||
|
CreateMap<DirectoryDetailsDto, DirectoryDetails>();
|
||||||
|
CreateMap<ExpenseModuleDetailsDto, ExpenseModuleDetails>();
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region ======================================================= Projects =======================================================
|
#region ======================================================= Projects =======================================================
|
||||||
|
@ -183,6 +183,7 @@ builder.Services.AddScoped<DirectoryHelper>();
|
|||||||
builder.Services.AddScoped<MasterHelper>();
|
builder.Services.AddScoped<MasterHelper>();
|
||||||
builder.Services.AddScoped<ReportHelper>();
|
builder.Services.AddScoped<ReportHelper>();
|
||||||
builder.Services.AddScoped<CacheUpdateHelper>();
|
builder.Services.AddScoped<CacheUpdateHelper>();
|
||||||
|
builder.Services.AddScoped<FeatureDetailsHelper>();
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Cache Services
|
#region Cache Services
|
||||||
|
Loading…
x
Reference in New Issue
Block a user