Compare commits
No commits in common. "194764c9d6f5c27da06d5f0f42106144fb7c813e" and "4af68918217db7cd82c601b14510543707225d68" have entirely different histories.
194764c9d6
...
4af6891821
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Added_New_Parameter_In_Tenant_Table : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "OfficeNumber",
|
||||
table: "Tenants",
|
||||
type: "longtext",
|
||||
nullable: true)
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "Tenants",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"),
|
||||
column: "OfficeNumber",
|
||||
value: null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "OfficeNumber",
|
||||
table: "Tenants");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,28 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Fixed_Spelling_Mistake_In_Tenant_Table : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "OragnizationSize",
|
||||
table: "Tenants",
|
||||
newName: "OrganizationSize");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "OrganizationSize",
|
||||
table: "Tenants",
|
||||
newName: "OragnizationSize");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,207 +0,0 @@
|
||||
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: "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: "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");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,28 +0,0 @@
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,28 +0,0 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Corrected_Typo_In_SubscriptionPlan_Table : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "PriceHalfMonthly",
|
||||
table: "SubscriptionPlans",
|
||||
newName: "PriceHalfYearly");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.RenameColumn(
|
||||
name: "PriceHalfYearly",
|
||||
table: "SubscriptionPlans",
|
||||
newName: "PriceHalfMonthly");
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,411 +0,0 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Marco.Pms.DataAccess.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class Seprated_SubscriptionPlan_And_SubscriptionPlanDetails : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_StatusMasters_Tenants_TenantId",
|
||||
table: "StatusMasters");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_SubscriptionPlans_CurrencyMaster_CurrencyId",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_SubscriptionPlans_Employees_CreatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_SubscriptionPlans_Employees_UpdatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_TenantSubscriptions_SubscriptionPlans_PlanId",
|
||||
table: "TenantSubscriptions");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_SubscriptionPlans_CreatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_SubscriptionPlans_CurrencyId",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_SubscriptionPlans_UpdatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_StatusMasters_TenantId",
|
||||
table: "StatusMasters");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreateAt",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CreatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "CurrencyId",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "FeaturesId",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MaxStorage",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MaxUser",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PriceHalfYearly",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PriceMonthly",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PriceQuarterly",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "PriceYearly",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TrialDays",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdateAt",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "UpdatedById",
|
||||
table: "SubscriptionPlans");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "TenantId",
|
||||
table: "StatusMasters");
|
||||
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "IsCancelled",
|
||||
table: "TenantSubscriptions",
|
||||
type: "tinyint(1)",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "MaxUsers",
|
||||
table: "TenantSubscriptions",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.CreateTable(
|
||||
name: "SubscriptionPlanDetails",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
|
||||
Price = table.Column<double>(type: "double", nullable: false),
|
||||
Frequency = table.Column<int>(type: "int", 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),
|
||||
PlanId = 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"),
|
||||
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_SubscriptionPlanDetails", x => x.Id);
|
||||
table.ForeignKey(
|
||||
name: "FK_SubscriptionPlanDetails_CurrencyMaster_CurrencyId",
|
||||
column: x => x.CurrencyId,
|
||||
principalTable: "CurrencyMaster",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_SubscriptionPlanDetails_Employees_CreatedById",
|
||||
column: x => x.CreatedById,
|
||||
principalTable: "Employees",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
table.ForeignKey(
|
||||
name: "FK_SubscriptionPlanDetails_Employees_UpdatedById",
|
||||
column: x => x.UpdatedById,
|
||||
principalTable: "Employees",
|
||||
principalColumn: "Id");
|
||||
table.ForeignKey(
|
||||
name: "FK_SubscriptionPlanDetails_SubscriptionPlans_PlanId",
|
||||
column: x => x.PlanId,
|
||||
principalTable: "SubscriptionPlans",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
})
|
||||
.Annotation("MySql:CharSet", "utf8mb4");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SubscriptionPlanDetails_CreatedById",
|
||||
table: "SubscriptionPlanDetails",
|
||||
column: "CreatedById");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SubscriptionPlanDetails_CurrencyId",
|
||||
table: "SubscriptionPlanDetails",
|
||||
column: "CurrencyId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SubscriptionPlanDetails_PlanId",
|
||||
table: "SubscriptionPlanDetails",
|
||||
column: "PlanId");
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_SubscriptionPlanDetails_UpdatedById",
|
||||
table: "SubscriptionPlanDetails",
|
||||
column: "UpdatedById");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_TenantSubscriptions_SubscriptionPlanDetails_PlanId",
|
||||
table: "TenantSubscriptions",
|
||||
column: "PlanId",
|
||||
principalTable: "SubscriptionPlanDetails",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_TenantSubscriptions_SubscriptionPlanDetails_PlanId",
|
||||
table: "TenantSubscriptions");
|
||||
|
||||
migrationBuilder.DropTable(
|
||||
name: "SubscriptionPlanDetails");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "IsCancelled",
|
||||
table: "TenantSubscriptions");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "MaxUsers",
|
||||
table: "TenantSubscriptions");
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "CreateAt",
|
||||
table: "SubscriptionPlans",
|
||||
type: "datetime(6)",
|
||||
nullable: false,
|
||||
defaultValue: new DateTime(1, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified));
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "CreatedById",
|
||||
table: "SubscriptionPlans",
|
||||
type: "char(36)",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "CurrencyId",
|
||||
table: "SubscriptionPlans",
|
||||
type: "char(36)",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "FeaturesId",
|
||||
table: "SubscriptionPlans",
|
||||
type: "char(36)",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "MaxStorage",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "MaxUser",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "PriceHalfYearly",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "PriceMonthly",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "PriceQuarterly",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<double>(
|
||||
name: "PriceYearly",
|
||||
table: "SubscriptionPlans",
|
||||
type: "double",
|
||||
nullable: false,
|
||||
defaultValue: 0.0);
|
||||
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "TrialDays",
|
||||
table: "SubscriptionPlans",
|
||||
type: "int",
|
||||
nullable: false,
|
||||
defaultValue: 0);
|
||||
|
||||
migrationBuilder.AddColumn<DateTime>(
|
||||
name: "UpdateAt",
|
||||
table: "SubscriptionPlans",
|
||||
type: "datetime(6)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "UpdatedById",
|
||||
table: "SubscriptionPlans",
|
||||
type: "char(36)",
|
||||
nullable: true,
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.AddColumn<Guid>(
|
||||
name: "TenantId",
|
||||
table: "StatusMasters",
|
||||
type: "char(36)",
|
||||
nullable: false,
|
||||
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
|
||||
collation: "ascii_general_ci");
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StatusMasters",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("33deaef9-9af1-4f2a-b443-681ea0d04f81"),
|
||||
column: "TenantId",
|
||||
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StatusMasters",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("603e994b-a27f-4e5d-a251-f3d69b0498ba"),
|
||||
column: "TenantId",
|
||||
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StatusMasters",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("b74da4c2-d07e-46f2-9919-e75e49b12731"),
|
||||
column: "TenantId",
|
||||
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StatusMasters",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("cdad86aa-8a56-4ff4-b633-9c629057dfef"),
|
||||
column: "TenantId",
|
||||
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
|
||||
|
||||
migrationBuilder.UpdateData(
|
||||
table: "StatusMasters",
|
||||
keyColumn: "Id",
|
||||
keyValue: new Guid("ef1c356e-0fe0-42df-a5d3-8daee355492d"),
|
||||
column: "TenantId",
|
||||
value: new Guid("b3466e83-7e11-464c-b93a-daf047838b26"));
|
||||
|
||||
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_StatusMasters_TenantId",
|
||||
table: "StatusMasters",
|
||||
column: "TenantId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_StatusMasters_Tenants_TenantId",
|
||||
table: "StatusMasters",
|
||||
column: "TenantId",
|
||||
principalTable: "Tenants",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_SubscriptionPlans_CurrencyMaster_CurrencyId",
|
||||
table: "SubscriptionPlans",
|
||||
column: "CurrencyId",
|
||||
principalTable: "CurrencyMaster",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_SubscriptionPlans_Employees_CreatedById",
|
||||
table: "SubscriptionPlans",
|
||||
column: "CreatedById",
|
||||
principalTable: "Employees",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_SubscriptionPlans_Employees_UpdatedById",
|
||||
table: "SubscriptionPlans",
|
||||
column: "UpdatedById",
|
||||
principalTable: "Employees",
|
||||
principalColumn: "Id");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_TenantSubscriptions_SubscriptionPlans_PlanId",
|
||||
table: "TenantSubscriptions",
|
||||
column: "PlanId",
|
||||
principalTable: "SubscriptionPlans",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Cascade);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@ -1,7 +1,6 @@
|
||||
using Marco.Pms.Model.MongoDBModels.Employees;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Marco.Pms.Helpers.CacheHelper
|
||||
@ -9,11 +8,8 @@ namespace Marco.Pms.Helpers.CacheHelper
|
||||
public class EmployeeCache
|
||||
{
|
||||
private readonly IMongoCollection<EmployeePermissionMongoDB> _collection;
|
||||
private readonly ILogger<EmployeeCache> _logger;
|
||||
|
||||
public EmployeeCache(IConfiguration configuration, ILogger<EmployeeCache> logger)
|
||||
public EmployeeCache(IConfiguration configuration)
|
||||
{
|
||||
_logger = logger;
|
||||
var connectionString = configuration["MongoDB:ConnectionString"];
|
||||
var mongoUrl = new MongoUrl(connectionString);
|
||||
var client = new MongoClient(mongoUrl); // Your MongoDB connection string
|
||||
@ -189,25 +185,6 @@ namespace Marco.Pms.Helpers.CacheHelper
|
||||
|
||||
return true;
|
||||
}
|
||||
public async Task<bool> ClearAllEmployeesFromCacheByEmployeeIds(List<string> employeeIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<EmployeePermissionMongoDB>.Filter.In(x => x.Id, employeeIds);
|
||||
|
||||
var result = await _collection.DeleteManyAsync(filter);
|
||||
|
||||
if (result.DeletedCount == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting employee profile");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// A private method to handle the one-time setup of the collection's indexes.
|
||||
private async Task InitializeCollectionAsync()
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Marco.Pms.Helpers.Utility
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,224 +0,0 @@
|
||||
using Marco.Pms.Model.AppMenu;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace Marco.Pms.CacheHelper
|
||||
{
|
||||
public class SidebarMenuHelper
|
||||
{
|
||||
private readonly IMongoCollection<MenuSection> _collection;
|
||||
private readonly ILogger<SidebarMenuHelper> _logger;
|
||||
|
||||
public SidebarMenuHelper(IConfiguration configuration, ILogger<SidebarMenuHelper> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
var connectionString = configuration["MongoDB:ModificationConnectionString"];
|
||||
var mongoUrl = new MongoUrl(connectionString);
|
||||
var client = new MongoClient(mongoUrl);
|
||||
var database = client.GetDatabase(mongoUrl.DatabaseName);
|
||||
_collection = database.GetCollection<MenuSection>("Menus");
|
||||
}
|
||||
|
||||
public async Task<MenuSection?> CreateMenuSectionAsync(MenuSection section)
|
||||
{
|
||||
try
|
||||
{
|
||||
await _collection.InsertOneAsync(section);
|
||||
return section;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occurred while adding MenuSection.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MenuSection?> UpdateMenuSectionAsync(Guid sectionId, MenuSection updatedSection)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<MenuSection>.Filter.Eq(s => s.Id, sectionId);
|
||||
|
||||
var update = Builders<MenuSection>.Update
|
||||
.Set(s => s.Header, updatedSection.Header)
|
||||
.Set(s => s.Title, updatedSection.Title)
|
||||
.Set(s => s.Items, updatedSection.Items);
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update);
|
||||
|
||||
if (result.ModifiedCount > 0)
|
||||
{
|
||||
return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error updating MenuSection.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MenuSection?> AddMenuItemAsync(Guid sectionId, MenuItem newItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
newItem.Id = Guid.NewGuid();
|
||||
|
||||
var filter = Builders<MenuSection>.Filter.Eq(s => s.Id, sectionId);
|
||||
|
||||
var update = Builders<MenuSection>.Update.Push(s => s.Items, newItem);
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update);
|
||||
|
||||
if (result.ModifiedCount > 0)
|
||||
{
|
||||
return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding menu item.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MenuItem?> UpdateMenuItemAsync(Guid sectionId, Guid itemId, MenuItem updatedItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<MenuSection>.Filter.And(
|
||||
Builders<MenuSection>.Filter.Eq(s => s.Id, sectionId),
|
||||
Builders<MenuSection>.Filter.ElemMatch(s => s.Items, i => i.Id == itemId)
|
||||
);
|
||||
|
||||
var update = Builders<MenuSection>.Update
|
||||
.Set("Items.$.Text", updatedItem.Text)
|
||||
.Set("Items.$.Icon", updatedItem.Icon)
|
||||
.Set("Items.$.Available", updatedItem.Available)
|
||||
.Set("Items.$.Link", updatedItem.Link)
|
||||
.Set("Items.$.PermissionIds", updatedItem.PermissionIds);
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update);
|
||||
|
||||
if (result.ModifiedCount > 0)
|
||||
{
|
||||
// Re-fetch section and return the updated item
|
||||
var section = await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync();
|
||||
return section?.Items.FirstOrDefault(i => i.Id == itemId);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error updating MenuItem.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<MenuSection?> AddSubMenuItemAsync(Guid sectionId, Guid itemId, SubMenuItem newSubItem)
|
||||
{
|
||||
try
|
||||
{
|
||||
newSubItem.Id = Guid.NewGuid();
|
||||
|
||||
// Match the MenuSection and the specific MenuItem inside it
|
||||
var filter = Builders<MenuSection>.Filter.And(
|
||||
Builders<MenuSection>.Filter.Eq(s => s.Id, sectionId),
|
||||
Builders<MenuSection>.Filter.ElemMatch(s => s.Items, i => i.Id == itemId)
|
||||
);
|
||||
|
||||
// Use positional operator `$` to target matched MenuItem and push into its Submenu
|
||||
var update = Builders<MenuSection>.Update.Push("Items.$.Submenu", newSubItem);
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update);
|
||||
|
||||
if (result.ModifiedCount > 0)
|
||||
{
|
||||
return await _collection.Find(s => s.Id == sectionId).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error adding submenu item.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SubMenuItem?> UpdateSubmenuItemAsync(Guid sectionId, Guid itemId, Guid subItemId, SubMenuItem updatedSub)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<MenuSection>.Filter.Eq(s => s.Id, sectionId);
|
||||
|
||||
var arrayFilters = new List<ArrayFilterDefinition>
|
||||
{
|
||||
new BsonDocumentArrayFilterDefinition<BsonDocument>(
|
||||
new BsonDocument("item._id", itemId.ToString())),
|
||||
new BsonDocumentArrayFilterDefinition<BsonDocument>(
|
||||
new BsonDocument("sub._id", subItemId.ToString()))
|
||||
};
|
||||
|
||||
var update = Builders<MenuSection>.Update
|
||||
.Set("Items.$[item].Submenu.$[sub].Text", updatedSub.Text)
|
||||
.Set("Items.$[item].Submenu.$[sub].Available", updatedSub.Available)
|
||||
.Set("Items.$[item].Submenu.$[sub].Link", updatedSub.Link)
|
||||
.Set("Items.$[item].Submenu.$[sub].PermissionKeys", updatedSub.PermissionIds);
|
||||
|
||||
var options = new UpdateOptions { ArrayFilters = arrayFilters };
|
||||
|
||||
var result = await _collection.UpdateOneAsync(filter, update, options);
|
||||
|
||||
if (result.ModifiedCount == 0)
|
||||
return null;
|
||||
|
||||
var updatedSection = await _collection.Find(x => x.Id == sectionId).FirstOrDefaultAsync();
|
||||
|
||||
var subItem = updatedSection?.Items
|
||||
.FirstOrDefault(i => i.Id == itemId)?
|
||||
.Submenu
|
||||
.FirstOrDefault(s => s.Id == subItemId);
|
||||
|
||||
return subItem;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error updating SubMenuItem.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<List<MenuSection>> GetAllMenuSectionsAsync(Guid tenantId)
|
||||
{
|
||||
var filter = Builders<MenuSection>.Filter.Eq(e => e.TenantId, tenantId);
|
||||
|
||||
var result = await _collection
|
||||
.Find(filter)
|
||||
.ToListAsync();
|
||||
if (result.Any())
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
tenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26");
|
||||
filter = Builders<MenuSection>.Filter.Eq(e => e.TenantId, tenantId);
|
||||
|
||||
result = await _collection
|
||||
.Find(filter)
|
||||
.ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Marco.Pms.Model.AppMenu
|
||||
{
|
||||
public class MenuItem
|
||||
{
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public string? Text { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public string? Link { get; set; }
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
|
||||
public List<SubMenuItem> Submenu { get; set; } = new List<SubMenuItem>();
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Marco.Pms.Model.AppMenu
|
||||
{
|
||||
public class MenuSection
|
||||
{
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public string? Header { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public List<MenuItem> Items { get; set; } = new List<MenuItem>();
|
||||
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public Guid TenantId { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,20 +0,0 @@
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
|
||||
namespace Marco.Pms.Model.AppMenu
|
||||
{
|
||||
public class SubMenuItem
|
||||
{
|
||||
[BsonId]
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public Guid Id { get; set; } = Guid.NewGuid();
|
||||
|
||||
public string? Text { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public string Link { get; set; } = string.Empty;
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class CreateMenuItemDto
|
||||
{
|
||||
public required string Text { get; set; }
|
||||
public required string Icon { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public required string Link { get; set; }
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
|
||||
public List<CreateSubMenuItemDto> Submenu { get; set; } = new List<CreateSubMenuItemDto>();
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class CreateMenuSectionDto
|
||||
{
|
||||
public required string Header { get; set; }
|
||||
public required string Title { get; set; }
|
||||
public List<CreateMenuItemDto> Items { get; set; } = new List<CreateMenuItemDto>();
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class CreateSubMenuItemDto
|
||||
{
|
||||
public required string Text { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public required string Link { get; set; } = string.Empty;
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class UpdateMenuItemDto
|
||||
{
|
||||
public required Guid Id { get; set; }
|
||||
|
||||
public required string Text { get; set; }
|
||||
public required string Icon { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public required string Link { get; set; }
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class UpdateMenuSectionDto
|
||||
{
|
||||
public required Guid Id { get; set; }
|
||||
public required string Header { get; set; }
|
||||
public required string Title { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.AppMenu
|
||||
{
|
||||
public class UpdateSubMenuItemDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string? Text { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
|
||||
public string Link { get; set; } = string.Empty;
|
||||
|
||||
// Changed from string → List<string>
|
||||
public List<string> PermissionIds { get; set; } = new List<string>();
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
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 double MaxUsers { get; set; }
|
||||
public bool IsTrial { get; set; } = false;
|
||||
public bool AutoRenew { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class AttendanceDetailsDto
|
||||
{
|
||||
public List<Guid>? FeatureId { get; set; }
|
||||
public string Name { get; set; } = "Attendance Management";
|
||||
public bool Enabled { get; set; } = false;
|
||||
public bool ManualEntry { get; set; } = true;
|
||||
public bool LocationTracking { get; set; } = true;
|
||||
public bool ShiftManagement { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class CreateTenantDto
|
||||
{
|
||||
public required string FirstName { get; set; }
|
||||
public required string LastName { get; set; }
|
||||
public required string Email { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public required string BillingAddress { get; set; }
|
||||
public string? TaxId { get; set; }
|
||||
public string? logoImage { get; set; }
|
||||
public required string OrganizationName { get; set; }
|
||||
public string? OfficeNumber { get; set; }
|
||||
public required string ContactNumber { get; set; }
|
||||
public required DateTime OnBoardingDate { get; set; }
|
||||
public required string OrganizationSize { get; set; }
|
||||
public required Guid IndustryId { get; set; }
|
||||
public required string Reference { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class DirectoryDetailsDto
|
||||
{
|
||||
public List<Guid>? FeatureId { get; set; }
|
||||
public string Name { get; set; } = "Directory Management";
|
||||
public bool Enabled { get; set; } = false;
|
||||
public int BucketLimit { get; set; } = 25;
|
||||
public bool OrganizationChart { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class ExpenseModuleDetailsDto
|
||||
{
|
||||
public List<Guid>? FeatureId { get; set; }
|
||||
public string Name { get; set; } = "Expense Management";
|
||||
public bool Enabled { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class ProjectManagementDetailsDto
|
||||
{
|
||||
public List<Guid>? FeatureId { get; set; }
|
||||
public string Name { get; set; } = "Project Management";
|
||||
public bool Enabled { get; set; } = false;
|
||||
public int MaxProject { get; set; } = 10;
|
||||
public double MaxTaskPerProject { get; set; } = 100000;
|
||||
public bool GanttChart { get; set; } = false;
|
||||
public bool ResourceAllocation { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class SubscriptionCheckListDto
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class SubscriptionPlanDetailsDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
public double Price { 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; }
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
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 SubscriptionPlanDetailsDto? MonthlyPlan { get; set; }
|
||||
public SubscriptionPlanDetailsDto? QuarterlyPlan { get; set; }
|
||||
public SubscriptionPlanDetailsDto? HalfYearlyPlan { get; set; }
|
||||
public SubscriptionPlanDetailsDto? YearlyPlan { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,10 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class UpdateSubscriptionDto
|
||||
{
|
||||
public Guid TenantId { get; set; }
|
||||
public Guid PlanId { get; set; }
|
||||
public Guid CurrencyId { get; set; }
|
||||
public double? MaxUsers { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
namespace Marco.Pms.Model.Dtos.Tenant
|
||||
{
|
||||
public class UpdateTenantDto
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public required string FirstName { get; set; }
|
||||
public required string LastName { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public required string BillingAddress { get; set; }
|
||||
public string? TaxId { get; set; }
|
||||
public string? logoImage { get; set; }
|
||||
public string? OfficeNumber { get; set; }
|
||||
public required string ContactNumber { get; set; }
|
||||
public required string OrganizationSize { get; set; }
|
||||
public required Guid IndustryId { get; set; }
|
||||
public required string Reference { get; set; }
|
||||
}
|
||||
}
|
||||
25
Marco.Pms.Model/Entitlements/Client.cs
Normal file
25
Marco.Pms.Model/Entitlements/Client.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
|
||||
namespace Marco.Pms.Model.Entitlements
|
||||
{
|
||||
public class Tenant
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public string? ContactName { get; set; }
|
||||
public string? ContactNumber { get; set; }
|
||||
public DateTime OnBoardingDate { get; set; }
|
||||
public string? OragnizationSize { get; set; }
|
||||
public Guid? IndustryId { get; set; }
|
||||
|
||||
[ForeignKey("IndustryId")]
|
||||
[ValidateNever]
|
||||
public Industry? Industry { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
}
|
||||
}
|
||||
@ -2,14 +2,9 @@
|
||||
{
|
||||
public static class PermissionsMaster
|
||||
{
|
||||
public static readonly Guid ManageTenants = Guid.Parse("d032cb1a-3f30-462c-bef0-7ace73a71c0b");
|
||||
public static readonly Guid ModifyTenant = Guid.Parse("00e20637-ce8d-4417-bec4-9b31b5e65092");
|
||||
public static readonly Guid ViewTenant = Guid.Parse("647145c6-2108-4c98-aab4-178602236e55");
|
||||
|
||||
public static readonly Guid DirectoryAdmin = Guid.Parse("4286a13b-bb40-4879-8c6d-18e9e393beda");
|
||||
public static readonly Guid DirectoryManager = Guid.Parse("62668630-13ce-4f52-a0f0-db38af2230c5");
|
||||
public static readonly Guid DirectoryUser = Guid.Parse("0f919170-92d4-4337-abd3-49b66fc871bb");
|
||||
|
||||
public static readonly Guid ViewProject = Guid.Parse("6ea44136-987e-44ba-9e5d-1cf8f5837ebc");
|
||||
public static readonly Guid ManageProject = Guid.Parse("172fc9b6-755b-4f62-ab26-55c34a330614");
|
||||
public static readonly Guid ManageTeam = Guid.Parse("b94802ce-0689-4643-9e1d-11c86950c35b");
|
||||
@ -19,19 +14,15 @@
|
||||
public static readonly Guid AddAndEditTask = Guid.Parse("08752f33-3b29-4816-b76b-ea8a968ed3c5");
|
||||
public static readonly Guid AssignAndReportProgress = Guid.Parse("6a32379b-8b3f-49a6-8c48-4b7ac1b55dc2");
|
||||
public static readonly Guid ApproveTask = Guid.Parse("db4e40c5-2ba9-4b6d-b8a6-a16a250ff99c");
|
||||
|
||||
public static readonly Guid ViewAllEmployees = Guid.Parse("60611762-7f8a-4fb5-b53f-b1139918796b");
|
||||
public static readonly Guid ViewTeamMembers = Guid.Parse("b82d2b7e-0d52-45f3-997b-c008ea460e7f");
|
||||
public static readonly Guid AddAndEditEmployee = Guid.Parse("a97d366a-c2bb-448d-be93-402bd2324566");
|
||||
public static readonly Guid AssignRoles = Guid.Parse("fbd213e0-0250-46f1-9f5f-4b2a1e6e76a3");
|
||||
|
||||
public static readonly Guid TeamAttendance = Guid.Parse("915e6bff-65f6-4e3f-aea8-3fd217d3ea9e");
|
||||
public static readonly Guid RegularizeAttendance = Guid.Parse("57802c4a-00aa-4a1f-a048-fd2f70dd44b6");
|
||||
public static readonly Guid SelfAttendance = Guid.Parse("ccb0589f-712b-43de-92ed-5b6088e7dc4e");
|
||||
|
||||
public static readonly Guid ViewMasters = Guid.Parse("5ffbafe0-7ab0-48b1-bb50-c1bf76b65f9d");
|
||||
public static readonly Guid ManageMasters = Guid.Parse("588a8824-f924-4955-82d8-fc51956cf323");
|
||||
|
||||
public static readonly Guid ExpenseViewSelf = Guid.Parse("385be49f-8fde-440e-bdbc-3dffeb8dd116");
|
||||
public static readonly Guid ExpenseViewAll = Guid.Parse("01e06444-9ca7-4df4-b900-8c3fa051b92f");
|
||||
public static readonly Guid ExpenseUpload = Guid.Parse("0f57885d-bcb2-4711-ac95-d841ace6d5a7");
|
||||
|
||||
@ -35,10 +35,8 @@ namespace Marco.Pms.Model.Mapper
|
||||
PhoneNumber = model.PhoneNumber,
|
||||
Photo = base64String,
|
||||
IsActive = model.IsActive,
|
||||
IsRootUser = model.ApplicationUser?.IsRootUser ?? false,
|
||||
IsSystem = model.IsSystem,
|
||||
JoiningDate = model.JoiningDate,
|
||||
TenantId = model.TenantId
|
||||
JoiningDate = model.JoiningDate
|
||||
};
|
||||
}
|
||||
public static BasicEmployeeVM ToBasicEmployeeVMFromEmployee(this Employee employee)
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
namespace Marco.Pms.Model.Master
|
||||
using Marco.Pms.Model.Utilities;
|
||||
|
||||
namespace Marco.Pms.Model.Master
|
||||
{
|
||||
public class StatusMaster
|
||||
public class StatusMaster : TenantRelation
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Status { get; set; }
|
||||
|
||||
@ -1,8 +0,0 @@
|
||||
namespace Marco.Pms.Model.Master
|
||||
{
|
||||
public class SubscriptionStatus
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
namespace Marco.Pms.Model.Master
|
||||
{
|
||||
public class TenantStatus
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
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 string? Name { get; set; }
|
||||
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public List<Guid> FeatureId { get; set; } = new List<Guid>();
|
||||
public bool Enabled { get; set; } = false;
|
||||
public bool ManualEntry { get; set; } = true;
|
||||
public bool LocationTracking { get; set; } = true;
|
||||
public bool ShiftManagement { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
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 string? Name { get; set; }
|
||||
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public List<Guid> FeatureId { get; set; } = new List<Guid>();
|
||||
public bool Enabled { get; set; } = false;
|
||||
public int BucketLimit { get; set; } = 25;
|
||||
public bool OrganizationChart { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,17 +0,0 @@
|
||||
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 string? Name { get; set; }
|
||||
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public List<Guid> FeatureId { get; set; } = new List<Guid>();
|
||||
public bool Enabled { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
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>();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,16 +0,0 @@
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
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 string? Name { get; set; }
|
||||
|
||||
[BsonRepresentation(BsonType.String)]
|
||||
public List<Guid> FeatureId { get; set; } = new List<Guid>();
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
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>();
|
||||
}
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
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 bool IsActive { get; set; } = true;
|
||||
}
|
||||
|
||||
public enum PLAN_FREQUENCY
|
||||
{
|
||||
MONTHLY = 0, QUARTERLY = 1, HALF_YEARLY = 2, YEARLY = 3
|
||||
}
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
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 SubscriptionPlanDetails
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public double Price { get; set; }
|
||||
public PLAN_FREQUENCY Frequency { 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 PlanId { get; set; }
|
||||
|
||||
[ForeignKey("PlanId")]
|
||||
[ValidateNever]
|
||||
public SubscriptionPlan? Plan { 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;
|
||||
}
|
||||
}
|
||||
@ -1,38 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Marco.Pms.Model.TenantModels
|
||||
{
|
||||
public class Tenant
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string ContactNumber { get; set; } = string.Empty;
|
||||
public string? OfficeNumber { get; set; }
|
||||
public string BillingAddress { get; set; } = string.Empty;
|
||||
public string? TaxId { get; set; }
|
||||
public string? logoImage { get; set; } // Base64
|
||||
public DateTime OnBoardingDate { get; set; }
|
||||
public string? OrganizationSize { get; set; }
|
||||
public Guid? IndustryId { get; set; }
|
||||
|
||||
[ForeignKey("IndustryId")]
|
||||
[ValidateNever]
|
||||
public Industry? Industry { get; set; }
|
||||
public Guid? CreatedById { get; set; } // EmployeeId
|
||||
public Guid TenantStatusId { get; set; }
|
||||
|
||||
[ForeignKey("TenantStatusId")]
|
||||
[ValidateNever]
|
||||
public TenantStatus? TenantStatus { get; set; }
|
||||
public string Reference { get; set; } = string.Empty;
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsSuperTenant { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,48 +0,0 @@
|
||||
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 SubscriptionPlanDetails? Plan { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public bool IsTrial { get; set; }
|
||||
public double MaxUsers { 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 bool IsCancelled { get; set; } = false;
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
namespace Marco.Pms.Model.Utilities
|
||||
{
|
||||
public class TenantFilter
|
||||
{
|
||||
public List<Guid>? IndustryIds { get; set; }
|
||||
public List<Guid>? CreatedByIds { get; set; }
|
||||
public List<Guid>? TenantStatusIds { get; set; }
|
||||
public List<string>? References { get; set; }
|
||||
public DateTime? StartDate { get; set; }
|
||||
public DateTime? EndDate { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
|
||||
namespace Marco.Pms.Model.Utilities
|
||||
{
|
||||
|
||||
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.AppMenu
|
||||
{
|
||||
public class MenuSectionVm
|
||||
{
|
||||
public string? Header { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public List<MenuItemVm> Items { get; set; } = new();
|
||||
}
|
||||
|
||||
public class MenuItemVm
|
||||
{
|
||||
public string? Text { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
public string? Link { get; set; }
|
||||
public List<SubMenuItemVm> Submenu { get; set; } = new();
|
||||
}
|
||||
|
||||
public class SubMenuItemVm
|
||||
{
|
||||
public string? Text { get; set; }
|
||||
public bool Available { get; set; } = true;
|
||||
public string Link { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.AppMenu
|
||||
{
|
||||
public class MasterMenuVM
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
{
|
||||
public class MenuItemVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
public bool Available { get; set; }
|
||||
public string? Link { get; set; }
|
||||
public List<SubMenuItemVM> Submenu { get; set; } = new List<SubMenuItemVM>();
|
||||
}
|
||||
}
|
||||
@ -1,9 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
{
|
||||
public class MenuSectionApplicationVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public bool Available { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
{
|
||||
public class MenuSectionVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string? Header { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public List<MenuItemVM> Items { get; set; } = new List<MenuItemVM>();
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.DocumentManager
|
||||
{
|
||||
public class SubMenuItemVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
|
||||
public string? Name { get; set; }
|
||||
public bool Available { get; set; }
|
||||
|
||||
public string? Link { get; set; }
|
||||
}
|
||||
}
|
||||
@ -21,7 +21,6 @@
|
||||
public string? AadharNumber { get; set; }
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsRootUser { get; set; }
|
||||
public string? PanNumber { get; set; }
|
||||
|
||||
public string? Photo { get; set; } // To store the captured photo
|
||||
@ -29,7 +28,6 @@
|
||||
public string? ApplicationUserId { get; set; }
|
||||
|
||||
public Guid? JobRoleId { get; set; }
|
||||
public Guid TenantId { get; set; }
|
||||
public bool IsSystem { get; set; }
|
||||
public string? JobRole { get; set; }
|
||||
|
||||
|
||||
@ -1,11 +0,0 @@
|
||||
namespace Marco.Pms.Model.ViewModels.Projects
|
||||
{
|
||||
public class ProjectHisteryVM
|
||||
{
|
||||
public string? ProjectName { get; set; }
|
||||
public string? ProjectShortName { get; set; }
|
||||
public DateTime AssignedDate { get; set; }
|
||||
public DateTime? RemovedDate { get; set; }
|
||||
public string? Designation { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||
{
|
||||
public class SubscriptionPlanDetailsVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string? PlanName { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public double Price { get; set; }
|
||||
public double MaxUsers { get; set; }
|
||||
public PLAN_FREQUENCY Frequency { get; set; }
|
||||
public DateTime StartDate { get; set; }
|
||||
public DateTime EndDate { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime? UpdatedAt { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public BasicEmployeeVM? updatedBy { get; set; }
|
||||
public CurrencyMaster? Currency { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
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 PLAN_FREQUENCY? Frequency { 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; }
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||
{
|
||||
public class TenantDetailsVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string ContactNumber { get; set; } = string.Empty;
|
||||
public string? OfficeNumber { get; set; }
|
||||
public string BillingAddress { get; set; } = string.Empty;
|
||||
public string? TaxId { get; set; }
|
||||
public string? logoImage { get; set; } // Base64
|
||||
public DateTime OnBoardingDate { get; set; }
|
||||
public string? OrganizationSize { get; set; }
|
||||
public Industry? Industry { get; set; }
|
||||
public TenantStatus? TenantStatus { get; set; }
|
||||
public string Reference { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsSuperTenant { get; set; } = false;
|
||||
public int SeatsAvailable { get; set; }
|
||||
public int ActiveEmployees { get; set; }
|
||||
public int InActiveEmployees { get; set; }
|
||||
public int? ActiveProjects { get; set; }
|
||||
public int? InProgressProjects { get; set; }
|
||||
public int? OnHoldProjects { get; set; }
|
||||
public int? InActiveProjects { get; set; }
|
||||
public int? CompletedProjects { get; set; }
|
||||
public DateTime? ExpiryDate { get; set; }
|
||||
public DateTime? NextBillingDate { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; }
|
||||
public List<SubscriptionPlanDetailsVM>? SubscriptionHistery { get; set; }
|
||||
public SubscriptionPlanDetailsVM? CurrentPlan { get; set; }
|
||||
public FeatureDetails? CurrentPlanFeatures { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,18 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||
{
|
||||
public class TenantListVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? DomainName { get; set; }
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string ContactNumber { get; set; } = string.Empty;
|
||||
public string? logoImage { get; set; } // Base64
|
||||
public string? OrganizationSize { get; set; }
|
||||
public Industry? Industry { get; set; }
|
||||
public TenantStatus? TenantStatus { get; set; }
|
||||
}
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
|
||||
namespace Marco.Pms.Model.ViewModels.Tenant
|
||||
{
|
||||
public class TenantVM
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Email { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public string? DomainName { get; set; }
|
||||
public string ContactName { get; set; } = string.Empty;
|
||||
public string ContactNumber { get; set; } = string.Empty;
|
||||
public string BillingAddress { get; set; } = string.Empty;
|
||||
public string? TaxId { get; set; }
|
||||
public string? logoImage { get; set; } // Base64
|
||||
public DateTime OnBoardingDate { get; set; }
|
||||
public string? OrganizationSize { get; set; }
|
||||
public Industry? Industry { get; set; }
|
||||
public BasicEmployeeVM? CreatedBy { get; set; } // EmployeeId
|
||||
public TenantStatus? TenantStatus { get; set; }
|
||||
public string Reference { get; set; } = string.Empty;
|
||||
|
||||
public bool IsActive { get; set; } = true;
|
||||
public bool IsSuperTenant { get; set; } = false;
|
||||
}
|
||||
}
|
||||
@ -1,736 +0,0 @@
|
||||
using AutoMapper;
|
||||
using Marco.Pms.CacheHelper;
|
||||
using Marco.Pms.Model.AppMenu;
|
||||
using Marco.Pms.Model.Dtos.AppMenu;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.AppMenu;
|
||||
using Marco.Pms.Model.ViewModels.DocumentManager;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Service;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Marco.Pms.Services.Controllers
|
||||
{
|
||||
[Authorize]
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AppMenuController : ControllerBase
|
||||
{
|
||||
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly SidebarMenuHelper _sideBarMenuHelper;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly IServiceScopeFactory _serviceScopeFactory;
|
||||
|
||||
private readonly Guid tenantId;
|
||||
private static readonly Guid superTenantId = Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26");
|
||||
private static readonly Guid ProjectManagement = Guid.Parse("53176ebf-c75d-42e5-839f-4508ffac3def");
|
||||
private static readonly Guid ExpenseManagement = Guid.Parse("a4e25142-449b-4334-a6e5-22f70e4732d7");
|
||||
private static readonly Guid TaskManagement = Guid.Parse("9d4b5489-2079-40b9-bd77-6e1bf90bc19f");
|
||||
private static readonly Guid EmployeeManagement = Guid.Parse("81ab8a87-8ccd-4015-a917-0627cee6a100");
|
||||
private static readonly Guid AttendanceManagement = Guid.Parse("52c9cf54-1eb2-44d2-81bb-524cf29c0a94");
|
||||
private static readonly Guid MastersMangent = Guid.Parse("be3b3afc-6ccf-4566-b9b6-aafcb65546be");
|
||||
private static readonly Guid DirectoryManagement = Guid.Parse("39e66f81-efc6-446c-95bd-46bff6cfb606");
|
||||
private static readonly Guid TenantManagement = Guid.Parse("2f3509b7-160d-410a-b9b6-daadd96c986d");
|
||||
|
||||
public AppMenuController(UserHelper userHelper,
|
||||
SidebarMenuHelper sideBarMenuHelper,
|
||||
IMapper mapper,
|
||||
ILoggingService logger,
|
||||
IServiceScopeFactory serviceScopeFactory)
|
||||
{
|
||||
|
||||
_userHelper = userHelper;
|
||||
_sideBarMenuHelper = sideBarMenuHelper;
|
||||
_mapper = mapper;
|
||||
_logger = logger;
|
||||
_serviceScopeFactory = serviceScopeFactory;
|
||||
tenantId = userHelper.GetTenantId();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new sidebar menu section for the tenant.
|
||||
/// Only accessible by root users or for the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="menuSectionDto">The data for the new menu section.</param>
|
||||
/// <returns>HTTP response with result of the operation.</returns>
|
||||
|
||||
[HttpPost("add/sidebar/menu-section")]
|
||||
public async Task<IActionResult> CreateAppSideBarMenu([FromBody] CreateMenuSectionDto menuSectionDto)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser || tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: Employee {EmployeeId} attempted to create sidebar menu in Tenant {TenantId}", loggedInEmployee.Id, tenantId);
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Map DTO to entity
|
||||
var sideMenuSection = _mapper.Map<MenuSection>(menuSectionDto);
|
||||
sideMenuSection.TenantId = tenantId;
|
||||
|
||||
try
|
||||
{
|
||||
// Step 4: Save entity using helper
|
||||
sideMenuSection = await _sideBarMenuHelper.CreateMenuSectionAsync(sideMenuSection);
|
||||
|
||||
if (sideMenuSection == null)
|
||||
{
|
||||
_logger.LogWarning("Failed to create sidebar menu section. Tenant: {TenantId}, Request: {@MenuSectionDto}", tenantId, menuSectionDto);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid MenuSection", 400));
|
||||
}
|
||||
|
||||
// Step 5: Log success
|
||||
_logger.LogInfo("Sidebar menu created successfully. SectionId: {SectionId}, TenantId: {TenantId}, EmployeeId: {EmployeeId}",
|
||||
sideMenuSection.Id, tenantId, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(sideMenuSection, "Sidebar menu created successfully.", 201));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 6: Handle and log unexpected server errors
|
||||
_logger.LogError(ex, "Unexpected error occurred while creating sidebar menu. Tenant: {TenantId}, EmployeeId: {EmployeeId}, Request: {@MenuSectionDto}",
|
||||
tenantId, loggedInEmployee.Id, menuSectionDto);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing sidebar menu section for the tenant.
|
||||
/// Only accessible by root users or for the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="sectionId">The unique identifier of the section to update.</param>
|
||||
/// <param name="updatedSection">The updated data for the sidebar menu section.</param>
|
||||
/// <returns>HTTP response with the result of the operation.</returns>
|
||||
|
||||
[HttpPut("edit/sidebar/menu-section/{sectionId}")]
|
||||
public async Task<IActionResult> UpdateMenuSection(Guid sectionId, [FromBody] UpdateMenuSectionDto updatedSection)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser && tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: User {UserId} attempted to update sidebar menu section {SectionId} in Tenant {TenantId}",
|
||||
loggedInEmployee.Id, sectionId, tenantId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Validate request
|
||||
if (sectionId == Guid.Empty || sectionId != updatedSection.Id)
|
||||
{
|
||||
_logger.LogWarning("Invalid update request. Tenant: {TenantId}, SectionId: {SectionId}, PayloadId: {PayloadId}, UserId: {UserId}",
|
||||
tenantId, sectionId, updatedSection.Id, loggedInEmployee.Id);
|
||||
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid section ID or mismatched payload.", 400));
|
||||
}
|
||||
|
||||
// Step 4: Map DTO to entity
|
||||
var menuSectionEntity = _mapper.Map<MenuSection>(updatedSection);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 5: Perform update operation
|
||||
var result = await _sideBarMenuHelper.UpdateMenuSectionAsync(sectionId, menuSectionEntity);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Menu section not found for update. SectionId: {SectionId}, TenantId: {TenantId}, UserId: {UserId}",
|
||||
sectionId, tenantId, loggedInEmployee.Id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Menu section not found", 404));
|
||||
}
|
||||
|
||||
// Step 6: Successful update
|
||||
_logger.LogInfo("Menu section updated successfully. SectionId: {SectionId}, TenantId: {TenantId}, UserId: {UserId}",
|
||||
sectionId, tenantId, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Menu section updated successfully"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 7: Unexpected server error
|
||||
_logger.LogError(ex, "Failed to update menu section. SectionId: {SectionId}, TenantId: {TenantId}, UserId: {UserId}, Payload: {@UpdatedSection}",
|
||||
sectionId, tenantId, loggedInEmployee.Id, updatedSection);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server error", "An unexpected error occurred while updating the menu section.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new menu item to an existing sidebar menu section.
|
||||
/// Only accessible by root users or for the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="sectionId">The unique identifier of the section the item will be added to.</param>
|
||||
/// <param name="newItemDto">The details of the new menu item.</param>
|
||||
/// <returns>HTTP response with the result of the operation.</returns>
|
||||
|
||||
[HttpPost("add/sidebar/menus/{sectionId}/items")]
|
||||
public async Task<IActionResult> AddMenuItem(Guid sectionId, [FromBody] CreateMenuItemDto newItemDto)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser && tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: User {UserId} attempted to add menu item to section {SectionId} in Tenant {TenantId}",
|
||||
loggedInEmployee.Id, sectionId, tenantId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Input validation
|
||||
if (sectionId == Guid.Empty || newItemDto == null)
|
||||
{
|
||||
_logger.LogWarning("Invalid AddMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, UserId: {UserId}",
|
||||
tenantId, sectionId, loggedInEmployee.Id);
|
||||
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid section ID or menu item payload.", 400));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Step 4: Map DTO to entity
|
||||
var menuItemEntity = _mapper.Map<MenuItem>(newItemDto);
|
||||
|
||||
// Step 5: Perform Add operation
|
||||
var result = await _sideBarMenuHelper.AddMenuItemAsync(sectionId, menuItemEntity);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Menu section not found. Unable to add menu item. SectionId: {SectionId}, TenantId: {TenantId}, UserId: {UserId}",
|
||||
sectionId, tenantId, loggedInEmployee.Id);
|
||||
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Menu section not found", 404));
|
||||
}
|
||||
|
||||
// Step 6: Successful addition
|
||||
_logger.LogInfo("Menu item added successfully. SectionId: {SectionId}, MenuItemId: {MenuItemId}, TenantId: {TenantId}, UserId: {UserId}",
|
||||
sectionId, result.Id, tenantId, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Menu item added successfully"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 7: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error occurred while adding menu item. SectionId: {SectionId}, TenantId: {TenantId}, UserId: {UserId}, Payload: {@NewItemDto}",
|
||||
sectionId, tenantId, loggedInEmployee.Id, newItemDto);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server error", "An unexpected error occurred while adding the menu item.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing menu item inside a sidebar menu section.
|
||||
/// Only accessible by root users or within the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="sectionId">The ID of the sidebar menu section.</param>
|
||||
/// <param name="itemId">The ID of the menu item to update.</param>
|
||||
/// <param name="updatedMenuItem">The updated menu item details.</param>
|
||||
/// <returns>HTTP response with the result of the update operation.</returns>
|
||||
|
||||
[HttpPut("edit/sidebar/{sectionId}/items/{itemId}")]
|
||||
public async Task<IActionResult> UpdateMenuItem(Guid sectionId, Guid itemId, [FromBody] UpdateMenuItemDto updatedMenuItem)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser && tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: User {UserId} attempted to update menu item {ItemId} in Section {SectionId}, Tenant {TenantId}",
|
||||
loggedInEmployee.Id, itemId, sectionId, tenantId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Input validation
|
||||
if (sectionId == Guid.Empty || itemId == Guid.Empty || updatedMenuItem == null || updatedMenuItem.Id != itemId)
|
||||
{
|
||||
_logger.LogWarning("Invalid UpdateMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id);
|
||||
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid section ID, item ID, or menu item payload.", 400));
|
||||
}
|
||||
|
||||
// Step 4: Map DTO to entity
|
||||
var menuItemEntity = _mapper.Map<MenuItem>(updatedMenuItem);
|
||||
|
||||
try
|
||||
{
|
||||
// Step 5: Perform update operation
|
||||
var result = await _sideBarMenuHelper.UpdateMenuItemAsync(sectionId, itemId, menuItemEntity);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Menu item not found or update failed. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Menu item not found or update failed.", 404));
|
||||
}
|
||||
|
||||
// Step 6: Success log
|
||||
_logger.LogInfo("Menu item updated successfully. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Sidebar menu item updated successfully."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// ✅ Step 7: Handle server errors
|
||||
_logger.LogError(ex, "Error occurred while updating menu item. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}, Payload: {@UpdatedMenuItem}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id, updatedMenuItem);
|
||||
|
||||
return StatusCode(
|
||||
500,
|
||||
ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred while updating the menu item.", 500)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a new sub-menu item to an existing menu item inside a sidebar menu section.
|
||||
/// Only accessible by root users or within the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="sectionId">The ID of the sidebar menu section.</param>
|
||||
/// <param name="itemId">The ID of the parent menu item.</param>
|
||||
/// <param name="newSubItem">The details of the new sub-menu item.</param>
|
||||
/// <returns>HTTP response with the result of the add operation.</returns>
|
||||
|
||||
[HttpPost("add/sidebar/menus/{sectionId}/items/{itemId}/subitems")]
|
||||
public async Task<IActionResult> AddSubMenuItem(Guid sectionId, Guid itemId, [FromBody] CreateSubMenuItemDto newSubItem)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser && tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: User {UserId} attempted to add sub-menu item in Section {SectionId}, MenuItem {ItemId}, Tenant {TenantId}",
|
||||
loggedInEmployee.Id, sectionId, itemId, tenantId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Validate input
|
||||
if (sectionId == Guid.Empty || itemId == Guid.Empty || newSubItem == null)
|
||||
{
|
||||
_logger.LogWarning("Invalid AddSubMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id);
|
||||
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid section ID, item ID, or sub-menu item payload.", 400));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Step 4: Map DTO to entity
|
||||
var subMenuItemEntity = _mapper.Map<SubMenuItem>(newSubItem);
|
||||
|
||||
// Step 5: Perform add operation
|
||||
var result = await _sideBarMenuHelper.AddSubMenuItemAsync(sectionId, itemId, subMenuItemEntity);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Parent menu item not found. Failed to add sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id);
|
||||
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Parent menu item not found.", 404));
|
||||
}
|
||||
|
||||
// Step 6: Success logging
|
||||
_logger.LogInfo("Sub-menu item added successfully. Tenant: {TenantId}, SectionId: {SectionId}, ParentItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, result.Id, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Sub-menu item added successfully."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 7: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error occurred while adding sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, UserId: {UserId}, Payload: {@NewSubItem}",
|
||||
tenantId, sectionId, itemId, loggedInEmployee.Id, newSubItem);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred while adding the sub-menu item.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates an existing sub-menu item inside a sidebar menu section.
|
||||
/// Only accessible by root users or within the super tenant.
|
||||
/// </summary>
|
||||
/// <param name="sectionId">The ID of the sidebar menu section.</param>
|
||||
/// <param name="itemId">The ID of the parent menu item.</param>
|
||||
/// <param name="subItemId">The ID of the sub-menu item to update.</param>
|
||||
/// <param name="updatedSubMenuItem">The updated sub-menu item details.</param>
|
||||
/// <returns>HTTP response with the result of the update operation.</returns>
|
||||
|
||||
[HttpPut("edit/sidebar/{sectionId}/items/{itemId}/subitems/{subItemId}")]
|
||||
public async Task<IActionResult> UpdateSubmenuItem(Guid sectionId, Guid itemId, Guid subItemId, [FromBody] UpdateSubMenuItemDto updatedSubMenuItem)
|
||||
{
|
||||
// Step 1: Fetch logged-in user
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var isRootUser = loggedInEmployee.ApplicationUser?.IsRootUser ?? false;
|
||||
|
||||
// Step 2: Authorization check
|
||||
if (!isRootUser && tenantId != superTenantId)
|
||||
{
|
||||
_logger.LogWarning("Access denied: User {UserId} attempted to update sub-menu {SubItemId} under MenuItem {ItemId} in Section {SectionId}, Tenant {TenantId}",
|
||||
loggedInEmployee.Id, subItemId, itemId, sectionId, tenantId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse("Access Denied", "User does not have permission.", 403));
|
||||
}
|
||||
|
||||
// Step 3: Input validation
|
||||
if (sectionId == Guid.Empty || itemId == Guid.Empty || subItemId == Guid.Empty || updatedSubMenuItem == null || updatedSubMenuItem.Id != subItemId)
|
||||
{
|
||||
_logger.LogWarning("Invalid UpdateSubMenuItem request. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id);
|
||||
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid section ID, menu item ID, sub-item ID, or payload mismatch.", 400));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Step 4: Map DTO to entity
|
||||
var subMenuEntity = _mapper.Map<SubMenuItem>(updatedSubMenuItem);
|
||||
|
||||
// Step 5: Perform update operation
|
||||
var result = await _sideBarMenuHelper.UpdateSubmenuItemAsync(sectionId, itemId, subItemId, subMenuEntity);
|
||||
|
||||
if (result == null)
|
||||
{
|
||||
_logger.LogWarning("Sub-menu item not found or update failed. Tenant: {TenantId}, SectionId: {SectionId}, ItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id);
|
||||
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Sub-menu item not found.", 404));
|
||||
}
|
||||
|
||||
// Step 6: Log success
|
||||
_logger.LogInfo("Sub-menu item updated successfully. Tenant: {TenantId}, SectionId: {SectionId}, MenuItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}",
|
||||
tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Sub-menu item updated successfully."));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 7: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error occurred while updating sub-menu item. Tenant: {TenantId}, SectionId: {SectionId}, MenuItemId: {ItemId}, SubItemId: {SubItemId}, UserId: {UserId}, Payload: {@UpdatedSubMenuItem}",
|
||||
tenantId, sectionId, itemId, subItemId, loggedInEmployee.Id, updatedSubMenuItem);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred while updating the sub-menu item.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fetches the sidebar menu for the current tenant and filters items based on employee permissions.
|
||||
/// </summary>
|
||||
/// <returns>The sidebar menu with only the items/sub-items the employee has access to.</returns>
|
||||
|
||||
[HttpGet("get/menu")]
|
||||
public async Task<IActionResult> GetAppSideBarMenu()
|
||||
{
|
||||
// Step 1: Get logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var employeeId = loggedInEmployee.Id;
|
||||
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var _permissions = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
|
||||
try
|
||||
{
|
||||
// Step 2: Fetch all menu sections for the tenant
|
||||
var menus = await _sideBarMenuHelper.GetAllMenuSectionsAsync(tenantId);
|
||||
|
||||
foreach (var menu in menus)
|
||||
{
|
||||
var allowedItems = new List<MenuItem>();
|
||||
|
||||
foreach (var item in menu.Items)
|
||||
{
|
||||
// --- Item permission check ---
|
||||
if (!item.PermissionIds.Any())
|
||||
{
|
||||
allowedItems.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert permission string IDs to GUIDs
|
||||
var menuPermissionIds = item.PermissionIds
|
||||
.Select(Guid.Parse)
|
||||
.ToList();
|
||||
|
||||
bool isAllowed = await _permissions.HasPermissionAny(menuPermissionIds, employeeId);
|
||||
|
||||
// If allowed, filter its submenus as well
|
||||
if (isAllowed)
|
||||
{
|
||||
if (item.Submenu?.Any() == true)
|
||||
{
|
||||
var allowedSubmenus = new List<SubMenuItem>();
|
||||
|
||||
foreach (var subItem in item.Submenu)
|
||||
{
|
||||
if (!subItem.PermissionIds.Any())
|
||||
{
|
||||
allowedSubmenus.Add(subItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
var subMenuPermissionIds = subItem.PermissionIds
|
||||
.Select(Guid.Parse)
|
||||
.ToList();
|
||||
|
||||
bool isSubItemAllowed = await _permissions.HasPermissionAny(subMenuPermissionIds, employeeId);
|
||||
|
||||
if (isSubItemAllowed)
|
||||
{
|
||||
allowedSubmenus.Add(subItem);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace with filtered submenus
|
||||
item.Submenu = allowedSubmenus;
|
||||
}
|
||||
|
||||
allowedItems.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace with filtered items
|
||||
menu.Items = allowedItems;
|
||||
}
|
||||
|
||||
// Step 3: Log success
|
||||
_logger.LogInfo("Fetched sidebar menu successfully. Tenant: {TenantId}, EmployeeId: {EmployeeId}, SectionsReturned: {Count}",
|
||||
tenantId, employeeId, menus.Count);
|
||||
|
||||
var response = _mapper.Map<List<MenuSectionVM>>(menus);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Sidebar menu fetched successfully"));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 4: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error occurred while fetching sidebar menu. Tenant: {TenantId}, EmployeeId: {EmployeeId}",
|
||||
tenantId, employeeId);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred while fetching the sidebar menu.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the master menu list based on enabled features for the current tenant.
|
||||
/// </summary>
|
||||
/// <returns>List of master menu items available for the tenant</returns>
|
||||
|
||||
[HttpGet("get/master-list")]
|
||||
public async Task<IActionResult> GetMasterList()
|
||||
{
|
||||
// Start logging scope for observability
|
||||
|
||||
try
|
||||
{
|
||||
// Get currently logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
_logger.LogInfo("Fetching master list for EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var generalHelper = scope.ServiceProvider.GetRequiredService<GeneralHelper>();
|
||||
|
||||
// Define static master menus for each feature section
|
||||
var featureMenus = new Dictionary<Guid, List<MasterMenuVM>>
|
||||
{
|
||||
{
|
||||
EmployeeManagement, new List<MasterMenuVM>
|
||||
{
|
||||
new MasterMenuVM { Id = 1, Name = "Application Role" },
|
||||
new MasterMenuVM { Id = 2, Name = "Job Role" }
|
||||
}
|
||||
},
|
||||
{
|
||||
ProjectManagement, new List<MasterMenuVM>
|
||||
{
|
||||
new MasterMenuVM { Id = 3, Name = "Activity" },
|
||||
new MasterMenuVM { Id = 4, Name = "Work Category" }
|
||||
}
|
||||
},
|
||||
{
|
||||
DirectoryManagement, new List<MasterMenuVM>
|
||||
{
|
||||
new MasterMenuVM { Id = 5, Name = "Contact Category" },
|
||||
new MasterMenuVM { Id = 6, Name = "Contact Tag" }
|
||||
}
|
||||
},
|
||||
{
|
||||
ExpenseManagement, new List<MasterMenuVM>
|
||||
{
|
||||
new MasterMenuVM { Id = 7, Name = "Expense Type" },
|
||||
new MasterMenuVM { Id = 8, Name = "Payment Mode" }
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (tenantId == superTenantId)
|
||||
{
|
||||
var superResponse = featureMenus.Values.SelectMany(list => list).OrderBy(r => r.Name).ToList();
|
||||
|
||||
_logger.LogInfo("MasterMenu count for TenantId {TenantId}: {Count}", tenantId, superResponse.Count);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(superResponse, "Successfully fetched the master table list", 200));
|
||||
}
|
||||
|
||||
// Fetch features enabled for tenant
|
||||
var featureIds = await generalHelper.GetFeatureIdsByTenentIdAsync(tenantId);
|
||||
_logger.LogInfo("Enabled features for TenantId: {TenantId} -> {FeatureIds}", tenantId, string.Join(",", featureIds));
|
||||
|
||||
// Aggregate menus based on enabled features
|
||||
var response = featureIds
|
||||
.Where(id => featureMenus.ContainsKey(id))
|
||||
.SelectMany(id => featureMenus[id])
|
||||
.OrderBy(r => r.Name)
|
||||
.ToList();
|
||||
|
||||
_logger.LogInfo("MasterMenu count for TenantId {TenantId}: {Count}", tenantId, response.Count);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Successfully fetched the master table list", 200));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Critical error tracking
|
||||
_logger.LogError(ex, "Error occurred while fetching master menu list for TenantId: {TenantId}", tenantId);
|
||||
return StatusCode(500, ApiResponse<string>.ErrorResponse("An unexpected error occurred while fetching master menu list."));
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("get/menu-mobile")]
|
||||
public async Task<IActionResult> GetAppSideBarMenuForobile()
|
||||
{
|
||||
// Step 1: Get logged-in employee
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var employeeId = loggedInEmployee.Id;
|
||||
|
||||
using var scope = _serviceScopeFactory.CreateScope();
|
||||
var _permissions = scope.ServiceProvider.GetRequiredService<PermissionServices>();
|
||||
|
||||
try
|
||||
{
|
||||
// Step 2: Fetch all menu sections for the tenant
|
||||
var menus = await _sideBarMenuHelper.GetAllMenuSectionsAsync(tenantId);
|
||||
List<MenuSectionApplicationVM> response = new List<MenuSectionApplicationVM>();
|
||||
|
||||
foreach (var menu in menus)
|
||||
{
|
||||
var allowedItems = new List<MenuItem>();
|
||||
|
||||
foreach (var item in menu.Items)
|
||||
{
|
||||
// --- Item permission check ---
|
||||
if (!item.PermissionIds.Any())
|
||||
{
|
||||
MenuSectionApplicationVM menuVM = new MenuSectionApplicationVM
|
||||
{
|
||||
Id = item.Id,
|
||||
Name = item.Text,
|
||||
Available = true
|
||||
};
|
||||
response.Add(menuVM);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert permission string IDs to GUIDs
|
||||
var menuPermissionIds = item.PermissionIds
|
||||
.Select(Guid.Parse)
|
||||
.ToList();
|
||||
|
||||
bool isAllowed = await _permissions.HasPermissionAny(menuPermissionIds, employeeId);
|
||||
|
||||
// If allowed, filter its submenus as well
|
||||
if (isAllowed)
|
||||
{
|
||||
if (item.Submenu?.Any() == true)
|
||||
{
|
||||
var allowedSubmenus = new List<SubMenuItem>();
|
||||
|
||||
foreach (var subItem in item.Submenu)
|
||||
{
|
||||
if (!subItem.PermissionIds.Any())
|
||||
{
|
||||
MenuSectionApplicationVM subMenuVM = new MenuSectionApplicationVM
|
||||
{
|
||||
Id = subItem.Id,
|
||||
Name = subItem.Text,
|
||||
Available = true
|
||||
};
|
||||
response.Add(subMenuVM);
|
||||
continue;
|
||||
}
|
||||
|
||||
var subMenuPermissionIds = subItem.PermissionIds
|
||||
.Select(Guid.Parse)
|
||||
.ToList();
|
||||
|
||||
bool isSubItemAllowed = await _permissions.HasPermissionAny(subMenuPermissionIds, employeeId);
|
||||
|
||||
if (isSubItemAllowed)
|
||||
{
|
||||
MenuSectionApplicationVM subMenuVM = new MenuSectionApplicationVM
|
||||
{
|
||||
Id = subItem.Id,
|
||||
Name = subItem.Text,
|
||||
Available = true
|
||||
};
|
||||
response.Add(subMenuVM);
|
||||
}
|
||||
}
|
||||
|
||||
// Replace with filtered submenus
|
||||
item.Submenu = allowedSubmenus;
|
||||
}
|
||||
|
||||
MenuSectionApplicationVM menuVM = new MenuSectionApplicationVM
|
||||
{
|
||||
Id = item.Id,
|
||||
Name = item.Text,
|
||||
Available = true
|
||||
};
|
||||
response.Add(menuVM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Replace with filtered items
|
||||
menu.Items = allowedItems;
|
||||
}
|
||||
|
||||
// Step 3: Log success
|
||||
_logger.LogInfo("Fetched sidebar menu successfully. Tenant: {TenantId}, EmployeeId: {EmployeeId}, SectionsReturned: {Count}",
|
||||
tenantId, employeeId, menus.Count);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, "Sidebar menu fetched successfully", 200));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 4: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error occurred while fetching sidebar menu. Tenant: {TenantId}, EmployeeId: {EmployeeId}",
|
||||
tenantId, employeeId);
|
||||
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Server Error", "An unexpected error occurred while fetching the sidebar menu.", 500));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -9,7 +9,6 @@ using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Employee;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Hubs;
|
||||
using Marco.Pms.Services.Service;
|
||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||
@ -37,7 +36,6 @@ namespace MarcoBMS.Services.Controllers
|
||||
private readonly IEmailSender _emailSender;
|
||||
private readonly EmployeeHelper _employeeHelper;
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly GeneralHelper _generalHelper;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly IHubContext<MarcoHub> _signalR;
|
||||
@ -49,14 +47,13 @@ namespace MarcoBMS.Services.Controllers
|
||||
|
||||
public EmployeeController(UserManager<ApplicationUser> userManager, IEmailSender emailSender,
|
||||
ApplicationDbContext context, EmployeeHelper employeeHelper, UserHelper userHelper, IConfiguration configuration, ILoggingService logger,
|
||||
IHubContext<MarcoHub> signalR, PermissionServices permission, IProjectServices projectServices, IMapper mapper, GeneralHelper generalHelper)
|
||||
IHubContext<MarcoHub> signalR, PermissionServices permission, IProjectServices projectServices, IMapper mapper)
|
||||
{
|
||||
_context = context;
|
||||
_userManager = userManager;
|
||||
_emailSender = emailSender;
|
||||
_employeeHelper = employeeHelper;
|
||||
_userHelper = userHelper;
|
||||
_generalHelper = generalHelper;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_signalR = signalR;
|
||||
@ -194,88 +191,24 @@ namespace MarcoBMS.Services.Controllers
|
||||
var response = await employeeQuery.Take(10).Select(e => _mapper.Map<BasicEmployeeVM>(e)).ToListAsync();
|
||||
return Ok(ApiResponse<object>.SuccessResponse(response, $"{response.Count} records of employees fetched successfully", 200));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a paginated list of employees assigned to a specified project (if provided),
|
||||
/// with optional search functionality.
|
||||
/// Ensures that the logged-in user has necessary permissions before accessing project employees.
|
||||
/// </summary>
|
||||
/// <param name="projectId">Optional project identifier to filter employees by project.</param>
|
||||
/// <param name="searchString">Optional search string to filter employees by name.</param>
|
||||
/// <param name="pageNumber">Page number for pagination (default = 1).</param>
|
||||
/// <returns>Paginated list of employees in BasicEmployeeVM format wrapped in ApiResponse.</returns>
|
||||
|
||||
[HttpGet("search")]
|
||||
public async Task<IActionResult> GetEmployeesByProjectBasic(Guid? projectId, [FromQuery] string? searchString,
|
||||
[FromQuery] int pageNumber = 1, [FromQuery] int pageSize = 10)
|
||||
[HttpGet]
|
||||
[Route("search/{name}/{projectid?}")]
|
||||
public async Task<IActionResult> SearchEmployee(string name, Guid? projectid)
|
||||
{
|
||||
// Log API entry with context
|
||||
_logger.LogInfo("Fetching employees. ProjectId: {ProjectId}, SearchString: {SearchString}, PageNumber: {PageNumber}",
|
||||
projectId ?? Guid.Empty, searchString ?? "", pageNumber);
|
||||
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
_logger.LogDebug("Logged-in EmployeeId: {EmployeeId}", loggedInEmployee.Id);
|
||||
|
||||
// Initialize query scoped by tenant
|
||||
var employeeQuery = _context.Employees.Where(e => e.TenantId == tenantId);
|
||||
|
||||
// Filter by project if projectId is supplied
|
||||
if (projectId.HasValue && projectId.Value != Guid.Empty)
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
_logger.LogDebug("Project filter applied. Checking permission for EmployeeId: {EmployeeId} on ProjectId: {ProjectId}",
|
||||
loggedInEmployee.Id, projectId);
|
||||
var errors = ModelState.Values
|
||||
.SelectMany(v => v.Errors)
|
||||
.Select(e => e.ErrorMessage)
|
||||
.ToList();
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
|
||||
|
||||
// Validate project access permission
|
||||
var hasProjectPermission = await _permission.HasProjectPermission(loggedInEmployee, projectId.Value);
|
||||
if (!hasProjectPermission)
|
||||
{
|
||||
_logger.LogWarning("Access denied. EmployeeId: {EmployeeId} does not have permission for ProjectId: {ProjectId}",
|
||||
loggedInEmployee.Id, projectId);
|
||||
|
||||
return StatusCode(403, ApiResponse<object>.ErrorResponse(
|
||||
"Access denied",
|
||||
"User does not have access to view employees for this project",
|
||||
403));
|
||||
}
|
||||
|
||||
// Employees allocated to the project
|
||||
var employeeIds = await _context.ProjectAllocations
|
||||
.Where(pa => pa.ProjectId == projectId && pa.IsActive && pa.TenantId == tenantId)
|
||||
.Select(pa => pa.EmployeeId)
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogDebug("Project employees retrieved. Total linked employees found: {Count}", employeeIds.Count);
|
||||
|
||||
// Apply project allocation filter
|
||||
employeeQuery = employeeQuery.Where(e => employeeIds.Contains(e.Id));
|
||||
}
|
||||
var result = await _employeeHelper.SearchEmployeeByProjectId(GetTenantId(), name.ToLower(), projectid);
|
||||
|
||||
// Apply search filter if provided
|
||||
if (!string.IsNullOrWhiteSpace(searchString))
|
||||
{
|
||||
var searchStringLower = searchString.ToLower();
|
||||
_logger.LogDebug("Search filter applied. Search term: {SearchTerm}", searchStringLower);
|
||||
|
||||
employeeQuery = employeeQuery.Where(e =>
|
||||
(e.FirstName + " " + e.LastName).ToLower().Contains(searchStringLower));
|
||||
}
|
||||
|
||||
// Pagination and Projection (executed in DB)
|
||||
var employees = await employeeQuery
|
||||
.Skip((pageNumber - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(e => _mapper.Map<BasicEmployeeVM>(e))
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInfo("Employees fetched successfully. Records returned: {Count}", employees.Count);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(
|
||||
employees,
|
||||
$"{employees.Count} employee records fetched successfully",
|
||||
200));
|
||||
return Ok(ApiResponse<object>.SuccessResponse(result, "Filter applied.", 200));
|
||||
}
|
||||
|
||||
|
||||
[HttpGet]
|
||||
[Route("profile/get/{employeeId}")]
|
||||
public async Task<IActionResult> GetEmployeeProfileById(Guid employeeId)
|
||||
@ -300,6 +233,11 @@ namespace MarcoBMS.Services.Controllers
|
||||
return _userHelper.GetTenantId();
|
||||
}
|
||||
|
||||
//[HttpPost("manage/quick")]
|
||||
//public async Task<IActionResult> CreateQuickUser([FromBody] CreateQuickUserDto model)
|
||||
//{
|
||||
// return Ok("Pending implementation");
|
||||
//}
|
||||
|
||||
[HttpPost("manage")]
|
||||
public async Task<IActionResult> CreateUser([FromBody] CreateUserDto model)
|
||||
@ -356,12 +294,7 @@ namespace MarcoBMS.Services.Controllers
|
||||
TenantId = tenantId
|
||||
|
||||
};
|
||||
var isSeatsAvaiable = await _generalHelper.CheckSeatsRemainingAsync(tenantId);
|
||||
if (!isSeatsAvaiable)
|
||||
{
|
||||
_logger.LogWarning("Maximum number of users reached for Tenant {TenantId}", tenantId);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Maximum number of users reached. Cannot add new user", "Maximum number of users reached. Cannot add new user", 400));
|
||||
}
|
||||
|
||||
// Create Identity User
|
||||
var result = await _userManager.CreateAsync(user, "User@123");
|
||||
if (!result.Succeeded)
|
||||
@ -514,104 +447,86 @@ namespace MarcoBMS.Services.Controllers
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> SuspendEmployee(Guid id, [FromQuery] bool active = false)
|
||||
public async Task<IActionResult> SuspendEmployee(Guid id)
|
||||
{
|
||||
Guid tenantId = _userHelper.GetTenantId();
|
||||
var LoggedEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.TenantId == tenantId);
|
||||
if (employee == null)
|
||||
Employee? employee = await _context.Employees.FirstOrDefaultAsync(e => e.Id == id && e.IsActive && e.TenantId == tenantId);
|
||||
if (employee != null)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
|
||||
return NotFound(ApiResponse<object>.ErrorResponse("Employee Not found successfully", "Employee Not found successfully", 404));
|
||||
}
|
||||
if (employee.IsSystem)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to suspend system-defined employee with ID {EmployeeId}", LoggedEmployee.Id, employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("System-defined employees cannot be suspended.", "System-defined employees cannot be suspended.", 400));
|
||||
}
|
||||
var assignedToTasks = await _context.TaskMembers.Where(t => t.EmployeeId == employee.Id).ToListAsync();
|
||||
if (assignedToTasks.Count != 0)
|
||||
{
|
||||
List<Guid> taskIds = assignedToTasks.Select(t => t.TaskAllocationId).ToList();
|
||||
var tasks = await _context.TaskAllocations.Where(t => taskIds.Contains(t.Id)).ToListAsync();
|
||||
|
||||
foreach (var assignedToTask in assignedToTasks)
|
||||
if (employee.IsSystem)
|
||||
{
|
||||
var task = tasks.Find(t => t.Id == assignedToTask.TaskAllocationId);
|
||||
if (task != null && task.CompletedTask == 0)
|
||||
_logger.LogWarning("Employee with ID {LoggedEmployeeId} tries to suspend system-defined employee with ID {EmployeeId}", LoggedEmployee.Id, employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("System-defined employees cannot be suspended.", "System-defined employees cannot be suspended.", 400));
|
||||
}
|
||||
else
|
||||
{
|
||||
var assignedToTasks = await _context.TaskMembers.Where(t => t.EmployeeId == employee.Id).ToListAsync();
|
||||
if (assignedToTasks.Count != 0)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {EmployeeId} is currently assigned to any incomplete task", employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee is currently assigned to any incomplete task", "Employee is currently assigned to any incomplete task", 400));
|
||||
}
|
||||
}
|
||||
}
|
||||
var attendance = await _context.Attendes.Where(a => a.EmployeeID == employee.Id && (a.OutTime == null || a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE)).ToListAsync();
|
||||
if (attendance.Count != 0)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {EmployeeId} have any pending check-out or regularization requests", employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee have any pending check-out or regularization requests", "Employee have any pending check-out or regularization requests", 400));
|
||||
}
|
||||
if (active)
|
||||
{
|
||||
employee.IsActive = true;
|
||||
var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId);
|
||||
if (user != null)
|
||||
{
|
||||
user.IsActive = true;
|
||||
_logger.LogInfo("The application user associated with employee ID {EmployeeId} has been actived.", employee.Id);
|
||||
List<Guid> taskIds = assignedToTasks.Select(t => t.TaskAllocationId).ToList();
|
||||
var tasks = await _context.TaskAllocations.Where(t => taskIds.Contains(t.Id)).ToListAsync();
|
||||
|
||||
foreach (var assignedToTask in assignedToTasks)
|
||||
{
|
||||
var task = tasks.Find(t => t.Id == assignedToTask.TaskAllocationId);
|
||||
if (task != null && task.CompletedTask == 0)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {EmployeeId} is currently assigned to any incomplete task", employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee is currently assigned to any incomplete task", "Employee is currently assigned to any incomplete task", 400));
|
||||
}
|
||||
}
|
||||
}
|
||||
var attendance = await _context.Attendes.Where(a => a.EmployeeID == employee.Id && (a.OutTime == null || a.Activity == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE)).ToListAsync();
|
||||
if (attendance.Count != 0)
|
||||
{
|
||||
_logger.LogWarning("Employee with ID {EmployeeId} have any pending check-out or regularization requests", employee.Id);
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Employee have any pending check-out or regularization requests", "Employee have any pending check-out or regularization requests", 400));
|
||||
}
|
||||
employee.IsActive = false;
|
||||
var projectAllocations = await _context.ProjectAllocations.Where(a => a.EmployeeId == employee.Id).ToListAsync();
|
||||
if (projectAllocations.Count != 0)
|
||||
{
|
||||
List<ProjectAllocation> allocations = new List<ProjectAllocation>();
|
||||
foreach (var projectAllocation in projectAllocations)
|
||||
{
|
||||
projectAllocation.ReAllocationDate = DateTime.UtcNow;
|
||||
projectAllocation.IsActive = false;
|
||||
allocations.Add(projectAllocation);
|
||||
}
|
||||
_logger.LogInfo("Employee with ID {EmployeeId} has been removed from all assigned projects.", employee.Id);
|
||||
}
|
||||
var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId);
|
||||
if (user != null)
|
||||
{
|
||||
user.IsActive = false;
|
||||
_logger.LogInfo("The application user associated with employee ID {EmployeeId} has been suspended.", employee.Id);
|
||||
|
||||
var refreshTokens = await _context.RefreshTokens.AsNoTracking().Where(t => t.UserId == user.Id).ToListAsync();
|
||||
if (refreshTokens.Count != 0)
|
||||
{
|
||||
_context.RefreshTokens.RemoveRange(refreshTokens);
|
||||
_logger.LogInfo("Refresh tokens associated with employee ID {EmployeeId} has been removed.", employee.Id);
|
||||
}
|
||||
|
||||
}
|
||||
var roleMapping = await _context.EmployeeRoleMappings.AsNoTracking().Where(r => r.EmployeeId == employee.Id).ToListAsync();
|
||||
if (roleMapping.Count != 0)
|
||||
{
|
||||
_context.EmployeeRoleMappings.RemoveRange(roleMapping);
|
||||
_logger.LogInfo("Application role mapping associated with employee ID {EmployeeId} has been removed.", employee.Id);
|
||||
}
|
||||
await _context.SaveChangesAsync();
|
||||
_logger.LogInfo("Employee with ID {EmployeId} Deleted successfully", employee.Id);
|
||||
var notification = new { LoggedInUserId = LoggedEmployee.Id, Keyword = "Employee", EmployeeId = employee.Id };
|
||||
|
||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
||||
}
|
||||
_logger.LogInfo("Employee with ID {EmployeId} Actived successfully", employee.Id);
|
||||
}
|
||||
else
|
||||
{
|
||||
employee.IsActive = false;
|
||||
var projectAllocations = await _context.ProjectAllocations.Where(a => a.EmployeeId == employee.Id).ToListAsync();
|
||||
if (projectAllocations.Count != 0)
|
||||
{
|
||||
List<ProjectAllocation> allocations = new List<ProjectAllocation>();
|
||||
foreach (var projectAllocation in projectAllocations)
|
||||
{
|
||||
projectAllocation.ReAllocationDate = DateTime.UtcNow;
|
||||
projectAllocation.IsActive = false;
|
||||
allocations.Add(projectAllocation);
|
||||
}
|
||||
_logger.LogInfo("Employee with ID {EmployeeId} has been removed from all assigned projects.", employee.Id);
|
||||
}
|
||||
var user = await _context.ApplicationUsers.FirstOrDefaultAsync(u => u.Id == employee.ApplicationUserId);
|
||||
if (user != null)
|
||||
{
|
||||
user.IsActive = false;
|
||||
_logger.LogInfo("The application user associated with employee ID {EmployeeId} has been suspended.", employee.Id);
|
||||
|
||||
var refreshTokens = await _context.RefreshTokens.AsNoTracking().Where(t => t.UserId == user.Id).ToListAsync();
|
||||
if (refreshTokens.Count != 0)
|
||||
{
|
||||
_context.RefreshTokens.RemoveRange(refreshTokens);
|
||||
_logger.LogInfo("Refresh tokens associated with employee ID {EmployeeId} has been removed.", employee.Id);
|
||||
}
|
||||
|
||||
}
|
||||
var roleMapping = await _context.EmployeeRoleMappings.AsNoTracking().Where(r => r.EmployeeId == employee.Id).ToListAsync();
|
||||
if (roleMapping.Count != 0)
|
||||
{
|
||||
_context.EmployeeRoleMappings.RemoveRange(roleMapping);
|
||||
_logger.LogInfo("Application role mapping associated with employee ID {EmployeeId} has been removed.", employee.Id);
|
||||
}
|
||||
_logger.LogInfo("Employee with ID {EmployeId} Deleted successfully", employee.Id);
|
||||
_logger.LogWarning("Employee with ID {EmploueeId} not found in database", id);
|
||||
}
|
||||
try
|
||||
{
|
||||
await _context.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException ex)
|
||||
{
|
||||
_logger.LogError(ex, "Exception Occured While activting/deactivting employee {EmployeeId}", employee.Id);
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("Internal Error Occured", "Error occured while saving the entity", 500));
|
||||
}
|
||||
var notification = new { LoggedInUserId = LoggedEmployee.Id, Keyword = "Employee", EmployeeId = employee.Id };
|
||||
|
||||
await _signalR.Clients.All.SendAsync("NotificationEventHandler", notification);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(new { }, "Employee Suspended successfully", 200));
|
||||
}
|
||||
private static Employee GetNewEmployeeModel(CreateUserDto model, Guid TenantId, string ApplicationUserId)
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
using AutoMapper;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.Mapper;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
|
||||
@ -17,102 +15,43 @@ namespace MarcoBMS.Services.Controllers
|
||||
public class FeatureController : ControllerBase
|
||||
{
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly GeneralHelper _generalHelper;
|
||||
//private readonly UserHelper _userHelper;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly Guid tenantId;
|
||||
|
||||
public FeatureController(ApplicationDbContext context, GeneralHelper generalHelper, UserHelper userHelper, IMapper mapper, ILoggingService logger)
|
||||
|
||||
public FeatureController(ApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
_generalHelper = generalHelper;
|
||||
//_userHelper = userHelper;
|
||||
_mapper = mapper;
|
||||
_logger = logger;
|
||||
tenantId = userHelper.GetTenantId();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts FeaturePermissions from Feature entity into FeaturePermissionVM collection.
|
||||
/// </summary>
|
||||
/// <param name="model">Feature entity from DB</param>
|
||||
/// <returns>Collection of FeaturePermissionVM, ordered by Name</returns>
|
||||
private ICollection<FeaturePermissionVM> GetFeaturePermissionVMs(Feature model)
|
||||
{
|
||||
if (model.FeaturePermissions == null || !model.FeaturePermissions.Any())
|
||||
ICollection<FeaturePermissionVM> features = [];
|
||||
if (model.FeaturePermissions != null)
|
||||
{
|
||||
_logger.LogInfo("No feature permissions found for Feature: {FeatureId}", model.Id);
|
||||
return new List<FeaturePermissionVM>();
|
||||
foreach (FeaturePermission permission in model.FeaturePermissions)
|
||||
{
|
||||
FeaturePermissionVM item = permission.ToFeaturePermissionVMFromFeaturePermission();
|
||||
features.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
// Project and order feature permissions
|
||||
var features = model.FeaturePermissions
|
||||
.Select(p => _mapper.Map<FeaturePermissionVM>(p))
|
||||
.OrderBy(f => f.Name)
|
||||
.ToList();
|
||||
|
||||
_logger.LogDebug("Mapped {Count} feature permissions for Feature: {FeatureId}", features.Count, model.Id);
|
||||
return features;
|
||||
return features.OrderBy(f => f.Name).ToList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// API endpoint to fetch all features and their permissions for the given tenant.
|
||||
/// </summary>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetAllFeaturesAsync()
|
||||
public async Task<IActionResult> GetAllFeatures()
|
||||
{
|
||||
try
|
||||
var roles = await _context.Features.Include("FeaturePermissions").Include("Module").ToListAsync();
|
||||
|
||||
var rolesVM = roles.Select(c => new FeatureVM()
|
||||
{
|
||||
_logger.LogInfo("Fetching all features for tenant: {TenantId}", tenantId);
|
||||
|
||||
var featureQuery = _context.Features
|
||||
.AsNoTracking(); // Optimization: Read-only query
|
||||
if (tenantId != Guid.Parse("b3466e83-7e11-464c-b93a-daf047838b26"))
|
||||
{
|
||||
|
||||
// Step 1: Get tenant-specific FeatureIds
|
||||
List<Guid> featureIds = await _generalHelper.GetFeatureIdsByTenentIdAsync(tenantId);
|
||||
if (featureIds == null || !featureIds.Any())
|
||||
{
|
||||
_logger.LogWarning("No features found for tenant: {TenantId}", tenantId);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(new List<FeatureVM>(), "No features found.", 200));
|
||||
}
|
||||
_logger.LogDebug("Retrieved {Count} feature IDs for tenant: {TenantId}", featureIds.Count, tenantId);
|
||||
|
||||
// Step 2: Query Features with related FeaturePermissions & Module
|
||||
featureQuery = featureQuery.Where(f => featureIds.Contains(f.Id));
|
||||
}
|
||||
|
||||
var features = await featureQuery
|
||||
.Include(f => f.FeaturePermissions)
|
||||
.Include(f => f.Module).ToListAsync();
|
||||
_logger.LogDebug("Fetched {Count} features from DB for tenant: {TenantId}", features.Count, tenantId);
|
||||
|
||||
// Step 3: Map features to ViewModels
|
||||
var featureVMs = features
|
||||
.Select(c => new FeatureVM
|
||||
{
|
||||
Id = c.Id,
|
||||
Name = c.Name,
|
||||
Description = c.Description,
|
||||
FeaturePermissions = GetFeaturePermissionVMs(c),
|
||||
ModuleId = c.ModuleId,
|
||||
ModuleName = c.Module?.Name ?? string.Empty,
|
||||
IsActive = c.IsActive
|
||||
})
|
||||
.OrderBy(f => f.Name)
|
||||
.ToList();
|
||||
|
||||
_logger.LogInfo("Returning {Count} features for tenant: {TenantId}", featureVMs.Count, tenantId);
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(featureVMs, "Success.", 200));
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while fetching features for tenant: {TenantId}", tenantId);
|
||||
return StatusCode(500, ApiResponse<object>.ErrorResponse("An unexpected error occurred.", 500));
|
||||
}
|
||||
Id = c.Id,
|
||||
Name = c.Name,
|
||||
Description = c.Description,
|
||||
FeaturePermissions = GetFeaturePermissionVMs(c),
|
||||
ModuleId = c.ModuleId,
|
||||
ModuleName = c.Module != null ? c.Module.Name : string.Empty,
|
||||
IsActive = c.IsActive
|
||||
}).OrderBy(f => f.Name).ToList();
|
||||
return Ok(ApiResponse<object>.SuccessResponse(rolesVM, "Success.", 200));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,7 +37,7 @@ namespace Marco.Pms.Services.Controllers
|
||||
return Ok(ApiResponse<object>.SuccessResponse(industries, "Success.", 200));
|
||||
}
|
||||
|
||||
[HttpPost("enquire")]
|
||||
[HttpPost("inquiry")]
|
||||
public async Task<IActionResult> RequestDemo([FromBody] InquiryDto inquiryDto)
|
||||
{
|
||||
Inquiries inquiry = inquiryDto.ToInquiriesFromInquiriesDto();
|
||||
|
||||
@ -276,23 +276,6 @@ namespace MarcoBMS.Services.Controllers
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpGet("allocation-histery/{employeeId}")]
|
||||
public async Task<IActionResult> GetProjectByEmployeeBasic([FromRoute] Guid employeeId)
|
||||
{
|
||||
// --- Step 1: Input Validation ---
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||
_logger.LogWarning("Get project list by employee Id called with invalid model state \n Errors: {Errors}", string.Join(", ", errors));
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request data provided.", errors, 400));
|
||||
}
|
||||
|
||||
// --- Step 2: Prepare data without I/O ---
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetProjectByEmployeeBasicAsync(employeeId, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
[HttpPost("assign-projects/{employeeId}")]
|
||||
public async Task<IActionResult> AssigneProjectsToEmployee([FromBody] List<ProjectsAllocationDto> projectAllocationDtos, [FromRoute] Guid employeeId)
|
||||
{
|
||||
@ -355,25 +338,6 @@ namespace MarcoBMS.Services.Controllers
|
||||
var response = await _projectServices.GetWorkItemsAsync(workAreaId, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
[HttpGet("tasks-employee/{employeeId}")]
|
||||
public async Task<IActionResult> GetTasksByEmployee(Guid employeeId, [FromQuery] DateTime? fromDate, DateTime? toDate)
|
||||
{
|
||||
// --- Step 1: Input Validation ---
|
||||
if (!ModelState.IsValid)
|
||||
{
|
||||
var errors = ModelState.Values.SelectMany(v => v.Errors).Select(e => e.ErrorMessage).ToList();
|
||||
_logger.LogWarning("Get Work Items by employeeId called with invalid model state \n Errors: {Errors}", string.Join(", ", errors));
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid request data provided.", errors, 400));
|
||||
}
|
||||
|
||||
if (!toDate.HasValue) toDate = DateTime.UtcNow;
|
||||
if (!fromDate.HasValue) fromDate = toDate.Value.AddDays(-7);
|
||||
|
||||
// --- Step 2: Prepare data without I/O ---
|
||||
Employee loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
var response = await _projectServices.GetTasksByEmployeeAsync(employeeId, fromDate.Value, toDate.Value, tenantId, loggedInEmployee);
|
||||
return StatusCode(response.StatusCode, response);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using System.Data;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Dtos.Employees;
|
||||
using Marco.Pms.Model.Dtos.Roles;
|
||||
using Marco.Pms.Model.Employees;
|
||||
@ -10,13 +11,12 @@ using Marco.Pms.Model.ViewModels;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Model.ViewModels.Roles;
|
||||
using Marco.Pms.Services.Helpers;
|
||||
using Marco.Pms.Services.Service;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Data;
|
||||
#nullable disable
|
||||
namespace MarcoBMS.Services.Controllers
|
||||
{
|
||||
@ -28,15 +28,15 @@ namespace MarcoBMS.Services.Controllers
|
||||
private readonly ApplicationDbContext _context;
|
||||
private readonly RolesHelper _rolesHelper;
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly PermissionServices _permissionService;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly CacheUpdateHelper _cache;
|
||||
|
||||
public RolesController(PermissionServices permissionServices, ApplicationDbContext context, RolesHelper rolesHelper, UserHelper userHelper, ILoggingService logger,
|
||||
public RolesController(UserManager<ApplicationUser> userManager, ApplicationDbContext context, RolesHelper rolesHelper, UserHelper userHelper, ILoggingService logger,
|
||||
CacheUpdateHelper cache)
|
||||
{
|
||||
_context = context;
|
||||
_permissionService = permissionServices;
|
||||
_userManager = userManager;
|
||||
_rolesHelper = rolesHelper;
|
||||
_userHelper = userHelper;
|
||||
_logger = logger;
|
||||
@ -213,17 +213,12 @@ namespace MarcoBMS.Services.Controllers
|
||||
}
|
||||
|
||||
Guid TenantId = GetTenantId();
|
||||
var loggedInEmployee = await _userHelper.GetCurrentEmployeeAsync();
|
||||
|
||||
if (createRoleDto.FeaturesPermission == null || (createRoleDto.FeaturesPermission != null && createRoleDto.FeaturesPermission.Count == 0))
|
||||
{
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Feature Permission is required.", "Feature Permission is required.", 400));
|
||||
}
|
||||
var hasManageMasterPermission = await _permissionService.HasPermission(PermissionsMaster.ManageMasters, loggedInEmployee.Id);
|
||||
if (!hasManageMasterPermission)
|
||||
{
|
||||
return StatusCode(403, ApiResponse<object>.SuccessResponse("Access Denied", "User do not have permission for this action", 403));
|
||||
}
|
||||
|
||||
bool roleExists = _context.ApplicationRoles
|
||||
.Any(r => r.TenantId == TenantId && r.Role.ToLower() == createRoleDto.Role.ToLower());// assuming role name is unique per tenant
|
||||
if (roleExists)
|
||||
@ -233,19 +228,14 @@ namespace MarcoBMS.Services.Controllers
|
||||
ApplicationRole role = createRoleDto.ToApplicationRoleFromCreateDto(TenantId);
|
||||
_context.ApplicationRoles.Add(role);
|
||||
|
||||
var hasPermission = await _permissionService.HasPermission(PermissionsMaster.ManageTenants, loggedInEmployee.Id);
|
||||
foreach (var permission in createRoleDto.FeaturesPermission)
|
||||
{
|
||||
if (!hasPermission &&
|
||||
permission.Id != PermissionsMaster.ManageTenants)
|
||||
{
|
||||
var item = new RolePermissionMappings() { ApplicationRoleId = role.Id, FeaturePermissionId = permission.Id };
|
||||
bool assigned = _context.RolePermissionMappings.Any(c => c.ApplicationRoleId == role.Id && c.FeaturePermissionId == permission.Id);
|
||||
if (permission.IsEnabled && !assigned)
|
||||
_context.RolePermissionMappings.Add(item);
|
||||
else
|
||||
_context.RolePermissionMappings.Remove(item);
|
||||
}
|
||||
var item = new RolePermissionMappings() { ApplicationRoleId = role.Id, FeaturePermissionId = permission.Id };
|
||||
bool assigned = _context.RolePermissionMappings.Any(c => c.ApplicationRoleId == role.Id && c.FeaturePermissionId == permission.Id);
|
||||
if (permission.IsEnabled && !assigned)
|
||||
_context.RolePermissionMappings.Add(item);
|
||||
else
|
||||
_context.RolePermissionMappings.Remove(item);
|
||||
}
|
||||
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -6,11 +6,8 @@ using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Employee;
|
||||
using Marco.Pms.Services.Service.ServiceInterfaces;
|
||||
using MarcoBMS.Services.Helpers;
|
||||
using MarcoBMS.Services.Service;
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using System.Net.Mail;
|
||||
|
||||
namespace MarcoBMS.Services.Controllers
|
||||
{
|
||||
@ -21,17 +18,14 @@ namespace MarcoBMS.Services.Controllers
|
||||
public class UserController : ControllerBase
|
||||
{
|
||||
private readonly UserHelper _userHelper;
|
||||
private readonly UserManager<ApplicationUser> _userManager;
|
||||
private readonly EmployeeHelper _employeeHelper;
|
||||
private readonly ILoggingService _logger;
|
||||
|
||||
private readonly IProjectServices _projectServices;
|
||||
private readonly RolesHelper _rolesHelper;
|
||||
|
||||
public UserController(EmployeeHelper employeeHelper, UserManager<ApplicationUser> userManager, ILoggingService logger, IProjectServices projectServices, UserHelper userHelper, RolesHelper rolesHelper)
|
||||
public UserController(EmployeeHelper employeeHelper, IProjectServices projectServices, UserHelper userHelper, RolesHelper rolesHelper)
|
||||
{
|
||||
_userManager = userManager;
|
||||
_userHelper = userHelper;
|
||||
_logger = logger;
|
||||
_employeeHelper = employeeHelper;
|
||||
_projectServices = projectServices;
|
||||
_rolesHelper = rolesHelper;
|
||||
@ -87,44 +81,5 @@ namespace MarcoBMS.Services.Controllers
|
||||
|
||||
return Ok(ApiResponse<object>.SuccessResponse(profile, "Success", 200));
|
||||
}
|
||||
|
||||
[HttpGet("email/{email}")]
|
||||
public async Task<IActionResult> GetUserByEmail(string email)
|
||||
{
|
||||
var isvalid = IsValidEmail(email);
|
||||
if (!isvalid)
|
||||
{
|
||||
_logger.LogWarning("User provided invalid email address");
|
||||
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid email", "Invalid email", 400));
|
||||
}
|
||||
var user = await _userManager.FindByEmailAsync(email);
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
_logger.LogInfo("User with email {Email} not found in ASP.NET users table", email);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(true, "User not exists", 200));
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogInfo("User with email {Email} founded in ASP.NET users table", email);
|
||||
return Ok(ApiResponse<object>.SuccessResponse(false, "User exists", 200));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static bool IsValidEmail(string email)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(email))
|
||||
return false;
|
||||
try
|
||||
{
|
||||
var addr = new MailAddress(email);
|
||||
return addr.Address == email.Trim();
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -853,18 +853,6 @@ namespace Marco.Pms.Services.Helpers
|
||||
_logger.LogWarning("Error occured while deleting Application role {RoleId} from Cache for employee {EmployeeId}: {Error}", roleId, employeeId, ex.Message);
|
||||
}
|
||||
}
|
||||
public async Task ClearAllEmployeesFromCacheByEmployeeIds(List<Guid> employeeIds)
|
||||
{
|
||||
try
|
||||
{
|
||||
var stringEmployeeIds = employeeIds.Select(e => e.ToString()).ToList();
|
||||
var response = await _employeeCache.ClearAllEmployeesFromCacheByEmployeeIds(stringEmployeeIds);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error occured while deleting all employees from Cache");
|
||||
}
|
||||
}
|
||||
public async Task ClearAllEmployees()
|
||||
{
|
||||
try
|
||||
|
||||
@ -20,7 +20,7 @@ namespace MarcoBMS.Services.Helpers
|
||||
public async Task<Employee> GetEmployeeByID(Guid EmployeeID)
|
||||
{
|
||||
|
||||
return await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == EmployeeID) ?? new Employee { };
|
||||
return await _context.Employees.Include(e => e.JobRole).FirstOrDefaultAsync(e => e.Id == EmployeeID && e.IsActive == true) ?? new Employee { };
|
||||
}
|
||||
|
||||
public async Task<Employee> GetEmployeeByApplicationUserID(string ApplicationUserID)
|
||||
@ -29,7 +29,7 @@ namespace MarcoBMS.Services.Helpers
|
||||
{
|
||||
var result = await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID && c.IsActive == true).ToListAsync();
|
||||
|
||||
return await _context.Employees.Include(e => e.ApplicationUser).Where(c => c.ApplicationUserId == ApplicationUserID && c.ApplicationUser != null && c.IsActive == true).SingleOrDefaultAsync() ?? new Employee { };
|
||||
return await _context.Employees.Where(c => c.ApplicationUserId == ApplicationUserID && c.IsActive == true).SingleOrDefaultAsync() ?? new Employee { };
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Helpers.Utility;
|
||||
using Marco.Pms.Model.MongoDBModels.Masters;
|
||||
using Marco.Pms.Model.MongoDBModels.Project;
|
||||
using MarcoBMS.Services.Service;
|
||||
@ -12,16 +11,13 @@ namespace Marco.Pms.Services.Helpers
|
||||
private readonly IDbContextFactory<ApplicationDbContext> _dbContextFactory;
|
||||
private readonly ApplicationDbContext _context; // Keeping this for direct scoped context use where appropriate
|
||||
private readonly ILoggingService _logger;
|
||||
private readonly FeatureDetailsHelper _featureDetailsHelper;
|
||||
public GeneralHelper(IDbContextFactory<ApplicationDbContext> dbContextFactory,
|
||||
ApplicationDbContext context,
|
||||
ILoggingService logger,
|
||||
FeatureDetailsHelper featureDetailsHelper)
|
||||
ILoggingService logger)
|
||||
{
|
||||
_dbContextFactory = dbContextFactory ?? throw new ArgumentNullException(nameof(dbContextFactory));
|
||||
_context = context ?? throw new ArgumentNullException(nameof(context));
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_featureDetailsHelper = featureDetailsHelper ?? throw new ArgumentNullException(nameof(featureDetailsHelper));
|
||||
}
|
||||
public async Task<List<BuildingMongoDB>> GetProjectInfraFromDB(Guid projectId)
|
||||
{
|
||||
@ -215,161 +211,5 @@ namespace Marco.Pms.Services.Helpers
|
||||
return new List<WorkItemMongoDB>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all enabled feature IDs for a given tenant based on their active subscription.
|
||||
/// </summary>
|
||||
/// <param name="tenantId">The unique identifier of the tenant.</param>
|
||||
/// <returns>A list of feature IDs available for the tenant.</returns>
|
||||
public async Task<List<Guid>> GetFeatureIdsByTenentIdAsync(Guid tenantId)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInfo("Fetching feature IDs for tenant: {TenantId}", tenantId);
|
||||
|
||||
// Step 1: Get active tenant subscription with plan
|
||||
var tenantSubscription = await _context.TenantSubscriptions
|
||||
.Include(ts => ts.Plan)
|
||||
.AsNoTracking() // Optimization: Read-only query, no need to track
|
||||
.FirstOrDefaultAsync(ts =>
|
||||
ts.TenantId == tenantId &&
|
||||
ts.Plan != null &&
|
||||
!ts.IsCancelled &&
|
||||
ts.EndDate.Date >= DateTime.UtcNow.Date); // FIX: Subscription should not be expired
|
||||
|
||||
if (tenantSubscription == null)
|
||||
{
|
||||
_logger.LogWarning("No active subscription found for tenant: {TenantId}", tenantId);
|
||||
return new List<Guid>();
|
||||
}
|
||||
|
||||
_logger.LogDebug("Active subscription found for tenant: {TenantId}, PlanId: {PlanId}",
|
||||
tenantId, tenantSubscription.Plan!.Id);
|
||||
|
||||
var featureIds = new List<Guid> { new Guid("2f3509b7-160d-410a-b9b6-daadd96c986d"), new Guid("be3b3afc-6ccf-4566-b9b6-aafcb65546be") };
|
||||
|
||||
// Step 2: Get feature details from Plan
|
||||
var featureDetails = await _featureDetailsHelper.GetFeatureDetails(tenantSubscription.Plan!.FeaturesId);
|
||||
|
||||
if (featureDetails == null)
|
||||
{
|
||||
_logger.LogWarning("No feature details found for tenant: {TenantId}, PlanId: {PlanId}",
|
||||
tenantId, tenantSubscription.Plan!.Id);
|
||||
return new List<Guid>();
|
||||
}
|
||||
|
||||
// Step 3: Collect all enabled feature IDs from modules
|
||||
|
||||
if (featureDetails.Modules?.Attendance?.Enabled == true)
|
||||
{
|
||||
featureIds.AddRange(featureDetails.Modules.Attendance.FeatureId);
|
||||
_logger.LogDebug("Added Attendance module features for tenant: {TenantId}", tenantId);
|
||||
}
|
||||
|
||||
if (featureDetails.Modules?.ProjectManagement?.Enabled == true)
|
||||
{
|
||||
featureIds.AddRange(featureDetails.Modules.ProjectManagement.FeatureId);
|
||||
_logger.LogDebug("Added Project Management module features for tenant: {TenantId}", tenantId);
|
||||
}
|
||||
|
||||
if (featureDetails.Modules?.Directory?.Enabled == true)
|
||||
{
|
||||
featureIds.AddRange(featureDetails.Modules.Directory.FeatureId);
|
||||
_logger.LogDebug("Added Directory module features for tenant: {TenantId}", tenantId);
|
||||
}
|
||||
|
||||
if (featureDetails.Modules?.Expense?.Enabled == true)
|
||||
{
|
||||
featureIds.AddRange(featureDetails.Modules.Expense.FeatureId);
|
||||
_logger.LogDebug("Added Expense module features for tenant: {TenantId}", tenantId);
|
||||
}
|
||||
|
||||
_logger.LogInfo("Returning {Count} feature IDs for tenant: {TenantId}", featureIds.Count, tenantId);
|
||||
|
||||
return featureIds.Distinct().ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Step 4: Handle unexpected errors
|
||||
_logger.LogError(ex, "Error retrieving feature IDs for tenant: {TenantId}", tenantId);
|
||||
return new List<Guid>();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the tenant still has available seats (MaxUsers not exceeded).
|
||||
/// </summary>
|
||||
/// <param name="tenantId">The ID of the tenant to check.</param>
|
||||
/// <returns>True if seats are available; otherwise false.</returns>
|
||||
public async Task<bool> CheckSeatsRemainingAsync(Guid tenantId)
|
||||
{
|
||||
_logger.LogInfo("Checking seats remaining for TenantId: {TenantId}", tenantId);
|
||||
|
||||
try
|
||||
{
|
||||
// Run both queries concurrently
|
||||
var totalSeatsTask = GetMaxSeatsAsync(tenantId);
|
||||
var totalSeatsTakenTask = GetActiveEmployeesCountAsync(tenantId);
|
||||
|
||||
await Task.WhenAll(totalSeatsTask, totalSeatsTakenTask);
|
||||
|
||||
var totalSeats = await totalSeatsTask;
|
||||
var totalSeatsTaken = await totalSeatsTakenTask;
|
||||
|
||||
_logger.LogInfo(
|
||||
"TenantId: {TenantId} | TotalSeats: {TotalSeats} | SeatsTaken: {SeatsTaken}",
|
||||
tenantId, totalSeats, totalSeatsTaken);
|
||||
|
||||
bool seatsAvailable = totalSeats >= totalSeatsTaken;
|
||||
|
||||
_logger.LogDebug("TenantId: {TenantId} | Seats Available: {SeatsAvailable}",
|
||||
tenantId, seatsAvailable);
|
||||
|
||||
return seatsAvailable;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error checking seats for TenantId: {TenantId}", tenantId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the maximum number of allowed seats (MaxUsers) for a tenant.
|
||||
/// </summary>
|
||||
private async Task<double> GetMaxSeatsAsync(Guid tenantId)
|
||||
{
|
||||
_logger.LogDebug("Fetching maximum seats for TenantId: {TenantId}", tenantId);
|
||||
|
||||
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var maxSeats = await dbContext.TenantSubscriptions
|
||||
.Where(ts => ts.TenantId == tenantId && !ts.IsCancelled)
|
||||
.Select(ts => ts.MaxUsers)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
_logger.LogDebug("TenantId: {TenantId} | MaxSeats: {MaxSeats}", tenantId, maxSeats);
|
||||
|
||||
return maxSeats;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Counts the number of active employees for a tenant.
|
||||
/// </summary>
|
||||
private async Task<int> GetActiveEmployeesCountAsync(Guid tenantId)
|
||||
{
|
||||
_logger.LogDebug("Counting active employees for TenantId: {TenantId}", tenantId);
|
||||
|
||||
await using var dbContext = await _dbContextFactory.CreateDbContextAsync();
|
||||
|
||||
var activeEmployees = await dbContext.Employees
|
||||
.Where(e => e.TenantId == tenantId && e.IsActive)
|
||||
.CountAsync();
|
||||
|
||||
_logger.LogDebug("TenantId: {TenantId} | ActiveEmployees: {ActiveEmployees}", tenantId, activeEmployees);
|
||||
|
||||
return activeEmployees;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,13 +70,12 @@ namespace MarcoBMS.Services.Helpers
|
||||
|
||||
// --- Step 3: Execute the main query on the main thread using its original context ---
|
||||
// This is now safe because the background task is using a different DbContext instance.
|
||||
var roleIds = await employeeRoleIdsQuery.ToListAsync();
|
||||
|
||||
var permissionIds = await _context.RolePermissionMappings
|
||||
.Where(rp => roleIds.Contains(rp.ApplicationRoleId)).Select(rp => rp.FeaturePermissionId).ToListAsync();
|
||||
|
||||
var permissions = await _context.FeaturePermissions.Include(f => f.Feature)
|
||||
.Where(fp => permissionIds.Contains(fp.Id))
|
||||
var permissions = await (
|
||||
from rpm in _context.RolePermissionMappings
|
||||
join fp in _context.FeaturePermissions.Include(f => f.Feature)
|
||||
on rpm.FeaturePermissionId equals fp.Id
|
||||
where employeeRoleIdsQuery.Contains(rpm.ApplicationRoleId) && fp.IsEnabled == true
|
||||
select fp)
|
||||
.Distinct()
|
||||
.ToListAsync();
|
||||
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using System.Security.Claims;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Security.Claims;
|
||||
|
||||
namespace MarcoBMS.Services.Helpers
|
||||
{
|
||||
@ -26,15 +25,6 @@ namespace MarcoBMS.Services.Helpers
|
||||
var tenant = _httpContextAccessor.HttpContext?.User.FindFirst("TenantId")?.Value;
|
||||
return (tenant != null ? Guid.Parse(tenant) : Guid.Empty);
|
||||
}
|
||||
public async Task<Tenant?> GetCurrentTenant()
|
||||
{
|
||||
var tenantId = _httpContextAccessor.HttpContext?.User.FindFirst("TenantId")?.Value;
|
||||
if (tenantId != null)
|
||||
{
|
||||
return await _context.Tenants.FirstOrDefaultAsync(t => t.Id == Guid.Parse(tenantId));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<IdentityUser?> GetCurrentUserAsync()
|
||||
{
|
||||
|
||||
@ -1,14 +1,10 @@
|
||||
using AutoMapper;
|
||||
using Marco.Pms.Model.Directory;
|
||||
using Marco.Pms.Model.Dtos.Directory;
|
||||
using Marco.Pms.Model.AppMenu;
|
||||
using Marco.Pms.Model.Dtos.AppMenu;
|
||||
using Marco.Pms.Model.Dtos.Expenses;
|
||||
using Marco.Pms.Model.Dtos.Master;
|
||||
using Marco.Pms.Model.Dtos.Project;
|
||||
using Marco.Pms.Model.Dtos.Tenant;
|
||||
using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.Expenses;
|
||||
using Marco.Pms.Model.Master;
|
||||
using Marco.Pms.Model.MongoDBModels;
|
||||
@ -17,8 +13,6 @@ using Marco.Pms.Model.MongoDBModels.Expenses;
|
||||
using Marco.Pms.Model.MongoDBModels.Masters;
|
||||
using Marco.Pms.Model.MongoDBModels.Project;
|
||||
using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
using Marco.Pms.Model.TenantModels.MongoDBModel;
|
||||
using Marco.Pms.Model.ViewModels.Activities;
|
||||
using Marco.Pms.Model.ViewModels.Directory;
|
||||
using Marco.Pms.Model.ViewModels.DocumentManager;
|
||||
@ -27,7 +21,6 @@ using Marco.Pms.Model.ViewModels.Expanses;
|
||||
using Marco.Pms.Model.ViewModels.Expenses;
|
||||
using Marco.Pms.Model.ViewModels.Master;
|
||||
using Marco.Pms.Model.ViewModels.Projects;
|
||||
using Marco.Pms.Model.ViewModels.Tenant;
|
||||
|
||||
namespace Marco.Pms.Services.MappingProfiles
|
||||
{
|
||||
@ -35,67 +28,6 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
{
|
||||
public MappingProfile()
|
||||
{
|
||||
#region ======================================================= Tenant =======================================================
|
||||
CreateMap<Tenant, TenantVM>();
|
||||
CreateMap<Tenant, TenantListVM>();
|
||||
CreateMap<Tenant, TenantDetailsVM>();
|
||||
|
||||
CreateMap<CreateTenantDto, Tenant>()
|
||||
.ForMember(
|
||||
dest => dest.ContactName,
|
||||
opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}")
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.Name,
|
||||
opt => opt.MapFrom(src => src.OrganizationName)
|
||||
);
|
||||
CreateMap<UpdateTenantDto, Tenant>()
|
||||
.ForMember(
|
||||
dest => dest.ContactName,
|
||||
opt => opt.MapFrom(src => $"{src.FirstName} {src.LastName}")
|
||||
);
|
||||
|
||||
CreateMap<SubscriptionPlanDetails, SubscriptionPlanVM>()
|
||||
.ForMember(
|
||||
dest => dest.PlanName,
|
||||
opt => opt.MapFrom(src => src.Plan != null ? src.Plan.PlanName : "")
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.Description,
|
||||
opt => opt.MapFrom(src => src.Plan != null ? src.Plan.Description : "")
|
||||
);
|
||||
CreateMap<TenantSubscriptions, SubscriptionPlanDetailsVM>()
|
||||
.ForMember(
|
||||
dest => dest.PlanName,
|
||||
opt => opt.MapFrom(src => src.Plan!.Plan != null ? src.Plan.Plan.PlanName : "")
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.Description,
|
||||
opt => opt.MapFrom(src => src.Plan!.Plan != null ? src.Plan.Plan.Description : "")
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.Price,
|
||||
opt => opt.MapFrom(src => src.Plan != null ? src.Plan.Price : 0)
|
||||
)
|
||||
.ForMember(
|
||||
dest => dest.Frequency,
|
||||
opt => opt.MapFrom(src => src.Plan != null ? src.Plan.Frequency : PLAN_FREQUENCY.MONTHLY)
|
||||
);
|
||||
CreateMap<SubscriptionPlanDetailsDto, SubscriptionPlanDetails>();
|
||||
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
|
||||
|
||||
#region ======================================================= Projects =======================================================
|
||||
// Your mappings
|
||||
CreateMap<Project, ProjectVM>();
|
||||
@ -228,8 +160,6 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
|
||||
#region ======================================================= Master =======================================================
|
||||
|
||||
CreateMap<FeaturePermission, FeaturePermissionVM>();
|
||||
|
||||
#region ======================================================= Expenses Type Master =======================================================
|
||||
|
||||
CreateMap<ExpensesTypeMasterDto, ExpensesTypeMaster>()
|
||||
@ -312,29 +242,6 @@ namespace Marco.Pms.Services.MappingProfiles
|
||||
|
||||
#endregion
|
||||
|
||||
#region ======================================================= AppMenu =======================================================
|
||||
CreateMap<CreateMenuSectionDto, MenuSection>();
|
||||
CreateMap<UpdateMenuSectionDto, MenuSection>();
|
||||
CreateMap<MenuSection, MenuSectionVM>()
|
||||
.ForMember(
|
||||
dest => dest.Name,
|
||||
opt => opt.MapFrom(src => src.Title));
|
||||
|
||||
CreateMap<CreateMenuItemDto, MenuItem>();
|
||||
CreateMap<UpdateMenuItemDto, MenuItem>();
|
||||
CreateMap<MenuItem, MenuItemVM>()
|
||||
.ForMember(
|
||||
dest => dest.Name,
|
||||
opt => opt.MapFrom(src => src.Text));
|
||||
|
||||
CreateMap<CreateSubMenuItemDto, SubMenuItem>();
|
||||
CreateMap<UpdateSubMenuItemDto, SubMenuItem>();
|
||||
CreateMap<SubMenuItem, SubMenuItemVM>()
|
||||
.ForMember(
|
||||
dest => dest.Name,
|
||||
opt => opt.MapFrom(src => src.Text));
|
||||
#endregion
|
||||
|
||||
#region ======================================================= Directory =======================================================
|
||||
|
||||
CreateMap<Contact, ContactVM>();
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
using Marco.Pms.CacheHelper;
|
||||
using Marco.Pms.DataAccess.Data;
|
||||
using Marco.Pms.Helpers;
|
||||
using Marco.Pms.Helpers.CacheHelper;
|
||||
@ -173,7 +172,6 @@ builder.Services.AddTransient<S3UploadService>();
|
||||
#region Customs Services
|
||||
builder.Services.AddScoped<RefreshTokenService>();
|
||||
builder.Services.AddScoped<PermissionServices>();
|
||||
builder.Services.AddScoped<MasterDataService>();
|
||||
builder.Services.AddScoped<ISignalRService, SignalRService>();
|
||||
builder.Services.AddScoped<IProjectServices, ProjectServices>();
|
||||
builder.Services.AddScoped<IExpensesService, ExpensesService>();
|
||||
@ -190,7 +188,6 @@ builder.Services.AddScoped<DirectoryHelper>();
|
||||
builder.Services.AddScoped<MasterHelper>();
|
||||
builder.Services.AddScoped<ReportHelper>();
|
||||
builder.Services.AddScoped<CacheUpdateHelper>();
|
||||
builder.Services.AddScoped<FeatureDetailsHelper>();
|
||||
builder.Services.AddScoped<UtilityMongoDBHelper>();
|
||||
#endregion
|
||||
|
||||
@ -199,7 +196,6 @@ builder.Services.AddScoped<ProjectCache>();
|
||||
builder.Services.AddScoped<EmployeeCache>();
|
||||
builder.Services.AddScoped<ReportCache>();
|
||||
builder.Services.AddScoped<ExpenseCache>();
|
||||
builder.Services.AddScoped<SidebarMenuHelper>();
|
||||
#endregion
|
||||
|
||||
// Singleton services (one instance for the app's lifetime)
|
||||
|
||||
@ -1,337 +0,0 @@
|
||||
using Marco.Pms.Model.Forum;
|
||||
using Marco.Pms.Model.Master;
|
||||
|
||||
namespace Marco.Pms.Services.Service
|
||||
{
|
||||
public class MasterDataService
|
||||
{
|
||||
public List<TicketStatusMaster> GetTicketStatusesData(Guid tenantId)
|
||||
{
|
||||
return new List<TicketStatusMaster>
|
||||
{
|
||||
new TicketStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "New",
|
||||
Description = "This is a newly created issue.",
|
||||
ColorCode = "#FFCC99",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Assigned",
|
||||
Description = "Assigned to employee or team of employees",
|
||||
ColorCode = "#E6FF99",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "In Progress",
|
||||
Description = "These issues are currently in progress",
|
||||
ColorCode = "#99E6FF",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "In Review",
|
||||
Description = "These issues are currently under review",
|
||||
ColorCode = "#8592a3",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Done",
|
||||
Description = "The following issues are resolved and closed",
|
||||
ColorCode = "#B399FF",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<TicketTypeMaster> GetTicketTypesData(Guid tenantId)
|
||||
{
|
||||
return new List<TicketTypeMaster>
|
||||
{
|
||||
new TicketTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Quality Issue",
|
||||
Description = "An identified problem that affects the performance, reliability, or standards of a product or service",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Help Desk",
|
||||
Description = "A support service that assists users with technical issues, requests, or inquiries.",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<TicketPriorityMaster> GetTicketPrioritysData(Guid tenantId)
|
||||
{
|
||||
return new List<TicketPriorityMaster>
|
||||
{
|
||||
new TicketPriorityMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Low",
|
||||
ColorCode = "008000",
|
||||
Level = 1,
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketPriorityMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Medium",
|
||||
ColorCode = "FFFF00",
|
||||
Level = 2,
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketPriorityMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "High",
|
||||
ColorCode = "#FFA500",
|
||||
Level = 3,
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketPriorityMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Critical",
|
||||
ColorCode = "#FFA500",
|
||||
Level = 4,
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketPriorityMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Urgent",
|
||||
ColorCode = "#FF0000",
|
||||
Level = 5,
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<TicketTagMaster> GetTicketTagsData(Guid tenantId)
|
||||
{
|
||||
return new List<TicketTagMaster>
|
||||
{
|
||||
new TicketTagMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Quality Issue",
|
||||
ColorCode = "#e59866",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new TicketTagMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Help Desk",
|
||||
ColorCode = "#85c1e9",
|
||||
IsDefault = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<WorkCategoryMaster> GetWorkCategoriesData(Guid tenantId)
|
||||
{
|
||||
return new List<WorkCategoryMaster>
|
||||
{
|
||||
new WorkCategoryMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Fresh Work",
|
||||
Description = "Created new task in a professional or creative context",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new WorkCategoryMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Rework",
|
||||
Description = "Revising, modifying, or correcting a task to improve its quality or fix issues",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new WorkCategoryMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Quality Issue",
|
||||
Description = "Any defect, deviation, or non-conformance in a task that fails to meet established standards or customer expectations.",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<WorkStatusMaster> GetWorkStatusesData(Guid tenantId)
|
||||
{
|
||||
return new List<WorkStatusMaster>
|
||||
{
|
||||
new WorkStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Approve",
|
||||
Description = "Confirm the tasks are actually finished as reported",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new WorkStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Partially Approve",
|
||||
Description = "Not all tasks are actually finished as reported",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new WorkStatusMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "NCR",
|
||||
Description = "Tasks are not finished as reported or have any issues in al the tasks",
|
||||
IsSystem = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<ExpensesTypeMaster> GetExpensesTypeesData(Guid tenantId)
|
||||
{
|
||||
return new List<ExpensesTypeMaster>
|
||||
{
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Procurement",
|
||||
Description = "Materials, equipment and supplies purchased for site operations.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Transport",
|
||||
Description = "Vehicle fuel, logistics services and delivery of goods or personnel.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Travelling",
|
||||
Description = "Delivery of personnel.",
|
||||
NoOfPersonsRequired = true,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Mobilization",
|
||||
Description = "Site setup costs including equipment deployment and temporary infrastructure.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Employee Welfare",
|
||||
Description = " Worker amenities like snacks, meals, safety gear, accommodation, medical support etc.",
|
||||
NoOfPersonsRequired = true,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Maintenance & Utilities",
|
||||
Description = "Machinery servicing, electricity, water, and temporary office needs.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Vendor/Supplier Payments",
|
||||
Description = "Scheduled payments for external services or goods.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new ExpensesTypeMaster
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Compliance & Safety",
|
||||
Description = "Government fees, insurance, inspections and safety-related expenditures.",
|
||||
NoOfPersonsRequired = false,
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<PaymentModeMatser> GetPaymentModesData(Guid tenantId)
|
||||
{
|
||||
return new List<PaymentModeMatser>
|
||||
{
|
||||
new PaymentModeMatser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Cash",
|
||||
Description = "Physical currency; still used for small or informal transactions.",
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new PaymentModeMatser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "Cheque",
|
||||
Description = "Paper-based payment order; less common now due to processing delays and fraud risks.",
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new PaymentModeMatser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "NetBanking",
|
||||
Description = "Online banking portals used to transfer funds directly between accounts",
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
},
|
||||
new PaymentModeMatser
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Name = "UPI",
|
||||
Description = "Real-time bank-to-bank transfer using mobile apps; widely used for peer-to-peer and merchant payments.",
|
||||
IsActive = true,
|
||||
TenantId = tenantId
|
||||
}
|
||||
};
|
||||
}
|
||||
public List<object> GetData(Guid tenantId)
|
||||
{
|
||||
return new List<object>
|
||||
{
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,18 +30,6 @@ namespace Marco.Pms.Services.Service
|
||||
var hasPermission = featurePermissionIds.Contains(featurePermissionId);
|
||||
return hasPermission;
|
||||
}
|
||||
public async Task<bool> HasPermissionAny(List<Guid> featurePermissionIds, Guid employeeId)
|
||||
{
|
||||
var allFeaturePermissionIds = await _cache.GetPermissions(employeeId);
|
||||
if (allFeaturePermissionIds == null)
|
||||
{
|
||||
List<FeaturePermission> featurePermission = await _rolesHelper.GetFeaturePermissionByEmployeeId(employeeId);
|
||||
allFeaturePermissionIds = featurePermission.Select(fp => fp.Id).ToList();
|
||||
}
|
||||
var hasPermission = featurePermissionIds.Any(f => allFeaturePermissionIds.Contains(f));
|
||||
|
||||
return hasPermission;
|
||||
}
|
||||
public async Task<bool> HasProjectPermission(Employee LoggedInEmployee, Guid projectId)
|
||||
{
|
||||
var employeeId = LoggedInEmployee.Id;
|
||||
|
||||
@ -7,7 +7,6 @@ using Marco.Pms.Model.Employees;
|
||||
using Marco.Pms.Model.Entitlements;
|
||||
using Marco.Pms.Model.MongoDBModels.Project;
|
||||
using Marco.Pms.Model.Projects;
|
||||
using Marco.Pms.Model.TenantModels;
|
||||
using Marco.Pms.Model.Utilities;
|
||||
using Marco.Pms.Model.ViewModels.Employee;
|
||||
using Marco.Pms.Model.ViewModels.Projects;
|
||||
@ -228,6 +227,10 @@ namespace Marco.Pms.Services.Service
|
||||
else
|
||||
{
|
||||
projectVM = _mapper.Map<ProjectVM>(projectDetails);
|
||||
if (projectVM.ProjectStatus != null)
|
||||
{
|
||||
projectVM.ProjectStatus.TenantId = tenantId;
|
||||
}
|
||||
}
|
||||
|
||||
if (projectVM == null)
|
||||
@ -892,73 +895,6 @@ namespace Marco.Pms.Services.Service
|
||||
return ApiResponse<List<ProjectAllocationVM>>.SuccessResponse(resultVm, "Assignments managed successfully.", 200);
|
||||
}
|
||||
|
||||
public async Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
// Log the start of the method execution with key input parameters
|
||||
_logger.LogInfo("Fetching projects for EmployeeId: {EmployeeId}, TenantId: {TenantId} by User: {UserId}",
|
||||
employeeId, tenantId, loggedInEmployee.Id);
|
||||
|
||||
try
|
||||
{
|
||||
// Retrieve project allocations linked to the specified employee and tenant
|
||||
var projectAllocation = await _context.ProjectAllocations
|
||||
.AsNoTracking() // Optimization: no tracking since entities are not updated
|
||||
.Include(pa => pa.Project) // Include related Project data
|
||||
.Include(pa => pa.Employee).ThenInclude(e => e!.JobRole) // Include related Employee and their JobRole
|
||||
.Where(pa => pa.EmployeeId == employeeId
|
||||
&& pa.TenantId == tenantId
|
||||
&& pa.Project != null
|
||||
&& pa.Employee != null)
|
||||
.Select(pa => new
|
||||
{
|
||||
ProjectName = pa.Project!.Name,
|
||||
ProjectShortName = pa.Project.ShortName,
|
||||
AssignedDate = pa.AllocationDate,
|
||||
RemovedDate = pa.ReAllocationDate,
|
||||
Designation = pa.Employee!.JobRole!.Name,
|
||||
DesignationId = pa.JobRoleId
|
||||
})
|
||||
.ToListAsync();
|
||||
|
||||
var designationIds = projectAllocation.Select(pa => pa.DesignationId).ToList();
|
||||
|
||||
var designations = await _context.JobRoles.Where(jr => designationIds.Contains(jr.Id)).ToListAsync();
|
||||
|
||||
var response = projectAllocation.Select(pa =>
|
||||
{
|
||||
var designation = designations.FirstOrDefault(jr => jr.Id == pa.DesignationId);
|
||||
return new ProjectHisteryVM
|
||||
{
|
||||
ProjectName = pa.ProjectName,
|
||||
ProjectShortName = pa.ProjectShortName,
|
||||
AssignedDate = pa.AssignedDate,
|
||||
RemovedDate = pa.RemovedDate,
|
||||
Designation = designation?.Name
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
// Log successful retrieval including count of records
|
||||
_logger.LogInfo("Successfully fetched {Count} projects for EmployeeId: {EmployeeId}",
|
||||
projectAllocation.Count, employeeId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(
|
||||
response,
|
||||
$"{response.Count} project assignments fetched for employee.",
|
||||
200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Log the exception with stack trace for debugging
|
||||
_logger.LogError(ex, "Error occurred while fetching projects for EmployeeId: {EmployeeId}, TenantId: {TenantId}",
|
||||
employeeId, tenantId);
|
||||
|
||||
return ApiResponse<object>.ErrorResponse(
|
||||
"An error occurred while fetching project assignments.",
|
||||
500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Project InfraStructure Get APIs ===================================================================
|
||||
@ -1089,83 +1025,6 @@ namespace Marco.Pms.Services.Service
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves tasks assigned to a specific employee within a date range for a tenant.
|
||||
/// </summary>
|
||||
/// <param name="employeeId">The ID of the employee to filter tasks.</param>
|
||||
/// <param name="fromDate">The start date to filter task assignments.</param>
|
||||
/// <param name="toDate">The end date to filter task assignments.</param>
|
||||
/// <param name="tenantId">The tenant ID to filter tasks.</param>
|
||||
/// <param name="loggedInEmployee">The employee requesting the data (for authorization/logging).</param>
|
||||
/// <returns>An ApiResponse containing the task details.</returns>
|
||||
public async Task<ApiResponse<object>> GetTasksByEmployeeAsync(Guid employeeId, DateTime fromDate, DateTime toDate, Guid tenantId, Employee loggedInEmployee)
|
||||
{
|
||||
_logger.LogInfo("Fetching tasks for EmployeeId: {EmployeeId} from {FromDate} to {ToDate} for TenantId: {TenantId}",
|
||||
employeeId, fromDate, toDate, tenantId);
|
||||
|
||||
try
|
||||
{
|
||||
// Query TaskMembers with related necessary fields in one projection to minimize DB calls and data size
|
||||
var taskData = await _context.TaskMembers
|
||||
.Where(tm => tm.EmployeeId == employeeId &&
|
||||
tm.TenantId == tenantId &&
|
||||
tm.TaskAllocation != null &&
|
||||
tm.TaskAllocation.AssignmentDate.Date >= fromDate.Date &&
|
||||
tm.TaskAllocation.AssignmentDate.Date <= toDate.Date)
|
||||
.Select(tm => new
|
||||
{
|
||||
AssignmentDate = tm.TaskAllocation!.AssignmentDate,
|
||||
PlannedTask = tm.TaskAllocation.PlannedTask,
|
||||
CompletedTask = tm.TaskAllocation.CompletedTask,
|
||||
ProjectId = tm.TaskAllocation.WorkItem!.WorkArea!.Floor!.Building!.ProjectId,
|
||||
BuildingName = tm.TaskAllocation.WorkItem.WorkArea.Floor.Building!.Name,
|
||||
FloorName = tm.TaskAllocation.WorkItem.WorkArea.Floor.FloorName,
|
||||
AreaName = tm.TaskAllocation.WorkItem.WorkArea.AreaName,
|
||||
ActivityName = tm.TaskAllocation.WorkItem.ActivityMaster!.ActivityName,
|
||||
ActivityUnit = tm.TaskAllocation.WorkItem.ActivityMaster.UnitOfMeasurement
|
||||
})
|
||||
.OrderByDescending(t => t.AssignmentDate)
|
||||
.ToListAsync();
|
||||
|
||||
_logger.LogInfo("Retrieved {TaskCount} tasks for EmployeeId: {EmployeeId}", taskData.Count, employeeId);
|
||||
|
||||
// Extract distinct project IDs to fetch project details efficiently
|
||||
var distinctProjectIds = taskData.Select(t => t.ProjectId).Distinct().ToList();
|
||||
|
||||
var projects = await _context.Projects
|
||||
.Where(p => distinctProjectIds.Contains(p.Id))
|
||||
.Select(p => new { p.Id, p.Name })
|
||||
.ToListAsync();
|
||||
|
||||
// Prepare the response
|
||||
var response = taskData.Select(t =>
|
||||
{
|
||||
var project = projects.FirstOrDefault(p => p.Id == t.ProjectId);
|
||||
|
||||
return new
|
||||
{
|
||||
ProjectName = project?.Name ?? "Unknown Project",
|
||||
t.AssignmentDate,
|
||||
t.PlannedTask,
|
||||
t.CompletedTask,
|
||||
Location = $"{t.BuildingName} > {t.FloorName} > {t.AreaName}",
|
||||
ActivityName = t.ActivityName,
|
||||
ActivityUnit = t.ActivityUnit
|
||||
};
|
||||
}).ToList();
|
||||
|
||||
_logger.LogInfo("Successfully prepared task response for EmployeeId: {EmployeeId}", employeeId);
|
||||
|
||||
return ApiResponse<object>.SuccessResponse(response, "Task fetched successfully", 200);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error while fetching tasks for EmployeeId: {EmployeeId}", employeeId);
|
||||
return ApiResponse<object>.ErrorResponse("An error occurred while fetching the tasks.", 500);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region =================================================================== Project Infrastructre Manage APIs ===================================================================
|
||||
|
||||
@ -20,11 +20,8 @@ namespace Marco.Pms.Services.Service.ServiceInterfaces
|
||||
Task<ApiResponse<List<ProjectAllocationVM>>> ManageAllocationAsync(List<ProjectAllocationDot> projectAllocationDots, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectsByEmployeeAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<List<ProjectAllocationVM>>> AssigneProjectsToEmployeeAsync(List<ProjectsAllocationDto> projectAllocationDtos, Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetProjectByEmployeeBasicAsync(Guid employeeId, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
Task<ApiResponse<object>> GetInfraDetailsAsync(Guid projectId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetWorkItemsAsync(Guid workAreaId, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<object>> GetTasksByEmployeeAsync(Guid employeeId, DateTime fromDate, DateTime toDate, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ServiceResponse> ManageProjectInfraAsync(List<InfraDto> infraDtos, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ApiResponse<List<WorkItemVM>>> CreateProjectTaskAsync(List<WorkItemDto> workItemDtos, Guid tenantId, Employee loggedInEmployee);
|
||||
Task<ServiceResponse> DeleteProjectTaskAsync(Guid id, Guid tenantId, Employee loggedInEmployee);
|
||||
|
||||
@ -1,54 +1,54 @@
|
||||
{
|
||||
"Cors": {
|
||||
"AllowedOrigins": "*",
|
||||
"AllowedMethods": "*",
|
||||
"AllowedHeaders": "*"
|
||||
},
|
||||
"Environment": {
|
||||
"Name": "Development",
|
||||
"Title": "Dev"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
|
||||
},
|
||||
"SmtpSettings": {
|
||||
"SmtpServer": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"SenderName": "MarcoAIOT",
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
//"SmtpSettings": {
|
||||
// "SmtpServer": "mail.marcoaiot.com",
|
||||
// "Port": 587,
|
||||
// "SenderName": "MarcoAIOT",
|
||||
// "SenderEmail": "ashutosh.nehete@marcoaiot.com",
|
||||
// "Password": "Reset@123"
|
||||
//},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "http://localhost:5173",
|
||||
"ImagesBaseUrl": "http://localhost:5173"
|
||||
},
|
||||
"Jwt": {
|
||||
"Issuer": "http://localhost:5246",
|
||||
"Audience": "http://localhost:5246",
|
||||
"Key": "sworffishhkjfa9dnfdndfu33infnajfj",
|
||||
"ExpiresInMinutes": 60,
|
||||
"RefreshTokenExpiresInDays": 7
|
||||
},
|
||||
"MailingList": {
|
||||
"RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
//"ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
},
|
||||
"AWS": {
|
||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
|
||||
"Region": "us-east-1",
|
||||
"BucketName": "testenv-marco-pms-documents"
|
||||
},
|
||||
"Cors": {
|
||||
"AllowedOrigins": "*",
|
||||
"AllowedMethods": "*",
|
||||
"AllowedHeaders": "*"
|
||||
},
|
||||
"Environment": {
|
||||
"Name": "Development",
|
||||
"Title": "Dev"
|
||||
},
|
||||
"ConnectionStrings": {
|
||||
"DefaultConnectionString": "Server=147.93.98.152;User ID=devuser;Password=AppUser@123$;Database=MarcoBMS1"
|
||||
},
|
||||
"SmtpSettings": {
|
||||
"SmtpServer": "smtp.gmail.com",
|
||||
"Port": 587,
|
||||
"SenderName": "MarcoAIOT",
|
||||
"SenderEmail": "marcoioitsoft@gmail.com",
|
||||
"Password": "qrtq wfuj hwpp fhqr"
|
||||
},
|
||||
//"SmtpSettings": {
|
||||
// "SmtpServer": "mail.marcoaiot.com",
|
||||
// "Port": 587,
|
||||
// "SenderName": "MarcoAIOT",
|
||||
// "SenderEmail": "ashutosh.nehete@marcoaiot.com",
|
||||
// "Password": "Reset@123"
|
||||
//},
|
||||
"AppSettings": {
|
||||
"WebFrontendUrl": "http://localhost:5173",
|
||||
"ImagesBaseUrl": "http://localhost:5173"
|
||||
},
|
||||
"Jwt": {
|
||||
"Issuer": "http://localhost:5246",
|
||||
"Audience": "http://localhost:5246",
|
||||
"Key": "sworffishhkjfa9dnfdndfu33infnajfj",
|
||||
"ExpiresInMinutes": 60,
|
||||
"RefreshTokenExpiresInDays": 7
|
||||
},
|
||||
"MailingList": {
|
||||
"RequestDemoReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
//"ProjectStatisticsReceivers": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
|
||||
},
|
||||
"AWS": {
|
||||
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
|
||||
"SecretKey": "NTS5XXgZINQbU6ctpNuLXtIY/Qk9GCgD9Rr5yNJP",
|
||||
"Region": "us-east-1",
|
||||
"BucketName": "testenv-marco-pms-documents"
|
||||
},
|
||||
"MongoDB": {
|
||||
"SerilogDatabaseUrl": "mongodb://localhost:27017/DotNetLogs",
|
||||
"ConnectionString": "mongodb://localhost:27017/MarcoBMS_Caches?socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500",
|
||||
"ModificationConnectionString": "mongodb://devuser:DevPass123@147.93.98.152:27017/MarcoBMSLocalDev?authSource=admin&eplicaSet=rs01&directConnection=true"
|
||||
"ModificationConnectionString": "mongodb://localhost:27017/ModificationLog?socketTimeoutMS=500&serverSelectionTimeoutMS=500&connectTimeoutMS=500"
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user