Implemented functionality to upload captured attendance images to Amazon S3 and record associated data in the database. #24

Merged
admin merged 4 commits from Ashutosh_Enhancement_#104_Store_Images_In_AmazonS3 into Feature_Forum 2025-04-23 10:37:10 +00:00
31 changed files with 9430 additions and 99 deletions

View File

@ -1,8 +1,10 @@
using Marco.Pms.Model.Activities; using Marco.Pms.Model.Activities;
using Marco.Pms.Model.AttendanceModule; using Marco.Pms.Model.AttendanceModule;
using Marco.Pms.Model.Authentication; using Marco.Pms.Model.Authentication;
using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
using Marco.Pms.Model.Forum;
using Marco.Pms.Model.Industries; using Marco.Pms.Model.Industries;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
@ -57,7 +59,7 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<Attendance> Attendes { get; set; } public DbSet<Attendance> Attendes { get; set; }
public DbSet<AttendanceLog> AttendanceLogs { get; set; } public DbSet<AttendanceLog> AttendanceLogs { get; set; }
// public DbSet<AttendLog> AttendLogs { get; set; } // public DbSet<AttendLog> AttendLogs { get; set; }
@ -72,10 +74,20 @@ namespace Marco.Pms.DataAccess.Data
public DbSet<JobRole> JobRoles { get; set; } public DbSet<JobRole> JobRoles { get; set; }
public DbSet<RolePermissionMappings> RolePermissionMappings { get; set; } public DbSet<RolePermissionMappings> RolePermissionMappings { get; set; }
public DbSet<Industry>Industries { get; set; } public DbSet<Industry> Industries { get; set; }
public DbSet<ActivityCheckList>ActivityCheckLists { get; set; } public DbSet<ActivityCheckList> ActivityCheckLists { get; set; }
public DbSet<CheckListMappings> CheckListMappings { get; set; } public DbSet<CheckListMappings> CheckListMappings { get; set; }
public DbSet<Inquiries> Inquiries { get; set; } public DbSet<Inquiries> Inquiries { get; set; }
public DbSet<TicketForum> Tickets { get; set; }
public DbSet<TicketAttachment> TicketAttachments { get; set; }
public DbSet<TicketComment> TicketComments { get; set; }
public DbSet<TicketStatusMaster> TicketStatusMasters { get; set; }
public DbSet<TicketTypeMaster> TicketTypeMasters { get; set; }
public DbSet<TicketPriorityMaster> TicketPriorityMasters { get; set; }
public DbSet<TicketTagMaster> TicketTagMasters { get; set; }
public DbSet<Document> Documents { get; set; }
public DbSet<TicketTag> TicketTags { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder) protected override void OnModelCreating(ModelBuilder modelBuilder)
{ {
@ -136,7 +148,7 @@ namespace Marco.Pms.DataAccess.Data
}); });
modelBuilder.Entity<Tenant>().HasData( modelBuilder.Entity<Tenant>().HasData(
new Tenant { Id = 1, Name = "MarcoBMS", ContactName = "Admin", ContactNumber = "123456789", Description = "", DomainName = "www.marcobms.org",IndustryId = 1, OnBoardingDate = DateTime.MinValue } new Tenant { Id = 1, Name = "MarcoBMS", ContactName = "Admin", ContactNumber = "123456789", Description = "", DomainName = "www.marcobms.org", IndustryId = 1, OnBoardingDate = DateTime.MinValue }
); );
modelBuilder.Entity<StatusMaster>().HasData( modelBuilder.Entity<StatusMaster>().HasData(
@ -284,16 +296,144 @@ namespace Marco.Pms.DataAccess.Data
} }
); );
modelBuilder.Entity<Industry>().HasData( modelBuilder.Entity<Industry>().HasData(
new Industry {Id = 1,Name = "Information Technology (IT) Services"}, new Industry { Id = 1, Name = "Information Technology (IT) Services" },
new Industry { Id = 2,Name = "Manufacturing & Production" }, new Industry { Id = 2, Name = "Manufacturing & Production" },
new Industry { Id = 3,Name = "Energy & Resources" }, new Industry { Id = 3, Name = "Energy & Resources" },
new Industry { Id = 4,Name = "Finance & Professional Services" }, new Industry { Id = 4, Name = "Finance & Professional Services" },
new Industry { Id = 5, Name = "Hospitals and Healthcare Services" }, new Industry { Id = 5, Name = "Hospitals and Healthcare Services" },
new Industry { Id = 6, Name = "Social Services" }, new Industry { Id = 6, Name = "Social Services" },
new Industry { Id = 7, Name = "Retail & Consumer Services" }, new Industry { Id = 7, Name = "Retail & Consumer Services" },
new Industry { Id = 8, Name = "Transportation & Logistics" }, new Industry { Id = 8, Name = "Transportation & Logistics" },
new Industry { Id = 9, Name = "Education & Training" } new Industry { Id = 9, Name = "Education & Training" }
);
modelBuilder.Entity<TicketStatusMaster>().HasData(
new TicketStatusMaster
{
Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"),
Name = "New",
Description = "This is a newly created issue.",
ColorCode = "#FFCC99",
IsDefault = true,
TenantId = 1
},
new TicketStatusMaster
{
Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"),
Name = "Assigned",
Description = "Assigned to employee or team of employees",
ColorCode = "#E6FF99",
IsDefault = true,
TenantId = 1
},
new TicketStatusMaster
{
Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"),
Name = "In Progress",
Description = "These issues are currently in progress",
ColorCode = "#99E6FF",
IsDefault = true,
TenantId = 1
},
new TicketStatusMaster
{
Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"),
Name = "In Review",
Description = "These issues are currently under review",
ColorCode = "#6c757d",
IsDefault = true,
TenantId = 1
},
new TicketStatusMaster
{
Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"),
Name = "Done",
Description = "The following issues are resolved and closed",
ColorCode = "#B399FF",
IsDefault = true,
TenantId = 1
}
);
modelBuilder.Entity<TicketTypeMaster>().HasData(
new TicketTypeMaster
{
Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"),
Name = "Quality Issue",
Description = "An identified problem that affects the performance, reliability, or standards of a product or service",
IsDefault = true,
TenantId = 1
},
new TicketTypeMaster
{
Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"),
Name = "Help Desk",
Description = "A support service that assists users with technical issues, requests, or inquiries.",
IsDefault = true,
TenantId = 1
}
);
modelBuilder.Entity<TicketPriorityMaster>().HasData(
new TicketPriorityMaster
{
Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"),
Name = "Low",
ColorCode = "008000",
Level = 1,
IsDefault = true,
TenantId = 1
},
new TicketPriorityMaster
{
Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"),
Name = "Medium",
ColorCode = "FFFF00",
Level = 2,
IsDefault = true,
TenantId = 1
}, new TicketPriorityMaster
{
Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"),
Name = "High",
ColorCode = "#FFA500",
Level = 3,
IsDefault = true,
TenantId = 1
}, new TicketPriorityMaster
{
Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"),
Name = "Critical",
ColorCode = "#FFA500",
Level = 4,
IsDefault = true,
TenantId = 1
},
new TicketPriorityMaster
{
Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"),
Name = "Urgent",
ColorCode = "#FF0000",
Level = 5,
IsDefault = true,
TenantId = 1
}
);
modelBuilder.Entity<TicketTagMaster>().HasData(
new TicketTagMaster
{
Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"),
Name = "Quality Issue",
ColorCode = "#e59866",
IsDefault = true,
TenantId = 1
},
new TicketTagMaster
{
Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"),
Name = "Help Desk",
ColorCode = "#85c1e9",
IsDefault = true,
TenantId = 1
}
); );
} }
@ -360,7 +500,7 @@ namespace Marco.Pms.DataAccess.Data
); );
modelBuilder.Entity<FeaturePermission>().HasData( modelBuilder.Entity<FeaturePermission>().HasData(
new FeaturePermission { Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project" , Description=""}, new FeaturePermission { Id = new Guid("6ea44136-987e-44ba-9e5d-1cf8f5837ebc"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "View Project", Description = "" },
new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "" }, new FeaturePermission { Id = new Guid("172fc9b6-755b-4f62-ab26-55c34a330614"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Project", Description = "" },
new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "" }, new FeaturePermission { Id = new Guid("b94802ce-0689-4643-9e1d-11c86950c35b"), FeatureId = new Guid("53176ebf-c75d-42e5-839f-4508ffac3def"), IsEnabled = true, Name = "Manage Team", Description = "" },

View File

@ -1,32 +0,0 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Marco.Pms.Model.Authentication;
using Marco.Pms.Model.Forum;
namespace Marco.Pms.DataAccess.Data
{
public class ForumDbContext : IdentityDbContext<IdentityUser>
{
private readonly IHttpContextAccessor _httpContextAccessor;
public ForumDbContext(DbContextOptions<ApplicationDbContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
{
_httpContextAccessor = httpContextAccessor;
}
public DbSet<TicketForum> Tickets { get; set; }
public DbSet<TicketAttachment> TicketAttachments { get; set; }
public DbSet<TicketComment> TicketComments { get; set; }
public DbSet<TicketStatusMaster> TicketStatusMasters { get; set; }
public DbSet<TicketTypeMaster> TicketTypeMasters { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,376 @@
using System;
using Microsoft.EntityFrameworkCore.Metadata;
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_Forum_Tables : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Documents",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
BatchId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
FileName = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
S3Key = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
ThumbS3Key = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
Base64Data = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
FileSize = table.Column<long>(type: "bigint", nullable: false),
ContentType = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
UploadedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Documents", x => x.Id);
table.ForeignKey(
name: "FK_Documents_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketComments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TicketId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
AuthorId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
MessageText = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
SentAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
ParentMessageId = table.Column<Guid>(type: "char(36)", nullable: true, collation: "ascii_general_ci"),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketComments", x => x.Id);
table.ForeignKey(
name: "FK_TicketComments_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketPriorityMasters",
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"),
Level = table.Column<int>(type: "int", nullable: false),
ColorCode = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsDefault = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketPriorityMasters", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketStatusMasters",
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"),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
ColorCode = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsDefault = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketStatusMasters", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketTagMasters",
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"),
ColorCode = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
TenantId = table.Column<int>(type: "int", nullable: false),
IsDefault = table.Column<bool>(type: "tinyint(1)", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketTagMasters", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketTypeMasters",
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"),
Description = table.Column<string>(type: "longtext", nullable: true)
.Annotation("MySql:CharSet", "utf8mb4"),
IsDefault = table.Column<bool>(type: "tinyint(1)", nullable: false),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_TicketTypeMasters", x => x.Id);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "Tickets",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
Subject = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
Description = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
StatusId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TypeId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
CreatedById = table.Column<int>(type: "int", nullable: false),
CreatedAt = table.Column<DateTime>(type: "datetime(6)", nullable: false),
LinkedActivityId = table.Column<int>(type: "int", nullable: false),
PriorityId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TenantId = table.Column<int>(type: "int", nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Tickets", x => x.Id);
table.ForeignKey(
name: "FK_Tickets_Tenants_TenantId",
column: x => x.TenantId,
principalTable: "Tenants",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Tickets_TicketPriorityMasters_PriorityId",
column: x => x.PriorityId,
principalTable: "TicketPriorityMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Tickets_TicketStatusMasters_StatusId",
column: x => x.StatusId,
principalTable: "TicketStatusMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_Tickets_TicketTypeMasters_TypeId",
column: x => x.TypeId,
principalTable: "TicketTypeMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketAttachments",
columns: table => new
{
Id = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TicketId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
CommentId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
FileName = table.Column<string>(type: "longtext", nullable: false)
.Annotation("MySql:CharSet", "utf8mb4"),
FileId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_TicketAttachments", x => x.Id);
table.ForeignKey(
name: "FK_TicketAttachments_TicketComments_CommentId",
column: x => x.CommentId,
principalTable: "TicketComments",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_TicketAttachments_Tickets_TicketId",
column: x => x.TicketId,
principalTable: "Tickets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.CreateTable(
name: "TicketTags",
columns: table => new
{
Id = table.Column<int>(type: "int", nullable: false)
.Annotation("MySql:ValueGenerationStrategy", MySqlValueGenerationStrategy.IdentityColumn),
TicketId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci"),
TagId = table.Column<Guid>(type: "char(36)", nullable: false, collation: "ascii_general_ci")
},
constraints: table =>
{
table.PrimaryKey("PK_TicketTags", x => x.Id);
table.ForeignKey(
name: "FK_TicketTags_TicketTagMasters_TagId",
column: x => x.TagId,
principalTable: "TicketTagMasters",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
table.ForeignKey(
name: "FK_TicketTags_Tickets_TicketId",
column: x => x.TicketId,
principalTable: "Tickets",
principalColumn: "Id",
onDelete: ReferentialAction.Cascade);
})
.Annotation("MySql:CharSet", "utf8mb4");
migrationBuilder.InsertData(
table: "TicketPriorityMasters",
columns: new[] { "Id", "ColorCode", "IsDefault", "Level", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"), "FFFF00", true, 2, "Medium", 1 },
{ new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"), "008000", true, 1, "Low", 1 },
{ new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"), "#FF0000", true, 5, "Urgent", 1 },
{ new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"), "#FFA500", true, 3, "High", 1 },
{ new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"), "#FFA500", true, 4, "Critical", 1 }
});
migrationBuilder.InsertData(
table: "TicketStatusMasters",
columns: new[] { "Id", "ColorCode", "Description", "IsDefault", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"), "#6c757d", "These issues are currently under review", true, "In Review", 1 },
{ new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"), "#FFCC99", "This is a newly created issue.", true, "New", 1 },
{ new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"), "#E6FF99", "Assigned to employee or team of employees", true, "Assigned", 1 },
{ new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"), "#99E6FF", "These issues are currently in progress", true, "In Progress", 1 },
{ new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"), "#B399FF", "The following issues are resolved and closed", true, "Done", 1 }
});
migrationBuilder.InsertData(
table: "TicketTagMasters",
columns: new[] { "Id", "ColorCode", "IsDefault", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"), "#85c1e9", true, "Help Desk", 1 },
{ new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"), "#e59866", true, "Quality Issue", 1 }
});
migrationBuilder.InsertData(
table: "TicketTypeMasters",
columns: new[] { "Id", "Description", "IsDefault", "Name", "TenantId" },
values: new object[,]
{
{ new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"), "An identified problem that affects the performance, reliability, or standards of a product or service", true, "Quality Issue", 1 },
{ new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"), "A support service that assists users with technical issues, requests, or inquiries.", true, "Help Desk", 1 }
});
migrationBuilder.CreateIndex(
name: "IX_Documents_TenantId",
table: "Documents",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_TicketAttachments_CommentId",
table: "TicketAttachments",
column: "CommentId");
migrationBuilder.CreateIndex(
name: "IX_TicketAttachments_TicketId",
table: "TicketAttachments",
column: "TicketId");
migrationBuilder.CreateIndex(
name: "IX_TicketComments_TenantId",
table: "TicketComments",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_PriorityId",
table: "Tickets",
column: "PriorityId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_StatusId",
table: "Tickets",
column: "StatusId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_TenantId",
table: "Tickets",
column: "TenantId");
migrationBuilder.CreateIndex(
name: "IX_Tickets_TypeId",
table: "Tickets",
column: "TypeId");
migrationBuilder.CreateIndex(
name: "IX_TicketTags_TagId",
table: "TicketTags",
column: "TagId");
migrationBuilder.CreateIndex(
name: "IX_TicketTags_TicketId",
table: "TicketTags",
column: "TicketId");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropTable(
name: "Documents");
migrationBuilder.DropTable(
name: "TicketAttachments");
migrationBuilder.DropTable(
name: "TicketTags");
migrationBuilder.DropTable(
name: "TicketComments");
migrationBuilder.DropTable(
name: "TicketTagMasters");
migrationBuilder.DropTable(
name: "Tickets");
migrationBuilder.DropTable(
name: "TicketPriorityMasters");
migrationBuilder.DropTable(
name: "TicketStatusMasters");
migrationBuilder.DropTable(
name: "TicketTypeMasters");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,50 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Added_Foreign_Key_In_Attendance_Log : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<Guid>(
name: "DocumentId",
table: "AttendanceLogs",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci");
migrationBuilder.CreateIndex(
name: "IX_AttendanceLogs_DocumentId",
table: "AttendanceLogs",
column: "DocumentId");
migrationBuilder.AddForeignKey(
name: "FK_AttendanceLogs_Documents_DocumentId",
table: "AttendanceLogs",
column: "DocumentId",
principalTable: "Documents",
principalColumn: "Id");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropForeignKey(
name: "FK_AttendanceLogs_Documents_DocumentId",
table: "AttendanceLogs");
migrationBuilder.DropIndex(
name: "IX_AttendanceLogs_DocumentId",
table: "AttendanceLogs");
migrationBuilder.DropColumn(
name: "DocumentId",
table: "AttendanceLogs");
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,41 @@
using System;
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace Marco.Pms.DataAccess.Migrations
{
/// <inheritdoc />
public partial class Made_BatchId_Nullable_In_Document : Migration
{
/// <inheritdoc />
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<Guid>(
name: "BatchId",
table: "Documents",
type: "char(36)",
nullable: true,
collation: "ascii_general_ci",
oldClrType: typeof(Guid),
oldType: "char(36)")
.OldAnnotation("Relational:Collation", "ascii_general_ci");
}
/// <inheritdoc />
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.AlterColumn<Guid>(
name: "BatchId",
table: "Documents",
type: "char(36)",
nullable: false,
defaultValue: new Guid("00000000-0000-0000-0000-000000000000"),
collation: "ascii_general_ci",
oldClrType: typeof(Guid),
oldType: "char(36)",
oldNullable: true)
.OldAnnotation("Relational:Collation", "ascii_general_ci");
}
}
}

View File

@ -200,6 +200,9 @@ namespace Marco.Pms.DataAccess.Migrations
.IsRequired() .IsRequired()
.HasColumnType("longtext"); .HasColumnType("longtext");
b.Property<Guid?>("DocumentId")
.HasColumnType("char(36)");
b.Property<int>("EmployeeID") b.Property<int>("EmployeeID")
.HasColumnType("int"); .HasColumnType("int");
@ -225,6 +228,8 @@ namespace Marco.Pms.DataAccess.Migrations
b.HasIndex("AttendanceId"); b.HasIndex("AttendanceId");
b.HasIndex("DocumentId");
b.HasIndex("EmployeeID"); b.HasIndex("EmployeeID");
b.HasIndex("TenantId"); b.HasIndex("TenantId");
@ -270,6 +275,49 @@ namespace Marco.Pms.DataAccess.Migrations
b.ToTable("RefreshTokens"); b.ToTable("RefreshTokens");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Base64Data")
.HasColumnType("longtext");
b.Property<Guid?>("BatchId")
.HasColumnType("char(36)");
b.Property<string>("ContentType")
.IsRequired()
.HasColumnType("longtext");
b.Property<string>("FileName")
.IsRequired()
.HasColumnType("longtext");
b.Property<long>("FileSize")
.HasColumnType("bigint");
b.Property<string>("S3Key")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.Property<string>("ThumbS3Key")
.HasColumnType("longtext");
b.Property<DateTime>("UploadedAt")
.HasColumnType("datetime(6)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("Documents");
});
modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1103,6 +1151,369 @@ namespace Marco.Pms.DataAccess.Migrations
}); });
}); });
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("CommentId")
.HasColumnType("char(36)");
b.Property<Guid>("FileId")
.HasColumnType("char(36)");
b.Property<string>("FileName")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid>("TicketId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("CommentId");
b.HasIndex("TicketId");
b.ToTable("TicketAttachments");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<Guid>("AuthorId")
.HasColumnType("char(36)");
b.Property<string>("MessageText")
.IsRequired()
.HasColumnType("longtext");
b.Property<Guid?>("ParentMessageId")
.HasColumnType("char(36)");
b.Property<DateTime>("SentAt")
.HasColumnType("datetime(6)");
b.Property<int>("TenantId")
.HasColumnType("int");
b.Property<Guid>("TicketId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TenantId");
b.ToTable("TicketComments");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<DateTime>("CreatedAt")
.HasColumnType("datetime(6)");
b.Property<int>("CreatedById")
.HasColumnType("int");
b.Property<string>("Description")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("LinkedActivityId")
.HasColumnType("int");
b.Property<Guid>("PriorityId")
.HasColumnType("char(36)");
b.Property<Guid>("StatusId")
.HasColumnType("char(36)");
b.Property<string>("Subject")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.Property<Guid>("TypeId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("PriorityId");
b.HasIndex("StatusId");
b.HasIndex("TenantId");
b.HasIndex("TypeId");
b.ToTable("Tickets");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketPriorityMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ColorCode")
.HasColumnType("longtext");
b.Property<bool>("IsDefault")
.HasColumnType("tinyint(1)");
b.Property<int>("Level")
.HasColumnType("int");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("TicketPriorityMasters");
b.HasData(
new
{
Id = new Guid("188d29b3-10f3-42d0-9587-1a46ae7a0320"),
ColorCode = "008000",
IsDefault = true,
Level = 1,
Name = "Low",
TenantId = 1
},
new
{
Id = new Guid("0919bc84-9f82-4ecf-98c7-962755dd9a97"),
ColorCode = "FFFF00",
IsDefault = true,
Level = 2,
Name = "Medium",
TenantId = 1
},
new
{
Id = new Guid("a13b7e59-16fd-4665-b5cf-a97399e8445a"),
ColorCode = "#FFA500",
IsDefault = true,
Level = 3,
Name = "High",
TenantId = 1
},
new
{
Id = new Guid("f340fbc3-c9fd-46aa-b063-0093418830e4"),
ColorCode = "#FFA500",
IsDefault = true,
Level = 4,
Name = "Critical",
TenantId = 1
},
new
{
Id = new Guid("44a7b91d-a0dd-45d1-8616-4d2f71e16401"),
ColorCode = "#FF0000",
IsDefault = true,
Level = 5,
Name = "Urgent",
TenantId = 1
});
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketStatusMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ColorCode")
.HasColumnType("longtext");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDefault")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("TicketStatusMasters");
b.HasData(
new
{
Id = new Guid("6b0c409b-3e80-4165-8b39-f3fcacb4c797"),
ColorCode = "#FFCC99",
Description = "This is a newly created issue.",
IsDefault = true,
Name = "New",
TenantId = 1
},
new
{
Id = new Guid("6c5ac37d-5b7d-40f3-adec-2dabaa5cca86"),
ColorCode = "#E6FF99",
Description = "Assigned to employee or team of employees",
IsDefault = true,
Name = "Assigned",
TenantId = 1
},
new
{
Id = new Guid("7f96bcd5-0c66-411b-8a1d-9d1a4785194e"),
ColorCode = "#99E6FF",
Description = "These issues are currently in progress",
IsDefault = true,
Name = "In Progress",
TenantId = 1
},
new
{
Id = new Guid("5c72b630-6923-4215-bf2c-b1622afd76e7"),
ColorCode = "#6c757d",
Description = "These issues are currently under review",
IsDefault = true,
Name = "In Review",
TenantId = 1
},
new
{
Id = new Guid("8ff85685-a875-4f21-aa95-d99551315fcc"),
ColorCode = "#B399FF",
Description = "The following issues are resolved and closed",
IsDefault = true,
Name = "Done",
TenantId = 1
});
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b =>
{
b.Property<int>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("int");
MySqlPropertyBuilderExtensions.UseMySqlIdentityColumn(b.Property<int>("Id"));
b.Property<Guid>("TagId")
.HasColumnType("char(36)");
b.Property<Guid>("TicketId")
.HasColumnType("char(36)");
b.HasKey("Id");
b.HasIndex("TagId");
b.HasIndex("TicketId");
b.ToTable("TicketTags");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTagMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("ColorCode")
.HasColumnType("longtext");
b.Property<bool>("IsDefault")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("TicketTagMasters");
b.HasData(
new
{
Id = new Guid("ef6c2a65-f61d-4537-9650-a7ab7f8d98db"),
ColorCode = "#e59866",
IsDefault = true,
Name = "Quality Issue",
TenantId = 1
},
new
{
Id = new Guid("5a168569-8ad7-4422-8db6-51ef25caddeb"),
ColorCode = "#85c1e9",
IsDefault = true,
Name = "Help Desk",
TenantId = 1
});
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTypeMaster", b =>
{
b.Property<Guid>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("char(36)");
b.Property<string>("Description")
.HasColumnType("longtext");
b.Property<bool>("IsDefault")
.HasColumnType("tinyint(1)");
b.Property<string>("Name")
.IsRequired()
.HasColumnType("longtext");
b.Property<int>("TenantId")
.HasColumnType("int");
b.HasKey("Id");
b.ToTable("TicketTypeMasters");
b.HasData(
new
{
Id = new Guid("c74e5480-2b71-483c-8f4a-1a9c69c32603"),
Description = "An identified problem that affects the performance, reliability, or standards of a product or service",
IsDefault = true,
Name = "Quality Issue",
TenantId = 1
},
new
{
Id = new Guid("d1f55eab-9898-4e46-9f03-b263e33e5d38"),
Description = "A support service that assists users with technical issues, requests, or inquiries.",
IsDefault = true,
Name = "Help Desk",
TenantId = 1
});
});
modelBuilder.Entity("Marco.Pms.Model.Industries.Industry", b => modelBuilder.Entity("Marco.Pms.Model.Industries.Industry", b =>
{ {
b.Property<int>("Id") b.Property<int>("Id")
@ -1756,6 +2167,10 @@ namespace Marco.Pms.DataAccess.Migrations
.OnDelete(DeleteBehavior.Cascade) .OnDelete(DeleteBehavior.Cascade)
.IsRequired(); .IsRequired();
b.HasOne("Marco.Pms.Model.DocumentManager.Document", "Document")
.WithMany()
.HasForeignKey("DocumentId");
b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee") b.HasOne("Marco.Pms.Model.Employees.Employee", "Employee")
.WithMany() .WithMany()
.HasForeignKey("EmployeeID") .HasForeignKey("EmployeeID")
@ -1774,6 +2189,8 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("Attendance"); b.Navigation("Attendance");
b.Navigation("Document");
b.Navigation("Employee"); b.Navigation("Employee");
b.Navigation("Tenant"); b.Navigation("Tenant");
@ -1791,6 +2208,17 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("User"); b.Navigation("User");
}); });
modelBuilder.Entity("Marco.Pms.Model.DocumentManager.Document", b =>
{
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b => modelBuilder.Entity("Marco.Pms.Model.Employees.Employee", b =>
{ {
b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser") b.HasOne("Marco.Pms.Model.Entitlements.ApplicationUser", "ApplicationUser")
@ -1940,6 +2368,90 @@ namespace Marco.Pms.DataAccess.Migrations
b.Navigation("Industry"); b.Navigation("Industry");
}); });
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketAttachment", b =>
{
b.HasOne("Marco.Pms.Model.Forum.TicketComment", "TicketComment")
.WithMany("Attachments")
.HasForeignKey("CommentId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket")
.WithMany()
.HasForeignKey("TicketId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Ticket");
b.Navigation("TicketComment");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b =>
{
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Tenant");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketForum", b =>
{
b.HasOne("Marco.Pms.Model.Forum.TicketPriorityMaster", "Priority")
.WithMany()
.HasForeignKey("PriorityId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Forum.TicketStatusMaster", "TicketStatusMaster")
.WithMany()
.HasForeignKey("StatusId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
.WithMany()
.HasForeignKey("TenantId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Forum.TicketTypeMaster", "TicketTypeMaster")
.WithMany()
.HasForeignKey("TypeId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Priority");
b.Navigation("Tenant");
b.Navigation("TicketStatusMaster");
b.Navigation("TicketTypeMaster");
});
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketTag", b =>
{
b.HasOne("Marco.Pms.Model.Forum.TicketTagMaster", "Tag")
.WithMany()
.HasForeignKey("TagId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.HasOne("Marco.Pms.Model.Forum.TicketForum", "Ticket")
.WithMany()
.HasForeignKey("TicketId")
.OnDelete(DeleteBehavior.Cascade)
.IsRequired();
b.Navigation("Tag");
b.Navigation("Ticket");
});
modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b => modelBuilder.Entity("Marco.Pms.Model.Projects.Building", b =>
{ {
b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant") b.HasOne("Marco.Pms.Model.Entitlements.Tenant", "Tenant")
@ -2117,6 +2629,11 @@ namespace Marco.Pms.DataAccess.Migrations
{ {
b.Navigation("FeaturePermissions"); b.Navigation("FeaturePermissions");
}); });
modelBuilder.Entity("Marco.Pms.Model.Forum.TicketComment", b =>
{
b.Navigation("Attachments");
});
#pragma warning restore 612, 618 #pragma warning restore 612, 618
} }
} }

View File

@ -1,5 +1,6 @@
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using Marco.Pms.Model.DocumentManager;
using Marco.Pms.Model.Dtos.Attendance; using Marco.Pms.Model.Dtos.Attendance;
using Marco.Pms.Model.Employees; using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Entitlements; using Marco.Pms.Model.Entitlements;
@ -41,6 +42,10 @@ namespace Marco.Pms.Model.AttendanceModule
[ValidateNever] [ValidateNever]
public Employee? UpdatedByEmployee { get; set; } public Employee? UpdatedByEmployee { get; set; }
public Guid? DocumentId { get; set; }
[ForeignKey("DocumentId")]
[ValidateNever]
public Document? Document { get; set; }
[DisplayName("TenantId")] [DisplayName("TenantId")]
public int TenantId { get; set; } public int TenantId { get; set; }

View File

@ -1,13 +1,13 @@
using Marco.Pms.Model.Entitlements; using System.ComponentModel.DataAnnotations.Schema;
using Marco.Pms.Model.Entitlements;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema;
namespace Marco.Pms.Model.DocumentManager namespace Marco.Pms.Model.DocumentManager
{ {
public class Document public class Document
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public Guid BatchId { get; set; } public Guid? BatchId { get; set; }
public string FileName { get; set; } = string.Empty; public string FileName { get; set; } = string.Empty;
/// <summary> /// <summary>
/// Full S3 object key /// Full S3 object key
@ -18,7 +18,9 @@ namespace Marco.Pms.Model.DocumentManager
/// </summary> /// </summary>
public string? ThumbS3Key { get; set; } public string? ThumbS3Key { get; set; }
public int FileSize { get; set; } public string? Base64Data { get; set; }
public long FileSize { get; set; }
public string ContentType { get; set; } = string.Empty; public string ContentType { get; set; } = string.Empty;
public DateTime UploadedAt { get; set; } public DateTime UploadedAt { get; set; }

View File

@ -18,7 +18,7 @@ namespace Marco.Pms.Model.Dtos.Attendance
public ATTENDANCE_MARK_TYPE Action { get; set; } public ATTENDANCE_MARK_TYPE Action { get; set; }
public List<FileUploadModel>? Image { get; set; } public FileUploadModel? Image { get; set; }
} }
public enum ATTENDANCE_MARK_TYPE public enum ATTENDANCE_MARK_TYPE

View File

@ -1,5 +1,5 @@
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations.Schema; using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Marco.Pms.Model.Forum namespace Marco.Pms.Model.Forum
{ {

View File

@ -1,7 +1,7 @@
using Marco.Pms.Model.Entitlements; using System.ComponentModel;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel; using Marco.Pms.Model.Entitlements;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
namespace Marco.Pms.Model.Forum namespace Marco.Pms.Model.Forum
{ {
@ -18,19 +18,19 @@ namespace Marco.Pms.Model.Forum
[ValidateNever] [ValidateNever]
[ForeignKey(nameof(TypeId))] [ForeignKey(nameof(TypeId))]
public TicketTypeMaster? TicketTypeMaster { get; set; } public TicketTypeMaster? TicketTypeMaster { get; set; }
public Guid CreatedById { get; set; } public int CreatedById { get; set; }
public DateTime CreatedAt { get; set; } public DateTime CreatedAt { get; set; }
public Guid? LinkedActivityId { get; set; } // task or project ID public int LinkedActivityId { get; set; } // task or project ID
public ICollection<TicketComment>? Comments { get; set; } //public ICollection<TicketComment>? Comments { get; set; } // view model
public ICollection<TicketAttachment>? Attachments { get; set; } //public ICollection<TicketAttachment>? Attachments { get; set; } // view model
public Guid PriorityId { get; set; } public Guid PriorityId { get; set; }
[ValidateNever] [ValidateNever]
[ForeignKey(nameof(PriorityId))] [ForeignKey(nameof(PriorityId))]
public TicketPriorityMaster? Priority { get; set; } public TicketPriorityMaster? Priority { get; set; }
public ICollection<TicketTag>? Tags { get; set; } //public ICollection<TicketTag>? Tags { get; set; } // view model
[DisplayName("TenantId")] [DisplayName("TenantId")]

View File

@ -1,19 +1,13 @@
using System; namespace Marco.Pms.Model.Forum
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Marco.Pms.Model.Forum
{ {
public class TicketPriorityMaster public class TicketPriorityMaster
{ {
public Guid Id { get; set; } public Guid Id { get; set; }
public string Name { get; set; } // e.g., Low, Medium, High, Critical public string Name { get; set; } = string.Empty; // e.g., Low, Medium, High, Critical
public int Level { get; set; } // 1 = Low, 2 = Medium... public int Level { get; set; } // 1 = Low, 2 = Medium...
public string? ColorCode { get; set; } public string? ColorCode { get; set; }
public bool IsDefault { get; set; } public bool IsDefault { get; set; }
public Guid TenantId { get; set; } public int TenantId { get; set; }
} }
} }

View File

@ -7,7 +7,7 @@
public string? Description { get; set; } public string? Description { get; set; }
public string? ColorCode { get; set; } // e.g., "#FF0000" public string? ColorCode { get; set; } // e.g., "#FF0000"
public bool IsDefault { get; set; } // true for system defaults public bool IsDefault { get; set; } // true for system defaults
public Guid TenantId { get; set; } // or nullable if global public int TenantId { get; set; } // or nullable if global
} }
} }

View File

@ -2,11 +2,12 @@
{ {
public class TicketTag public class TicketTag
{ {
public int Id { get; set; }
public Guid TicketId { get; set; } public Guid TicketId { get; set; }
public TicketForum Ticket { get; set; } public TicketForum Ticket { get; set; } = new TicketForum();
public Guid TagId { get; set; } public Guid TagId { get; set; }
public TicketTagMaster Tag { get; set; } public TicketTagMaster Tag { get; set; } = new TicketTagMaster();
} }
} }

View File

@ -5,7 +5,7 @@
public Guid Id { get; set; } public Guid Id { get; set; }
public string Name { get; set; } = string.Empty; // e.g., "Bug", "UI", "Urgent" public string Name { get; set; } = string.Empty; // e.g., "Bug", "UI", "Urgent"
public string? ColorCode { get; set; } public string? ColorCode { get; set; }
public Guid TenantId { get; set; } public int TenantId { get; set; }
public bool IsDefault { get; set; } public bool IsDefault { get; set; }
} }

View File

@ -6,7 +6,7 @@
public string Name { get; set; } = string.Empty; // e.g., "Quality Issue" public string Name { get; set; } = string.Empty; // e.g., "Quality Issue"
public string? Description { get; set; } public string? Description { get; set; }
public bool IsDefault { get; set; } // true for system defaults public bool IsDefault { get; set; } // true for system defaults
public Guid TenantId { get; set; } public int TenantId { get; set; }
} }
} }

View File

@ -0,0 +1,10 @@
namespace Marco.Pms.Model.Utilities
{
public class AWSSettings
{
public string AccessKey { get; set; } = string.Empty;
public string SecretKey { get; set; } = string.Empty;
public string Region { get; set; } = string.Empty;
public string BucketName { get; set; } = string.Empty;
}
}

View File

@ -14,5 +14,11 @@ namespace Marco.Pms.Model.ViewModels.Attendance
public string? JobRoleName { get; set; } public string? JobRoleName { get; set; }
public ATTENDANCE_MARK_TYPE Activity { get; set; } public ATTENDANCE_MARK_TYPE Activity { get; set; }
public string? ThumbPreSignedUrl { get; set; }
public string? PreSignedUrl { get; set; }
} }
} }

View File

@ -6,13 +6,17 @@ using Marco.Pms.Model.Employees;
using Marco.Pms.Model.Projects; using Marco.Pms.Model.Projects;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Model.ViewModels.Attendance; using Marco.Pms.Model.ViewModels.Attendance;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Helpers;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
using Document = Marco.Pms.Model.DocumentManager.Document;
namespace MarcoBMS.Services.Controllers namespace MarcoBMS.Services.Controllers
{ {
[Authorize]
[ApiController] [ApiController]
[Route("api/[controller]")] [Route("api/[controller]")]
public class AttendanceController : ControllerBase public class AttendanceController : ControllerBase
@ -21,15 +25,17 @@ namespace MarcoBMS.Services.Controllers
private readonly EmployeeHelper _employeeHelper; private readonly EmployeeHelper _employeeHelper;
private readonly ProjectsHelper _projectsHelper; private readonly ProjectsHelper _projectsHelper;
private readonly UserHelper _userHelper; private readonly UserHelper _userHelper;
private readonly S3UploadService _s3Service;
public AttendanceController( public AttendanceController(
ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper) ApplicationDbContext context, EmployeeHelper employeeHelper, ProjectsHelper projectsHelper, UserHelper userHelper, S3UploadService s3Service)
{ {
_context = context; _context = context;
_employeeHelper = employeeHelper; _employeeHelper = employeeHelper;
_projectsHelper = projectsHelper; _projectsHelper = projectsHelper;
_userHelper = userHelper; _userHelper = userHelper;
_s3Service = s3Service;
} }
private int GetTenantId() private int GetTenantId()
@ -101,7 +107,7 @@ namespace MarcoBMS.Services.Controllers
Attendance? attendance = null; Attendance? attendance = null;
if (dateFrom == null) fromDate = DateTime.UtcNow.Date; if (dateFrom == null) fromDate = DateTime.UtcNow.Date;
if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1); if (dateTo == null && dateFrom != null) toDate = fromDate.AddDays(-1);
List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date <= fromDate && c.AttendanceDate.Date >= toDate && c.TenantId == TenantId).ToListAsync(); List<Attendance> lstAttendance = await _context.Attendes.Where(c => c.ProjectID == projectId && c.AttendanceDate.Date <= fromDate && c.AttendanceDate.Date >= toDate && c.TenantId == TenantId).ToListAsync();
@ -199,7 +205,8 @@ namespace MarcoBMS.Services.Controllers
} }
} }
result.Sort(delegate (EmployeeAttendanceVM x, EmployeeAttendanceVM y) { result.Sort(delegate (EmployeeAttendanceVM x, EmployeeAttendanceVM y)
{
//return x.FirstName.CompareTo(y.FirstName); //return x.FirstName.CompareTo(y.FirstName);
return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal); return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
}); });
@ -223,29 +230,30 @@ namespace MarcoBMS.Services.Controllers
foreach (Attendance attende in lstAttendance) foreach (Attendance attende in lstAttendance)
{ {
var result1 = new EmployeeAttendanceVM() var result1 = new EmployeeAttendanceVM()
{ {
Id = attende.Id, Id = attende.Id,
CheckInTime = attende.InTime, CheckInTime = attende.InTime,
CheckOutTime = attende.OutTime, CheckOutTime = attende.OutTime,
Activity = attende.Activity, Activity = attende.Activity,
EmployeeAvatar = null, EmployeeAvatar = null,
EmployeeId = attende.EmployeeID, EmployeeId = attende.EmployeeID,
}; };
var teamMember = projectteam.Find(m => m.EmployeeId == attende.EmployeeID); var teamMember = projectteam.Find(m => m.EmployeeId == attende.EmployeeID);
if (teamMember != null && teamMember.Employee.JobRole != null) if (teamMember != null && teamMember.Employee.JobRole != null)
{ {
result1.FirstName = teamMember.Employee.FirstName; result1.FirstName = teamMember.Employee.FirstName;
result1.LastName = teamMember.Employee.LastName; result1.LastName = teamMember.Employee.LastName;
result1.JobRoleName = teamMember.Employee.JobRole.Name; result1.JobRoleName = teamMember.Employee.JobRole.Name;
} }
result.Add(result1); result.Add(result1);
} }
result.Sort(delegate (EmployeeAttendanceVM x, EmployeeAttendanceVM y) { result.Sort(delegate (EmployeeAttendanceVM x, EmployeeAttendanceVM y)
{
return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal); return string.Compare(x.FirstName, y.FirstName, StringComparison.Ordinal);
}); });
@ -273,7 +281,7 @@ namespace MarcoBMS.Services.Controllers
{ {
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ; Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ;
if (recordAttendanceDot.MarkTime == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time",400)); if (recordAttendanceDot.MarkTime == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime); DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
if (recordAttendanceDot.Comment == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400)); if (recordAttendanceDot.Comment == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
@ -372,7 +380,7 @@ namespace MarcoBMS.Services.Controllers
await transaction.CommitAsync(); // Commit transaction await transaction.CommitAsync(); // Commit transaction
Employee employee = await _employeeHelper.GetEmployeeByID(recordAttendanceDot.EmployeeID); Employee employee = await _employeeHelper.GetEmployeeByID(recordAttendanceDot.EmployeeID);
if(employee.JobRole != null) if (employee.JobRole != null)
{ {
EmployeeAttendanceVM vm = new EmployeeAttendanceVM() EmployeeAttendanceVM vm = new EmployeeAttendanceVM()
{ {
@ -400,6 +408,192 @@ namespace MarcoBMS.Services.Controllers
} }
[HttpPost]
[Route("record-image")]
public async Task<IActionResult> RecordAttendanceWithImage([FromBody] RecordAttendanceDot recordAttendanceDot)
{
if (!ModelState.IsValid)
{
var errors = ModelState.Values
.SelectMany(v => v.Errors)
.Select(e => e.ErrorMessage)
.ToList();
return BadRequest(ApiResponse<object>.ErrorResponse("Invalid data", errors, 400));
}
int TenantId = GetTenantId();
using var transaction = await _context.Database.BeginTransactionAsync();
try
{
Attendance? attendance = await _context.Attendes.FirstOrDefaultAsync(a => a.Id == recordAttendanceDot.Id && a.TenantId == TenantId); ;
if (recordAttendanceDot.MarkTime == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Mark Time", "Invalid Mark Time", 400));
DateTime finalDateTime = GetDateFromTimeStamp(recordAttendanceDot.Date, recordAttendanceDot.MarkTime);
if (recordAttendanceDot.Comment == null) return BadRequest(ApiResponse<object>.ErrorResponse("Invalid Comment", "Invalid Comment", 400));
if (attendance != null)
{
attendance.Comment = recordAttendanceDot.Comment;
if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_IN)
{
attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
}
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.CHECK_OUT)
{
attendance.IsApproved = true;
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
//string timeString = "10:30 PM"; // Format: "hh:mm tt"
attendance.OutTime = finalDateTime;
}
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE)
{
DateTime date = attendance.AttendanceDate;
finalDateTime = GetDateFromTimeStamp(date.Date, recordAttendanceDot.MarkTime);
attendance.OutTime = finalDateTime;
attendance.Activity = ATTENDANCE_MARK_TYPE.REQUEST_REGULARIZE;
// do nothing
}
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.REGULARIZE)
{
attendance.IsApproved = true;
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE;
// do nothing
}
else if (recordAttendanceDot.Action == ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT)
{
attendance.IsApproved = false;
attendance.Activity = ATTENDANCE_MARK_TYPE.REGULARIZE_REJECT;
// do nothing
}
attendance.Date = DateTime.UtcNow;
// update code
_context.Attendes.Update(attendance);
}
else
{
attendance = new Attendance();
attendance.TenantId = TenantId;
attendance.AttendanceDate = recordAttendanceDot.Date;
// attendance.Activity = recordAttendanceDot.Action;
attendance.Comment = recordAttendanceDot.Comment;
attendance.EmployeeID = recordAttendanceDot.EmployeeID;
attendance.ProjectID = recordAttendanceDot.ProjectID;
attendance.Date = DateTime.UtcNow;
attendance.InTime = finalDateTime;
attendance.OutTime = null;
attendance.Activity = ATTENDANCE_MARK_TYPE.CHECK_OUT;
_context.Attendes.Add(attendance);
}
byte[] fileBytes;
var Image = recordAttendanceDot.Image;
if (string.IsNullOrEmpty(Image.Base64Data))
return BadRequest(ApiResponse<object>.ErrorResponse("Base64 data is missing", "Base64 data is missing", 400));
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception ex)
{
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400)); ;
}
using var stream = new MemoryStream(fileBytes);
var objectKey = await _s3Service.UploadFileAsync(stream, Image.FileName, Image.ContentType);
var preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
Document document = new Document
{
FileName = Image.FileName,
ContentType = Image.ContentType,
S3Key = objectKey,
Base64Data = Image.Base64Data,
FileSize = Image.FileSize,
UploadedAt = recordAttendanceDot.Date,
TenantId = TenantId
};
_context.Documents.Add(document);
await _context.SaveChangesAsync();
// Step 3: Always insert a new log entry
var attendanceLog = new AttendanceLog
{
AttendanceId = attendance.Id, // Use existing or new AttendanceId
Activity = attendance.Activity,
ActivityTime = finalDateTime,
Comment = recordAttendanceDot.Comment,
EmployeeID = recordAttendanceDot.EmployeeID,
Latitude = recordAttendanceDot.Latitude,
Longitude = recordAttendanceDot.Longitude,
DocumentId = document.Id,
TenantId = TenantId,
UpdatedBy = recordAttendanceDot.EmployeeID,
UpdatedOn = recordAttendanceDot.Date
};
//if (recordAttendanceDot.Image != null && recordAttendanceDot.Image.Count > 0)
//{
// attendanceLog.Photo = recordAttendanceDot.Image[0].Base64Data;
//}
_context.AttendanceLogs.Add(attendanceLog);
await _context.SaveChangesAsync();
await transaction.CommitAsync(); // Commit transaction
Employee employee = await _employeeHelper.GetEmployeeByID(recordAttendanceDot.EmployeeID);
if (employee.JobRole != null)
{
EmployeeAttendanceVM vm = new EmployeeAttendanceVM()
{
CheckInTime = attendance.InTime,
CheckOutTime = attendance.OutTime,
EmployeeAvatar = null,
EmployeeId = recordAttendanceDot.EmployeeID,
FirstName = employee.FirstName,
LastName = employee.LastName,
Id = attendance.Id,
Activity = attendance.Activity,
JobRoleName = employee.JobRole.Name,
ThumbPreSignedUrl = preSignedUrl,
PreSignedUrl = preSignedUrl
};
return Ok(ApiResponse<object>.SuccessResponse(vm, "Attendance marked successfully.", 200));
}
return Ok(ApiResponse<object>.SuccessResponse(new EmployeeAttendanceVM(), "Attendance marked successfully.", 200));
}
catch (Exception ex)
{
await transaction.RollbackAsync(); // Rollback on failure
return BadRequest(ApiResponse<object>.ErrorResponse(ex.Message, ex, 400));
}
}
private static DateTime GetDateFromTimeStamp(DateTime date, string timeString) private static DateTime GetDateFromTimeStamp(DateTime date, string timeString)
{ {
//DateTime date = recordAttendanceDot.Date; //DateTime date = recordAttendanceDot.Date;

View File

@ -1,3 +1,5 @@
using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
namespace MarcoBMS.Services.Controllers namespace MarcoBMS.Services.Controllers
@ -12,10 +14,12 @@ namespace MarcoBMS.Services.Controllers
}; };
private readonly ILogger<WeatherForecastController> _logger; private readonly ILogger<WeatherForecastController> _logger;
private readonly S3UploadService _s3Service;
public WeatherForecastController(ILogger<WeatherForecastController> logger) public WeatherForecastController(ILogger<WeatherForecastController> logger, S3UploadService s3Service)
{ {
_logger = logger; _logger = logger;
_s3Service = s3Service;
} }
[HttpGet(Name = "GetWeatherForecast")] [HttpGet(Name = "GetWeatherForecast")]
@ -29,5 +33,41 @@ namespace MarcoBMS.Services.Controllers
}) })
.ToArray(); .ToArray();
} }
[HttpPost("upload-image")]
public async Task<IActionResult> SendToSThree([FromBody] FileUploadModel Image)
{
if (string.IsNullOrEmpty(Image.Base64Data))
return BadRequest("Base64 data is missing");
byte[] fileBytes;
try
{
//If base64 has a data URI prefix, strip it
var base64 = Image.Base64Data.Contains(",")
? Image.Base64Data.Substring(Image.Base64Data.IndexOf(",") + 1)
: Image.Base64Data;
fileBytes = Convert.FromBase64String(base64);
}
catch (Exception error)
{
//return BadRequest("Invalid base64 string.");
return BadRequest(error);
}
using var stream = new MemoryStream(fileBytes);
var objectKey = await _s3Service.UploadFileAsync(stream, Image.FileName, Image.ContentType);
//var objectKey = await _s3Service.UploadFileAsync(Image.FileName, Image.ContentType);
var preSignedUrl = await _s3Service.GeneratePreSignedUrlAsync(objectKey);
return Ok(new
{
objectKey,
url = preSignedUrl
});
}
} }
} }

