diff --git a/Controllers/VehicleController.cs b/Controllers/VehicleController.cs index d00dcb6..baf56c0 100644 --- a/Controllers/VehicleController.cs +++ b/Controllers/VehicleController.cs @@ -154,6 +154,34 @@ namespace CarCareTracker.Controllers _dataAccess.DeleteVehicle(vehicleId); return Json(result); } + [HttpPost] + public IActionResult DuplicateVehicleCollaborators(int sourceVehicleId, int destVehicleId) + { + try + { + //retrieve collaborators for both source and destination vehicle id. + if (_userLogic.UserCanEditVehicle(GetUserID(), sourceVehicleId) && _userLogic.UserCanEditVehicle(GetUserID(), destVehicleId)) + { + var sourceCollaborators = _userLogic.GetCollaboratorsForVehicle(sourceVehicleId).Select(x => x.UserVehicle.UserId).ToList(); + var destCollaborators = _userLogic.GetCollaboratorsForVehicle(destVehicleId).Select(x => x.UserVehicle.UserId).ToList(); + sourceCollaborators.RemoveAll(x => destCollaborators.Contains(x)); + if (sourceCollaborators.Any()) { + foreach (int collaboratorId in sourceCollaborators) + { + _userLogic.AddUserAccessToVehicle(collaboratorId, destVehicleId); + } + } else + { + return Json(new OperationResponse { Success = false, Message = "Both vehicles already have identical collaborators" }); + } + } + return Json(new OperationResponse { Success = true, Message = "Collaborators Copied"}); + } catch (Exception ex) + { + _logger.LogError(ex.Message); + return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage }); + } + } #region "Bulk Imports and Exports" [HttpGet] public IActionResult GetBulkImportModalPartialView(ImportMode mode) @@ -712,11 +740,11 @@ namespace CarCareTracker.Controllers } //move files from temp. serviceRecord.Files = serviceRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); - var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); - if (result && serviceRecord.Supplies.Any()) + if (serviceRecord.Supplies.Any()) { - RequisitionSupplyRecordsByUsage(serviceRecord.Supplies); + serviceRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(serviceRecord.Supplies, DateTime.Parse(serviceRecord.Date), serviceRecord.Description); } + var result = _serviceRecordDataAccess.SaveServiceRecordToVehicle(serviceRecord.ToServiceRecord()); return Json(result); } [HttpGet] @@ -740,6 +768,7 @@ namespace CarCareTracker.Controllers VehicleId = result.VehicleId, Files = result.Files, Tags = result.Tags, + RequisitionHistory = result.RequisitionHistory, ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.ServiceRecord).ExtraFields) }; return PartialView("_ServiceRecordModal", convertedResult); @@ -783,11 +812,11 @@ namespace CarCareTracker.Controllers } //move files from temp. collisionRecord.Files = collisionRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); - var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord()); - if (result && collisionRecord.Supplies.Any()) + if (collisionRecord.Supplies.Any()) { - RequisitionSupplyRecordsByUsage(collisionRecord.Supplies); + collisionRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(collisionRecord.Supplies, DateTime.Parse(collisionRecord.Date), collisionRecord.Description); } + var result = _collisionRecordDataAccess.SaveCollisionRecordToVehicle(collisionRecord.ToCollisionRecord()); return Json(result); } [HttpGet] @@ -811,6 +840,7 @@ namespace CarCareTracker.Controllers VehicleId = result.VehicleId, Files = result.Files, Tags = result.Tags, + RequisitionHistory = result.RequisitionHistory, ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.RepairRecord).ExtraFields) }; return PartialView("_CollisionRecordModal", convertedResult); @@ -1464,11 +1494,11 @@ namespace CarCareTracker.Controllers } //move files from temp. upgradeRecord.Files = upgradeRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); - var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord()); - if (result && upgradeRecord.Supplies.Any()) + if (upgradeRecord.Supplies.Any()) { - RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies); + upgradeRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(upgradeRecord.Supplies, DateTime.Parse(upgradeRecord.Date), upgradeRecord.Description); } + var result = _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(upgradeRecord.ToUpgradeRecord()); return Json(result); } [HttpGet] @@ -1492,6 +1522,7 @@ namespace CarCareTracker.Controllers VehicleId = result.VehicleId, Files = result.Files, Tags = result.Tags, + RequisitionHistory = result.RequisitionHistory, ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.UpgradeRecord).ExtraFields) }; return PartialView("_UpgradeRecordModal", convertedResult); @@ -1564,8 +1595,9 @@ namespace CarCareTracker.Controllers } return result; } - private void RequisitionSupplyRecordsByUsage(List supplyUsage) + private List RequisitionSupplyRecordsByUsage(List supplyUsage, DateTime dateRequisitioned, string usageDescription) { + List results = new List(); foreach(SupplyUsage supply in supplyUsage) { //get supply record. @@ -1575,9 +1607,29 @@ namespace CarCareTracker.Controllers result.Quantity -= supply.Quantity; //deduct cost. result.Cost -= (supply.Quantity * unitCost); + //check decimal places to ensure that it always has a max of 3 decimal places. + var roundedDecimal = decimal.Round(result.Cost, 3); + if (roundedDecimal != result.Cost) + { + //Too many decimals + result.Cost = roundedDecimal; + } + //create new requisitionrrecord + var requisitionRecord = new SupplyUsageHistory + { + Date = dateRequisitioned, + Description = usageDescription, + Quantity = supply.Quantity, + Cost = (supply.Quantity * unitCost) + }; + result.RequisitionHistory.Add(requisitionRecord); //save _supplyRecordDataAccess.SaveSupplyRecordToVehicle(result); + requisitionRecord.Description = result.Description; //change the name of the description for plan/service/repair/upgrade records + requisitionRecord.PartNumber = result.PartNumber; //populate part number if not displayed in supplies modal. + results.Add(requisitionRecord); } + return results; } [TypeFilter(typeof(CollaboratorFilter))] [HttpGet] @@ -1647,6 +1699,7 @@ namespace CarCareTracker.Controllers VehicleId = result.VehicleId, Files = result.Files, Tags = result.Tags, + RequisitionHistory = result.RequisitionHistory, ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.SupplyRecord).ExtraFields) }; return PartialView("_SupplyRecordModal", convertedResult); @@ -1677,11 +1730,11 @@ namespace CarCareTracker.Controllers planRecord.DateModified = DateTime.Now.ToString("G"); //move files from temp. planRecord.Files = planRecord.Files.Select(x => { return new UploadedFiles { Name = x.Name, Location = _fileHelper.MoveFileFromTemp(x.Location, "documents/") }; }).ToList(); - var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord()); - if (result && planRecord.Supplies.Any()) + if (planRecord.Supplies.Any()) { - RequisitionSupplyRecordsByUsage(planRecord.Supplies); + planRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(planRecord.Supplies, DateTime.Parse(planRecord.DateCreated), planRecord.Description); } + var result = _planRecordDataAccess.SavePlanRecordToVehicle(planRecord.ToPlanRecord()); return Json(result); } [HttpPost] @@ -1727,15 +1780,24 @@ namespace CarCareTracker.Controllers return Json(new OperationResponse { Success = false, Message = string.Join("
", supplyAvailability) }); } } + if (existingRecord.ReminderRecordId != default) + { + //check if reminder still exists and is still recurring. + var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(existingRecord.ReminderRecordId); + if (existingReminder is null || existingReminder.Id == default || !existingReminder.IsRecurring) + { + return Json(new OperationResponse { Success = false, Message = "Missing or Non-recurring Reminder, Please Delete This Template and Recreate It." }); + } + } //populate createdDate existingRecord.DateCreated = DateTime.Now.ToString("G"); existingRecord.DateModified = DateTime.Now.ToString("G"); existingRecord.Id = default; - var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord()); - if (result && existingRecord.Supplies.Any()) + if (existingRecord.Supplies.Any()) { - RequisitionSupplyRecordsByUsage(existingRecord.Supplies); + existingRecord.RequisitionHistory = RequisitionSupplyRecordsByUsage(existingRecord.Supplies, DateTime.Parse(existingRecord.DateCreated), existingRecord.Description); } + var result = _planRecordDataAccess.SavePlanRecordToVehicle(existingRecord.ToPlanRecord()); return Json(new OperationResponse { Success = result, Message = result ? "Plan Record Added" : StaticHelper.GenericErrorMessage }); } [HttpGet] @@ -1744,6 +1806,16 @@ namespace CarCareTracker.Controllers return PartialView("_PlanRecordModal", new PlanRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields }); } [HttpPost] + public IActionResult GetAddPlanRecordPartialView(PlanRecordInput? planModel) + { + if (planModel is not null) + { + planModel.ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields; + return PartialView("_PlanRecordModal", planModel); + } + return PartialView("_PlanRecordModal", new PlanRecordInput() { ExtraFields = _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields }); + } + [HttpPost] public IActionResult UpdatePlanRecordProgress(int planRecordId, PlanProgress planProgress, int odometer = 0) { var existingRecord = _planRecordDataAccess.GetPlanRecordById(planRecordId); @@ -1775,6 +1847,7 @@ namespace CarCareTracker.Controllers Cost = existingRecord.Cost, Notes = existingRecord.Notes, Files = existingRecord.Files, + RequisitionHistory = existingRecord.RequisitionHistory, ExtraFields = existingRecord.ExtraFields }; _serviceRecordDataAccess.SaveServiceRecordToVehicle(newRecord); @@ -1790,6 +1863,7 @@ namespace CarCareTracker.Controllers Cost = existingRecord.Cost, Notes = existingRecord.Notes, Files = existingRecord.Files, + RequisitionHistory = existingRecord.RequisitionHistory, ExtraFields = existingRecord.ExtraFields }; _collisionRecordDataAccess.SaveCollisionRecordToVehicle(newRecord); @@ -1805,10 +1879,29 @@ namespace CarCareTracker.Controllers Cost = existingRecord.Cost, Notes = existingRecord.Notes, Files = existingRecord.Files, + RequisitionHistory = existingRecord.RequisitionHistory, ExtraFields = existingRecord.ExtraFields }; _upgradeRecordDataAccess.SaveUpgradeRecordToVehicle(newRecord); } + //push back any reminders + if (existingRecord.ReminderRecordId != default) + { + var existingReminder = _reminderRecordDataAccess.GetReminderRecordById(existingRecord.ReminderRecordId); + if (existingReminder is not null && existingReminder.Id != default && existingReminder.IsRecurring) + { + existingReminder = _reminderHelper.GetUpdatedRecurringReminderRecord(existingReminder); + //save to db. + var reminderUpdateResult = _reminderRecordDataAccess.SaveReminderRecordToVehicle(existingReminder); + if (!reminderUpdateResult) + { + _logger.LogError("Unable to update reminder either because the reminder no longer exists or is no longer recurring"); + } + } else + { + _logger.LogError("Unable to update reminder because it no longer exists."); + } + } } return Json(result); } @@ -1830,6 +1923,8 @@ namespace CarCareTracker.Controllers Notes = result.Notes, VehicleId = result.VehicleId, Files = result.Files, + RequisitionHistory = result.RequisitionHistory, + ReminderRecordId = result.ReminderRecordId, ExtraFields = StaticHelper.AddExtraFields(result.ExtraFields, _extraFieldDataAccess.GetExtraFieldsById((int)ImportMode.PlanRecord).ExtraFields) }; return PartialView("_PlanRecordModal", convertedResult); @@ -1946,5 +2041,6 @@ namespace CarCareTracker.Controllers return Json(result); } #endregion + } } diff --git a/Models/Collision/CollisionRecordInput.cs b/Models/Collision/CollisionRecordInput.cs index 7ceef0f..703bb2f 100644 --- a/Models/Collision/CollisionRecordInput.cs +++ b/Models/Collision/CollisionRecordInput.cs @@ -13,6 +13,20 @@ public List Supplies { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); - public CollisionRecord ToCollisionRecord() { return new CollisionRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields }; } + public List RequisitionHistory { get; set; } = new List(); + public CollisionRecord ToCollisionRecord() { return new CollisionRecord { + Id = Id, + VehicleId = VehicleId, + Date = DateTime.Parse(Date), + Cost = Cost, + Mileage = Mileage, + Description = Description, + Notes = Notes, + Files = Files, + Tags = Tags, + ExtraFields = ExtraFields, + RequisitionHistory = RequisitionHistory + }; + } } } diff --git a/Models/GenericRecord.cs b/Models/GenericRecord.cs index 37de27e..f9a8f6b 100644 --- a/Models/GenericRecord.cs +++ b/Models/GenericRecord.cs @@ -12,5 +12,6 @@ public List Files { get; set; } = new List(); public List Tags { get; set;} = new List(); public List ExtraFields { get; set; } = new List(); + public List RequisitionHistory { get; set; } = new List(); } } diff --git a/Models/PlanRecord/PlanCostItem.cs b/Models/PlanRecord/PlanCostItem.cs deleted file mode 100644 index 37bafa7..0000000 --- a/Models/PlanRecord/PlanCostItem.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace CarCareTracker.Models -{ - public class PlanCostItem - { - public string CostName { get; set; } - public decimal CostAmount { get; set; } - } -} diff --git a/Models/PlanRecord/PlanRecord.cs b/Models/PlanRecord/PlanRecord.cs index 5746552..83bad98 100644 --- a/Models/PlanRecord/PlanRecord.cs +++ b/Models/PlanRecord/PlanRecord.cs @@ -4,6 +4,7 @@ { public int Id { get; set; } public int VehicleId { get; set; } + public int ReminderRecordId { get; set; } public DateTime DateCreated { get; set; } public DateTime DateModified { get; set; } public string Description { get; set; } @@ -14,5 +15,6 @@ public PlanProgress Progress { get; set; } public decimal Cost { get; set; } public List ExtraFields { get; set; } = new List(); + public List RequisitionHistory { get; set; } = new List(); } } diff --git a/Models/PlanRecord/PlanRecordInput.cs b/Models/PlanRecord/PlanRecordInput.cs index 22f5106..801bd6f 100644 --- a/Models/PlanRecord/PlanRecordInput.cs +++ b/Models/PlanRecord/PlanRecordInput.cs @@ -4,6 +4,7 @@ { public int Id { get; set; } public int VehicleId { get; set; } + public int ReminderRecordId { get; set; } public string DateCreated { get; set; } = DateTime.Now.ToShortDateString(); public string DateModified { get; set; } = DateTime.Now.ToShortDateString(); public string Description { get; set; } @@ -15,9 +16,11 @@ public PlanProgress Progress { get; set; } public decimal Cost { get; set; } public List ExtraFields { get; set; } = new List(); + public List RequisitionHistory { get; set; } = new List(); public PlanRecord ToPlanRecord() { return new PlanRecord { Id = Id, VehicleId = VehicleId, + ReminderRecordId = ReminderRecordId, DateCreated = DateTime.Parse(DateCreated), DateModified = DateTime.Parse(DateModified), Description = Description, @@ -27,7 +30,12 @@ Cost = Cost, Priority = Priority, Progress = Progress, - ExtraFields = ExtraFields + ExtraFields = ExtraFields, + RequisitionHistory = RequisitionHistory }; } + /// + /// only used to hide view template button on plan create modal. + /// + public bool CreatedFromReminder { get; set; } } } diff --git a/Models/ServiceRecord/ServiceRecordInput.cs b/Models/ServiceRecord/ServiceRecordInput.cs index 30f8ccf..430c1aa 100644 --- a/Models/ServiceRecord/ServiceRecordInput.cs +++ b/Models/ServiceRecord/ServiceRecordInput.cs @@ -13,6 +13,20 @@ public List Supplies { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); - public ServiceRecord ToServiceRecord() { return new ServiceRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields }; } + public List RequisitionHistory { get; set; } = new List(); + public ServiceRecord ToServiceRecord() { return new ServiceRecord { + Id = Id, + VehicleId = VehicleId, + Date = DateTime.Parse(Date), + Cost = Cost, + Mileage = Mileage, + Description = Description, + Notes = Notes, + Files = Files, + Tags = Tags, + ExtraFields = ExtraFields, + RequisitionHistory = RequisitionHistory + }; + } } } diff --git a/Models/Supply/SupplyRecord.cs b/Models/Supply/SupplyRecord.cs index 6ecfbe9..02863b5 100644 --- a/Models/Supply/SupplyRecord.cs +++ b/Models/Supply/SupplyRecord.cs @@ -35,5 +35,6 @@ public List Files { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); + public List RequisitionHistory { get; set; } = new List(); } } diff --git a/Models/Supply/SupplyRecordInput.cs b/Models/Supply/SupplyRecordInput.cs index 14896d2..ba186af 100644 --- a/Models/Supply/SupplyRecordInput.cs +++ b/Models/Supply/SupplyRecordInput.cs @@ -14,6 +14,7 @@ public List Files { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); + public List RequisitionHistory { get; set; } = new List(); public SupplyRecord ToSupplyRecord() { return new SupplyRecord { Id = Id, VehicleId = VehicleId, @@ -26,7 +27,8 @@ Notes = Notes, Files = Files, Tags = Tags, - ExtraFields = ExtraFields + ExtraFields = ExtraFields, + RequisitionHistory = RequisitionHistory }; } } } diff --git a/Models/Supply/SupplyUsageHistory.cs b/Models/Supply/SupplyUsageHistory.cs new file mode 100644 index 0000000..e944de8 --- /dev/null +++ b/Models/Supply/SupplyUsageHistory.cs @@ -0,0 +1,10 @@ +namespace CarCareTracker.Models +{ + public class SupplyUsageHistory { + public DateTime Date { get; set; } + public string PartNumber { get; set; } + public string Description { get; set; } + public decimal Quantity { get; set; } + public decimal Cost { get; set; } + } +} diff --git a/Models/UpgradeRecord/UpgradeReportInput.cs b/Models/UpgradeRecord/UpgradeReportInput.cs index ddc60ec..812c8c4 100644 --- a/Models/UpgradeRecord/UpgradeReportInput.cs +++ b/Models/UpgradeRecord/UpgradeReportInput.cs @@ -13,6 +13,20 @@ public List Supplies { get; set; } = new List(); public List Tags { get; set; } = new List(); public List ExtraFields { get; set; } = new List(); - public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord { Id = Id, VehicleId = VehicleId, Date = DateTime.Parse(Date), Cost = Cost, Mileage = Mileage, Description = Description, Notes = Notes, Files = Files, Tags = Tags, ExtraFields = ExtraFields }; } + public List RequisitionHistory { get; set; } = new List(); + public UpgradeRecord ToUpgradeRecord() { return new UpgradeRecord { + Id = Id, + VehicleId = VehicleId, + Date = DateTime.Parse(Date), + Cost = Cost, + Mileage = Mileage, + Description = Description, + Notes = Notes, + Files = Files, + Tags = Tags, + ExtraFields = ExtraFields, + RequisitionHistory = RequisitionHistory + }; + } } } diff --git a/Views/Home/_GarageDisplay.cshtml b/Views/Home/_GarageDisplay.cshtml index d168efc..cc145c5 100644 --- a/Views/Home/_GarageDisplay.cshtml +++ b/Views/Home/_GarageDisplay.cshtml @@ -23,9 +23,9 @@
@foreach (Vehicle vehicle in Model) { -
+
- +
@($"{vehicle.Year}")
@($"{vehicle.Make}")
diff --git a/Views/Home/_Settings.cshtml b/Views/Home/_Settings.cshtml index c1286c3..606f2f1 100644 --- a/Views/Home/_Settings.cshtml +++ b/Views/Home/_Settings.cshtml @@ -201,7 +201,7 @@
- Version 1.2.0 + Version 1.2.1

Proudly developed in the rural town of Price, Utah by Hargata Softworks. diff --git a/Views/Vehicle/_CollisionRecordModal.cshtml b/Views/Vehicle/_CollisionRecordModal.cshtml index 1c8625a..4722f8f 100644 --- a/Views/Vehicle/_CollisionRecordModal.cshtml +++ b/Views/Vehicle/_CollisionRecordModal.cshtml @@ -83,6 +83,10 @@

+ \ No newline at end of file diff --git a/Views/Vehicle/_ServiceRecordModal.cshtml b/Views/Vehicle/_ServiceRecordModal.cshtml index 45c59e6..a65c3dc 100644 --- a/Views/Vehicle/_ServiceRecordModal.cshtml +++ b/Views/Vehicle/_ServiceRecordModal.cshtml @@ -83,6 +83,10 @@