diff --git a/Marco.Pms.DataAccess/Data/ForumDbContext.cs b/Marco.Pms.DataAccess/Data/ForumDbContext.cs new file mode 100644 index 0000000..980887c --- /dev/null +++ b/Marco.Pms.DataAccess/Data/ForumDbContext.cs @@ -0,0 +1,32 @@ +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 + { + private readonly IHttpContextAccessor _httpContextAccessor; + + public ForumDbContext(DbContextOptions options, IHttpContextAccessor httpContextAccessor) : base(options) + { + _httpContextAccessor = httpContextAccessor; + + } + + public DbSet Tickets { get; set; } + public DbSet TicketAttachments { get; set; } + public DbSet TicketComments { get; set; } + public DbSet TicketStatusMasters { get; set; } + public DbSet TicketTypeMasters { get; set; } + + } +} diff --git a/Marco.Pms.Model/DocumentManager/Document.cs b/Marco.Pms.Model/DocumentManager/Document.cs new file mode 100644 index 0000000..6312d29 --- /dev/null +++ b/Marco.Pms.Model/DocumentManager/Document.cs @@ -0,0 +1,31 @@ +using Marco.Pms.Model.Entitlements; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.DocumentManager +{ + public class Document + { + public Guid Id { get; set; } + public Guid BatchId { get; set; } + public string FileName { get; set; } = string.Empty; + /// + /// Full S3 object key + /// + public string S3Key { get; set; } = string.Empty; + /// + /// S3 key for thumbnail image + /// + public string? ThumbS3Key { get; set; } + + public int FileSize { get; set; } + public string ContentType { get; set; } = string.Empty; + public DateTime UploadedAt { get; set; } + + public int TenantId { get; set; } + + [ValidateNever] + [ForeignKey(nameof(TenantId))] + public Tenant? Tenant { get; set; } + } +} diff --git a/Marco.Pms.Model/Dtos/Forum/AddCommentDto.cs b/Marco.Pms.Model/Dtos/Forum/AddCommentDto.cs new file mode 100644 index 0000000..c0772c9 --- /dev/null +++ b/Marco.Pms.Model/Dtos/Forum/AddCommentDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Marco.Pms.Model.Dtos.Forum +{ + public class AddCommentDto + { + } +} diff --git a/Marco.Pms.Model/Dtos/Forum/CreateTicketDto.cs b/Marco.Pms.Model/Dtos/Forum/CreateTicketDto.cs new file mode 100644 index 0000000..25967ec --- /dev/null +++ b/Marco.Pms.Model/Dtos/Forum/CreateTicketDto.cs @@ -0,0 +1,6 @@ +namespace Marco.Pms.Model.Dtos.Forum +{ + public class CreateTicketDto + { + } +} diff --git a/Marco.Pms.Model/Dtos/Forum/ForumAttachmentDto.cs b/Marco.Pms.Model/Dtos/Forum/ForumAttachmentDto.cs new file mode 100644 index 0000000..d392c4e --- /dev/null +++ b/Marco.Pms.Model/Dtos/Forum/ForumAttachmentDto.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Marco.Pms.Model.Dtos.Forum +{ + public class ForumAttachmentDto + { + } +} diff --git a/Marco.Pms.Model/Forum/TicketAttachment.cs b/Marco.Pms.Model/Forum/TicketAttachment.cs new file mode 100644 index 0000000..af776ae --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketAttachment.cs @@ -0,0 +1,21 @@ +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Marco.Pms.Model.Forum +{ + + public class TicketAttachment + { + public Guid Id { get; set; } + public Guid TicketId { get; set; } + [ValidateNever] + [ForeignKey(nameof(TicketId))] + public TicketForum? Ticket { get; set; } + public Guid CommentId { get; set; } + [ValidateNever] + [ForeignKey(nameof(CommentId))] + public TicketComment? TicketComment { get; set; } + public string FileName { get; set; } = string.Empty; + public Guid FileId { get; set; } + } +} diff --git a/Marco.Pms.Model/Forum/TicketComment.cs b/Marco.Pms.Model/Forum/TicketComment.cs new file mode 100644 index 0000000..7ed0e67 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketComment.cs @@ -0,0 +1,27 @@ +using Marco.Pms.Model.Entitlements; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel; + +namespace Marco.Pms.Model.Forum +{ + public class TicketComment + { + public Guid Id { get; set; } + public Guid TicketId { get; set; } + public Guid AuthorId { get; set; } + public string MessageText { get; set; } = string.Empty; + public DateTime SentAt { get; set; } + public Guid? ParentMessageId { get; set; } // For threaded replies + + public ICollection? Attachments { get; set; } + + [DisplayName("TenantId")] + public int TenantId { get; set; } + + [ValidateNever] + [ForeignKey(nameof(TenantId))] + public Tenant? Tenant { get; set; } + + } +} diff --git a/Marco.Pms.Model/Forum/TicketForum.cs b/Marco.Pms.Model/Forum/TicketForum.cs new file mode 100644 index 0000000..b46bd10 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketForum.cs @@ -0,0 +1,44 @@ +using Marco.Pms.Model.Entitlements; +using Microsoft.AspNetCore.Mvc.ModelBinding.Validation; +using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel; + +namespace Marco.Pms.Model.Forum +{ + public class TicketForum + { + public Guid Id { get; set; } + public string Subject { get; set; } = string.Empty; + public string Description { get; set; } = string.Empty; + public Guid StatusId { get; set; } + [ValidateNever] + [ForeignKey(nameof(StatusId))] + public TicketStatusMaster? TicketStatusMaster { get; set; } + public Guid TypeId { get; set; } // QualityIssue, HelpDesk, Feedback + [ValidateNever] + [ForeignKey(nameof(TypeId))] + public TicketTypeMaster? TicketTypeMaster { get; set; } + public Guid CreatedById { get; set; } + public DateTime CreatedAt { get; set; } + public Guid? LinkedActivityId { get; set; } // task or project ID + + public ICollection? Comments { get; set; } + public ICollection? Attachments { get; set; } + + public Guid PriorityId { get; set; } + [ValidateNever] + [ForeignKey(nameof(PriorityId))] + public TicketPriorityMaster? Priority { get; set; } + + public ICollection? Tags { get; set; } + + + [DisplayName("TenantId")] + public int TenantId { get; set; } + + [ValidateNever] + [ForeignKey(nameof(TenantId))] + public Tenant? Tenant { get; set; } + } + +} diff --git a/Marco.Pms.Model/Forum/TicketPriorityMaster.cs b/Marco.Pms.Model/Forum/TicketPriorityMaster.cs new file mode 100644 index 0000000..eed4c84 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketPriorityMaster.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Marco.Pms.Model.Forum +{ + public class TicketPriorityMaster + { + public Guid Id { get; set; } + public string Name { get; set; } // e.g., Low, Medium, High, Critical + public int Level { get; set; } // 1 = Low, 2 = Medium... + public string? ColorCode { get; set; } + public bool IsDefault { get; set; } + public Guid TenantId { get; set; } + } + +} diff --git a/Marco.Pms.Model/Forum/TicketStatusMaster.cs b/Marco.Pms.Model/Forum/TicketStatusMaster.cs new file mode 100644 index 0000000..1dfab31 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketStatusMaster.cs @@ -0,0 +1,13 @@ +namespace Marco.Pms.Model.Forum +{ + public class TicketStatusMaster + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; // e.g., "Open", "In Progress" + public string? Description { get; set; } + public string? ColorCode { get; set; } // e.g., "#FF0000" + public bool IsDefault { get; set; } // true for system defaults + public Guid TenantId { get; set; } // or nullable if global + } + +} diff --git a/Marco.Pms.Model/Forum/TicketTag.cs b/Marco.Pms.Model/Forum/TicketTag.cs new file mode 100644 index 0000000..08f5248 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketTag.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Forum +{ + public class TicketTag + { + public Guid TicketId { get; set; } + public TicketForum Ticket { get; set; } + + public Guid TagId { get; set; } + public TicketTagMaster Tag { get; set; } + } + +} diff --git a/Marco.Pms.Model/Forum/TicketTagMaster.cs b/Marco.Pms.Model/Forum/TicketTagMaster.cs new file mode 100644 index 0000000..7815c57 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketTagMaster.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Forum +{ + public class TicketTagMaster + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; // e.g., "Bug", "UI", "Urgent" + public string? ColorCode { get; set; } + public Guid TenantId { get; set; } + public bool IsDefault { get; set; } + } + +} diff --git a/Marco.Pms.Model/Forum/TicketTypeMaster.cs b/Marco.Pms.Model/Forum/TicketTypeMaster.cs new file mode 100644 index 0000000..0516ec9 --- /dev/null +++ b/Marco.Pms.Model/Forum/TicketTypeMaster.cs @@ -0,0 +1,12 @@ +namespace Marco.Pms.Model.Forum +{ + public class TicketTypeMaster + { + public Guid Id { get; set; } + public string Name { get; set; } = string.Empty; // e.g., "Quality Issue" + public string? Description { get; set; } + public bool IsDefault { get; set; } // true for system defaults + public Guid TenantId { get; set; } + } + +} diff --git a/Marco.Pms.Model/ViewModels/Forum/ForumTicketVM.cs b/Marco.Pms.Model/ViewModels/Forum/ForumTicketVM.cs new file mode 100644 index 0000000..aa83753 --- /dev/null +++ b/Marco.Pms.Model/ViewModels/Forum/ForumTicketVM.cs @@ -0,0 +1,6 @@ +namespace Marco.Pms.Model.ViewModels.Forum +{ + public class ForumTicketVM + { + } +} diff --git a/Marco.Pms.Services/Controllers/ForumController.cs b/Marco.Pms.Services/Controllers/ForumController.cs new file mode 100644 index 0000000..8b45d4f --- /dev/null +++ b/Marco.Pms.Services/Controllers/ForumController.cs @@ -0,0 +1,73 @@ +using Marco.Pms.DataAccess.Data; +using Marco.Pms.Model.Authentication; +using Marco.Pms.Model.Dtos.Forum; +using Marco.Pms.Model.Dtos.Util; +using Marco.Pms.Model.Industries; +using Marco.Pms.Model.Utilities; +using MarcoBMS.Services.Helpers; +using MarcoBMS.Services.Service; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; + +namespace Marco.Pms.Services.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class ForumController : ControllerBase + { + private readonly UserManager _userManager; + private readonly ApplicationDbContext _context; + private readonly JwtSettings _jwtSettings; + private readonly RefreshTokenService _refreshTokenService; + private readonly IEmailSender _emailSender; + private readonly IConfiguration _configuration; + private readonly EmployeeHelper _employeeHelper; + //string tenentId = "1"; + public ForumController(UserManager userManager, ApplicationDbContext context, JwtSettings jwtSettings, RefreshTokenService refreshTokenService, + IEmailSender emailSender, IConfiguration configuration, EmployeeHelper employeeHelper) + { + _userManager = userManager; + _jwtSettings = jwtSettings; + _refreshTokenService = refreshTokenService; + _emailSender = emailSender; + _configuration = configuration; + _employeeHelper = employeeHelper; + _context = context; + } + + [HttpPost("tickets")] + public async Task CreateNewTicket([FromBody] CreateTicketDto createTicketDto) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + + [HttpPost("tickets/{id}/comment")] + public async Task AddComment([FromBody] AddCommentDto addCommentDto) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + + [HttpPost("tickets/{id}/attachments")] + public async Task UploadAttachments([FromBody] ForumAttachmentDto forumAttachmentDto) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + + [HttpPatch("tickets/{id}/status")] + public async Task UpdateTicketStatus([FromBody] InquiryDto inquiryDto) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + [HttpGet("tickets/{id}")] + public async Task GetTicketDetail(Guid id) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + + [HttpGet("tickets")] + public async Task ListTickets([FromBody] InquiryDto inquiryDto) + { + return NotFound(ApiResponse.ErrorResponse("Industry not found.", "Industry not found.", 404)); + } + } +} diff --git a/Marco.Pms.Services/Program.cs b/Marco.Pms.Services/Program.cs index 6f45552..71a7555 100644 --- a/Marco.Pms.Services/Program.cs +++ b/Marco.Pms.Services/Program.cs @@ -96,6 +96,10 @@ builder.Services.AddDbContext(options => { options.UseMySql(connString, ServerVersion.AutoDetect(connString)); }); +builder.Services.AddDbContext(options => +{ + options.UseMySql(connString, ServerVersion.AutoDetect(connString)); +}); builder.Services.AddMemoryCache();