diff --git a/ExportDXF.sln b/ExportDXF.sln index 5c9b6de..e194613 100644 --- a/ExportDXF.sln +++ b/ExportDXF.sln @@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FabWorks.Core", "FabWorks.C EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FabWorks.Tests", "FabWorks.Tests\FabWorks.Tests.csproj", "{6DD89774-D86B-47E9-B982-2794BD95616A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FabWorks.Api", "FabWorks.Api\FabWorks.Api.csproj", "{9BD571FA-52D8-430D-8843-FEB6EABD421C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -83,6 +85,18 @@ Global {6DD89774-D86B-47E9-B982-2794BD95616A}.Release|x64.Build.0 = Release|Any CPU {6DD89774-D86B-47E9-B982-2794BD95616A}.Release|x86.ActiveCfg = Release|Any CPU {6DD89774-D86B-47E9-B982-2794BD95616A}.Release|x86.Build.0 = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|x64.ActiveCfg = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|x64.Build.0 = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|x86.ActiveCfg = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Debug|x86.Build.0 = Debug|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|Any CPU.Build.0 = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|x64.ActiveCfg = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|x64.Build.0 = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|x86.ActiveCfg = Release|Any CPU + {9BD571FA-52D8-430D-8843-FEB6EABD421C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FabWorks.Api/Controllers/ExportsController.cs b/FabWorks.Api/Controllers/ExportsController.cs new file mode 100644 index 0000000..743c857 --- /dev/null +++ b/FabWorks.Api/Controllers/ExportsController.cs @@ -0,0 +1,140 @@ +using FabWorks.Api.DTOs; +using FabWorks.Core.Data; +using FabWorks.Core.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace FabWorks.Api.Controllers +{ + [ApiController] + [Route("api/[controller]")] + public class ExportsController : ControllerBase + { + private readonly FabWorksDbContext _db; + + public ExportsController(FabWorksDbContext db) => _db = db; + + [HttpPost] + public async Task> Create(CreateExportRequest request) + { + var record = new ExportRecord + { + DrawingNumber = request.DrawingNumber, + SourceFilePath = request.SourceFilePath, + OutputFolder = request.OutputFolder, + ExportedAt = DateTime.Now, + ExportedBy = Environment.UserName + }; + + _db.ExportRecords.Add(record); + await _db.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetById), new { id = record.Id }, MapToDto(record)); + } + + [HttpGet("{id}")] + public async Task> GetById(int id) + { + var record = await _db.ExportRecords + .Include(r => r.BomItems).ThenInclude(b => b.CutTemplate) + .Include(r => r.BomItems).ThenInclude(b => b.FormProgram) + .FirstOrDefaultAsync(r => r.Id == id); + + if (record == null) return NotFound(); + return MapToDto(record); + } + + [HttpGet("by-source")] + public async Task> GetBySourceFile([FromQuery] string path) + { + var record = await _db.ExportRecords + .Where(r => r.SourceFilePath.ToLower() == path.ToLower() + && !string.IsNullOrEmpty(r.DrawingNumber)) + .OrderByDescending(r => r.Id) + .FirstOrDefaultAsync(); + + if (record == null) return NotFound(); + return MapToDto(record); + } + + [HttpGet("by-drawing")] + public async Task>> GetByDrawing([FromQuery] string drawingNumber) + { + var records = await _db.ExportRecords + .Include(r => r.BomItems).ThenInclude(b => b.CutTemplate) + .Include(r => r.BomItems).ThenInclude(b => b.FormProgram) + .Where(r => r.DrawingNumber == drawingNumber) + .OrderByDescending(r => r.ExportedAt) + .ToListAsync(); + + return records.Select(MapToDto).ToList(); + } + + [HttpGet("next-item-number")] + public async Task> GetNextItemNumber([FromQuery] string drawingNumber) + { + if (string.IsNullOrEmpty(drawingNumber)) return "1"; + + var existingItems = await _db.ExportRecords + .Where(r => r.DrawingNumber == drawingNumber) + .SelectMany(r => r.BomItems) + .Select(b => b.ItemNo) + .ToListAsync(); + + int maxNum = 0; + foreach (var itemNo in existingItems) + { + if (int.TryParse(itemNo, out var num) && num > maxNum) + maxNum = num; + } + return (maxNum + 1).ToString(); + } + + private static ExportDetailDto MapToDto(ExportRecord r) => new() + { + Id = r.Id, + DrawingNumber = r.DrawingNumber, + SourceFilePath = r.SourceFilePath, + OutputFolder = r.OutputFolder, + ExportedAt = r.ExportedAt, + ExportedBy = r.ExportedBy, + PdfContentHash = r.PdfContentHash, + BomItems = r.BomItems?.Select(b => new BomItemDto + { + ID = b.ID, + ItemNo = b.ItemNo, + PartNo = b.PartNo, + SortOrder = b.SortOrder, + Qty = b.Qty, + TotalQty = b.TotalQty, + Description = b.Description, + PartName = b.PartName, + ConfigurationName = b.ConfigurationName, + Material = b.Material, + CutTemplate = b.CutTemplate == null ? null : new CutTemplateDto + { + Id = b.CutTemplate.Id, + DxfFilePath = b.CutTemplate.DxfFilePath, + ContentHash = b.CutTemplate.ContentHash, + Thickness = b.CutTemplate.Thickness, + KFactor = b.CutTemplate.KFactor, + DefaultBendRadius = b.CutTemplate.DefaultBendRadius + }, + FormProgram = b.FormProgram == null ? null : new FormProgramDto + { + Id = b.FormProgram.Id, + ProgramFilePath = b.FormProgram.ProgramFilePath, + ContentHash = b.FormProgram.ContentHash, + ProgramName = b.FormProgram.ProgramName, + Thickness = b.FormProgram.Thickness, + MaterialType = b.FormProgram.MaterialType, + KFactor = b.FormProgram.KFactor, + BendCount = b.FormProgram.BendCount, + UpperToolNames = b.FormProgram.UpperToolNames, + LowerToolNames = b.FormProgram.LowerToolNames, + SetupNotes = b.FormProgram.SetupNotes + } + }).ToList() ?? new() + }; + } +} diff --git a/FabWorks.Api/DTOs/CreateExportRequest.cs b/FabWorks.Api/DTOs/CreateExportRequest.cs new file mode 100644 index 0000000..6cb0d6f --- /dev/null +++ b/FabWorks.Api/DTOs/CreateExportRequest.cs @@ -0,0 +1,9 @@ +namespace FabWorks.Api.DTOs +{ + public class CreateExportRequest + { + public string DrawingNumber { get; set; } + public string SourceFilePath { get; set; } + public string OutputFolder { get; set; } + } +} diff --git a/FabWorks.Api/DTOs/ExportDetailDto.cs b/FabWorks.Api/DTOs/ExportDetailDto.cs new file mode 100644 index 0000000..a8efd81 --- /dev/null +++ b/FabWorks.Api/DTOs/ExportDetailDto.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; + +namespace FabWorks.Api.DTOs +{ + public class ExportDetailDto + { + public int Id { get; set; } + public string DrawingNumber { get; set; } + public string SourceFilePath { get; set; } + public string OutputFolder { get; set; } + public DateTime ExportedAt { get; set; } + public string ExportedBy { get; set; } + public string PdfContentHash { get; set; } + public List BomItems { get; set; } = new(); + } + + public class BomItemDto + { + public int ID { get; set; } + public string ItemNo { get; set; } + public string PartNo { get; set; } + public int SortOrder { get; set; } + public int? Qty { get; set; } + public int? TotalQty { get; set; } + public string Description { get; set; } + public string PartName { get; set; } + public string ConfigurationName { get; set; } + public string Material { get; set; } + public CutTemplateDto CutTemplate { get; set; } + public FormProgramDto FormProgram { get; set; } + } + + public class CutTemplateDto + { + public int Id { get; set; } + public string DxfFilePath { get; set; } + public string ContentHash { get; set; } + public double? Thickness { get; set; } + public double? KFactor { get; set; } + public double? DefaultBendRadius { get; set; } + } + + public class FormProgramDto + { + public int Id { get; set; } + public string ProgramFilePath { get; set; } + public string ContentHash { get; set; } + public string ProgramName { get; set; } + public double? Thickness { get; set; } + public string MaterialType { get; set; } + public double? KFactor { get; set; } + public int BendCount { get; set; } + public string UpperToolNames { get; set; } + public string LowerToolNames { get; set; } + public string SetupNotes { get; set; } + } +} diff --git a/FabWorks.Api/FabWorks.Api.csproj b/FabWorks.Api/FabWorks.Api.csproj new file mode 100644 index 0000000..e4f3a2f --- /dev/null +++ b/FabWorks.Api/FabWorks.Api.csproj @@ -0,0 +1,13 @@ + + + + net8.0 + disable + enable + + + + + + + diff --git a/FabWorks.Api/Program.cs b/FabWorks.Api/Program.cs new file mode 100644 index 0000000..dc2cc89 --- /dev/null +++ b/FabWorks.Api/Program.cs @@ -0,0 +1,15 @@ +using FabWorks.Api.Services; +using FabWorks.Core.Data; +using Microsoft.EntityFrameworkCore; + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllers(); +builder.Services.AddDbContext(options => + options.UseSqlServer(builder.Configuration.GetConnectionString("FabWorksDb"))); +builder.Services.AddSingleton(); + +var app = builder.Build(); + +app.MapControllers(); +app.Run(); diff --git a/FabWorks.Api/Properties/launchSettings.json b/FabWorks.Api/Properties/launchSettings.json new file mode 100644 index 0000000..b41988c --- /dev/null +++ b/FabWorks.Api/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:45483", + "sslPort": 44397 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "http://localhost:5206", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "weatherforecast", + "applicationUrl": "https://localhost:7182;http://localhost:5206", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "weatherforecast", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/FabWorks.Api/appsettings.Development.json b/FabWorks.Api/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/FabWorks.Api/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/FabWorks.Api/appsettings.json b/FabWorks.Api/appsettings.json new file mode 100644 index 0000000..7326dc1 --- /dev/null +++ b/FabWorks.Api/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "FabWorksDb": "Server=localhost;Database=ExportDxfDb;Trusted_Connection=True;TrustServerCertificate=True;" + } +}