From e8ee7dfb8e166e34c7950e90d5fe9bcf31dc351b Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Mon, 16 Dec 2019 10:33:43 +0200 Subject: Some fixes. --- .../Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index 46b4c301f..4f517165b 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -1917,11 +1917,11 @@ namespace Tango.MachineStudio.Developer.ViewModels ActiveJob.IsSynchronized = false; ActiveJob.Rml = SelectedRML; ActiveJob.EstimatedDurationMili = (int)EstimatedDuration.TotalMilliseconds; + ActiveJob.MarkModified(_activeJobDbContext); _activeJobDbContext.SaveChanges(); _machineDbContext.Entry(SelectedMachineJob).Reload(); - _machineDbContext.Entry(SelectedMachineJob).Collection(x => x.Segments).Load(); foreach (var segment in SelectedMachineJob.Segments.ToList()) -- cgit v1.3.1 From bdf56799cd6c4c42ec7a8dc36f56ddd17a5feeab Mon Sep 17 00:00:00 2001 From: Roy Ben Shabat Date: Tue, 17 Dec 2019 00:02:49 +0200 Subject: Added SOURCE to JOB. Added IS_SYNCHRONIZED to TANGO_UPDATE. Added OfflineUpdates to Synchronization. Added TangoUpdates on PPC side. --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes Software/DB/TCC/TCC.mdf | Bin 8388608 -> 8388608 bytes Software/DB/TCC/TCC_log.ldf | Bin 8388608 -> 8388608 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../ViewModels/MainViewVM.cs | 3 + .../Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 2 + .../MachineSetup/MachineSetupManager.cs | 27 +++ .../MachineUpdate/MachineUpdateManager.cs | 181 ++++++++++++++++++--- .../PPC/Tango.PPC.Common/Publish/PublishInfo.cs | 16 ++ .../DefaultMachineDataSynchronizer.cs | 33 ++++ .../Tango.PPC.Common/Web/CheckForUpdateResponse.cs | 1 + .../Tango.PPC.Common/Web/DownloadUpdateResponse.cs | 2 + .../Tango.PPC.Common/Web/MachineSetupResponse.cs | 2 + .../Web/UploadMachineDataRequest.cs | 2 + .../Web/UploadMachineDataResponse.cs | 2 + Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs | 8 + .../Tango.BL/DTO/TangoUpdateDTOBase.cs | 8 + Software/Visual_Studio/Tango.BL/Entities/Job.cs | 11 ++ .../Visual_Studio/Tango.BL/Entities/JobBase.cs | 39 +++++ .../Visual_Studio/Tango.BL/Entities/TangoUpdate.cs | 22 ++- .../Tango.BL/Entities/TangoUpdateBase.cs | 38 +++++ .../Tango.BL/Enumerations/JobSource.cs | 20 +++ .../Tango.BL/Enumerations/TangoUpdateStatuses.cs | 7 + Software/Visual_Studio/Tango.BL/Tango.BL.csproj | 3 +- Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs | 1 + .../Tango.DAL.Remote/DB/RemoteADO.edmx | 6 + .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 154 +++++++++--------- .../Tango.DAL.Remote/DB/TANGO_UPDATES.cs | 1 + .../Controllers/PPCController.cs | 31 ++++ 31 files changed, 518 insertions(+), 102 deletions(-) create mode 100644 Software/Visual_Studio/Tango.BL/Enumerations/JobSource.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index 8bce1236f..8ad9bc103 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 9e9f5d60a..9bce4a9c4 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/TCC/TCC.mdf b/Software/DB/TCC/TCC.mdf index f77c2e733..3540a7786 100644 Binary files a/Software/DB/TCC/TCC.mdf and b/Software/DB/TCC/TCC.mdf differ diff --git a/Software/DB/TCC/TCC_log.ldf b/Software/DB/TCC/TCC_log.ldf index 048d3ccb0..94b99ac61 100644 Binary files a/Software/DB/TCC/TCC_log.ldf and b/Software/DB/TCC/TCC_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 6af55afc8..e70e0e6e3 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 33e76f9de..e65b718bb 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index 4f517165b..71cbd9ffe 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -50,6 +50,7 @@ using Tango.Core.ExtensionMethods; using Tango.ColorConversion; using Tango.PMR.Exports; using Microsoft.WindowsAPICodePack.Dialogs; +using Tango.BL.Enumerations; namespace Tango.MachineStudio.Developer.ViewModels { @@ -2211,6 +2212,8 @@ namespace Tango.MachineStudio.Developer.ViewModels var settings = SettingsManager.Default.GetOrCreate(); Job newJob = new Job(); + newJob.LastUpdated = DateTime.UtcNow; + newJob.JobSource = JobSource.Remote; newJob.Name = jobName; newJob.CreationDate = DateTime.UtcNow; newJob.UserGuid = AuthenticationProvider.CurrentUser.Guid; diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 785472d0d..1eb7e1f04 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -500,6 +500,8 @@ namespace Tango.PPC.Jobs.ViewModels settings.Save(); Job job = new Job(); + job.LastUpdated = DateTime.UtcNow; + job.JobSource = JobSource.Local; job.Name = "untitled"; job.NumberOfHeads = 1; job.NumberOfUnits = 1; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs index dfa9b833b..582eec83b 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineSetup/MachineSetupManager.cs @@ -11,6 +11,8 @@ using System.Net.Http.Headers; using System.Text; using System.Threading; using System.Threading.Tasks; +using Tango.BL; +using Tango.BL.Entities; using Tango.Core; using Tango.Core.DB; using Tango.Core.ExtensionMethods; @@ -29,6 +31,7 @@ using Tango.Settings; using Tango.SharedUI.Helpers; using Tango.SQLExaminer; using Tango.Transport.Web; +using System.Data.Entity; namespace Tango.PPC.Common.MachineSetup { @@ -45,6 +48,7 @@ namespace Tango.PPC.Common.MachineSetup private PPCWebClient _client; private List _logs; private bool _isUpdating; + private DateTime _setupStartDate; #region Events @@ -164,6 +168,28 @@ namespace Tango.PPC.Common.MachineSetup } } + if (response != null) + { + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = response.Version; + update.FirmwareVersion = response.FirmwareVersion; + update.MachineGuid = (await db.Machines.FirstAsync()).Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.SetupCompleted; + update.StartDate = _setupStartDate; + update.EndDate = DateTime.UtcNow; + await db.SaveChangesAsync(); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error saving tango setup information to database."); + } + } + _isUpdating = false; } @@ -191,6 +217,7 @@ namespace Tango.PPC.Common.MachineSetup TaskCompletionSource result = new TaskCompletionSource(); MachineSetupResponse setup_response = null; + _setupStartDate = DateTime.UtcNow; try { diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs index 088e80f61..666b6813c 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/MachineUpdate/MachineUpdateManager.cs @@ -10,6 +10,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using Tango.BL; +using Tango.BL.Entities; using Tango.Core; using Tango.Core.DB; using Tango.Core.ExtensionMethods; @@ -29,6 +30,7 @@ using Tango.Settings; using Tango.SharedUI.Helpers; using Tango.SQLExaminer; using Tango.Transport.Web; +using System.Data.Entity; namespace Tango.PPC.Common.MachineUpdate { @@ -42,6 +44,7 @@ namespace Tango.PPC.Common.MachineUpdate private System.Timers.Timer _checkForUpdateTimer; private bool _isUpdating; private PPCSettings _settings; + private DateTime _updateStartDate; #region Events @@ -140,7 +143,7 @@ namespace Tango.PPC.Common.MachineUpdate }); } - private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null) + private async void OnFailed(Exception ex, TaskCompletionSource completionSource, DownloadUpdateResponse response, bool performDatabaseRollback, String dbBackupFile, String backupsFolder, String tempDbName, Tango.Core.DataSource localDataSource, String tempUpdatePackageFolder = null, PublishInfo tupPublishInfo = null) { LogManager.Log(ex, "An error occurred in machine update."); @@ -217,6 +220,8 @@ namespace Tango.PPC.Common.MachineUpdate completionSource.SetException(ex); + String logs = GetLogsStringAndClear(); + if (response != null) { try @@ -226,19 +231,65 @@ namespace Tango.PPC.Common.MachineUpdate Token = response.NotifyCompletedToken, Status = BL.Enumerations.TangoUpdateStatuses.UpdateFailed, FailedReason = ex.FlattenMessage(), - FailedLog = GetLogsStringAndClear(), + FailedLog = logs, }); } catch (Exception xx) { LogManager.Log(xx, "Error notifying update failed."); } + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = response.Version; + update.FirmwareVersion = response.FirmwareVersion; + update.MachineGuid = _machineProvider.Machine.Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.UpdateFailed; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + update.FailedReason = ex.FlattenMessage(); + update.FailedLog = logs; + await db.SaveChangesAsync(); + } + } + catch (Exception xxx) + { + LogManager.Log(xxx, "Error saving tango update information to database."); + } + } + + + if (tupPublishInfo != null) + { + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = tupPublishInfo.ApplicationVersion; + update.FirmwareVersion = tupPublishInfo.GetFirmwareVersion(); + update.MachineGuid = _machineProvider.Machine.Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.OfflineUpdateFailed; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + update.FailedReason = ex.FlattenMessage(); + update.FailedLog = logs; + await db.SaveChangesAsync(); + } + } + catch (Exception xxx) + { + LogManager.Log(xxx, "Error saving tango offline update information to database."); + } } _isUpdating = false; } - private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource) + private async void OnCompleted(MachineUpdateResult result, TaskCompletionSource completionSource, DownloadUpdateResponse response, String tempDbName, String backupsFolder, Core.DataSource localDataSource, PublishInfo tupPublishInfo = null) { await Task.Factory.StartNew(() => { @@ -299,26 +350,47 @@ namespace Tango.PPC.Common.MachineUpdate { LogManager.Log(ex, "Error notifying update completed."); } + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = response.Version; + update.FirmwareVersion = response.FirmwareVersion; + update.MachineGuid = (await db.Machines.FirstAsync()).Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.UpdateCompleted; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + await db.SaveChangesAsync(); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error saving tango update information to database."); + } } - _isUpdating = false; - } - private void OnCompleted(UpdateDBResponse response) - { - if (response != null) + if (tupPublishInfo != null) { try { - var r = _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest() + using (ObservablesContext db = ObservablesContext.CreateDefault()) { - Token = response.NotifyCompletedToken, - Status = BL.Enumerations.TangoUpdateStatuses.DatabaseCompleted, - }).Result; + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = tupPublishInfo.ApplicationVersion; + update.FirmwareVersion = tupPublishInfo.GetFirmwareVersion(); + update.MachineGuid = _machineProvider.Machine.Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.OfflineUpdateCompleted; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + await db.SaveChangesAsync(); + } } - catch (Exception ex) + catch (Exception xxx) { - LogManager.Log(ex, "Error notifying database completed."); + LogManager.Log(xxx, "Error saving tango offline update information to database."); } } @@ -357,6 +429,8 @@ namespace Tango.PPC.Common.MachineUpdate } } + String logs = GetLogsStringAndClear(); + if (response != null) { try @@ -366,13 +440,74 @@ namespace Tango.PPC.Common.MachineUpdate Token = response.NotifyCompletedToken, Status = BL.Enumerations.TangoUpdateStatuses.DatabaseFailed, FailedReason = ex.FlattenMessage(), - FailedLog = GetLogsStringAndClear(), + FailedLog = logs, }).Result; } catch (Exception xx) { LogManager.Log(xx, "Error notifying database failed."); } + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = _app_manager.Version.ToString(); + update.FirmwareVersion = _app_manager.FirmwareVersion.ToString(); + update.MachineGuid = _machineProvider.Machine.Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.DatabaseFailed; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + update.FailedReason = ex.FlattenMessage(); + update.FailedLog = logs; + db.SaveChanges(); + } + } + catch (Exception exx) + { + LogManager.Log(exx, "Error saving database update information to database."); + } + } + + _isUpdating = false; + } + + private void OnCompleted(UpdateDBResponse response) + { + if (response != null) + { + try + { + var r = _client.NotifyUpdateCompleted(new MachineUpdateCompletedRequest() + { + Token = response.NotifyCompletedToken, + Status = BL.Enumerations.TangoUpdateStatuses.DatabaseCompleted, + }).Result; + } + catch (Exception ex) + { + LogManager.Log(ex, "Error notifying database completed."); + } + + try + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + TangoUpdate update = new TangoUpdate(); + update.ApplicationVersion = _app_manager.Version.ToString(); + update.FirmwareVersion = _app_manager.FirmwareVersion.ToString(); + update.MachineGuid = _machineProvider.Machine.Guid; + update.UpdateStatus = BL.Enumerations.TangoUpdateStatuses.DatabaseCompleted; + update.StartDate = _updateStartDate; + update.EndDate = DateTime.UtcNow; + db.SaveChanges(); + } + } + catch (Exception ex) + { + LogManager.Log(ex, "Error saving database update information to database."); + } } _isUpdating = false; @@ -404,6 +539,7 @@ namespace Tango.PPC.Common.MachineUpdate /// Database tango does not exists. public async Task Update(bool setupFirmware, bool setupFPGA) { + _updateStartDate = DateTime.UtcNow; _logs.Clear(); TaskCompletionSource result = new TaskCompletionSource(); @@ -739,6 +875,7 @@ namespace Tango.PPC.Common.MachineUpdate /// public Task UpdateDB(DbCompareResult dbCompareResult, String serialNumber) { + _updateStartDate = DateTime.UtcNow; _logs.Clear(); return Task.Factory.StartNew(() => @@ -975,6 +1112,7 @@ namespace Tango.PPC.Common.MachineUpdate /// public async Task UpdateFromTUP(string fileName, bool setupFirmware, bool setupFPGA) { + _updateStartDate = DateTime.UtcNow; _logs.Clear(); TaskCompletionSource result = new TaskCompletionSource(); @@ -986,6 +1124,7 @@ namespace Tango.PPC.Common.MachineUpdate String tempDbFileName = tempDbName + ".bak"; String backupsFolder = "C:\\Backups"; bool replaceBinaries = false; + PublishInfo publishInfo = null; String serialNumber = _machineProvider.Machine.SerialNumber; @@ -1035,7 +1174,7 @@ namespace Tango.PPC.Common.MachineUpdate //Extracting publish info UpdateProgress("Exploring package", "Verifying..."); - PublishInfo publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json"))); + publishInfo = PublishInfo.FromJson(File.ReadAllText(Path.Combine(_newPackageTempFolder, "version.json"))); if (!publishInfo.IsMachineTupPackage) { @@ -1214,7 +1353,7 @@ namespace Tango.PPC.Common.MachineUpdate handler.Failed += (_, ex) => { stream.Dispose(); - OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo); }; handler.Completed += (_, __) => { @@ -1224,12 +1363,12 @@ namespace Tango.PPC.Common.MachineUpdate { UpdatePackagePath = _newPackageTempFolder, RequiresBinariesUpdate = replaceBinaries, - }, result, null, tempDbName, backupsFolder, localDataSource); + }, result, null, tempDbName, backupsFolder, localDataSource, publishInfo); }; handler.Canceled += (_, __) => { stream.Dispose(); - OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + OnFailed(new Exception("The operation has been canceled."), result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo); }; handler.Progress += (_, e) => { @@ -1242,12 +1381,12 @@ namespace Tango.PPC.Common.MachineUpdate { UpdatePackagePath = _newPackageTempFolder, RequiresBinariesUpdate = replaceBinaries, - }, result, null, tempDbName, backupsFolder, localDataSource); + }, result, null, tempDbName, backupsFolder, localDataSource, publishInfo); } } catch (Exception ex) { - OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder); + OnFailed(ex, result, null, performDatabaseRollback, dbBackupFile, backupsFolder, tempDbName, localDataSource, _newPackageTempFolder, publishInfo); } return await result.Task; diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs index df5690a05..1bbdb80d0 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Publish/PublishInfo.cs @@ -32,5 +32,21 @@ namespace Tango.PPC.Common.Publish { return JsonConvert.DeserializeObject(json); } + + public String GetFirmwareVersion() + { + Version version = new Version("1.0.0.0"); + + var s = Firmware.FileDescriptors.FirstOrDefault(x => x.Destination == VersionFileDestination.Mcu); + if (s != null) + { + if (Version.TryParse(s.Version,out version)) + { + return version.ToString(); + } + } + + return version.ToString(); + } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs index 8260eb4b3..22c3dbe20 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Synchronization/DefaultMachineDataSynchronizer.cs @@ -40,6 +40,7 @@ namespace Tango.PPC.Common.Synchronization public int MaxJobs { get; set; } public int MaxJobRuns { get; set; } public int MaxMachinesEvents { get; set; } + public int MaxOfflineUpdates { get; set; } private SynchronizationStatus _currentStatus; public SynchronizationStatus CurrentStatus @@ -80,6 +81,7 @@ namespace Tango.PPC.Common.Synchronization MaxJobs = 10; MaxJobRuns = 100; MaxMachinesEvents = 100; + MaxOfflineUpdates = 50; var settings = SettingsManager.Default.GetOrCreate(); Interval = settings.SynchronizationInterval; @@ -190,6 +192,21 @@ namespace Tango.PPC.Common.Synchronization request.MachineEvents.Add(dto); } } + + if (syncDiagnostics) + { + LogManager.Log("Checking Offline Updates..."); + + var tangoUpdates = await db.TangoUpdates.Where(x => !x.IsSynchronized && (x.Status == (int)TangoUpdateStatuses.OfflineUpdateCompleted || x.Status == (int)TangoUpdateStatuses.OfflineUpdateFailed)).Take(MaxOfflineUpdates).OrderByDescending(x => x.LastUpdated).ToListAsync(); + List dtos = new List(); + + foreach (var tangoUpdate in tangoUpdates) + { + tangoUpdate.IsSynchronized = true; + var dto = TangoUpdateDTO.FromObservable(tangoUpdate); + request.OfflineUpdates.Add(dto); + } + } } return request; @@ -247,6 +264,22 @@ namespace Tango.PPC.Common.Synchronization } } + //Finalize tango updates + foreach (var tangoUpdate in request.OfflineUpdates) + { + var failedTangoUpdate = response.FailedOfflineUpdates.SingleOrDefault(x => x.Guid == tangoUpdate.Guid); + + if (failedTangoUpdate == null) + { + var dbTangoUpdate = await db.TangoUpdates.SingleOrDefaultAsync(x => x.Guid == tangoUpdate.Guid); + dbTangoUpdate.IsSynchronized = true; + } + else + { + LogManager.Log($"Synchronization Error - TangoUpdate '{tangoUpdate.ID}' cannot be stored on the server due to the following reason:\n{failedTangoUpdate.Reason}", LogCategory.Error); + } + } + await db.SaveChangesAsync(); } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateResponse.cs index 63d870834..a857a20a1 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/CheckForUpdateResponse.cs @@ -12,6 +12,7 @@ namespace Tango.PPC.Common.Web public bool IsUpdateAvailable { get; set; } public bool IsDatabaseUpdateAvailable { get; set; } public String Version { get; set; } + public String FirmwareVersion { get; set; } public bool SetupFirmware { get; set; } public bool SetupFPGA { get; set; } public UpdateDBResponse UpdateDBResponse { get; set; } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadUpdateResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadUpdateResponse.cs index b092aedbe..2fc7e4810 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadUpdateResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/DownloadUpdateResponse.cs @@ -14,6 +14,8 @@ namespace Tango.PPC.Common.Web public String Version { get; set; } + public String FirmwareVersion { get; set; } + public String BlobAddress { get; set; } public String CdnAddress { get; set; } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/MachineSetupResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/MachineSetupResponse.cs index 714a413ab..a642eddf2 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/MachineSetupResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/MachineSetupResponse.cs @@ -14,6 +14,8 @@ namespace Tango.PPC.Common.Web public String Version { get; set; } + public String FirmwareVersion { get; set; } + public String BlobAddress { get; set; } public String CdnAddress { get; set; } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs index dc0b05988..d7475819c 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataRequest.cs @@ -14,6 +14,7 @@ namespace Tango.PPC.Common.Web public List Jobs { get; set; } public List JobRuns { get; set; } public List MachineEvents { get; set; } + public List OfflineUpdates { get; set; } public String ApplicationVersion { get; set; } public String FirmwareVersion { get; set; } @@ -22,6 +23,7 @@ namespace Tango.PPC.Common.Web Jobs = new List(); JobRuns = new List(); MachineEvents = new List(); + OfflineUpdates = new List(); } } } diff --git a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs index e4dda4013..0119c07b6 100644 --- a/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs +++ b/Software/Visual_Studio/PPC/Tango.PPC.Common/Web/UploadMachineDataResponse.cs @@ -14,6 +14,7 @@ namespace Tango.PPC.Common.Web public List FailedJobs { get; set; } public List FailedJobRuns { get; set; } public List FailedMachineEvents { get; set; } + public List FailedOfflineUpdates { get; set; } public String NotifyCompletedToken { get; set; } public UploadMachineDataResponse() @@ -21,6 +22,7 @@ namespace Tango.PPC.Common.Web FailedJobs = new List(); FailedJobRuns = new List(); FailedMachineEvents = new List(); + FailedOfflineUpdates = new List(); } } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs index c3c418f1f..2960381fc 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobDTOBase.cs @@ -282,5 +282,13 @@ namespace Tango.BL.DTO get; set; } + /// + /// source + /// + public Int32 Source + { + get; set; + } + } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/TangoUpdateDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/TangoUpdateDTOBase.cs index 5eb16841c..8e87df812 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/TangoUpdateDTOBase.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/TangoUpdateDTOBase.cs @@ -85,5 +85,13 @@ namespace Tango.BL.DTO get; set; } + /// + /// is synchronized + /// + public Boolean IsSynchronized + { + get; set; + } + } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/Job.cs b/Software/Visual_Studio/Tango.BL/Entities/Job.cs index d2a416271..c4847c5e9 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/Job.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/Job.cs @@ -100,6 +100,17 @@ namespace Tango.BL.Entities set { Status = value.ToInt32(); RaisePropertyChangedAuto(); } } + /// + /// Gets or sets the origin of the job. + /// + [NotMapped] + [JsonIgnore] + public JobSource JobSource + { + get { return (JobSource)Source; } + set { Source = value.ToInt32(); RaisePropertyChangedAuto(); } + } + /// /// Gets or sets the job property as enum instead of int. /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs index 599e379a8..45e0e3437 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/JobBase.cs @@ -83,6 +83,8 @@ namespace Tango.BL.Entities public event EventHandler IsSynchronizedChanged; + public event EventHandler SourceChanged; + public event EventHandler ColorCatalogChanged; public event EventHandler ColorSpaceChanged; @@ -1022,6 +1024,34 @@ namespace Tango.BL.Entities } } + protected Int32 _source; + + /// + /// 0 = Remote + /// 1 = Local + /// + + [Column("SOURCE")] + + public Int32 Source + { + get + { + return _source; + } + + set + { + if (_source != value) + { + _source = value; + + OnSourceChanged(value); + + } + } + } + protected ColorCatalog _colorcatalog; /// @@ -1537,6 +1567,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(IsSynchronized)); } + /// + /// Called when the Source has changed. + /// + protected virtual void OnSourceChanged(Int32 source) + { + SourceChanged?.Invoke(this, source); + RaisePropertyChanged(nameof(Source)); + } + /// /// Called when the ColorCatalog has changed. /// diff --git a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs index 4ab67b7c5..f290618cb 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdate.cs @@ -78,6 +78,19 @@ namespace Tango.BL.Entities } } + [NotMapped] + [JsonIgnore] + public bool IsOfflineUpdate + { + get + { + return + UpdateStatus == TangoUpdateStatuses.OfflineUpdateStarted || + UpdateStatus == TangoUpdateStatuses.OfflineUpdateCompleted || + UpdateStatus == TangoUpdateStatuses.OfflineUpdateFailed; + } + } + [NotMapped] [JsonIgnore] public bool IsStarted @@ -88,7 +101,8 @@ namespace Tango.BL.Entities UpdateStatus == TangoUpdateStatuses.SetupStarted || UpdateStatus == TangoUpdateStatuses.UpdateStarted || UpdateStatus == TangoUpdateStatuses.DatabaseStarted || - UpdateStatus == TangoUpdateStatuses.SynchronizationStarted; + UpdateStatus == TangoUpdateStatuses.SynchronizationStarted || + UpdateStatus == TangoUpdateStatuses.OfflineUpdateStarted; } } @@ -102,7 +116,8 @@ namespace Tango.BL.Entities UpdateStatus == TangoUpdateStatuses.SetupCompleted || UpdateStatus == TangoUpdateStatuses.UpdateCompleted || UpdateStatus == TangoUpdateStatuses.DatabaseCompleted || - UpdateStatus == TangoUpdateStatuses.SynchronizationCompleted; + UpdateStatus == TangoUpdateStatuses.SynchronizationCompleted || + UpdateStatus == TangoUpdateStatuses.OfflineUpdateCompleted; } } @@ -116,7 +131,8 @@ namespace Tango.BL.Entities UpdateStatus == TangoUpdateStatuses.SetupFailed || UpdateStatus == TangoUpdateStatuses.UpdateFailed || UpdateStatus == TangoUpdateStatuses.DatabaseFailed || - UpdateStatus == TangoUpdateStatuses.SynchronizationFailed; + UpdateStatus == TangoUpdateStatuses.SynchronizationFailed || + UpdateStatus == TangoUpdateStatuses.OfflineUpdateFailed; } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdateBase.cs b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdateBase.cs index 9f75b0021..57475977b 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/TangoUpdateBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/TangoUpdateBase.cs @@ -40,6 +40,8 @@ namespace Tango.BL.Entities public event EventHandler> EndDateChanged; + public event EventHandler IsSynchronizedChanged; + protected String _applicationversion; /// @@ -254,6 +256,33 @@ namespace Tango.BL.Entities } } + protected Boolean _issynchronized; + + /// + /// Gets or sets the tangoupdatebase is synchronized. + /// + + [Column("IS_SYNCHRONIZED")] + + public Boolean IsSynchronized + { + get + { + return _issynchronized; + } + + set + { + if (_issynchronized != value) + { + _issynchronized = value; + + OnIsSynchronizedChanged(value); + + } + } + } + /// /// Called when the ApplicationVersion has changed. /// @@ -317,6 +346,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(EndDate)); } + /// + /// Called when the IsSynchronized has changed. + /// + protected virtual void OnIsSynchronizedChanged(Boolean issynchronized) + { + IsSynchronizedChanged?.Invoke(this, issynchronized); + RaisePropertyChanged(nameof(IsSynchronized)); + } + /// /// Initializes a new instance of the class. /// diff --git a/Software/Visual_Studio/Tango.BL/Enumerations/JobSource.cs b/Software/Visual_Studio/Tango.BL/Enumerations/JobSource.cs new file mode 100644 index 000000000..2327f5b66 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Enumerations/JobSource.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.Enumerations +{ + public enum JobSource + { + /// + /// The job was originated from an application that is working directly against the main db (Machine Studio etc.) + /// + Remote = 0, + /// + /// The job was originated from an application that is working against a private local db (PPC etc.). + /// + Local = 1, + } +} diff --git a/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs b/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs index 855d8b29b..5fdf24e22 100644 --- a/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs +++ b/Software/Visual_Studio/Tango.BL/Enumerations/TangoUpdateStatuses.cs @@ -36,5 +36,12 @@ namespace Tango.BL.Enumerations SynchronizationCompleted = 301, [Description("Synchronization failed")] SynchronizationFailed = 302, + + [Description("Offline update started but did not complete")] + OfflineUpdateStarted = 400, + [Description("Offline update completed successfully")] + OfflineUpdateCompleted = 401, + [Description("Offline update failed")] + OfflineUpdateFailed = 402, } } diff --git a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj index 99855796d..6111a1a35 100644 --- a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj +++ b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj @@ -370,6 +370,7 @@ + @@ -579,7 +580,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs index 923cceacf..f30b43230 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/JOB.cs @@ -57,6 +57,7 @@ namespace Tango.DAL.Remote.DB public int EDITING_STATE { get; set; } public double LENGTH_PERCENTAGE_FACTOR { get; set; } public bool IS_SYNCHRONIZED { get; set; } + public int SOURCE { get; set; } public virtual COLOR_CATALOGS COLOR_CATALOGS { get; set; } public virtual COLOR_SPACES COLOR_SPACES { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index 83e251c1e..f8f4f9505 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -637,6 +637,7 @@ + @@ -1015,6 +1016,7 @@ + @@ -3734,6 +3736,7 @@ + @@ -4172,6 +4175,7 @@ + @@ -6020,6 +6024,7 @@ + @@ -6442,6 +6447,7 @@ + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index 77b14d7c2..f13138208 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,83 +5,83 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/TANGO_UPDATES.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/TANGO_UPDATES.cs index d91e9920c..b591f562c 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/TANGO_UPDATES.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/TANGO_UPDATES.cs @@ -25,5 +25,6 @@ namespace Tango.DAL.Remote.DB public string FAILED_LOG { get; set; } public System.DateTime START_DATE { get; set; } public Nullable END_DATE { get; set; } + public bool IS_SYNCHRONIZED { get; set; } } } diff --git a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs index 77b3a180f..4bde9148a 100644 --- a/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs +++ b/Software/Visual_Studio/Web/Tango.MachineService/Controllers/PPCController.cs @@ -107,6 +107,7 @@ namespace Tango.MachineService.Controllers var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); response.Version = latest_machine_version.Version; + response.FirmwareVersion = latest_machine_version.FirmwareVersion; var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); @@ -195,6 +196,7 @@ namespace Tango.MachineService.Controllers var latest_machine_version = db.TangoVersions.Where(x => x.MachineVersionGuid == machine_version.Guid).ToList().OrderByDescending(x => Version.Parse(x.Version)).FirstOrDefault(); response.Version = latest_machine_version.Version; + response.FirmwareVersion = latest_machine_version.FirmwareVersion; var manager = new BlobStorageManager(); var container = manager.GetContainer(MachineServiceConfig.TANGO_VERSIONS_CONTAINER); @@ -313,6 +315,7 @@ namespace Tango.MachineService.Controllers } response.Version = latest_machine_version.Version; + response.FirmwareVersion = latest_machine_version.FirmwareVersion; //Compare database @@ -588,6 +591,34 @@ namespace Tango.MachineService.Controllers } } } + + //Insert TangoUpdates. + foreach (var dto in request.OfflineUpdates) + { + using (ObservablesContext db = ObservablesContextHelper.CreateContext()) + { + try + { + var update = dto.ToObservable(); + update.ID = 0; + update.IsSynchronized = true; + + if (db.TangoUpdates.SingleOrDefault(x => x.Guid == update.Guid) == null) + { + db.TangoUpdates.Add(update); + db.SaveChanges(); + } + } + catch (Exception ex) + { + response.FailedOfflineUpdates.Add(new SynchronizationFailedEntity() + { + Guid = dto.Guid, + Reason = ex.FlattenMessage(), + }); + } + } + } } catch (Exception ex) { -- cgit v1.3.1 From b98fb311b28c8e36b7b44775c641083d501ef92a Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Tue, 17 Dec 2019 12:57:27 +0200 Subject: Add JobSource handling on PPC and Machine Studio Job Import. --- .../Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs | 1 + .../Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs | 1 + 2 files changed, 2 insertions(+) (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer') diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index 71cbd9ffe..ceb093be2 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -2606,6 +2606,7 @@ namespace Tango.MachineStudio.Developer.ViewModels var bytes = File.ReadAllBytes(file); var jobFile = JobFile.Parser.ParseFrom(bytes); var job = await Job.FromJobFile(jobFile, SelectedMachine.Guid, AuthenticationProvider.CurrentUser.Guid); + job.JobSource = JobSource.Remote; _machineDbContext.Jobs.Add(job); } diff --git a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs index 1eb7e1f04..109e3e27a 100644 --- a/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs +++ b/Software/Visual_Studio/PPC/Modules/Tango.PPC.Jobs/ViewModels/JobsViewVM.cs @@ -809,6 +809,7 @@ namespace Tango.PPC.Jobs.ViewModels { JobFile jFile = JobFile.Parser.ParseFrom(File.ReadAllBytes(jobFile.Path)); var job = await Job.FromJobFile(jFile, MachineProvider.Machine.Guid, AuthenticationProvider.CurrentUser.Guid); + job.JobSource = JobSource.Local; jobContext.Jobs.Add(job); await jobContext.SaveChangesAsync(); LoadJobs(() => -- cgit v1.3.1 From 74d6b86d46819376f0389d6fd4055e40e4e01598 Mon Sep 17 00:00:00 2001 From: Roy Ben-Shabat Date: Tue, 17 Dec 2019 20:04:34 +0200 Subject: Started working on Action Logs !!! --- Software/DB/PPC/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/PPC/Tango_log.ldf | Bin 53673984 -> 53673984 bytes Software/DB/Tango.mdf | Bin 75497472 -> 75497472 bytes Software/DB/Tango_log.ldf | Bin 22675456 -> 22675456 bytes .../ViewModels/MainViewVM.cs | 12 +- .../Tango.MachineStudio.UI/ViewModelLocator.cs | 3 + .../Tango.BL/ActionLogs/BasicActionLogComparer.cs | 181 +++++++++++++ .../Tango.BL/ActionLogs/DefaultActionLogManager.cs | 122 +++++++++ .../Tango.BL/ActionLogs/IActionLogComparable.cs | 21 ++ .../Tango.BL/ActionLogs/IActionLogManager.cs | 23 ++ .../Visual_Studio/Tango.BL/DTO/ActionLogDTO.cs | 14 + .../Visual_Studio/Tango.BL/DTO/ActionLogDTOBase.cs | 73 ++++++ .../Visual_Studio/Tango.BL/DTO/BrushStopDTO.cs | 5 +- Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs | 7 + .../Visual_Studio/Tango.BL/Entities/ActionLog.cs | 60 +++++ .../Tango.BL/Entities/ActionLogBase.cs | 282 +++++++++++++++++++++ Software/Visual_Studio/Tango.BL/Entities/Job.cs | 2 + .../Visual_Studio/Tango.BL/Entities/UserBase.cs | 38 +++ .../Tango.BL/Enumerations/ActionLogType.cs | 90 +++++++ .../Visual_Studio/Tango.BL/ObservableEntity.cs | 28 +- .../Visual_Studio/Tango.BL/ObservableEntityDTO.cs | 24 +- .../Visual_Studio/Tango.BL/ObservablesContext.cs | 8 + .../ObservablesEntitiesAdapterExtension.cs | 38 +++ .../ObservablesStaticCollectionsExtension.cs | 38 +++ Software/Visual_Studio/Tango.BL/Tango.BL.csproj | 12 +- .../Tango.BL/ValueObjects/ActionLogDifference.cs | 16 ++ .../Tango.DAL.Remote/DB/ACTION_LOGS.cs | 29 +++ .../Tango.DAL.Remote/DB/RemoteADO.Context.cs | 1 + .../Tango.DAL.Remote/DB/RemoteADO.Designer.cs | 2 +- .../Tango.DAL.Remote/DB/RemoteADO.edmx | 79 ++++++ .../Tango.DAL.Remote/DB/RemoteADO.edmx.diagram | 156 ++++++------ Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs | 3 + .../Tango.DAL.Remote/Tango.DAL.Remote.csproj | 5 +- 33 files changed, 1288 insertions(+), 84 deletions(-) create mode 100644 Software/Visual_Studio/Tango.BL/ActionLogs/BasicActionLogComparer.cs create mode 100644 Software/Visual_Studio/Tango.BL/ActionLogs/DefaultActionLogManager.cs create mode 100644 Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogComparable.cs create mode 100644 Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogManager.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/ActionLogDTO.cs create mode 100644 Software/Visual_Studio/Tango.BL/DTO/ActionLogDTOBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/ActionLog.cs create mode 100644 Software/Visual_Studio/Tango.BL/Entities/ActionLogBase.cs create mode 100644 Software/Visual_Studio/Tango.BL/Enumerations/ActionLogType.cs create mode 100644 Software/Visual_Studio/Tango.BL/ValueObjects/ActionLogDifference.cs create mode 100644 Software/Visual_Studio/Tango.DAL.Remote/DB/ACTION_LOGS.cs (limited to 'Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer') diff --git a/Software/DB/PPC/Tango.mdf b/Software/DB/PPC/Tango.mdf index 41603a45f..4d696d2c1 100644 Binary files a/Software/DB/PPC/Tango.mdf and b/Software/DB/PPC/Tango.mdf differ diff --git a/Software/DB/PPC/Tango_log.ldf b/Software/DB/PPC/Tango_log.ldf index 12b0bd50c..9e60e0704 100644 Binary files a/Software/DB/PPC/Tango_log.ldf and b/Software/DB/PPC/Tango_log.ldf differ diff --git a/Software/DB/Tango.mdf b/Software/DB/Tango.mdf index 5d5ff5ddb..a4bdfc14b 100644 Binary files a/Software/DB/Tango.mdf and b/Software/DB/Tango.mdf differ diff --git a/Software/DB/Tango_log.ldf b/Software/DB/Tango_log.ldf index 4ff9f3fd3..2fe319056 100644 Binary files a/Software/DB/Tango_log.ldf and b/Software/DB/Tango_log.ldf differ diff --git a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs index ceb093be2..d598e2458 100644 --- a/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs +++ b/Software/Visual_Studio/MachineStudio/Modules/Tango.MachineStudio.Developer/ViewModels/MainViewVM.cs @@ -51,6 +51,8 @@ using Tango.ColorConversion; using Tango.PMR.Exports; using Microsoft.WindowsAPICodePack.Dialogs; using Tango.BL.Enumerations; +using Tango.BL.DTO; +using Tango.BL.ActionLogs; namespace Tango.MachineStudio.Developer.ViewModels { @@ -86,6 +88,8 @@ namespace Tango.MachineStudio.Developer.ViewModels private TaskItem _preparingTaskItem; private IColorConverter _converter; private string _current_job_string; + private JobDTO _beforeSaveJobDTO; + private IActionLogManager _actionLogManager; #region Properties @@ -748,7 +752,7 @@ namespace Tango.MachineStudio.Developer.ViewModels /// /// The application manager. /// The notification provider. - public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IDiagnosticsFrameProvider diagnosticsFrameProvider, IVideoCaptureProvider videoCaptureProvider, DeveloperNavigationManager navigation, INavigationManager navigationManager, IAuthenticationProvider authentication, IEventLogger eventLogger, ISpeechProvider speech) + public MainViewVM(IStudioApplicationManager applicationManager, INotificationProvider notificationProvider, IDiagnosticsFrameProvider diagnosticsFrameProvider, IVideoCaptureProvider videoCaptureProvider, DeveloperNavigationManager navigation, INavigationManager navigationManager, IAuthenticationProvider authentication, IEventLogger eventLogger, ISpeechProvider speech, IActionLogManager actionLogManager) { _converter = new DefaultColorConverter(); @@ -757,6 +761,7 @@ namespace Tango.MachineStudio.Developer.ViewModels AuthenticationProvider = authentication; + _actionLogManager = actionLogManager; _notification = notificationProvider; _speech = speech; _navigation = navigation; @@ -1848,6 +1853,7 @@ namespace Tango.MachineStudio.Developer.ViewModels //_activeJobDbContext.IdsPacks.Where(x => x.ConfigurationGuid == ActiveJob.Machine.ConfigurationGuid).ToList(); + _beforeSaveJobDTO = JobDTO.FromObservable(ActiveJob); LogManager.Log("Setting selected segment..."); @@ -1921,6 +1927,10 @@ namespace Tango.MachineStudio.Developer.ViewModels ActiveJob.MarkModified(_activeJobDbContext); _activeJobDbContext.SaveChanges(); + var afterJobDTO = JobDTO.FromObservable(ActiveJob); + _actionLogManager.InsertLog(ActionLogType.JobSaved, AuthenticationProvider.CurrentUser, _beforeSaveJobDTO.Name, _beforeSaveJobDTO, afterJobDTO, "Job saved from research module in Machine Studio.").GetAwaiter().GetResult(); + _beforeSaveJobDTO = afterJobDTO; + _machineDbContext.Entry(SelectedMachineJob).Reload(); _machineDbContext.Entry(SelectedMachineJob).Collection(x => x.Segments).Load(); diff --git a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs index 25843d1c3..a61f14746 100644 --- a/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs +++ b/Software/Visual_Studio/MachineStudio/Tango.MachineStudio.UI/ViewModelLocator.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using System.Windows; +using Tango.BL.ActionLogs; using Tango.Core.DI; using Tango.Integration.ExternalBridge; using Tango.Logging; @@ -70,6 +71,7 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); TangoIOC.Default.Unregister(); + TangoIOC.Default.Unregister(); @@ -93,6 +95,7 @@ namespace Tango.MachineStudio.UI TangoIOC.Default.Register(); TangoIOC.Default.Register(); TangoIOC.Default.Register(); + TangoIOC.Default.Register(new DefaultActionLogManager() { ThrowExceptions = false }); TangoIOC.Default.Register(new TeamFoundationServiceExtendedClient("https://twinetfs.visualstudio.com", String.Empty, "szzfokrceo4rhd4eqi5qpmxn3pa5iwl3q7tlqd36l2m7smz2ynoa")); diff --git a/Software/Visual_Studio/Tango.BL/ActionLogs/BasicActionLogComparer.cs b/Software/Visual_Studio/Tango.BL/ActionLogs/BasicActionLogComparer.cs new file mode 100644 index 000000000..61fc373a8 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ActionLogs/BasicActionLogComparer.cs @@ -0,0 +1,181 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.ValueObjects; + +namespace Tango.BL.ActionLogs +{ + public class BasicActionLogComparer + { + public Task> Compare(IActionLogComparable before, IActionLogComparable after) + { + return Task.Factory.StartNew>(() => + { + List diffs = new List(); + + Compare(diffs, before, after, null); + + return diffs; + }); + } + + private void Compare(List diffs, Object before, Object after, HashSet scannedObjects) + { + if (scannedObjects == null) + { + scannedObjects = new HashSet(); + } + + if (before == null && after == null) return; + + if (before != null) + { + if (scannedObjects.Contains(before)) return; + scannedObjects.Add(before); + } + + if (after != null) + { + if (scannedObjects.Contains(after)) return; + scannedObjects.Add(after); + } + + String component = GetComponentName(before, after); + + foreach (var prop in GetProperties(before, after)) + { + if (GetShouldIgnore(prop, before, after)) continue; + + if (prop.PropertyType.IsPrimitive || prop.PropertyType.IsValueType || prop.PropertyType == typeof(String)) + { + object beforeValue = null; + object afterValue = null; + + if (before != null) + { + beforeValue = prop.GetValue(before); + } + + if (after != null) + { + afterValue = prop.GetValue(after); + } + + if (afterValue == null && beforeValue != null) AddDiff(diffs, component, prop.Name, beforeValue, afterValue); + if (afterValue != null && beforeValue == null) AddDiff(diffs, component, prop.Name, beforeValue, afterValue); + + if (afterValue != null && beforeValue != null) + { + if (!afterValue.Equals(beforeValue)) + { + AddDiff(diffs, component, prop.Name, beforeValue, afterValue); + } + } + } + else if (!prop.PropertyType.IsGenericType) + { + object beforePropInstance = null; + object afterPropInstance = null; + + if (before != null) + { + beforePropInstance = prop.GetValue(before); + } + + if (after != null) + { + afterPropInstance = prop.GetValue(after); + } + + Compare(diffs, beforePropInstance, afterPropInstance, scannedObjects); + } + else + { + IList beforeCollection = null; + IList afterCollection = null; + + if (before != null) + { + beforeCollection = prop.GetValue(before) as IList; + } + + if (after != null) + { + afterCollection = prop.GetValue(after) as IList; + } + + if (beforeCollection != null && beforeCollection == null) + { + for (int i = 0; i < beforeCollection.Count; i++) + { + Compare(diffs, beforeCollection[i], null, scannedObjects); + } + } + else if (beforeCollection == null && afterCollection != null) + { + for (int i = 0; i < afterCollection.Count; i++) + { + Compare(diffs, null, afterCollection[i], scannedObjects); + } + } + + if (beforeCollection != null && afterCollection != null) + { + for (int i = 0; i < Math.Max(beforeCollection.Count, afterCollection.Count); i++) + { + var beforeItem = i < beforeCollection.Count ? beforeCollection[i] : null; + var afterItem = i < afterCollection.Count ? afterCollection[i] : null; + Compare(diffs, beforeItem, afterItem, scannedObjects); + } + } + } + } + } + + private void AddDiff(List diffs, String component, String property, object before, object after) + { + diffs.Add(new ActionLogDifference() + { + Component = component, + Property = property, + Before = before, + After = after + }); + } + + private String GetComponentName(Object before, Object after) + { + return after != null ? after.GetType().Name : before.GetType().Name; + } + + private PropertyInfo GetProperty(String name, Object before, Object after) + { + return after != null ? after.GetType().GetProperty(name) : before.GetType().GetProperty(name); + } + + private List GetProperties(BindingFlags flags, Object before, Object after) + { + return after != null ? after.GetType().GetProperties(flags).ToList() : before.GetType().GetProperties(flags).ToList(); + } + + private List GetProperties(Object before, Object after) + { + return after != null ? after.GetType().GetProperties().ToList() : before.GetType().GetProperties().ToList(); + } + + private bool GetShouldIgnore(PropertyInfo prop, Object before, Object after) + { + var beforeCast = before as IActionLogComparable; + var afterCast = after as IActionLogComparable; + + if (beforeCast != null) return beforeCast.ShouldActionLogIgnore(prop.Name); + if (afterCast != null) return afterCast.ShouldActionLogIgnore(prop.Name); + + return false; + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/ActionLogs/DefaultActionLogManager.cs b/Software/Visual_Studio/Tango.BL/ActionLogs/DefaultActionLogManager.cs new file mode 100644 index 000000000..23562bee0 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ActionLogs/DefaultActionLogManager.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.BL.ValueObjects; +using Tango.Core; +using Tango.Core.ExtensionMethods; + +namespace Tango.BL.ActionLogs +{ + public class DefaultActionLogManager : ExtendedObject, IActionLogManager + { + public bool ThrowExceptions { get; set; } + + public DefaultActionLogManager() + { + ThrowExceptions = true; + } + + public async Task InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, List differences, string message = null) + { + using (ObservablesContext db = ObservablesContext.CreateDefault()) + { + try + { + ActionLog log = new ActionLog(); + log.ActionType = type; + log.LastUpdated = DateTime.UtcNow; + log.UserGuid = userGuid; + log.RelatedObjectName = relatedObjectName; + log.RelatedObjectGuid = relatedObjectGuid; + log.Message = message; + log.Differences = differences; + + db.ActionLogs.Add(log); + + await db.SaveChangesAsync(); + + LogManager.Log($"Action log '{type}' inserted."); + + if (differences != null && differences.Count > 0) + { + Debug.WriteLine($"Action log differences:\n{differences.ToJsonString()}"); + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error inserting action log '{type}'."); + + if (ThrowExceptions) + { + throw ex; + } + } + } + } + + public async Task InsertLog(ActionLogType type, string userGuid, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null) + { + List diffs = null; + + try + { + if (relatedObjectAfter != null) + { + diffs = await relatedObjectAfter.CompareTo(relatedObjectBefore); + } + else + { + diffs = await relatedObjectBefore.CompareTo(relatedObjectAfter); + } + } + catch (Exception ex) + { + LogManager.Log(ex, $"Error while comparing for action log '{type}'."); + + if (ThrowExceptions) + { + throw ex; + } + } + + if (diffs.Count > 0) + { + await InsertLog(type, userGuid, relatedObjectName, relatedObjectAfter.Guid, diffs, message); + } + else + { + LogManager.Log($"Action log '{type}' was about to be inserted but skipped due to no differences."); + } + } + + public Task InsertLog(ActionLogType type, User user, string relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, string message = null) + { + return InsertLog(type, user.Guid, relatedObjectName, relatedObjectBefore, relatedObjectAfter, message); + } + + public Task InsertLog(ActionLogType type, string userGuid, string relatedObjectName, string relatedObjectGuid, string message = null) + { + return InsertLog(type, userGuid, relatedObjectName, relatedObjectGuid, null, message); + } + + public Task InsertLog(ActionLogType type, User user, string relatedObjectName, IObservableEntity relatedObject, string message = null) + { + return InsertLog(type, user.Guid, relatedObjectName, relatedObject?.Guid, message); + } + + public Task InsertLog(ActionLogType type, string userGuid, string message = null) + { + return InsertLog(type, userGuid, null, null, message); + } + + public Task InsertLog(ActionLogType type, User user, string message = null) + { + return InsertLog(type, user.Guid, message); + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogComparable.cs b/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogComparable.cs new file mode 100644 index 000000000..de534141b --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogComparable.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.ValueObjects; + +namespace Tango.BL.ActionLogs +{ + public interface IActionLogComparable + { + String Guid { get; } + Task> CompareTo(IActionLogComparable before); + bool ShouldActionLogIgnore(String propName); + } + + public interface IActionLogComparable : IActionLogComparable where T : class + { + Task> CompareTo(T before); + } +} diff --git a/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogManager.cs b/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogManager.cs new file mode 100644 index 000000000..fd903bbba --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ActionLogs/IActionLogManager.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; +using Tango.BL.Enumerations; +using Tango.BL.ValueObjects; + +namespace Tango.BL.ActionLogs +{ + public interface IActionLogManager + { + bool ThrowExceptions { get; set; } + Task InsertLog(ActionLogType type, String userGuid, String relatedObjectName, String relatedObjectGuid, List differences, String message = null); + Task InsertLog(ActionLogType type, String userGuid, String relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, String message = null); + Task InsertLog(ActionLogType type, User user, String relatedObjectName, IActionLogComparable relatedObjectBefore, IActionLogComparable relatedObjectAfter, String message = null); + Task InsertLog(ActionLogType type, String userGuid, String relatedObjectName, String relatedObjectGuid, String message = null); + Task InsertLog(ActionLogType type, User user, String relatedObjectName, IObservableEntity relatedObject, String message = null); + Task InsertLog(ActionLogType type, String userGuid, String message = null); + Task InsertLog(ActionLogType type, User user, String message = null); + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTO.cs new file mode 100644 index 000000000..a847c6f24 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTO.cs @@ -0,0 +1,14 @@ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.DTO +{ + public class ActionLogDTO : ActionLogDTOBase + { + + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTOBase.cs b/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTOBase.cs new file mode 100644 index 000000000..24cf4e94f --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/DTO/ActionLogDTOBase.cs @@ -0,0 +1,73 @@ + +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Entities; + +namespace Tango.BL.DTO +{ + public abstract class ActionLogDTOBase : ObservableEntityDTO + { + + /// + /// type + /// + public Int32 Type + { + get; set; + } + + /// + /// user guid + /// + public String UserGuid + { + get; set; + } + + /// + /// related object name + /// + public String RelatedObjectName + { + get; set; + } + + /// + /// related object guid + /// + public String RelatedObjectGuid + { + get; set; + } + + /// + /// message + /// + public String Message + { + get; set; + } + + /// + /// difference + /// + public String Difference + { + get; set; + } + + } +} diff --git a/Software/Visual_Studio/Tango.BL/DTO/BrushStopDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/BrushStopDTO.cs index 447509ba7..585f2f2ee 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/BrushStopDTO.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/BrushStopDTO.cs @@ -9,6 +9,9 @@ namespace Tango.BL.DTO { public class BrushStopDTO : BrushStopDTOBase { - + protected override bool OnShouldActionLogIgnore(string propName) + { + return propName == nameof(Corrected); + } } } diff --git a/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs b/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs index 7ee6c9bb0..36f7ea9be 100644 --- a/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs +++ b/Software/Visual_Studio/Tango.BL/DTO/JobDTO.cs @@ -15,5 +15,12 @@ namespace Tango.BL.DTO { Segments = new List(); } + + protected override bool OnShouldActionLogIgnore(string propName) + { + return propName == nameof(JobDTO.LastRun) || + propName == nameof(JobDTO.Status) || + propName == nameof(JobDTO.IsSynchronized); + } } } diff --git a/Software/Visual_Studio/Tango.BL/Entities/ActionLog.cs b/Software/Visual_Studio/Tango.BL/Entities/ActionLog.cs new file mode 100644 index 000000000..af88ee7f1 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/ActionLog.cs @@ -0,0 +1,60 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Tango.BL.Enumerations; +using Tango.BL.ValueObjects; + +namespace Tango.BL.Entities +{ + public class ActionLog : ActionLogBase + { + private List _differences; + + [NotMapped] + [JsonIgnore] + public ActionLogType ActionType + { + get { return (ActionLogType)Type; } + set { Type = value.ToInt32(); RaisePropertyChanged(nameof(ActionType)); } + } + + [NotMapped] + [JsonIgnore] + public List Differences + { + get + { + if (_differences != null) + { + try + { + _differences = JsonConvert.DeserializeObject>(Difference); + } + catch + { + _differences = new List(); + } + } + else + { + _differences = new List(); + } + + return _differences; + } + set + { + _differences = value; + + if (_differences != null) + { + Difference = JsonConvert.SerializeObject(_differences); + } + } + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/ActionLogBase.cs b/Software/Visual_Studio/Tango.BL/Entities/ActionLogBase.cs new file mode 100644 index 000000000..077c834d2 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Entities/ActionLogBase.cs @@ -0,0 +1,282 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Tango Observables Generator +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. Do not modify! +// +//------------------------------------------------------------------------------ + +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; +using System.Xml.Serialization; +using Newtonsoft.Json; +using System.Linq; +using Tango.DAL.Remote.DB; +using Tango.Core; +using System.ComponentModel; + +namespace Tango.BL.Entities +{ + [Table("ACTION_LOGS")] + public abstract class ActionLogBase : ObservableEntity + { + + public event EventHandler TypeChanged; + + public event EventHandler RelatedObjectNameChanged; + + public event EventHandler MessageChanged; + + public event EventHandler DifferenceChanged; + + public event EventHandler UserChanged; + + protected Int32 _type; + + /// + /// Gets or sets the actionlogbase type. + /// + + [Column("TYPE")] + + public Int32 Type + { + get + { + return _type; + } + + set + { + if (_type != value) + { + _type = value; + + OnTypeChanged(value); + + } + } + } + + protected String _userguid; + + /// + /// Gets or sets the actionlogbase user guid. + /// + + [Column("USER_GUID")] + [ForeignKey("User")] + + public String UserGuid + { + get + { + return _userguid; + } + + set + { + if (_userguid != value) + { + _userguid = value; + + } + } + } + + protected String _relatedobjectname; + + /// + /// Gets or sets the actionlogbase related object name. + /// + + [Column("RELATED_OBJECT_NAME")] + + public String RelatedObjectName + { + get + { + return _relatedobjectname; + } + + set + { + if (_relatedobjectname != value) + { + _relatedobjectname = value; + + OnRelatedObjectNameChanged(value); + + } + } + } + + protected String _relatedobjectguid; + + /// + /// Gets or sets the actionlogbase related object guid. + /// + + [Column("RELATED_OBJECT_GUID")] + + public String RelatedObjectGuid + { + get + { + return _relatedobjectguid; + } + + set + { + if (_relatedobjectguid != value) + { + _relatedobjectguid = value; + + } + } + } + + protected String _message; + + /// + /// Gets or sets the actionlogbase message. + /// + + [Column("MESSAGE")] + + public String Message + { + get + { + return _message; + } + + set + { + if (_message != value) + { + _message = value; + + OnMessageChanged(value); + + } + } + } + + protected String _difference; + + /// + /// Gets or sets the actionlogbase difference. + /// + + [Column("DIFFERENCE")] + + public String Difference + { + get + { + return _difference; + } + + set + { + if (_difference != value) + { + _difference = value; + + OnDifferenceChanged(value); + + } + } + } + + protected User _user; + + /// + /// Gets or sets the actionlogbase user. + /// + + [XmlIgnore] + [JsonIgnore] + public virtual User User + { + get + { + return _user; + } + + set + { + if (_user != value) + { + _user = value; + + if (User != null) + { + UserGuid = User.Guid; + } + + OnUserChanged(value); + + } + } + } + + /// + /// Called when the Type has changed. + /// + protected virtual void OnTypeChanged(Int32 type) + { + TypeChanged?.Invoke(this, type); + RaisePropertyChanged(nameof(Type)); + } + + /// + /// Called when the RelatedObjectName has changed. + /// + protected virtual void OnRelatedObjectNameChanged(String relatedobjectname) + { + RelatedObjectNameChanged?.Invoke(this, relatedobjectname); + RaisePropertyChanged(nameof(RelatedObjectName)); + } + + /// + /// Called when the Message has changed. + /// + protected virtual void OnMessageChanged(String message) + { + MessageChanged?.Invoke(this, message); + RaisePropertyChanged(nameof(Message)); + } + + /// + /// Called when the Difference has changed. + /// + protected virtual void OnDifferenceChanged(String difference) + { + DifferenceChanged?.Invoke(this, difference); + RaisePropertyChanged(nameof(Difference)); + } + + /// + /// Called when the User has changed. + /// + protected virtual void OnUserChanged(User user) + { + UserChanged?.Invoke(this, user); + RaisePropertyChanged(nameof(User)); + } + + /// + /// Initializes a new instance of the class. + /// + public ActionLogBase() : base() + { + } + } +} diff --git a/Software/Visual_Studio/Tango.BL/Entities/Job.cs b/Software/Visual_Studio/Tango.BL/Entities/Job.cs index c4847c5e9..1a5883557 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/Job.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/Job.cs @@ -10,8 +10,10 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; using System.Windows.Media.Imaging; +using Tango.BL.ActionLogs; using Tango.BL.Builders; using Tango.BL.Enumerations; +using Tango.BL.ValueObjects; using Tango.Core; using Tango.Core.ExtensionMethods; using Tango.Logging; diff --git a/Software/Visual_Studio/Tango.BL/Entities/UserBase.cs b/Software/Visual_Studio/Tango.BL/Entities/UserBase.cs index 5445b2980..805cf9d57 100644 --- a/Software/Visual_Studio/Tango.BL/Entities/UserBase.cs +++ b/Software/Visual_Studio/Tango.BL/Entities/UserBase.cs @@ -34,6 +34,8 @@ namespace Tango.BL.Entities public event EventHandler> LastLoginChanged; + public event EventHandler> ActionLogsChanged; + public event EventHandler
AddressChanged; public event EventHandler ContactChanged; @@ -236,6 +238,31 @@ namespace Tango.BL.Entities } } + protected SynchronizedObservableCollection _actionlogs; + + /// + /// Gets or sets the userbase action logs. + /// + + public virtual SynchronizedObservableCollection ActionLogs + { + get + { + return _actionlogs; + } + + set + { + if (_actionlogs != value) + { + _actionlogs = value; + + OnActionLogsChanged(value); + + } + } + } + protected Address _address; /// @@ -493,6 +520,15 @@ namespace Tango.BL.Entities RaisePropertyChanged(nameof(LastLogin)); } + /// + /// Called when the ActionLogs has changed. + /// + protected virtual void OnActionLogsChanged(SynchronizedObservableCollection actionlogs) + { + ActionLogsChanged?.Invoke(this, actionlogs); + RaisePropertyChanged(nameof(ActionLogs)); + } + /// /// Called when the Address has changed. /// @@ -571,6 +607,8 @@ namespace Tango.BL.Entities public UserBase() : base() { + ActionLogs = new SynchronizedObservableCollection(); + Jobs = new SynchronizedObservableCollection(); MachineStudioVersions = new SynchronizedObservableCollection(); diff --git a/Software/Visual_Studio/Tango.BL/Enumerations/ActionLogType.cs b/Software/Visual_Studio/Tango.BL/Enumerations/ActionLogType.cs new file mode 100644 index 000000000..94eb07cda --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/Enumerations/ActionLogType.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.Enumerations +{ + public enum ActionLogType + { + //Organizations and Users + [Description("Organization Created")] + OrganizationCreated = 1, + [Description("Organization Deleted")] + OrganizationDeleted = 2, + [Description("Organization Saved")] + OrganizationSaved = 3, + [Description("User Created")] + UserCreated = 4, + [Description("User Deleted")] + UserDeleted = 5, + [Description("User Saved")] + UserSaved = 6, + [Description("User Login")] + UserLogin = 7, + [Description("User Logout")] + UserLogout = 8, + + //Hardware Version + [Description("Hardware Version Created")] + HardwareVersionCreated = 100, + [Description("Hardware Version Deleted")] + HardwareVersionDeleted = 101, + [Description("Hardware Version Saved")] + HardwareVersionSaved = 102, + + //RML + [Description("RML Created")] + RmlCreated = 200, + [Description("RML Deleted")] + RmlDeleted = 201, + [Description("RML Saved")] + RmlSaved = 202, + + //Jobs + [Description("Job Created")] + JobCreated = 300, + [Description("Job Deleted")] + JobDeleted = 301, + [Description("Job Saved")] + JobSaved = 302, + + //Machines + [Description("Machine Created")] + MachineCreated = 400, + [Description("Machine Deleted")] + MachineDeleted = 401, + [Description("Machine Saved")] + MachineSaved = 402, + + //Catalogs + [Description("Catalog Created")] + CatalogCreated = 500, + [Description("Catalog Deleted")] + CatalogDeleted = 501, + [Description("Catalog Saved")] + CatalogSaved = 502, + + //Sites + [Description("Site Created")] + SiteCreated = 600, + [Description("Site Deleted")] + SiteDeleted = 601, + [Description("Site Saved")] + SiteSaved = 602, + + //Dispensers + [Description("Dispenser Created")] + DispenserCreated = 700, + [Description("Dispenser Deleted")] + DispenserDeleted = 701, + [Description("Dispenser Saved")] + DispenserSaved = 702, + + //Firmware + [Description("Firmware Upgraded")] + FirmwareUpgraded = 800, + } +} diff --git a/Software/Visual_Studio/Tango.BL/ObservableEntity.cs b/Software/Visual_Studio/Tango.BL/ObservableEntity.cs index 4f03263d9..11aca0e99 100644 --- a/Software/Visual_Studio/Tango.BL/ObservableEntity.cs +++ b/Software/Visual_Studio/Tango.BL/ObservableEntity.cs @@ -27,6 +27,8 @@ using Tango.Core.Json; using Newtonsoft.Json.Converters; using Tango.BL.Serialization; using Newtonsoft.Json.Linq; +using Tango.BL.ActionLogs; +using Tango.BL.ValueObjects; namespace Tango.BL { @@ -50,7 +52,7 @@ namespace Tango.BL /// /// [Serializable] - public abstract class ObservableEntity : ExtendedObject, IObservableEntity where T : class, IObservableEntity + public abstract class ObservableEntity : ExtendedObject, IObservableEntity, IActionLogComparable where T : class, IObservableEntity { #region Events @@ -658,5 +660,29 @@ namespace Tango.BL } #endregion + + #region Action Log + + public Task> CompareTo(T before) + { + return new BasicActionLogComparer().Compare(before as IActionLogComparable, this); + } + + Task> IActionLogComparable.CompareTo(IActionLogComparable before) + { + return CompareTo(before as T); + } + + bool IActionLogComparable.ShouldActionLogIgnore(string propName) + { + return propName == nameof(LastUpdated) || OnShouldActionLogIgnore(propName); + } + + protected virtual bool OnShouldActionLogIgnore(string propName) + { + return false; + } + + #endregion } } diff --git a/Software/Visual_Studio/Tango.BL/ObservableEntityDTO.cs b/Software/Visual_Studio/Tango.BL/ObservableEntityDTO.cs index 5950a3cd2..f587147e1 100644 --- a/Software/Visual_Studio/Tango.BL/ObservableEntityDTO.cs +++ b/Software/Visual_Studio/Tango.BL/ObservableEntityDTO.cs @@ -5,10 +5,12 @@ using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; +using Tango.BL.ActionLogs; +using Tango.BL.ValueObjects; namespace Tango.BL { - public abstract class ObservableEntityDTO : IObservableEntityDTO, IEquatable where T : IObservableEntity where DTO : ObservableEntityDTO + public abstract class ObservableEntityDTO : IObservableEntityDTO, IEquatable, IActionLogComparable where T : IObservableEntity where DTO : ObservableEntityDTO { public int ID { get; set; } @@ -207,5 +209,25 @@ namespace Tango.BL { return EqualsToObservable(observable); } + + public Task> CompareTo(DTO before) + { + return new BasicActionLogComparer().Compare(before, this); + } + + Task> IActionLogComparable.CompareTo(IActionLogComparable before) + { + return CompareTo(before as DTO); + } + + bool IActionLogComparable.ShouldActionLogIgnore(string propName) + { + return propName == nameof(LastUpdated) || OnShouldActionLogIgnore(propName); + } + + protected virtual bool OnShouldActionLogIgnore(string propName) + { + return false; + } } } diff --git a/Software/Visual_Studio/Tango.BL/ObservablesContext.cs b/Software/Visual_Studio/Tango.BL/ObservablesContext.cs index 4eaf256d2..3511a7624 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesContext.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesContext.cs @@ -30,6 +30,14 @@ namespace Tango.BL get; set; } + /// + /// Gets or sets the ActionLogs. + /// + public DbSet ActionLogs + { + get; set; + } + /// /// Gets or sets the Addresses. /// diff --git a/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs index c86933713..cccc2fcae 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesEntitiesAdapterExtension.cs @@ -53,6 +53,42 @@ namespace Tango.BL } + private ObservableCollection _actionlogs; + /// + /// Gets or sets the ActionLogs. + /// + public ObservableCollection ActionLogs + { + get + { + return _actionlogs; + } + + set + { + _actionlogs = value; RaisePropertyChanged(nameof(ActionLogs)); + } + + } + + private ICollectionView _actionlogsViewSource; + /// + /// Gets or sets the ActionLogs View Source. + /// + public ICollectionView ActionLogsViewSource + { + get + { + return _actionlogsViewSource; + } + + set + { + _actionlogsViewSource = value; RaisePropertyChanged(nameof(ActionLogsViewSource)); + } + + } + private ObservableCollection
_addresses; /// /// Gets or sets the Addresses. @@ -2833,6 +2869,8 @@ namespace Tango.BL SyncConfigurationsViewSource = CreateCollectionView(SyncConfigurations); + ActionLogsViewSource = CreateCollectionView(ActionLogs); + AddressesViewSource = CreateCollectionView(Addresses); ApplicationDisplayPanelVersionsViewSource = CreateCollectionView(ApplicationDisplayPanelVersions); diff --git a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs index efa188fec..4e108deb2 100644 --- a/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs +++ b/Software/Visual_Studio/Tango.BL/ObservablesStaticCollectionsExtension.cs @@ -53,6 +53,42 @@ namespace Tango.BL } + private ObservableCollection _actionlogs; + /// + /// Gets or sets the ActionLogs. + /// + public ObservableCollection ActionLogs + { + get + { + return _actionlogs; + } + + set + { + _actionlogs = value; RaisePropertyChanged(nameof(ActionLogs)); + } + + } + + private ICollectionView _actionlogsViewSource; + /// + /// Gets or sets the ActionLogs View Source. + /// + public ICollectionView ActionLogsViewSource + { + get + { + return _actionlogsViewSource; + } + + set + { + _actionlogsViewSource = value; RaisePropertyChanged(nameof(ActionLogsViewSource)); + } + + } + private ObservableCollection
_addresses; /// /// Gets or sets the Addresses. @@ -2833,6 +2869,8 @@ namespace Tango.BL SyncConfigurationsViewSource = CreateCollectionView(SyncConfigurations); + ActionLogsViewSource = CreateCollectionView(ActionLogs); + AddressesViewSource = CreateCollectionView(Addresses); ApplicationDisplayPanelVersionsViewSource = CreateCollectionView(ApplicationDisplayPanelVersions); diff --git a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj index 6111a1a35..469e23165 100644 --- a/Software/Visual_Studio/Tango.BL/Tango.BL.csproj +++ b/Software/Visual_Studio/Tango.BL/Tango.BL.csproj @@ -84,6 +84,10 @@ GlobalVersionInfo.cs + + + + @@ -115,6 +119,8 @@ + + @@ -269,6 +275,8 @@ + + @@ -368,6 +376,7 @@ + @@ -500,6 +509,7 @@ + @@ -580,7 +590,7 @@ - + \ No newline at end of file diff --git a/Software/Visual_Studio/Tango.BL/ValueObjects/ActionLogDifference.cs b/Software/Visual_Studio/Tango.BL/ValueObjects/ActionLogDifference.cs new file mode 100644 index 000000000..a89348249 --- /dev/null +++ b/Software/Visual_Studio/Tango.BL/ValueObjects/ActionLogDifference.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Tango.BL.ValueObjects +{ + public class ActionLogDifference + { + public String Component { get; set; } + public String Property { get; set; } + public Object Before { get; set; } + public Object After { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/ACTION_LOGS.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/ACTION_LOGS.cs new file mode 100644 index 000000000..7bfa1fa2c --- /dev/null +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/ACTION_LOGS.cs @@ -0,0 +1,29 @@ +//------------------------------------------------------------------------------ +// +// This code was generated from a template. +// +// Manual changes to this file may cause unexpected behavior in your application. +// Manual changes to this file will be overwritten if the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Tango.DAL.Remote.DB +{ + using System; + using System.Collections.Generic; + + public partial class ACTION_LOGS + { + public int ID { get; set; } + public string GUID { get; set; } + public System.DateTime LAST_UPDATED { get; set; } + public int TYPE { get; set; } + public string USER_GUID { get; set; } + public string RELATED_OBJECT_NAME { get; set; } + public string RELATED_OBJECT_GUID { get; set; } + public string MESSAGE { get; set; } + public string DIFFERENCE { get; set; } + + public virtual USER USER { get; set; } + } +} diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs index 3ef793f7f..2a158ad49 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Context.cs @@ -26,6 +26,7 @@ namespace Tango.DAL.Remote.DB } public virtual DbSet SYNC_CONFIGURATIONS { get; set; } + public virtual DbSet ACTION_LOGS { get; set; } public virtual DbSet
ADDRESSES { get; set; } public virtual DbSet APPLICATION_DISPLAY_PANEL_VERSIONS { get; set; } public virtual DbSet APPLICATION_FIRMWARE_VERSIONS { get; set; } diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs index d26e67908..17bc2683d 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.Designer.cs @@ -1,4 +1,4 @@ -// T4 code generation is enabled for model 'C:\DATA\Development\Tango\Software\Visual_Studio\Tango.DAL.Remote\DB\RemoteADO.edmx'. +// T4 code generation is enabled for model 'D:\Development\Tango\Software\Visual_Studio\Tango.DAL.Remote\DB\RemoteADO.edmx'. // To enable legacy code generation, change the value of the 'Code Generation Strategy' designer // property to 'Legacy ObjectContext'. This property is available in the Properties Window when the model // is open in the designer. diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx index f8f4f9505..eb161228c 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx @@ -5,6 +5,20 @@ + + + + + + + + + + + + + + @@ -1155,6 +1169,18 @@ + + + + + + + + + + + + @@ -2204,6 +2230,7 @@ + @@ -2282,6 +2309,10 @@ + + + + @@ -2613,6 +2644,7 @@ + @@ -2690,6 +2722,10 @@ + + + + @@ -3023,6 +3059,21 @@ + + + + + + + + + + + + + + + @@ -4294,6 +4345,7 @@ + @@ -4327,6 +4379,18 @@ + + + + + + + + + + + + @@ -5390,6 +5454,21 @@ + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram index f13138208..a9ff9aacf 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/RemoteADO.edmx.diagram @@ -5,83 +5,85 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs b/Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs index f8c124d43..e71c100ff 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs +++ b/Software/Visual_Studio/Tango.DAL.Remote/DB/USER.cs @@ -17,6 +17,7 @@ namespace Tango.DAL.Remote.DB [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")] public USER() { + this.ACTION_LOGS = new HashSet(); this.JOBS = new HashSet(); this.MACHINE_STUDIO_VERSIONS = new HashSet(); this.MACHINES_EVENTS = new HashSet(); @@ -35,6 +36,8 @@ namespace Tango.DAL.Remote.DB public string ADDRESS_GUID { get; set; } public Nullable LAST_LOGIN { get; set; } + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] + public virtual ICollection ACTION_LOGS { get; set; } public virtual ADDRESS ADDRESS { get; set; } public virtual CONTACT CONTACT { get; set; } [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")] diff --git a/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj b/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj index 75fa9179c..0a0cad6e2 100644 --- a/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj +++ b/Software/Visual_Studio/Tango.DAL.Remote/Tango.DAL.Remote.csproj @@ -66,6 +66,9 @@ GlobalVersionInfo.cs + + RemoteADO.tt + RemoteADO.tt @@ -365,7 +368,7 @@ - + \ No newline at end of file -- cgit v1.3.1