refactor: wire ExportDXF to use FabWorks API
Replace direct DB access with API client calls throughout MainForm, DxfExportService, PartExporter, and Program. Add title field to UI, async export flow, API-based dropdown loading, and file uploads. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
48
ExportDXF/Forms/MainForm.Designer.cs
generated
48
ExportDXF/Forms/MainForm.Designer.cs
generated
@@ -42,6 +42,8 @@ namespace ExportDXF.Forms
|
|||||||
label1 = new System.Windows.Forms.Label();
|
label1 = new System.Windows.Forms.Label();
|
||||||
label2 = new System.Windows.Forms.Label();
|
label2 = new System.Windows.Forms.Label();
|
||||||
drawingNoBox = new System.Windows.Forms.ComboBox();
|
drawingNoBox = new System.Windows.Forms.ComboBox();
|
||||||
|
titleLabel = new System.Windows.Forms.Label();
|
||||||
|
titleBox = new System.Windows.Forms.TextBox();
|
||||||
mainTabControl.SuspendLayout();
|
mainTabControl.SuspendLayout();
|
||||||
logEventsTab.SuspendLayout();
|
logEventsTab.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)logEventsDataGrid).BeginInit();
|
((System.ComponentModel.ISupportInitialize)logEventsDataGrid).BeginInit();
|
||||||
@@ -54,10 +56,10 @@ namespace ExportDXF.Forms
|
|||||||
// runButton
|
// runButton
|
||||||
//
|
//
|
||||||
runButton.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
runButton.Anchor = System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right;
|
||||||
runButton.Location = new System.Drawing.Point(821, 13);
|
runButton.Location = new System.Drawing.Point(508, 12);
|
||||||
runButton.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
runButton.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
|
||||||
runButton.Name = "runButton";
|
runButton.Name = "runButton";
|
||||||
runButton.Size = new System.Drawing.Size(100, 55);
|
runButton.Size = new System.Drawing.Size(65, 87);
|
||||||
runButton.TabIndex = 11;
|
runButton.TabIndex = 11;
|
||||||
runButton.Text = "Start";
|
runButton.Text = "Start";
|
||||||
runButton.UseVisualStyleBackColor = true;
|
runButton.UseVisualStyleBackColor = true;
|
||||||
@@ -66,7 +68,7 @@ namespace ExportDXF.Forms
|
|||||||
// label3
|
// label3
|
||||||
//
|
//
|
||||||
label3.AutoSize = true;
|
label3.AutoSize = true;
|
||||||
label3.Location = new System.Drawing.Point(26, 46);
|
label3.Location = new System.Drawing.Point(26, 77);
|
||||||
label3.Name = "label3";
|
label3.Name = "label3";
|
||||||
label3.Size = new System.Drawing.Size(105, 17);
|
label3.Size = new System.Drawing.Size(105, 17);
|
||||||
label3.TabIndex = 2;
|
label3.TabIndex = 2;
|
||||||
@@ -76,7 +78,7 @@ namespace ExportDXF.Forms
|
|||||||
//
|
//
|
||||||
viewFlipDeciderBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
viewFlipDeciderBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
|
||||||
viewFlipDeciderBox.FormattingEnabled = true;
|
viewFlipDeciderBox.FormattingEnabled = true;
|
||||||
viewFlipDeciderBox.Location = new System.Drawing.Point(137, 43);
|
viewFlipDeciderBox.Location = new System.Drawing.Point(137, 74);
|
||||||
viewFlipDeciderBox.Name = "viewFlipDeciderBox";
|
viewFlipDeciderBox.Name = "viewFlipDeciderBox";
|
||||||
viewFlipDeciderBox.Size = new System.Drawing.Size(365, 25);
|
viewFlipDeciderBox.Size = new System.Drawing.Size(365, 25);
|
||||||
viewFlipDeciderBox.TabIndex = 3;
|
viewFlipDeciderBox.TabIndex = 3;
|
||||||
@@ -87,11 +89,11 @@ namespace ExportDXF.Forms
|
|||||||
mainTabControl.Controls.Add(logEventsTab);
|
mainTabControl.Controls.Add(logEventsTab);
|
||||||
mainTabControl.Controls.Add(bomTab);
|
mainTabControl.Controls.Add(bomTab);
|
||||||
mainTabControl.Controls.Add(cutTemplatesTab);
|
mainTabControl.Controls.Add(cutTemplatesTab);
|
||||||
mainTabControl.Location = new System.Drawing.Point(15, 74);
|
mainTabControl.Location = new System.Drawing.Point(15, 105);
|
||||||
mainTabControl.Name = "mainTabControl";
|
mainTabControl.Name = "mainTabControl";
|
||||||
mainTabControl.Padding = new System.Drawing.Point(20, 5);
|
mainTabControl.Padding = new System.Drawing.Point(20, 5);
|
||||||
mainTabControl.SelectedIndex = 0;
|
mainTabControl.SelectedIndex = 0;
|
||||||
mainTabControl.Size = new System.Drawing.Size(910, 441);
|
mainTabControl.Size = new System.Drawing.Size(910, 492);
|
||||||
mainTabControl.TabIndex = 12;
|
mainTabControl.TabIndex = 12;
|
||||||
//
|
//
|
||||||
// logEventsTab
|
// logEventsTab
|
||||||
@@ -100,7 +102,7 @@ namespace ExportDXF.Forms
|
|||||||
logEventsTab.Location = new System.Drawing.Point(4, 30);
|
logEventsTab.Location = new System.Drawing.Point(4, 30);
|
||||||
logEventsTab.Name = "logEventsTab";
|
logEventsTab.Name = "logEventsTab";
|
||||||
logEventsTab.Padding = new System.Windows.Forms.Padding(3);
|
logEventsTab.Padding = new System.Windows.Forms.Padding(3);
|
||||||
logEventsTab.Size = new System.Drawing.Size(902, 407);
|
logEventsTab.Size = new System.Drawing.Size(902, 458);
|
||||||
logEventsTab.TabIndex = 0;
|
logEventsTab.TabIndex = 0;
|
||||||
logEventsTab.Text = "Log Events";
|
logEventsTab.Text = "Log Events";
|
||||||
logEventsTab.UseVisualStyleBackColor = true;
|
logEventsTab.UseVisualStyleBackColor = true;
|
||||||
@@ -112,16 +114,16 @@ namespace ExportDXF.Forms
|
|||||||
logEventsDataGrid.GridColor = System.Drawing.Color.WhiteSmoke;
|
logEventsDataGrid.GridColor = System.Drawing.Color.WhiteSmoke;
|
||||||
logEventsDataGrid.Location = new System.Drawing.Point(6, 6);
|
logEventsDataGrid.Location = new System.Drawing.Point(6, 6);
|
||||||
logEventsDataGrid.Name = "logEventsDataGrid";
|
logEventsDataGrid.Name = "logEventsDataGrid";
|
||||||
logEventsDataGrid.Size = new System.Drawing.Size(890, 391);
|
logEventsDataGrid.Size = new System.Drawing.Size(890, 440);
|
||||||
logEventsDataGrid.TabIndex = 0;
|
logEventsDataGrid.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// bomTab
|
// bomTab
|
||||||
//
|
//
|
||||||
bomTab.Controls.Add(bomDataGrid);
|
bomTab.Controls.Add(bomDataGrid);
|
||||||
bomTab.Location = new System.Drawing.Point(4, 30);
|
bomTab.Location = new System.Drawing.Point(4, 28);
|
||||||
bomTab.Name = "bomTab";
|
bomTab.Name = "bomTab";
|
||||||
bomTab.Padding = new System.Windows.Forms.Padding(3);
|
bomTab.Padding = new System.Windows.Forms.Padding(3);
|
||||||
bomTab.Size = new System.Drawing.Size(902, 407);
|
bomTab.Size = new System.Drawing.Size(902, 409);
|
||||||
bomTab.TabIndex = 1;
|
bomTab.TabIndex = 1;
|
||||||
bomTab.Text = "Bill Of Materials";
|
bomTab.Text = "Bill Of Materials";
|
||||||
bomTab.UseVisualStyleBackColor = true;
|
bomTab.UseVisualStyleBackColor = true;
|
||||||
@@ -139,10 +141,10 @@ namespace ExportDXF.Forms
|
|||||||
// cutTemplatesTab
|
// cutTemplatesTab
|
||||||
//
|
//
|
||||||
cutTemplatesTab.Controls.Add(cutTemplatesDataGrid);
|
cutTemplatesTab.Controls.Add(cutTemplatesDataGrid);
|
||||||
cutTemplatesTab.Location = new System.Drawing.Point(4, 30);
|
cutTemplatesTab.Location = new System.Drawing.Point(4, 28);
|
||||||
cutTemplatesTab.Name = "cutTemplatesTab";
|
cutTemplatesTab.Name = "cutTemplatesTab";
|
||||||
cutTemplatesTab.Padding = new System.Windows.Forms.Padding(3);
|
cutTemplatesTab.Padding = new System.Windows.Forms.Padding(3);
|
||||||
cutTemplatesTab.Size = new System.Drawing.Size(902, 407);
|
cutTemplatesTab.Size = new System.Drawing.Size(902, 409);
|
||||||
cutTemplatesTab.TabIndex = 2;
|
cutTemplatesTab.TabIndex = 2;
|
||||||
cutTemplatesTab.Text = "Cut Templates";
|
cutTemplatesTab.Text = "Cut Templates";
|
||||||
cutTemplatesTab.UseVisualStyleBackColor = true;
|
cutTemplatesTab.UseVisualStyleBackColor = true;
|
||||||
@@ -191,10 +193,28 @@ namespace ExportDXF.Forms
|
|||||||
drawingNoBox.Size = new System.Drawing.Size(119, 25);
|
drawingNoBox.Size = new System.Drawing.Size(119, 25);
|
||||||
drawingNoBox.TabIndex = 13;
|
drawingNoBox.TabIndex = 13;
|
||||||
//
|
//
|
||||||
|
// titleLabel
|
||||||
|
//
|
||||||
|
titleLabel.AutoSize = true;
|
||||||
|
titleLabel.Location = new System.Drawing.Point(99, 46);
|
||||||
|
titleLabel.Name = "titleLabel";
|
||||||
|
titleLabel.Size = new System.Drawing.Size(32, 17);
|
||||||
|
titleLabel.TabIndex = 14;
|
||||||
|
titleLabel.Text = "Title";
|
||||||
|
//
|
||||||
|
// titleBox
|
||||||
|
//
|
||||||
|
titleBox.Location = new System.Drawing.Point(137, 43);
|
||||||
|
titleBox.Name = "titleBox";
|
||||||
|
titleBox.Size = new System.Drawing.Size(365, 25);
|
||||||
|
titleBox.TabIndex = 15;
|
||||||
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
|
||||||
ClientSize = new System.Drawing.Size(937, 527);
|
ClientSize = new System.Drawing.Size(937, 609);
|
||||||
|
Controls.Add(titleBox);
|
||||||
|
Controls.Add(titleLabel);
|
||||||
Controls.Add(drawingNoBox);
|
Controls.Add(drawingNoBox);
|
||||||
Controls.Add(equipmentBox);
|
Controls.Add(equipmentBox);
|
||||||
Controls.Add(mainTabControl);
|
Controls.Add(mainTabControl);
|
||||||
@@ -237,5 +257,7 @@ namespace ExportDXF.Forms
|
|||||||
private System.Windows.Forms.Label label1;
|
private System.Windows.Forms.Label label1;
|
||||||
private System.Windows.Forms.Label label2;
|
private System.Windows.Forms.Label label2;
|
||||||
private System.Windows.Forms.ComboBox drawingNoBox;
|
private System.Windows.Forms.ComboBox drawingNoBox;
|
||||||
|
private System.Windows.Forms.Label titleLabel;
|
||||||
|
private System.Windows.Forms.TextBox titleBox;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ExportDXF.Data;
|
using ExportDXF.ApiClient;
|
||||||
using ExportDXF.Extensions;
|
using ExportDXF.Extensions;
|
||||||
using ExportDXF.Models;
|
using ExportDXF.Models;
|
||||||
using ExportDXF.Services;
|
using ExportDXF.Services;
|
||||||
@@ -18,15 +18,14 @@ namespace ExportDXF.Forms
|
|||||||
{
|
{
|
||||||
private readonly ISolidWorksService _solidWorksService;
|
private readonly ISolidWorksService _solidWorksService;
|
||||||
private readonly IDxfExportService _exportService;
|
private readonly IDxfExportService _exportService;
|
||||||
private readonly IFileExportService _fileExportService;
|
private readonly IFabWorksApiClient _apiClient;
|
||||||
private readonly Func<ExportDxfDbContext> _dbContextFactory;
|
|
||||||
private CancellationTokenSource _cancellationTokenSource;
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
private readonly BindingList<LogEvent> _logEvents;
|
private readonly BindingList<LogEvent> _logEvents;
|
||||||
private readonly BindingList<BomItem> _bomItems;
|
private readonly BindingList<BomItem> _bomItems;
|
||||||
private readonly BindingList<CutTemplate> _cutTemplates;
|
private readonly BindingList<CutTemplate> _cutTemplates;
|
||||||
private List<DrawingInfo> _allDrawings;
|
private List<DrawingInfo> _allDrawings;
|
||||||
|
|
||||||
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, IFileExportService fileExportService, Func<ExportDxfDbContext> dbContextFactory = null)
|
public MainForm(ISolidWorksService solidWorksService, IDxfExportService exportService, IFabWorksApiClient apiClient)
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
_solidWorksService = solidWorksService ??
|
_solidWorksService = solidWorksService ??
|
||||||
@@ -34,9 +33,8 @@ namespace ExportDXF.Forms
|
|||||||
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
||||||
_exportService = exportService ??
|
_exportService = exportService ??
|
||||||
throw new ArgumentNullException(nameof(exportService));
|
throw new ArgumentNullException(nameof(exportService));
|
||||||
_fileExportService = fileExportService ??
|
_apiClient = apiClient ??
|
||||||
throw new ArgumentNullException(nameof(fileExportService));
|
throw new ArgumentNullException(nameof(apiClient));
|
||||||
_dbContextFactory = dbContextFactory ?? (() => new ExportDxfDbContext());
|
|
||||||
_logEvents = new BindingList<LogEvent>();
|
_logEvents = new BindingList<LogEvent>();
|
||||||
_bomItems = new BindingList<BomItem>();
|
_bomItems = new BindingList<BomItem>();
|
||||||
_cutTemplates = new BindingList<CutTemplate>();
|
_cutTemplates = new BindingList<CutTemplate>();
|
||||||
@@ -70,9 +68,10 @@ namespace ExportDXF.Forms
|
|||||||
LogMessage("Connecting to SolidWorks, this may take a minute...");
|
LogMessage("Connecting to SolidWorks, this may take a minute...");
|
||||||
await _solidWorksService.ConnectAsync();
|
await _solidWorksService.ConnectAsync();
|
||||||
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
_solidWorksService.ActiveDocumentChanged += OnActiveDocumentChanged;
|
||||||
LogMessage($"Output folder: {_fileExportService.OutputFolder}");
|
LogMessage("Files will be uploaded to FabWorks API");
|
||||||
|
await LoadDrawingDropdownsAsync();
|
||||||
LogMessage("Ready");
|
LogMessage("Ready");
|
||||||
UpdateActiveDocumentDisplay();
|
await UpdateActiveDocumentDisplayAsync();
|
||||||
runButton.Enabled = true;
|
runButton.Enabled = true;
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -274,74 +273,60 @@ namespace ExportDXF.Forms
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void InitializeDrawingDropdowns()
|
private void InitializeDrawingDropdowns()
|
||||||
|
{
|
||||||
|
// Wire up event handler; actual data loading happens in LoadDrawingDropdownsAsync
|
||||||
|
equipmentBox.SelectedIndexChanged += EquipmentBox_SelectedIndexChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task LoadDrawingDropdownsAsync()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var db = _dbContextFactory())
|
var equipmentNumbers = await _apiClient.GetEquipmentNumbersAsync();
|
||||||
|
|
||||||
|
equipmentBox.Items.Clear();
|
||||||
|
equipmentBox.Items.Add("");
|
||||||
|
foreach (var eq in equipmentNumbers)
|
||||||
{
|
{
|
||||||
// Get all drawing numbers from the database
|
equipmentBox.Items.Add(eq);
|
||||||
var drawingNumbers = db.ExportRecords
|
|
||||||
.Select(r => r.DrawingNumber)
|
|
||||||
.Where(d => !string.IsNullOrEmpty(d))
|
|
||||||
.Distinct()
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Parse into DrawingInfo objects
|
|
||||||
_allDrawings = drawingNumbers
|
|
||||||
.Select(DrawingInfo.Parse)
|
|
||||||
.Where(d => d != null)
|
|
||||||
.Distinct()
|
|
||||||
.OrderBy(d => d.EquipmentNo)
|
|
||||||
.ThenBy(d => d.DrawingNo)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Get distinct equipment numbers
|
|
||||||
var equipmentNumbers = _allDrawings
|
|
||||||
.Select(d => d.EquipmentNo)
|
|
||||||
.Distinct()
|
|
||||||
.OrderBy(e => e)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Populate equipment dropdown
|
|
||||||
equipmentBox.Items.Clear();
|
|
||||||
equipmentBox.Items.Add(""); // Empty option for "all"
|
|
||||||
foreach (var eq in equipmentNumbers)
|
|
||||||
{
|
|
||||||
equipmentBox.Items.Add(eq);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Populate drawing dropdown with all drawings initially
|
|
||||||
UpdateDrawingDropdown();
|
|
||||||
|
|
||||||
// Wire up event handler for equipment selection change
|
|
||||||
equipmentBox.SelectedIndexChanged += EquipmentBox_SelectedIndexChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear _allDrawings — drawing list is now loaded on equipment selection
|
||||||
|
_allDrawings = new List<DrawingInfo>();
|
||||||
|
await UpdateDrawingDropdownAsync();
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
// Database might not exist yet - that's OK
|
// API might not be available yet - that's OK
|
||||||
System.Diagnostics.Debug.WriteLine($"Failed to load drawings from database: {ex.Message}");
|
System.Diagnostics.Debug.WriteLine($"Failed to load equipment numbers from API: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EquipmentBox_SelectedIndexChanged(object sender, EventArgs e)
|
private async void EquipmentBox_SelectedIndexChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
UpdateDrawingDropdown();
|
await UpdateDrawingDropdownAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateDrawingDropdown()
|
private async Task UpdateDrawingDropdownAsync()
|
||||||
{
|
{
|
||||||
var selectedEquipment = equipmentBox.SelectedItem?.ToString();
|
var selectedEquipment = equipmentBox.SelectedItem?.ToString();
|
||||||
|
|
||||||
var filteredDrawings = string.IsNullOrEmpty(selectedEquipment)
|
|
||||||
? _allDrawings
|
|
||||||
: _allDrawings.Where(d => d.EquipmentNo == selectedEquipment).ToList();
|
|
||||||
|
|
||||||
drawingNoBox.Items.Clear();
|
drawingNoBox.Items.Clear();
|
||||||
drawingNoBox.Items.Add(""); // Empty option
|
drawingNoBox.Items.Add("");
|
||||||
foreach (var drawing in filteredDrawings)
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
drawingNoBox.Items.Add(drawing.DrawingNo);
|
var drawingNumbers = await _apiClient.GetDrawingNumbersByEquipmentAsync(
|
||||||
|
string.IsNullOrEmpty(selectedEquipment) ? null : selectedEquipment);
|
||||||
|
|
||||||
|
foreach (var dn in drawingNumbers)
|
||||||
|
{
|
||||||
|
drawingNoBox.Items.Add(dn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// API might not be available
|
||||||
}
|
}
|
||||||
|
|
||||||
if (drawingNoBox.Items.Count > 0)
|
if (drawingNoBox.Items.Count > 0)
|
||||||
@@ -380,11 +365,13 @@ namespace ExportDXF.Forms
|
|||||||
// Use equipment/drawing values from the UI dropdowns
|
// Use equipment/drawing values from the UI dropdowns
|
||||||
var equipment = equipmentBox.Text?.Trim();
|
var equipment = equipmentBox.Text?.Trim();
|
||||||
var drawingNo = drawingNoBox.Text?.Trim();
|
var drawingNo = drawingNoBox.Text?.Trim();
|
||||||
var filePrefix = !string.IsNullOrEmpty(equipment) && !string.IsNullOrEmpty(drawingNo)
|
var filePrefix = !string.IsNullOrEmpty(equipment)
|
||||||
? $"{equipment} {drawingNo}"
|
? (!string.IsNullOrEmpty(drawingNo) ? $"{equipment} {drawingNo}" : equipment)
|
||||||
: activeDoc.Title;
|
: activeDoc.Title;
|
||||||
|
|
||||||
var viewFlipDecider = GetSelectedViewFlipDecider();
|
var viewFlipDecider = GetSelectedViewFlipDecider();
|
||||||
|
var title = titleBox.Text?.Trim();
|
||||||
|
|
||||||
var exportContext = new ExportContext
|
var exportContext = new ExportContext
|
||||||
{
|
{
|
||||||
ActiveDocument = activeDoc,
|
ActiveDocument = activeDoc,
|
||||||
@@ -392,6 +379,7 @@ namespace ExportDXF.Forms
|
|||||||
FilePrefix = filePrefix,
|
FilePrefix = filePrefix,
|
||||||
Equipment = equipment,
|
Equipment = equipment,
|
||||||
DrawingNo = drawingNo,
|
DrawingNo = drawingNo,
|
||||||
|
Title = string.IsNullOrEmpty(title) ? null : title,
|
||||||
EquipmentId = null,
|
EquipmentId = null,
|
||||||
CancellationToken = token,
|
CancellationToken = token,
|
||||||
ProgressCallback = (msg, level, file) => LogMessage(msg, level, file),
|
ProgressCallback = (msg, level, file) => LogMessage(msg, level, file),
|
||||||
@@ -403,11 +391,11 @@ namespace ExportDXF.Forms
|
|||||||
_cutTemplates.Clear();
|
_cutTemplates.Clear();
|
||||||
|
|
||||||
LogMessage($"Started at {DateTime.Now:t}");
|
LogMessage($"Started at {DateTime.Now:t}");
|
||||||
LogMessage($"Exporting to: {_fileExportService.OutputFolder}");
|
LogMessage("Exporting (files will be uploaded to API)...");
|
||||||
|
|
||||||
_solidWorksService.SetCommandInProgress(true);
|
_solidWorksService.SetCommandInProgress(true);
|
||||||
|
|
||||||
await Task.Run(() => _exportService.Export(exportContext), token);
|
await Task.Run(async () => await _exportService.ExportAsync(exportContext), token);
|
||||||
|
|
||||||
LogMessage("Done.");
|
LogMessage("Done.");
|
||||||
}
|
}
|
||||||
@@ -454,17 +442,17 @@ namespace ExportDXF.Forms
|
|||||||
runButton.Enabled = true;
|
runButton.Enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnActiveDocumentChanged(object sender, EventArgs e)
|
private async void OnActiveDocumentChanged(object sender, EventArgs e)
|
||||||
{
|
{
|
||||||
if (InvokeRequired)
|
if (InvokeRequired)
|
||||||
{
|
{
|
||||||
Invoke(new Action(() => OnActiveDocumentChanged(sender, e)));
|
Invoke(new Action(async () => await UpdateActiveDocumentDisplayAsync()));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
UpdateActiveDocumentDisplay();
|
await UpdateActiveDocumentDisplayAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void UpdateActiveDocumentDisplay()
|
private async Task UpdateActiveDocumentDisplayAsync()
|
||||||
{
|
{
|
||||||
var activeDoc = _solidWorksService.GetActiveDocument();
|
var activeDoc = _solidWorksService.GetActiveDocument();
|
||||||
var docTitle = activeDoc?.Title ?? "No Document Open";
|
var docTitle = activeDoc?.Title ?? "No Document Open";
|
||||||
@@ -473,12 +461,12 @@ namespace ExportDXF.Forms
|
|||||||
if (activeDoc == null)
|
if (activeDoc == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Try database first: look up the most recent export for this file path
|
// Try API first: look up the most recent export for this file path
|
||||||
DrawingInfo drawingInfo = null;
|
DrawingInfo drawingInfo = null;
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(activeDoc.FilePath))
|
if (!string.IsNullOrEmpty(activeDoc.FilePath))
|
||||||
{
|
{
|
||||||
drawingInfo = LookupDrawingInfoFromHistory(activeDoc.FilePath);
|
drawingInfo = await LookupDrawingInfoFromHistoryAsync(activeDoc.FilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fall back to parsing the document title
|
// Fall back to parsing the document title
|
||||||
@@ -489,36 +477,37 @@ namespace ExportDXF.Forms
|
|||||||
|
|
||||||
if (drawingInfo != null)
|
if (drawingInfo != null)
|
||||||
{
|
{
|
||||||
if (!equipmentBox.Items.Contains(drawingInfo.EquipmentNo))
|
if (!string.IsNullOrEmpty(drawingInfo.EquipmentNo))
|
||||||
equipmentBox.Items.Add(drawingInfo.EquipmentNo);
|
{
|
||||||
equipmentBox.Text = drawingInfo.EquipmentNo;
|
if (!equipmentBox.Items.Contains(drawingInfo.EquipmentNo))
|
||||||
|
equipmentBox.Items.Add(drawingInfo.EquipmentNo);
|
||||||
|
equipmentBox.Text = drawingInfo.EquipmentNo;
|
||||||
|
}
|
||||||
|
|
||||||
if (!drawingNoBox.Items.Contains(drawingInfo.DrawingNo))
|
if (!string.IsNullOrEmpty(drawingInfo.DrawingNo))
|
||||||
drawingNoBox.Items.Add(drawingInfo.DrawingNo);
|
{
|
||||||
drawingNoBox.Text = drawingInfo.DrawingNo;
|
if (!drawingNoBox.Items.Contains(drawingInfo.DrawingNo))
|
||||||
|
drawingNoBox.Items.Add(drawingInfo.DrawingNo);
|
||||||
|
drawingNoBox.Text = drawingInfo.DrawingNo;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private DrawingInfo LookupDrawingInfoFromHistory(string filePath)
|
private async Task<DrawingInfo> LookupDrawingInfoFromHistoryAsync(string filePath)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var db = _dbContextFactory())
|
var dto = await _apiClient.GetExportBySourceFileAsync(filePath);
|
||||||
|
if (dto != null && !string.IsNullOrEmpty(dto.DrawingNumber))
|
||||||
{
|
{
|
||||||
var drawingNumber = db.ExportRecords
|
if (!string.IsNullOrEmpty(dto.Title))
|
||||||
.Where(r => r.SourceFilePath.ToLower() == filePath.ToLower()
|
titleBox.Text = dto.Title;
|
||||||
&& !string.IsNullOrEmpty(r.DrawingNumber))
|
return DrawingInfo.Parse(dto.DrawingNumber);
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.Select(r => r.DrawingNumber)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (drawingNumber != null)
|
|
||||||
return DrawingInfo.Parse(drawingNumber);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
System.Diagnostics.Debug.WriteLine($"Failed to look up drawing info from history: {ex.Message}");
|
System.Diagnostics.Debug.WriteLine($"Failed to look up drawing info from API: {ex.Message}");
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -68,8 +68,9 @@ namespace ExportDXF.Services
|
|||||||
public string ContentHash { get; set; }
|
public string ContentHash { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Path to the stashed (backed-up) previous DXF file (transient, not persisted).
|
/// Full path to the locally-exported DXF temp file (transient, not persisted).
|
||||||
|
/// Set after successful export; used for upload to the API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string StashedFilePath { get; set; }
|
public string LocalTempPath { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
|
using ExportDXF.ApiClient;
|
||||||
using ExportDXF.Forms;
|
using ExportDXF.Forms;
|
||||||
using ExportDXF.Services;
|
using ExportDXF.Services;
|
||||||
using System;
|
using System;
|
||||||
using System.Configuration;
|
using System.Configuration;
|
||||||
|
using System.Net.Http;
|
||||||
using System.Windows.Forms;
|
using System.Windows.Forms;
|
||||||
|
|
||||||
namespace ExportDXF
|
namespace ExportDXF
|
||||||
@@ -28,29 +30,35 @@ namespace ExportDXF
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class ServiceContainer
|
public class ServiceContainer
|
||||||
{
|
{
|
||||||
private readonly string _outputFolder;
|
private readonly string _apiBaseUrl;
|
||||||
|
|
||||||
public ServiceContainer()
|
public ServiceContainer()
|
||||||
{
|
{
|
||||||
_outputFolder = ConfigurationManager.AppSettings["ExportOutputFolder"] ?? @"C:\ExportDXF\Output";
|
_apiBaseUrl = ConfigurationManager.AppSettings["FabWorksApiUrl"] ?? "http://localhost:5206";
|
||||||
}
|
}
|
||||||
|
|
||||||
public MainForm ResolveMainForm()
|
public MainForm ResolveMainForm()
|
||||||
{
|
{
|
||||||
var solidWorksService = new SolidWorksService();
|
var solidWorksService = new SolidWorksService();
|
||||||
var bomExtractor = new BomExtractor();
|
var bomExtractor = new BomExtractor();
|
||||||
var fileExportService = new FileExportService(_outputFolder);
|
var partExporter = new PartExporter();
|
||||||
var partExporter = new PartExporter(fileExportService);
|
|
||||||
var drawingExporter = new DrawingExporter();
|
var drawingExporter = new DrawingExporter();
|
||||||
|
|
||||||
|
var httpClient = new HttpClient
|
||||||
|
{
|
||||||
|
BaseAddress = new Uri(_apiBaseUrl),
|
||||||
|
Timeout = TimeSpan.FromSeconds(30)
|
||||||
|
};
|
||||||
|
var apiClient = new FabWorksApiClient(httpClient);
|
||||||
|
|
||||||
var exportService = new DxfExportService(
|
var exportService = new DxfExportService(
|
||||||
solidWorksService,
|
solidWorksService,
|
||||||
bomExtractor,
|
bomExtractor,
|
||||||
partExporter,
|
partExporter,
|
||||||
drawingExporter,
|
drawingExporter,
|
||||||
fileExportService);
|
apiClient);
|
||||||
|
|
||||||
return new MainForm(solidWorksService, exportService, fileExportService);
|
return new MainForm(solidWorksService, exportService, apiClient);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
using ExportDXF.Data;
|
using ExportDXF.ApiClient;
|
||||||
using ExportDXF.Extensions;
|
using ExportDXF.Extensions;
|
||||||
using ExportDXF.ItemExtractors;
|
using ExportDXF.ItemExtractors;
|
||||||
using ExportDXF.Models;
|
using ExportDXF.Models;
|
||||||
using ExportDXF.Utilities;
|
using ExportDXF.Utilities;
|
||||||
using ExportDXF;
|
using ExportDXF;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using SolidWorks.Interop.sldworks;
|
using SolidWorks.Interop.sldworks;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace ExportDXF.Services
|
namespace ExportDXF.Services
|
||||||
{
|
{
|
||||||
@@ -19,11 +19,12 @@ namespace ExportDXF.Services
|
|||||||
/// Exports the document specified in the context to DXF format.
|
/// Exports the document specified in the context to DXF format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">The export context containing all necessary information.</param>
|
/// <param name="context">The export context containing all necessary information.</param>
|
||||||
void Export(ExportContext context);
|
Task ExportAsync(ExportContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Service responsible for orchestrating the export of SolidWorks documents to DXF format.
|
/// Service responsible for orchestrating the export of SolidWorks documents to DXF format.
|
||||||
|
/// Files are generated locally in a temp directory, then uploaded to the API for storage and versioning.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class DxfExportService : IDxfExportService
|
public class DxfExportService : IDxfExportService
|
||||||
{
|
{
|
||||||
@@ -31,29 +32,26 @@ namespace ExportDXF.Services
|
|||||||
private readonly IBomExtractor _bomExtractor;
|
private readonly IBomExtractor _bomExtractor;
|
||||||
private readonly IPartExporter _partExporter;
|
private readonly IPartExporter _partExporter;
|
||||||
private readonly IDrawingExporter _drawingExporter;
|
private readonly IDrawingExporter _drawingExporter;
|
||||||
private readonly IFileExportService _fileExportService;
|
private readonly IFabWorksApiClient _apiClient;
|
||||||
private readonly Func<ExportDxfDbContext> _dbContextFactory;
|
|
||||||
|
|
||||||
public DxfExportService(
|
public DxfExportService(
|
||||||
ISolidWorksService solidWorksService,
|
ISolidWorksService solidWorksService,
|
||||||
IBomExtractor bomExtractor,
|
IBomExtractor bomExtractor,
|
||||||
IPartExporter partExporter,
|
IPartExporter partExporter,
|
||||||
IDrawingExporter drawingExporter,
|
IDrawingExporter drawingExporter,
|
||||||
IFileExportService fileExportService,
|
IFabWorksApiClient apiClient)
|
||||||
Func<ExportDxfDbContext> dbContextFactory = null)
|
|
||||||
{
|
{
|
||||||
_solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService));
|
_solidWorksService = solidWorksService ?? throw new ArgumentNullException(nameof(solidWorksService));
|
||||||
_bomExtractor = bomExtractor ?? throw new ArgumentNullException(nameof(bomExtractor));
|
_bomExtractor = bomExtractor ?? throw new ArgumentNullException(nameof(bomExtractor));
|
||||||
_partExporter = partExporter ?? throw new ArgumentNullException(nameof(partExporter));
|
_partExporter = partExporter ?? throw new ArgumentNullException(nameof(partExporter));
|
||||||
_drawingExporter = drawingExporter ?? throw new ArgumentNullException(nameof(drawingExporter));
|
_drawingExporter = drawingExporter ?? throw new ArgumentNullException(nameof(drawingExporter));
|
||||||
_fileExportService = fileExportService ?? throw new ArgumentNullException(nameof(fileExportService));
|
_apiClient = apiClient ?? throw new ArgumentNullException(nameof(apiClient));
|
||||||
_dbContextFactory = dbContextFactory ?? (() => new ExportDxfDbContext());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Exports the document specified in the context to DXF format.
|
/// Exports the document specified in the context to DXF format.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void Export(ExportContext context)
|
public async Task ExportAsync(ExportContext context)
|
||||||
{
|
{
|
||||||
if (context == null)
|
if (context == null)
|
||||||
throw new ArgumentNullException(nameof(context));
|
throw new ArgumentNullException(nameof(context));
|
||||||
@@ -62,26 +60,26 @@ namespace ExportDXF.Services
|
|||||||
SetupExportContext(context);
|
SetupExportContext(context);
|
||||||
|
|
||||||
var startTime = DateTime.Now;
|
var startTime = DateTime.Now;
|
||||||
|
var tempDir = CreateTempWorkDir();
|
||||||
var drawingNumber = ParseDrawingNumber(context);
|
|
||||||
var outputFolder = _fileExportService.GetDrawingOutputFolder(context.Equipment, context.DrawingNo);
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_solidWorksService.EnableUserControl(false);
|
_solidWorksService.EnableUserControl(false);
|
||||||
|
|
||||||
|
var drawingNumber = ParseDrawingNumber(context);
|
||||||
|
|
||||||
switch (context.ActiveDocument.DocumentType)
|
switch (context.ActiveDocument.DocumentType)
|
||||||
{
|
{
|
||||||
case DocumentType.Part:
|
case DocumentType.Part:
|
||||||
ExportPart(context, outputFolder, drawingNumber);
|
await ExportPartAsync(context, tempDir, drawingNumber);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DocumentType.Assembly:
|
case DocumentType.Assembly:
|
||||||
ExportAssembly(context, outputFolder, drawingNumber);
|
await ExportAssemblyAsync(context, tempDir, drawingNumber);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DocumentType.Drawing:
|
case DocumentType.Drawing:
|
||||||
ExportDrawing(context, drawingNumber, outputFolder);
|
await ExportDrawingAsync(context, drawingNumber, tempDir);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@@ -93,6 +91,7 @@ namespace ExportDXF.Services
|
|||||||
{
|
{
|
||||||
CleanupExportContext(context);
|
CleanupExportContext(context);
|
||||||
_solidWorksService.EnableUserControl(true);
|
_solidWorksService.EnableUserControl(true);
|
||||||
|
CleanupTempDir(tempDir);
|
||||||
|
|
||||||
var duration = DateTime.Now - startTime;
|
var duration = DateTime.Now - startTime;
|
||||||
LogProgress(context, $"Run time: {duration.ToReadableFormat()}");
|
LogProgress(context, $"Run time: {duration.ToReadableFormat()}");
|
||||||
@@ -101,7 +100,7 @@ namespace ExportDXF.Services
|
|||||||
|
|
||||||
#region Export Methods by Document Type
|
#region Export Methods by Document Type
|
||||||
|
|
||||||
private void ExportPart(ExportContext context, string outputFolder, string drawingNumber)
|
private async Task ExportPartAsync(ExportContext context, string tempDir, string drawingNumber)
|
||||||
{
|
{
|
||||||
LogProgress(context, "Active document is a Part");
|
LogProgress(context, "Active document is a Part");
|
||||||
|
|
||||||
@@ -112,14 +111,14 @@ namespace ExportDXF.Services
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var exportRecord = CreateExportRecord(context, drawingNumber, outputFolder);
|
var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
|
||||||
var item = _partExporter.ExportSinglePart(part, outputFolder, context);
|
var item = _partExporter.ExportSinglePart(part, tempDir, context);
|
||||||
|
|
||||||
if (item != null)
|
if (item != null)
|
||||||
{
|
{
|
||||||
// Assign auto-incremented item number
|
// Check if this part+config already has a BOM item for this drawing
|
||||||
var nextItemNo = GetNextItemNumber(drawingNumber);
|
var existingItemNo = await FindExistingItemNoAsync(exportRecord?.Id, item.PartName, item.Configuration);
|
||||||
item.ItemNo = nextItemNo;
|
item.ItemNo = existingItemNo ?? await GetNextItemNumberAsync(drawingNumber);
|
||||||
|
|
||||||
var bomItem = new BomItem
|
var bomItem = new BomItem
|
||||||
{
|
{
|
||||||
@@ -135,29 +134,31 @@ namespace ExportDXF.Services
|
|||||||
Material = item.Material ?? ""
|
Material = item.Material ?? ""
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(item.FileName))
|
// Upload DXF to API and get stored path
|
||||||
|
if (!string.IsNullOrEmpty(item.LocalTempPath))
|
||||||
{
|
{
|
||||||
var dxfPath = Path.Combine(outputFolder, item.FileName + ".dxf");
|
var uploadResult = await UploadDxfAsync(item, context);
|
||||||
bomItem.CutTemplate = new CutTemplate
|
if (uploadResult != null)
|
||||||
{
|
{
|
||||||
DxfFilePath = dxfPath,
|
bomItem.CutTemplate = new CutTemplate
|
||||||
ContentHash = item.ContentHash,
|
{
|
||||||
Thickness = item.Thickness > 0 ? item.Thickness : null,
|
DxfFilePath = uploadResult.StoredFilePath,
|
||||||
KFactor = item.KFactor > 0 ? item.KFactor : null,
|
ContentHash = item.ContentHash,
|
||||||
DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
|
Thickness = item.Thickness > 0 ? item.Thickness : null,
|
||||||
};
|
KFactor = item.KFactor > 0 ? item.KFactor : null,
|
||||||
|
DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
|
||||||
HandleDxfVersioning(item, dxfPath, context);
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.BomItemCallback?.Invoke(bomItem);
|
context.BomItemCallback?.Invoke(bomItem);
|
||||||
|
|
||||||
if (exportRecord != null)
|
if (exportRecord != null)
|
||||||
SaveBomItem(bomItem, context);
|
await SaveBomItemAsync(exportRecord.Id, bomItem, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExportAssembly(ExportContext context, string outputFolder, string drawingNumber)
|
private async Task ExportAssemblyAsync(ExportContext context, string tempDir, string drawingNumber)
|
||||||
{
|
{
|
||||||
LogProgress(context, "Active document is an Assembly");
|
LogProgress(context, "Active document is an Assembly");
|
||||||
LogProgress(context, "Fetching components...");
|
LogProgress(context, "Fetching components...");
|
||||||
@@ -179,23 +180,31 @@ namespace ExportDXF.Services
|
|||||||
|
|
||||||
LogProgress(context, $"Found {items.Count} item(s).");
|
LogProgress(context, $"Found {items.Count} item(s).");
|
||||||
|
|
||||||
var exportRecord = CreateExportRecord(context, drawingNumber, outputFolder);
|
var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
|
||||||
|
|
||||||
// Auto-assign item numbers for items that don't have one
|
// Check existing BOM items and reuse item numbers, or assign new ones
|
||||||
var nextNum = int.Parse(GetNextItemNumber(drawingNumber));
|
var nextNum = int.Parse(await GetNextItemNumberAsync(drawingNumber));
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(item.ItemNo))
|
if (string.IsNullOrWhiteSpace(item.ItemNo))
|
||||||
{
|
{
|
||||||
item.ItemNo = nextNum.ToString();
|
var existingItemNo = await FindExistingItemNoAsync(exportRecord?.Id, item.PartName, item.Configuration);
|
||||||
nextNum++;
|
if (existingItemNo != null)
|
||||||
|
{
|
||||||
|
item.ItemNo = existingItemNo;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
item.ItemNo = nextNum.ToString();
|
||||||
|
nextNum++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExportItems(items, outputFolder, context, exportRecord?.Id);
|
await ExportItemsAsync(items, tempDir, context, exportRecord?.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExportDrawing(ExportContext context, string drawingNumber, string drawingOutputFolder)
|
private async Task ExportDrawingAsync(ExportContext context, string drawingNumber, string tempDir)
|
||||||
{
|
{
|
||||||
LogProgress(context, "Active document is a Drawing");
|
LogProgress(context, "Active document is a Drawing");
|
||||||
LogProgress(context, "Finding BOM tables...");
|
LogProgress(context, "Finding BOM tables...");
|
||||||
@@ -217,88 +226,46 @@ namespace ExportDXF.Services
|
|||||||
|
|
||||||
LogProgress(context, $"Found {items.Count} component(s)");
|
LogProgress(context, $"Found {items.Count} component(s)");
|
||||||
|
|
||||||
// Export drawing to PDF
|
// Export drawing to PDF in temp dir
|
||||||
var tempDir = CreateTempWorkDir();
|
|
||||||
_drawingExporter.ExportToPdf(drawing, tempDir, context);
|
_drawingExporter.ExportToPdf(drawing, tempDir, context);
|
||||||
|
|
||||||
// Copy PDF to output folder with versioning
|
// Create export record via API
|
||||||
string pdfStashPath = null;
|
var exportRecord = await CreateExportRecordAsync(context, drawingNumber);
|
||||||
string savedPdfPath = null;
|
|
||||||
|
// Upload PDF to API with versioning
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var pdfs = Directory.GetFiles(tempDir, "*.pdf");
|
var pdfs = Directory.GetFiles(tempDir, "*.pdf");
|
||||||
if (pdfs.Length > 0)
|
if (pdfs.Length > 0)
|
||||||
{
|
{
|
||||||
// Determine the destination path to stash the existing file
|
var pdfTempPath = pdfs[0];
|
||||||
var pdfFileName = !string.IsNullOrEmpty(drawingNumber)
|
var pdfHash = ContentHasher.ComputeFileHash(pdfTempPath);
|
||||||
? $"{drawingNumber}.pdf"
|
|
||||||
: Path.GetFileName(pdfs[0]);
|
|
||||||
var pdfDestPath = Path.Combine(drawingOutputFolder, pdfFileName);
|
|
||||||
|
|
||||||
pdfStashPath = _fileExportService.StashFile(pdfDestPath);
|
var uploadResult = await _apiClient.UploadPdfAsync(
|
||||||
savedPdfPath = _fileExportService.SavePdfFile(pdfs[0], drawingNumber, drawingOutputFolder);
|
pdfTempPath,
|
||||||
|
context.Equipment,
|
||||||
|
context.DrawingNo,
|
||||||
|
pdfHash,
|
||||||
|
exportRecord?.Id);
|
||||||
|
|
||||||
|
if (uploadResult != null)
|
||||||
|
{
|
||||||
|
if (uploadResult.WasUnchanged)
|
||||||
|
LogProgress(context, $"PDF unchanged: {uploadResult.FileName}", LogLevel.Info);
|
||||||
|
else if (uploadResult.IsNewFile)
|
||||||
|
LogProgress(context, $"Saved PDF: {uploadResult.FileName}", LogLevel.Info);
|
||||||
|
else
|
||||||
|
LogProgress(context, $"PDF updated: {uploadResult.FileName}", LogLevel.Info);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogProgress(context, $"PDF save error: {ex.Message}", LogLevel.Error);
|
LogProgress(context, $"PDF upload error: {ex.Message}", LogLevel.Error);
|
||||||
}
|
|
||||||
|
|
||||||
// Create export record in database
|
|
||||||
var exportRecord = CreateExportRecord(context, drawingNumber, drawingOutputFolder);
|
|
||||||
|
|
||||||
// Handle PDF versioning and update export record with hash
|
|
||||||
if (exportRecord != null && savedPdfPath != null)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
HandlePdfVersioning(savedPdfPath, exportRecord.DrawingNumber, exportRecord, context);
|
|
||||||
|
|
||||||
// Archive or discard old PDF based on hash comparison
|
|
||||||
if (pdfStashPath != null)
|
|
||||||
{
|
|
||||||
using (var db = _dbContextFactory())
|
|
||||||
{
|
|
||||||
var previousRecord = db.ExportRecords
|
|
||||||
.Where(r => r.DrawingNumber == exportRecord.DrawingNumber
|
|
||||||
&& r.PdfContentHash != null
|
|
||||||
&& r.Id != exportRecord.Id)
|
|
||||||
.OrderByDescending(r => r.Id)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (previousRecord != null && previousRecord.PdfContentHash == exportRecord.PdfContentHash)
|
|
||||||
{
|
|
||||||
_fileExportService.DiscardStash(pdfStashPath);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_fileExportService.ArchiveFile(pdfStashPath, savedPdfPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the record with the PDF hash
|
|
||||||
using (var db = _dbContextFactory())
|
|
||||||
{
|
|
||||||
db.ExportRecords.Attach(exportRecord);
|
|
||||||
db.Entry(exportRecord).Property(r => r.PdfContentHash).IsModified = true;
|
|
||||||
db.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_fileExportService.DiscardStash(pdfStashPath);
|
|
||||||
LogProgress(context, $"PDF versioning error: {ex.Message}", LogLevel.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (pdfStashPath != null)
|
|
||||||
{
|
|
||||||
// No export record - discard stash
|
|
||||||
_fileExportService.DiscardStash(pdfStashPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export parts to DXF and save BOM items
|
// Export parts to DXF and save BOM items
|
||||||
ExportItems(items, drawingOutputFolder, context, exportRecord?.Id);
|
await ExportItemsAsync(items, tempDir, context, exportRecord?.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -357,7 +324,7 @@ namespace ExportDXF.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExportItems(List<Item> items, string saveDirectory, ExportContext context, int? exportRecordId = null)
|
private async Task ExportItemsAsync(List<Item> items, string tempDir, ExportContext context, int? exportRecordId = null)
|
||||||
{
|
{
|
||||||
int successCount = 0;
|
int successCount = 0;
|
||||||
int skippedCount = 0;
|
int skippedCount = 0;
|
||||||
@@ -375,7 +342,7 @@ namespace ExportDXF.Services
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
// PartExporter will handle template drawing creation through context
|
// PartExporter will handle template drawing creation through context
|
||||||
_partExporter.ExportItem(item, saveDirectory, context);
|
_partExporter.ExportItem(item, tempDir, context);
|
||||||
|
|
||||||
// Always create BomItem for every item (sheet metal or not)
|
// Always create BomItem for every item (sheet metal or not)
|
||||||
var bomItem = new BomItem
|
var bomItem = new BomItem
|
||||||
@@ -392,23 +359,23 @@ namespace ExportDXF.Services
|
|||||||
Material = item.Material ?? ""
|
Material = item.Material ?? ""
|
||||||
};
|
};
|
||||||
|
|
||||||
// Only create CutTemplate if DXF was exported successfully
|
// Only upload and create CutTemplate if DXF was exported successfully
|
||||||
if (!string.IsNullOrEmpty(item.FileName))
|
if (!string.IsNullOrEmpty(item.LocalTempPath))
|
||||||
{
|
{
|
||||||
successCount++;
|
successCount++;
|
||||||
|
|
||||||
var dxfPath = Path.Combine(saveDirectory, item.FileName + ".dxf");
|
var uploadResult = await UploadDxfAsync(item, context);
|
||||||
bomItem.CutTemplate = new CutTemplate
|
if (uploadResult != null)
|
||||||
{
|
{
|
||||||
DxfFilePath = dxfPath,
|
bomItem.CutTemplate = new CutTemplate
|
||||||
ContentHash = item.ContentHash,
|
{
|
||||||
Thickness = item.Thickness > 0 ? item.Thickness : null,
|
DxfFilePath = uploadResult.StoredFilePath,
|
||||||
KFactor = item.KFactor > 0 ? item.KFactor : null,
|
ContentHash = item.ContentHash,
|
||||||
DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
|
Thickness = item.Thickness > 0 ? item.Thickness : null,
|
||||||
};
|
KFactor = item.KFactor > 0 ? item.KFactor : null,
|
||||||
|
DefaultBendRadius = item.BendRadius > 0 ? item.BendRadius : null
|
||||||
// Compare hash with previous export to decide archive/discard
|
};
|
||||||
HandleDxfVersioning(item, dxfPath, context);
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -418,21 +385,10 @@ namespace ExportDXF.Services
|
|||||||
// Add to UI
|
// Add to UI
|
||||||
context.BomItemCallback?.Invoke(bomItem);
|
context.BomItemCallback?.Invoke(bomItem);
|
||||||
|
|
||||||
// Save BOM item to database if we have an export record
|
// Save BOM item via API if we have an export record
|
||||||
if (exportRecordId.HasValue)
|
if (exportRecordId.HasValue)
|
||||||
{
|
{
|
||||||
try
|
await SaveBomItemAsync(exportRecordId.Value, bomItem, context);
|
||||||
{
|
|
||||||
using (var db = _dbContextFactory())
|
|
||||||
{
|
|
||||||
db.BomItems.Add(bomItem);
|
|
||||||
db.SaveChanges();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception dbEx)
|
|
||||||
{
|
|
||||||
LogProgress(context, $"Database error saving BOM item: {dbEx.Message}", LogLevel.Error);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
@@ -449,146 +405,103 @@ namespace ExportDXF.Services
|
|||||||
|
|
||||||
if (exportRecordId.HasValue)
|
if (exportRecordId.HasValue)
|
||||||
{
|
{
|
||||||
LogProgress(context, $"BOM items saved to database (ExportRecord ID: {exportRecordId.Value})", LogLevel.Info);
|
LogProgress(context, $"BOM items saved (ExportRecord ID: {exportRecordId.Value})", LogLevel.Info);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Versioning
|
#region File Upload
|
||||||
|
|
||||||
private void HandleDxfVersioning(Item item, string dxfPath, ExportContext context)
|
private async Task<ApiFileUploadResponse> UploadDxfAsync(Item item, ExportContext context)
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(item.ContentHash))
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var db = _dbContextFactory())
|
|
||||||
{
|
|
||||||
var previousCutTemplate = db.CutTemplates
|
|
||||||
.Where(ct => ct.DxfFilePath == dxfPath && ct.ContentHash != null)
|
|
||||||
.OrderByDescending(ct => ct.Id)
|
|
||||||
.FirstOrDefault();
|
|
||||||
|
|
||||||
if (previousCutTemplate != null && previousCutTemplate.ContentHash == item.ContentHash)
|
|
||||||
{
|
|
||||||
// Content unchanged - discard the stashed file
|
|
||||||
_fileExportService.DiscardStash(item.StashedFilePath);
|
|
||||||
LogProgress(context, $"DXF unchanged: {item.FileName}.dxf", LogLevel.Info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Content changed or first export - archive the old file
|
|
||||||
if (!string.IsNullOrEmpty(item.StashedFilePath))
|
|
||||||
{
|
|
||||||
_fileExportService.ArchiveFile(item.StashedFilePath, dxfPath);
|
|
||||||
LogProgress(context, $"DXF updated, previous version archived: {item.FileName}.dxf", LogLevel.Info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogProgress(context, $"Exported: {item.FileName}.dxf", LogLevel.Info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
// Don't fail the export if versioning fails - just discard the stash
|
|
||||||
_fileExportService.DiscardStash(item.StashedFilePath);
|
|
||||||
LogProgress(context, $"Versioning check failed for {item.FileName}: {ex.Message}", LogLevel.Warning);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void HandlePdfVersioning(string pdfPath, string drawingNumber, ExportRecord exportRecord, ExportContext context)
|
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var newHash = ContentHasher.ComputeFileHash(pdfPath);
|
var result = await _apiClient.UploadDxfAsync(
|
||||||
|
item.LocalTempPath,
|
||||||
|
context.Equipment,
|
||||||
|
context.DrawingNo,
|
||||||
|
item.ItemNo,
|
||||||
|
item.ContentHash);
|
||||||
|
|
||||||
using (var db = _dbContextFactory())
|
if (result.WasUnchanged)
|
||||||
{
|
LogProgress(context, $"DXF unchanged: {result.FileName}", LogLevel.Info);
|
||||||
var previousRecord = db.ExportRecords
|
else if (result.IsNewFile)
|
||||||
.Where(r => r.DrawingNumber == drawingNumber && r.PdfContentHash != null)
|
LogProgress(context, $"Exported: {result.FileName}", LogLevel.Info);
|
||||||
.OrderByDescending(r => r.Id)
|
else
|
||||||
.FirstOrDefault();
|
LogProgress(context, $"DXF updated: {result.FileName}", LogLevel.Info);
|
||||||
|
|
||||||
if (previousRecord != null && previousRecord.PdfContentHash == newHash)
|
return result;
|
||||||
{
|
|
||||||
LogProgress(context, $"PDF unchanged: {Path.GetFileName(pdfPath)}", LogLevel.Info);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LogProgress(context, $"Saved PDF: {Path.GetFileName(pdfPath)}", LogLevel.Info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (exportRecord != null)
|
|
||||||
exportRecord.PdfContentHash = newHash;
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogProgress(context, $"PDF versioning check failed: {ex.Message}", LogLevel.Warning);
|
LogProgress(context, $"DXF upload failed for {item.FileName}: {ex.Message}", LogLevel.Warning);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Database Helpers
|
|
||||||
|
|
||||||
private ExportRecord CreateExportRecord(ExportContext context, string drawingNumber, string outputFolder)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var db = _dbContextFactory())
|
|
||||||
{
|
|
||||||
db.Database.Migrate();
|
|
||||||
var record = new ExportRecord
|
|
||||||
{
|
|
||||||
DrawingNumber = drawingNumber ?? context.ActiveDocument.Title,
|
|
||||||
SourceFilePath = context.ActiveDocument.FilePath,
|
|
||||||
OutputFolder = outputFolder,
|
|
||||||
ExportedAt = DateTime.Now,
|
|
||||||
ExportedBy = System.Environment.UserName
|
|
||||||
};
|
|
||||||
|
|
||||||
db.ExportRecords.Add(record);
|
|
||||||
db.SaveChanges();
|
|
||||||
LogProgress(context, $"Created export record (ID: {record.Id})", LogLevel.Info);
|
|
||||||
return record;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LogProgress(context, $"Database error creating export record: {ex.Message}", LogLevel.Error);
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetNextItemNumber(string drawingNumber)
|
#endregion
|
||||||
|
|
||||||
|
#region API Helpers
|
||||||
|
|
||||||
|
private async Task<ExportRecord> CreateExportRecordAsync(ExportContext context, string drawingNumber)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var dto = await _apiClient.CreateExportAsync(
|
||||||
|
drawingNumber ?? context.ActiveDocument.Title,
|
||||||
|
context.Equipment ?? "",
|
||||||
|
context.DrawingNo ?? "",
|
||||||
|
context.ActiveDocument.FilePath,
|
||||||
|
"", // Output folder is now managed by the API
|
||||||
|
context.Title);
|
||||||
|
|
||||||
|
var record = new ExportRecord
|
||||||
|
{
|
||||||
|
Id = dto.Id,
|
||||||
|
DrawingNumber = dto.DrawingNumber,
|
||||||
|
EquipmentNo = dto.EquipmentNo,
|
||||||
|
DrawingNo = dto.DrawingNo,
|
||||||
|
SourceFilePath = dto.SourceFilePath,
|
||||||
|
OutputFolder = dto.OutputFolder,
|
||||||
|
ExportedAt = dto.ExportedAt,
|
||||||
|
ExportedBy = dto.ExportedBy
|
||||||
|
};
|
||||||
|
|
||||||
|
LogProgress(context, $"Created export record (ID: {record.Id})", LogLevel.Info);
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogProgress(context, $"API error creating export record: {ex.Message}", LogLevel.Error);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> FindExistingItemNoAsync(int? exportRecordId, string partName, string configurationName)
|
||||||
|
{
|
||||||
|
if (!exportRecordId.HasValue)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var existing = await _apiClient.FindExistingBomItemAsync(exportRecordId.Value, partName, configurationName);
|
||||||
|
return existing?.ItemNo;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<string> GetNextItemNumberAsync(string drawingNumber)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(drawingNumber))
|
if (string.IsNullOrEmpty(drawingNumber))
|
||||||
return "1";
|
return "1";
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var db = _dbContextFactory())
|
return await _apiClient.GetNextItemNumberAsync(drawingNumber);
|
||||||
{
|
|
||||||
var existingItems = db.ExportRecords
|
|
||||||
.Where(r => r.DrawingNumber == drawingNumber)
|
|
||||||
.SelectMany(r => r.BomItems)
|
|
||||||
.Select(b => b.ItemNo)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
int maxNum = 0;
|
|
||||||
foreach (var itemNo in existingItems)
|
|
||||||
{
|
|
||||||
if (int.TryParse(itemNo, out var num) && num > maxNum)
|
|
||||||
maxNum = num;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (maxNum + 1).ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -596,19 +509,40 @@ namespace ExportDXF.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SaveBomItem(BomItem bomItem, ExportContext context)
|
private async Task SaveBomItemAsync(int exportRecordId, BomItem bomItem, ExportContext context)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
using (var db = _dbContextFactory())
|
var apiBomItem = new ApiBomItem
|
||||||
{
|
{
|
||||||
db.BomItems.Add(bomItem);
|
ItemNo = bomItem.ItemNo,
|
||||||
db.SaveChanges();
|
PartNo = bomItem.PartNo,
|
||||||
|
SortOrder = bomItem.SortOrder,
|
||||||
|
Qty = bomItem.Qty,
|
||||||
|
TotalQty = bomItem.TotalQty,
|
||||||
|
Description = bomItem.Description,
|
||||||
|
PartName = bomItem.PartName,
|
||||||
|
ConfigurationName = bomItem.ConfigurationName,
|
||||||
|
Material = bomItem.Material
|
||||||
|
};
|
||||||
|
|
||||||
|
if (bomItem.CutTemplate != null)
|
||||||
|
{
|
||||||
|
apiBomItem.CutTemplate = new ApiCutTemplate
|
||||||
|
{
|
||||||
|
DxfFilePath = bomItem.CutTemplate.DxfFilePath,
|
||||||
|
ContentHash = bomItem.CutTemplate.ContentHash,
|
||||||
|
Thickness = bomItem.CutTemplate.Thickness,
|
||||||
|
KFactor = bomItem.CutTemplate.KFactor,
|
||||||
|
DefaultBendRadius = bomItem.CutTemplate.DefaultBendRadius
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _apiClient.CreateBomItemAsync(exportRecordId, apiBomItem);
|
||||||
}
|
}
|
||||||
catch (Exception dbEx)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogProgress(context, $"Database error saving BOM item: {dbEx.Message}", LogLevel.Error);
|
LogProgress(context, $"API error saving BOM item: {ex.Message}", LogLevel.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,11 +557,28 @@ namespace ExportDXF.Services
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CleanupTempDir(string tempDir)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(tempDir))
|
||||||
|
Directory.Delete(tempDir, recursive: true);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Best-effort cleanup
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private string ParseDrawingNumber(ExportContext context)
|
private string ParseDrawingNumber(ExportContext context)
|
||||||
{
|
{
|
||||||
// Use explicit Equipment/DrawingNo from the UI when available
|
// Use explicit Equipment/DrawingNo from the UI when available
|
||||||
if (!string.IsNullOrWhiteSpace(context?.Equipment) && !string.IsNullOrWhiteSpace(context?.DrawingNo))
|
if (!string.IsNullOrWhiteSpace(context?.Equipment))
|
||||||
return $"{context.Equipment} {context.DrawingNo}";
|
{
|
||||||
|
return !string.IsNullOrWhiteSpace(context?.DrawingNo)
|
||||||
|
? $"{context.Equipment} {context.DrawingNo}"
|
||||||
|
: context.Equipment;
|
||||||
|
}
|
||||||
|
|
||||||
// Fallback: parse from prefix or document title
|
// Fallback: parse from prefix or document title
|
||||||
var candidate = context?.FilePrefix;
|
var candidate = context?.FilePrefix;
|
||||||
@@ -637,7 +588,7 @@ namespace ExportDXF.Services
|
|||||||
var title = context?.ActiveDocument?.Title;
|
var title = context?.ActiveDocument?.Title;
|
||||||
info = string.IsNullOrWhiteSpace(title) ? null : DrawingInfo.Parse(title);
|
info = string.IsNullOrWhiteSpace(title) ? null : DrawingInfo.Parse(title);
|
||||||
}
|
}
|
||||||
return info != null ? ($"{info.EquipmentNo} {info.DrawingNo}") : null;
|
return info?.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ValidateContext(ExportContext context)
|
private void ValidateContext(ExportContext context)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using ExportDXF.Extensions;
|
using ExportDXF.Extensions;
|
||||||
using ExportDXF.Models;
|
using ExportDXF.Models;
|
||||||
using ExportDXF.Utilities;
|
using ExportDXF.Utilities;
|
||||||
using SolidWorks.Interop.sldworks;
|
using SolidWorks.Interop.sldworks;
|
||||||
@@ -18,7 +18,7 @@ namespace ExportDXF.Services
|
|||||||
/// Returns an Item with export metadata (filename, hash, sheet metal properties), or null if export failed.
|
/// Returns an Item with export metadata (filename, hash, sheet metal properties), or null if export failed.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="part">The part document to export.</param>
|
/// <param name="part">The part document to export.</param>
|
||||||
/// <param name="saveDirectory">The directory where the DXF file will be saved.</param>
|
/// <param name="saveDirectory">The temp directory where the DXF file will be saved.</param>
|
||||||
/// <param name="context">The export context.</param>
|
/// <param name="context">The export context.</param>
|
||||||
Item ExportSinglePart(PartDoc part, string saveDirectory, ExportContext context);
|
Item ExportSinglePart(PartDoc part, string saveDirectory, ExportContext context);
|
||||||
|
|
||||||
@@ -26,18 +26,15 @@ namespace ExportDXF.Services
|
|||||||
/// Exports an item (component from BOM or assembly) to DXF.
|
/// Exports an item (component from BOM or assembly) to DXF.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="item">The item to export.</param>
|
/// <param name="item">The item to export.</param>
|
||||||
/// <param name="saveDirectory">The directory where the DXF file will be saved.</param>
|
/// <param name="saveDirectory">The temp directory where the DXF file will be saved.</param>
|
||||||
/// <param name="context">The export context.</param>
|
/// <param name="context">The export context.</param>
|
||||||
void ExportItem(Item item, string saveDirectory, ExportContext context);
|
void ExportItem(Item item, string saveDirectory, ExportContext context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class PartExporter : IPartExporter
|
public class PartExporter : IPartExporter
|
||||||
{
|
{
|
||||||
private readonly IFileExportService _fileExportService;
|
public PartExporter()
|
||||||
|
|
||||||
public PartExporter(IFileExportService fileExportService)
|
|
||||||
{
|
{
|
||||||
_fileExportService = fileExportService ?? throw new ArgumentNullException(nameof(fileExportService));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Item ExportSinglePart(PartDoc part, string saveDirectory, ExportContext context)
|
public Item ExportSinglePart(PartDoc part, string saveDirectory, ExportContext context)
|
||||||
@@ -90,25 +87,17 @@ namespace ExportDXF.Services
|
|||||||
// Get material
|
// Get material
|
||||||
item.Material = part.GetMaterialPropertyName2(originalConfigName, out _);
|
item.Material = part.GetMaterialPropertyName2(originalConfigName, out _);
|
||||||
|
|
||||||
// Stash existing file before overwriting
|
|
||||||
item.StashedFilePath = _fileExportService.StashFile(savePath);
|
|
||||||
|
|
||||||
context.GetOrCreateTemplateDrawing();
|
context.GetOrCreateTemplateDrawing();
|
||||||
|
|
||||||
if (ExportPartToDxf(part, originalConfigName, savePath, context))
|
if (ExportPartToDxf(part, originalConfigName, savePath, context))
|
||||||
{
|
{
|
||||||
item.FileName = Path.GetFileNameWithoutExtension(savePath);
|
item.FileName = Path.GetFileNameWithoutExtension(savePath);
|
||||||
item.ContentHash = Utilities.ContentHasher.ComputeDxfContentHash(savePath);
|
item.ContentHash = Utilities.ContentHasher.ComputeDxfContentHash(savePath);
|
||||||
|
item.LocalTempPath = savePath;
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Export failed - restore stashed file
|
|
||||||
if (item.StashedFilePath != null && File.Exists(item.StashedFilePath))
|
|
||||||
{
|
|
||||||
File.Move(item.StashedFilePath, savePath, overwrite: true);
|
|
||||||
item.StashedFilePath = null;
|
|
||||||
}
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -155,22 +144,14 @@ namespace ExportDXF.Services
|
|||||||
|
|
||||||
var templateDrawing = context.GetOrCreateTemplateDrawing();
|
var templateDrawing = context.GetOrCreateTemplateDrawing();
|
||||||
|
|
||||||
// Stash existing file before overwriting
|
|
||||||
item.StashedFilePath = _fileExportService.StashFile(savePath);
|
|
||||||
|
|
||||||
if (ExportPartToDxf(part, item.Component.ReferencedConfiguration, savePath, context))
|
if (ExportPartToDxf(part, item.Component.ReferencedConfiguration, savePath, context))
|
||||||
{
|
{
|
||||||
item.FileName = Path.GetFileNameWithoutExtension(savePath);
|
item.FileName = Path.GetFileNameWithoutExtension(savePath);
|
||||||
item.ContentHash = Utilities.ContentHasher.ComputeDxfContentHash(savePath);
|
item.ContentHash = Utilities.ContentHasher.ComputeDxfContentHash(savePath);
|
||||||
|
item.LocalTempPath = savePath;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Export failed - restore stashed file if we have one
|
|
||||||
if (item.StashedFilePath != null && File.Exists(item.StashedFilePath))
|
|
||||||
{
|
|
||||||
File.Move(item.StashedFilePath, savePath, overwrite: true);
|
|
||||||
item.StashedFilePath = null;
|
|
||||||
}
|
|
||||||
LogExportFailure(item, context);
|
LogExportFailure(item, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user