2024-09-28 14:58:36 -04:00
using Api.SeaHavenIndustries.Helper ;
using Data.SeaHavenIndustries ;
using Microsoft.AspNetCore.Authentication.JwtBearer ;
using Microsoft.AspNetCore.Identity ;
using Microsoft.AspNetCore.ResponseCompression ;
using Microsoft.EntityFrameworkCore ;
using Microsoft.IdentityModel.Tokens ;
using Microsoft.OpenApi.Models ;
using System.Text ;
var builder = WebApplication . CreateBuilder ( args ) ;
ConfigurationManager configuration = builder . Configuration ;
builder . Services . AddDbContext < ApplicationDbContext > ( options = > options . UseSqlServer ( configuration . GetConnectionString ( "DefaultConnection" ) ) ) ;
builder . Services . AddIdentity < ApplicationUser , IdentityRole > ( options = >
{
options . User . RequireUniqueEmail = false ;
} )
. AddEntityFrameworkStores < ApplicationDbContext > ( )
. AddDefaultTokenProviders ( ) ;
builder . Services . AddControllers ( ) . AddJsonOptions ( options = >
{
options . JsonSerializerOptions . MaxDepth = 264 ; // or any other desired value
} ) ;
builder . Services . AddResponseCompression ( opts = >
{
opts . MimeTypes = ResponseCompressionDefaults . MimeTypes . Concat (
new [ ] { "application/octet-stream" } ) ;
} ) ;
builder . Services . AddCors ( option = >
option . AddDefaultPolicy ( builder = > builder . AllowAnyOrigin ( ) . AllowAnyHeader ( ) . AllowAnyMethod ( ) ) ) ;
builder . Services . AddScoped < SendMessage > ( ) ;
2026-04-17 11:56:06 -04:00
builder . Services . AddSingleton < Api . SeaHavenIndustries . Helper . ZipCodeDistance > ( sp = >
{
var zipService = new Api . SeaHavenIndustries . Helper . ZipCodeDistance ( ) ;
var env = sp . GetRequiredService < IWebHostEnvironment > ( ) ;
var csvPath = Path . Combine ( env . WebRootPath , "zipcodes.csv" ) ;
if ( File . Exists ( csvPath ) ) zipService . Load ( csvPath ) ;
return zipService ;
} ) ;
2024-09-28 14:58:36 -04:00
builder . Services . AddAuthentication ( options = >
{
options . DefaultAuthenticateScheme = JwtBearerDefaults . AuthenticationScheme ;
options . DefaultChallengeScheme = JwtBearerDefaults . AuthenticationScheme ;
options . DefaultScheme = JwtBearerDefaults . AuthenticationScheme ;
} )
. AddJwtBearer ( options = >
{
options . SaveToken = true ;
options . RequireHttpsMetadata = false ;
options . TokenValidationParameters = new TokenValidationParameters ( )
{
ValidateIssuer = true ,
ValidateAudience = true ,
ValidAudience = configuration [ "JWT:ValidAudience" ] ,
ValidIssuer = configuration [ "JWT:ValidIssuer" ] ,
IssuerSigningKey = new SymmetricSecurityKey ( Encoding . UTF8 . GetBytes ( configuration [ "JWT:Secret" ] ) )
} ;
} ) ;
builder . Services . AddEndpointsApiExplorer ( ) ;
builder . Services . AddSwaggerGen ( c = >
{
c . SwaggerDoc ( "v1" , new OpenApiInfo { Title = "Seahaven" , Version = "v1" } ) ;
c . AddSecurityDefinition ( "Bearer" , new OpenApiSecurityScheme ( )
{
Name = "Authorization" ,
Type = SecuritySchemeType . ApiKey ,
Scheme = "Bearer" ,
BearerFormat = "JWT" ,
In = ParameterLocation . Header ,
Description = "JWT Authorization header using the Bearer scheme. \r\n\r\n Enter 'Bearer' [space] and then your token in the text input below.\r\n\r\nExample: \"Bearer 12345abcdef\"" ,
} ) ;
c . AddSecurityRequirement ( new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType . SecurityScheme ,
Id = "Bearer"
}
} ,
new string [ ] { }
}
} ) ;
} ) ;
var app = builder . Build ( ) ;
// Configure the HTTP request pipeline.
if ( app . Environment . IsDevelopment ( ) | | app . Environment . IsProduction ( ) )
{
app . UseSwagger ( ) ;
app . UseSwaggerUI ( c = >
{
c . SwaggerEndpoint ( "/swagger/v1/swagger.json" , "Sari" ) ;
c . RoutePrefix = string . Empty ;
} ) ;
}
2026-04-16 16:25:03 -04:00
if ( ! app . Environment . IsDevelopment ( ) )
app . UseHttpsRedirection ( ) ;
2024-09-28 14:58:36 -04:00
app . UseStaticFiles ( ) ;
app . UseCors ( ) ;
app . UseAuthentication ( ) ;
app . UseAuthorization ( ) ;
app . MapControllers ( ) ;
2026-04-16 16:25:03 -04:00
if ( app . Environment . IsDevelopment ( ) )
{
using var scope = app . Services . CreateScope ( ) ;
var userManager = scope . ServiceProvider . GetRequiredService < UserManager < ApplicationUser > > ( ) ;
var roleManager = scope . ServiceProvider . GetRequiredService < RoleManager < IdentityRole > > ( ) ;
if ( ! await roleManager . RoleExistsAsync ( "Admin" ) )
await roleManager . CreateAsync ( new IdentityRole ( "Admin" ) ) ;
var adminEmail = "admin@seahavenind.com" ;
if ( await userManager . FindByNameAsync ( adminEmail ) = = null )
{
var admin = new ApplicationUser
{
UserName = adminEmail ,
Email = adminEmail ,
FirstName = "Admin" ,
LastName = "User" ,
EmailConfirmed = true ,
UniqueName = "Active" ,
CreatedDate = DateTime . Now
} ;
var result = await userManager . CreateAsync ( admin , "Admin@123" ) ;
if ( result . Succeeded )
await userManager . AddToRoleAsync ( admin , "Admin" ) ;
}
Add configurable dropdowns, new WO fields, and seed data
- Create DropdownOption model with Category, Value, ParentValue for Trade/SubTrade/Problem
- Add DropdownOptionsController with CRUD + ByCategory endpoint with parent filtering
- Add Problem, Trade, SubTrade, VendorNTE, ScheduledDate, CompletedDate, Source to WorkOrder
- Update EditWorkorder_DTO and GetWorkorderById with new fields
- Audit log tracks changes to all new fields
- Seed default Trades (10), SubTrades (20), and Problems (11) on startup
2026-04-17 10:40:38 -04:00
var db = scope . ServiceProvider . GetRequiredService < ApplicationDbContext > ( ) ;
if ( ! db . DropdownOptions . Any ( ) )
{
var trades = new [ ] { "Plumbing" , "Electrical" , "HVAC" , "Fire/Life Safety" , "General" , "Roofing" , "Janitorial" , "Painting" , "Locksmith" , "Carpentry" } ;
for ( int i = 0 ; i < trades . Length ; i + + )
db . DropdownOptions . Add ( new DropdownOption { Category = "Trade" , Value = trades [ i ] , SortOrder = i } ) ;
var subTrades = new ( string trade , string sub ) [ ] {
( "Plumbing" , "Drain Cleaning" ) , ( "Plumbing" , "Pipe Repair" ) , ( "Plumbing" , "Fixture Install" ) , ( "Plumbing" , "Backflow Testing" ) ,
( "Electrical" , "Lighting" ) , ( "Electrical" , "Panel/Breaker" ) , ( "Electrical" , "Wiring" ) , ( "Electrical" , "Generator" ) ,
( "HVAC" , "AC Repair" ) , ( "HVAC" , "Heating" ) , ( "HVAC" , "Ductwork" ) , ( "HVAC" , "Controls/BMS" ) ,
( "Fire/Life Safety" , "Sprinkler" ) , ( "Fire/Life Safety" , "Fire Alarm" ) , ( "Fire/Life Safety" , "Extinguisher" ) , ( "Fire/Life Safety" , "Fire Pump" ) ,
( "General" , "Doors" ) , ( "General" , "Flooring" ) , ( "General" , "Drywall" ) , ( "General" , "Concrete" ) ,
} ;
for ( int i = 0 ; i < subTrades . Length ; i + + )
db . DropdownOptions . Add ( new DropdownOption { Category = "SubTrade" , Value = subTrades [ i ] . sub , ParentValue = subTrades [ i ] . trade , SortOrder = i } ) ;
var problems = new [ ] { "Leak" , "No Power" , "Not Cooling" , "Not Heating" , "Clogged" , "Broken/Damaged" , "Alarm Fault" , "Preventive Maintenance" , "Inspection" , "Installation" , "Other" } ;
for ( int i = 0 ; i < problems . Length ; i + + )
db . DropdownOptions . Add ( new DropdownOption { Category = "Problem" , Value = problems [ i ] , SortOrder = i } ) ;
await db . SaveChangesAsync ( ) ;
}
2026-04-16 16:25:03 -04:00
}
2024-09-28 14:58:36 -04:00
app . Run ( ) ;