mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 07:13:12 +00:00
Add Task List Templates with CRUD controller
- TaskListTemplate and TaskListTemplateItem models - TaskListTemplateController: list, get by ID, create with items, update (replace items), soft delete - Migration for new tables
This commit is contained in:
parent
63f76e9b2c
commit
1f4bd12cd7
8 changed files with 2979 additions and 0 deletions
146
Api.SeaHavenIndustries/Controllers/TaskListTemplateController.cs
Normal file
146
Api.SeaHavenIndustries/Controllers/TaskListTemplateController.cs
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
using Api.SeaHavenIndustries.DTOs;
|
||||||
|
using Data.SeaHavenIndustries;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace Api.SeaHavenIndustries.Controllers
|
||||||
|
{
|
||||||
|
[Authorize]
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[Route("api/tasklisttemplates")]
|
||||||
|
public class TaskListTemplateController : Controller
|
||||||
|
{
|
||||||
|
private readonly ApplicationDbContext _db;
|
||||||
|
|
||||||
|
public TaskListTemplateController(ApplicationDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<IActionResult> GetAll()
|
||||||
|
{
|
||||||
|
var data = await _db.TaskListTemplates
|
||||||
|
.Where(t => t.IsActive)
|
||||||
|
.Include(t => t.Items.OrderBy(i => i.SortOrder))
|
||||||
|
.OrderBy(t => t.Name)
|
||||||
|
.Select(t => new
|
||||||
|
{
|
||||||
|
t.Id,
|
||||||
|
t.Name,
|
||||||
|
t.Description,
|
||||||
|
t.IsActive,
|
||||||
|
items = t.Items.OrderBy(i => i.SortOrder).Select(i => new
|
||||||
|
{
|
||||||
|
i.Id,
|
||||||
|
i.ItemText,
|
||||||
|
i.SortOrder
|
||||||
|
}).ToList()
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
return Ok(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("{id}")]
|
||||||
|
public async Task<IActionResult> GetById(int id)
|
||||||
|
{
|
||||||
|
var template = await _db.TaskListTemplates
|
||||||
|
.Include(t => t.Items.OrderBy(i => i.SortOrder))
|
||||||
|
.Where(t => t.Id == id)
|
||||||
|
.Select(t => new
|
||||||
|
{
|
||||||
|
t.Id,
|
||||||
|
t.Name,
|
||||||
|
t.Description,
|
||||||
|
t.IsActive,
|
||||||
|
items = t.Items.OrderBy(i => i.SortOrder).Select(i => new
|
||||||
|
{
|
||||||
|
i.Id,
|
||||||
|
i.ItemText,
|
||||||
|
i.SortOrder
|
||||||
|
}).ToList()
|
||||||
|
})
|
||||||
|
.FirstOrDefaultAsync();
|
||||||
|
|
||||||
|
if (template == null)
|
||||||
|
return NotFound(new Response { Status = "Error", Message = "Template not found" });
|
||||||
|
|
||||||
|
return Ok(template);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost]
|
||||||
|
public async Task<IActionResult> Create([FromBody] TaskListTemplate_DTO model)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var template = new TaskListTemplate
|
||||||
|
{
|
||||||
|
Name = model.Name,
|
||||||
|
Description = model.Description,
|
||||||
|
IsActive = model.IsActive,
|
||||||
|
Items = model.Items.Select((item, idx) => new TaskListTemplateItem
|
||||||
|
{
|
||||||
|
ItemText = item.ItemText,
|
||||||
|
SortOrder = item.SortOrder > 0 ? item.SortOrder : idx
|
||||||
|
}).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
_db.TaskListTemplates.Add(template);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
return Ok(new { message = "Template created", id = template.Id });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("{id}")]
|
||||||
|
public async Task<IActionResult> Update(int id, [FromBody] TaskListTemplate_DTO model)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var template = await _db.TaskListTemplates
|
||||||
|
.Include(t => t.Items)
|
||||||
|
.FirstOrDefaultAsync(t => t.Id == id);
|
||||||
|
|
||||||
|
if (template == null)
|
||||||
|
return NotFound(new Response { Status = "Error", Message = "Template not found" });
|
||||||
|
|
||||||
|
template.Name = model.Name;
|
||||||
|
template.Description = model.Description;
|
||||||
|
template.IsActive = model.IsActive;
|
||||||
|
|
||||||
|
_db.TaskListTemplateItems.RemoveRange(template.Items);
|
||||||
|
|
||||||
|
template.Items = model.Items.Select((item, idx) => new TaskListTemplateItem
|
||||||
|
{
|
||||||
|
TaskListTemplateId = id,
|
||||||
|
ItemText = item.ItemText,
|
||||||
|
SortOrder = item.SortOrder > 0 ? item.SortOrder : idx
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
return Ok(new { message = "Template updated" });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpDelete("{id}")]
|
||||||
|
public async Task<IActionResult> Delete(int id)
|
||||||
|
{
|
||||||
|
var template = await _db.TaskListTemplates.FindAsync(id);
|
||||||
|
if (template == null)
|
||||||
|
return NotFound(new Response { Status = "Error", Message = "Template not found" });
|
||||||
|
|
||||||
|
template.IsActive = false;
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
return Ok(new { message = "Template deleted" });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
Api.SeaHavenIndustries/DTOs/TaskListTemplate_DTO.cs
Normal file
16
Api.SeaHavenIndustries/DTOs/TaskListTemplate_DTO.cs
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
namespace Api.SeaHavenIndustries.DTOs
|
||||||
|
{
|
||||||
|
public class TaskListTemplate_DTO
|
||||||
|
{
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public List<TaskListTemplateItem_DTO> Items { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class TaskListTemplateItem_DTO
|
||||||
|
{
|
||||||
|
public string? ItemText { get; set; }
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -41,6 +41,8 @@ namespace Data.SeaHavenIndustries
|
||||||
public DbSet<DropdownOption> DropdownOptions { get; set; }
|
public DbSet<DropdownOption> DropdownOptions { get; set; }
|
||||||
public DbSet<Vendor> Vendors { get; set; }
|
public DbSet<Vendor> Vendors { get; set; }
|
||||||
public DbSet<Dispatch> Dispatches { get; set; }
|
public DbSet<Dispatch> Dispatches { get; set; }
|
||||||
|
public DbSet<TaskListTemplate> TaskListTemplates { get; set; }
|
||||||
|
public DbSet<TaskListTemplateItem> TaskListTemplateItems { get; set; }
|
||||||
|
|
||||||
// New DbSets for added entities
|
// New DbSets for added entities
|
||||||
public DbSet<Accounts> Accounts { get; set; }
|
public DbSet<Accounts> Accounts { get; set; }
|
||||||
|
|
|
||||||
2608
Data.SeaHavenIndustries/Migrations/20260417182910_AddTaskListTemplates.Designer.cs
generated
Normal file
2608
Data.SeaHavenIndustries/Migrations/20260417182910_AddTaskListTemplates.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Data.SeaHavenIndustries.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddTaskListTemplates : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "TaskListTemplates",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
Name = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
Description = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
IsActive = table.Column<bool>(type: "bit", nullable: false),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: true),
|
||||||
|
createdby = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
DeleterUserId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
CreatedDate = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierUserId = table.Column<int>(type: "int", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_TaskListTemplates", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "TaskListTemplateItems",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
TaskListTemplateId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
ItemText = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
SortOrder = table.Column<int>(type: "int", nullable: false),
|
||||||
|
IsDeleted = table.Column<bool>(type: "bit", nullable: true),
|
||||||
|
createdby = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
DeleterUserId = table.Column<string>(type: "nvarchar(max)", nullable: true),
|
||||||
|
DeletionTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
CreatedDate = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModificationTime = table.Column<DateTime>(type: "datetime2", nullable: true),
|
||||||
|
LastModifierUserId = table.Column<int>(type: "int", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_TaskListTemplateItems", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_TaskListTemplateItems_TaskListTemplates_TaskListTemplateId",
|
||||||
|
column: x => x.TaskListTemplateId,
|
||||||
|
principalTable: "TaskListTemplates",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Restrict);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_TaskListTemplateItems_TaskListTemplateId",
|
||||||
|
table: "TaskListTemplateItems",
|
||||||
|
column: "TaskListTemplateId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "TaskListTemplateItems");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "TaskListTemplates");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1386,6 +1386,94 @@ namespace Data.SeaHavenIndustries.Migrations
|
||||||
b.ToTable("Regions");
|
b.ToTable("Regions");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Data.SeaHavenIndustries.TaskListTemplate", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime?>("CreatedDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("DeleterUserId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("Description")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<bool>("IsActive")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<bool?>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int?>("LastModifierUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("createdby")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("TaskListTemplates");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Data.SeaHavenIndustries.TaskListTemplateItem", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<DateTime?>("CreatedDate")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<string>("DeleterUserId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DeletionTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<bool?>("IsDeleted")
|
||||||
|
.HasColumnType("bit");
|
||||||
|
|
||||||
|
b.Property<string>("ItemText")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("LastModificationTime")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int?>("LastModifierUserId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("SortOrder")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("TaskListTemplateId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("createdby")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("TaskListTemplateId");
|
||||||
|
|
||||||
|
b.ToTable("TaskListTemplateItems");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Data.SeaHavenIndustries.Template", b =>
|
modelBuilder.Entity("Data.SeaHavenIndustries.Template", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
|
|
@ -2243,6 +2331,17 @@ namespace Data.SeaHavenIndustries.Migrations
|
||||||
b.Navigation("Quotes");
|
b.Navigation("Quotes");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Data.SeaHavenIndustries.TaskListTemplateItem", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Data.SeaHavenIndustries.TaskListTemplate", "Template")
|
||||||
|
.WithMany("Items")
|
||||||
|
.HasForeignKey("TaskListTemplateId")
|
||||||
|
.OnDelete(DeleteBehavior.Restrict)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Template");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Data.SeaHavenIndustries.Template", b =>
|
modelBuilder.Entity("Data.SeaHavenIndustries.Template", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Data.SeaHavenIndustries.ApplicationUser", "AssignToUser")
|
b.HasOne("Data.SeaHavenIndustries.ApplicationUser", "AssignToUser")
|
||||||
|
|
@ -2476,6 +2575,11 @@ namespace Data.SeaHavenIndustries.Migrations
|
||||||
b.Navigation("Employees");
|
b.Navigation("Employees");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Data.SeaHavenIndustries.TaskListTemplate", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Items");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Data.SeaHavenIndustries.Vendor", b =>
|
modelBuilder.Entity("Data.SeaHavenIndustries.Vendor", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Dispatches");
|
b.Navigation("Dispatches");
|
||||||
|
|
|
||||||
10
Data.SeaHavenIndustries/Models/TaskListTemplate.cs
Normal file
10
Data.SeaHavenIndustries/Models/TaskListTemplate.cs
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
namespace Data.SeaHavenIndustries
|
||||||
|
{
|
||||||
|
public class TaskListTemplate : FullAuditEntity
|
||||||
|
{
|
||||||
|
public string? Name { get; set; }
|
||||||
|
public string? Description { get; set; }
|
||||||
|
public bool IsActive { get; set; } = true;
|
||||||
|
public ICollection<TaskListTemplateItem>? Items { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
13
Data.SeaHavenIndustries/Models/TaskListTemplateItem.cs
Normal file
13
Data.SeaHavenIndustries/Models/TaskListTemplateItem.cs
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Data.SeaHavenIndustries
|
||||||
|
{
|
||||||
|
public class TaskListTemplateItem : FullAuditEntity
|
||||||
|
{
|
||||||
|
public int TaskListTemplateId { get; set; }
|
||||||
|
[ForeignKey(nameof(TaskListTemplateId))]
|
||||||
|
public virtual TaskListTemplate? Template { get; set; }
|
||||||
|
public string? ItemText { get; set; }
|
||||||
|
public int SortOrder { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue