using CarCareTracker.Filter; using CarCareTracker.Helper; using CarCareTracker.Models; using Microsoft.AspNetCore.Mvc; namespace CarCareTracker.Controllers { public partial class APIController { [HttpGet] [Route("/api/vehicle/taxrecords/all")] public IActionResult AllTaxRecords(MethodParameter parameters) { List vehicleIds = new List(); var vehicles = _dataAccess.GetVehicles(); if (!User.IsInRole(nameof(UserData.IsRootUser))) { vehicles = _userLogic.FilterUserVehicles(vehicles, GetUserID()); } vehicleIds.AddRange(vehicles.Select(x => x.Id)); List vehicleRecords = new List(); foreach (int vehicleId in vehicleIds) { vehicleRecords.AddRange(_taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId)); } if (parameters.Id != default) { vehicleRecords.RemoveAll(x => x.Id != parameters.Id); } if (!string.IsNullOrWhiteSpace(parameters.StartDate) && DateTime.TryParse(parameters.StartDate, out DateTime startDate)) { vehicleRecords.RemoveAll(x => x.Date < startDate); } if (!string.IsNullOrWhiteSpace(parameters.EndDate) && DateTime.TryParse(parameters.EndDate, out DateTime endDate)) { vehicleRecords.RemoveAll(x => x.Date > endDate); } if (!string.IsNullOrWhiteSpace(parameters.Tags)) { var tagsFilter = parameters.Tags.Split(' ').Distinct(); vehicleRecords.RemoveAll(x => !x.Tags.Any(y => tagsFilter.Contains(y))); } var result = vehicleRecords.Select(x => new TaxRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); } else { return Json(result); } } [TypeFilter(typeof(CollaboratorFilter))] [HttpGet] [Route("/api/vehicle/taxrecords")] public IActionResult TaxRecords(int vehicleId, MethodParameter parameters) { if (vehicleId == default) { var response = OperationResponse.Failed("Must provide a valid vehicle id"); Response.StatusCode = 400; return Json(response); } var vehicleRecords = _taxRecordDataAccess.GetTaxRecordsByVehicleId(vehicleId); if (parameters.Id != default) { vehicleRecords.RemoveAll(x => x.Id != parameters.Id); } if (!string.IsNullOrWhiteSpace(parameters.StartDate) && DateTime.TryParse(parameters.StartDate, out DateTime startDate)) { vehicleRecords.RemoveAll(x => x.Date < startDate); } if (!string.IsNullOrWhiteSpace(parameters.EndDate) && DateTime.TryParse(parameters.EndDate, out DateTime endDate)) { vehicleRecords.RemoveAll(x => x.Date > endDate); } if (!string.IsNullOrWhiteSpace(parameters.Tags)) { var tagsFilter = parameters.Tags.Split(' ').Distinct(); vehicleRecords.RemoveAll(x => !x.Tags.Any(y => tagsFilter.Contains(y))); } var result = vehicleRecords.Select(x => new TaxRecordExportModel { Id = x.Id.ToString(), Date = x.Date.ToShortDateString(), Description = x.Description, Cost = x.Cost.ToString(), Notes = x.Notes, ExtraFields = x.ExtraFields, Files = x.Files, Tags = string.Join(' ', x.Tags) }); if (_config.GetInvariantApi() || Request.Headers.ContainsKey("culture-invariant")) { return Json(result, StaticHelper.GetInvariantOption()); } else { return Json(result); } } [HttpGet] [Route("/api/vehicle/taxrecords/check")] public IActionResult CheckRecurringTaxRecords() { List vehicles = new List(); try { var result = _dataAccess.GetVehicles(); if (!User.IsInRole(nameof(UserData.IsRootUser))) { result = _userLogic.FilterUserVehicles(result, GetUserID()); } vehicles.AddRange(result); int vehiclesUpdated = 0; foreach (Vehicle vehicle in vehicles) { var updateResult = _vehicleLogic.UpdateRecurringTaxes(vehicle.Id); if (updateResult) { vehiclesUpdated++; } } if (vehiclesUpdated != default) { return Json(OperationResponse.Succeed($"Recurring Taxes for {vehiclesUpdated} Vehicles Updated!")); } else { return Json(OperationResponse.Succeed("No Recurring Taxes Updated")); } } catch (Exception ex) { return Json(OperationResponse.Failed($"No Recurring Taxes Updated Due To Error: {ex.Message}")); } } [TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })] [TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })] [HttpPost] [Route("/api/vehicle/taxrecords/add")] [Consumes("application/json")] public IActionResult AddTaxRecordJson(int vehicleId, [FromBody] TaxRecordExportModel input) => AddTaxRecord(vehicleId, input); [TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })] [TypeFilter(typeof(CollaboratorFilter), Arguments = new object[] { false, true, HouseholdPermission.Edit })] [HttpPost] [Route("/api/vehicle/taxrecords/add")] public IActionResult AddTaxRecord(int vehicleId, TaxRecordExportModel input) { if (vehicleId == default) { Response.StatusCode = 400; return Json(OperationResponse.Failed("Must provide a valid vehicle id")); } if (string.IsNullOrWhiteSpace(input.Date) || string.IsNullOrWhiteSpace(input.Description) || string.IsNullOrWhiteSpace(input.Cost)) { Response.StatusCode = 400; return Json(OperationResponse.Failed("Input object invalid, Date, Description, and Cost cannot be empty.")); } if (input.Files == null) { input.Files = new List(); } if (input.ExtraFields == null) { input.ExtraFields = new List(); } try { var taxRecord = new TaxRecord() { VehicleId = vehicleId, Date = DateTime.Parse(input.Date), Description = input.Description, Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes, Cost = decimal.Parse(input.Cost), ExtraFields = input.ExtraFields, Files = input.Files, Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList() }; _taxRecordDataAccess.SaveTaxRecordToVehicle(taxRecord); _vehicleLogic.UpdateRecurringTaxes(vehicleId); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromTaxRecord(taxRecord, "taxrecord.add.api", User.Identity.Name)); return Json(OperationResponse.Succeed("Tax Record Added", new { recordId = taxRecord.Id })); } catch (Exception ex) { Response.StatusCode = 500; return Json(OperationResponse.Failed(ex.Message)); } } [TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Delete })] [HttpDelete] [Route("/api/vehicle/taxrecords/delete")] public IActionResult DeleteTaxRecord(int id) { var existingRecord = _taxRecordDataAccess.GetTaxRecordById(id); if (existingRecord == null || existingRecord.Id == default) { Response.StatusCode = 400; return Json(OperationResponse.Failed("Invalid Record Id")); } //security check. if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Delete)) { Response.StatusCode = 401; return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle.")); } var result = _taxRecordDataAccess.DeleteTaxRecordById(existingRecord.Id); if (result) { StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromTaxRecord(existingRecord, "taxrecord.delete.api", User.Identity.Name)); } return Json(OperationResponse.Conditional(result, "Tax Record Deleted")); } [TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })] [HttpPut] [Route("/api/vehicle/taxrecords/update")] [Consumes("application/json")] public IActionResult UpdateTaxRecordJson([FromBody] TaxRecordExportModel input) => UpdateTaxRecord(input); [TypeFilter(typeof(APIKeyFilter), Arguments = new object[] { HouseholdPermission.Edit })] [HttpPut] [Route("/api/vehicle/taxrecords/update")] public IActionResult UpdateTaxRecord(TaxRecordExportModel input) { if (string.IsNullOrWhiteSpace(input.Id) || string.IsNullOrWhiteSpace(input.Date) || string.IsNullOrWhiteSpace(input.Description) || string.IsNullOrWhiteSpace(input.Cost)) { Response.StatusCode = 400; return Json(OperationResponse.Failed("Input object invalid, Id, Date, Description, and Cost cannot be empty.")); } if (input.Files == null) { input.Files = new List(); } if (input.ExtraFields == null) { input.ExtraFields = new List(); } try { //retrieve existing record var existingRecord = _taxRecordDataAccess.GetTaxRecordById(int.Parse(input.Id)); if (existingRecord != null && existingRecord.Id == int.Parse(input.Id)) { //check if user has access to the vehicleId if (!_userLogic.UserCanEditVehicle(GetUserID(), existingRecord.VehicleId, HouseholdPermission.Edit)) { Response.StatusCode = 401; return Json(OperationResponse.Failed("Access Denied, you don't have access to this vehicle.")); } existingRecord.Date = DateTime.Parse(input.Date); existingRecord.Description = input.Description; existingRecord.Notes = string.IsNullOrWhiteSpace(input.Notes) ? "" : input.Notes; existingRecord.Cost = decimal.Parse(input.Cost); existingRecord.ExtraFields = input.ExtraFields; existingRecord.Files = input.Files; existingRecord.Tags = string.IsNullOrWhiteSpace(input.Tags) ? new List() : input.Tags.Split(' ').Distinct().ToList(); _taxRecordDataAccess.SaveTaxRecordToVehicle(existingRecord); StaticHelper.NotifyAsync(_config.GetWebHookUrl(), WebHookPayload.FromTaxRecord(existingRecord, "taxrecord.update.api", User.Identity.Name)); } else { Response.StatusCode = 400; return Json(OperationResponse.Failed("Invalid Record Id")); } return Json(OperationResponse.Succeed("Tax Record Updated")); } catch (Exception ex) { Response.StatusCode = 500; return Json(OperationResponse.Failed(ex.Message)); } } } }