< Summary - MechanicsSoftware — Coverage Report

Information
Class: MechanicsSoftware.Infrastructure.Persistence.Configurations.ServiceOrderConfiguration
Assembly: MechanicsSoftware.Infrastructure
File(s): /home/runner/work/mechanics-software/mechanics-software/src/MechanicsSoftware.Infrastructure/Persistence/Configurations/ServiceOrderConfiguration.cs
Line coverage
100%
Covered lines: 136
Uncovered lines: 0
Coverable lines: 136
Total lines: 162
Line coverage: 100%
Branch coverage
100%
Covered branches: 42
Total branches: 42
Branch coverage: 100%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
Configure(...)100%11100%
Configure(...)100%11100%
ParseOrderStatus(...)100%3232100%
.cctor()100%11100%
ParseBudgetStatus(...)100%66100%
ParseOrderStatus(...)100%22100%
ParseBudgetStatus(...)100%22100%

File(s)

/home/runner/work/mechanics-software/mechanics-software/src/MechanicsSoftware.Infrastructure/Persistence/Configurations/ServiceOrderConfiguration.cs

#LineLine coverage
 1using Microsoft.EntityFrameworkCore;
 2using Microsoft.EntityFrameworkCore.Metadata.Builders;
 3using MechanicsSoftware.Domain.Entities;
 4using MechanicsSoftware.Domain.ValueObjects;
 5using MechanicsSoftware.Domain.Enums;
 6using MechanicsSoftware.Domain.Exceptions;
 7
 8namespace MechanicsSoftware.Infrastructure.Persistence.Configurations;
 9
 10public sealed class ServiceOrderConfiguration : IEntityTypeConfiguration<ServiceOrder>
 11{
 12    public void Configure(EntityTypeBuilder<ServiceOrder> builder)
 313    {
 314        builder.ToTable("service_orders");
 15
 316        builder.HasKey(so => so.Id);
 317        builder.Property(so => so.Id).HasColumnName("id");
 18
 319        builder.Property(so => so.CustomerId)
 320            .HasColumnName("customer_id")
 321            .IsRequired();
 22
 323        builder.Property(so => so.VehicleId)
 324            .HasColumnName("vehicle_id")
 325            .IsRequired();
 26
 327        builder.Property(so => so.Status)
 328            .HasConversion(
 329                v => v.ToString(),
 330                v => ParseOrderStatus(v))
 331            .HasColumnName("status")
 332            .HasMaxLength(30)
 333            .IsRequired();
 34
 335        builder.Property(so => so.CreatedAt)
 336            .HasColumnName("created_at")
 337            .IsRequired();
 38
 339        builder.Property(so => so.CompletedAt)
 340            .HasColumnName("completed_at");
 41
 342        builder.Property(so => so.DeliveredAt)
 343            .HasColumnName("delivered_at");
 144
 345        builder.Navigation(so => so.ServiceItems)
 346            .HasField("_serviceItems")
 347            .UsePropertyAccessMode(PropertyAccessMode.Field);
 148
 349        builder.Navigation(so => so.PartItems)
 350            .HasField("_partItems")
 351            .UsePropertyAccessMode(PropertyAccessMode.Field);
 152
 353        builder.OwnsMany(so => so.ServiceItems, si =>
 354        {
 355            si.ToTable("service_items");
 356            si.HasKey(s => s.Id);
 357            si.Property(s => s.Id).HasColumnName("id");
 358            si.WithOwner().HasForeignKey(s => s.ServiceOrderId);
 359            si.Property(s => s.ServiceOrderId).HasColumnName("service_order_id");
 360            si.HasIndex(s => s.ServiceOrderId).HasDatabaseName("ix_service_items_service_order_id");
 361            si.Property(s => s.ServiceId).HasColumnName("service_id").IsRequired();
 262            si.Property(s => s.ServiceName)
 363                .HasColumnName("service_name")
 364                .HasMaxLength(100)
 365                .IsRequired();
 366            si.Property(s => s.UnitPrice)
 367                .HasConversion(m => m.Cents, m => new Money(m))
 368                .HasColumnName("unit_price")
 369                .IsRequired();
 370            si.Property(s => s.Quantity).HasColumnName("quantity").IsRequired();
 371            si.Ignore(s => s.Total);
 372        });
 173
 374        builder.OwnsMany(so => so.PartItems, pi =>
 375        {
 376            pi.ToTable("part_items");
 377            pi.HasKey(p => p.Id);
 378            pi.Property(p => p.Id).HasColumnName("id");
 379            pi.WithOwner().HasForeignKey(p => p.ServiceOrderId);
 380            pi.Property(p => p.ServiceOrderId).HasColumnName("service_order_id");
 381            pi.HasIndex(p => p.ServiceOrderId).HasDatabaseName("ix_part_items_service_order_id");
 382            pi.Property(p => p.PartId).HasColumnName("part_id").IsRequired();
 383            pi.Property(p => p.PartName)
 384                .HasColumnName("part_name")
 385                .HasMaxLength(100)
 386                .IsRequired();
 287            pi.Property(p => p.UnitPrice)
 388                .HasConversion(m => m.Cents, m => new Money(m))
 389                .HasColumnName("unit_price")
 390                .IsRequired();
 391            pi.Property(p => p.Quantity).HasColumnName("quantity").IsRequired();
 392            pi.Property(p => p.Availability)
 393                .HasConversion<string>()
 394                .HasColumnName("availability")
 395                .IsRequired();
 396            pi.Ignore(p => p.Total);
 397        });
 198
 399        builder.OwnsOne(so => so.Budget, budget =>
 3100        {
 3101            budget.ToTable("budgets");
 3102            budget.HasKey(b => b.Id);
 3103            budget.Property(b => b.Id).HasColumnName("id");
 3104            budget.WithOwner().HasForeignKey(b => b.ServiceOrderId);
 3105            budget.Property(b => b.ServiceOrderId).HasColumnName("service_order_id");
 3106            budget.HasIndex(b => b.ServiceOrderId).IsUnique().HasDatabaseName("ix_budgets_service_order_id");
 3107            budget.Property(b => b.Total)
 3108                .HasConversion(m => m.Cents, m => new Money(m))
 2109                .HasColumnName("total")
 3110                .IsRequired();
 3111            budget.Property(b => b.Status)
 2112                .HasConversion(
 3113                    v => v.ToString(),
 3114                    v => ParseBudgetStatus(v))
 3115                .HasColumnName("status")
 3116                .HasMaxLength(20)
 2117                .IsRequired();
 3118            budget.Property(b => b.CreatedAt).HasColumnName("created_at").IsRequired();
 3119        });
 1120
 3121        builder.HasIndex(so => so.CustomerId).HasDatabaseName("ix_service_orders_customer_id");
 3122        builder.HasIndex(so => so.VehicleId).HasDatabaseName("ix_service_orders_vehicle_id");
 123
 2124        builder.HasOne<Customer>()
 13125            .WithMany()
 13126            .HasForeignKey(so => so.CustomerId)
 3127            .OnDelete(DeleteBehavior.Restrict);
 2128
 3129        builder.HasOne<Vehicle>()
 4130            .WithMany()
 3131            .HasForeignKey(so => so.VehicleId)
 3132            .OnDelete(DeleteBehavior.Restrict);
 4133    }
 1134
 13135    private static readonly Dictionary<string, ServiceOrderStatus.Status> _orderStatusMap = new()
 2136    {
 2137        ["RECEIVED"]          = ServiceOrderStatus.Status.Received,
 11138        ["IN_DIAGNOSIS"]      = ServiceOrderStatus.Status.InDiagnosis,
 11139        ["AWAITING_APPROVAL"] = ServiceOrderStatus.Status.AwaitingApproval,
 4140        ["IN_EXECUTION"]      = ServiceOrderStatus.Status.InExecution,
 6141        ["COMPLETED"]         = ServiceOrderStatus.Status.Completed,
 4142        ["DELIVERED"]         = ServiceOrderStatus.Status.Delivered,
 3143        ["CANCELLED"]         = ServiceOrderStatus.Status.Cancelled,
 11144    };
 145
 2146    private static readonly Dictionary<string, BudgetStatus.Status> _budgetStatusMap = new()
 2147    {
 2148        ["PENDING"]  = BudgetStatus.Status.Pending,
 2149        ["APPROVED"] = BudgetStatus.Status.Approved,
 2150        ["REJECTED"] = BudgetStatus.Status.Rejected,
 2151    };
 152
 153    internal static ServiceOrderStatus ParseOrderStatus(string value) =>
 116154        _orderStatusMap.TryGetValue(value, out var status)
 116155            ? new ServiceOrderStatus(status)
 116156            : throw new InvalidOperationException($"Unknown service order status: '{value}'");
 157
 158    internal static BudgetStatus ParseBudgetStatus(string value) =>
 56159        _budgetStatusMap.TryGetValue(value, out var status)
 56160            ? new BudgetStatus(status)
 56161            : throw new InvalidOperationException($"Unknown budget status: '{value}'");
 162}