View File

@ -11,6 +11,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AWSSDK.S3" Version="3.7.416.13" />
<PackageReference Include="MailKit" Version="4.9.0" /> <PackageReference Include="MailKit" Version="4.9.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.20" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.12" /> <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.12" />

View File

@ -1,6 +1,8 @@
using System.Text;
using Marco.Pms.DataAccess.Data; using Marco.Pms.DataAccess.Data;
using Marco.Pms.Model.Authentication; using Marco.Pms.Model.Authentication;
using Marco.Pms.Model.Utilities; using Marco.Pms.Model.Utilities;
using Marco.Pms.Services.Service;
using MarcoBMS.Services.Helpers; using MarcoBMS.Services.Helpers;
using MarcoBMS.Services.Middleware; using MarcoBMS.Services.Middleware;
using MarcoBMS.Services.Service; using MarcoBMS.Services.Service;
@ -10,7 +12,6 @@ using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi.Models;
using Serilog; using Serilog;
using System.Text;
var builder = WebApplication.CreateBuilder(args); var builder = WebApplication.CreateBuilder(args);
@ -87,6 +88,9 @@ builder.Services.AddSwaggerGen(option =>
builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("EmailSettings")); builder.Services.Configure<SmtpSettings>(builder.Configuration.GetSection("EmailSettings"));
builder.Services.AddTransient<IEmailSender, EmailSender>(); builder.Services.AddTransient<IEmailSender, EmailSender>();
builder.Services.Configure<AWSSettings>(builder.Configuration.GetSection("AWS")); // For uploading images to aws s3
builder.Services.AddTransient<S3UploadService>();
builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders(); builder.Services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>().AddDefaultTokenProviders();
@ -96,10 +100,7 @@ builder.Services.AddDbContext<ApplicationDbContext>(options =>
{ {
options.UseMySql(connString, ServerVersion.AutoDetect(connString)); options.UseMySql(connString, ServerVersion.AutoDetect(connString));
}); });
builder.Services.AddDbContext<ForumDbContext>(options =>
{
options.UseMySql(connString, ServerVersion.AutoDetect(connString));
});
builder.Services.AddMemoryCache(); builder.Services.AddMemoryCache();
@ -123,7 +124,7 @@ builder.Services.AddSingleton<ILoggingService, LoggingService>();
builder.Services.AddHttpContextAccessor(); builder.Services.AddHttpContextAccessor();
var jwtSettings = builder.Configuration.GetSection("Jwt").Get<JwtSettings>(); var jwtSettings = builder.Configuration.GetSection("Jwt").Get<JwtSettings>();
if(jwtSettings != null && jwtSettings.Key != null) if (jwtSettings != null && jwtSettings.Key != null)
{ {
builder.Services.AddAuthentication(options => builder.Services.AddAuthentication(options =>
{ {
@ -166,7 +167,8 @@ if (app.Environment.IsDevelopment())
app.UseSwaggerUI(); app.UseSwaggerUI();
// Use CORS in the pipeline // Use CORS in the pipeline
app.UseCors("DevCorsPolicy"); app.UseCors("DevCorsPolicy");
}else }
else
{ {
//if (app.Environment.IsProduction()) //if (app.Environment.IsProduction())
//{ //{

View File

@ -0,0 +1,59 @@
using Amazon.S3;
using Amazon.S3.Model;
using Amazon.S3.Transfer;
using Marco.Pms.Model.Utilities;
using Microsoft.Extensions.Options;
namespace Marco.Pms.Services.Service
{
public class S3UploadService
{
private readonly IAmazonS3 _s3Client;
private readonly string _bucketName = "your-bucket-name";
public S3UploadService(IOptions<AWSSettings> awsOptions)
{
var settings = awsOptions.Value;
var region = Amazon.RegionEndpoint.GetBySystemName(settings.Region);
_bucketName = settings.BucketName;
_s3Client = new AmazonS3Client(settings.AccessKey, settings.SecretKey, region);
}
//public async Task<string> UploadFileAsync(string fileName, string contentType)
public async Task<string> UploadFileAsync(Stream fileStream, string fileName, string contentType)
{
// Generate a unique object key (you can customize this)
var objectKey = $"{Guid.NewGuid()}_{fileName}";
var uploadRequest = new TransferUtilityUploadRequest
{
InputStream = fileStream,
Key = objectKey,
BucketName = _bucketName,
ContentType = contentType,
AutoCloseStream = true
};
var transferUtility = new TransferUtility(_s3Client);
await transferUtility.UploadAsync(uploadRequest);
return objectKey;
}
public async Task<string> GeneratePreSignedUrlAsync(string objectKey)
{
int expiresInMinutes = 1;
var request = new GetPreSignedUrlRequest
{
BucketName = _bucketName,
Key = objectKey,
Expires = DateTime.UtcNow.AddMinutes(expiresInMinutes),
Verb = HttpVerb.GET // for download
};
string url = _s3Client.GetPreSignedURL(request);
return url;
}
}
}

View File

@ -96,7 +96,14 @@
"Password": "qrtq wfuj hwpp fhqr" "Password": "qrtq wfuj hwpp fhqr"
}, },
"Contact": { "Contact": {
"Emails": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com" //"Emails": "ashutosh.nehete@marcoaiot.com;vikas@marcoaiot.com;umesh@marcoait.com"
"Emails": "ashutosh.nehete@marcoaiot.com"
},
"AWS": {
"AccessKey": "AKIARZDBH3VDMSUUY2FX",
"SecretKey": "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",
"Region": "us-east-1",
"BucketName": "testenv-marco-pms-documents"
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 171 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 806 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 MiB