mirror of
https://github.com/Sea-Haven-Industries/shoc-backend.git
synced 2026-09-30 08:23:12 +00:00
Add LocationController with full CRUD and extended model
- Extend Locations model with Address, City, State, ZipCode, Phone, Contact, ContactEmail, Status, AccountId
- Update Location DTOs to match new fields
- Create LocationController with paged list, get by ID, create, update, delete
- Support both REST-style routes (/api/Location/{id}) and legacy query routes (/api/Location/DeleteLocation?id=)
- Add migration for new Location columns
This commit is contained in:
parent
51b52a7fb5
commit
534f97d6f1
7 changed files with 2560 additions and 3 deletions
184
Api.SeaHavenIndustries/Controllers/LocationController.cs
Normal file
184
Api.SeaHavenIndustries/Controllers/LocationController.cs
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
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]")]
|
||||
public class LocationController : Controller
|
||||
{
|
||||
private readonly ApplicationDbContext _db;
|
||||
|
||||
public LocationController(ApplicationDbContext db)
|
||||
{
|
||||
_db = db;
|
||||
}
|
||||
|
||||
[HttpGet("GetLocationList")]
|
||||
public IActionResult GetLocationList(string? search = "", int page = 1, int pageSize = 10)
|
||||
{
|
||||
var query = _db.Locations.AsQueryable();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(search))
|
||||
{
|
||||
var s = search.ToLower();
|
||||
query = query.Where(l =>
|
||||
(l.Name ?? "").ToLower().Contains(s) ||
|
||||
(l.Title ?? "").ToLower().Contains(s) ||
|
||||
(l.Address ?? "").ToLower().Contains(s) ||
|
||||
(l.City ?? "").ToLower().Contains(s));
|
||||
}
|
||||
|
||||
var totalCount = query.Count();
|
||||
|
||||
var data = query
|
||||
.OrderByDescending(l => l.Id)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.Select(l => new
|
||||
{
|
||||
l.Id,
|
||||
l.Name,
|
||||
l.Title,
|
||||
l.Address,
|
||||
l.City,
|
||||
l.State,
|
||||
l.ZipCode,
|
||||
l.Phone,
|
||||
l.Contact,
|
||||
l.ContactEmail,
|
||||
l.Status,
|
||||
l.AccountId
|
||||
})
|
||||
.ToList();
|
||||
|
||||
var viewModel = new Pagination_DTO
|
||||
{
|
||||
Data = data,
|
||||
PageNumber = page,
|
||||
PageSize = pageSize,
|
||||
TotalCount = totalCount,
|
||||
TotalPages = (int)Math.Ceiling(totalCount / (double)pageSize)
|
||||
};
|
||||
|
||||
return Ok(viewModel);
|
||||
}
|
||||
|
||||
[HttpGet("{id}")]
|
||||
public async Task<IActionResult> GetLocationById(int id)
|
||||
{
|
||||
var location = await _db.Locations
|
||||
.Where(l => l.Id == id)
|
||||
.Select(l => new
|
||||
{
|
||||
l.Id,
|
||||
l.Name,
|
||||
l.Title,
|
||||
l.Address,
|
||||
l.City,
|
||||
l.State,
|
||||
l.ZipCode,
|
||||
l.Phone,
|
||||
l.Contact,
|
||||
l.ContactEmail,
|
||||
l.Status,
|
||||
l.AccountId
|
||||
})
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (location == null)
|
||||
return NotFound(new Response { Status = "Error", Message = "Location not found" });
|
||||
|
||||
return Ok(location);
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> AddLocation([FromBody] Location_DTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var location = new Locations
|
||||
{
|
||||
Name = model.Name,
|
||||
Title = model.Title,
|
||||
Address = model.Address,
|
||||
City = model.City,
|
||||
State = model.State,
|
||||
ZipCode = model.ZipCode,
|
||||
Phone = model.Phone,
|
||||
Contact = model.Contact,
|
||||
ContactEmail = model.ContactEmail,
|
||||
Status = model.Status,
|
||||
AccountId = model.AccountId
|
||||
};
|
||||
|
||||
_db.Locations.Add(location);
|
||||
await _db.SaveChangesAsync();
|
||||
return Ok(new DataResponse { Message = "Location Created Successfully", Status = "200" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> EditLocation(int id, [FromBody] EditLocation_DTO model)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exist = await _db.Locations.Where(l => l.Id == id).FirstOrDefaultAsync();
|
||||
if (exist == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
||||
|
||||
exist.Name = model.Name;
|
||||
exist.Title = model.Title;
|
||||
exist.Address = model.Address;
|
||||
exist.City = model.City;
|
||||
exist.State = model.State;
|
||||
exist.ZipCode = model.ZipCode;
|
||||
exist.Phone = model.Phone;
|
||||
exist.Contact = model.Contact;
|
||||
exist.ContactEmail = model.ContactEmail;
|
||||
exist.Status = model.Status;
|
||||
exist.AccountId = model.AccountId;
|
||||
|
||||
await _db.SaveChangesAsync();
|
||||
return Ok(new DataResponse { Message = "Location Updated Successfully", Status = "200" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> DeleteLocation(int id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var exist = await _db.Locations.Where(l => l.Id == id).FirstOrDefaultAsync();
|
||||
if (exist == null)
|
||||
return BadRequest(new Response { Status = "Error", Message = "Location not found" });
|
||||
|
||||
_db.Locations.Remove(exist);
|
||||
await _db.SaveChangesAsync();
|
||||
return Ok(new DataResponse { Message = "Location Deleted Successfully", Status = "200" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return BadRequest(new Response { Status = "Error", Message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("DeleteLocation")]
|
||||
public async Task<IActionResult> DeleteLocationByQuery(int id)
|
||||
{
|
||||
return await DeleteLocation(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,9 +1,18 @@
|
|||
namespace Api.SeaHavenIndustries.DTOs
|
||||
namespace Api.SeaHavenIndustries.DTOs
|
||||
{
|
||||
public class EditLocation_DTO
|
||||
{
|
||||
public int Id { get; set; }
|
||||
public string? Title { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? Contact { get; set; }
|
||||
public string? ContactEmail { get; set; }
|
||||
public string? Status { get; set; }
|
||||
public int? AccountId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,17 @@
|
|||
namespace Api.SeaHavenIndustries.DTOs
|
||||
namespace Api.SeaHavenIndustries.DTOs
|
||||
{
|
||||
public class Location_DTO
|
||||
{
|
||||
public string? Title { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? Contact { get; set; }
|
||||
public string? ContactEmail { get; set; }
|
||||
public string? Status { get; set; }
|
||||
public int? AccountId { get; set; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
2177
Data.SeaHavenIndustries/Migrations/20260416210833_AddLocationFields.Designer.cs
generated
Normal file
2177
Data.SeaHavenIndustries/Migrations/20260416210833_AddLocationFields.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,129 @@
|
|||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace Data.SeaHavenIndustries.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class AddLocationFields : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<int>(
|
||||
name: "AccountId",
|
||||
table: "Locations",
|
||||
type: "int",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Address",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "City",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Contact",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ContactEmail",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Phone",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "State",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "Status",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.AddColumn<string>(
|
||||
name: "ZipCode",
|
||||
table: "Locations",
|
||||
type: "nvarchar(max)",
|
||||
nullable: true);
|
||||
|
||||
migrationBuilder.CreateIndex(
|
||||
name: "IX_Locations_AccountId",
|
||||
table: "Locations",
|
||||
column: "AccountId");
|
||||
|
||||
migrationBuilder.AddForeignKey(
|
||||
name: "FK_Locations_Accounts_AccountId",
|
||||
table: "Locations",
|
||||
column: "AccountId",
|
||||
principalTable: "Accounts",
|
||||
principalColumn: "Id",
|
||||
onDelete: ReferentialAction.Restrict);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropForeignKey(
|
||||
name: "FK_Locations_Accounts_AccountId",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropIndex(
|
||||
name: "IX_Locations_AccountId",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "AccountId",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Address",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "City",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Contact",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ContactEmail",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Phone",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "State",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "Status",
|
||||
table: "Locations");
|
||||
|
||||
migrationBuilder.DropColumn(
|
||||
name: "ZipCode",
|
||||
table: "Locations");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -979,6 +979,21 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
|
||||
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||
|
||||
b.Property<int?>("AccountId")
|
||||
.HasColumnType("int");
|
||||
|
||||
b.Property<string>("Address")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("City")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Contact")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ContactEmail")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<DateTime?>("CreatedDate")
|
||||
.HasColumnType("datetime2");
|
||||
|
||||
|
|
@ -1006,14 +1021,28 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
b.Property<string>("Name")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Phone")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("State")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Status")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("Title")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("ZipCode")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.Property<string>("createdby")
|
||||
.HasColumnType("nvarchar(max)");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.HasIndex("AccountId");
|
||||
|
||||
b.ToTable("Locations");
|
||||
});
|
||||
|
||||
|
|
@ -1863,6 +1892,16 @@ namespace Data.SeaHavenIndustries.Migrations
|
|||
b.Navigation("WorkOrder");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.Locations", b =>
|
||||
{
|
||||
b.HasOne("Data.SeaHavenIndustries.Accounts", "Account")
|
||||
.WithMany()
|
||||
.HasForeignKey("AccountId")
|
||||
.OnDelete(DeleteBehavior.Restrict);
|
||||
|
||||
b.Navigation("Account");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("Data.SeaHavenIndustries.PMSchedules", b =>
|
||||
{
|
||||
b.HasOne("Data.SeaHavenIndustries.Assets", "Asset")
|
||||
|
|
|
|||
|
|
@ -8,10 +8,20 @@ namespace Data.SeaHavenIndustries
|
|||
{
|
||||
public string? Title { get; set; }
|
||||
public string? Name { get; set; }
|
||||
public string? Address { get; set; }
|
||||
public string? City { get; set; }
|
||||
public string? State { get; set; }
|
||||
public string? ZipCode { get; set; }
|
||||
public string? Phone { get; set; }
|
||||
public string? Contact { get; set; }
|
||||
public string? ContactEmail { get; set; }
|
||||
public string? Status { get; set; }
|
||||
public string? Latitude { get; set; }
|
||||
public string? Longitude { get; set; }
|
||||
public int? AccountId { get; set; }
|
||||
[ForeignKey("AccountId")]
|
||||
public Accounts? Account { get; set; }
|
||||
public ICollection<Template>? Templates { get; set; }
|
||||
public ICollection<WorkOrder>? workOrders { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue