< Summary

Information
Class: LGDXRobotCloud.API.Services.Navigation.RobotService
Assembly: LGDXRobotCloud.API
File(s): /builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Navigation/RobotService.cs
Line coverage
71%
Covered lines: 216
Uncovered lines: 86
Coverable lines: 302
Total lines: 375
Line coverage: 71.5%
Branch coverage
63%
Covered branches: 19
Total branches: 30
Branch coverage: 63.3%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%88100%
GetRobotsAsync()100%44100%
GetRobotAsync()100%22100%
CreateRobotAsync()100%22100%
UpdateRobotAsync()0%620%
UpdateRobotChassisInfoAsync()0%620%
GetRobotChassisInfoAsync()100%210%
TestDeleteRobotAsync()100%22100%
DeleteRobotAsync()0%620%
GetRobotSystemInfoAsync()100%11100%
CreateRobotSystemInfoAsync()100%11100%
UpdateRobotSystemInfoAsync()100%210%
SearchRobotsAsync()50%22100%
GetRobotRealmIdAsync()100%44100%

File(s)

/builds/yukaitung/lgdxrobot2-cloud/LGDXRobotCloud.API/Services/Navigation/RobotService.cs

#LineLine coverage
 1using LGDXRobotCloud.API.Exceptions;
 2using LGDXRobotCloud.API.Services.Administration;
 3using LGDXRobotCloud.Data.DbContexts;
 4using LGDXRobotCloud.Data.Entities;
 5using LGDXRobotCloud.Data.Models.Business.Administration;
 6using LGDXRobotCloud.Data.Models.Business.Automation;
 7using LGDXRobotCloud.Data.Models.Business.Navigation;
 8using LGDXRobotCloud.Utilities.Enums;
 9using LGDXRobotCloud.Utilities.Helpers;
 10using Microsoft.EntityFrameworkCore;
 11using Microsoft.Extensions.Caching.Memory;
 12
 13namespace LGDXRobotCloud.API.Services.Navigation;
 14
 15public interface IRobotService
 16{
 17  Task<(IEnumerable<RobotListBusinessModel>, PaginationHelper)> GetRobotsAsync(int? realmId, string? name, int pageNumbe
 18  Task<RobotBusinessModel> GetRobotAsync(Guid robotId);
 19  Task<RobotCreateResponseBusinessModel> CreateRobotAsync(RobotCreateBusinessModel robotCreateBusinessModel);
 20  Task<bool> UpdateRobotAsync(Guid id, RobotUpdateBusinessModel robotUpdateDtoBusinessModel);
 21  Task<RobotChassisInfoBusinessModel?> GetRobotChassisInfoAsync(Guid robotId);
 22  Task<bool> UpdateRobotChassisInfoAsync(Guid id, RobotChassisInfoUpdateBusinessModel robotChassisInfoUpdateBusinessMode
 23  Task<bool> TestDeleteRobotAsync(Guid id);
 24  Task<bool> DeleteRobotAsync(Guid id);
 25
 26  Task<RobotSystemInfoBusinessModel?> GetRobotSystemInfoAsync(Guid robotId);
 27  Task<bool> CreateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoCreateBusinessModel robotSystemInfoCreateBusinessMo
 28  Task<bool> UpdateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoUpdateBusinessModel robotSystemInfoUpdateBusinessMo
 29
 30  Task<IEnumerable<RobotSearchBusinessModel>> SearchRobotsAsync(int realmId, string? name, Guid? robotId);
 31
 32  Task<int?> GetRobotRealmIdAsync(Guid robotId);
 33}
 34
 1935public class RobotService(
 1936    IActivityLogService activityLogService,
 1937    IMemoryCache memoryCache,
 1938    IRobotCertificateService robotCertificateService,
 1939    LgdxContext context
 1940  ) : IRobotService
 41{
 1942  private readonly IActivityLogService _activityLogService = activityLogService ?? throw new ArgumentNullException(nameo
 1943  private readonly IMemoryCache _memoryCache = memoryCache ?? throw new ArgumentNullException(nameof(memoryCache));
 1944  private readonly IRobotCertificateService _robotCertificateService = robotCertificateService ?? throw new ArgumentNull
 1945  private readonly LgdxContext _context = context ?? throw new ArgumentNullException(nameof(context));
 46
 47  public async Task<(IEnumerable<RobotListBusinessModel>, PaginationHelper)> GetRobotsAsync(int? realmId, string? name, 
 448  {
 449    var query = _context.Robots as IQueryable<Robot>;
 450    if (realmId != null)
 451    {
 452      query = query.Where(r => r.RealmId == realmId);
 453    }
 454    if (!string.IsNullOrWhiteSpace(name))
 355    {
 356      name = name.Trim();
 357      query = query.Where(r => r.Name.ToLower().Contains(name.ToLower()));
 358    }
 459    var itemCount = await query.CountAsync();
 460    var PaginationHelper = new PaginationHelper(itemCount, pageNumber, pageSize);
 461    var robots = await query.AsNoTracking()
 462      .OrderBy(r => r.Id)
 463      .Skip(pageSize * (pageNumber - 1))
 464      .Take(pageSize)
 465      .Select(r => new RobotListBusinessModel {
 466        Id = r.Id,
 467        Name = r.Name,
 468        RealmId = r.RealmId,
 469        RealmName = r.Realm.Name,
 470      })
 471      .AsSplitQuery()
 472      .ToListAsync();
 473    return (robots, PaginationHelper);
 474  }
 75
 76  public async Task<RobotBusinessModel> GetRobotAsync(Guid robotId)
 277  {
 278    return await _context.Robots.AsNoTracking()
 279      .Where(r => r.Id == robotId)
 280      .Select(r => new RobotBusinessModel {
 281        Id = r.Id,
 282        Name = r.Name,
 283        RealmId = r.RealmId,
 284        RealmName = r.Realm.Name,
 285        IsProtectingHardwareSerialNumber = r.IsProtectingHardwareSerialNumber,
 286        RobotCertificate = new RobotCertificateBusinessModel {
 287          Id = r.RobotCertificate.Id,
 288          RobotId = r.Id,
 289          RobotName = r.Name,
 290          Thumbprint = r.RobotCertificate.Thumbprint,
 291          ThumbprintBackup = r.RobotCertificate.ThumbprintBackup,
 292          NotBefore = r.RobotCertificate.NotBefore,
 293          NotAfter = r.RobotCertificate.NotAfter,
 294        },
 295        RobotSystemInfo = r.RobotSystemInfo == null ? null : new RobotSystemInfoBusinessModel {
 296          Id = r.RobotSystemInfo.Id,
 297          Cpu = r.RobotSystemInfo.Cpu,
 298          IsLittleEndian = r.RobotSystemInfo.IsLittleEndian,
 299          Motherboard = r.RobotSystemInfo.Motherboard,
 2100          MotherboardSerialNumber = r.RobotSystemInfo.MotherboardSerialNumber,
 2101          RamMiB = r.RobotSystemInfo.RamMiB,
 2102          Gpu = r.RobotSystemInfo.Gpu,
 2103          Os = r.RobotSystemInfo.Os,
 2104          Is32Bit = r.RobotSystemInfo.Is32Bit,
 2105          McuSerialNumber = r.RobotSystemInfo.McuSerialNumber,
 2106        },
 2107        RobotChassisInfo = r.RobotChassisInfo == null ? null : new RobotChassisInfoBusinessModel {
 2108          Id = r.RobotChassisInfo.Id,
 2109          RobotTypeId = r.RobotChassisInfo.RobotTypeId,
 2110          ChassisLengthX = r.RobotChassisInfo.ChassisLengthX,
 2111          ChassisLengthY = r.RobotChassisInfo.ChassisLengthY,
 2112          ChassisWheelCount = r.RobotChassisInfo.ChassisWheelCount,
 2113          ChassisWheelRadius = r.RobotChassisInfo.ChassisWheelRadius,
 2114          BatteryCount = r.RobotChassisInfo.BatteryCount,
 2115          BatteryMaxVoltage = r.RobotChassisInfo.BatteryMaxVoltage,
 2116          BatteryMinVoltage = r.RobotChassisInfo.BatteryMinVoltage,
 2117        },
 2118        AssignedTasks = r.AssignedTasks
 2119          .Where(t =>  t.CurrentProgressId != (int)ProgressState.Aborted
 2120                    && t.CurrentProgressId != (int)ProgressState.Completed
 2121                    && t.CurrentProgressId != (int)ProgressState.Template)
 2122          .OrderByDescending(t => t.CurrentProgressId)
 2123          .ThenBy(t => t.Id)
 2124          .Select(t => new AutoTaskListBusinessModel {
 2125          Id = t.Id,
 2126          Name = t.Name,
 2127          Priority = t.Priority,
 2128          FlowId = t.FlowId,
 2129          FlowName = t.Flow!.Name,
 2130          RealmId = r.RealmId,
 2131          RealmName = r.Realm.Name,
 2132          AssignedRobotId = r.Id,
 2133          AssignedRobotName = r.Name,
 2134          CurrentProgressId = t.CurrentProgressId,
 2135          CurrentProgressName = t.CurrentProgress.Name,
 2136        })
 2137        .ToList(),
 2138      })
 2139      .FirstOrDefaultAsync()
 2140        ?? throw new LgdxNotFound404Exception();
 1141  }
 142
 143  public async Task<RobotCreateResponseBusinessModel> CreateRobotAsync(RobotCreateBusinessModel robotCreateBusinessModel
 2144  {
 2145    var realm = await _context.Realms.Where(r => r.Id == robotCreateBusinessModel.RealmId).AnyAsync();
 2146    if (realm == false)
 1147    {
 1148      throw new LgdxValidation400Expection(nameof(robotCreateBusinessModel.RealmId), "Realm does not exist.");
 149    }
 150
 1151    var id = Guid.CreateVersion7();
 1152    var robotCertificate = await _robotCertificateService.IssueRobotCertificateAsync(id);
 1153    var robot = new Robot {
 1154      Id = id,
 1155      Name = robotCreateBusinessModel.Name,
 1156      RealmId = robotCreateBusinessModel.RealmId,
 1157      IsProtectingHardwareSerialNumber = robotCreateBusinessModel.IsProtectingHardwareSerialNumber,
 1158      RobotCertificate = new RobotCertificate {
 1159        Thumbprint = robotCertificate.RobotCertificateThumbprint,
 1160        NotBefore = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotBefore, DateTimeKind.Utc),
 1161        NotAfter = DateTime.SpecifyKind(robotCertificate.RobotCertificateNotAfter, DateTimeKind.Utc)
 1162      },
 1163      RobotChassisInfo = new RobotChassisInfo {
 1164        RobotTypeId = robotCreateBusinessModel.RobotChassisInfo.RobotTypeId,
 1165        ChassisLengthX = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthX,
 1166        ChassisLengthY = robotCreateBusinessModel.RobotChassisInfo.ChassisLengthY,
 1167        ChassisWheelCount = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelCount,
 1168        ChassisWheelRadius = robotCreateBusinessModel.RobotChassisInfo.ChassisWheelRadius,
 1169        BatteryCount = robotCreateBusinessModel.RobotChassisInfo.BatteryCount,
 1170        BatteryMaxVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMaxVoltage,
 1171        BatteryMinVoltage = robotCreateBusinessModel.RobotChassisInfo.BatteryMinVoltage,
 1172      }
 1173    };
 1174    await _context.Robots.AddAsync(robot);
 1175    await _context.SaveChangesAsync();
 176
 1177    await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 1178    {
 1179      EntityName = nameof(Robot),
 1180      EntityId = robot.Id.ToString(),
 1181      Action = ActivityAction.Create,
 1182    });
 183
 1184    return new RobotCreateResponseBusinessModel
 1185    {
 1186      RobotId = robot.Id,
 1187      RobotName = robot.Name,
 1188      RootCertificate = robotCertificate.RootCertificate,
 1189      RobotCertificatePrivateKey = robotCertificate.RobotCertificatePrivateKey,
 1190      RobotCertificatePublicKey = robotCertificate.RobotCertificatePublicKey
 1191    };
 1192  }
 193
 194  public async Task<bool> UpdateRobotAsync(Guid id, RobotUpdateBusinessModel robotUpdateDtoBusinessModel)
 0195  {
 0196    bool result = await _context.Robots
 0197      .Where(r => r.Id == id)
 0198      .ExecuteUpdateAsync(setters => setters
 0199        .SetProperty(r => r.Name, robotUpdateDtoBusinessModel.Name)
 0200        .SetProperty(r => r.IsProtectingHardwareSerialNumber, robotUpdateDtoBusinessModel.IsProtectingHardwareSerialNumb
 0201      ) == 1;
 202
 0203    if (result)
 0204    {
 0205      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0206      {
 0207        EntityName = nameof(Robot),
 0208        EntityId = id.ToString(),
 0209        Action = ActivityAction.Update,
 0210      });
 0211    }
 0212    return result;
 0213  }
 214
 215  public async Task<bool> UpdateRobotChassisInfoAsync(Guid id, RobotChassisInfoUpdateBusinessModel robotChassisInfoUpdat
 0216  {
 0217    bool result = await _context.RobotChassisInfos
 0218      .Where(r => r.RobotId == id)
 0219      .ExecuteUpdateAsync(setters => setters
 0220        .SetProperty(r => r.RobotTypeId, robotChassisInfoUpdateBusinessModel.RobotTypeId)
 0221        .SetProperty(r => r.ChassisLengthX, robotChassisInfoUpdateBusinessModel.ChassisLengthX)
 0222        .SetProperty(r => r.ChassisLengthY, robotChassisInfoUpdateBusinessModel.ChassisLengthY)
 0223        .SetProperty(r => r.ChassisWheelCount, robotChassisInfoUpdateBusinessModel.ChassisWheelCount)
 0224        .SetProperty(r => r.ChassisWheelRadius, robotChassisInfoUpdateBusinessModel.ChassisWheelRadius)
 0225        .SetProperty(r => r.BatteryCount, robotChassisInfoUpdateBusinessModel.BatteryCount)
 0226        .SetProperty(r => r.BatteryMaxVoltage, robotChassisInfoUpdateBusinessModel.BatteryMaxVoltage)
 0227        .SetProperty(r => r.BatteryMinVoltage, robotChassisInfoUpdateBusinessModel.BatteryMinVoltage)
 0228      ) == 1;
 229
 0230    if (result)
 0231    {
 0232      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0233      {
 0234        EntityName = nameof(Robot),
 0235        EntityId = id.ToString(),
 0236        Action = ActivityAction.Update,
 0237      });
 0238    }
 0239    return result;
 0240  }
 241
 242  public async Task<RobotChassisInfoBusinessModel?> GetRobotChassisInfoAsync(Guid robotId)
 0243  {
 0244    return await _context.RobotChassisInfos.AsNoTracking()
 0245      .Where(r => r.RobotId == robotId)
 0246      .Select(r => new RobotChassisInfoBusinessModel {
 0247        Id = r.Id,
 0248        RobotTypeId = r.RobotTypeId,
 0249        ChassisLengthX = r.ChassisLengthX,
 0250        ChassisLengthY = r.ChassisLengthY,
 0251        ChassisWheelCount = r.ChassisWheelCount,
 0252        ChassisWheelRadius = r.ChassisWheelRadius,
 0253        BatteryCount = r.BatteryCount,
 0254        BatteryMaxVoltage = r.BatteryMaxVoltage,
 0255        BatteryMinVoltage = r.BatteryMinVoltage,
 0256      }).FirstOrDefaultAsync();
 0257  }
 258
 259  public async Task<bool> TestDeleteRobotAsync(Guid id)
 2260  {
 2261    var dependencies = await _context.AutoTasks
 2262      .Where(t => t.AssignedRobotId == id)
 2263      .Where(t => t.CurrentProgressId != (int)ProgressState.Completed && t.CurrentProgressId != (int)ProgressState.Abort
 2264      .CountAsync();
 2265    if (dependencies > 0)
 1266    {
 1267      throw new LgdxValidation400Expection(nameof(id), $"This robot has been used by {dependencies} running/waiting/temp
 268    }
 1269    return true;
 1270  }
 271
 272  public async Task<bool> DeleteRobotAsync(Guid id)
 0273  {
 0274    bool result = await _context.Robots.Where(r => r.Id == id)
 0275      .ExecuteDeleteAsync() == 1;
 276
 0277    if (result)
 0278    {
 0279      await _activityLogService.CreateActivityLogAsync(new ActivityLogCreateBusinessModel
 0280      {
 0281        EntityName = nameof(Robot),
 0282        EntityId = id.ToString(),
 0283        Action = ActivityAction.Delete,
 0284      });
 0285    }
 0286    return result;
 0287  }
 288
 289  public async Task<RobotSystemInfoBusinessModel?> GetRobotSystemInfoAsync(Guid robotId)
 1290  {
 1291    return await _context.RobotSystemInfos.AsNoTracking()
 1292      .Where(r => r.RobotId == robotId)
 1293      .Select(r => new RobotSystemInfoBusinessModel {
 1294        Id = r.Id,
 1295        Cpu = r.Cpu,
 1296        IsLittleEndian = r.IsLittleEndian,
 1297        Motherboard = r.Motherboard,
 1298        MotherboardSerialNumber = r.MotherboardSerialNumber,
 1299        RamMiB = r.RamMiB,
 1300        Gpu = r.Gpu,
 1301        Os = r.Os,
 1302        Is32Bit = r.Is32Bit,
 1303        McuSerialNumber = r.McuSerialNumber,
 1304      })
 1305      .FirstOrDefaultAsync();
 1306  }
 307
 308  public async Task<bool> CreateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoCreateBusinessModel robotSystemInfoCre
 1309  {
 1310    var robotSystemInfo = new RobotSystemInfo {
 1311      Cpu = robotSystemInfoCreateBusinessModel.Cpu,
 1312      IsLittleEndian = robotSystemInfoCreateBusinessModel.IsLittleEndian,
 1313      Motherboard = robotSystemInfoCreateBusinessModel.Motherboard,
 1314      MotherboardSerialNumber = robotSystemInfoCreateBusinessModel.MotherboardSerialNumber,
 1315      RamMiB = robotSystemInfoCreateBusinessModel.RamMiB,
 1316      Gpu = robotSystemInfoCreateBusinessModel.Gpu,
 1317      Os = robotSystemInfoCreateBusinessModel.Os,
 1318      Is32Bit = robotSystemInfoCreateBusinessModel.Is32Bit,
 1319      McuSerialNumber = robotSystemInfoCreateBusinessModel.McuSerialNumber,
 1320      RobotId = robotId
 1321    };
 1322    _context.RobotSystemInfos.Add(robotSystemInfo);
 1323    return await _context.SaveChangesAsync() >= 1;
 1324  }
 325
 326  public async Task<bool> UpdateRobotSystemInfoAsync(Guid robotId, RobotSystemInfoUpdateBusinessModel robotSystemInfoUpd
 0327  {
 0328    return await _context.RobotSystemInfos
 0329      .Where(r => r.RobotId == robotId)
 0330      .ExecuteUpdateAsync(setters => setters
 0331        .SetProperty(r => r.Cpu, robotSystemInfoUpdateBusinessModel.Cpu)
 0332        .SetProperty(r => r.IsLittleEndian, robotSystemInfoUpdateBusinessModel.IsLittleEndian)
 0333        .SetProperty(r => r.Motherboard, robotSystemInfoUpdateBusinessModel.Motherboard)
 0334        .SetProperty(r => r.MotherboardSerialNumber, robotSystemInfoUpdateBusinessModel.MotherboardSerialNumber)
 0335        .SetProperty(r => r.RamMiB, robotSystemInfoUpdateBusinessModel.RamMiB)
 0336        .SetProperty(r => r.Gpu, robotSystemInfoUpdateBusinessModel.Gpu)
 0337        .SetProperty(r => r.Os, robotSystemInfoUpdateBusinessModel.Os)
 0338        .SetProperty(r => r.Is32Bit, robotSystemInfoUpdateBusinessModel.Is32Bit)
 0339        .SetProperty(r => r.McuSerialNumber, robotSystemInfoUpdateBusinessModel.McuSerialNumber)
 0340      ) == 1;
 0341  }
 342
 343  public async Task<IEnumerable<RobotSearchBusinessModel>> SearchRobotsAsync(int realmId, string? name, Guid? robotId)
 4344  {
 4345    var n = name ?? string.Empty;
 4346    return await _context.Robots.AsNoTracking()
 4347      .Where(r => r.RealmId == realmId)
 4348      .Where(t => t.Name.ToLower().Contains(n.ToLower()))
 4349      .Where(r => robotId == null || r.Id == robotId)
 4350      .Take(10)
 4351      .Select(m => new RobotSearchBusinessModel {
 4352        Id = m.Id,
 4353        Name = m.Name,
 4354      })
 4355      .ToListAsync();
 4356  }
 357
 358  public async Task<int?> GetRobotRealmIdAsync(Guid robotId)
 3359  {
 3360    if (_memoryCache.TryGetValue<int>($"RobotService_GetRobotRealmIdAsync_{robotId}", out var RealmId))
 1361    {
 1362      return RealmId;
 363    }
 364
 2365    var robot = await _context.Robots.AsNoTracking()
 2366      .Where(m => m.Id == robotId)
 2367      .Select(m => new { m.Id, m.RealmId })
 2368      .FirstOrDefaultAsync();
 2369    if (robot == null)
 1370      return null;
 371
 1372    _memoryCache.Set($"RobotService_GetRobotRealmIdAsync_{robotId}", robot!.RealmId, TimeSpan.FromDays(1));
 1373    return robot.RealmId;
 3374  }
 375}